From 6e9cf2ba916134ff16c9ca9e83a4c31d1134ec6f Mon Sep 17 00:00:00 2001 From: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com> Date: Fri, 23 Sep 2022 12:51:40 +0100 Subject: [PATCH] ios: fix background refresh crash, memoize migrateChatDatabase (#1103) * ios: fix background refresh crash, memoize migrateChatDatabase * store returned value --- apps/ios/Shared/Model/BGManager.swift | 13 ++++++++----- apps/ios/Shared/Model/ChatModel.swift | 1 + apps/ios/Shared/Model/SimpleXAPI.swift | 1 + apps/ios/Shared/SimpleXApp.swift | 12 +++++++----- .../Views/Database/DatabaseEncryptionView.swift | 1 + apps/ios/Shared/Views/Database/DatabaseView.swift | 1 + apps/ios/SimpleXChat/API.swift | 14 +++++++++----- 7 files changed, 28 insertions(+), 15 deletions(-) diff --git a/apps/ios/Shared/Model/BGManager.swift b/apps/ios/Shared/Model/BGManager.swift index d7267ff8b8..e10012c118 100644 --- a/apps/ios/Shared/Model/BGManager.swift +++ b/apps/ios/Shared/Model/BGManager.swift @@ -82,12 +82,15 @@ class BGManager { } self.completed = false DispatchQueue.main.async { - do { - try initializeChat(start: true) - } catch let error { - fatalError("Failed to start or load chats: \(responseError(error))") + let m = ChatModel.shared + if (!m.chatInitialized) { + do { + try initializeChat(start: true) + } catch let error { + fatalError("Failed to start or load chats: \(responseError(error))") + } } - if ChatModel.shared.currentUser == nil { + if m.currentUser == nil { completeReceiving("no current user") return } diff --git a/apps/ios/Shared/Model/ChatModel.swift b/apps/ios/Shared/Model/ChatModel.swift index 19ba23766f..ad22f27fb8 100644 --- a/apps/ios/Shared/Model/ChatModel.swift +++ b/apps/ios/Shared/Model/ChatModel.swift @@ -16,6 +16,7 @@ final class ChatModel: ObservableObject { @Published var onboardingStage: OnboardingStage? @Published var v3DBMigration: V3DBMigrationState = v3DBMigrationDefault.get() @Published var currentUser: User? + @Published var chatInitialized = false @Published var chatRunning: Bool? @Published var chatDbChanged = false @Published var chatDbEncrypted: Bool? diff --git a/apps/ios/Shared/Model/SimpleXAPI.swift b/apps/ios/Shared/Model/SimpleXAPI.swift index ba66393c63..e67585453d 100644 --- a/apps/ios/Shared/Model/SimpleXAPI.swift +++ b/apps/ios/Shared/Model/SimpleXAPI.swift @@ -734,6 +734,7 @@ func initializeChat(start: Bool, dbKey: String? = nil) throws { let _ = getChatCtrl(dbKey) try apiSetFilesFolder(filesFolder: getAppFilesDirectory().path) try apiSetIncognito(incognito: incognitoGroupDefault.get()) + m.chatInitialized = true m.currentUser = try apiGetActiveUser() if m.currentUser == nil { m.onboardingStage = .step1_SimpleXInfo diff --git a/apps/ios/Shared/SimpleXApp.swift b/apps/ios/Shared/SimpleXApp.swift index 386ae0c431..91f04ee456 100644 --- a/apps/ios/Shared/SimpleXApp.swift +++ b/apps/ios/Shared/SimpleXApp.swift @@ -41,11 +41,13 @@ struct SimpleXApp: App { chatModel.appOpenUrl = url } .onAppear() { - do { - chatModel.v3DBMigration = v3DBMigrationDefault.get() - try initializeChat(start: chatModel.v3DBMigration.startChat) - } catch let error { - fatalError("Failed to start or load chats: \(responseError(error))") + if (!chatModel.chatInitialized) { + do { + chatModel.v3DBMigration = v3DBMigrationDefault.get() + try initializeChat(start: chatModel.v3DBMigration.startChat) + } catch let error { + fatalError("Failed to start or load chats: \(responseError(error))") + } } } .onChange(of: scenePhase) { phase in diff --git a/apps/ios/Shared/Views/Database/DatabaseEncryptionView.swift b/apps/ios/Shared/Views/Database/DatabaseEncryptionView.swift index 0f4b0a14c9..764a44917d 100644 --- a/apps/ios/Shared/Views/Database/DatabaseEncryptionView.swift +++ b/apps/ios/Shared/Views/Database/DatabaseEncryptionView.swift @@ -245,6 +245,7 @@ struct DatabaseEncryptionView: View { private func operationEnded(_ dbAlert: DatabaseEncryptionAlert) async { await MainActor.run { m.chatDbChanged = true + m.chatInitialized = false progressIndicator = false alert = dbAlert } diff --git a/apps/ios/Shared/Views/Database/DatabaseView.swift b/apps/ios/Shared/Views/Database/DatabaseView.swift index a8d6225a22..320a305e50 100644 --- a/apps/ios/Shared/Views/Database/DatabaseView.swift +++ b/apps/ios/Shared/Views/Database/DatabaseView.swift @@ -354,6 +354,7 @@ struct DatabaseView: View { private func operationEnded(_ dbAlert: DatabaseAlert) async { await MainActor.run { m.chatDbChanged = true + m.chatInitialized = false progressIndicator = false alert = dbAlert } diff --git a/apps/ios/SimpleXChat/API.swift b/apps/ios/SimpleXChat/API.swift index 45362a0de7..92d2a5e8aa 100644 --- a/apps/ios/SimpleXChat/API.swift +++ b/apps/ios/SimpleXChat/API.swift @@ -10,6 +10,8 @@ import Foundation private var chatController: chat_ctrl? +private var migrationResult: (Bool, DBMigrationResult)? + public func getChatCtrl(_ useKey: String? = nil) -> chat_ctrl { if let controller = chatController { return controller } let dbPath = getAppDatabasePath().path @@ -23,6 +25,7 @@ public func getChatCtrl(_ useKey: String? = nil) -> chat_ctrl { } public func migrateChatDatabase(_ useKey: String? = nil) -> (Bool, DBMigrationResult) { + if let res = migrationResult { return res } logger.debug("migrateChatDatabase \(storeDBPassphraseGroupDefault.get())") let dbPath = getAppDatabasePath().path var dbKey = "" @@ -42,16 +45,17 @@ public func migrateChatDatabase(_ useKey: String? = nil) -> (Bool, DBMigrationRe var cPath = dbPath.cString(using: .utf8)! var cKey = dbKey.cString(using: .utf8)! let cjson = chat_migrate_db(&cPath, &cKey)! - let res = dbMigrationResult(fromCString(cjson)) + let dbRes = dbMigrationResult(fromCString(cjson)) let encrypted = dbKey != "" - if case .ok = res, useKeychain && encrypted && !setDatabaseKey(dbKey) { - return (encrypted, .errorKeychain) - } - return (encrypted, res) + let keychainErr = dbRes == .ok && useKeychain && encrypted && !setDatabaseKey(dbKey) + let result = (encrypted, keychainErr ? .errorKeychain : dbRes) + migrationResult = result + return result } public func resetChatCtrl() { chatController = nil + migrationResult = nil } public func sendSimpleXCmd(_ cmd: ChatCommand) -> ChatResponse {