WithdrawAcceptView.swift (7385B)
1 /* 2 * This file is part of GNU Taler, ©2022-25 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 struct WithdrawAcceptView: View { 13 private let symLog = SymLogV(0) 14 let stack: CallStack 15 let navTitle = String(localized: "Withdrawal") 16 17 // the URL from the bank website 18 let url: URL 19 let scope: ScopeInfo 20 @Binding var amountToTransfer: Amount 21 @Binding var wireFee: Amount? 22 @Binding var exchange: Exchange? // user can select one from possibleExchanges 23 24 @EnvironmentObject private var controller: Controller 25 @EnvironmentObject private var model: WalletModel 26 @AppStorage("myListStyle") var myListStyle: MyListStyle = .automatic 27 28 @State private var withdrawalDetails: WithdrawalDetailsForAmount? = nil 29 30 @MainActor 31 func reloadExchange() async -> Void { // TODO: throws? 32 if let exchange { 33 if let someExchange = try? await model.getExchangeByUrl(url: exchange.exchangeBaseUrl) { 34 self.exchange = someExchange 35 } 36 } 37 } 38 39 @MainActor 40 private func viewDidLoad() async { 41 symLog.log(".task \(exchange?.id ?? "nil")") 42 if !amountToTransfer.isZero, let exchange { 43 if let details = try? await model.getWithdrawalDetailsForAmount(amountToTransfer, 44 baseUrl: exchange.exchangeBaseUrl, 45 scope: nil) { // TODO: scope 46 withdrawalDetails = details 47 } 48 // agePicker.setAges(ages: details?.ageRestrictionOptions) 49 } else { // TODO: error 50 symLog.log("no exchangeBaseUrl or no exchange") 51 withdrawalDetails = nil 52 } 53 } 54 55 var body: some View { 56 #if PRINT_CHANGES 57 let _ = Self._printChanges() 58 let _ = symLog.vlog(scope.url ?? amountToTransfer.readableDescription) // just to get the # 59 #endif 60 ZStack { // there is only _one_ Z item ever - use ZStack to ensure .task is run only _once_ when exchange is switched 61 if let exchange2 = exchange { // there should always be an exchange... 62 VStack { 63 let tosAccepted = exchange2.tosStatus == .accepted 64 || exchange2.tosStatus == .missingTos // no ToS to accept 65 if !tosAccepted { 66 ToSButtonView(stack: stack.push(), 67 exchangeBaseUrl: exchange2.exchangeBaseUrl, 68 viewID: SHEET_WITHDRAW_TOS, 69 p2p: false, 70 acceptAction: reloadExchange) 71 } 72 List { 73 if let withdrawalDetails { 74 let raw = withdrawalDetails.amountRaw 75 let effective = withdrawalDetails.amountEffective 76 let currency = raw.currencyStr 77 let fee = try! Amount.diff(raw, effective) 78 let outColor = WalletColors().transactionColor(false) 79 let inColor = WalletColors().transactionColor(true) 80 81 ThreeAmountsSection(stack: stack.push(), 82 scope: scope, 83 topTitle: String(localized: "Chosen amount to withdraw:"), 84 topAbbrev: String(localized: "Withdraw:", comment: "Chosen amount to withdraw:"), 85 topAmount: raw, 86 noFees: exchange2.noFees, 87 fee: fee, 88 feeIsNegative: true, 89 bottomTitle: String(localized: "Amount to obtain:"), 90 bottomAbbrev: String(localized: "Obtain:", comment: "Amount to obtain:"), 91 bottomAmount: effective, 92 large: false, 93 pendingDialog: false, 94 isDone: false, 95 incoming: true, 96 baseURL: exchange2.exchangeBaseUrl, 97 txStateLcl: nil, // common.txState.major.localizedState 98 summary: nil, 99 products: nil) 100 if let wireFee { 101 if !wireFee.isZero { 102 let currencyInfo = controller.info(for: scope, controller.currencyTicker) 103 let feeStr = wireFee.formatted(currencyInfo, isNegative: false) 104 let feeTitle = String(localized: "FEE_WITHDRAW_BANK_WIRE", 105 defaultValue: "Your bank's wire fee: \(feeStr.0)") 106 let feeA11y = String(localized: "FEE_WITHDRAW_BANK_WIRE_A11Y", 107 defaultValue: "Your bank's wire fee: \(feeStr.1)", comment: "a11y") 108 Text(feeTitle) 109 .accessibilityLabel(Text(feeA11y)) 110 } 111 } 112 } else { 113 Section { 114 Text("The amount will be determined by the Cash Acceptor.") 115 } 116 } 117 } 118 .listStyle(myListStyle.style).anyView 119 .navigationTitle(navTitle) 120 .safeAreaInset(edge: .bottom) { 121 if tosAccepted { 122 let destination = WithdrawAcceptDone(stack: stack.push(), 123 // scope: scope, 124 exchangeBaseUrl: exchange2.exchangeBaseUrl, 125 url: url, 126 amountToTransfer: amountToTransfer.isZero ? nil : amountToTransfer) 127 NavigationLink(destination: destination) { 128 Text("Confirm Withdrawal") // SHEET_WITHDRAW_ACCEPT 129 } 130 .buttonStyle(TalerButtonStyle(type: .prominent)) 131 .padding(.horizontal) 132 } 133 } 134 } 135 .onAppear() { 136 symLog.log("onAppear") 137 DebugViewC.shared.setSheetID(SHEET_WITHDRAW_ACCEPT, // 132 WithdrawAcceptView 138 stack: stack.push()) 139 } 140 } else { // no exchange - should not happen 141 #if DEBUG 142 let message = url.host 143 #else 144 let message: String? = nil 145 #endif 146 let _ = symLog.log("Loading") 147 LoadingView(stack: stack.push(), scopeInfo: nil, message: message) 148 } 149 } 150 .task(id: exchange?.id) { // re-run this whenever the user switches the exchange 151 await viewDidLoad() 152 } 153 } 154 }