diff --git a/TalerWallet1/Views/Settings/Bank/BankEditView.swift b/TalerWallet1/Views/Settings/Bank/BankEditView.swift index c77b9f01..43c055b1 100755 --- a/TalerWallet1/Views/Settings/Bank/BankEditView.swift +++ b/TalerWallet1/Views/Settings/Bank/BankEditView.swift @@ -59,6 +59,16 @@ struct BankEditView: View { // } // } + /// An x-taler-bank target is BANK-HOST/ACCOUNT (RFC 8905). wallet-core rejects + /// anything with fewer than two components as + /// "payto URI is malformed (COMPONENTS_LENGTH)", which reached the user as + /// "Internal core error" with the raw JSON. Check it here instead. + private var xTalerValid: Bool { + let parts = xTaler.split(separator: "/", omittingEmptySubsequences: false) + return parts.count >= 2 + && parts.allSatisfy { !$0.isEmpty && !$0.contains(where: { $0.isWhitespace }) } + } + @ViewBuilder func barButton() -> some View { let isNew = accountID == nil let titleStr = isNew ? String(localized: "Add", comment: "button title: Add bank account") @@ -66,7 +76,7 @@ struct BankEditView: View { let a11yStr = isNew ? String(localized: "Add bank account", comment: "a11y") : String(localized: "Update bank account", comment: "a11y") let notValid: Bool = paytoType == .iban ? (iban.isEmpty || !ibanValid) - : xTaler.isEmpty + : !xTalerValid DoneButton(titleStr: titleStr, accessibilityLabelStr: titleStr) { Task { if await updateAccount() { @@ -105,7 +115,7 @@ struct BankEditView: View { let isIBAN = paytoType == .iban if !accountHolder.isEmpty && !accountLabel.isEmpty { if isIBAN ? !iban.isEmpty - : !xTaler.isEmpty { + : xTalerValid { // Build the payto URI with URLComponents so each component is escaped as a // component. The previous code percent-encoded the ALREADY-ASSEMBLED string // with .urlQueryAllowed, which leaves "?", "&" and "=" untouched — an @@ -266,12 +276,21 @@ struct BankEditView: View { .foregroundColor(WalletColors().fieldForeground) // text color .background(WalletColors().fieldBackground) .textFieldStyle(.roundedBorder) - .padding(.bottom) + .autocapitalization(.none) + .disableAutocorrection(true) + .padding(.bottom, xTaler.isEmpty || xTalerValid ? nil : 0) .onChange(of: xTaler) { newValue in if userTyped { unchanged = false } } + if !xTaler.isEmpty && !xTalerValid { + Text("Enter the account as BANK-HOST/ACCOUNT, for example bank.example.com/alice", + comment: "hint below the x-taler-bank field") + .talerFont(.body) + .foregroundColor(.red) + .padding(.bottom) + } } else { Text("unknown payment method") .talerFont(.title3)