commit 651a9f00472e170ae9a1c9dd00ac3d2100508995
parent 6abaadf3ce03cf297cedb26badc2a0a4f3a61fe8
Author: Marc Stibane <marc@taler.net>
Date: Thu, 29 Oct 2026 09:50:04 +0100
TalDir: Helper
Diffstat:
3 files changed, 184 insertions(+), 0 deletions(-)
diff --git a/TalerWallet1/Views/TalDir/Helper/LookupButton.swift b/TalerWallet1/Views/TalDir/Helper/LookupButton.swift
@@ -0,0 +1,65 @@
+/*
+ * This file is part of GNU Taler, ©2022-26 Taler Systems S.A.
+ * See LICENSE.md
+ */
+/**
+ * @author Marc Stibane
+ */
+import SwiftUI
+import taler_swift
+
+// MARK: -
+enum LookupState {
+ case unknown // not yet asked
+ case error // (Error)
+ case unregistered //
+ case registered(String, Duration) // we just (un)registered it, but it isn't confirmed yet
+ case confirmed(String, Duration) // lookup result
+
+ var hasTarget: Bool {
+ switch self {
+ case .registered, .confirmed:
+ return true
+ default:
+ return false
+ }
+ }
+}
+// MARK: -
+struct LookupButton: View {
+ let stack: CallStack
+ let alias: String
+ let aliasType: TaldirAliasType
+ @Binding var lookupState: LookupState
+// @FocusState.Binding var isFocused: Bool
+ let focus: () -> Void
+ let action: () -> Void
+
+ @EnvironmentObject private var model: WalletModel
+ @State private var working: Bool = false
+
+ var body: some View {
+ let buttonTitle = String(localized: "Lookup Alias", comment: "button")
+ FeedbackButton(buttonTitle, disabled: working, haptic: false) {
+ working = true
+ focus() // isFocused = false // dismiss keyboard
+ let lookup = TaldirLookup(alias: alias,
+ aliasType: aliasType.name)
+ Task {
+ let lookup = try? await model.lookupAlias(lookup)
+ if let targetUri = lookup?.targetUri {
+ if targetUri.isEmpty {
+ lookupState = .unregistered
+ } else {
+ let validFor = lookup?.validFor
+ lookupState = .confirmed(targetUri, validFor ?? Duration.microseconds(0))
+ }
+ } else {
+ lookupState = .error
+ }
+ self.working = false
+ action()
+ }
+ }
+ }
+}
diff --git a/TalerWallet1/Views/TalDir/Helper/MailAddressInput.swift b/TalerWallet1/Views/TalDir/Helper/MailAddressInput.swift
@@ -0,0 +1,50 @@
+/*
+ * This file is part of GNU Taler, ©2022-26 Taler Systems S.A.
+ * See LICENSE.md
+ */
+/**
+ * @author Marc Stibane
+ */
+import SwiftUI
+
+struct MailAddressInput: View {
+ let stack: CallStack
+ @Binding var text: String
+// @FocusState.Binding
+ var isFocused: Bool
+ let focusAction: () -> Void
+
+ var body: some View {
+ let label = String(localized: "Address:", comment: "TextEdit purpose, a11y")
+ let placeHolder = EMPTYSTRING
+ VStack(alignment: .leading, spacing: 6) {
+ Text(label)
+ .talerFont(.title3)
+ if #available(iOS 16.4, *) {
+ TextField(placeHolder, text: $text, axis: .vertical)
+ .lineLimit(2...6)
+ .textFieldStyle(.roundedBorder)
+ .textInputAutocapitalization(.never)
+ .onChange(of: text) { newValue in
+// .onSubmit {} doesn't work with multiple lines, so we need to check for "\n"
+ guard isFocused else { return }
+ guard newValue.contains(LINEFEED) else { return }
+ focusAction()
+ text = newValue.replacing(LINEFEED, with: EMPTYSTRING)
+ }
+ .talerFont(.title3)
+// .accessibilityLabel(label)
+ } else {
+ TextField(placeHolder, text: $text)
+ .textFieldStyle(.roundedBorder)
+ .textInputAutocapitalization(.never)
+// .focused($isFocused)
+ .onSubmit {
+ guard isFocused else { return }
+ focusAction()
+ }
+ .talerFont(.title2)
+ }
+ }
+ }
+}
diff --git a/TalerWallet1/Views/TalDir/Helper/StandardInput.swift b/TalerWallet1/Views/TalDir/Helper/StandardInput.swift
@@ -0,0 +1,69 @@
+/*
+ * This file is part of GNU Taler, ©2022-26 Taler Systems S.A.
+ * See LICENSE.md
+ */
+/**
+ * @author Marc Stibane
+ */
+import SwiftUI
+
+struct StandardInput: View {
+ let stack: CallStack
+ let label: String
+ let placeHolder: String
+ @Binding var text: String
+// let submitAction: () -> Void
+
+ var body: some View {
+ let textField = TextField(placeHolder, text: $text)
+ .textFieldStyle(.roundedBorder)
+ .textInputAutocapitalization(.never)
+ if #available(iOS 16.4, *) {
+ LabeledContent(label) {
+ textField
+ }
+ .talerFont(.title3)
+// .accessibilityLabel(label)
+ } else {
+ Text(label)
+ .talerFont(.title3)
+ textField
+ .talerFont(.title2)
+ }
+ }
+}
+// MARK: -
+struct AliasInput: View {
+ let stack: CallStack
+ @Binding var text: String
+ let lastAlias: String
+ let changeAction: () -> Void
+
+ var body: some View {
+ let label = String(localized: "Alias:", comment: "TextEdit purpose, a11y")
+ let placeHolder = "user@example.com"
+ let textField = TextField(placeHolder, text: $text)
+ .textFieldStyle(.roundedBorder)
+ .textInputAutocapitalization(.never)
+// .frame(height: frameHeight)
+ .onChange(of: text) { newVal in
+ if newVal != lastAlias {
+ changeAction() // lookupState = .unknown
+ }
+ }
+// .submitLabel(.search) just stick with the standard
+
+ if #available(iOS 16.4, *) {
+ LabeledContent(label) {
+ textField
+ }
+ .talerFont(.title3)
+// .accessibilityLabel(label)
+ } else {
+ Text(label)
+ .talerFont(.title3)
+ textField
+ .talerFont(.title2)
+ }
+ }
+}