taler-ios

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

commit a095fe42f9df8d0fc981c80ec6e0c8264640f777
parent 378ee2c76ff3f6e027b8196e20e8056932de4d70
Author: Marc Stibane <marc@taler.net>
Date:   Sun, 11 Feb 2024 22:29:38 +0100

feeIsNotZero, secondary color if zero

Diffstat:
MTalerWallet1/Model/Model+Exchange.swift | 1+
MTalerWallet1/Views/Balances/BalancesSectionView.swift | 7+++++--
MTalerWallet1/Views/Peer2peer/P2PSubjectV.swift | 13++++++++-----
MTalerWallet1/Views/Peer2peer/RequestPayment.swift | 23++++++++++++++++++++++-
MTalerWallet1/Views/Peer2peer/SendAmount.swift | 51++++++++++++++++++++++++++++++++++++++++++---------
5 files changed, 78 insertions(+), 17 deletions(-)

diff --git a/TalerWallet1/Model/Model+Exchange.swift b/TalerWallet1/Model/Model+Exchange.swift @@ -56,6 +56,7 @@ struct Exchange: Codable, Hashable, Identifiable { // var exchangeStatus: String? var exchangeEntryStatus: ExchangeEntryStatus var exchangeUpdateStatus: ExchangeUpdateStatus + var hasNoFees: Bool? var ageRestrictionOptions: [Int] var lastUpdateErrorInfo: ExchangeError? diff --git a/TalerWallet1/Views/Balances/BalancesSectionView.swift b/TalerWallet1/Views/Balances/BalancesSectionView.swift @@ -208,6 +208,7 @@ fileprivate struct BalancesNavigationLinksView: View { let symLog: SymLogV? let stack: CallStack let balance: Balance + // let sectionCount: Int @Binding var amountToTransfer: Amount // does still have the wrong currency @Binding var summary: String @@ -241,14 +242,16 @@ fileprivate struct BalancesNavigationLinksView: View { SendAmount(stack: stack.push(), amountAvailable: balance.available, amountToTransfer: $amountToTransfer, // with correct currency - summary: $summary) + summary: $summary, + scopeInfo: balance.scopeInfo) }, tag: 1, selection: $buttonSelected ) { EmptyView() }.frame(width: 0).opacity(0).hidden() // SendAmount NavigationLink(destination: LazyView { RequestPayment(stack: stack.push(), amountToTransfer: $amountToTransfer, // with correct currency - summary: $summary) + summary: $summary, + scopeInfo: balance.scopeInfo) }, tag: 2, selection: $buttonSelected ) { EmptyView() }.frame(width: 0).opacity(0).hidden() // RequestPayment diff --git a/TalerWallet1/Views/Peer2peer/P2PSubjectV.swift b/TalerWallet1/Views/Peer2peer/P2PSubjectV.swift @@ -19,6 +19,7 @@ struct P2PSubjectV: View { private let symLog = SymLogV(0) let stack: CallStack let feeLabel: String? + let feeIsNotZero: Bool? // nil = no fees at all, false = no fee for this tx let currencyInfo: CurrencyInfo let amountToSend: Bool @Binding var amountToTransfer: Amount @@ -56,12 +57,14 @@ struct P2PSubjectV: View { let _ = symLog.vlog(amountToTransfer.readableDescription) // just to get the # to compare it with .onAppear & onDisappear #endif ScrollView { VStack (alignment: .leading, spacing: 6) { - let label = feeLabel ?? myFeeLabel - if label.count > 0 { + if let feeIsNotZero { // don't show fee if nil + let label = feeLabel ?? myFeeLabel + if label.count > 0 { Text(label) - .foregroundColor(.red) .frame(maxWidth: .infinity, alignment: .trailing) + .foregroundColor(feeIsNotZero ? .red : .secondary) .talerFont(.body) + } } if !minimalistic { Text("Enter subject:") // Purpose @@ -93,7 +96,7 @@ struct P2PSubjectV: View { Text(verbatim: "\(summary.count)/100") // maximum 100 characters .frame(maxWidth: .infinity, alignment: .trailing) .talerFont(.body) - .accessibilityValue("\(summary.count) characters of 100") + .accessibilityValue("\(summary.count) characters of 100") // TODO: compute max Expiration day from peerPushCheck to disable 30 (and even 7) SelectDays(selected: $expireDays, maxExpiration: THIRTYDAYS) @@ -131,7 +134,7 @@ struct P2PSubjectV: View { let ppCheck = try await model.checkPeerPushDebitM(amountToTransfer) if let feeAmount = p2pFee(ppCheck: ppCheck) { let feeStr = feeAmount.string(currencyInfo) - myFeeLabel = String(localized: "+ \(feeStr) send fee") + myFeeLabel = String(localized: "+ \(feeStr) fee") } else { myFeeLabel = EMPTYSTRING } } catch { // TODO: error symLog.log(error.localizedDescription) diff --git a/TalerWallet1/Views/Peer2peer/RequestPayment.swift b/TalerWallet1/Views/Peer2peer/RequestPayment.swift @@ -13,6 +13,7 @@ struct RequestPayment: View { @Binding var amountToTransfer: Amount @Binding var summary: String + let scopeInfo: ScopeInfo @EnvironmentObject private var controller: Controller @EnvironmentObject private var model: WalletModel @@ -22,11 +23,20 @@ struct RequestPayment: View { @State private var expireDays: UInt = 0 @State private var buttonSelected = false @State private var amountShortcut = Amount.zero(currency: EMPTYSTRING) // Update currency when used + @State private var exchange: Exchange? = nil // wg. hasNoFees private func shortcutAction(_ shortcut: Amount) { amountShortcut = shortcut buttonSelected = true } + private func feeIsNotZero() -> Bool? { + if let hasNoFees = exchange?.hasNoFees { + if hasNoFees { + return nil // this exchange never has fees + } + } + return peerPullCheck != nil ? true : false + } var body: some View { #if PRINT_CHANGES @@ -44,6 +54,7 @@ struct RequestPayment: View { let inputDestination = LazyView { P2PSubjectV(stack: stack.push(), feeLabel: someCoins.feeLabel(currencyInfo), + feeIsNotZero: feeIsNotZero(), currencyInfo: currencyInfo, amountToSend: false, amountToTransfer: $amountToTransfer, @@ -53,6 +64,7 @@ struct RequestPayment: View { let shortcutDestination = LazyView { P2PSubjectV(stack: stack.push(), feeLabel: nil, + feeIsNotZero: feeIsNotZero(), currencyInfo: currencyInfo, amountToSend: false, amountToTransfer: $amountShortcut, @@ -64,7 +76,7 @@ struct RequestPayment: View { CurrencyInputView(amount: $amountToTransfer, available: nil, title: minimalistic ? String(localized: "Amount:") - : String(localized: "Amount to request:"), + : String(localized: "Amount to request:"), shortcutAction: shortcutAction) .padding(.top) QuiteSomeCoins(someCoins: someCoins, @@ -91,6 +103,15 @@ struct RequestPayment: View { symLog.log("❗️ \(navTitle) onDisappear") } .task(id: amountToTransfer.value) { + if exchange == nil { + if let url = scopeInfo.url { + if let exc = await model.getExchangeByUrl(url: url) { + exchange = exc + } else { + // TODO: Error "Can't get Exchange / Payment Service Provider Info" + } + } + } if amountToTransfer.isZero { // fee = EMPTYSTRING } else { diff --git a/TalerWallet1/Views/Peer2peer/SendAmount.swift b/TalerWallet1/Views/Peer2peer/SendAmount.swift @@ -14,6 +14,7 @@ struct SendAmount: View { let amountAvailable: Amount // TODO: GetMaxPeerPushAmount @Binding var amountToTransfer: Amount @Binding var summary: String + let scopeInfo: ScopeInfo @EnvironmentObject private var controller: Controller @EnvironmentObject private var model: WalletModel @@ -22,27 +23,39 @@ struct SendAmount: View { @State var peerPushCheck: CheckPeerPushDebitResponse? = nil @State private var expireDays = SEVENDAYS @State private var insufficient = false + @State private var feeAmount: Amount? = nil @State private var feeStr: String = EMPTYSTRING @State private var buttonSelected = false @State private var amountShortcut = Amount.zero(currency: EMPTYSTRING) // Update currency when used + @State private var exchange: Exchange? = nil // wg. hasNoFees private func fee(ppCheck: CheckPeerPushDebitResponse?) -> Amount? { do { if let ppCheck { // Outgoing: fee = effective - raw - let fee = try ppCheck.amountEffective - ppCheck.amountRaw - return fee + feeAmount = try ppCheck.amountEffective - ppCheck.amountRaw + return feeAmount } } catch {} - return nil + feeAmount = nil + return feeAmount } - var feeLabel: String { feeStr.count > 0 ? String(localized: "+ \(feeStr) send fee") : EMPTYSTRING } + var feeLabel: String { feeStr.count > 0 ? String(localized: "+ \(feeStr) fee") : EMPTYSTRING } private func shortcutAction(_ shortcut: Amount) { amountShortcut = shortcut buttonSelected = true } + private func feeIsNotZero() -> Bool? { + if let hasNoFees = exchange?.hasNoFees { + if hasNoFees { + return nil // this exchange never has fees + } + } + return peerPushCheck != nil ? (!(feeAmount?.isZero ?? false)) + : false + } var body: some View { #if PRINT_CHANGES @@ -65,6 +78,7 @@ struct SendAmount: View { let inputDestination = LazyView { P2PSubjectV(stack: stack.push(), feeLabel: feeLabel, + feeIsNotZero: feeIsNotZero(), currencyInfo: currencyInfo, amountToSend: true, amountToTransfer: $amountToTransfer, @@ -74,6 +88,7 @@ struct SendAmount: View { let shortcutDestination = LazyView { P2PSubjectV(stack: stack.push(), feeLabel: nil, + feeIsNotZero: feeIsNotZero(), currencyInfo: currencyInfo, amountToSend: true, amountToTransfer: $amountShortcut, @@ -88,12 +103,13 @@ struct SendAmount: View { CurrencyInputView(amount: $amountToTransfer, available: amountAvailable, title: minimalistic ? String(localized: "Amount:") - : String(localized: "Amount to send:"), + : String(localized: "Amount to send:"), shortcutAction: shortcutAction) Text(insufficient ? insufficientLabel : feeLabel) .talerFont(.body) - .foregroundColor(.red) + .foregroundColor(insufficient ? .red + : (feeAmount?.isZero ?? true) ? .secondary : .red) .padding(4) NavigationLink(destination: inputDestination) { Text("Next") } .buttonStyle(TalerButtonStyle(type: .prominent)) @@ -114,6 +130,15 @@ struct SendAmount: View { symLog.log("❗️ \(navTitle) onDisappear") } .task(id: amountToTransfer.value) { + if exchange == nil { + if let url = scopeInfo.url { + if let exc = await model.getExchangeByUrl(url: url) { + exchange = exc + } else { + // TODO: Error "Can't get Exchange / Payment Service Provider Info" + } + } + } do { insufficient = try amountToTransfer > amountAvailable } catch { @@ -146,15 +171,23 @@ struct SendAmount: View { // MARK: - #if DEBUG fileprivate struct Preview_Content: View { - @State private var amountToPreview = Amount(currency: TESTCURRENCY, cent: 510) + @State private var amountToPreview = Amount(currency: LONGCURRENCY, cent: 510) @State private var summary: String = "" var body: some View { - let amount = Amount(currency: TESTCURRENCY, cent: 1000) + let amount = Amount(currency: LONGCURRENCY, cent: 1000) + let scopeInfo = ScopeInfo(type: .exchange, currency: LONGCURRENCY) + let exchange2 = Exchange(exchangeBaseUrl: ARS_EXP_EXCHANGE, + scopeInfo: scopeInfo, + paytoUris: [], + tosStatus: .proposed, + exchangeEntryStatus: .ephemeral, + exchangeUpdateStatus: .ready, + ageRestrictionOptions: []) SendAmount(stack: CallStack("Preview"), amountAvailable: amount, amountToTransfer: $amountToPreview, - summary: $summary) + summary: $summary, scopeInfo: scopeInfo) } }