WithdrawAcceptView.swift (7223B)
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 if !tosAccepted { 65 ToSButtonView(stack: stack.push(), 66 exchangeBaseUrl: exchange2.exchangeBaseUrl, 67 viewID: SHEET_WITHDRAW_TOS, 68 p2p: false, 69 acceptAction: reloadExchange) 70 } 71 List { 72 if let withdrawalDetails { 73 let raw = withdrawalDetails.amountRaw 74 let effective = withdrawalDetails.amountEffective 75 let currency = raw.currencyStr 76 let fee = try! Amount.diff(raw, effective) 77 let outColor = WalletColors().transactionColor(false) 78 let inColor = WalletColors().transactionColor(true) 79 80 ThreeAmountsSection(stack: stack.push(), 81 scope: scope, 82 topTitle: String(localized: "Chosen amount to withdraw:"), 83 topAbbrev: String(localized: "Withdraw:", comment: "Chosen amount to withdraw:"), 84 topAmount: raw, 85 noFees: exchange2.noFees, 86 fee: fee, 87 feeIsNegative: true, 88 bottomTitle: String(localized: "Amount to obtain:"), 89 bottomAbbrev: String(localized: "Obtain:", comment: "Amount to obtain:"), 90 bottomAmount: effective, 91 large: false, 92 pending: false, 93 incoming: true, 94 baseURL: exchange2.exchangeBaseUrl, 95 txStateLcl: nil, // common.txState.major.localizedState 96 summary: nil, 97 merchant: nil, 98 products: nil) 99 if let wireFee { 100 if !wireFee.isZero { 101 let currencyInfo = controller.info(for: scope, controller.currencyTicker) 102 let feeStr = wireFee.formatted(currencyInfo, isNegative: false) 103 let feeTitle = String(localized: "FEE_WITHDRAW_BANK_WIRE", 104 defaultValue: "Your bank's wire fee: \(feeStr.0)") 105 let feeA11y = String(localized: "FEE_WITHDRAW_BANK_WIRE_A11Y", 106 defaultValue: "Your bank's wire fee: \(feeStr.1)", comment: "a11y") 107 Text(feeTitle) 108 .accessibilityLabel(Text(feeA11y)) 109 } 110 } 111 } else { 112 Section { 113 Text("The amount will be determined by the Cash Acceptor.") 114 } 115 } 116 } 117 .listStyle(myListStyle.style).anyView 118 .navigationTitle(navTitle) 119 .safeAreaInset(edge: .bottom) { 120 if tosAccepted { 121 let destination = WithdrawAcceptDone(stack: stack.push(), 122 // scope: scope, 123 exchangeBaseUrl: exchange2.exchangeBaseUrl, 124 url: url, 125 amountToTransfer: amountToTransfer.isZero ? nil : amountToTransfer) 126 NavigationLink(destination: destination) { 127 Text("Confirm Withdrawal") // SHEET_WITHDRAW_ACCEPT 128 } 129 .buttonStyle(TalerButtonStyle(type: .prominent)) 130 .padding(.horizontal) 131 } 132 } 133 } 134 .onAppear() { 135 symLog.log("onAppear") 136 DebugViewC.shared.setSheetID(SHEET_WITHDRAW_ACCEPT) // 132 WithdrawAcceptView 137 } 138 } else { // no exchange - should not happen 139 #if DEBUG 140 let message = url.host 141 #else 142 let message: String? = nil 143 #endif 144 let _ = symLog.log("Loading") 145 LoadingView(stack: stack.push(), scopeInfo: nil, message: message) 146 } 147 } 148 .task(id: exchange?.id) { // re-run this whenever the user switches the exchange 149 await viewDidLoad() 150 } 151 } 152 }