BalancesListView.swift (5686B)
1 /* 2 * This file is part of GNU Taler, ©2022-26 Taler Systems S.A. 3 * See LICENSE.md 4 */ 5 /** 6 * @author Marc Stibane 7 */ 8 import SwiftUI 9 import taler_swift 10 import SymLog 11 import AVFoundation 12 13 /// This view shows the list of balances / currencies, each in its own section 14 struct BalancesListView: View { 15 private let symLog = SymLogV(0) 16 let stack: CallStack 17 let title: String 18 @Binding var selectedBalance: Balance? // set in TransactionsListView 19 @Binding var reloadTransactions: Int 20 21 @EnvironmentObject private var model: WalletModel 22 @EnvironmentObject private var controller: Controller 23 @Environment(\.accessibilityVoiceOverEnabled) private var voiceOverEnabled 24 @AppStorage("myListStyle") var myListStyle: MyListStyle = .automatic 25 @AppStorage("preferredColorScheme") var preferredColorScheme: Int = 0 26 @AppStorage("oimEuro") var oimEuro: Bool = false 27 28 @State private var amountToTransfer = Amount.zero(currency: EMPTYSTRING) // Update currency when used 29 @State private var summary = EMPTYSTRING 30 @State private var showRealCashHint = true 31 32 @State private var historyTapped: Int? = nil 33 @Namespace var namespace 34 35 private static func className() -> String {"\(self)"} 36 37 func refresh() async { 38 controller.hapticNotification(.success) 39 symLog.log("refreshing balances") 40 await controller.loadBalances(stack.push("refreshing balances"), model) 41 } 42 43 @ViewBuilder 44 func balancesList() -> some View { 45 let count = controller.balances.count 46 let list = List { 47 if !controller.haveProdBalance && !controller.defaultExchanges.isEmpty { 48 ProdSectionView(stack: stack.push(), 49 showRealCashHint: $showRealCashHint, 50 isEmpty: false, 51 disabled: false) 52 } 53 ForEachWithIndex(data: controller.balances) { index, balance in 54 BalancesSectionView(stack: stack.push("\(balance.scopeInfo.currency)"), 55 balance: balance, // this is the currency to be used 56 selectedBalance: $selectedBalance, // set in TransactionsListView 57 balanceIndex: index, 58 sectionCount: count, 59 amountToTransfer: $amountToTransfer, // does still have the wrong currency 60 summary: $summary, 61 historyTapped: $historyTapped, 62 reloadTransactions: $reloadTransactions) 63 } 64 #if DEBUG || TALER_NIGHTLY 65 if count > 1 { // otherwise it comes before recentTransactions 66 DiscountPassesSection(stack: stack.push()) 67 } 68 #endif 69 } 70 .listStyle(myListStyle.style).anyView 71 .background(FullBackground()) 72 .onAppear() { 73 DebugViewC.shared.setViewID(VIEW_BALANCES, stack: stack.push("onAppear")) 74 if !controller.oimModeActive { 75 print("🚩BalancesListView.onAppear() reset selectedBalance") 76 // if count > 1 { 77 selectedBalance = nil // reset 78 // } 79 } 80 } 81 .refreshable { 82 await refresh() 83 } 84 .navigationTitle(title) 85 if #available(iOS 26.0, *) { 86 let list26 = list 87 .toolbar { 88 ToolbarItem(placement: .topBarTrailing) { //secondaryAction 89 SettingsButton26(sortPriority: 0) 90 } 91 } 92 #if OIM 93 if controller.oimModeActive || voiceOverEnabled { 94 list // hide SettingsButton (in Toolbar) 95 } else { 96 list26 97 } 98 #else 99 list26 100 #endif 101 } else { 102 list 103 } 104 } 105 106 var body: some View { 107 #if PRINT_CHANGES 108 let _ = Self._printChanges() 109 let _ = symLog.vlog() // just to get the # to compare it with .onAppear & onDisappear 110 #endif 111 /// In standard mode, selectedBalance just sets a "preference" which balance to pre-select for Actions. 112 /// However, the user can select another balance (with the picker) in each action 113 /// In OIM mode, the user selects a balance 'here' (in OIMView) when tapping on a savings box (representing the balance) 114 115 let list = balancesList() 116 .onChange(of: controller.oimModeActive) { oimModeActive in 117 if !oimModeActive { 118 print("🚩BalancesListView.onChange(of: oimModeActive) reset selectedBalance") 119 // if count > 1 { 120 selectedBalance = nil // reset 121 // } 122 } 123 } 124 ZStack { 125 if preferredColorScheme == 3, #available(iOS 17.0, *) { 126 list.scrollContentBackground(.hidden) 127 } else { 128 list 129 } 130 } 131 .overlay { if #available(iOS 16.4, *) { 132 if controller.oimModeActive { 133 #if OIM 134 OIMbalances(stack: stack.push(), 135 selectedBalance: $selectedBalance, // set to user choice 136 historyTapped: $historyTapped, 137 oimEuro: oimEuro) 138 .environmentObject(NamespaceWrapper(namespace)) // keep OIMviews apart 139 #endif // OIM 140 } 141 } } 142 } 143 }