taler-ios

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

commit 30fe84b851df78cf438583a32c25d85764d7da2e
parent d5b566919f53a7f44f7c96acb1abff5b7bc5e121
Author: Marc Stibane <marc@taler.net>
Date:   Sun, 23 Aug 2026 19:24:51 +0200

Debugging

Diffstat:
MTalerWallet1/Views/HelperViews/TabBarView.swift | 17++++++++++-------
MTalerWallet1/Views/Main/WalletMain.swift | 28++++++++++++++++++----------
MTalerWallet1/Views/Transactions/TransactionSummaryList.swift | 34++++++++++++++++++++++------------
3 files changed, 50 insertions(+), 29 deletions(-)

diff --git a/TalerWallet1/Views/HelperViews/TabBarView.swift b/TalerWallet1/Views/HelperViews/TabBarView.swift @@ -10,9 +10,10 @@ import SymLog struct ActionItem: View { private let symLog = SymLogV(0) + let stack: CallStack let tab: TalerTab let onTap: () -> Void - let onDrag: () -> Void + let onDrag: (CallStack) -> Void @EnvironmentObject private var controller: Controller @AppStorage("tapped") var tapped: Int = 0 @@ -46,7 +47,7 @@ struct ActionItem: View { offset = .zero } didDrag = true - onDrag() // switch to camera + onDrag(stack.push()) // switch to camera if tapped >= TAPPED { dragged += 1 } @@ -86,7 +87,7 @@ struct ActionItem: View { // .opacity(1 - Double(abs(offset.height / 35))) .gesture(dragGesture()) .onLongPressGesture(minimumDuration: 0.4) { - onDrag() + onDrag(stack.push()) } .onTapGesture { onTap() @@ -136,10 +137,11 @@ struct ActionItem: View { // MARK: - struct TabBarView: View { private let symLog = SymLogV(0) + let stack: CallStack @Binding var selection: TalerTab @Binding var hidden: Int let onActionTab: () -> Void - let onActionDrag: () -> Void + let onActionDrag: (CallStack) -> Void @Environment(\.keyboardShowing) var keyboardShowing @EnvironmentObject private var controller: Controller @@ -191,9 +193,10 @@ struct TabBarView: View { if keyboardShowing || hidden > 0 { EmptyView() } else { - let actionTab = ActionItem(tab: TalerTab.actions, - onTap: onActionTab, - onDrag: onActionDrag) + let actionTab = ActionItem(stack: stack.push(), + tab: TalerTab.actions, + onTap: onActionTab, + onDrag: onActionDrag) let balanceTab = tabBarItem(for: TalerTab.balances) .onTapGesture { selection = .balances diff --git a/TalerWallet1/Views/Main/WalletMain.swift b/TalerWallet1/Views/Main/WalletMain.swift @@ -194,9 +194,10 @@ struct WalletMain: View { SettingsButton26(sortPriority: 0) } Spacer() - ActionItem(tab: TalerTab.actions, - onTap: onActionTab, - onDrag: onActionDrag) + ActionItem(stack: stack.push(), + tab: TalerTab.actions, + onTap: onActionTab, + onDrag: onActionDrag) .accessibilitySortPriority(2) // Reads second .matchedTransitionSource(id: "unique_transition_id", in: wrapper.namespace) // .navigationTransition(.zoom(sourceID: "unique_transition_id", in: wrapper.namespace)) @@ -256,18 +257,25 @@ struct WalletMain: View { showActionSheet = true } - func onActionDrag() { // TODO: gets called multiple times - logger.log("onActionDrag: showScanner = true") - showScanner = true + func onActionDrag(_ stack: CallStack) { + if !showScanner { // gets called multiple times - log only once +#if DEBUG + if let caller = stack.peek() { + logger.log("showScanner = true (onActionDrag: \(caller.file):\(caller.function))") + } +#endif + showScanner = true + } } func tabBarView() -> some View { // iOS 15..18: custom tabBar (with Actions button) is rendered on top of the TabView, // and overlays the native iOS tabBar (which is still used for VoiceOver) - TabBarView(selection: tabSelection(), - hidden: $tabBarModel.tabBarHidden, - onActionTab: onActionTab, - onActionDrag: onActionDrag) + TabBarView(stack: stack.push(), + selection: tabSelection(), + hidden: $tabBarModel.tabBarHidden, + onActionTab: onActionTab, + onActionDrag: onActionDrag) .ignoresSafeArea(.keyboard, edges: .bottom) .accessibilityHidden(true) // for a11y we use the original tabBar, not our custom one } diff --git a/TalerWallet1/Views/Transactions/TransactionSummaryList.swift b/TalerWallet1/Views/Transactions/TransactionSummaryList.swift @@ -108,7 +108,7 @@ struct TransactionSummaryList: View { if transition.transactionId == talerTX.common.transactionId { // is the transition for THIS transaction? symLog.log(logStr) if talerTX.common.type.isPayment { - checkReload(notification, logStr) + checkReload(stack.push("checkDismiss1"), notification, logStr) } else { dismissTop(stack.push()) // if this view is in a sheet then dissmiss the sheet return true @@ -116,7 +116,7 @@ struct TransactionSummaryList: View { } } } else { // no sheet but the details view -> reload - checkReload(notification, logStr) + checkReload(stack.push("checkDismiss2"), notification, logStr) } return false } @@ -130,16 +130,26 @@ struct TransactionSummaryList: View { } } - func checkReload(_ notification: Notification, _ logStr: String = EMPTYSTRING) { - if let transition = notification.userInfo?[TRANSACTIONTRANSITION] as? TransactionTransition { + func checkReload(_ stack: CallStack, _ notification: Notification, _ logStr: String = EMPTYSTRING) { + if let transition: TransactionTransition = notification.userInfo?[TRANSACTIONTRANSITION] as? TransactionTransition { if transition.transactionId == transactionId { // is the transition for THIS transaction? let newMajor = transition.newTxState.major - Task { // runs on MainActor - // flush the screen first, then reload - withAnimation { talerTX = TalerTransaction(dummyCurrency: DEMOCURRENCY); viewId = UUID() } - symLog.log("newState: \(newMajor), reloading transaction") - if newMajor != .none { // don't reload after delete - await loadTransaction() + let message = stack.peek()?.message ?? "?" + if newMajor == .deleted { + symLog.log("newState: \(newMajor), show 'deleted', for: \(message)") + let error = transition.errorInfo ?? + TalerErrorDetail(code: 7049, // WALLET_MERCHANT_ORDER_NOT_FOUND + when: .now(), + hint: "Transaction has been deleted") + model.setError(WalletBackendError.walletCoreError(error)) + } else { + Task { // runs on MainActor + // flush the screen first, then reload + withAnimation { talerTX = TalerTransaction(dummyCurrency: DEMOCURRENCY); viewId = UUID() } + if newMajor != .none { // don't reload after delete + symLog.log("newState: \(newMajor), reloading transaction, for: \(message)") + await loadTransaction() + } } } } @@ -335,11 +345,11 @@ struct TransactionSummaryList: View { checkDismiss(notification, "exchangeWaitReserve or withdrawCoins => dismiss sheet") } .onNotification(.PendingReady) { notification in - checkReload(notification, "pending ready ==> reload for talerURI") + checkReload(stack.push("pendingReady"), notification, "pending ready ==> reload for talerURI") } .onNotification(.TransactionStateTransition) { notification in if !didDelete { - checkReload(notification, "some transition ==> reload") + checkReload(stack.push("TransactionStateTransition"), notification, "some transition ==> reload") } } .navigationTitle(navTitle ?? navTitle2)