taler-ios

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

commit b1db8f7fce77b9175448168e24e4314a7a609752
parent 586eed9692448837f9a43b3531e0ce660f813469
Author: Marc Stibane <marc@taler.net>
Date:   Fri, 13 Oct 2023 16:53:07 +0200

Source of Truth for balances

Diffstat:
MTalerWallet1/Views/Balances/BalancesListView.swift | 91+++++++++++++++++++++++++++----------------------------------------------------
MTalerWallet1/Views/Main/MainView.swift | 15+++++++++++++--
2 files changed, 44 insertions(+), 62 deletions(-)

diff --git a/TalerWallet1/Views/Balances/BalancesListView.swift b/TalerWallet1/Views/Balances/BalancesListView.swift @@ -12,13 +12,15 @@ struct BalancesListView: View { private let symLog = SymLogV() let stack: CallStack let navTitle: String + @Binding var balances: [Balance] + @Binding var shouldReloadBalances: Int + @State private var lastReloadedBalances = 0 #if TABBAR // Taler Wallet #else // GNU Taler let hamburgerAction: () -> Void #endif @EnvironmentObject private var model: WalletModel - @State private var balances: [Balance] = [] @State private var centsToTransfer: UInt64 = 0 @State private var summary: String = "" @State private var showQRScanner: Bool = false @@ -75,7 +77,10 @@ struct BalancesListView: View { /// runs on MainActor if called in some Task {} @discardableResult - private func reloadAction(_ stack: CallStack) async -> Int { + private func reloadAction(_ stack: CallStack, _ invalidateCache: Bool) async -> Int { + if invalidateCache { + model.cachedBalances = nil + } let reloaded = await model.balancesM(stack.push()) let count = reloaded.count balances = reloaded // redraw @@ -98,34 +103,20 @@ struct BalancesListView: View { .navigationTitle(navTitle) .navigationBarItems(leading: hamburger, trailing: QRButton(action: checkCameraAvailable)) - .overlay { - if balances.isEmpty { - WalletEmptyView(stack: stack.push()) - .refreshable { // already async - symLog.log("empty refreshing") - let count = await reloadAction(stack.push("empty refreshing")) - if count > 0 { -// postNotificationM(.BalanceReloaded) - NotificationCenter.default.post(name: .BalanceReloaded, object: nil) - } - } - } - } .alert("Scanning QR-codes requires access to the camera", isPresented: $showCameraAlert, actions: { openSettingsButton dismissAlertButton }, message: { Text("Please allow camera access in settings.") }) - .onAppear() { - DebugViewC.shared.setViewID(VIEW_BALANCES, stack: stack.push("onAppear")) - } .sheet(isPresented: $showQRScanner) { let sheet = AnyView(QRSheet(stack: stack.push())) Sheet(sheetView: sheet) } // sheet - .task { - symLog.log(".task getBalances") - await reloadAction(stack.push(".task")) + .task(id: shouldReloadBalances) { + symLog.log(".task shouldReloadBalances \(shouldReloadBalances)") + let invalidateCache = (lastReloadedBalances != shouldReloadBalances) + lastReloadedBalances = shouldReloadBalances + await reloadAction(stack.push(".task"), invalidateCache) } // task } } @@ -138,11 +129,7 @@ extension BalancesListView { @Binding var balances: [Balance] @Binding var centsToTransfer: UInt64 @Binding var summary: String -// @discardableResult - var reloadAction: (_ stack: CallStack) async -> Int - - @State private var isActive = true - @State private var shouldReload = false + var reloadAction: (_ stack: CallStack, _ invalidateCache: Bool) async -> Int var body: some View { #if DEBUG @@ -151,43 +138,27 @@ extension BalancesListView { #endif Group { // necessary for .backslide transition (bug in SwiftUI) let count = balances.count - List(balances, id: \.self) { balance in - BalancesSectionView(stack: stack.push(), - balance: balance, - sectionCount: count, - centsToTransfer: $centsToTransfer, - summary: $summary) - } - .refreshable { // already async - symLog?.log("refreshing") - let count = await reloadAction(stack.push("refreshing")) - if count > 0 { -// postNotificationM(.BalanceReloaded) - NotificationCenter.default.post(name: .BalanceReloaded, object: nil) + if balances.isEmpty { + WalletEmptyView(stack: stack.push("isEmpty")) + } else { + List(balances, id: \.self) { balance in + BalancesSectionView(stack: stack.push("\(balance.available.currencyStr)"), + balance: balance, + sectionCount: count, + centsToTransfer: $centsToTransfer, + summary: $summary) } + .onAppear() { + DebugViewC.shared.setViewID(VIEW_BALANCES, stack: stack.push("onAppear")) + } + .listStyle(myListStyle.style).anyView } - .listStyle(myListStyle.style).anyView - } - .onAppear() { - isActive = true - if shouldReload { - shouldReload = false - symLog?.log(".onAppear ==> shouldReload was true, reloading now") - Task { await reloadAction(stack.push("shouldReload")) } // runs on MainActor - } - } - .onDisappear() { - isActive = false } - .onNotification(.BalanceChange) { notification in - // reload balances on receiving BalanceChange notification ... - // doesn't need to be received on main thread because we just reload in a background task anyway - if isActive { - symLog?.log(".onNotification(.BalanceChange) ==> reload") - Task { await reloadAction(stack.push(".BalanceChange")) } - } else { - symLog?.log(".onNotification(.BalanceChange) ==> reload postponed, shouldReload = true") - shouldReload = true + .refreshable { // already async + symLog?.log("refreshing balances") + let count = await reloadAction(stack.push("refreshing balances"), true) + if count > 0 { + NotificationCenter.default.post(name: .BalanceReloaded, object: nil) } } } // body diff --git a/TalerWallet1/Views/Main/MainView.swift b/TalerWallet1/Views/Main/MainView.swift @@ -75,6 +75,8 @@ extension MainView { struct Content: View { let symLog: SymLogV? let stack: CallStack + @State private var shouldReloadBalances = 0 + @State private var balances: [Balance] = [] @Binding var talerFont: Int @AppStorage("iconOnly") var iconOnly: Bool = false let balancesTitle = String(localized: "Balances") @@ -112,6 +114,8 @@ extension MainView { sysImage: "creditcard.fill", // TODO: Wallet Icon view: AnyView(BalancesListView(stack: stack.push(balancesTitle), navTitle: balancesTitle, + balances: $balances, + shouldReloadBalances: $shouldReloadBalances, hamburgerAction: hamburgerAction) )), SidebarItem(name: exchangesTitle, @@ -141,7 +145,9 @@ extension MainView { TabView(selection: tabSelection()) { NavigationView { BalancesListView(stack: stack.push(balancesTitle), - navTitle: balancesTitle) + navTitle: balancesTitle, + balances: $balances, + shouldReloadBalances: $shouldReloadBalances) } .tabItem { Image(systemName: "creditcard") // system will automatically use filled variant @@ -199,6 +205,11 @@ extension MainView { } #endif } - } + .onNotification(.BalanceChange) { notification in + // reload balances on receiving BalanceChange notification ... + symLog?.log(".onNotification(.BalanceChange) ==> reload") + shouldReloadBalances += 1 + } + } // body } // Content }