taler-ios

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

commit 29db29f2ec249ff94bc8286006b0c22b12b6705a
parent d16a62de5809a46688b8ffc8671cf5d7ecc95e87
Author: Marc Stibane <marc@taler.net>
Date:   Fri, 14 Aug 2026 20:22:42 +0200

AI: PreparedTemplate to avoid instantiiating twice

Diffstat:
MTalerWallet1/Views/Sheets/Payment/PayTemplateScan.swift | 12+++++++++---
MTalerWallet1/Views/Sheets/Payment/PaymentScan.swift | 23+++++++++++++++++++++++
2 files changed, 32 insertions(+), 3 deletions(-)

diff --git a/TalerWallet1/Views/Sheets/Payment/PayTemplateScan.swift b/TalerWallet1/Views/Sheets/Payment/PayTemplateScan.swift @@ -41,6 +41,9 @@ struct PayTemplateScan: View { @State private var isPaivana = false @State private var summary: String = EMPTYSTRING // templateParam @State private var scope: ScopeInfo? = nil + /// survives PaymentScan being popped and pushed again, so that we don't + /// instantiate the template (= create another order) a second time + @State private var prepared: PreparedTemplate? = nil // @State private var feeAmount: Amount? = nil // @State private var feeStr: String = EMPTYSTRING @@ -122,7 +125,8 @@ struct PayTemplateScan: View { amountToTransfer: $amountToTransfer, summary: $summary, amountIsEditable: amountIsEditable, - summaryIsEditable: summaryIsEditable) + summaryIsEditable: summaryIsEditable, + prepared: $prepared) // final destination with amountShortcut, when user tapped a shortcut let finalDestinationS = PaymentScan(stack: stack.push(), @@ -131,7 +135,8 @@ struct PayTemplateScan: View { amountToTransfer: $amountShortcut, summary: $summary, amountIsEditable: amountIsEditable, - summaryIsEditable: summaryIsEditable) + summaryIsEditable: summaryIsEditable, + prepared: $prepared) // destination to subject input let inputDestination = SubjectInputV(stack: stack.push(), @@ -196,7 +201,8 @@ struct PayTemplateScan: View { amountToTransfer: $amountToTransfer, summary: $summary, amountIsEditable: amountIsEditable, - summaryIsEditable: summaryIsEditable) + summaryIsEditable: summaryIsEditable, + prepared: $prepared) } } .navigationTitle(navTitle) // .ignoresSafeArea(.keyboard, edges: .bottom) diff --git a/TalerWallet1/Views/Sheets/Payment/PaymentScan.swift b/TalerWallet1/Views/Sheets/Payment/PaymentScan.swift @@ -15,6 +15,12 @@ fileprivate func feeLabel(_ feeString: String) -> String { feeString.isEmpty ? EMPTYSTRING : String(localized: "+ \(feeString) fee") } +/// The pay-template instantiation which already created an order at the merchant +struct PreparedTemplate: Equatable { + let key: String // the parameters that order was created for + let transactionId: String +} + // MARK: - // Will be called either by the user scanning a <pay> QR code or tapping the provided link, // both from the shop's website - or even from a printed QR code. @@ -31,6 +37,7 @@ struct PaymentScan: View, Sendable { @Binding var summary: String let amountIsEditable: Bool // let summaryIsEditable: Bool // + var prepared: Binding<PreparedTemplate?>? = nil // template only, lives in PayTemplateScan @EnvironmentObject private var model: WalletModel @EnvironmentObject private var controller: Controller @@ -42,14 +49,30 @@ struct PaymentScan: View, Sendable { @State private var elapsed: Int = 0 @State private var talerTX = TalerTransaction(dummyCurrency: DEMOCURRENCY) + /// the parameters an already instantiated template order belongs to + private var templateKey: String { + url.trimmedString + "\n" + + (amountIsEditable ? amountToTransfer.description : EMPTYSTRING) + "\n" + + (summaryIsEditable ? summary : EMPTYSTRING) + } + @MainActor private func viewDidLoad() async { // symLog.log(".task") if template { + /// Instantiating a template creates a fresh order at the merchant, and this view is + /// pushed anew (with new @State) whenever the user navigates back and forward again + /// - so only instantiate once per amount/subject the user entered. + let key = templateKey + if let already = prepared?.wrappedValue, already.key == key { + txId = already.transactionId + return + } if let templateResponse = try? await model.preparePayForTemplate(url.trimmedString, amount: amountIsEditable ? amountToTransfer : nil, summary: summaryIsEditable ? summary : nil) { txId = templateResponse.transactionId + prepared?.wrappedValue = PreparedTemplate(key: key, transactionId: templateResponse.transactionId) // preparePayResult = templateResponse // let raw = templateResponse.amountRaw // controller.updateAmount(raw, forSaved: url)