taler-ios

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

commit 46290ddbb3a777b24ce931963ef26936c2e9d3ad
parent 8eb478d5d086a10ca5a627b34fc5dad16b548c19
Author: Marc Stibane <marc@taler.net>
Date:   Mon, 10 Aug 2026 19:09:11 +0200

extract WireTransferView

Diffstat:
MTalerWallet1/Views/Transactions/ManualDetailsV.swift | 191++++++++++++++++++++++++++++++++++++++++++++-----------------------------------
1 file changed, 107 insertions(+), 84 deletions(-)

diff --git a/TalerWallet1/Views/Transactions/ManualDetailsV.swift b/TalerWallet1/Views/Transactions/ManualDetailsV.swift @@ -14,6 +14,30 @@ struct ManualDetailsV: View { let common: TransactionCommon let details: WithdrawalDetails + var body: some View { + if let validDetails = details.exchangeCreditAccountDetails?.validDetails { + WireTransferView(stack: stack.push(), + title: String(localized: "The payment service is waiting for your wire-transfer.", comment: ""), + isKYC: false, + reservePub: details.reservePub, + amountRaw: common.amountRaw, + amountEffective: common.amountEffective, // only for withdrawal + debitIBAN: nil, // only for deposit auth + validDetails: validDetails) + } else { ErrorView(stack.push(), title: "Payment Error", message: "No valid details") } + } // body +} +// MARK: - +struct WireTransferView: View { + let stack: CallStack + let title: String + let isKYC: Bool + let reservePub: String + let amountRaw: Amount + let amountEffective: Amount? // only for withdrawal + let debitIBAN: String? // only for deposit auth + let validDetails: AccountDetailsArray + @EnvironmentObject private var model: WalletModel #if DEBUG @AppStorage("developerMode") var developerMode: Bool = true @@ -42,100 +66,99 @@ struct ManualDetailsV: View { } var body: some View { - if let validDetails = details.validDetails { - let validCount = validDetails.count // guaranteed to be > 0 - let account = validDetails[validIndex] - let json = account.toJSON() - if account.transferAmount != nil { - if let transferOptions = account.transferOptions, let firstOption = transferOptions.first { - let specs = account.currencySpecification - let amountStr = common.amountRaw.formatted(specs: specs, isNegative: false) - let amountValue = common.amountRaw.valueStr - let obtainStr = common.amountEffective.formatted(specs: specs, isNegative: false) + let validCount = validDetails.count // guaranteed to be > 0 + let account = validDetails[validIndex] + let json = account.toJSON() + if account.transferAmount != nil { + if let transferOptions = account.transferOptions, let firstOption = transferOptions.first { + let specs = account.currencySpecification + let amountStr = amountRaw.formatted(specs: specs, isNegative: false) + let amountValue = amountRaw.valueStr + let obtainStr = amountEffective?.formatted(specs: specs, isNegative: false) // or nil // let _ = print(amountStr, " | ", obtainStr) - if !minimalistic { - Text("The payment service is waiting for your wire-transfer.") - .bold() - .multilineTextAlignment(.leading) - .listRowSeparator(.hidden) - } - if validCount > 1 { - if validCount > 3 { // too many for SegmentControl - AccountPicker(title: String(localized: "Bank"), - value: $validIndex, - accountDetails: validDetails, - action: redraw) - .listRowSeparator(.hidden) - .pickerStyle(.menu) - } else { - SegmentControl(value: $validIndex, accountDetails: validDetails, action: redraw) - .listRowSeparator(.hidden) - } - } else if let bankName = account.bankLabel { - Text(bankName + ": " + amountStr.0) - .accessibilityLabel(bankName + ": " + amountStr.1) + if !minimalistic { + Text(title) + .bold() + .multilineTextAlignment(.leading) + .listRowSeparator(.hidden) + } + if validCount > 1 { + if validCount > 3 { // too many for SegmentControl + AccountPicker(title: String(localized: "Bank"), + value: $validIndex, + accountDetails: validDetails, + action: redraw) + .listRowSeparator(.hidden) + .pickerStyle(.menu) } else { - Text(amountStr.0) - .accessibilityLabel(amountStr.1) + SegmentControl(value: $validIndex, accountDetails: validDetails, action: redraw) + .listRowSeparator(.hidden) } + } else if let bankName = account.bankLabel { + Text(bankName + ": " + amountStr.0) + .accessibilityLabel(bankName + ": " + amountStr.1) + } else { + Text(amountStr.0) + .accessibilityLabel(amountStr.1) + } - let countA = transferOptions.count - let countB = firstOption.qrCodes?.count ?? 0 + let countA = transferOptions.count + let countB = firstOption.qrCodes?.count ?? 0 - if let paytoUri = firstOption.paytoUri { - let payto = PayTo(paytoUri) - if let receiverStr = payto.receiver { - let wireDetails = ManualDetailsWireV(stack: stack.push(), - reservePub: details.reservePub, - payto: payto, - restrictions: account.creditRestrictions, - amountValue: amountValue, - amountStr: amountStr, - obtainStr: obtainStr, - debitIBAN: nil // only for deposit auth - ) - NavigationLink(destination: wireDetails) { - Text(minimalistic ? "Instructions" - : "Wire transfer instructions") - .talerFont(.title3) - } + if let paytoUri = firstOption.paytoUri { + let payto = PayTo(paytoUri) + if let receiverStr = payto.receiver { + let wireDetails = ManualDetailsWireV(stack: stack.push(), + reservePub: reservePub, + payto: payto, + restrictions: account.creditRestrictions, + amountValue: amountValue, + amountStr: amountStr, + obtainStr: obtainStr, // only for withdrawal + debitIBAN: debitIBAN // only for deposit auth + ) + NavigationLink(destination: wireDetails) { + Text(minimalistic ? "Instructions" + : "Wire transfer instructions") + .talerFont(.title3) + } - Group { - if countA > 1 || countB > 1 { - qrCodesRow(transferOptions) - } else if countA > 0 { // show the single QR directly - Text("If your banking software runs on another device, you can scan this QR code:") - .listRowSeparator(.hidden) - QRcodeCopyShare(option: firstOption) - .listRowSeparator(.automatic) - } - }.id(listID) - .talerFont(.body) + Group { + if countA > 1 || countB > 1 { + qrCodesRow(transferOptions) + } else if countA > 0 { // show the single QR directly + Text("If your banking software runs on another device, you can scan this QR code:") + .listRowSeparator(.hidden) + QRcodeCopyShare(option: firstOption) + .listRowSeparator(.automatic) + } + }.id(listID) + .talerFont(.body) #if DEBUG - if developerMode { - if let iban = payto.iban { - Text(minimalistic ? "**Alternative:** Use this PayTo-Link:" - : "**Alternative:** If your bank already supports PayTo, you can use this PayTo-Link instead:") - .multilineTextAlignment(.leading) - .padding(.top) - .listRowSeparator(.hidden) - let title = String(localized: "Share the PayTo URL", comment: "a11y") - let minTitle = String(localized: "Share PayTo", comment: "mini") - let textToShare = String("\(payto)\n\nIBAN: \(iban)\nReceiver: \(receiverStr)\nAmount: \(amountStr.1)\nSubject: \(details.reservePub)") + if developerMode { + if let iban = payto.iban { + Text(minimalistic ? "**Alternative:** Use this PayTo-Link:" + : "**Alternative:** If your bank already supports PayTo, you can use this PayTo-Link instead:") + .multilineTextAlignment(.leading) + .padding(.top) + .listRowSeparator(.hidden) + let title = String(localized: "Share the PayTo URL", comment: "a11y") + let minTitle = String(localized: "Share PayTo", comment: "mini") + // TODO: chQRr + let textToShare = String("\(payto)\n\nIBAN: \(iban)\nReceiver: \(receiverStr)\nAmount: \(amountStr.1)\nSubject: \(reservePub)") let _ = print(textToShare) - ShareButton(textToShare, title: minimalistic ? minTitle : title) - .frame(maxWidth: .infinity, alignment: .center) - .accessibilityLabel(Text(title)) - .disabled(false) - .listRowSeparator(.hidden) - } + ShareButton(textToShare, title: minimalistic ? minTitle : title) + .frame(maxWidth: .infinity, alignment: .center) + .accessibilityLabel(Text(title)) + .disabled(false) + .listRowSeparator(.hidden) } + } #endif - } else { ErrorView(stack.push(), title: "No receiver", message: json, copyable: true) } - } else { ErrorView(stack.push(), title: "No payto URL", message: json, copyable: true) } - } else { ErrorView(stack.push(), title: "No transfer options", message: json, copyable: true) } - } else { ErrorView(stack.push(), title: "No amount", message: json, copyable: true) } - } else { ErrorView(stack.push(), title: "Payment Error", message: "No valid details") } + } else { ErrorView(stack.push(), title: "No receiver", message: json, copyable: true) } + } else { ErrorView(stack.push(), title: "No payto URL", message: json, copyable: true) } + } else { ErrorView(stack.push(), title: "No transfer options", message: json, copyable: true) } + } else { ErrorView(stack.push(), title: "No amount", message: json, copyable: true) } } } // MARK: -