taler-ios

iOS apps for GNU Taler (wallet)
Log | Files | Refs | README | LICENSE

commit 651a9f00472e170ae9a1c9dd00ac3d2100508995
parent 6abaadf3ce03cf297cedb26badc2a0a4f3a61fe8
Author: Marc Stibane <marc@taler.net>
Date:   Thu, 29 Oct 2026 09:50:04 +0100

TalDir: Helper

Diffstat:
ATalerWallet1/Views/TalDir/Helper/LookupButton.swift | 65+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ATalerWallet1/Views/TalDir/Helper/MailAddressInput.swift | 50++++++++++++++++++++++++++++++++++++++++++++++++++
ATalerWallet1/Views/TalDir/Helper/StandardInput.swift | 69+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
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) + } + } +}