taler-ios

iOS apps for GNU Taler (wallet)
Log | Files | Refs | README | LICENSE

commit e6a549b1b054ce2bcb1f63f051ca61a15cc2c787
parent 63d75161e6bed751d15dd22f22b6226b991e49d4
Author: Marc Stibane <marc@taler.net>
Date:   Fri, 12 Dec 2025 08:45:57 +0100

show ExchangeStatus and errors

Diffstat:
ATalerWallet1/Views/Settings/Exchange/ExchangeDetailView.swift | 79+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
MTalerWallet1/Views/Settings/Exchange/ExchangeRowView.swift | 72+++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------
2 files changed, 132 insertions(+), 19 deletions(-)

diff --git a/TalerWallet1/Views/Settings/Exchange/ExchangeDetailView.swift b/TalerWallet1/Views/Settings/Exchange/ExchangeDetailView.swift @@ -0,0 +1,79 @@ +/* + * This file is part of GNU Taler, ©2022-25 Taler Systems S.A. + * See LICENSE.md + */ +/** + * @author Marc Stibane + */ +import SwiftUI +import taler_swift +import SymLog + +struct ExchangeDetailView: View { + private let symLog = SymLogV(0) + let stack: CallStack + let exchange: Exchange + + @Environment(\.sizeCategory) var sizeCategory + @EnvironmentObject private var controller: Controller + @EnvironmentObject private var model: WalletModel + @EnvironmentObject private var tabBarModel: TabBarModel + @AppStorage("minimalistic") var minimalistic: Bool = false + + var body: some View { +#if PRINT_CHANGES + let _ = Self._printChanges() + let _ = symLog.vlog() // just to get the # to compare it with .onAppear & onDisappear + let delay: UInt = 0 // set to 5 to test delayed currency information +#else + let delay: UInt = 0 +#endif + let baseURL = exchange.exchangeBaseUrl + let rowView = HStack { + if !minimalistic { + Text("Status:") + } + Text(exchange.exchangeUpdateStatus.rawValue) // VIEW_WITHDRAW_TOS + } + .talerFont(.body) + rowView + + } +} +// MARK: - +#if DEBUG +fileprivate struct ExchangeDetail_Previews: PreviewProvider { + @MainActor + struct BindingViewContainer : View { + + var body: some View { + let scopeInfo = ScopeInfo(type: .exchange, currency: LONGCURRENCY) + let exchange1 = Exchange(exchangeBaseUrl: ARS_AGE_EXCHANGE, + masterPub: "masterPub", + scopeInfo: scopeInfo, + paytoUris: [], + tosStatus: .pending, + exchangeEntryStatus: .preset, + exchangeUpdateStatus: .initial, + ageRestrictionOptions: [12,16]) + let exchange2 = Exchange(exchangeBaseUrl: ARS_EXP_EXCHANGE, + masterPub: "masterPub", + scopeInfo: scopeInfo, + paytoUris: [], + tosStatus: .proposed, + exchangeEntryStatus: .ephemeral, + exchangeUpdateStatus: .ready, + ageRestrictionOptions: []) + ExchangeDetailView(stack: CallStack("Preview"), + exchange: exchange1) + } + } + + @MainActor + static var previews: some View { + List { + BindingViewContainer() + } + } +} +#endif diff --git a/TalerWallet1/Views/Settings/Exchange/ExchangeRowView.swift b/TalerWallet1/Views/Settings/Exchange/ExchangeRowView.swift @@ -19,7 +19,6 @@ struct ExchangeRowView: View { @EnvironmentObject private var controller: Controller @EnvironmentObject private var model: WalletModel @EnvironmentObject private var tabBarModel: TabBarModel - @AppStorage("minimalistic") var minimalistic: Bool = false var body: some View { #if PRINT_CHANGES @@ -30,42 +29,77 @@ struct ExchangeRowView: View { let delay: UInt = 0 #endif let baseURL = exchange.exchangeBaseUrl + let chevron = Text(Image(systemName: "chevron.right")) + .talerFont(.table) + .foregroundColor(.secondary) + + let termsLine = HStack { + Text("Terms of Service") // VIEW_WITHDRAW_TOS + Spacer() + chevron + } + let rowView = VStack(alignment: .leading) { Text(baseURL.trimURL) .talerFont(.headline) - if !minimalistic { - Text("Terms of Service") // VIEW_WITHDRAW_TOS - .talerFont(.body) - } - } - let cellView = HStack { - rowView - Spacer() - Text(Image(systemName: "chevron.right")) - .talerFont(.table) - .foregroundColor(.secondary) - }.background { // only needed for .onTapGesture - Color.gray.opacity(INVISIBLE) + ExchangeStatus(exchange: exchange) + termsLine + .talerFont(.body) + .background { // only needed for .onTapGesture + Color.gray.opacity(INVISIBLE) + } + .onTapGesture { + tabBarModel.tosView = index + } } let showToS = WithdrawTOSView(stack: stack.push(), exchangeBaseUrl: baseURL, viewID: VIEW_WITHDRAW_TOS, acceptAction: nil) // pop back to here + let details = ExchangeDetailView(stack: stack.push(), + exchange: exchange) let actions = Group { NavLink(index, $tabBarModel.tosView) { showToS } } Group { -// NavigationLink(destination: showToS) { rowView } - cellView + rowView .background(actions) - .onTapGesture { - tabBarModel.tosView = index - } }.listRowSeparator(.hidden) } } // MARK: - +struct ExchangeStatus: View { + let exchange: Exchange + + @EnvironmentObject private var controller: Controller + @AppStorage("minimalistic") var minimalistic: Bool = false + + var body: some View { + let status = controller.isConnected ? exchange.exchangeUpdateStatus.localized + : ExchangeUpdateStatus.unavailable.localized + VStack(alignment: .leading) { + HStack { + if !minimalistic { + Text("Status:") + } + Text(status) + } + if let lastUpdateErrorInfo = exchange.lastUpdateErrorInfo { + Text("Last Error: \(lastUpdateErrorInfo.error.code)") + if let hint = lastUpdateErrorInfo.error.hint { + Text(hint) // TODO: L10N + } + if let detail = lastUpdateErrorInfo.error.detail { + Text(detail) // TODO: L10N + } + } + } + .padding(.bottom, 4) + .talerFont(.body) + } +} +// MARK: - #if DEBUG fileprivate struct ExchangeRow_Previews: PreviewProvider { @MainActor