commit e11066ff16fa260ced62a3a2d0e9107dbd831c82
parent 32eb6cd428efabea97739e7ec75631a84e1ced22
Author: Marc Stibane <marc@taler.net>
Date: Sat, 28 Sep 2024 09:03:02 +0200
delete rows (swipeActions)
Diffstat:
5 files changed, 121 insertions(+), 86 deletions(-)
diff --git a/TalerWallet1/Views/Balances/BalancesPendingRowV.swift b/TalerWallet1/Views/Balances/BalancesPendingRowV.swift
@@ -64,7 +64,7 @@ struct BalancesPendingRowV: View {
currencyInfo: $currencyInfo,
navTitle: String(localized: "Pending", comment: "ViewTitle of TransactionList"),
scopeInfo: balance.scopeInfo,
- transactions: pendingTransactions,
+ transactions: $pendingTransactions,
reloadAllAction: reloadPending,
reloadOneAction: reloadOneAction)
}
@@ -81,7 +81,7 @@ struct BalancesPendingRowV: View {
fileprivate struct BalancesPendingRowV_Previews: PreviewProvider {
@MainActor
struct BindingViewContainer: View {
- @State private var pendingTransactions: [Transaction] = []
+ @State private var previewTransactions: [Transaction] = []
@State private var currencyInfoD: CurrencyInfo = CurrencyInfo.zero(DEMOCURRENCY)
var body: some View {
let flags: [BalanceFlag] = [.incomingConfirmation]
@@ -96,7 +96,7 @@ fileprivate struct BalancesPendingRowV_Previews: PreviewProvider {
stack: CallStack("Preview"),
currencyInfo: $currencyInfoD,
balance: balance,
- pendingTransactions: $pendingTransactions,
+ pendingTransactions: $previewTransactions,
reloadPending: {stack in },
reloadOneAction: nil)
}
diff --git a/TalerWallet1/Views/Balances/BalancesSectionView.swift b/TalerWallet1/Views/Balances/BalancesSectionView.swift
@@ -42,8 +42,8 @@ struct BalancesSectionView {
@State private var showSpendingHint = true
@State private var isShowingDetailView = false
- @State private var transactions: [Transaction] = []
@State private var completedTransactions: [Transaction] = []
+ @State private var recentTransactions: [Transaction] = []
@State private var pendingTransactions: [Transaction] = []
@State private var currencyInfo: CurrencyInfo = CurrencyInfo.zero(UNKNOWN)
@State private var currencyName: String = UNKNOWN
@@ -59,21 +59,32 @@ struct BalancesSectionView {
@State private var sectionID = UUID()
@State private var shownSectionID = UUID() // guaranteed to be different the first time
- func reloadCompleted(_ stack: CallStack) async -> () {
+ func loadRecent(_ stack: CallStack) async -> () {
if let transactions = try? await model.transactionsT(stack.push(),
scopeInfo: balance.scopeInfo,
-// filterByState: .final, // TODO: .final
+// filterByState: .done, // TODO: .done
includeRefreshes: false) {
- completedTransactions = WalletModel.completedTransactions(transactions)
+ let recent = WalletModel.completedTransactions(transactions)
+ // TODO: only load the MAXRECENT most recent transactions
+ let slice = recent.prefix(MAXRECENT) // already sorted
+ withAnimation { recentTransactions = Array(slice) }
}
}
-
- func reloadPending(_ stack: CallStack) async -> () {
+ func loadCompleted(_ stack: CallStack) async -> () {
+ if let transactions = try? await model.transactionsT(stack.push(),
+ scopeInfo: balance.scopeInfo,
+// filterByState: .final, // TODO: .final
+ includeRefreshes: developerMode) {
+ let completed = WalletModel.completedTransactions(transactions)
+ withAnimation { completedTransactions = completed }
+ }
+ }
+ func loadPending(_ stack: CallStack) async -> () {
if let transactions = try? await model.transactionsT(stack.push(),
scopeInfo: balance.scopeInfo,
filterByState: .nonfinal,
includeRefreshes: developerMode) {
- pendingTransactions = WalletModel.pendingTransactions(transactions)
+ withAnimation { pendingTransactions = WalletModel.pendingTransactions(transactions) }
}
}
}
@@ -93,8 +104,8 @@ extension BalancesSectionView: View {
currencyInfo: $currencyInfo,
navTitle: String(localized: "Transactions", comment: "ViewTitle of TransactionList"),
scopeInfo: scopeInfo,
- transactions: completedTransactions,
- reloadAllAction: reloadCompleted,
+ transactions: $completedTransactions,
+ reloadAllAction: loadCompleted,
reloadOneAction: reloadOneAction)
}
@@ -139,7 +150,7 @@ extension BalancesSectionView: View {
currencyInfo: $currencyInfo,
balance: balance,
pendingTransactions: $pendingTransactions,
- reloadPending: reloadPending,
+ reloadPending: loadPending,
reloadOneAction: reloadOneAction)
.padding(.leading, ICONLEADING)
}
@@ -188,37 +199,29 @@ extension BalancesSectionView: View {
currencySymbol = currencyInfo.altUnitSymbol ?? currencyName
}
.task(id: shouldReloadBalances + 1_000_000) {
-// if shownSectionID != sectionID {
- symLog.log(".task for BalancesSectionView - reload Transactions")
- // TODO: only load the MAXRECENT most recent transactions
- if let response = try? await model.transactionsT(stack.push(".task - reload Transactions"), scopeInfo: scopeInfo, includeRefreshes: developerMode) {
- transactions = response
- pendingTransactions = WalletModel.pendingTransactions(response)
- completedTransactions = WalletModel.completedTransactions(response)
- shownSectionID = sectionID
- }
-// } else {
-// symLog.log("task for BalancesSectionView \(sectionID) ❗️ skip reloading Transactions")
-// }
+ symLog.log(".task for BalancesSectionView - load recent+completed+pending")
+ await loadRecent(stack.push(".task - load recent"))
+ await loadCompleted(stack.push(".task - load completed"))
+ await loadPending(stack.push(".task - load pending"))
}
- let transactionCount = completedTransactions.count
/// if there is only one currency, then show MAXRECENT recent transactions
- if sectionCount == 1 && transactionCount > 0 {
+ if sectionCount == 1 && recentTransactions.count > 0 {
Section {
- let slice = completedTransactions.prefix(MAXRECENT) // already sorted
- let threeTransactions = Array(slice)
+ let _ = symLog.log("recent transactions")
TransactionsArraySliceV(symLog: symLog,
stack: stack.push(),
currencyInfo: $currencyInfo,
scopeInfo: scopeInfo,
- transactions: threeTransactions,
+ transactions: $recentTransactions,
+ reloadAllAction: loadRecent,
reloadOneAction: reloadOneAction)
.padding(.leading, ICONLEADING)
} header: {
if !minimalistic {
- let count = transactionCount > MAXRECENT ? MAXRECENT : transactionCount
- Text(count > 1 ? "Recent \(count) transactions"
- : "Recent transaction")
+ let recentHeader = recentTransactions.count > 1
+ ? String(localized: "Recent transactions", comment: "section header plural")
+ : String(localized: "Recent transaction", comment: "section header singular")
+ Text(recentHeader)
.talerFont(.title3)
.foregroundColor(WalletColors().secondary(colorScheme, colorSchemeContrast))
}
diff --git a/TalerWallet1/Views/Overview/OverviewRowV.swift b/TalerWallet1/Views/Overview/OverviewRowV.swift
@@ -23,7 +23,12 @@ struct CurrenciesCell: View {
/// Renders the Balance button. "Balance" leading, amountStr trailing. If it doesn't fit in one row then
/// amount (trailing) goes underneath "Balance" (leading).
var body: some View {
- let amountV = AmountV(stack: stack.push(), currencyInfo: $currencyInfo, amount: amount, isNegative: false, large: true)
+ let amountV = AmountV(stack: stack.push(),
+ currencyInfo: $currencyInfo,
+ amount: amount,
+ isNegative: nil, // don't show the + sign
+ strikethrough: false,
+ large: true)
.foregroundColor(.primary)
let hLayout = amountV
.frame(maxWidth: .infinity, alignment: .trailing)
diff --git a/TalerWallet1/Views/Overview/OverviewSectionV.swift b/TalerWallet1/Views/Overview/OverviewSectionV.swift
@@ -36,8 +36,8 @@ struct OverviewSectionV {
@State private var showSpendingHint = true
@State private var isShowingDetailView = false
- @State private var transactions: [Transaction] = []
@State private var completedTransactions: [Transaction] = []
+ @State private var recentTransactions: [Transaction] = []
@State private var pendingTransactions: [Transaction] = []
@State private var currencyInfo: CurrencyInfo = CurrencyInfo.zero(UNKNOWN)
@State private var currencyName: String = UNKNOWN
@@ -50,15 +50,32 @@ struct OverviewSectionV {
@State private var sectionID = UUID()
@State private var shownSectionID = UUID() // guaranteed to be different the first time
- func reloadCompleted(_ stack: CallStack) async -> () {
- if let transactions = try? await model.transactionsT(stack.push(), scopeInfo: balance.scopeInfo, includeRefreshes: developerMode) {
- completedTransactions = WalletModel.completedTransactions(transactions)
+ func loadRecent(_ stack: CallStack) async -> () {
+ if let transactions = try? await model.transactionsT(stack.push(),
+ scopeInfo: balance.scopeInfo,
+// filterByState: .done, // TODO: .done
+ includeRefreshes: false) {
+ let recent = WalletModel.completedTransactions(transactions)
+ // TODO: only load the MAXRECENT most recent transactions
+ let slice = recent.prefix(MAXRECENT) // already sorted
+ withAnimation { recentTransactions = Array(slice) }
}
}
-
- func reloadPending(_ stack: CallStack) async -> () {
- if let transactions = try? await model.transactionsT(stack.push(), scopeInfo: balance.scopeInfo, includeRefreshes: developerMode) {
- pendingTransactions = WalletModel.pendingTransactions(transactions)
+ func loadCompleted(_ stack: CallStack) async -> () {
+ if let transactions = try? await model.transactionsT(stack.push(),
+ scopeInfo: balance.scopeInfo,
+// filterByState: .final, // TODO: .final
+ includeRefreshes: developerMode) {
+ let completed = WalletModel.completedTransactions(transactions)
+ withAnimation { completedTransactions = completed }
+ }
+ }
+ func loadPending(_ stack: CallStack) async -> () {
+ if let transactions = try? await model.transactionsT(stack.push(),
+ scopeInfo: balance.scopeInfo,
+ filterByState: .nonfinal,
+ includeRefreshes: developerMode) {
+ withAnimation { pendingTransactions = WalletModel.pendingTransactions(transactions) }
}
}
}
@@ -88,7 +105,7 @@ extension OverviewSectionV: View {
amountToTransfer: $amountToTransfer, // does still have the wrong currency
summary: $summary,
completedTransactions: $completedTransactions,
- reloadAllAction: reloadCompleted,
+ reloadAllAction: loadCompleted,
reloadOneAction: reloadOneAction)
if pendingTransactions.count > 0 {
BalancesPendingRowV(//symLog: symLog,
@@ -96,7 +113,7 @@ extension OverviewSectionV: View {
currencyInfo: $currencyInfo,
balance: balance,
pendingTransactions: $pendingTransactions,
- reloadPending: reloadPending,
+ reloadPending: loadPending,
reloadOneAction: reloadOneAction)
.padding(.leading, ICONLEADING)
}
@@ -113,37 +130,30 @@ extension OverviewSectionV: View {
currencySymbol = currencyInfo.altUnitSymbol ?? currencyName
}
.task(id: shouldReloadBalances + 1_000_000) {
-// if shownSectionID != sectionID {
- symLog.log(".task for BalancesSectionView - reload Transactions")
- // TODO: only load the MAXRECENT most recent transactions
- if let response = try? await model.transactionsT(stack.push(".task - reload Transactions"), scopeInfo: scopeInfo, includeRefreshes: developerMode) {
- transactions = response
- pendingTransactions = WalletModel.pendingTransactions(response)
- completedTransactions = WalletModel.completedTransactions(response)
- shownSectionID = sectionID
- }
-// } else {
-// symLog.log("task for BalancesSectionView \(sectionID) ❗️ skip reloading Transactions")
-// }
+ symLog.log(".task for OverviewSectionV - load recent+completed+pending")
+ await loadRecent(stack.push(".task - load recent"))
+ await loadCompleted(stack.push(".task - load completed"))
+ await loadPending(stack.push(".task - load pending"))
+ shownSectionID = sectionID
}
- let transactionCount = completedTransactions.count
/// if there is only one currency, then show MAXRECENT recent transactions
- if sectionCount == 1 && transactionCount > 0 {
+ if sectionCount == 1 && recentTransactions.count > 0 {
Section {
- let slice = completedTransactions.prefix(MAXRECENT) // already sorted
- let threeTransactions = Array(slice)
+ let _ = symLog.log("recent transactions")
TransactionsArraySliceV(symLog: symLog,
stack: stack.push(),
currencyInfo: $currencyInfo,
scopeInfo: scopeInfo,
- transactions: threeTransactions,
+ transactions: $recentTransactions,
+ reloadAllAction: loadRecent,
reloadOneAction: reloadOneAction)
.padding(.leading, ICONLEADING)
} header: {
if !minimalistic {
- let count = transactionCount > MAXRECENT ? MAXRECENT : transactionCount
- Text(count > 1 ? "Recent \(count) transactions"
- : "Recent transaction")
+ let recentHeader = recentTransactions.count > 1
+ ? String(localized: "Recent transactions", comment: "section header plural")
+ : String(localized: "Recent transaction", comment: "section header singular")
+ Text(recentHeader)
.talerFont(.title3)
.foregroundColor(WalletColors().secondary(colorScheme, colorSchemeContrast))
}
@@ -192,7 +202,7 @@ fileprivate struct CurrenciesNavigationLinksV: View {
currencyInfo: $currencyInfo,
navTitle: String(localized: "Transactions", comment: "ViewTitle of TransactionList"),
scopeInfo: scopeInfo,
- transactions: completedTransactions,
+ transactions: $completedTransactions,
reloadAllAction: reloadAllAction,
reloadOneAction: reloadOneAction)
}
diff --git a/TalerWallet1/Views/Transactions/TransactionsListView.swift b/TalerWallet1/Views/Transactions/TransactionsListView.swift
@@ -20,7 +20,8 @@ struct TransactionsListView: View {
let navTitle: String
let scopeInfo: ScopeInfo
- let transactions: [Transaction]
+ @Binding var transactions: [Transaction]
+
let reloadAllAction: (_ stack: CallStack) async -> ()
let reloadOneAction: ((_ transactionId: String, _ viewHandles: Bool) async throws -> Transaction)
@@ -39,7 +40,8 @@ struct TransactionsListView: View {
stack: stack.push(),
currencyInfo: $currencyInfo,
scopeInfo: scopeInfo,
- transactions: transactions,
+ transactions: $transactions,
+ reloadAllAction: reloadAllAction,
reloadOneAction: reloadOneAction)
.padding(.leading, ICONLEADING)
}
@@ -67,7 +69,7 @@ struct TransactionsListView: View {
.navigationTitle(navTitle)
.accessibilityHint(String(localized: "Transaction list"))
.task {
- symLog.log(".task ")
+ symLog.log("❗️.task List❗️")
await reloadAllAction(stack.push())
}
.overlay {
@@ -87,10 +89,12 @@ struct TransactionsArraySliceV: View {
let stack: CallStack
@Binding var currencyInfo: CurrencyInfo
let scopeInfo: ScopeInfo
- let transactions: [Transaction]
+ @Binding var transactions: [Transaction]
+ let reloadAllAction: (_ stack: CallStack) async -> ()
let reloadOneAction: ((_ transactionId: String, _ viewHandles: Bool) async throws -> Transaction)
@EnvironmentObject private var model: WalletModel
+
var body: some View {
#if PRINT_CHANGES
let _ = Self._printChanges()
@@ -101,25 +105,38 @@ struct TransactionsArraySliceV: View {
let failAction = model.failTransaction
let suspendAction = model.suspendTransaction
let resumeAction = model.resumeTransaction
- ForEach(Array(zip(transactions.indices, transactions)), id: \.1) { index, transaction in
- NavigationLink {
- LazyView {
- TransactionSummaryV(stack: stack.push(),
- currencyInfo: $currencyInfo,
- transactionId: transaction.id,
- reloadAction: reloadOneAction,
- navTitle: nil,
- hasDone: false,
- abortAction: abortAction,
- deleteAction: deleteAction,
- failAction: failAction,
- suspendAction: suspendAction,
- resumeAction: resumeAction)
- }
- } label: {
+
+ ForEach(transactions, id: \.self) { transaction in
+ let destination = TransactionSummaryV(stack: stack.push(),
+ currencyInfo: $currencyInfo,
+ transactionId: transaction.id,
+ reloadAction: reloadOneAction,
+ navTitle: nil,
+ hasDone: false,
+ abortAction: abortAction,
+ deleteAction: deleteAction,
+ failAction: failAction,
+ suspendAction: suspendAction,
+ resumeAction: resumeAction)
+ let row = NavigationLink { destination } label: {
TransactionRowView(currencyInfo: $currencyInfo, transaction: transaction)
+ }.id(transaction.id)
+ if transaction.isDeleteable {
+ row.swipeActions(edge: .trailing) {
+ Button {
+ symLog?.log("deleteAction")
+ Task { // runs on MainActor
+ let _ = try? await deleteAction(transaction.id, false)
+ await reloadAllAction(stack.push())
+ }
+ } label: {
+ Label("Delete", systemImage: "trash")
+ }
+ .tint(.red)
+ }
+ } else {
+ row
}
- .id(Int(index))
}
}
}