commit f6a838560b5d7fc6f80b74b33c4baf099c30e331
parent dbf44d68d7673acfc9f7d9a688c0bc2871614012
Author: Marc Stibane <marc@taler.net>
Date: Tue, 8 Aug 2023 11:54:49 +0200
PaymentView
Diffstat:
8 files changed, 192 insertions(+), 267 deletions(-)
diff --git a/TalerWallet.xcodeproj/project.pbxproj b/TalerWallet.xcodeproj/project.pbxproj
@@ -68,7 +68,7 @@
4EB095502989CBFE0043A8A1 /* SettingsItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EB095262989CBFE0043A8A1 /* SettingsItem.swift */; };
4EB095522989CBFE0043A8A1 /* ExchangeListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EB095292989CBFE0043A8A1 /* ExchangeListView.swift */; };
4EB095542989CBFE0043A8A1 /* Model+Payment.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EB0952C2989CBFE0043A8A1 /* Model+Payment.swift */; };
- 4EB095552989CBFE0043A8A1 /* PaymentURIView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EB0952D2989CBFE0043A8A1 /* PaymentURIView.swift */; };
+ 4EB095552989CBFE0043A8A1 /* PaymentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EB0952D2989CBFE0043A8A1 /* PaymentView.swift */; };
4EB095562989CBFE0043A8A1 /* TransactionsListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EB0952F2989CBFE0043A8A1 /* TransactionsListView.swift */; };
4EB095572989CBFE0043A8A1 /* TransactionRowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EB095302989CBFE0043A8A1 /* TransactionRowView.swift */; };
4EB095582989CBFE0043A8A1 /* TransactionDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EB095312989CBFE0043A8A1 /* TransactionDetailView.swift */; };
@@ -206,7 +206,7 @@
4EB095262989CBFE0043A8A1 /* SettingsItem.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SettingsItem.swift; sourceTree = "<group>"; };
4EB095292989CBFE0043A8A1 /* ExchangeListView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExchangeListView.swift; sourceTree = "<group>"; };
4EB0952C2989CBFE0043A8A1 /* Model+Payment.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Model+Payment.swift"; sourceTree = "<group>"; };
- 4EB0952D2989CBFE0043A8A1 /* PaymentURIView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PaymentURIView.swift; sourceTree = "<group>"; };
+ 4EB0952D2989CBFE0043A8A1 /* PaymentView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PaymentView.swift; sourceTree = "<group>"; };
4EB0952F2989CBFE0043A8A1 /* TransactionsListView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TransactionsListView.swift; sourceTree = "<group>"; };
4EB095302989CBFE0043A8A1 /* TransactionRowView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TransactionRowView.swift; sourceTree = "<group>"; };
4EB095312989CBFE0043A8A1 /* TransactionDetailView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TransactionDetailView.swift; sourceTree = "<group>"; };
@@ -451,7 +451,7 @@
4EB0952A2989CBFE0043A8A1 /* Payment */ = {
isa = PBXGroup;
children = (
- 4EB0952D2989CBFE0043A8A1 /* PaymentURIView.swift */,
+ 4EB0952D2989CBFE0043A8A1 /* PaymentView.swift */,
);
path = Payment;
sourceTree = "<group>";
@@ -775,7 +775,7 @@
4E578E942A4822D500F21F1C /* P2pPayURIView.swift in Sources */,
4EB095542989CBFE0043A8A1 /* Model+Payment.swift in Sources */,
4EB0954F2989CBFE0043A8A1 /* SettingsView.swift in Sources */,
- 4EB095552989CBFE0043A8A1 /* PaymentURIView.swift in Sources */,
+ 4EB095552989CBFE0043A8A1 /* PaymentView.swift in Sources */,
4EB095612989CBFE0043A8A1 /* WithdrawURIView.swift in Sources */,
4EF840A72A0B85F400EE0D47 /* CopyShare.swift in Sources */,
4EB094ED298979620043A8A1 /* TalerWallet1App.swift in Sources */,
diff --git a/TalerWallet1/Views/HelperViews/SelectDays.swift b/TalerWallet1/Views/HelperViews/SelectDays.swift
@@ -65,9 +65,9 @@ struct SelectDays: View {
}
}
-struct SelectDays_Previews: PreviewProvider {
- static var previews: some View {
- @State var expireDays: UInt = 1
- SelectDays(selected: $expireDays, maxExpiration: 20)
- }
-}
+//struct SelectDays_Previews: PreviewProvider {
+// static var previews: some View {
+// @State var expireDays: UInt = 1
+// SelectDays(selected: $expireDays, maxExpiration: 20)
+// }
+//}
diff --git a/TalerWallet1/Views/Payment/DeleteMe.swift b/TalerWallet1/Views/Payment/DeleteMe.swift
@@ -1,79 +0,0 @@
-/*
- * This file is part of GNU Taler, ©2022-23 Taler Systems S.A.
- * See LICENSE.md
- */
-import SwiftUI
-import taler_swift
-import AVFoundation
-import SymLog
-
-struct PaymentAcceptView: View {
- private let symLog = SymLogV()
-
- let detailsForUri: PaymentDetailsForUri
- let acceptAction: () -> Void
-
- let navTitle = String(localized: "Accept Payment")
-
- @State private var disabled = false
- var body: some View {
- Group {
- let raw = detailsForUri.amountRaw
- let effective = detailsForUri.amountEffective
- let currency = raw.currencyStr
- let fee = try! Amount.diff(raw, effective) // TODO: different currencies
- ThreeAmountsView(topTitle: String(localized: "Amount to pay:"),
- topAmount: raw, fee: fee,
- bottomTitle: String(localized: "\(currency) to be spent:"),
- bottomAmount: effective,
- large: true, pending: false, incoming: false,
- baseURL: detailsForUri.contractTerms.exchanges.first?.url)
- // TODO: payment: popup with all possible exchanges, check fees
- .safeAreaInset(edge: .bottom) {
- Button(String(localized: "Accept"), action: acceptAction)
- .buttonStyle(TalerButtonStyle(type: .prominent))
- .padding(.horizontal)
- }
- }
- .navigationTitle(navTitle)
- }
-}
-// MARK: -
-struct PaymentAccept_Previews: PreviewProvider {
- static var previews: some View {
- let merchant = Merchant(name: "Merchant")
- let extra = Extra(articleName: "articleName")
- let product = Product(description: "description")
- let terms = ContractTerms(amount: try! Amount(fromString: LONGCURRENCY + ":2.2"),
- maxFee: try! Amount(fromString: LONGCURRENCY + ":0.2"),
- maxWireFee: try! Amount(fromString: LONGCURRENCY + ":0.2"),
- merchant: merchant,
- extra: extra,
- summary: "summary",
- timestamp: Timestamp.now(),
- payDeadline: Timestamp.tomorrow(),
- refundDeadline: Timestamp.tomorrow(),
- wireTransferDeadline: Timestamp.tomorrow(),
- merchantBaseURL: "merchantBaseURL",
- fulfillmentURL: "fulfillmentURL",
- publicReorderURL: "publicReorderURL",
- auditors: [],
- exchanges: [],
- orderID: "orderID",
- nonce: "nonce",
- merchantPub: "merchantPub",
- products: [product],
- hWire: "hWire",
- wireMethod: "wireMethod",
- wireFeeAmortization: 0)
- let details = PaymentDetailsForUri(
- amountRaw: try! Amount(fromString: LONGCURRENCY + ":2.2"),
- amountEffective: try! Amount(fromString: LONGCURRENCY + ":2.4"),
- noncePriv: "noncePriv",
- proposalId: "proposalId",
- contractTerms: terms,
- contractTermsHash: "termsHash"
- )
- PaymentAcceptView(detailsForUri: details, acceptAction: {})
- }
-}
diff --git a/TalerWallet1/Views/Payment/PaymentURIView.swift b/TalerWallet1/Views/Payment/PaymentURIView.swift
@@ -1,153 +0,0 @@
-/*
- * This file is part of GNU Taler, ©2022-23 Taler Systems S.A.
- * See LICENSE.md
- */
-import SwiftUI
-import taler_swift
-import SymLog
-
-// Will be called either by the user scanning a QR code or tapping the provided link,
-// both from the shop's website. We show the payment details
-struct PaymentURIView: View {
- private let symLog = SymLogV()
- let navTitle = String(localized: "Confirm Payment", comment:"pay merchant")
-
- @EnvironmentObject private var controller: Controller
- @AppStorage("myListStyle") var myListStyle: MyListStyle = .automatic
-
- // the scanned URL
- let url: URL
-
- @EnvironmentObject private var model: WalletModel
-
- func acceptAction(preparePayResult: PreparePayResult) {
- Task {
- do {
- let confirmPayResult = try await model.confirmPayM(preparePayResult.transactionId)
-// symLog.log(confirmPayResult as Any)
- if confirmPayResult.type != "done" {
- controller.playSound(0)
- // TODO: show error
- }
- } catch {
- controller.playSound(0)
- // TODO: error
- symLog.log(error.localizedDescription)
- }
- dismissTop()
- }
- }
-
- @State var preparePayResult: PreparePayResult? = nil
-
- var body: some View {
- if let preparePayResult {
- let effective = preparePayResult.amountEffective
- List {
- let baseURL = preparePayResult.contractTerms.exchanges.first?.url
- let raw = preparePayResult.amountRaw
- let currency = raw.currencyStr
- let topTitle = String(localized: "Amount to pay:")
- if let effective {
- // TODO: already paid
- let fee = try! Amount.diff(raw, effective) // TODO: different currencies
- ThreeAmountsView(topTitle: topTitle,
- topAmount: raw, fee: fee,
- bottomTitle: String(localized: "\(currency) to be spent:"),
- bottomAmount: effective,
- large: false, pending: false, incoming: false,
- baseURL: baseURL)
- // TODO: payment: popup with all possible exchanges, check fees
- } else if let balanceDetails = preparePayResult.balanceDetails { // Insufficient
- Text("You don't have enough \(currency)")
- ThreeAmountsView(topTitle: topTitle,
- topAmount: raw, fee: nil,
- bottomTitle: String(localized: "\(currency) available:"),
- bottomAmount: balanceDetails.balanceAvailable,
- large: false, pending: false, incoming: false,
- baseURL: baseURL)
- } else {
- // TODO: Error - neither effective nor balanceDetails
- Text("Error")
- }
- }
- .listStyle(myListStyle.style).anyView
- .safeAreaInset(edge: .bottom) {
- if let effective {
- Button(navTitle, action: { acceptAction(preparePayResult: preparePayResult) })
- .buttonStyle(TalerButtonStyle(type: .prominent))
- .padding(.horizontal)
- } else {
- Button("Cancel", action: { dismissTop() })
- .buttonStyle(TalerButtonStyle(type: .bordered))
- .padding(.horizontal)
- }
- }
- .navigationTitle(navTitle)
- } else {
- let badURL = "Error in Link: \(url)"
- WithdrawProgressView(message: url.host ?? badURL)
- .navigationTitle("Find Exchange")
- .task {
- do {
- symLog.log(".task")
- let result = try await model.preparePayForUriM(url.absoluteString)
- preparePayResult = result
- } catch { // TODO: error
- symLog.log(error.localizedDescription)
- }
- }
- }
- }
-}
-// MARK: -
-struct PaymentURIView_Previews: PreviewProvider {
- static var previews: some View {
- let merchant = Merchant(name: "Merchant")
- let extra = Extra(articleName: "articleName")
- let product = Product(description: "description")
- let terms = MerchantContractTerms(hWire: "hWire",
- wireMethod: "wireMethod",
- summary: "summary",
- summaryI18n: nil,
- nonce: "nonce",
- amount: try! Amount(fromString: LONGCURRENCY + ":2.2"),
- payDeadline: Timestamp.tomorrow(),
- maxFee: try! Amount(fromString: LONGCURRENCY + ":0.2"),
- merchant: merchant,
- merchantPub: "merchantPub",
- deliveryDate: nil,
- deliveryLocation: nil,
- exchanges: [],
- products: [product],
- refundDeadline: Timestamp.tomorrow(),
- wireTransferDeadline: Timestamp.tomorrow(),
- timestamp: Timestamp.now(),
- orderID: "orderID",
- merchantBaseURL: "merchantBaseURL",
- fulfillmentURL: "fulfillmentURL",
- publicReorderURL: "publicReorderURL",
- fulfillmentMessage: nil,
- fulfillmentMessageI18n: nil,
- wireFeeAmortization: 0,
- maxWireFee: try! Amount(fromString: LONGCURRENCY + ":0.2"),
- minimumAge: nil,
- extra: extra
-// auditors: [],
- )
- let details = PreparePayResult(
- status: PreparePayResultType.paymentPossible,
- transactionId: "txn:payment:012345",
- contractTerms: terms,
- contractTermsHash: "termsHash",
- amountRaw: try! Amount(fromString: LONGCURRENCY + ":2.2"),
- amountEffective: try! Amount(fromString: LONGCURRENCY + ":2.4"),
- balanceDetails: nil,
- paid: nil
-// , talerUri: "talerURI"
- )
- let url = URL(string: "taler://pay/some_amount")!
-
- PaymentURIView(url: url, preparePayResult: details)
- }
-}
diff --git a/TalerWallet1/Views/Payment/PaymentView.swift b/TalerWallet1/Views/Payment/PaymentView.swift
@@ -0,0 +1,157 @@
+/*
+ * This file is part of GNU Taler, ©2022-23 Taler Systems S.A.
+ * See LICENSE.md
+ */
+import SwiftUI
+import taler_swift
+import SymLog
+
+// Will be called either by the user scanning a QR code or tapping the provided link,
+// both from the shop's website. We show the payment details
+struct PaymentView: View {
+ private let symLog = SymLogV()
+ let navTitle = String(localized: "Confirm Payment", comment:"pay merchant")
+
+ @EnvironmentObject private var controller: Controller
+ @AppStorage("myListStyle") var myListStyle: MyListStyle = .automatic
+
+ // the scanned URL
+ let url: URL
+
+ @EnvironmentObject private var model: WalletModel
+
+ func acceptAction(preparePayResult: PreparePayResult) {
+ Task {
+ do {
+ let confirmPayResult = try await model.confirmPayM(preparePayResult.transactionId)
+// symLog.log(confirmPayResult as Any)
+ if confirmPayResult.type != "done" {
+ controller.playSound(0)
+ // TODO: show error
+ }
+ } catch {
+ controller.playSound(0)
+ // TODO: error
+ symLog.log(error.localizedDescription)
+ }
+ dismissTop()
+ }
+ }
+
+ @State var preparePayResult: PreparePayResult? = nil
+
+ var body: some View {
+ if let preparePayResult {
+ let effective = preparePayResult.amountEffective
+ List {
+ let baseURL = preparePayResult.contractTerms.exchanges.first?.url
+ let raw = preparePayResult.amountRaw
+ let currency = raw.currencyStr
+ let topTitle = String(localized: "Amount to pay:")
+ if let effective {
+ // TODO: already paid
+ let fee = try! Amount.diff(raw, effective) // TODO: different currencies
+ ThreeAmountsView(topTitle: topTitle,
+ topAmount: raw, fee: fee,
+ bottomTitle: String(localized: "\(currency) to be spent:"),
+ bottomAmount: effective,
+ large: false, pending: false, incoming: false,
+ baseURL: baseURL)
+ // TODO: payment: popup with all possible exchanges, check fees
+ } else if let balanceDetails = preparePayResult.balanceDetails { // Insufficient
+ Text("You don't have enough \(currency)")
+ ThreeAmountsView(topTitle: topTitle,
+ topAmount: raw, fee: nil,
+ bottomTitle: String(localized: "\(currency) available:"),
+ bottomAmount: balanceDetails.balanceAvailable,
+ large: false, pending: false, incoming: false,
+ baseURL: baseURL)
+ } else {
+ // TODO: Error - neither effective nor balanceDetails
+ Text("Error")
+ }
+ }
+ .listStyle(myListStyle.style).anyView
+ .safeAreaInset(edge: .bottom) {
+ if let effective {
+ Button(navTitle, action: { acceptAction(preparePayResult: preparePayResult) })
+ .buttonStyle(TalerButtonStyle(type: .prominent))
+ .padding(.horizontal)
+ } else {
+ Button("Cancel", action: { dismissTop() })
+ .buttonStyle(TalerButtonStyle(type: .bordered))
+ .padding(.horizontal)
+ }
+ }
+ .navigationTitle(navTitle)
+ .onAppear() {
+ symLog.log("onAppear")
+ DebugViewC.shared.setSheetID(SHEET_PAYMENT)
+ }
+ } else {
+ let badURL = "Error in Link: \(url)"
+ WithdrawProgressView(message: url.host ?? badURL)
+ .navigationTitle("Find Exchange")
+ .task {
+ do {
+ symLog.log(".task")
+ let result = try await model.preparePayForUriM(url.absoluteString)
+ preparePayResult = result
+ } catch { // TODO: error
+ symLog.log(error.localizedDescription)
+ }
+ }
+ }
+ }
+}
+// MARK: -
+struct PaymentURIView_Previews: PreviewProvider {
+ static var previews: some View {
+ let merchant = Merchant(name: "Merchant")
+ let extra = Extra(articleName: "articleName")
+ let product = Product(description: "description")
+ let terms = MerchantContractTerms(hWire: "hWire",
+ wireMethod: "wireMethod",
+ summary: "summary",
+ summaryI18n: nil,
+ nonce: "nonce",
+ amount: try! Amount(fromString: LONGCURRENCY + ":2.2"),
+ payDeadline: Timestamp.tomorrow(),
+ maxFee: try! Amount(fromString: LONGCURRENCY + ":0.2"),
+ merchant: merchant,
+ merchantPub: "merchantPub",
+ deliveryDate: nil,
+ deliveryLocation: nil,
+ exchanges: [],
+ products: [product],
+ refundDeadline: Timestamp.tomorrow(),
+ wireTransferDeadline: Timestamp.tomorrow(),
+ timestamp: Timestamp.now(),
+ orderID: "orderID",
+ merchantBaseURL: "merchantBaseURL",
+ fulfillmentURL: "fulfillmentURL",
+ publicReorderURL: "publicReorderURL",
+ fulfillmentMessage: nil,
+ fulfillmentMessageI18n: nil,
+ wireFeeAmortization: 0,
+ maxWireFee: try! Amount(fromString: LONGCURRENCY + ":0.2"),
+ minimumAge: nil,
+ extra: extra
+// auditors: [],
+ )
+ let details = PreparePayResult(
+ status: PreparePayResultType.paymentPossible,
+ transactionId: "txn:payment:012345",
+ contractTerms: terms,
+ contractTermsHash: "termsHash",
+ amountRaw: try! Amount(fromString: LONGCURRENCY + ":2.2"),
+ amountEffective: try! Amount(fromString: LONGCURRENCY + ":2.4"),
+ balanceDetails: nil,
+ paid: nil
+// , talerUri: "talerURI"
+ )
+ let url = URL(string: "taler://pay/some_amount")!
+
+ PaymentView(url: url, preparePayResult: details)
+ }
+}
diff --git a/TalerWallet1/Views/Peer2peer/PaymentPurpose.swift b/TalerWallet1/Views/Peer2peer/PaymentPurpose.swift
@@ -95,17 +95,17 @@ struct PaymentPurpose: View {
}
// MARK: -
#if DEBUG
-struct PaymentPurpose_Previews: PreviewProvider {
- static var previews: some View {
- let scopeInfo = ScopeInfo(type: ScopeInfo.ScopeInfoType.exchange, exchangeBaseUrl: DEMOEXCHANGE, currency: LONGCURRENCY)
- @State var summary: String = "pUrPoSe"
- @State var expireDays: UInt = 0
- PaymentPurpose(scopeInfo: scopeInfo,
- centsToTransfer: 5,
- fee: "fee",
- summary: $summary,
- expireDays: $expireDays)
+//struct PaymentPurpose_Previews: PreviewProvider {
+// static var previews: some View {
+// let scopeInfo = ScopeInfo(type: ScopeInfo.ScopeInfoType.exchange, exchangeBaseUrl: DEMOEXCHANGE, currency: LONGCURRENCY)
+// @State var summary: String = "pUrPoSe"
+// @State var expireDays: UInt = 0
+// PaymentPurpose(scopeInfo: scopeInfo,
+// centsToTransfer: 5,
+// fee: "fee",
+// summary: $summary,
+// expireDays: $expireDays)
// { print("deactivateAction") }
- }
-}
+// }
+//}
#endif
diff --git a/TalerWallet1/Views/Peer2peer/SendPurpose.swift b/TalerWallet1/Views/Peer2peer/SendPurpose.swift
@@ -103,17 +103,17 @@ struct SendPurpose: View {
}
// MARK: -
#if DEBUG
-struct SendPurpose_Previews: PreviewProvider {
- static var previews: some View {
- @State var summary: String = ""
- @State var expireDays: UInt = 0
- let amount = Amount(currency: LONGCURRENCY, integer: 10, fraction: 0)
- SendPurpose(amountAvailable: amount,
- centsToTransfer: 543,
- fee: "0,43",
- summary: $summary,
- expireDays: $expireDays)
+//struct SendPurpose_Previews: PreviewProvider {
+// static var previews: some View {
+// @State var summary: String = ""
+// @State var expireDays: UInt = 0
+// let amount = Amount(currency: LONGCURRENCY, integer: 10, fraction: 0)
+// SendPurpose(amountAvailable: amount,
+// centsToTransfer: 543,
+// fee: "0,43",
+// summary: $summary,
+// expireDays: $expireDays)
// { print("deactivateAction") }
- }
-}
+// }
+//}
#endif
diff --git a/TalerWallet1/Views/Sheets/URLSheet.swift b/TalerWallet1/Views/Sheets/URLSheet.swift
@@ -19,7 +19,7 @@ struct URLSheet: View {
case .withdraw:
WithdrawURIView(url: urlToOpen)
case .pay:
- PaymentURIView(url: urlToOpen)
+ PaymentView(url: urlToOpen)
case .payPull:
P2pPayURIView(url: urlToOpen)
case .payPush: