ExchangeRowView.swift (5335B)
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 struct ExchangeRowView: View { 13 private let symLog = SymLogV(0) 14 let stack: CallStack 15 let exchange: Exchange 16 let index: Int 17 18 @Environment(\.sizeCategory) var sizeCategory 19 @EnvironmentObject private var controller: Controller 20 @EnvironmentObject private var model: WalletModel 21 @EnvironmentObject private var tabBarModel: TabBarModel 22 23 var body: some View { 24 #if PRINT_CHANGES 25 let _ = Self._printChanges() 26 let _ = symLog.vlog() // just to get the # to compare it with .onAppear & onDisappear 27 let delay: UInt = 0 // set to 5 to test delayed currency information 28 #else 29 let delay: UInt = 0 30 #endif 31 let baseURL = exchange.exchangeBaseUrl 32 let chevron = Text(Image(systemName: "chevron.right")) 33 .talerFont(.table) 34 .foregroundColor(.secondary) 35 36 let termsLine = HStack { 37 Text("Terms of Service") // VIEW_WITHDRAW_TOS 38 Spacer() 39 chevron 40 } 41 42 let rowView = VStack(alignment: .leading) { 43 Text(baseURL.trimURL) 44 .talerFont(.headline) 45 ExchangeStatus(exchange: exchange) 46 termsLine 47 .talerFont(.body) 48 .background { // only needed for .onTapGesture 49 Color.gray.opacity(INVISIBLE) 50 } 51 .onTapGesture { 52 tabBarModel.tosView = index 53 } 54 } 55 let showToS = WithdrawTOSView(stack: stack.push(), 56 exchangeBaseUrl: baseURL, 57 viewID: VIEW_WITHDRAW_TOS, 58 acceptAction: nil) // pop back to here 59 let details = ExchangeDetailView(stack: stack.push(), 60 exchange: exchange) 61 let actions = Group { 62 NavLink(index, $tabBarModel.tosView) { showToS } 63 } 64 65 Group { 66 rowView 67 .background(actions) 68 }.listRowSeparator(.hidden) 69 } 70 } 71 // MARK: - 72 struct ExchangeStatus: View { 73 let exchange: Exchange 74 75 @EnvironmentObject private var controller: Controller 76 @AppStorage("minimalistic") var minimalistic: Bool = false 77 78 var body: some View { 79 let status = controller.isConnected ? exchange.exchangeUpdateStatus.localized 80 : ExchangeUpdateStatus.unavailable.localized 81 VStack(alignment: .leading) { 82 HStack { 83 if !minimalistic { 84 Text("Status:") 85 } 86 Text(status) 87 } 88 if let lastUpdateErrorInfo = exchange.lastUpdateErrorInfo { 89 Text("Last Error: \(lastUpdateErrorInfo.error.code)") 90 if let hint = lastUpdateErrorInfo.error.hint { 91 Text(hint) // TODO: L10N 92 } 93 if let detail = lastUpdateErrorInfo.error.detail { 94 Text(detail) // TODO: L10N 95 } 96 } 97 } 98 .padding(.bottom, 4) 99 .talerFont(.body) 100 } 101 } 102 // MARK: - 103 #if DEBUG 104 fileprivate struct ExchangeRow_Previews: PreviewProvider { 105 @MainActor 106 struct BindingViewContainer : View { 107 @State private var amountToPreview = Amount(currency: LONGCURRENCY, cent: 1234) 108 @State private var depositIBAN = "DE1234567890" 109 @State private var accountHolder = "Marc Stibane" 110 // @State private var previewL: CurrencyInfo = CurrencyInfo.zero(LONGCURRENCY) 111 112 // let amount = Amount(currency: LONGCURRENCY, cent: 123456) 113 var body: some View { 114 let scopeInfo = ScopeInfo(type: .exchange, currency: LONGCURRENCY) 115 let exchange1 = Exchange(exchangeBaseUrl: ARS_AGE_EXCHANGE, 116 masterPub: "masterPub", 117 scopeInfo: scopeInfo, 118 paytoUris: [], 119 tosStatus: .pending, 120 exchangeEntryStatus: .preset, 121 exchangeUpdateStatus: .initial, 122 ageRestrictionOptions: [12,16]) 123 let exchange2 = Exchange(exchangeBaseUrl: ARS_EXP_EXCHANGE, 124 masterPub: "masterPub", 125 scopeInfo: scopeInfo, 126 paytoUris: [], 127 tosStatus: .proposed, 128 exchangeEntryStatus: .ephemeral, 129 exchangeUpdateStatus: .ready, 130 ageRestrictionOptions: []) 131 ExchangeRowView(stack: CallStack("Preview"), 132 exchange: exchange1, 133 index: 1) 134 } 135 } 136 137 @MainActor 138 static var previews: some View { 139 List { 140 BindingViewContainer() 141 } 142 } 143 } 144 #endif