commit acd7dda4e3a53a90d45bf330ae479b8e72afb2c0
parent 2f2f820ed0dded72a110c4f9c315ad554801a2c3
Author: Marc Stibane <marc@taler.net>
Date: Wed, 20 Nov 2024 07:28:00 +0100
DepositAmountView
Diffstat:
3 files changed, 212 insertions(+), 188 deletions(-)
diff --git a/TalerWallet.xcodeproj/project.pbxproj b/TalerWallet.xcodeproj/project.pbxproj
@@ -289,6 +289,8 @@
4EE77E7F2C0280E5007C9064 /* Taler_Wallet InfoPlist.xcstrings in Resources */ = {isa = PBXBuildFile; fileRef = 4EE77E7E2C0280E5007C9064 /* Taler_Wallet InfoPlist.xcstrings */; };
4EE77E812C06E513007C9064 /* WithdrawAcceptView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EE77E802C06E513007C9064 /* WithdrawAcceptView.swift */; };
4EE77E822C06E513007C9064 /* WithdrawAcceptView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EE77E802C06E513007C9064 /* WithdrawAcceptView.swift */; };
+ 4EE9864F2CE26E0F00F75634 /* DepositAmountView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EE9864E2CE26E0F00F75634 /* DepositAmountView.swift */; };
+ 4EE986502CE26E0F00F75634 /* DepositAmountView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EE9864E2CE26E0F00F75634 /* DepositAmountView.swift */; };
4EEBEFB02C8982180020D340 /* View+innerSize.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EEBEFAF2C8982180020D340 /* View+innerSize.swift */; };
4EEBEFB12C8982180020D340 /* View+innerSize.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EEBEFAF2C8982180020D340 /* View+innerSize.swift */; };
4EEC118D2B83DE4800146CFF /* AmountInputV.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EEC118C2B83DE4700146CFF /* AmountInputV.swift */; };
@@ -499,6 +501,7 @@
4EE77E7C2C0280E5007C9064 /* GNU_Taler InfoPlist.xcstrings */ = {isa = PBXFileReference; lastKnownFileType = text.json.xcstrings; path = "GNU_Taler InfoPlist.xcstrings"; sourceTree = "<group>"; };
4EE77E7E2C0280E5007C9064 /* Taler_Wallet InfoPlist.xcstrings */ = {isa = PBXFileReference; lastKnownFileType = text.json.xcstrings; path = "Taler_Wallet InfoPlist.xcstrings"; sourceTree = "<group>"; };
4EE77E802C06E513007C9064 /* WithdrawAcceptView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WithdrawAcceptView.swift; sourceTree = "<group>"; };
+ 4EE9864E2CE26E0F00F75634 /* DepositAmountView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DepositAmountView.swift; sourceTree = "<group>"; };
4EEBEFAF2C8982180020D340 /* View+innerSize.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "View+innerSize.swift"; sourceTree = "<group>"; };
4EEC118C2B83DE4700146CFF /* AmountInputV.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AmountInputV.swift; sourceTree = "<group>"; };
4EEC11922B83FB7A00146CFF /* SubjectInputV.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SubjectInputV.swift; sourceTree = "<group>"; };
@@ -924,6 +927,7 @@
children = (
4EBC0F002B7B3CD600C0CB19 /* DepositIbanV.swift */,
4E96583B2B79656E00404A68 /* DepositAmountV.swift */,
+ 4EE9864E2CE26E0F00F75634 /* DepositAmountView.swift */,
4E50B34F2A1BEE8000F9F01C /* ManualWithdraw.swift */,
4EBA82AC2A3F580500E5F39A /* QuiteSomeCoins.swift */,
4EB431662A1E55C700C5690E /* ManualWithdrawDone.swift */,
@@ -1257,6 +1261,7 @@
4E3EAE3E2A990778009F1BE8 /* ManualDetailsV.swift in Sources */,
4E3EAE3F2A990778009F1BE8 /* View+dismissTop.swift in Sources */,
4E3EAE402A990778009F1BE8 /* TransactionsListView.swift in Sources */,
+ 4EE9864F2CE26E0F00F75634 /* DepositAmountView.swift in Sources */,
4E0A71142C396D86002485BB /* Error+debugDescription.swift in Sources */,
4E3EAE412A990778009F1BE8 /* WalletBackendRequest.swift in Sources */,
4E3EAE422A990778009F1BE8 /* KeyboardResponder.swift in Sources */,
@@ -1392,6 +1397,7 @@
4E6EDD852A3615BE0031D520 /* ManualDetailsV.swift in Sources */,
4EB0950B2989CB7C0043A8A1 /* View+dismissTop.swift in Sources */,
4EB095562989CBFE0043A8A1 /* TransactionsListView.swift in Sources */,
+ 4EE986502CE26E0F00F75634 /* DepositAmountView.swift in Sources */,
4E0A71152C396D86002485BB /* Error+debugDescription.swift in Sources */,
4EB0951F2989CBCB0043A8A1 /* WalletBackendRequest.swift in Sources */,
4EAD117629F672FA008EDD0B /* KeyboardResponder.swift in Sources */,
diff --git a/TalerWallet1/Views/Actions/Banking/DepositAmountV.swift b/TalerWallet1/Views/Actions/Banking/DepositAmountV.swift
@@ -82,7 +82,7 @@ struct DepositAmountV: View {
.padding(.horizontal)
.padding(.bottom, 4)
}
- DepositAmountContent(stack: stack.push(),
+ DepositAmountView(stack: stack.push(),
balance: $balance,
balanceIndex: $balanceIndex,
amountLastUsed: $amountLastUsed,
@@ -93,13 +93,6 @@ struct DepositAmountV: View {
.navigationTitle(navTitle)
.frame(maxWidth: .infinity, alignment: .leading)
.background(WalletColors().backgroundColor.edgesIgnoringSafeArea(.all))
- .onAppear {
- DebugViewC.shared.setViewID(VIEW_DEPOSIT, stack: stack.push())
- symLog.log("❗️ \(navTitle) onAppear")
- }
- .onDisappear {
- symLog.log("❗️ \(navTitle) onDisappear")
- }
.task { await viewDidLoad() }
.task(id: balanceIndex + (1000 * controller.currencyTicker)) { await newBalance() }
@@ -115,183 +108,3 @@ struct DepositAmountV: View {
}
}
}
-// MARK: -
-struct DepositAmountContent: View {
- private let symLog = SymLogV(0)
- let stack: CallStack
- @Binding var balance: Balance?
- @Binding var balanceIndex: Int
- @Binding var amountLastUsed: Amount
- @Binding var amountToTransfer: Amount
- let amountAvailable: Amount
- let paytoUri: String?
-
- @EnvironmentObject private var controller: Controller
- @EnvironmentObject private var model: WalletModel
- @Environment(\.colorScheme) private var colorScheme
- @Environment(\.colorSchemeContrast) private var colorSchemeContrast
- @AppStorage("minimalistic") var minimalistic: Bool = false
-
- @State var checkDepositResult: CheckDepositResponse? = nil
- @State private var insufficient = false
- @State private var feeAmount: Amount? = nil
- @State private var feeStr: String = EMPTYSTRING
- @State private var depositStarted = false
- @State private var exchange: Exchange? = nil // wg. noFees
-
- private func feeLabel(_ feeString: String) -> String {
- feeString.count > 0 ? String(localized: "+ \(feeString) fee")
- : EMPTYSTRING
- }
-
- private func feeIsNotZero() -> Bool? {
- if let hasNoFees = exchange?.noFees {
- if hasNoFees {
- return nil // this exchange never has fees
- }
- }
- return checkDepositResult == nil ? false
- : true // TODO: !(feeAmount?.isZero ?? false)
- }
-
- private func computeFeeDeposit(_ amount: Amount) async -> ComputeFeeResult? {
- if amount.isZero {
- return ComputeFeeResult.zero()
- }
- let insufficient = (try? amount > amountAvailable) ?? true
- if insufficient {
- return ComputeFeeResult.insufficient()
- }
-// private func fee(ppCheck: CheckDepositResponse?) -> Amount? {
- do {
-// if let ppCheck {
-// // Outgoing: fee = effective - raw
-// feeAmount = try ppCheck.fees.coin + ppCheck.fees.wire + ppCheck.fees.refresh
-// return feeAmount
-// }
- } catch {
-
- }
- return nil
- }
-
- private func buttonTitle(_ amount: Amount) -> String {
- if let balance {
- let amountWithCurrency = amount.formatted(balance.scopeInfo, isNegative: false, useISO: true)
- return String(localized: "Deposit \(amountWithCurrency)", comment: "Button: amount with currency")
- }
- return subjectTitle(amount) // should never happen
- }
-
- private func subjectTitle(_ amount: Amount) -> String {
-// let amountStr = amount.formatted(scopeInfo, isNegative: false)
- return String(localized: "NavTitle_Deposit_AmountStr",
- defaultValue: "Deposit", comment: "NavTitle: Deposit")
- // defaultValue: "Deposit \(amountStr)", comment: "NavTitle: Deposit 'amountStr'")
- }
-
- @MainActor
- private func startDeposit() {
- if let paytoUri {
- depositStarted = true // don't run twice
- Task {
- symLog.log("Deposit")
- if let result = try? await model.createDepositGroup(paytoUri, amount: amountToTransfer) {
- symLog.log(result.transactionId)
- ViewState2.shared.popToRootView(stack.push())
- NotificationCenter.default.post(name: .TransactionDone, object: nil, userInfo: nil)
- } else {
- depositStarted = false
- }
- }
- }
- }
-
- var body: some View {
-#if PRINT_CHANGES
- let _ = Self._printChanges()
- let _ = symLog.vlog() // just to get the # to compare it with .onAppear & onDisappear
-#endif
- if depositStarted {
- LoadingView(scopeInfo: nil, message: "Depositing...")
- .navigationBarBackButtonHidden(true)
- .interactiveDismissDisabled() // can only use "Done" button to dismiss
- } else { Group {
- if let balance {
- let scopeInfo = balance.scopeInfo
- let availableStr = amountAvailable.formatted(scopeInfo, isNegative: false)
-
- let currencyInfo = controller.info(for: scopeInfo, controller.currencyTicker)
-// let amountVoiceOver = amountToTransfer.formatted(scopeInfo, isNegative: false)
- let insufficientLabel = String(localized: "You don't have enough \(currencyInfo.specs.name).")
-// let insufficientLabel2 = String(localized: "but you only have \(available) to deposit.")
-
- let disabled = insufficient || amountToTransfer.isZero
-
- Text("Available:\t\(availableStr)")
- .talerFont(.title3)
- .padding(.bottom, 2)
- CurrencyInputView(scope: scopeInfo,
- amount: $amountToTransfer,
- amountLastUsed: amountLastUsed,
- available: nil, // amountAvailable,
- title: minimalistic ? String(localized: "Amount:")
- : String(localized: "Amount to deposit:"),
- shortcutAction: nil)
-
- Text(insufficient ? insufficientLabel
- : feeLabel(feeStr))
- .talerFont(.body)
- .foregroundColor(insufficient ? .red
- : (feeAmount?.isZero ?? true) ? WalletColors().secondary(colorScheme, colorSchemeContrast)
- : .red)
- .padding(4)
- Button(buttonTitle(amountToTransfer)) { startDeposit() }
- .buttonStyle(TalerButtonStyle(type: .prominent, disabled: disabled || depositStarted))
- .disabled(disabled || depositStarted)
- .accessibilityHint(disabled ? String(localized: "enabled when amount is non-zero, but not higher than your available amount") : EMPTYSTRING)
- } else { // no balance - Yikes
- Text("No balance. There seems to be a problem with the database...")
- }
- }
-// .task(id: amountToTransfer.value) {
-// if let amountAvailable {
-// do {
-// insufficient = try amountToTransfer > amountAvailable
-// } catch {
-// print("Yikes❗️ insufficient failed❗️")
-// insufficient = true
-// }
-//
-// if insufficient {
-// announce("\(amountVoiceOver), \(insufficientLabel2)")
-// feeStr = EMPTYSTRING
-// }
-// }
-// if !insufficient {
-// if amountToTransfer.isZero {
-// feeStr = EMPTYSTRING
-// checkDepositResult = nil
-// } else if let paytoUri {
-// if let ppCheck = try? await model.checkDepositM(paytoUri, amount: amountToTransfer) {
-// if let feeAmount = fee(ppCheck: ppCheck) {
-// feeStr = feeAmount.formatted(scopeInfo, isNegative: false)
-// let feeLabel = feeLabel(feeStr)
-// announce("\(amountVoiceOver), \(feeLabel)")
-// } else {
-// feeStr = EMPTYSTRING
-// announce(amountVoiceOver)
-// }
-// checkDepositResult = ppCheck
-// } else {
-// checkDepositResult = nil
-// }
-// }
-// }
-// }
- } // else
- } // body
-}
-// MARK: -
-#if DEBUG
-#endif
diff --git a/TalerWallet1/Views/Actions/Banking/DepositAmountView.swift b/TalerWallet1/Views/Actions/Banking/DepositAmountView.swift
@@ -0,0 +1,205 @@
+/*
+ * This file is part of GNU Taler, ©2022-24 Taler Systems S.A.
+ * See LICENSE.md
+ */
+/**
+ * @author Marc Stibane
+ */
+import SwiftUI
+import taler_swift
+import SymLog
+
+// Called when tapping [Withdraw]
+struct DepositAmountView: View {
+ private let symLog = SymLogV(0)
+ let stack: CallStack
+ @Binding var balance: Balance?
+ @Binding var balanceIndex: Int
+ @Binding var amountLastUsed: Amount
+ @Binding var amountToTransfer: Amount
+ let amountAvailable: Amount
+ let paytoUri: String?
+
+ @EnvironmentObject private var controller: Controller
+ @EnvironmentObject private var model: WalletModel
+ @Environment(\.colorScheme) private var colorScheme
+ @Environment(\.colorSchemeContrast) private var colorSchemeContrast
+ @AppStorage("minimalistic") var minimalistic: Bool = false
+
+ @State var checkDepositResult: CheckDepositResponse? = nil
+ @State private var insufficient = false
+ @State private var feeAmount: Amount? = nil
+ @State private var feeStr: String = EMPTYSTRING
+ @State private var depositStarted = false
+ @State private var exchange: Exchange? = nil // wg. noFees
+
+ public static func navTitle(_ currency: String = EMPTYSTRING,
+ _ condition: Bool = false
+ ) -> String {
+ condition ? String(localized: "NavTitle_Deposit_Currency",
+ defaultValue: "Deposit \(currency)",
+ comment: "NavTitle: Deposit 'currency'")
+ : String(localized: "NavTitle_Deposit",
+ defaultValue: "Deposit",
+ comment: "NavTitle: Deposit")
+ }
+
+ private func feeLabel(_ feeString: String) -> String {
+ feeString.count > 0 ? String(localized: "+ \(feeString) fee")
+ : EMPTYSTRING
+ }
+
+ private func feeIsNotZero() -> Bool? {
+ if let hasNoFees = exchange?.noFees {
+ if hasNoFees {
+ return nil // this exchange never has fees
+ }
+ }
+ return checkDepositResult == nil ? false
+ : true // TODO: !(feeAmount?.isZero ?? false)
+ }
+
+ @MainActor
+ private func computeFeeDeposit(_ amount: Amount) async -> ComputeFeeResult? {
+ if amount.isZero {
+ return ComputeFeeResult.zero()
+ }
+ let insufficient = (try? amount > amountAvailable) ?? true
+ if insufficient {
+ return ComputeFeeResult.insufficient()
+ }
+// private func fee(ppCheck: CheckDepositResponse?) -> Amount? {
+ do {
+// if let ppCheck {
+// // Outgoing: fee = effective - raw
+// feeAmount = try ppCheck.fees.coin + ppCheck.fees.wire + ppCheck.fees.refresh
+// return feeAmount
+// }
+ } catch {
+
+ }
+ return nil
+ }
+
+ private func buttonTitle(_ amount: Amount) -> String {
+ if let balance {
+ let amountWithCurrency = amount.formatted(balance.scopeInfo, isNegative: false, useISO: true)
+ return DepositAmountView.navTitle(amountWithCurrency, true)
+ }
+ return DepositAmountView.navTitle() // should never happen
+ }
+
+ @MainActor
+ private func startDeposit() {
+ if let paytoUri {
+ depositStarted = true // don't run twice
+ Task {
+ symLog.log("Deposit")
+ if let result = try? await model.createDepositGroup(paytoUri, amount: amountToTransfer) {
+ symLog.log(result.transactionId)
+ ViewState2.shared.popToRootView(stack.push())
+ NotificationCenter.default.post(name: .TransactionDone, object: nil, userInfo: nil)
+ } else {
+ depositStarted = false
+ }
+ }
+ }
+ }
+
+ var body: some View {
+#if PRINT_CHANGES
+ let _ = Self._printChanges()
+ let _ = symLog.vlog() // just to get the # to compare it with .onAppear & onDisappear
+#endif
+ if depositStarted {
+ LoadingView(scopeInfo: nil, message: "Depositing...")
+ .navigationBarBackButtonHidden(true)
+ .interactiveDismissDisabled() // can only use "Done" button to dismiss
+ } else { Group {
+ if let balance {
+ let scopeInfo = balance.scopeInfo
+ let availableStr = amountAvailable.formatted(scopeInfo, isNegative: false)
+
+ let currencyInfo = controller.info(for: scopeInfo, controller.currencyTicker)
+// let amountVoiceOver = amountToTransfer.formatted(scopeInfo, isNegative: false)
+ let insufficientLabel = String(localized: "You don't have enough \(currencyInfo.specs.name).")
+// let insufficientLabel2 = String(localized: "but you only have \(available) to deposit.")
+
+ let disabled = insufficient || amountToTransfer.isZero
+
+ Text("Available:\t\(availableStr)")
+ .talerFont(.title3)
+ .padding(.bottom, 2)
+ CurrencyInputView(scope: scopeInfo,
+ amount: $amountToTransfer,
+ amountLastUsed: amountLastUsed,
+ available: nil, // amountAvailable,
+ title: minimalistic ? String(localized: "Amount:")
+ : String(localized: "Amount to deposit:"),
+ shortcutAction: nil)
+ .padding(.horizontal)
+
+ Text(insufficient ? insufficientLabel
+ : feeLabel(feeStr))
+ .talerFont(.body)
+ .foregroundColor(insufficient ? WalletColors().attention
+ : (feeAmount?.isZero ?? true) ? WalletColors().secondary(colorScheme, colorSchemeContrast)
+ : WalletColors().negative)
+ .padding(4)
+ Button(buttonTitle(amountToTransfer)) { startDeposit() }
+ .buttonStyle(TalerButtonStyle(type: .prominent, disabled: disabled || depositStarted))
+ .disabled(disabled || depositStarted)
+ .accessibilityHint(disabled ? String(localized: "enabled when amount is non-zero, but not higher than your available amount") : EMPTYSTRING)
+ } else { // no balance - Yikes
+ Text("No balance. There seems to be a problem with the database...")
+ }
+ }
+ .onAppear {
+ DebugViewC.shared.setViewID(VIEW_DEPOSIT, stack: stack.push())
+ symLog.log("❗️ onAppear")
+ }
+ .onDisappear {
+ symLog.log("❗️ onDisappear")
+ }
+
+// .task(id: amountToTransfer.value) {
+// if let amountAvailable {
+// do {
+// insufficient = try amountToTransfer > amountAvailable
+// } catch {
+// print("Yikes❗️ insufficient failed❗️")
+// insufficient = true
+// }
+//
+// if insufficient {
+// announce("\(amountVoiceOver), \(insufficientLabel2)")
+// feeStr = EMPTYSTRING
+// }
+// }
+// if !insufficient {
+// if amountToTransfer.isZero {
+// feeStr = EMPTYSTRING
+// checkDepositResult = nil
+// } else if let paytoUri {
+// if let ppCheck = try? await model.checkDepositM(paytoUri, amount: amountToTransfer) {
+// if let feeAmount = fee(ppCheck: ppCheck) {
+// feeStr = feeAmount.formatted(scopeInfo, isNegative: false)
+// let feeLabel = feeLabel(feeStr)
+// announce("\(amountVoiceOver), \(feeLabel)")
+// } else {
+// feeStr = EMPTYSTRING
+// announce(amountVoiceOver)
+// }
+// checkDepositResult = ppCheck
+// } else {
+// checkDepositResult = nil
+// }
+// }
+// }
+// }
+ } // else
+ } // body
+}
+// MARK: -
+#if DEBUG
+#endif