P2pPayURIView.swift (5439B)
1 /* 2 * This file is part of GNU Taler, ©2022-25 Taler Systems S.A. 3 * See LICENSE.md 4 */ 5 /** 6 * @author Marc Stibane 7 */ 8 import SwiftUI 9 import taler_swift 10 import SymLog 11 12 // Called either when scanning a QR code or tapping the provided link 13 // from another user's Request(Invoice). We show the P2P details. 14 struct P2pPayURIView: View { 15 private let symLog = SymLogV(0) 16 let stack: CallStack 17 18 // the scanned URL 19 let url: URL 20 21 @EnvironmentObject private var model: WalletModel 22 @EnvironmentObject private var controller: Controller 23 @AppStorage("myListStyle") var myListStyle: MyListStyle = .automatic 24 25 @State private var peerPullDebitResponse: PreparePeerPullDebitResponse? 26 27 let navTitle = String(localized: "Pay Request", comment: "Nav Title") 28 29 @MainActor 30 private func viewDidLoad() async { 31 do { 32 symLog.log(".task") 33 let response = try? await model.preparePeerPullDebit(url.absoluteString) 34 if let response { 35 controller.removeURL(url) // tx is now saved by wallet-core 36 } 37 peerPullDebitResponse = response 38 } 39 } 40 41 var body: some View { 42 VStack { 43 if let peerPullDebitResponse { 44 List { 45 PeerPullDebitView(stack: stack.push(), 46 raw: peerPullDebitResponse.amountRaw, 47 effective: peerPullDebitResponse.amountEffective, 48 scope: peerPullDebitResponse.scopeInfo, 49 summary: peerPullDebitResponse.contractTerms.summary) 50 let expiration = peerPullDebitResponse.contractTerms.purse_expiration 51 ExpiresView(expiration: expiration) 52 } 53 .listStyle(myListStyle.style).anyView 54 .navigationTitle(navTitle) 55 // .task(id: controller.currencyTicker) { 56 // let currency = peerPullDebitResponse.amountRaw.currencyStr 57 // currencyInfo = controller.info2(for: currency, controller.currencyTicker) 58 // } 59 .safeAreaInset(edge: .bottom) { 60 if peerPullDebitResponse.txState.isConfirmed { 61 Button("Done") { dismissTop(stack.push()) } 62 .buttonStyle(TalerButtonStyle(type: .prominent)) 63 .padding(.horizontal) 64 } else { 65 PeerPullDebitConfirm(stack: stack.push(), url: url, 66 transactionId: peerPullDebitResponse.transactionId) 67 } 68 } 69 } else { 70 #if DEBUG 71 let message = url.host 72 #else 73 let message: String? = nil 74 #endif 75 LoadingView(stack: stack.push(), scopeInfo: nil, message: message) 76 .task { await viewDidLoad() } 77 } 78 } 79 .onAppear() { 80 symLog.log("onAppear") 81 DebugViewC.shared.setSheetID(SHEET_PAY_P2P) 82 } 83 } 84 } 85 // MARK: - 86 //#Preview { 87 // P2pPayURIView(url: <#T##URL#>, model: <#T##WalletModel#>) 88 //} 89 // MARK: - 90 struct PeerPullDebitConfirm: View { 91 let stack: CallStack 92 let url: URL? 93 let transactionId: String 94 95 var body: some View { 96 let destination = P2pAcceptDone(stack: stack.push(), 97 url: url, 98 transactionId: transactionId, 99 incoming: false) 100 NavigationLink(destination: destination) { 101 Text("Confirm Payment", comment:"pay P2P request/invoice") // SHEET_PAY_P2P 102 } 103 .buttonStyle(TalerButtonStyle(type: .prominent)) 104 .padding(.horizontal) 105 } 106 } 107 // MARK: - 108 struct PeerPullDebitView: View { 109 let stack: CallStack 110 // let peerPullDebitResponse: PreparePeerPullDebitResponse 111 let raw: Amount 112 let effective: Amount 113 let scope: ScopeInfo? 114 let summary: String 115 116 @Environment(\.colorScheme) private var colorScheme 117 @Environment(\.colorSchemeContrast) private var colorSchemeContrast 118 @AppStorage("minimalistic") var minimalistic: Bool = false 119 var body: some View { 120 // let raw = peerPullDebitResponse.amountRaw 121 // let effective = peerPullDebitResponse.amountEffective 122 // let scope = peerPullDebitResponse.scopeInfo 123 let currency = raw.currencyStr 124 let fee = try! Amount.diff(raw, effective) 125 ThreeAmountsSection(stack: stack.push(), 126 scope: scope, 127 topTitle: String(localized: "Amount to pay:"), 128 topAbbrev: String(localized: "Pay:", comment: "mini"), 129 topAmount: raw, 130 noFees: nil, // TODO: check baseURL for fees 131 fee: fee, 132 bottomTitle: String(localized: "Amount to be spent:"), 133 bottomAbbrev: String(localized: "Effective:", comment: "mini"), 134 bottomAmount: effective, 135 large: false, pending: false, incoming: false, 136 baseURL: nil, 137 txStateLcl: nil, 138 summary: summary, 139 merchant: nil, 140 products: nil) 141 } 142 }