From 6ff5e7cf234353826dc368d5e9effd7c24bfe76e Mon Sep 17 00:00:00 2001 From: Evgeny Poberezkin Date: Sun, 22 Dec 2024 10:23:45 +0000 Subject: [PATCH 1/4] readme: update --- README.md | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index ad70c350e4..936667da8c 100644 --- a/README.md +++ b/README.md @@ -163,13 +163,14 @@ Your donations help us raise more funds - any amount, even the price of the cup It is possible to donate via: - [GitHub](https://github.com/sponsors/simplex-chat) (commission-free) or [OpenCollective](https://opencollective.com/simplex-chat) (~10% commission). -- Bitcoin: bc1qd74rc032ek2knhhr3yjq2ajzc5enz3h4qwnxad -- Monero: 8568eeVjaJ1RQ65ZUn9PRQ8ENtqeX9VVhcCYYhnVLxhV4JtBqw42so2VEUDQZNkFfsH5sXCuV7FN8VhRQ21DkNibTZP57Qt +- BTC: bc1q2gy6f02nn6vvcxs0pnu29tpnpyz0qf66505d4u +- XMR: 8568eeVjaJ1RQ65ZUn9PRQ8ENtqeX9VVhcCYYhnVLxhV4JtBqw42so2VEUDQZNkFfsH5sXCuV7FN8VhRQ21DkNibTZP57Qt - BCH: bitcoincash:qq6c8vfvxqrk6rhdysgvkhqc24sggkfsx5nqvdlqcg -- Ethereum: 0xD9ee7Db0AD0dc1Dfa7eD53290199ED06beA04692 -- USDT: - - Ethereum: 0xD9ee7Db0AD0dc1Dfa7eD53290199ED06beA04692 -- Solana: 7JCf5m3TiHmYKZVr6jCu1KeZVtb9Y1jRMQDU69p5ARnu +- ETH: 0xD9ee7Db0AD0dc1Dfa7eD53290199ED06beA04692 +- USDT (Ethereum): 0xD9ee7Db0AD0dc1Dfa7eD53290199ED06beA04692 +- ZEC: t1fwjQW5gpFhDqXNhxqDWyF9j9WeKvVS5Jg +- DOGE: D99pV4n9TrPxBPCkQGx4w4SMSa6QjRBxPf +- SOL: 7JCf5m3TiHmYKZVr6jCu1KeZVtb9Y1jRMQDU69p5ARnu - please ask if you want to donate any other coins. Thank you, From 3fead10ea266b4af416b452621fb9071be041153 Mon Sep 17 00:00:00 2001 From: Stanislav Dmitrenko <7953703+avently@users.noreply.github.com> Date: Sun, 22 Dec 2024 23:19:05 +0700 Subject: [PATCH 2/4] android, desktop: show alert when import database is failed or succeeded (#5402) --- .../chat/simplex/common/views/database/DatabaseView.kt | 7 ++++--- .../chat/simplex/common/views/migration/MigrateToDevice.kt | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/database/DatabaseView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/database/DatabaseView.kt index bf59524a06..28772f01d3 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/database/DatabaseView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/database/DatabaseView.kt @@ -60,8 +60,7 @@ fun DatabaseView() { if (to != null) { importArchiveAlert { stopChatRunBlockStartChat(stopped, chatLastStart, progressIndicator) { - importArchive(to, appFilesCountAndSize, progressIndicator) - true + importArchive(to, appFilesCountAndSize, progressIndicator, false) } } } @@ -645,6 +644,7 @@ suspend fun importArchive( importedArchiveURI: URI, appFilesCountAndSize: MutableState>, progressIndicator: MutableState, + migration: Boolean ): Boolean { val m = chatModel progressIndicator.value = true @@ -666,12 +666,13 @@ suspend fun importArchive( if (chatModel.localUserCreated.value == false) { chatModel.chatRunning.value = false } + return true } else { operationEnded(m, progressIndicator) { showArchiveImportedWithErrorsAlert(archiveErrors) } + return migration } - return true } catch (e: Error) { operationEnded(m, progressIndicator) { AlertManager.shared.showAlertMsg(generalGetString(MR.strings.error_importing_database), e.toString()) diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/migration/MigrateToDevice.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/migration/MigrateToDevice.kt index 788c07a9d2..6baa4952b4 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/migration/MigrateToDevice.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/migration/MigrateToDevice.kt @@ -239,7 +239,7 @@ private fun ArchiveImportView(progressIndicator: MutableState, close: ( val importArchiveLauncher = rememberFileChooserLauncher(true) { to: URI? -> if (to != null) { withLongRunningApi { - val success = importArchive(to, mutableStateOf(0 to 0), progressIndicator) + val success = importArchive(to, mutableStateOf(0 to 0), progressIndicator, true) if (success) { startChat( chatModel, From 9c87b8782c604a100250aa229e22fd34a5e36ebe Mon Sep 17 00:00:00 2001 From: Stanislav Dmitrenko <7953703+avently@users.noreply.github.com> Date: Sun, 22 Dec 2024 23:22:36 +0700 Subject: [PATCH 3/4] android, desktop: update message successfully if it's the same (#5404) --- .../commonMain/kotlin/chat/simplex/common/model/SimpleXAPI.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/SimpleXAPI.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/SimpleXAPI.kt index e95fdb446f..08051927fd 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/SimpleXAPI.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/SimpleXAPI.kt @@ -968,6 +968,7 @@ object ChatController { val r = sendCmd(rh, CC.ApiUpdateChatItem(type, id, itemId, mc, live)) when { r is CR.ChatItemUpdated -> return r.chatItem + r is CR.ChatItemNotChanged -> return r.chatItem r is CR.ChatCmdError && r.chatError is ChatError.ChatErrorStore && r.chatError.storeError is StoreError.LargeMsg -> { AlertManager.shared.showAlertMsg( generalGetString(MR.strings.maximum_message_size_title), From 8c90a96d789c51d4d801aeffd1b4912d5061b646 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 4/4] 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),