Improve error message handling with user-friendly messages
- Add ErrorMessageParser in Kotlin and Swift to detect network errors and technical messages, replacing them with human-readable text - Update all ViewModels to use ErrorMessageParser.parse() for error display - Remove redundant error popup from LoginView (error shows inline only) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -9,23 +9,58 @@ import kotlinx.serialization.json.jsonPrimitive
|
||||
*/
|
||||
object ErrorMessageParser {
|
||||
|
||||
// Network/connection error patterns to detect
|
||||
private val networkErrorPatterns = listOf(
|
||||
"Could not connect to the server" to "Unable to connect to the server. Please check your internet connection.",
|
||||
"NSURLErrorDomain" to "Unable to connect to the server. Please check your internet connection.",
|
||||
"UnresolvedAddressException" to "Unable to connect to the server. Please check your internet connection.",
|
||||
"ConnectException" to "Unable to connect to the server. Please check your internet connection.",
|
||||
"SocketTimeoutException" to "Request timed out. Please try again.",
|
||||
"TimeoutException" to "Request timed out. Please try again.",
|
||||
"No address associated" to "Unable to connect to the server. Please check your internet connection.",
|
||||
"Network is unreachable" to "No internet connection. Please check your network settings.",
|
||||
"Connection refused" to "Unable to connect to the server. The server may be down.",
|
||||
"Connection reset" to "Connection was interrupted. Please try again.",
|
||||
"SSLHandshakeException" to "Secure connection failed. Please try again.",
|
||||
"CertificateException" to "Secure connection failed. Please try again.",
|
||||
"UnknownHostException" to "Unable to connect to the server. Please check your internet connection.",
|
||||
"java.net.SocketException" to "Connection error. Please try again.",
|
||||
"CFNetwork" to "Unable to connect to the server. Please check your internet connection.",
|
||||
"kCFStreamError" to "Unable to connect to the server. Please check your internet connection.",
|
||||
"Code=-1004" to "Unable to connect to the server. Please check your internet connection.",
|
||||
"Code=-1009" to "No internet connection. Please check your network settings.",
|
||||
"Code=-1001" to "Request timed out. Please try again."
|
||||
)
|
||||
|
||||
/**
|
||||
* Parses error messages to extract user-friendly text
|
||||
* If the error message is JSON, extract relevant error details
|
||||
* @param rawMessage The raw error message from the API
|
||||
* Handles network errors, JSON error responses, and raw error messages
|
||||
* @param rawMessage The raw error message from the API or exception
|
||||
* @return A user-friendly error message
|
||||
*/
|
||||
fun parse(rawMessage: String): String {
|
||||
val trimmed = rawMessage.trim()
|
||||
|
||||
// Check if the message looks like JSON (starts with { or [)
|
||||
if (!trimmed.startsWith("{") && !trimmed.startsWith("[")) {
|
||||
// Not JSON, return as-is
|
||||
return rawMessage
|
||||
// Check for network/connection errors first (these are technical messages from exceptions)
|
||||
for ((pattern, friendlyMessage) in networkErrorPatterns) {
|
||||
if (trimmed.contains(pattern, ignoreCase = true)) {
|
||||
return friendlyMessage
|
||||
}
|
||||
}
|
||||
|
||||
// If it's JSON, it's not meant for user display
|
||||
// Try to parse and extract meaningful error info
|
||||
// Check if it looks like a technical exception message
|
||||
if (isTechnicalError(trimmed)) {
|
||||
return "Something went wrong. Please try again."
|
||||
}
|
||||
|
||||
// Check if the message looks like JSON (starts with { or [)
|
||||
if (!trimmed.startsWith("{") && !trimmed.startsWith("[")) {
|
||||
// Not JSON - if it's a short, readable message, return it
|
||||
// Otherwise return a generic message
|
||||
return if (isUserFriendly(trimmed)) trimmed else "Something went wrong. Please try again."
|
||||
}
|
||||
|
||||
// If it's JSON, try to parse and extract meaningful error info
|
||||
return try {
|
||||
val jsonElement = Json.parseToJsonElement(trimmed)
|
||||
|
||||
@@ -51,4 +86,37 @@ object ErrorMessageParser {
|
||||
"An error occurred. Please try again."
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the message looks like a technical/developer error (stack trace, exception, etc)
|
||||
*/
|
||||
private fun isTechnicalError(message: String): Boolean {
|
||||
val technicalIndicators = listOf(
|
||||
"Exception",
|
||||
"Error Domain=",
|
||||
"UserInfo=",
|
||||
"at com.",
|
||||
"at org.",
|
||||
"at java.",
|
||||
"at kotlin.",
|
||||
"at io.",
|
||||
"Caused by:",
|
||||
"Stack trace:",
|
||||
".kt:",
|
||||
".java:",
|
||||
"0x",
|
||||
"Code=",
|
||||
"interface:",
|
||||
"LocalDataTask"
|
||||
)
|
||||
return technicalIndicators.any { message.contains(it, ignoreCase = true) }
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a message is user-friendly (short, no technical jargon)
|
||||
*/
|
||||
private fun isUserFriendly(message: String): Boolean {
|
||||
// If it's short and doesn't contain technical indicators, it's probably user-friendly
|
||||
return message.length < 200 && !isTechnicalError(message)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -126,7 +126,7 @@ class ContractorSharingManager: ObservableObject {
|
||||
completion(false)
|
||||
}
|
||||
} catch {
|
||||
self.importError = error.localizedDescription
|
||||
self.importError = ErrorMessageParser.parse(error.localizedDescription)
|
||||
self.isImporting = false
|
||||
completion(false)
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ class ContractorViewModel: ObservableObject {
|
||||
self.isLoading = false
|
||||
}
|
||||
} catch {
|
||||
self.errorMessage = error.localizedDescription
|
||||
self.errorMessage = ErrorMessageParser.parse(error.localizedDescription)
|
||||
self.isLoading = false
|
||||
}
|
||||
}
|
||||
@@ -79,7 +79,7 @@ class ContractorViewModel: ObservableObject {
|
||||
self.isLoading = false
|
||||
}
|
||||
} catch {
|
||||
self.errorMessage = error.localizedDescription
|
||||
self.errorMessage = ErrorMessageParser.parse(error.localizedDescription)
|
||||
self.isLoading = false
|
||||
}
|
||||
}
|
||||
@@ -104,7 +104,7 @@ class ContractorViewModel: ObservableObject {
|
||||
completion(false)
|
||||
}
|
||||
} catch {
|
||||
self.errorMessage = error.localizedDescription
|
||||
self.errorMessage = ErrorMessageParser.parse(error.localizedDescription)
|
||||
self.isCreating = false
|
||||
completion(false)
|
||||
}
|
||||
@@ -130,7 +130,7 @@ class ContractorViewModel: ObservableObject {
|
||||
completion(false)
|
||||
}
|
||||
} catch {
|
||||
self.errorMessage = error.localizedDescription
|
||||
self.errorMessage = ErrorMessageParser.parse(error.localizedDescription)
|
||||
self.isUpdating = false
|
||||
completion(false)
|
||||
}
|
||||
@@ -156,7 +156,7 @@ class ContractorViewModel: ObservableObject {
|
||||
completion(false)
|
||||
}
|
||||
} catch {
|
||||
self.errorMessage = error.localizedDescription
|
||||
self.errorMessage = ErrorMessageParser.parse(error.localizedDescription)
|
||||
self.isDeleting = false
|
||||
completion(false)
|
||||
}
|
||||
@@ -176,7 +176,7 @@ class ContractorViewModel: ObservableObject {
|
||||
completion(false)
|
||||
}
|
||||
} catch {
|
||||
self.errorMessage = error.localizedDescription
|
||||
self.errorMessage = ErrorMessageParser.parse(error.localizedDescription)
|
||||
completion(false)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@ class DocumentViewModel: ObservableObject {
|
||||
self.isLoading = false
|
||||
}
|
||||
} catch {
|
||||
self.errorMessage = error.localizedDescription
|
||||
self.errorMessage = ErrorMessageParser.parse(error.localizedDescription)
|
||||
self.isLoading = false
|
||||
}
|
||||
}
|
||||
@@ -135,7 +135,7 @@ class DocumentViewModel: ObservableObject {
|
||||
completion(false, self.errorMessage)
|
||||
}
|
||||
} catch {
|
||||
self.errorMessage = error.localizedDescription
|
||||
self.errorMessage = ErrorMessageParser.parse(error.localizedDescription)
|
||||
self.isLoading = false
|
||||
completion(false, self.errorMessage)
|
||||
}
|
||||
@@ -203,7 +203,7 @@ class DocumentViewModel: ObservableObject {
|
||||
completion(false, self.errorMessage)
|
||||
}
|
||||
} catch {
|
||||
self.errorMessage = error.localizedDescription
|
||||
self.errorMessage = ErrorMessageParser.parse(error.localizedDescription)
|
||||
self.isLoading = false
|
||||
completion(false, self.errorMessage)
|
||||
}
|
||||
@@ -228,7 +228,7 @@ class DocumentViewModel: ObservableObject {
|
||||
completion(false)
|
||||
}
|
||||
} catch {
|
||||
self.errorMessage = error.localizedDescription
|
||||
self.errorMessage = ErrorMessageParser.parse(error.localizedDescription)
|
||||
self.isLoading = false
|
||||
completion(false)
|
||||
}
|
||||
|
||||
@@ -1,22 +1,82 @@
|
||||
import Foundation
|
||||
|
||||
/// Utility for parsing and cleaning error messages from API responses
|
||||
/// Utility for parsing and cleaning error messages from API responses and network errors
|
||||
enum ErrorMessageParser {
|
||||
|
||||
// Network/connection error patterns to detect
|
||||
private static let networkErrorPatterns: [(pattern: String, message: String)] = [
|
||||
("Could not connect to the server", "Unable to connect to the server. Please check your internet connection."),
|
||||
("NSURLErrorDomain", "Unable to connect to the server. Please check your internet connection."),
|
||||
("The Internet connection appears to be offline", "No internet connection. Please check your network settings."),
|
||||
("A server with the specified hostname could not be found", "Unable to connect to the server. Please check your internet connection."),
|
||||
("The request timed out", "Request timed out. Please try again."),
|
||||
("The network connection was lost", "Connection was interrupted. Please try again."),
|
||||
("An SSL error has occurred", "Secure connection failed. Please try again."),
|
||||
("CFNetwork", "Unable to connect to the server. Please check your internet connection."),
|
||||
("kCFStreamError", "Unable to connect to the server. Please check your internet connection."),
|
||||
("Code=-1004", "Unable to connect to the server. Please check your internet connection."),
|
||||
("Code=-1009", "No internet connection. Please check your network settings."),
|
||||
("Code=-1001", "Request timed out. Please try again."),
|
||||
("Code=-1003", "Unable to connect to the server. Please check your internet connection."),
|
||||
("Code=-1005", "Connection was interrupted. Please try again."),
|
||||
("Code=-1200", "Secure connection failed. Please try again."),
|
||||
("UnresolvedAddressException", "Unable to connect to the server. Please check your internet connection."),
|
||||
("ConnectException", "Unable to connect to the server. Please check your internet connection."),
|
||||
("SocketTimeoutException", "Request timed out. Please try again."),
|
||||
("Connection refused", "Unable to connect to the server. The server may be down."),
|
||||
("Connection reset", "Connection was interrupted. Please try again.")
|
||||
]
|
||||
|
||||
// Indicators that a message is technical/developer-facing
|
||||
private static let technicalIndicators = [
|
||||
"Exception",
|
||||
"Error Domain=",
|
||||
"UserInfo=",
|
||||
"at com.",
|
||||
"at org.",
|
||||
"at java.",
|
||||
"at kotlin.",
|
||||
"at io.",
|
||||
"Caused by:",
|
||||
"Stack trace:",
|
||||
".kt:",
|
||||
".java:",
|
||||
".swift:",
|
||||
"0x",
|
||||
"Code=",
|
||||
"interface:",
|
||||
"LocalDataTask",
|
||||
"NSUnderlyingError",
|
||||
"_kCF"
|
||||
]
|
||||
|
||||
/// Parses error messages to extract user-friendly text
|
||||
/// If the error message is JSON, extract relevant error details
|
||||
/// - Parameter rawMessage: The raw error message from the API
|
||||
/// Handles network errors, JSON error responses, and raw error messages
|
||||
/// - Parameter rawMessage: The raw error message from the API or exception
|
||||
/// - Returns: A user-friendly error message
|
||||
static func parse(_ rawMessage: String) -> String {
|
||||
// Check if the message looks like JSON (starts with { or [)
|
||||
let trimmed = rawMessage.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
guard trimmed.hasPrefix("{") || trimmed.hasPrefix("[") else {
|
||||
// Not JSON, return as-is
|
||||
return rawMessage
|
||||
|
||||
// Check for network/connection errors first (these are technical messages from exceptions)
|
||||
for (pattern, friendlyMessage) in networkErrorPatterns {
|
||||
if trimmed.localizedCaseInsensitiveContains(pattern) {
|
||||
return friendlyMessage
|
||||
}
|
||||
}
|
||||
|
||||
// If it's JSON, it's not meant for user display
|
||||
// Try to parse and extract meaningful error info
|
||||
// Check if it looks like a technical exception message
|
||||
if isTechnicalError(trimmed) {
|
||||
return "Something went wrong. Please try again."
|
||||
}
|
||||
|
||||
// Check if the message looks like JSON (starts with { or [)
|
||||
guard trimmed.hasPrefix("{") || trimmed.hasPrefix("[") else {
|
||||
// Not JSON - if it's a short, readable message, return it
|
||||
// Otherwise return a generic message
|
||||
return isUserFriendly(trimmed) ? trimmed : "Something went wrong. Please try again."
|
||||
}
|
||||
|
||||
// If it's JSON, try to parse and extract meaningful error info
|
||||
guard let data = trimmed.data(using: .utf8) else {
|
||||
return "An error occurred. Please try again."
|
||||
}
|
||||
@@ -47,4 +107,15 @@ enum ErrorMessageParser {
|
||||
// If we couldn't parse or extract a message, return a generic error
|
||||
return "An error occurred. Please try again."
|
||||
}
|
||||
|
||||
/// Checks if the message looks like a technical/developer error (stack trace, exception, etc)
|
||||
private static func isTechnicalError(_ message: String) -> Bool {
|
||||
return technicalIndicators.contains { message.localizedCaseInsensitiveContains($0) }
|
||||
}
|
||||
|
||||
/// Checks if a message is user-friendly (short, no technical jargon)
|
||||
private static func isUserFriendly(_ message: String) -> Bool {
|
||||
// If it's short and doesn't contain technical indicators, it's probably user-friendly
|
||||
return message.count < 200 && !isTechnicalError(message)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,7 +65,7 @@ class AppleSignInViewModel: ObservableObject {
|
||||
}
|
||||
} catch {
|
||||
self.isLoading = false
|
||||
self.errorMessage = error.localizedDescription
|
||||
self.errorMessage = ErrorMessageParser.parse(error.localizedDescription)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -115,7 +115,7 @@ class AppleSignInViewModel: ObservableObject {
|
||||
}
|
||||
errorMessage = appleError.errorDescription
|
||||
} else {
|
||||
errorMessage = error.localizedDescription
|
||||
errorMessage = ErrorMessageParser.parse(error.localizedDescription)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -352,10 +352,6 @@ struct LoginView: View {
|
||||
showPasswordReset = true
|
||||
}
|
||||
}
|
||||
.handleErrors(
|
||||
error: viewModel.errorMessage,
|
||||
onRetry: { viewModel.login() }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -97,7 +97,7 @@ class LoginViewModel: ObservableObject {
|
||||
}
|
||||
} catch {
|
||||
self.isLoading = false
|
||||
self.errorMessage = error.localizedDescription
|
||||
self.errorMessage = ErrorMessageParser.parse(error.localizedDescription)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,7 +69,7 @@ class PasswordResetViewModel: ObservableObject {
|
||||
}
|
||||
} catch {
|
||||
self.isLoading = false
|
||||
self.errorMessage = error.localizedDescription
|
||||
self.errorMessage = ErrorMessageParser.parse(error.localizedDescription)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -106,7 +106,7 @@ class PasswordResetViewModel: ObservableObject {
|
||||
}
|
||||
} catch {
|
||||
self.isLoading = false
|
||||
self.errorMessage = error.localizedDescription
|
||||
self.errorMessage = ErrorMessageParser.parse(error.localizedDescription)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -155,7 +155,7 @@ class PasswordResetViewModel: ObservableObject {
|
||||
}
|
||||
} catch {
|
||||
self.isLoading = false
|
||||
self.errorMessage = error.localizedDescription
|
||||
self.errorMessage = ErrorMessageParser.parse(error.localizedDescription)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -382,7 +382,7 @@ class NotificationPreferencesViewModelWrapper: ObservableObject {
|
||||
self.isLoading = false
|
||||
}
|
||||
} catch {
|
||||
self.errorMessage = error.localizedDescription
|
||||
self.errorMessage = ErrorMessageParser.parse(error.localizedDescription)
|
||||
self.isLoading = false
|
||||
}
|
||||
}
|
||||
@@ -435,7 +435,7 @@ class NotificationPreferencesViewModelWrapper: ObservableObject {
|
||||
self.isSaving = false
|
||||
}
|
||||
} catch {
|
||||
self.errorMessage = error.localizedDescription
|
||||
self.errorMessage = ErrorMessageParser.parse(error.localizedDescription)
|
||||
self.isSaving = false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,7 +71,7 @@ class ProfileViewModel: ObservableObject {
|
||||
self.isLoadingUser = false
|
||||
}
|
||||
} catch {
|
||||
self.errorMessage = error.localizedDescription
|
||||
self.errorMessage = ErrorMessageParser.parse(error.localizedDescription)
|
||||
self.isLoadingUser = false
|
||||
}
|
||||
}
|
||||
@@ -113,7 +113,7 @@ class ProfileViewModel: ObservableObject {
|
||||
}
|
||||
} catch {
|
||||
self.isLoading = false
|
||||
self.errorMessage = error.localizedDescription
|
||||
self.errorMessage = ErrorMessageParser.parse(error.localizedDescription)
|
||||
self.successMessage = nil
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,7 +76,7 @@ class RegisterViewModel: ObservableObject {
|
||||
self.isLoading = false
|
||||
}
|
||||
} catch {
|
||||
self.errorMessage = error.localizedDescription
|
||||
self.errorMessage = ErrorMessageParser.parse(error.localizedDescription)
|
||||
self.isLoading = false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,7 +112,7 @@ struct ManageUsersView: View {
|
||||
}
|
||||
} catch {
|
||||
await MainActor.run {
|
||||
self.errorMessage = error.localizedDescription
|
||||
self.errorMessage = ErrorMessageParser.parse(error.localizedDescription)
|
||||
self.isLoading = false
|
||||
}
|
||||
}
|
||||
@@ -162,7 +162,7 @@ struct ManageUsersView: View {
|
||||
}
|
||||
} catch {
|
||||
await MainActor.run {
|
||||
self.errorMessage = error.localizedDescription
|
||||
self.errorMessage = ErrorMessageParser.parse(error.localizedDescription)
|
||||
self.isGeneratingCode = false
|
||||
}
|
||||
}
|
||||
@@ -188,7 +188,7 @@ struct ManageUsersView: View {
|
||||
}
|
||||
} catch {
|
||||
await MainActor.run {
|
||||
self.errorMessage = error.localizedDescription
|
||||
self.errorMessage = ErrorMessageParser.parse(error.localizedDescription)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -468,7 +468,7 @@ private extension ResidenceDetailView {
|
||||
} catch {
|
||||
await MainActor.run {
|
||||
self.isDeleting = false
|
||||
self.viewModel.errorMessage = error.localizedDescription
|
||||
self.viewModel.errorMessage = ErrorMessageParser.parse(error.localizedDescription)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -500,7 +500,7 @@ private extension ResidenceDetailView {
|
||||
}
|
||||
} catch {
|
||||
await MainActor.run {
|
||||
self.contractorsError = error.localizedDescription
|
||||
self.contractorsError = ErrorMessageParser.parse(error.localizedDescription)
|
||||
self.isLoadingContractors = false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -151,7 +151,7 @@ class ResidenceSharingManager: ObservableObject {
|
||||
completion(false)
|
||||
}
|
||||
} catch {
|
||||
self.errorMessage = error.localizedDescription
|
||||
self.errorMessage = ErrorMessageParser.parse(error.localizedDescription)
|
||||
self.isImporting = false
|
||||
completion(false)
|
||||
}
|
||||
|
||||
@@ -75,7 +75,7 @@ class ResidenceViewModel: ObservableObject {
|
||||
}
|
||||
self.isLoading = false
|
||||
} catch {
|
||||
self.errorMessage = error.localizedDescription
|
||||
self.errorMessage = ErrorMessageParser.parse(error.localizedDescription)
|
||||
self.isLoading = false
|
||||
}
|
||||
}
|
||||
@@ -105,7 +105,7 @@ class ResidenceViewModel: ObservableObject {
|
||||
self.isLoading = false
|
||||
}
|
||||
} catch {
|
||||
self.errorMessage = error.localizedDescription
|
||||
self.errorMessage = ErrorMessageParser.parse(error.localizedDescription)
|
||||
self.isLoading = false
|
||||
}
|
||||
}
|
||||
@@ -127,7 +127,7 @@ class ResidenceViewModel: ObservableObject {
|
||||
self.isLoading = false
|
||||
}
|
||||
} catch {
|
||||
self.errorMessage = error.localizedDescription
|
||||
self.errorMessage = ErrorMessageParser.parse(error.localizedDescription)
|
||||
self.isLoading = false
|
||||
}
|
||||
}
|
||||
@@ -176,7 +176,7 @@ class ResidenceViewModel: ObservableObject {
|
||||
} catch {
|
||||
print("🏠 ResidenceVM: Exception: \(error)")
|
||||
await MainActor.run {
|
||||
self.errorMessage = error.localizedDescription
|
||||
self.errorMessage = ErrorMessageParser.parse(error.localizedDescription)
|
||||
self.isLoading = false
|
||||
completion(nil)
|
||||
}
|
||||
@@ -205,7 +205,7 @@ class ResidenceViewModel: ObservableObject {
|
||||
completion(false)
|
||||
}
|
||||
} catch {
|
||||
self.errorMessage = error.localizedDescription
|
||||
self.errorMessage = ErrorMessageParser.parse(error.localizedDescription)
|
||||
self.isLoading = false
|
||||
completion(false)
|
||||
}
|
||||
@@ -228,7 +228,7 @@ class ResidenceViewModel: ObservableObject {
|
||||
self.isGeneratingReport = false
|
||||
}
|
||||
} catch {
|
||||
self.reportMessage = error.localizedDescription
|
||||
self.reportMessage = ErrorMessageParser.parse(error.localizedDescription)
|
||||
self.isGeneratingReport = false
|
||||
}
|
||||
}
|
||||
@@ -263,7 +263,7 @@ class ResidenceViewModel: ObservableObject {
|
||||
completion(false)
|
||||
}
|
||||
} catch {
|
||||
self.errorMessage = error.localizedDescription
|
||||
self.errorMessage = ErrorMessageParser.parse(error.localizedDescription)
|
||||
self.isLoading = false
|
||||
completion(false)
|
||||
}
|
||||
|
||||
@@ -85,7 +85,7 @@ class TaskViewModel: ObservableObject {
|
||||
}
|
||||
} catch {
|
||||
self.actionState = .error(.create, error.localizedDescription)
|
||||
self.errorMessage = error.localizedDescription
|
||||
self.errorMessage = ErrorMessageParser.parse(error.localizedDescription)
|
||||
completion(false)
|
||||
}
|
||||
}
|
||||
@@ -112,7 +112,7 @@ class TaskViewModel: ObservableObject {
|
||||
}
|
||||
} catch {
|
||||
self.actionState = .error(.cancel, error.localizedDescription)
|
||||
self.errorMessage = error.localizedDescription
|
||||
self.errorMessage = ErrorMessageParser.parse(error.localizedDescription)
|
||||
completion(false)
|
||||
}
|
||||
}
|
||||
@@ -136,7 +136,7 @@ class TaskViewModel: ObservableObject {
|
||||
}
|
||||
} catch {
|
||||
self.actionState = .error(.uncancel, error.localizedDescription)
|
||||
self.errorMessage = error.localizedDescription
|
||||
self.errorMessage = ErrorMessageParser.parse(error.localizedDescription)
|
||||
completion(false)
|
||||
}
|
||||
}
|
||||
@@ -160,7 +160,7 @@ class TaskViewModel: ObservableObject {
|
||||
}
|
||||
} catch {
|
||||
self.actionState = .error(.markInProgress, error.localizedDescription)
|
||||
self.errorMessage = error.localizedDescription
|
||||
self.errorMessage = ErrorMessageParser.parse(error.localizedDescription)
|
||||
completion(false)
|
||||
}
|
||||
}
|
||||
@@ -184,7 +184,7 @@ class TaskViewModel: ObservableObject {
|
||||
}
|
||||
} catch {
|
||||
self.actionState = .error(.archive, error.localizedDescription)
|
||||
self.errorMessage = error.localizedDescription
|
||||
self.errorMessage = ErrorMessageParser.parse(error.localizedDescription)
|
||||
completion(false)
|
||||
}
|
||||
}
|
||||
@@ -208,7 +208,7 @@ class TaskViewModel: ObservableObject {
|
||||
}
|
||||
} catch {
|
||||
self.actionState = .error(.unarchive, error.localizedDescription)
|
||||
self.errorMessage = error.localizedDescription
|
||||
self.errorMessage = ErrorMessageParser.parse(error.localizedDescription)
|
||||
completion(false)
|
||||
}
|
||||
}
|
||||
@@ -232,7 +232,7 @@ class TaskViewModel: ObservableObject {
|
||||
}
|
||||
} catch {
|
||||
self.actionState = .error(.update, error.localizedDescription)
|
||||
self.errorMessage = error.localizedDescription
|
||||
self.errorMessage = ErrorMessageParser.parse(error.localizedDescription)
|
||||
completion(false)
|
||||
}
|
||||
}
|
||||
@@ -268,7 +268,7 @@ class TaskViewModel: ObservableObject {
|
||||
self.isLoadingCompletions = false
|
||||
}
|
||||
} catch {
|
||||
self.completionsError = error.localizedDescription
|
||||
self.completionsError = ErrorMessageParser.parse(error.localizedDescription)
|
||||
self.isLoadingCompletions = false
|
||||
}
|
||||
}
|
||||
@@ -360,7 +360,7 @@ class TaskViewModel: ObservableObject {
|
||||
}
|
||||
} catch {
|
||||
await MainActor.run {
|
||||
self.tasksError = error.localizedDescription
|
||||
self.tasksError = ErrorMessageParser.parse(error.localizedDescription)
|
||||
self.isLoadingTasks = false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ class VerifyEmailViewModel: ObservableObject {
|
||||
self.isLoading = false
|
||||
}
|
||||
} catch {
|
||||
self.errorMessage = error.localizedDescription
|
||||
self.errorMessage = ErrorMessageParser.parse(error.localizedDescription)
|
||||
self.isLoading = false
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user