taler-ios

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

commit bfaf17c0dd86af27ec33dce206dad8b0dc3a8158
parent 05eed763d0f142dd2ebd78fcae4dc35fc6663824
Author: Marc Stibane <marc@taler.net>
Date:   Sat,  9 Nov 2024 10:02:31 +0100

Transactions

Diffstat:
MTalerWallet1/Model/Model+Transactions.swift | 58++++++++++++++++++++--------------------------------------
MTalerWallet1/Views/Balances/BalancesSectionView.swift | 29++++++++++++++++-------------
MTalerWallet1/Views/HelperViews/BarGraph.swift | 23+++++++++++++----------
MTalerWallet1/Views/HelperViews/TransactionButton.swift | 1+
4 files changed, 50 insertions(+), 61 deletions(-)

diff --git a/TalerWallet1/Model/Model+Transactions.swift b/TalerWallet1/Model/Model+Transactions.swift @@ -57,14 +57,14 @@ struct TransactionOffset: Codable { /// A request to get the transactions in the wallet's history. fileprivate struct GetTransactionsV2: WalletBackendFormattedRequest { func operation() -> String { "getTransactionsV2" } - func args() -> Args { Args(scopeInfo: scopeInfo, + func args() -> Args { Args(scopeInfo: scope, filterByState: filterByState, includeRefreshes: includeRefreshes, limit: -limit, // descending offsetTransactionId: offset?.txID, offsetTimestamp: offset?.txTime) } - var scopeInfo: ScopeInfo? + var scope: ScopeInfo? var filterByState: TransactionStateFilter? var limit: Int var offset: TransactionOffset? @@ -139,69 +139,51 @@ struct ResumeTransaction: WalletBackendFormattedRequest { } // MARK: - extension WalletModel { - /// ask wallet-core for its list of transactions filtered by searchString - func transactionsT(_ stack: CallStack, scopeInfo: ScopeInfo, // searchString: String? = nil, <= never worked anyway - sort: String = "descending", filterByState: TransactionStateFilter? = nil, - includeRefreshes: Bool = false, viewHandles: Bool = false) - async throws -> [Transaction] { - let request = GetTransactions(scopeInfo: scopeInfo, currency: scopeInfo.currency, // search: searchString, <= never worked - sort: sort, filterByState: filterByState, includeRefreshes: includeRefreshes) - let response = try await sendRequest(request, ASYNCDELAY, viewHandles: viewHandles) - return response.transactions - } - /// fetch transactions from Wallet-Core. No networking involved - @MainActor func transactionsM(_ stack: CallStack, scopeInfo: ScopeInfo, // searchString: String? = nil, - sort: String = "descending", filterByState: TransactionStateFilter? = nil, - viewHandles: Bool = false) - async throws -> [Transaction] { // M for MainActor - return try await transactionsT(stack.push(), scopeInfo: scopeInfo, // searchString: searchString, - sort: sort, filterByState: filterByState, viewHandles: viewHandles) - } - /// ask wallet-core for its list of transactions filtered by searchString - func transactionsT2(_ stack: CallStack, - scopeInfo: ScopeInfo, - filterByState: TransactionStateFilter, - limit: Int = 1_000_000, - offset: TransactionOffset? = nil, - includeRefreshes: Bool = false, - viewHandles: Bool = false) + /// ask wallet-core for its list of transactions filtered by state + nonisolated func getTransactionsV2(_ stack: CallStack, + scope: ScopeInfo, + filterByState: TransactionStateFilter, + limit: Int = 1_000_000, + offset: TransactionOffset? = nil, + includeRefreshes: Bool = false, + viewHandles: Bool = false) async throws -> [Transaction] { - let request = GetTransactionsV2(scopeInfo: scopeInfo, - filterByState: filterByState, - limit: limit, - offset: offset, - includeRefreshes: includeRefreshes) + let request = GetTransactionsV2(scope: scope, + filterByState: filterByState, + limit: limit, + offset: offset, + includeRefreshes: includeRefreshes) let response = try await sendRequest(request, ASYNCDELAY, viewHandles: viewHandles) return response.transactions } // MARK: - /// abort the specified transaction from Wallet-Core. No networking involved - func abortTransaction(transactionId: String, viewHandles: Bool = false) async throws { + nonisolated func abortTransaction(transactionId: String, viewHandles: Bool = false) async throws { let request = AbortTransaction(transactionId: transactionId) logger.notice("abortTransaction: \(transactionId, privacy: .private(mask: .hash))") let _ = try await sendRequest(request, ASYNCDELAY, viewHandles: viewHandles) } /// delete the specified transaction from Wallet-Core. No networking involved - func deleteTransaction(transactionId: String, viewHandles: Bool = false) async throws { + nonisolated func deleteTransaction(transactionId: String, viewHandles: Bool = false) async throws { let request = DeleteTransaction(transactionId: transactionId) logger.notice("deleteTransaction: \(transactionId, privacy: .private(mask: .hash))") let _ = try await sendRequest(request, ASYNCDELAY, viewHandles: viewHandles) } - func failTransaction(transactionId: String, viewHandles: Bool = false) async throws { + nonisolated func failTransaction(transactionId: String, viewHandles: Bool = false) async throws { let request = FailTransaction(transactionId: transactionId) logger.notice("failTransaction: \(transactionId, privacy: .private(mask: .hash))") let _ = try await sendRequest(request, ASYNCDELAY, viewHandles: viewHandles) } - func suspendTransaction(transactionId: String, viewHandles: Bool = false) async throws { + nonisolated func suspendTransaction(transactionId: String, viewHandles: Bool = false) async throws { let request = SuspendTransaction(transactionId: transactionId) logger.notice("suspendTransaction: \(transactionId, privacy: .private(mask: .hash))") let _ = try await sendRequest(request, ASYNCDELAY, viewHandles: viewHandles) } - func resumeTransaction(transactionId: String, viewHandles: Bool = false) async throws { + nonisolated func resumeTransaction(transactionId: String, viewHandles: Bool = false) async throws { let request = ResumeTransaction(transactionId: transactionId) logger.notice("resumeTransaction: \(transactionId, privacy: .private(mask: .hash))") let _ = try await sendRequest(request, ASYNCDELAY, viewHandles: viewHandles) diff --git a/TalerWallet1/Views/Balances/BalancesSectionView.swift b/TalerWallet1/Views/Balances/BalancesSectionView.swift @@ -52,33 +52,36 @@ struct BalancesSectionView { @State private var sectionID = UUID() @State private var shownSectionID = UUID() // guaranteed to be different the first time + @MainActor func loadRecent(_ stack: CallStack) async -> () { - if let transactions = try? await model.transactionsT2(stack.push("loadRecent - \(balance.scopeInfo.url?.trimURL)"), - scopeInfo: balance.scopeInfo, - filterByState: .final, - limit: MAXRECENT, - includeRefreshes: false) { + if let transactions = try? await model.getTransactionsV2(stack.push("loadRecent - \(balance.scopeInfo.url?.trimURL)"), + scope: balance.scopeInfo, + filterByState: .final, + limit: MAXRECENT, + includeRefreshes: false) { // let recent = WalletModel.completedTransactions(transactions) // let slice = recent.prefix(MAXRECENT) // already sorted // withAnimation { recentTransactions = Array(slice) } withAnimation { recentTransactions = transactions } } } + @MainActor func loadCompleted(_ stack: CallStack) async -> () { - if let transactions = try? await model.transactionsT2(stack.push("loadCompleted - \(balance.scopeInfo.url?.trimURL)"), - scopeInfo: balance.scopeInfo, - filterByState: .final, - includeRefreshes: developerMode) { + if let transactions = try? await model.getTransactionsV2(stack.push("loadCompleted - \(balance.scopeInfo.url?.trimURL)"), + scope: balance.scopeInfo, + filterByState: .final, + includeRefreshes: developerMode) { // let completed = WalletModel.completedTransactions(transactions) // withAnimation { completedTransactions = completed } withAnimation { completedTransactions = transactions } } } + @MainActor func loadPending(_ stack: CallStack) async -> () { - if let transactions = try? await model.transactionsT2(stack.push("loadPending - \(balance.scopeInfo.url?.trimURL)"), - scopeInfo: balance.scopeInfo, - filterByState: .nonfinal, - includeRefreshes: developerMode) { + if let transactions = try? await model.getTransactionsV2(stack.push("loadPending - \(balance.scopeInfo.url?.trimURL)"), + scope: balance.scopeInfo, + filterByState: .nonfinal, + includeRefreshes: developerMode) { // let pending = WalletModel.pendingTransactions(transactions) // withAnimation { pendingTransactions = pending } withAnimation { pendingTransactions = transactions } diff --git a/TalerWallet1/Views/HelperViews/BarGraph.swift b/TalerWallet1/Views/HelperViews/BarGraph.swift @@ -22,6 +22,18 @@ struct BarGraphHeader: View { @State private var completedTransactions: [Transaction] = [] @ScaledMetric var barHeight = 9 // relative to fontSize + @MainActor + private func loadCompleted() async { + symLog.log(".task for BarGraphHeader(\(scope.currency)) - load \(MAXBARS) Transactions") + if let response = try? await model.getTransactionsV2(stack.push("BarGraphHeader - \(scope.url?.trimURL)"), + scope: scope, + filterByState: .done, + limit: MAXBARS + ) { + completedTransactions = response + } + } + var body: some View { let currencyInfo = controller.info(for: scope, controller.currencyTicker) HStack (alignment: .center, spacing: 10) { @@ -34,16 +46,7 @@ struct BarGraphHeader: View { maxBars: MAXBARS, barHeight: barHeight) } // .headerProminence(.increased) // unfortunately this is not useful - .task(id: shouldReloadBalances + 2_000_000) { - symLog.log(".task for BarGraphHeader(\(scope.currency)) - load \(MAXBARS) Transactions") - if let response = try? await model.transactionsT2(stack.push("BarGraphHeader - \(scope.url?.trimURL)"), - scopeInfo: scope, - filterByState: .done, - limit: MAXBARS - ) { - completedTransactions = response - } - } + .task(id: shouldReloadBalances + 2_000_000) { await loadCompleted() } } } // MARK: - diff --git a/TalerWallet1/Views/HelperViews/TransactionButton.swift b/TalerWallet1/Views/HelperViews/TransactionButton.swift @@ -67,6 +67,7 @@ struct TransactionButton: View { @State private var executed: Bool = false @State private var buttonTitle: String = EMPTYSTRING + @MainActor private func doAction() { disabled = true // don't try this more than once Task { // runs on MainActor