P2PReadyV.swift (5897B)
1 /* 2 * This file is part of GNU Taler, ©2022-26 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 when initiating a P2P transaction: Send or Request(Invoice) 13 struct P2PReadyV: View { 14 private let symLog = SymLogV(0) 15 let stack: CallStack 16 let scope: ScopeInfo 17 let summary: String 18 let iconID: String? 19 let expireDays: UInt 20 let outgoing: Bool 21 let amountToTransfer: Amount 22 @Binding var transactionStarted: Bool 23 24 @EnvironmentObject private var controller: Controller 25 @EnvironmentObject private var model: WalletModel 26 #if DEBUG 27 @AppStorage("developerMode") var developerMode: Bool = true 28 #else 29 @AppStorage("developerMode") var developerMode: Bool = false 30 #endif 31 @AppStorage("myListStyle") var myListStyle: MyListStyle = .automatic 32 33 @State private var transactionId: String? = nil 34 @State private var initiationError: Error? = nil 35 @State private var noTransaction: TalerTransaction? = nil 36 @State private var talerTX = TalerTransaction(dummyCurrency: DEMOCURRENCY) 37 @Namespace var namespace 38 39 @MainActor 40 private func viewDidLoad() async { 41 symLog.log("viewDidLoad") 42 guard transactionStarted == false else { 43 // TODO: logger.warning("Trying to start P2P a second time") 44 symLog.log("Yikes❗️ Trying to start P2P a second time") 45 return 46 } 47 transactionStarted = true 48 let timestamp = developerMode ? Timestamp.inSomeMinutes(expireDays > 20 ? (24*60) // 24h 49 : expireDays > 5 ? 60 // 1h 50 : 3) // 3m 51 : Timestamp.inSomeDays(expireDays) 52 let purseExpiration = developerMode ? timestamp 53 : outgoing ? nil : timestamp 54 let terms = PeerContractTerms(amount: amountToTransfer, 55 summary: summary, 56 purse_expiration: purseExpiration, 57 icon_id: iconID) 58 do { 59 if outgoing { 60 let response = try await model.initiatePeerPushDebit(scope: scope, terms: terms, 61 viewHandles: true) 62 // will switch from WithdrawProgressView to TransactionSummaryList 63 transactionId = response.transactionId 64 } else { 65 // scope is the exchange the user picked in the ScopePicker, and the one the 66 // fee was computed for. nil (== wallet-core decides) only for global scope. 67 let response = try await model.initiatePeerPullCredit(scope.url, terms: terms, 68 viewHandles: true) 69 // will switch from WithdrawProgressView to TransactionSummaryList 70 transactionId = response.transactionId 71 } 72 } catch { 73 symLog.log("❗️ \(error), \(error.localizedDescription)") 74 transactionStarted = false // failed, so let the user try again 75 initiationError = error // we show it ourselves (viewHandles: true) 76 } 77 } 78 79 func doneAction() { 80 dismissTop(stack.push()) 81 } 82 83 var body: some View { 84 #if PRINT_CHANGES 85 let _ = Self._printChanges() 86 let _ = symLog.vlog() // just to get the # to compare it with .onAppear & onDisappear 87 #endif 88 let navTitle = String(localized: "Ready") 89 ZStack { 90 if let transactionId { 91 TransactionSummaryList(stack: stack.push(), 92 // scope: scope, 93 transactionId: transactionId, 94 talerTX: $talerTX, 95 navTitle: navTitle, 96 hasDone: true, // conclude p2p 97 showDone: .prominent, 98 url: nil, 99 withActions: false) 100 } else if let initiationError { 101 // don't spin forever - the user can go back and start over 102 ErrorView(stack.push(), error: initiationError, devMode: developerMode) 103 } else { 104 #if DEBUG 105 let message = amountToTransfer.currencyStr 106 #else 107 let message: String? = nil 108 #endif 109 LoadingView(stack: stack.push(), scopeInfo: scope, message: message) 110 .task { await viewDidLoad() } 111 } 112 }.onAppear { 113 symLog.log("onAppear") 114 DebugViewC.shared.setViewID(VIEW_P2P_READY, stack: stack.push()) 115 } 116 .onDisappear { 117 // print("❗️ P2PReadyV onDisappear") 118 } 119 #if OIM 120 .overlay { if #available(iOS 16.4, *) { 121 if controller.oimModeActive { 122 OIMp2pReadyView(stack: stack.push(), 123 transactionId: $transactionId, 124 talerTX: talerTX, 125 scope: scope, 126 action: doneAction) 127 .environmentObject(NamespaceWrapper(namespace)) // keep OIMviews apart 128 } 129 } } 130 #endif 131 } 132 } 133 // MARK: - 134 //struct SendNow_Previews: PreviewProvider { 135 // static var previews: some View { 136 // Group { 137 // SendDoneV(stack: CallStack("Preview"), 138 // amountToSend: Amount(currency: LONGCURRENCY, cent: 480), 139 // amountToReceive: nil, 140 // summary: "some subject/purpose", 141 // expireDays: 0) 142 // } 143 // } 144 //}