commit e6a549b1b054ce2bcb1f63f051ca61a15cc2c787
parent 63d75161e6bed751d15dd22f22b6226b991e49d4
Author: Marc Stibane <marc@taler.net>
Date: Fri, 12 Dec 2025 08:45:57 +0100
show ExchangeStatus and errors
Diffstat:
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