commit d5e285e741f1ac2427c80e1f4fcf63a9439ede9f
parent b1da0929c1468ca0a44655a775d1f9fb3051faea
Author: Marc Stibane <marc@taler.net>
Date: Sat, 15 Mar 2025 15:23:57 +0100
ErrorView (no sheet, but ZStack)
Diffstat:
7 files changed, 144 insertions(+), 144 deletions(-)
diff --git a/TalerWallet.xcodeproj/project.pbxproj b/TalerWallet.xcodeproj/project.pbxproj
@@ -334,8 +334,8 @@
E37AA62B2AF197E5003850CF /* Model+Refund.swift in Sources */ = {isa = PBXBuildFile; fileRef = E37AA6292AF197E5003850CF /* Model+Refund.swift */; };
E37AA62E2AF19BE0003850CF /* RefundURIView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E37AA62D2AF19BE0003850CF /* RefundURIView.swift */; };
E37AA62F2AF19BE0003850CF /* RefundURIView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E37AA62D2AF19BE0003850CF /* RefundURIView.swift */; };
- E3E48FB22B9B7B5400898A0F /* ErrorSheet.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3E48FB12B9B7B5400898A0F /* ErrorSheet.swift */; };
- E3E48FB32B9B7B5400898A0F /* ErrorSheet.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3E48FB12B9B7B5400898A0F /* ErrorSheet.swift */; };
+ E3E48FB22B9B7B5400898A0F /* ErrorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3E48FB12B9B7B5400898A0F /* ErrorView.swift */; };
+ E3E48FB32B9B7B5400898A0F /* ErrorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3E48FB12B9B7B5400898A0F /* ErrorView.swift */; };
E3E48FB52B9B7D5000898A0F /* Encodable+toJSON.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3E48FB42B9B7D5000898A0F /* Encodable+toJSON.swift */; };
E3E48FB62B9B7D5000898A0F /* Encodable+toJSON.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3E48FB42B9B7D5000898A0F /* Encodable+toJSON.swift */; };
/* End PBXBuildFile section */
@@ -547,7 +547,7 @@
D14AFD3E24D232B500C51073 /* TalerUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = TalerUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
E37AA6292AF197E5003850CF /* Model+Refund.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Model+Refund.swift"; sourceTree = "<group>"; };
E37AA62D2AF19BE0003850CF /* RefundURIView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RefundURIView.swift; sourceTree = "<group>"; };
- E3E48FB12B9B7B5400898A0F /* ErrorSheet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ErrorSheet.swift; sourceTree = "<group>"; };
+ E3E48FB12B9B7B5400898A0F /* ErrorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ErrorView.swift; sourceTree = "<group>"; };
E3E48FB42B9B7D5000898A0F /* Encodable+toJSON.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Encodable+toJSON.swift"; sourceTree = "<group>"; };
/* End PBXFileReference section */
@@ -894,6 +894,7 @@
isa = PBXGroup;
children = (
4EB095442989CBFE0043A8A1 /* MainView.swift */,
+ E3E48FB12B9B7B5400898A0F /* ErrorView.swift */,
4EED38542D140C1400F6C038 /* TabBarModel.swift */,
4EB095392989CBFE0043A8A1 /* WalletEmptyView.swift */,
);
@@ -970,7 +971,6 @@
4EB0952A2989CBFE0043A8A1 /* Payment */,
E37AA62C2AF19BA6003850CF /* Refund */,
4E3B4BBF2A41E64000CC88B8 /* P2P_Sheets */,
- E3E48FB12B9B7B5400898A0F /* ErrorSheet.swift */,
);
path = Sheets;
sourceTree = "<group>";
@@ -1329,7 +1329,7 @@
4E3EAE452A990778009F1BE8 /* P2PReadyV.swift in Sources */,
4E3EAE462A990778009F1BE8 /* TextFieldAlert.swift in Sources */,
4E3EAE472A990778009F1BE8 /* QuiteSomeCoins.swift in Sources */,
- E3E48FB22B9B7B5400898A0F /* ErrorSheet.swift in Sources */,
+ E3E48FB22B9B7B5400898A0F /* ErrorView.swift in Sources */,
4E2D8DD52B45822A00234039 /* AmountV.swift in Sources */,
4E3EAE492A990778009F1BE8 /* ManualWithdrawDone.swift in Sources */,
4E3EAE4B2A990778009F1BE8 /* ShareSheet.swift in Sources */,
@@ -1474,7 +1474,7 @@
4EB3136129FEE79B007D68BC /* P2PReadyV.swift in Sources */,
4EB0956B2989CBFE0043A8A1 /* TextFieldAlert.swift in Sources */,
4EBA82AD2A3F580500E5F39A /* QuiteSomeCoins.swift in Sources */,
- E3E48FB32B9B7B5400898A0F /* ErrorSheet.swift in Sources */,
+ E3E48FB32B9B7B5400898A0F /* ErrorView.swift in Sources */,
4E2D8DD62B45822A00234039 /* AmountV.swift in Sources */,
4EB431672A1E55C700C5690E /* ManualWithdrawDone.swift in Sources */,
4E753A082A0B6A5F002D9328 /* ShareSheet.swift in Sources */,
diff --git a/TalerWallet1/Views/Main/ErrorView.swift b/TalerWallet1/Views/Main/ErrorView.swift
@@ -0,0 +1,125 @@
+/*
+ * This file is part of GNU Taler, ©2022-25 Taler Systems S.A.
+ * See LICENSE.md
+ */
+/**
+ * @author Iván Ávalos
+ */
+import SwiftUI
+import taler_swift
+
+enum ErrorData {
+ case message(title: String, message: String)
+ case error(Error)
+}
+
+struct ErrorView: View {
+ var title: String
+ var message: String? = nil
+ var copyable: Bool
+
+ var onDismiss: () -> Void
+
+ init(title: String, message: String? = nil, copyable: Bool, onDismiss: @escaping () -> Void) {
+ self.title = title
+ self.message = message
+ self.copyable = copyable
+ self.onDismiss = onDismiss
+ }
+
+ init(error: Error, devMode: Bool, onDismiss: @escaping () -> Void) {
+ let walletCoreError = String(localized: "Internal core error")
+ let initializationError = String(localized: "Initialization error")
+ let serializationError = String(localized: "Serialization error")
+ let deserializationError = String(localized: "Deserialization error")
+ let unknownError = String(localized: "Unknown error")
+
+ switch error {
+ case let walletError as WalletBackendError:
+ switch walletError {
+ case .walletCoreError(let error):
+ if let json = error?.toJSON(), devMode {
+ self.init(title: walletCoreError, message: json, copyable: true, onDismiss: onDismiss)
+ } else if let hint = error?.errorResponse?.hint ?? error?.hint {
+ self.init(title: walletCoreError, message: hint, copyable: false, onDismiss: onDismiss)
+ } else if let message = error?.message {
+ self.init(title: walletCoreError, message: message, copyable: false, onDismiss: onDismiss)
+ } else {
+ self.init(title: walletCoreError, copyable: false, onDismiss: onDismiss)
+ }
+ case .initializationError:
+ self.init(title: initializationError, copyable: false, onDismiss: onDismiss)
+ case .serializationError:
+ self.init(title: serializationError, copyable: false, onDismiss: onDismiss)
+ case .deserializationError:
+ self.init(title: deserializationError, copyable: false, onDismiss: onDismiss)
+ }
+ default:
+ self.init(title: unknownError, message: error.localizedDescription, copyable: false, onDismiss: onDismiss)
+ }
+ }
+
+ init(data: ErrorData, devMode: Bool, onDismiss: @escaping () -> Void) {
+ switch data {
+ case .message(let title, let message):
+ self.init(title: title, message: message, copyable: false, onDismiss: onDismiss)
+ case .error(let error):
+ self.init(error: error, devMode: devMode, onDismiss: onDismiss)
+ }
+ }
+
+ var body: some View {
+ ScrollView {
+ VStack {
+ Image(systemName: "exclamationmark.circle")
+ .resizable()
+ .frame(width: 50, height: 50)
+ .aspectRatio(contentMode: .fit)
+ .foregroundStyle(WalletColors().attention)
+ .padding()
+
+ Text(title)
+ .talerFont(.title)
+ .padding(.bottom)
+
+ if let message {
+ if copyable {
+ if #available(iOS 16.4, *) {
+ Text(message).monospaced()
+ } else {
+ Text(message).font(.system(.body, design: .monospaced))
+ }
+
+ CopyButton(textToCopy: message, vertical: false)
+ .accessibilityLabel("Copy the error JSON")
+ .padding()
+ } else {
+ Text(message)
+ .multilineTextAlignment(.center)
+ }
+ }
+ }
+ }
+ .padding()
+ .safeAreaInset(edge: .bottom) {
+ Button("Close", role: .cancel) {
+ onDismiss()
+ }
+ .buttonStyle(TalerButtonStyle(type: .bordered))
+ .padding(.bottom)
+ .padding(.horizontal)
+ }
+ }
+}
+
+struct ErrorSheet_Previews: PreviewProvider {
+ static let error = WalletBackendError.walletCoreError(WalletBackendResponseError(
+ code: 7025, when: Timestamp.now(),
+ hint: "A KYC step is required before withdrawal can proceed",
+ message: "A KYC step is required before withdrawal can proceed"))
+
+ static var previews: some View {
+ ErrorView(error: error, devMode: true, onDismiss: {})
+ ErrorView(error: error, devMode: false, onDismiss: {})
+ }
+}
diff --git a/TalerWallet1/Views/Main/MainView.swift b/TalerWallet1/Views/Main/MainView.swift
@@ -82,7 +82,7 @@ struct MainView: View {
if (!showScanner && urlToOpen == nil) {
if let error2 = model.error2 {
- ErrorSheet(data: error2, devMode: developerMode) {
+ ErrorView(data: error2, devMode: developerMode) {
model.setError(nil)
}.interactiveDismissDisabled()
.background(WalletColors().backgroundColor.edgesIgnoringSafeArea(.all))
@@ -96,8 +96,8 @@ struct MainView: View {
let mainGroup = Group {
switch controller.backendState {
case .ready: mainContent
- case .error: ErrorSheet(title: String(localized: ""),
- copyable: true) {}
+ case .error: ErrorView(title: String(localized: ""),
+ copyable: true) {}
default: // show launch animation until either ready or error
LaunchAnimationView()
}
diff --git a/TalerWallet1/Views/Sheets/ErrorSheet.swift b/TalerWallet1/Views/Sheets/ErrorSheet.swift
@@ -1,125 +0,0 @@
-/*
- * This file is part of GNU Taler, ©2022-25 Taler Systems S.A.
- * See LICENSE.md
- */
-/**
- * @author Iván Ávalos
- */
-import SwiftUI
-import taler_swift
-
-enum ErrorData {
- case message(title: String, message: String)
- case error(Error)
-}
-
-struct ErrorSheet: View {
- var title: String
- var message: String? = nil
- var copyable: Bool
-
- var onDismiss: () -> Void
-
- init(title: String, message: String? = nil, copyable: Bool, onDismiss: @escaping () -> Void) {
- self.title = title
- self.message = message
- self.copyable = copyable
- self.onDismiss = onDismiss
- }
-
- init(error: Error, devMode: Bool, onDismiss: @escaping () -> Void) {
- let walletCoreError = String(localized: "Internal core error")
- let initializationError = String(localized: "Initialization error")
- let serializationError = String(localized: "Serialization error")
- let deserializationError = String(localized: "Deserialization error")
- let unknownError = String(localized: "Unknown error")
-
- switch error {
- case let walletError as WalletBackendError:
- switch walletError {
- case .walletCoreError(let error):
- if let json = error?.toJSON(), devMode {
- self.init(title: walletCoreError, message: json, copyable: true, onDismiss: onDismiss)
- } else if let hint = error?.errorResponse?.hint ?? error?.hint {
- self.init(title: walletCoreError, message: hint, copyable: false, onDismiss: onDismiss)
- } else if let message = error?.message {
- self.init(title: walletCoreError, message: message, copyable: false, onDismiss: onDismiss)
- } else {
- self.init(title: walletCoreError, copyable: false, onDismiss: onDismiss)
- }
- case .initializationError:
- self.init(title: initializationError, copyable: false, onDismiss: onDismiss)
- case .serializationError:
- self.init(title: serializationError, copyable: false, onDismiss: onDismiss)
- case .deserializationError:
- self.init(title: deserializationError, copyable: false, onDismiss: onDismiss)
- }
- default:
- self.init(title: unknownError, message: error.localizedDescription, copyable: false, onDismiss: onDismiss)
- }
- }
-
- init(data: ErrorData, devMode: Bool, onDismiss: @escaping () -> Void) {
- switch data {
- case .message(let title, let message):
- self.init(title: title, message: message, copyable: false, onDismiss: onDismiss)
- case .error(let error):
- self.init(error: error, devMode: devMode, onDismiss: onDismiss)
- }
- }
-
- var body: some View {
- ScrollView {
- VStack {
- Image(systemName: "exclamationmark.circle")
- .resizable()
- .frame(width: 50, height: 50)
- .aspectRatio(contentMode: .fit)
- .foregroundStyle(WalletColors().attention)
- .padding()
-
- Text(title)
- .talerFont(.title)
- .padding(.bottom)
-
- if let message {
- if copyable {
- if #available(iOS 16.4, *) {
- Text(message).monospaced()
- } else {
- Text(message).font(.system(.body, design: .monospaced))
- }
-
- CopyButton(textToCopy: message, vertical: false)
- .accessibilityLabel("Copy the error JSON")
- .padding()
- } else {
- Text(message)
- .multilineTextAlignment(.center)
- }
- }
- }
- }
- .padding()
- .safeAreaInset(edge: .bottom) {
- Button("Close", role: .cancel) {
- onDismiss()
- }
- .buttonStyle(TalerButtonStyle(type: .bordered))
- .padding(.bottom)
- .padding(.horizontal)
- }
- }
-}
-
-struct ErrorSheet_Previews: PreviewProvider {
- static let error = WalletBackendError.walletCoreError(WalletBackendResponseError(
- code: 7025, when: Timestamp.now(),
- hint: "A KYC step is required before withdrawal can proceed",
- message: "A KYC step is required before withdrawal can proceed"))
-
- static var previews: some View {
- ErrorSheet(error: error, devMode: true, onDismiss: {})
- ErrorSheet(error: error, devMode: false, onDismiss: {})
- }
-}
diff --git a/TalerWallet1/Views/Sheets/QRSheet.swift b/TalerWallet1/Views/Sheets/QRSheet.swift
@@ -47,16 +47,16 @@ struct QRSheet: View {
urlToOpen: $urlToOpen)
} else {
// let _ = print(scannedURL) // TODO: error logging
- ErrorSheet(title: String(localized: "Scanned QR is no talerURI"),
- message: scannedURL.absoluteString,
- copyable: true) {
+ ErrorView(title: String(localized: "Scanned QR is no talerURI"),
+ message: scannedURL.absoluteString,
+ copyable: true) {
dismissTop(stack.push())
}
}
} else {
- ErrorSheet(title: String(localized: "Scanned QR is no URL"),
- message: scannedCode,
- copyable: true) {
+ ErrorView(title: String(localized: "Scanned QR is no URL"),
+ message: scannedCode,
+ copyable: true) {
dismissTop(stack.push())
}
}
diff --git a/TalerWallet1/Views/Sheets/Sheet.swift b/TalerWallet1/Views/Sheets/Sheet.swift
@@ -56,7 +56,7 @@ struct Sheet: View {
.accessibilityValue(idString)
}
if let error2 = model.error2 {
- ErrorSheet(data: error2, devMode: developerMode) {
+ ErrorView(data: error2, devMode: developerMode) {
model.setError(nil)
logger.log("ErrorSheet dismissTop")
dismissTop(stack.push())
diff --git a/TalerWallet1/Views/Transactions/TransactionSummaryV.swift b/TalerWallet1/Views/Transactions/TransactionSummaryV.swift
@@ -298,9 +298,9 @@ struct TransactionSummaryV: View {
badge: CONFIRM_BANK)
} } } }
@unknown default:
- ErrorSheet(title: "Unknown withdrawal type", // should not happen, so no L10N
- message: withdrawalDetails.type.rawValue,
- copyable: true) {
+ ErrorView(title: "Unknown withdrawal type", // should not happen, so no L10N
+ message: withdrawalDetails.type.rawValue,
+ copyable: true) {
dismissTop(stack.push())
}
} // switch