DepositAmountV.swift (4563B)
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 12 // Called from DepositSelectV 13 struct DepositAmountV: View { 14 private let symLog = SymLogV(0) 15 let stack: CallStack 16 // when Action is tapped while in currency TransactionList… 17 let selectedBalance: Balance? // …then use THIS balance, otherwise show picker 18 @Binding var amountLastUsed: Amount 19 let paytoUri: String? 20 let label: String? 21 22 @EnvironmentObject private var controller: Controller 23 @EnvironmentObject private var model: WalletModel 24 25 @State private var balanceIndex = 0 26 @State private var balance: Balance? = nil // nil only when balances == [] 27 @State private var currencyInfo: CurrencyInfo = CurrencyInfo.zero(UNKNOWN) 28 @State private var amountToTransfer = Amount.zero(currency: EMPTYSTRING) // Update currency when used 29 @State private var amountAvailable = Amount.zero(currency: EMPTYSTRING) // GetMaxPeerPushAmount 30 31 @MainActor 32 private func viewDidLoad() async { 33 let balances = controller.balances 34 if let selectedBalance { 35 let disableDeposits = selectedBalance.disableDirectDeposits ?? false 36 if disableDeposits { 37 // find another balance 38 balance = Balance.firstwithDeposit(balances) 39 } else { 40 balance = selectedBalance 41 } 42 } else { 43 balance = Balance.firstwithDeposit(balances) 44 } 45 if let balance { 46 balanceIndex = balances.firstIndex(of: balance) ?? 0 47 } else { 48 balanceIndex = 0 49 balance = (balances.count > 0) ? balances[0] : nil 50 } 51 } 52 53 @MainActor 54 private func newBalance() async { 55 // runs whenever the user changes the exchange via ScopePicker, or on new currencyInfo 56 symLog.log("❗️ task \(balanceIndex)") 57 if let balance { 58 let scope = balance.scopeInfo 59 amountToTransfer.setCurrency(scope.currency) 60 currencyInfo = controller.info(for: scope, controller.currencyTicker) 61 do { 62 amountAvailable = try await model.getMaxDepositAmount(scope) 63 } catch { 64 // TODO: Error 65 amountAvailable = balance.available 66 } 67 } 68 } 69 70 var body: some View { 71 #if PRINT_CHANGES 72 let _ = Self._printChanges() 73 #endif 74 let count = controller.balances.count 75 let _ = symLog.log("count = \(count)") 76 let currencySymbol = currencyInfo.symbol 77 let navA11y = DepositAmountView.navTitle(currencyInfo.name, true) // always include currency for a11y 78 let navTitle = DepositAmountView.navTitle(currencySymbol, currencyInfo.hasSymbol) 79 let scrollView = ScrollView { 80 if let label { 81 Text("to \(label)") 82 .talerFont(.picker) 83 .frame(maxWidth: .infinity, alignment: .leading) 84 .padding(.horizontal) 85 } 86 if count > 0 { 87 ScopePicker(stack: stack.push(), 88 value: $balanceIndex, 89 onlyNonZero: true) // can only send what exists 90 { index in 91 balanceIndex = index 92 balance = controller.balances[index] 93 } 94 .padding(.horizontal) 95 .padding(.bottom, 4) 96 } 97 DepositAmountView(stack: stack.push(), 98 balance: $balance, 99 balanceIndex: $balanceIndex, 100 amountLastUsed: $amountLastUsed, 101 amountToTransfer: $amountToTransfer, 102 amountAvailable: amountAvailable, 103 paytoUri: paytoUri) 104 } // ScrollView 105 .navigationTitle(navTitle) 106 .frame(maxWidth: .infinity, alignment: .leading) 107 .background(WalletColors().backgroundColor.edgesIgnoringSafeArea(.all)) 108 .task { 109 setVoice(to: nil) 110 await viewDidLoad() 111 } 112 .task(id: balanceIndex + (1000 * controller.currencyTicker)) { await newBalance() } 113 114 if #available(iOS 16.4, *) { 115 scrollView.toolbar(.hidden, for: .tabBar) 116 .scrollBounceBehavior(.basedOnSize) 117 } else { 118 scrollView 119 } 120 } 121 }