diff options
author | Marc Stibane <marc@taler.net> | 2023-08-08 12:00:12 +0200 |
---|---|---|
committer | Marc Stibane <marc@taler.net> | 2023-08-08 12:04:30 +0200 |
commit | e728e0f48e9bb6f384b205db82c8c1dadd700c00 (patch) | |
tree | 6c2c3f1223d6d67407d34ffac4144e21a7d6a647 | |
parent | f6a838560b5d7fc6f80b74b33c4baf099c30e331 (diff) | |
download | taler-ios-e728e0f48e9bb6f384b205db82c8c1dadd700c00.tar.gz taler-ios-e728e0f48e9bb6f384b205db82c8c1dadd700c00.tar.bz2 taler-ios-e728e0f48e9bb6f384b205db82c8c1dadd700c00.zip |
started with PayTemplates
-rw-r--r-- | TalerWallet.xcodeproj/project.pbxproj | 4 | ||||
-rw-r--r-- | TalerWallet1/Controllers/Controller.swift | 3 | ||||
-rw-r--r-- | TalerWallet1/Controllers/DebugViewC.swift | 1 | ||||
-rw-r--r-- | TalerWallet1/Model/Model+Payment.swift | 18 | ||||
-rw-r--r-- | TalerWallet1/Views/Payment/PayTemplateView.swift | 113 | ||||
-rw-r--r-- | TalerWallet1/Views/Sheets/URLSheet.swift | 6 |
6 files changed, 144 insertions, 1 deletions
diff --git a/TalerWallet.xcodeproj/project.pbxproj b/TalerWallet.xcodeproj/project.pbxproj index 5024d76..eae83d9 100644 --- a/TalerWallet.xcodeproj/project.pbxproj +++ b/TalerWallet.xcodeproj/project.pbxproj @@ -96,6 +96,7 @@ 4EB095702989CBFE0043A8A1 /* PendingOpsListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EB0954E2989CBFE0043A8A1 /* PendingOpsListView.swift */; }; 4EB3136129FEE79B007D68BC /* SendDone.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EB3136029FEE79B007D68BC /* SendDone.swift */; }; 4EB431672A1E55C700C5690E /* ManualWithdrawDone.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EB431662A1E55C700C5690E /* ManualWithdrawDone.swift */; }; + 4EBA56412A7FF5200084948B /* PayTemplateView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EBA56402A7FF5200084948B /* PayTemplateView.swift */; }; 4EBA82AB2A3EB2CA00E5F39A /* TransactionButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EBA82AA2A3EB2CA00E5F39A /* TransactionButton.swift */; }; 4EBA82AD2A3F580500E5F39A /* QuiteSomeCoins.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EBA82AC2A3F580500E5F39A /* QuiteSomeCoins.swift */; }; 4EC90C782A1B528B0071DC58 /* ExchangeSectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EC90C772A1B528B0071DC58 /* ExchangeSectionView.swift */; }; @@ -234,6 +235,7 @@ 4EB0954E2989CBFE0043A8A1 /* PendingOpsListView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PendingOpsListView.swift; sourceTree = "<group>"; }; 4EB3136029FEE79B007D68BC /* SendDone.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SendDone.swift; sourceTree = "<group>"; }; 4EB431662A1E55C700C5690E /* ManualWithdrawDone.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ManualWithdrawDone.swift; sourceTree = "<group>"; }; + 4EBA56402A7FF5200084948B /* PayTemplateView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PayTemplateView.swift; sourceTree = "<group>"; }; 4EBA82AA2A3EB2CA00E5F39A /* TransactionButton.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TransactionButton.swift; sourceTree = "<group>"; }; 4EBA82AC2A3F580500E5F39A /* QuiteSomeCoins.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuiteSomeCoins.swift; sourceTree = "<group>"; }; 4EC90C772A1B528B0071DC58 /* ExchangeSectionView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExchangeSectionView.swift; sourceTree = "<group>"; }; @@ -452,6 +454,7 @@ isa = PBXGroup; children = ( 4EB0952D2989CBFE0043A8A1 /* PaymentView.swift */, + 4EBA56402A7FF5200084948B /* PayTemplateView.swift */, ); path = Payment; sourceTree = "<group>"; @@ -791,6 +794,7 @@ 4EB3136129FEE79B007D68BC /* SendDone.swift in Sources */, 4EB0956B2989CBFE0043A8A1 /* TextFieldAlert.swift in Sources */, 4EBA82AD2A3F580500E5F39A /* QuiteSomeCoins.swift in Sources */, + 4EBA56412A7FF5200084948B /* PayTemplateView.swift in Sources */, 4EB431672A1E55C700C5690E /* ManualWithdrawDone.swift in Sources */, 4E9320472A164BC700A87B0E /* PaymentPurpose.swift in Sources */, 4E753A082A0B6A5F002D9328 /* ShareSheet.swift in Sources */, diff --git a/TalerWallet1/Controllers/Controller.swift b/TalerWallet1/Controllers/Controller.swift index 96e1fef..17201f5 100644 --- a/TalerWallet1/Controllers/Controller.swift +++ b/TalerWallet1/Controllers/Controller.swift @@ -21,6 +21,7 @@ enum UrlCommand { case pay case payPull case payPush + case payTemplate } // MARK: - @@ -103,6 +104,8 @@ extension Controller { return UrlCommand.payPull case "pay-push": return UrlCommand.payPush + case "pay-template": + return UrlCommand.payTemplate default: symLog.log("unknown command taler://\(command)") } diff --git a/TalerWallet1/Controllers/DebugViewC.swift b/TalerWallet1/Controllers/DebugViewC.swift index f25b353..4cd365c 100644 --- a/TalerWallet1/Controllers/DebugViewC.swift +++ b/TalerWallet1/Controllers/DebugViewC.swift @@ -73,6 +73,7 @@ public let SHEET_WITHDRAW_CONFIRM = SHEET_WITHDRAW_ACCEPT + 1 // 133 waiti // MARK: Merchant Payment // openURL (Link, NFC or scan QR) ==> pays merchant public let SHEET_PAYMENT = SHEET_WITHDRAWAL + 10 // 140 Pay Merchant +public let SHEET_PAY_TEMPLATE = SHEET_PAYMENT + 2 // 142 Pay Merchant Template // MARK: Reward - Receive Coins (from merchant) // openURL (Link, NFC or scan QR) ==> receive coins from merchant diff --git a/TalerWallet1/Model/Model+Payment.swift b/TalerWallet1/Model/Model+Payment.swift index 51e8d57..88872e2 100644 --- a/TalerWallet1/Model/Model+Payment.swift +++ b/TalerWallet1/Model/Model+Payment.swift @@ -147,6 +147,17 @@ fileprivate struct PreparePayForUri: WalletBackendFormattedRequest { var talerPayUri: String } } +/// A request to get an exchange's payment contract terms. +fileprivate struct PreparePayForTemplate: WalletBackendFormattedRequest { + typealias Response = PreparePayResult + func operation() -> String { return "preparePayForTemplate" } + func args() -> Args { return Args(talerPayTemplateUri: talerPayTemplateUri) } + + var talerPayTemplateUri: String + struct Args: Encodable { + var talerPayTemplateUri: String + } +} // MARK: - /// The result from confirmPayForUri struct ConfirmPayResult: Decodable { @@ -176,6 +187,13 @@ extension WalletModel { return response } @MainActor + func preparePayForTemplateM(_ talerPayTemplateUri: String) // M for MainActor + async throws -> PreparePayResult { + let request = PreparePayForTemplate(talerPayTemplateUri: talerPayTemplateUri) + let response = try await sendRequest(request, ASYNCDELAY) + return response + } + @MainActor func confirmPayM(_ transactionId: String) // M for MainActor async throws -> ConfirmPayResult { let request = confirmPayForUri(transactionId: transactionId) diff --git a/TalerWallet1/Views/Payment/PayTemplateView.swift b/TalerWallet1/Views/Payment/PayTemplateView.swift new file mode 100644 index 0000000..526d0b0 --- /dev/null +++ b/TalerWallet1/Views/Payment/PayTemplateView.swift @@ -0,0 +1,113 @@ +/* + * 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 PayTemplateView: 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 + + func query(url: URL) -> String? { + if let query = url.query { + let array = query.components(separatedBy: "&") + } + return 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_PAY_TEMPLATE) + } + } 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.preparePayForTemplateM(url.absoluteString) + preparePayResult = result + } catch { // TODO: error + symLog.log(error.localizedDescription) + } + } + } + } +} diff --git a/TalerWallet1/Views/Sheets/URLSheet.swift b/TalerWallet1/Views/Sheets/URLSheet.swift index 42ec8b2..1db6169 100644 --- a/TalerWallet1/Views/Sheets/URLSheet.swift +++ b/TalerWallet1/Views/Sheets/URLSheet.swift @@ -24,7 +24,11 @@ struct URLSheet: View { P2pPayURIView(url: urlToOpen) case .payPush: P2pReceiveURIView(url: urlToOpen) - case .unknown: // Error view + case .payTemplate: + PayTemplateView(url: urlToOpen) +// case .reward: +// RewardURIView(url: urlToOpen) + default: // Error view VStack { Text("unknown command") .font(.title) |