taler-ios

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

commit d5955cd69b75bcbb301f3c922dc73d8b23e9fffa
parent f96ea13f3385933939c0fc08805dd5b680bcf70f
Author: Marc Stibane <marc@taler.net>
Date:   Sat, 19 Oct 2024 17:56:33 +0200

ScopePicker

Diffstat:
MTalerWallet1/Views/Actions/Banking/ManualWithdraw.swift | 237++++++++++++++++++++++++++++++++++++++++++++++++++-----------------------------
MTalerWallet1/Views/Main/MainView.swift | 7++-----
MTalerWallet1/Views/Sheets/WithdrawExchangeV.swift | 12++++--------
3 files changed, 157 insertions(+), 99 deletions(-)

diff --git a/TalerWallet1/Views/Actions/Banking/ManualWithdraw.swift b/TalerWallet1/Views/Actions/Banking/ManualWithdraw.swift @@ -15,12 +15,94 @@ struct ManualWithdraw: View { private let symLog = SymLogV(0) let stack: CallStack @Binding var selectedBalance: Balance? -// @Binding var currencyInfo: CurrencyInfo + @Binding var amountLastUsed: Amount let isSheet: Bool -// let exchangeBaseUrl: String - let scopeInfo: ScopeInfo? - @Binding var exchange: Exchange? - @Binding var amountToTransfer: Amount + + @EnvironmentObject private var controller: Controller + + @State private var balanceIndex = 0 + @State private var balance: Balance? = nil // nil only when balances == [] + @State private var currencyInfo: CurrencyInfo = CurrencyInfo.zero(UNKNOWN) + + func navTitle(_ currency: String, _ condition: Bool = false) -> String { + condition ? String(localized: "NavTitle_Withdraw_Currency)", + defaultValue: "Withdraw \(currency)", + comment: "NavTitle: Withdraw 'currency'") + : String(localized: "NavTitle_Withdraw", + defaultValue: "Withdraw", + comment: "NavTitle: Withdraw") + } + + var body: some View { +#if PRINT_CHANGES + let _ = Self._printChanges() +#endif + let currencySymbol = currencyInfo.symbol + let navA11y = navTitle(currencyInfo.name) + let navTitle = navTitle(currencySymbol, currencyInfo.hasSymbol) + let count = controller.balances.count + let _ = symLog.log("count = \(count)") + let scrollView = ScrollView { + if count > 0 { + ScopePicker(value: $balanceIndex, + onlyNonZero: false) + { index in + balanceIndex = index + balance = controller.balances[index] + } + .padding(.horizontal) + .padding(.bottom, 4) + } + ManualWithdrawContent(stack: stack.push(), + currencyInfo: $currencyInfo, + balance: $balance, + balanceIndex: $balanceIndex, + amountLastUsed: $amountLastUsed) + } // ScrollView + .navigationTitle(navTitle) + .frame(maxWidth: .infinity, alignment: .leading) + .background(WalletColors().backgroundColor.edgesIgnoringSafeArea(.all)) + .onAppear { + if isSheet { + DebugViewC.shared.setSheetID(SHEET_WITHDRAW_ACCEPT) // 132 WithdrawAcceptView + } else { + DebugViewC.shared.setViewID(VIEW_WITHDRAWAL, // 30 WithdrawAmount + stack: stack.push()) + } + symLog.log("❗️ \(navTitle) onAppear") + } + .onDisappear { + symLog.log("❗️ \(navTitle) onDisappear") + } + .task { + if let selectedBalance { + balance = selectedBalance + balanceIndex = controller.balances.firstIndex(of: selectedBalance) ?? 0 + } else { + balanceIndex = 0 + balance = (count > 0) ? controller.balances[0] : nil + } + } + + if #available(iOS 16.0, *) { + if #available(iOS 16.4, *) { + scrollView.toolbar(.hidden, for: .tabBar) + .scrollBounceBehavior(.basedOnSize) + } else { + scrollView.toolbar(.hidden, for: .tabBar) + } + } else { + scrollView + } + } +} +// MARK: - +struct ManualWithdrawContent: View { + private let symLog = SymLogV() + let stack: CallStack + @Binding var currencyInfo: CurrencyInfo + @Binding var balance: Balance? + @Binding var balanceIndex: Int @Binding var amountLastUsed: Amount @EnvironmentObject private var controller: Controller @@ -28,49 +110,49 @@ struct ManualWithdraw: View { @AppStorage("minimalistic") var minimalistic: Bool = false @State private var withdrawalAmountDetails: WithdrawalAmountDetails? = nil + @State private var amountToTransfer = Amount.zero(currency: EMPTYSTRING) // Update currency when used // @State var ageMenuList: [Int] = [] // @State var selectedAge = 0 - @State private var currencyInfo: CurrencyInfo = CurrencyInfo.zero(UNKNOWN) + @State private var exchanges: [Exchange] = [] + @State private var exchange: Exchange? = nil + + private func exchangeVia(_ baseURL: String?) -> String? { + if let baseURL { + return String(localized: "via \(baseURL.trimURL)") + } + return nil + } var body: some View { #if PRINT_CHANGES let _ = Self._printChanges() let _ = symLog.vlog() // just to get the # to compare it with .onAppear & onDisappear #endif - let baseURL = exchange?.exchangeBaseUrl - ?? scopeInfo?.url - ?? String(localized: "Unknown payment service") - Group { - if let exchange { - let scopeInfo = exchange.scopeInfo - let currency = scopeInfo.currency - let currencyInfo = controller.info2(for: currency, controller.currencyTicker) + let coinData = CoinData(details: withdrawalAmountDetails) + Group { + if let balance { + let scopeInfo = balance.scopeInfo + let currency = scopeInfo.currency +// let currencyInfo = controller.info(for: currency, controller.currencyTicker) + let baseURL = exchange?.exchangeBaseUrl ?? scopeInfo.url // nil for global currency - let navTitle = String(localized: "NavTitle_Withdraw (currency)", - defaultValue: "Withdraw \(currencyInfo.symbol)", - comment: "NavTitle: Withdraw 'currencySymbol'") - let navA11y = String(localized: "NavTitle_Withdraw (currency) A11y", - defaultValue: "Withdraw \(currencyInfo.name)", - comment: "NavTitle: Withdraw 'currency'") -// let agePicker = AgePicker(ageMenuList: $ageMenuList, selectedAge: $selectedAge) +// let agePicker = AgePicker(ageMenuList: $ageMenuList, selectedAge: $selectedAge) - let coinData = CoinData(details: withdrawalAmountDetails) -// let restrictAge: Int? = (selectedAge == 0) ? nil -// : selectedAge +// let restrictAge: Int? = (selectedAge == 0) ? nil +// : selectedAge // let _ = print(selectedAge, restrictAge) - let destination = LazyView { - ManualWithdrawDone(stack: stack.push(), - currencyInfo: $currencyInfo, - exchange: exchange, - balance: nil, - amountToTransfer: amountToTransfer) -// restrictAge: restrictAge) - } - let disabled = amountToTransfer.isZero || coinData.invalid || coinData.tooMany - let tosAccepted = exchange.tosStatus == .accepted - ScrollView { VStack(alignment: .trailing) { - Text("via \(exchange.exchangeBaseUrl.trimURL)") + let destination = ManualWithdrawDone(stack: stack.push(), + currencyInfo: $currencyInfo, + exchange: nil, // exchange, + balance: balance, + amountToTransfer: amountToTransfer) +// restrictAge: restrictAge) + let disabled = amountToTransfer.isZero || coinData.invalid || coinData.tooMany + let tosAccepted = (exchange?.tosStatus == .accepted) ?? false + + VStack(alignment: .trailing) { + Text(exchangeVia(baseURL) ?? currency) .multilineTextAlignment(.center) .talerFont(.body) if tosAccepted { @@ -95,63 +177,46 @@ struct ManualWithdraw: View { .buttonStyle(TalerButtonStyle(type: .prominent, disabled: disabled)) .disabled(disabled) .padding(.top) - } else { + } else if let baseURL { ToSButtonView(stack: stack.push(), - exchangeBaseUrl: exchange.exchangeBaseUrl, + exchangeBaseUrl: baseURL, viewID: VIEW_WITHDRAW_TOS, // 31 WithdrawTOSView TODO: YIKES might be withdraw-exchange p2p: false, acceptAction: nil) .padding(.top) } - }.padding(.horizontal) } // ScrollVStack - .frame(maxWidth: .infinity, alignment: .leading) -// .scrollBounceBehavior(.basedOnSize) needs iOS 16.4 - .background(WalletColors().backgroundColor.edgesIgnoringSafeArea(.all)) - .navigationTitle(navTitle) - .onAppear { - if isSheet { - DebugViewC.shared.setSheetID(SHEET_WITHDRAW_ACCEPT) // 132 WithdrawAcceptView - } else { - DebugViewC.shared.setViewID(VIEW_WITHDRAWAL, // 30 WithdrawAmount - stack: stack.push()) - } - symLog.log("❗️ \(navTitle) onAppear") - } - .onDisappear { - symLog.log("❗️ \(navTitle) onDisappear") + }.padding(.horizontal) // VStack + } else { // got no balance yet + Text("No balance. There seems to be a problem with the database...") } - } else { - let contacting = String(localized: "Contacting...") - LoadingView(scopeInfo: scopeInfo, message: contacting) - } - } - .task(id: amountToTransfer.value) { // re-run this whenever amountToTransfer changes - if let exchangeBaseUrl = scopeInfo?.url { - symLog.log("getExchangeByUrl(\(exchangeBaseUrl))") - if exchange == nil || exchange?.tosStatus != .accepted { - exchange = try? await model.getExchangeByUrl(url: exchangeBaseUrl) - } - if !amountToTransfer.isZero { - do { - let details = try await model.getWithdrawalDetailsForAmountM(exchangeBaseUrl, - amount: amountToTransfer, - viewHandles: true) - withdrawalAmountDetails = details -// agePicker.setAges(ages: withdrawalAmountDetails?.ageRestrictionOptions) - } catch WalletBackendError.walletCoreError(let walletBackendResponseError) { - symLog.log(walletBackendResponseError?.hint) - // TODO: ignore WALLET_CORE_REQUEST_CANCELLED but handle all others - // Passing non-nil to clientCancellationId will throw WALLET_CORE_REQUEST_CANCELLED - // when calling getWithdrawalDetailsForAmount again before the last call returned. - // Since amountToTransfer changed and we don't need the old fee anymore, we just - // ignore it and do nothing. - } catch { - symLog.log(error.localizedDescription) - withdrawalAmountDetails = nil - } - } - } - } + } // Group +// .task(id: amountToTransfer.value) { // re-run this whenever amountToTransfer changes +// if let exchangeBaseUrl = scopeInfo?.url { +// symLog.log("getExchangeByUrl(\(exchangeBaseUrl))") +// if exchange == nil || exchange?.tosStatus != .accepted { +// exchange = try? await model.getExchangeByUrl(url: exchangeBaseUrl) +// } +// if !amountToTransfer.isZero { +// do { +// let details = try await model.getWithdrawalDetailsForAmountM(exchangeBaseUrl, +// amount: amountToTransfer, +// viewHandles: true) +// withdrawalAmountDetails = details +//// agePicker.setAges(ages: withdrawalAmountDetails?.ageRestrictionOptions) +// } catch WalletBackendError.walletCoreError(let walletBackendResponseError) { +// symLog.log(walletBackendResponseError?.hint) +// // TODO: ignore WALLET_CORE_REQUEST_CANCELLED but handle all others +// // Passing non-nil to clientCancellationId will throw WALLET_CORE_REQUEST_CANCELLED +// // when calling getWithdrawalDetailsForAmount again before the last call returned. +// // Since amountToTransfer changed and we don't need the old fee anymore, we just +// // ignore it and do nothing. +// } catch { +// symLog.log(error.localizedDescription) +// withdrawalAmountDetails = nil +// } +// } +// } +// } } } // MARK: - diff --git a/TalerWallet1/Views/Main/MainView.swift b/TalerWallet1/Views/Main/MainView.swift @@ -341,11 +341,8 @@ extension MainView { let manualWithdrawDest = ManualWithdraw(stack: stack.push(Self.name), selectedBalance: $selectedBalance, - isSheet: false, - scopeInfo: scope, - exchange: $myExchange, - amountToTransfer: $amountToTransfer, - amountLastUsed: $amountLastUsed) + amountLastUsed: $amountLastUsed, // currency needs to be updated! + isSheet: false) ZStack(alignment: .bottom) { TabView(selection: tabSelection()) { diff --git a/TalerWallet1/Views/Sheets/WithdrawExchangeV.swift b/TalerWallet1/Views/Sheets/WithdrawExchangeV.swift @@ -31,19 +31,15 @@ struct WithdrawExchangeV: View { let _ = symLog.vlog() // just to get the # to compare it with .onAppear & onDisappear #endif if let exchange { - let currency = exchange.scopeInfo.currency + let scopeInfo = exchange.scopeInfo Group { ManualWithdraw(stack: stack.push(), selectedBalance: $selectedBalance, -// currencyInfo: $currencyInfo, - isSheet: true, - scopeInfo: exchange.scopeInfo, - exchange: $exchange, - amountToTransfer: $amountToTransfer, - amountLastUsed: $amountLastUsed) + amountLastUsed: $amountLastUsed, + isSheet: true) } .task(id: controller.currencyTicker) { - currencyInfo = controller.info2(for: currency, controller.currencyTicker) + currencyInfo = controller.info(for: scopeInfo, controller.currencyTicker) } } else { LoadingView(scopeInfo: nil, message: "No exchangeBaseUrl!")