Fix: the "Pay now" button renders the currency as UNKNOWN. `currencyInfo` in TransactionSummaryList is initialised to CurrencyInfo.zero(UNKNOWN) and assigned in exactly one place -- an `.onChange(of: scope)`. SwiftUI's onChange fires only when the value changes after the view appears, so a scope that was already set when the view was created never reaches it, and the button formats its amount with an unresolved currency while the rest of the same screen renders the amount correctly. This adds the `.task(id: controller.currencyTicker)` resolution that WithdrawUriScan.swift:207, SendAmountV.swift:91 and RequestPayment.swift:93 already use, which also covers the second case: `controller.info(for:)` answers nil until the currency specification has been fetched, so even a scope change that does fire can land before the currency is known. The two-argument `info(for:_:)` returns a non-optional CurrencyInfo, which is why there is no `?? zero(UNKNOWN)` on the new call. The existing onChange is left in place: it is harmless and still covers a scope change between ticker bumps. Generated against taler-ios master, 2026-11-08. Apply with `git apply`. --- a/TalerWallet1/Views/Transactions/TransactionSummaryList.swift +++ b/TalerWallet1/Views/Transactions/TransactionSummaryList.swift @@ -446,8 +446,28 @@ if let newVal { currencyInfo = controller.info(for: newVal) ?? CurrencyInfo.zero(UNKNOWN) } } + // `onChange` alone is not enough, and the "Pay now" button + // is where that showed. It fires only when the value changes *after* + // the view appears, so a `scope` that was already set when this view + // was created never reached `currencyInfo`, which stayed + // CurrencyInfo.zero(UNKNOWN) -- and that is what `effective + // .formatted(currencyInfo)` renders the button's amount with. The + // result is a Confirm Payment screen reading "0.1 KUDOS" in the body + // and "Pay UNKNOWN 0.1 now" on the button. + // + // It also has to re-run when the controller learns a currency later: + // `controller.info(for:)` answers nil until the currency + // specification has been fetched. The same pattern is already used + // in WithdrawUriScan.swift:207, SendAmountV.swift:91 and + // RequestPayment.swift:93; this view was the one that did not. + .task(id: controller.currencyTicker) { + if let scope { + currencyInfo = controller.info(for: scope, + controller.currencyTicker) + } + } .onAppear { symLog.log("onAppear") DebugViewC.shared.setViewID(VIEW_TRANSACTIONSUMMARY, stack: stack.push()) }