taler-ios

iOS apps for GNU Taler (wallet)
Log | Files | Refs | README | LICENSE

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 }