commit 12c22a6d530641e19efb67ea719fd9b49170b6d5
parent 6e6f68033a8e428798d6f9e7e46354166862e3e9
Author: Marc Stibane <marc@taler.net>
Date: Sat, 20 Jul 2024 19:07:29 +0200
ThreeAmountsSection
Diffstat:
7 files changed, 264 insertions(+), 256 deletions(-)
diff --git a/TalerWallet.xcodeproj/project.pbxproj b/TalerWallet.xcodeproj/project.pbxproj
@@ -101,7 +101,7 @@
4E3EAE642A990778009F1BE8 /* LaunchAnimationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EB095432989CBFE0043A8A1 /* LaunchAnimationView.swift */; };
4E3EAE682A990778009F1BE8 /* WalletModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EB095112989CBB00043A8A1 /* WalletModel.swift */; };
4E3EAE692A990778009F1BE8 /* URLSheet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EB095332989CBFE0043A8A1 /* URLSheet.swift */; };
- 4E3EAE6A2A990778009F1BE8 /* ThreeAmountsV.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4ED2F94A2A278F5100453B40 /* ThreeAmountsV.swift */; };
+ 4E3EAE6A2A990778009F1BE8 /* ThreeAmountsSection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4ED2F94A2A278F5100453B40 /* ThreeAmountsSection.swift */; };
4E3EAE6B2A990778009F1BE8 /* Model+Withdraw.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EB0953D2989CBFE0043A8A1 /* Model+Withdraw.swift */; };
4E3EAE6C2A990778009F1BE8 /* ExchangeSectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EC90C772A1B528B0071DC58 /* ExchangeSectionView.swift */; };
4E3EAE6D2A990778009F1BE8 /* P2PSubjectV.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E7940DD29FC307C00A9AEA1 /* P2PSubjectV.swift */; };
@@ -253,7 +253,7 @@
4EC90C782A1B528B0071DC58 /* ExchangeSectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EC90C772A1B528B0071DC58 /* ExchangeSectionView.swift */; };
4ECB62802A0BA6DF004ABBB7 /* Model+P2P.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4ECB627F2A0BA6DF004ABBB7 /* Model+P2P.swift */; };
4ECB62822A0BB01D004ABBB7 /* SelectDays.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4ECB62812A0BB01D004ABBB7 /* SelectDays.swift */; };
- 4ED2F94B2A278F5100453B40 /* ThreeAmountsV.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4ED2F94A2A278F5100453B40 /* ThreeAmountsV.swift */; };
+ 4ED2F94B2A278F5100453B40 /* ThreeAmountsSection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4ED2F94A2A278F5100453B40 /* ThreeAmountsSection.swift */; };
4ED80E882B8F5FB8008BD576 /* CStringArray.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4ED80E872B8F5FB8008BD576 /* CStringArray.swift */; };
4ED80E892B8F5FB8008BD576 /* CStringArray.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4ED80E872B8F5FB8008BD576 /* CStringArray.swift */; };
4ED80E8B2B8F60E7008BD576 /* Atomic.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4ED80E8A2B8F60E7008BD576 /* Atomic.swift */; };
@@ -465,7 +465,7 @@
4EC90C772A1B528B0071DC58 /* ExchangeSectionView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExchangeSectionView.swift; sourceTree = "<group>"; };
4ECB627F2A0BA6DF004ABBB7 /* Model+P2P.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Model+P2P.swift"; sourceTree = "<group>"; };
4ECB62812A0BB01D004ABBB7 /* SelectDays.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SelectDays.swift; sourceTree = "<group>"; };
- 4ED2F94A2A278F5100453B40 /* ThreeAmountsV.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ThreeAmountsV.swift; sourceTree = "<group>"; };
+ 4ED2F94A2A278F5100453B40 /* ThreeAmountsSection.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ThreeAmountsSection.swift; sourceTree = "<group>"; };
4ED80E872B8F5FB8008BD576 /* CStringArray.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CStringArray.swift; sourceTree = "<group>"; };
4ED80E8A2B8F60E7008BD576 /* Atomic.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Atomic.swift; sourceTree = "<group>"; };
4ED80E8D2B8F6212008BD576 /* QuickDataTask.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QuickDataTask.swift; sourceTree = "<group>"; };
@@ -785,7 +785,7 @@
4E6EF56D2B669C7000AF252A /* TransactionDetailV.swift */,
4E87C8722A31CB7F001C6406 /* TransactionsEmptyView.swift */,
4E6EDD842A3615BE0031D520 /* ManualDetailsV.swift */,
- 4ED2F94A2A278F5100453B40 /* ThreeAmountsV.swift */,
+ 4ED2F94A2A278F5100453B40 /* ThreeAmountsSection.swift */,
);
path = Transactions;
sourceTree = "<group>";
@@ -1262,7 +1262,7 @@
E37AA62A2AF197E5003850CF /* Model+Refund.swift in Sources */,
4E3EAE682A990778009F1BE8 /* WalletModel.swift in Sources */,
4E3EAE692A990778009F1BE8 /* URLSheet.swift in Sources */,
- 4E3EAE6A2A990778009F1BE8 /* ThreeAmountsV.swift in Sources */,
+ 4E3EAE6A2A990778009F1BE8 /* ThreeAmountsSection.swift in Sources */,
4E3EAE6B2A990778009F1BE8 /* Model+Withdraw.swift in Sources */,
4ED80E882B8F5FB8008BD576 /* CStringArray.swift in Sources */,
4E3EAE6C2A990778009F1BE8 /* ExchangeSectionView.swift in Sources */,
@@ -1389,7 +1389,7 @@
E37AA62B2AF197E5003850CF /* Model+Refund.swift in Sources */,
4EB095162989CBB00043A8A1 /* WalletModel.swift in Sources */,
4EB0955A2989CBFE0043A8A1 /* URLSheet.swift in Sources */,
- 4ED2F94B2A278F5100453B40 /* ThreeAmountsV.swift in Sources */,
+ 4ED2F94B2A278F5100453B40 /* ThreeAmountsSection.swift in Sources */,
4EB095622989CBFE0043A8A1 /* Model+Withdraw.swift in Sources */,
4ED80E892B8F5FB8008BD576 /* CStringArray.swift in Sources */,
4EC90C782A1B528B0071DC58 /* ExchangeSectionView.swift in Sources */,
diff --git a/TalerWallet1/Views/Sheets/P2P_Sheets/P2pPayURIView.swift b/TalerWallet1/Views/Sheets/P2P_Sheets/P2pPayURIView.swift
@@ -31,19 +31,19 @@ struct P2pPayURIView: View {
let effective = peerPullDebitResponse.amountEffective
let currency = raw.currencyStr
let fee = try! Amount.diff(raw, effective)
- ThreeAmountsV(stack: stack.push(),
- topTitle: String(localized: "Amount to pay:"),
- topAbbrev: String(localized: "Pay:", comment: "mini"),
- topAmount: raw, fee: fee,
- bottomTitle: String(localized: "Amount to be spent:"),
- bottomAbbrev: String(localized: "Effective:", comment: "mini"),
- bottomAmount: effective,
- large: false, pending: false, incoming: false,
- baseURL: nil,
- noFees: nil, // TODO: check baseURL for fees
- txStateLcl: nil,
- summary: peerPullDebitResponse.contractTerms.summary,
- merchant: nil)
+ ThreeAmountsSection(stack: stack.push(),
+ topTitle: String(localized: "Amount to pay:"),
+ topAbbrev: String(localized: "Pay:", comment: "mini"),
+ topAmount: raw, fee: fee,
+ bottomTitle: String(localized: "Amount to be spent:"),
+ bottomAbbrev: String(localized: "Effective:", comment: "mini"),
+ bottomAmount: effective,
+ large: false, pending: false, incoming: false,
+ baseURL: nil,
+ noFees: nil, // TODO: check baseURL for fees
+ txStateLcl: nil,
+ summary: peerPullDebitResponse.contractTerms.summary,
+ merchant: nil)
let expiration = peerPullDebitResponse.contractTerms.purse_expiration
let (dateString, date) = TalerDater.dateString(from: expiration)
let a11yDate = TalerDater.accessibilityDate(date) ?? dateString
diff --git a/TalerWallet1/Views/Sheets/P2P_Sheets/P2pReceiveURIView.swift b/TalerWallet1/Views/Sheets/P2P_Sheets/P2pReceiveURIView.swift
@@ -41,19 +41,19 @@ struct P2pReceiveURIView: View {
let effective = peerPushCreditResponse.amountEffective
let currency = raw.currencyStr
let fee = try! Amount.diff(raw, effective)
- ThreeAmountsV(stack: stack.push(),
- topTitle: String(localized: "Gross Amount to receive:"),
- topAbbrev: String(localized: "Receive gross:", comment: "mini"),
- topAmount: raw, fee: fee,
- bottomTitle: String(localized: "Net Amount to receive:"),
- bottomAbbrev: String(localized: "Receive net:", comment: "mini"),
- bottomAmount: effective,
- large: false, pending: false, incoming: true,
- baseURL: nil,
- noFees: nil, // TODO: check baseURL for fees
- txStateLcl: nil,
- summary: peerPushCreditResponse.contractTerms.summary,
- merchant: nil)
+ ThreeAmountsSection(stack: stack.push(),
+ topTitle: String(localized: "Gross Amount to receive:"),
+ topAbbrev: String(localized: "Receive gross:", comment: "mini"),
+ topAmount: raw, fee: fee,
+ bottomTitle: String(localized: "Net Amount to receive:"),
+ bottomAbbrev: String(localized: "Receive net:", comment: "mini"),
+ bottomAmount: effective,
+ large: false, pending: false, incoming: true,
+ baseURL: nil,
+ noFees: nil, // TODO: check baseURL for fees
+ txStateLcl: nil,
+ summary: peerPushCreditResponse.contractTerms.summary,
+ merchant: nil)
let expiration = peerPushCreditResponse.contractTerms.purse_expiration
let (dateString, date) = TalerDater.dateString(from: expiration)
let a11yDate = TalerDater.accessibilityDate(date) ?? dateString
diff --git a/TalerWallet1/Views/Sheets/Payment/PaymentView.swift b/TalerWallet1/Views/Sheets/Payment/PaymentView.swift
@@ -102,36 +102,40 @@ struct PaymentView: View {
if let effective {
// TODO: already paid
let fee = try! Amount.diff(raw, effective) // TODO: different currencies
- ThreeAmountsV(stack: stack.push(),
- topTitle: topTitle,
- topAbbrev: topAbbrev,
- topAmount: raw, fee: fee,
- bottomTitle: String(localized: "Amount to spend:"),
- bottomAbbrev: String(localized: "Effective:", comment: "mini"),
- bottomAmount: effective,
- large: false, pending: false, incoming: false,
- baseURL: baseURL,
- noFees: nil, // TODO: check baseURL for fees
- txStateLcl: nil,
- summary: terms.summary,
- merchant: terms.merchant.name)
+ ThreeAmountsSection(stack: stack.push(),
+ topTitle: topTitle,
+ topAbbrev: topAbbrev,
+ topAmount: raw, fee: fee,
+ bottomTitle: String(localized: "Amount to spend:"),
+ bottomAbbrev: String(localized: "Effective:", comment: "mini"),
+ bottomAmount: effective,
+ large: false,
+ pending: false,
+ incoming: false,
+ baseURL: baseURL,
+ noFees: nil, // TODO: check baseURL for fees
+ txStateLcl: nil,
+ summary: terms.summary,
+ merchant: terms.merchant.name)
// TODO: payment: popup with all possible exchanges, check fees
} else if let balanceDetails = preparePayResult.balanceDetails { // Insufficient
Text("You don't have enough \(currency).")
.talerFont(.headline)
- ThreeAmountsV(stack: stack.push(),
- topTitle: topTitle,
- topAbbrev: topAbbrev,
- topAmount: raw, fee: nil,
- bottomTitle: String(localized: "Amount available:"),
- bottomAbbrev: String(localized: "Available:", comment: "mini"),
- bottomAmount: balanceDetails.balanceAvailable,
- large: false, pending: false, incoming: false,
- baseURL: baseURL,
- noFees: nil, // TODO: check baseURL for fees
- txStateLcl: nil,
- summary: terms.summary,
- merchant: terms.merchant.name)
+ ThreeAmountsSection(stack: stack.push(),
+ topTitle: topTitle,
+ topAbbrev: topAbbrev,
+ topAmount: raw, fee: nil,
+ bottomTitle: String(localized: "Amount available:"),
+ bottomAbbrev: String(localized: "Available:", comment: "mini"),
+ bottomAmount: balanceDetails.balanceAvailable,
+ large: false,
+ pending: false,
+ incoming: false,
+ baseURL: baseURL,
+ noFees: nil, // TODO: check baseURL for fees
+ txStateLcl: nil,
+ summary: terms.summary,
+ merchant: terms.merchant.name)
} else {
// TODO: Error - neither effective nor balanceDetails
Text("Error")
diff --git a/TalerWallet1/Views/Sheets/WithdrawBankIntegrated/WithdrawAcceptView.swift b/TalerWallet1/Views/Sheets/WithdrawBankIntegrated/WithdrawAcceptView.swift
@@ -54,19 +54,19 @@ struct WithdrawAcceptView: View {
let outColor = WalletColors().transactionColor(false)
let inColor = WalletColors().transactionColor(true)
- ThreeAmountsV(stack: stack.push(),
- topTitle: String(localized: "Chosen amount to withdraw:"),
- topAbbrev: String(localized: "Chosen:", comment: "mini"),
- topAmount: raw, fee: fee,
- bottomTitle: String(localized: "Amount to be withdrawn:"),
- bottomAbbrev: String(localized: "Effective:", comment: "mini"),
- bottomAmount: effective,
- large: false, pending: false, incoming: true,
- baseURL: exchange.exchangeBaseUrl,
- noFees: exchange.noFees,
- txStateLcl: nil, // common.txState.major.localizedState
- summary: nil,
- merchant: nil)
+ ThreeAmountsSection(stack: stack.push(),
+ topTitle: String(localized: "Chosen amount to withdraw:"),
+ topAbbrev: String(localized: "Chosen:", comment: "mini"),
+ topAmount: raw, fee: fee,
+ bottomTitle: String(localized: "Amount to be withdrawn:"),
+ bottomAbbrev: String(localized: "Effective:", comment: "mini"),
+ bottomAmount: effective,
+ large: false, pending: false, incoming: true,
+ baseURL: exchange.exchangeBaseUrl,
+ noFees: exchange.noFees,
+ txStateLcl: nil, // common.txState.major.localizedState
+ summary: nil,
+ merchant: nil)
let coinData = CoinData(details: withdrawalAmountDetails)
QuiteSomeCoins(currencyInfo: currencyInfo,
currency: currency,
diff --git a/TalerWallet1/Views/Transactions/ThreeAmountsSection.swift b/TalerWallet1/Views/Transactions/ThreeAmountsSection.swift
@@ -0,0 +1,189 @@
+/*
+ * This file is part of GNU Taler, ©2022-24 Taler Systems S.A.
+ * See LICENSE.md
+ */
+/**
+ * @author Marc Stibane
+ */
+import SwiftUI
+import taler_swift
+
+struct ThreeAmountsSheet: View {
+ let stack: CallStack
+ var common: TransactionCommon
+ var topAbbrev: String
+ var topTitle: String
+ var bottomTitle: String?
+ var bottomAbbrev: String?
+ let baseURL: String?
+ let noFees: Bool? // true if exchange charges no fees at all
+ let large: Bool // set to false for QR or IBAN
+ let summary: String?
+ let merchant: String?
+
+#if DEBUG
+ @AppStorage("developerMode") var developerMode: Bool = true
+#else
+ @AppStorage("developerMode") var developerMode: Bool = false
+#endif
+
+ var body: some View {
+ let raw = common.amountRaw
+ let effective = common.amountEffective
+ let fee = common.fee()
+ let incoming = common.incoming()
+ let pending = common.isPending
+ let isDone = common.isDone
+ let incomplete = !(isDone || pending)
+
+ let defaultBottomTitle = incoming ? (pending ? String(localized: "Pending amount to obtain:")
+ : String(localized: "Obtained amount:") )
+ : (pending ? String(localized: "Amount to pay:")
+ : String(localized: "Paid amount:") )
+ let defaultBottomAbbrev = incoming ? (pending ? String(localized: "Pending:", comment: "mini")
+ : String(localized: "Obtained:", comment: "mini") )
+ : (pending ? String(localized: "Pay:", comment: "mini")
+ : String(localized: "Paid:", comment: "mini") )
+ let majorLcl = common.txState.major.localizedState
+ let txStateLcl = developerMode && pending ? (common.txState.minor?.localizedState ?? majorLcl)
+ : majorLcl
+ ThreeAmountsSection(stack: stack.push(),
+ topTitle: topTitle,
+ topAbbrev: topAbbrev,
+ topAmount: raw,
+ fee: fee,
+ bottomTitle: bottomTitle ?? defaultBottomTitle,
+ bottomAbbrev: bottomAbbrev ?? defaultBottomAbbrev,
+ bottomAmount: incomplete ? nil : effective,
+ large: large,
+ pending: pending,
+ incoming: incoming,
+ baseURL: baseURL,
+ noFees: noFees,
+ txStateLcl: txStateLcl,
+ summary: summary,
+ merchant: merchant)
+ }
+}
+// MARK: -
+struct ThreeAmountsSection: View {
+ let stack: CallStack
+ var topTitle: String
+ var topAbbrev: String
+ var topAmount: Amount
+ var fee: Amount? // nil = don't show fee line, zero = no fee for this tx
+ var bottomTitle: String
+ var bottomAbbrev: String
+ var bottomAmount: Amount? // nil = incomplete (aborted, timed out)
+ let large: Bool
+ let pending: Bool
+ let incoming: Bool
+ let baseURL: String?
+ let noFees: Bool? // true if exchange charges no fees at all
+ let txStateLcl: String? // localizedState
+ let summary: String?
+ let merchant: String?
+
+ @Environment(\.colorScheme) private var colorScheme
+ @Environment(\.colorSchemeContrast) private var colorSchemeContrast
+ @AppStorage("minimalistic") var minimalistic: Bool = false
+
+ var body: some View {
+ let labelColor = WalletColors().labelColor
+ let foreColor = pending ? WalletColors().pendingColor(incoming)
+ : WalletColors().transactionColor(incoming)
+ let hasNoFees = noFees ?? false
+ Section {
+ if let summary {
+ Text(summary)
+ .talerFont(.title3)
+ .lineLimit(4)
+ .padding(.bottom)
+ }
+ if let merchant {
+ Text(merchant)
+ .talerFont(.title3)
+ .lineLimit(4)
+ .padding(.bottom)
+ }
+ AmountRowV(stack: stack.push(),
+ title: minimalistic ? topAbbrev : topTitle,
+ amount: topAmount,
+ isNegative: !incoming,
+ color: labelColor,
+ large: false)
+ .padding(.bottom, 4)
+ if hasNoFees == false {
+ if let fee {
+ let title = minimalistic ? String(localized: "Exchange fee (short):", defaultValue: "Fee:", comment: "short version")
+ : String(localized: "Exchange fee (long):", defaultValue: "Fee:", comment: "long version")
+ AmountRowV(stack: stack.push(),
+ title: title,
+ amount: fee,
+ isNegative: !incoming,
+ color: labelColor,
+ large: false)
+ .padding(.bottom, 4)
+ }
+ if let bottomAmount {
+ AmountRowV(stack: stack.push(),
+ title: minimalistic ? bottomAbbrev : bottomTitle,
+ amount: bottomAmount,
+ isNegative: !incoming,
+ color: foreColor,
+ large: large)
+ }
+ }
+ if let baseURL {
+ VStack(alignment: .leading) {
+ // TODO: "Issued by" for withdrawals
+ Text(minimalistic ? "Payment provider:" : "Using payment service provider:")
+ .multilineTextAlignment(.leading)
+ .talerFont(.body)
+ Text(baseURL.trimURL())
+ .frame(maxWidth: .infinity, alignment: .trailing)
+ .multilineTextAlignment(.center)
+ .talerFont(large ? .title3 : .body)
+// .fontWeight(large ? .medium : .regular) // @available(iOS 16.0, *)
+ .foregroundColor(labelColor)
+ }
+ .padding(.top, 4)
+ .frame(maxWidth: .infinity, alignment: .leading)
+ .listRowSeparator(.hidden)
+ .accessibilityElement(children: .combine)
+ }
+ } header: {
+ if !minimalistic {
+ Text("Summary")
+ .talerFont(.title3)
+ .foregroundColor(WalletColors().secondary(colorScheme, colorSchemeContrast))
+ }
+ }
+ }
+}
+// MARK: -
+struct ThreeAmounts_Previews: PreviewProvider {
+ static var previews: some View {
+ let common = TransactionCommon(type: .withdrawal,
+ txState: TransactionState(major: .done),
+ amountEffective: Amount(currency: LONGCURRENCY, cent: 10),
+ amountRaw: Amount(currency: LONGCURRENCY, cent: 20),
+ transactionId: "someTxID",
+ timestamp: Timestamp(from: 1_666_666_000_000),
+ txActions: [])
+ Group {
+ List {
+ ThreeAmountsSheet(stack: CallStack("Preview"),
+ common: common, topAbbrev: "Withdrawal",
+ topTitle: "Withdrawal", baseURL: DEMOEXCHANGE, noFees: false,
+ large: 1==0, summary: nil, merchant: nil)
+ .safeAreaInset(edge: .bottom) {
+ Button(String(localized: "Accept"), action: {})
+ .buttonStyle(TalerButtonStyle(type: .prominent))
+ .padding(.horizontal)
+ .disabled(true)
+ }
+ }
+ }
+ }
+}
diff --git a/TalerWallet1/Views/Transactions/ThreeAmountsV.swift b/TalerWallet1/Views/Transactions/ThreeAmountsV.swift
@@ -1,185 +0,0 @@
-/*
- * This file is part of GNU Taler, ©2022-24 Taler Systems S.A.
- * See LICENSE.md
- */
-/**
- * @author Marc Stibane
- */
-import SwiftUI
-import taler_swift
-
-struct ThreeAmountsSheet: View {
- let stack: CallStack
- var common: TransactionCommon
- var topAbbrev: String
- var topTitle: String
- var bottomTitle: String?
- var bottomAbbrev: String?
- let baseURL: String?
- let noFees: Bool? // true if exchange charges no fees at all
- let large: Bool // set to false for QR or IBAN
- let summary: String?
- let merchant: String?
-
-#if DEBUG
- @AppStorage("developerMode") var developerMode: Bool = true
-#else
- @AppStorage("developerMode") var developerMode: Bool = false
-#endif
-
- var body: some View {
- let raw = common.amountRaw
- let effective = common.amountEffective
- let fee = common.fee()
- let incoming = common.incoming()
- let pending = common.isPending
- let isDone = common.isDone
- let incomplete = !(isDone || pending)
-
- let defaultBottomTitle = incoming ? (pending ? String(localized: "Pending amount to obtain:")
- : String(localized: "Obtained amount:") )
- : (pending ? String(localized: "Amount to pay:")
- : String(localized: "Paid amount:") )
- let defaultBottomAbbrev = incoming ? (pending ? String(localized: "Pending:", comment: "mini")
- : String(localized: "Obtained:", comment: "mini") )
- : (pending ? String(localized: "Pay:", comment: "mini")
- : String(localized: "Paid:", comment: "mini") )
- let majorLcl = common.txState.major.localizedState
- let txStateLcl = developerMode && pending ? (common.txState.minor?.localizedState ?? majorLcl)
- : majorLcl
- ThreeAmountsV(stack: stack.push(),
- topTitle: topTitle, topAbbrev: topAbbrev,
- topAmount: raw, fee: fee,
- bottomTitle: bottomTitle ?? defaultBottomTitle,
- bottomAbbrev: bottomAbbrev ?? defaultBottomAbbrev,
- bottomAmount: incomplete ? nil : effective,
- large: large, pending: pending, incoming: incoming,
- baseURL: baseURL,
- noFees: noFees,
- txStateLcl: txStateLcl,
- summary: summary,
- merchant: merchant)
- }
-}
-// MARK: -
-struct ThreeAmountsV: View {
- let stack: CallStack
- var topTitle: String
- var topAbbrev: String
- var topAmount: Amount
- var fee: Amount? // nil = don't show fee line, zero = no fee for this tx
- var bottomTitle: String
- var bottomAbbrev: String
- var bottomAmount: Amount? // nil = incomplete (aborted, timed out)
- let large: Bool
- let pending: Bool
- let incoming: Bool
- let baseURL: String?
- let noFees: Bool? // true if exchange charges no fees at all
- let txStateLcl: String? // localizedState
- let summary: String?
- let merchant: String?
-
- @Environment(\.colorScheme) private var colorScheme
- @Environment(\.colorSchemeContrast) private var colorSchemeContrast
- @AppStorage("minimalistic") var minimalistic: Bool = false
-
- var body: some View {
- let labelColor = WalletColors().labelColor
- let foreColor = pending ? WalletColors().pendingColor(incoming)
- : WalletColors().transactionColor(incoming)
- let hasNoFees = noFees ?? false
- Section {
- if let summary {
- Text(summary)
- .talerFont(.title3)
- .lineLimit(4)
- .padding(.bottom)
- }
- if let merchant {
- Text(merchant)
- .talerFont(.title3)
- .lineLimit(4)
- .padding(.bottom)
- }
- AmountRowV(stack: stack.push(),
- title: minimalistic ? topAbbrev : topTitle,
- amount: topAmount,
- isNegative: !incoming,
- color: labelColor,
- large: false)
- .padding(.bottom, 4)
- if hasNoFees == false {
- if let fee {
- let title = minimalistic ? String(localized: "Exchange fee (short):", defaultValue: "Fee:", comment: "short version")
- : String(localized: "Exchange fee (long):", defaultValue: "Fee:", comment: "long version")
- AmountRowV(stack: stack.push(),
- title: title,
- amount: fee,
- isNegative: !incoming,
- color: labelColor,
- large: false)
- .padding(.bottom, 4)
- }
- if let bottomAmount {
- AmountRowV(stack: stack.push(),
- title: minimalistic ? bottomAbbrev : bottomTitle,
- amount: bottomAmount,
- isNegative: !incoming,
- color: foreColor,
- large: large)
- }
- }
- if let baseURL {
- VStack(alignment: .leading) {
- // TODO: "Issued by" for withdrawals
- Text(minimalistic ? "Payment provider:" : "Using payment service provider:")
- .multilineTextAlignment(.leading)
- .talerFont(.body)
- Text(baseURL.trimURL())
- .frame(maxWidth: .infinity, alignment: .trailing)
- .multilineTextAlignment(.center)
- .talerFont(large ? .title3 : .body)
-// .fontWeight(large ? .medium : .regular) // @available(iOS 16.0, *)
- .foregroundColor(labelColor)
- }
- .padding(.top, 4)
- .frame(maxWidth: .infinity, alignment: .leading)
- .listRowSeparator(.hidden)
- .accessibilityElement(children: .combine)
- }
- } header: {
- if !minimalistic {
- Text("Summary")
- .talerFont(.title3)
- .foregroundColor(WalletColors().secondary(colorScheme, colorSchemeContrast))
- }
- }
- }
-}
-// MARK: -
-struct ThreeAmounts_Previews: PreviewProvider {
- static var previews: some View {
- let common = TransactionCommon(type: .withdrawal,
- txState: TransactionState(major: .done),
- amountEffective: Amount(currency: LONGCURRENCY, cent: 10),
- amountRaw: Amount(currency: LONGCURRENCY, cent: 20),
- transactionId: "someTxID",
- timestamp: Timestamp(from: 1_666_666_000_000),
- txActions: [])
- Group {
- List {
- ThreeAmountsSheet(stack: CallStack("Preview"),
- common: common, topAbbrev: "Withdrawal",
- topTitle: "Withdrawal", baseURL: DEMOEXCHANGE, noFees: false,
- large: 1==0, summary: nil, merchant: nil)
- .safeAreaInset(edge: .bottom) {
- Button(String(localized: "Accept"), action: {})
- .buttonStyle(TalerButtonStyle(type: .prominent))
- .padding(.horizontal)
- .disabled(true)
- }
- }
- }
- }
-}