From bcdf08488ec2e1837db94696a06b7c85aafd74d0 Mon Sep 17 00:00:00 2001 From: Stanislav Dmitrenko <7953703+avently@users.noreply.github.com> Date: Sun, 22 Dec 2024 23:18:45 +0700 Subject: [PATCH] ios: show alert when import database is failed or succeeded (#5400) * ios: show alert when import database is failed or succeeded * don't hide error alert until pressing Ok * always skip starting chat in case of import error * changes * defer --- .../Shared/Views/Database/DatabaseView.swift | 19 ++++++++++++------- .../Views/Migration/MigrateToDevice.swift | 17 ++++++++++++++++- 2 files changed, 28 insertions(+), 8 deletions(-) diff --git a/apps/ios/Shared/Views/Database/DatabaseView.swift b/apps/ios/Shared/Views/Database/DatabaseView.swift index 4a367f7722..4c05434eb6 100644 --- a/apps/ios/Shared/Views/Database/DatabaseView.swift +++ b/apps/ios/Shared/Views/Database/DatabaseView.swift @@ -262,8 +262,7 @@ struct DatabaseView: View { message: Text("Your current chat database will be DELETED and REPLACED with the imported one.") + Text("This action cannot be undone - your profile, contacts, messages and files will be irreversibly lost."), primaryButton: .destructive(Text("Import")) { stopChatRunBlockStartChat(m.chatRunning == false, $progressIndicator) { - _ = await DatabaseView.importArchive(fileURL, $progressIndicator, $alert) - return true + await DatabaseView.importArchive(fileURL, $progressIndicator, $alert, false) } }, secondaryButton: .cancel() @@ -467,9 +466,13 @@ struct DatabaseView: View { static func importArchive( _ archivePath: URL, _ progressIndicator: Binding, - _ alert: Binding + _ alert: Binding, + _ migration: Bool ) async -> Bool { if archivePath.startAccessingSecurityScopedResource() { + defer { + archivePath.stopAccessingSecurityScopedResource() + } await MainActor.run { progressIndicator.wrappedValue = true } @@ -483,17 +486,17 @@ struct DatabaseView: View { _ = kcDatabasePassword.remove() if archiveErrors.isEmpty { await operationEnded(.archiveImported, progressIndicator, alert) + return true } else { await operationEnded(.archiveImportedWithErrors(archiveErrors: archiveErrors), progressIndicator, alert) + return migration } - return true } catch let error { await operationEnded(.error(title: "Error importing chat database", error: responseError(error)), progressIndicator, alert) } } catch let error { await operationEnded(.error(title: "Error deleting chat database", error: responseError(error)), progressIndicator, alert) } - archivePath.stopAccessingSecurityScopedResource() } else { showAlert("Error accessing database file") } @@ -542,6 +545,8 @@ struct DatabaseView: View { } else if case .chatDeleted = dbAlert { let (title, message) = chatDeletedAlertText() showAlert(title, message: message, actions: { [okAlertActionWaiting] }) + } else if case let .error(title, error) = dbAlert { + showAlert("\(title)", message: error, actions: { [okAlertActionWaiting] }) } else { alert.wrappedValue = dbAlert cont.resume() @@ -587,13 +592,13 @@ struct DatabaseView: View { } } -private func archiveImportedAlertText() -> (String, String) { +func archiveImportedAlertText() -> (String, String) { ( NSLocalizedString("Chat database imported", comment: ""), NSLocalizedString("Restart the app to use imported chat database", comment: "") ) } -private func archiveImportedWithErrorsAlertText(errs: [ArchiveError]) -> (String, String) { +func archiveImportedWithErrorsAlertText(errs: [ArchiveError]) -> (String, String) { ( NSLocalizedString("Chat database imported", comment: ""), NSLocalizedString("Restart the app to use imported chat database", comment: "") + "\n" + NSLocalizedString("Some non-fatal errors occurred during import:", comment: "") + archiveErrorsText(errs) diff --git a/apps/ios/Shared/Views/Migration/MigrateToDevice.swift b/apps/ios/Shared/Views/Migration/MigrateToDevice.swift index 763cd473fe..2d83cdc7c8 100644 --- a/apps/ios/Shared/Views/Migration/MigrateToDevice.swift +++ b/apps/ios/Shared/Views/Migration/MigrateToDevice.swift @@ -96,6 +96,7 @@ struct MigrateToDevice: View { @Binding var migrationState: MigrationToState? @State private var useKeychain = storeDBPassphraseGroupDefault.get() @State private var alert: MigrateToDeviceViewAlert? + @State private var databaseAlert: DatabaseAlert? = nil private let tempDatabaseUrl = urlForTemporaryDatabase() @State private var chatReceiver: MigrationChatReceiver? = nil // Prevent from hiding the view until migration is finished or app deleted @@ -178,6 +179,20 @@ struct MigrateToDevice: View { return Alert(title: Text(title), message: Text(error)) } } + .alert(item: $databaseAlert) { item in + switch item { + case .archiveImported: + let (title, message) = archiveImportedAlertText() + return Alert(title: Text(title), message: Text(message)) + case let .archiveImportedWithErrors(errs): + let (title, message) = archiveImportedWithErrorsAlertText(errs: errs) + return Alert(title: Text(title), message: Text(message)) + case let .error(title, error): + return Alert(title: Text(title), message: Text(error)) + default: // not expected this branch to be called because this alert is used only for importArchive purpose + return Alert(title: Text("Error")) + } + } .interactiveDismissDisabled(backDisabled) } @@ -243,7 +258,7 @@ struct MigrateToDevice: View { ) { result in if case let .success(files) = result, let fileURL = files.first { Task { - let success = await DatabaseView.importArchive(fileURL, $importingArchiveFromFileProgressIndicator, Binding.constant(nil)) + let success = await DatabaseView.importArchive(fileURL, $importingArchiveFromFileProgressIndicator, $databaseAlert, true) if success { DatabaseView.startChat( Binding.constant(false),