From 03b4bea82a3cc571872086b5dff6deb993920467 Mon Sep 17 00:00:00 2001 From: Stanislav Dmitrenko <7953703+avently@users.noreply.github.com> Date: Tue, 6 Sep 2022 21:13:27 +0300 Subject: [PATCH 1/7] ci: script for downloading and unpacking prebuilt aarch64 libs for Android (#864) * Script for downloading and unpacking prebuilt aarch64 libs for Android * set -e * Script for downloading libs supports macOs --- scripts/android/download_libs_aarch64.sh | 33 ++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100755 scripts/android/download_libs_aarch64.sh diff --git a/scripts/android/download_libs_aarch64.sh b/scripts/android/download_libs_aarch64.sh new file mode 100755 index 0000000000..939ac16da8 --- /dev/null +++ b/scripts/android/download_libs_aarch64.sh @@ -0,0 +1,33 @@ +#!/bin/bash + +set -e + +function readlink() { + echo $(cd $(dirname $1); pwd -P) +} + +if [ -z ${1} ]; then + echo "Job repo is unset. Provide it via first argument like: $(readlink $0)/download_libs_aarch64.sh https://something.com/job/something" + exit 1 +fi + +job_repo=$1 +arch="aarch64" +#arch="x86_64" +output_arch="arm64-v8a" +#output_arch="x86_64" + +root_dir="$(dirname $(dirname $(readlink $0)))" +output_dir="$root_dir/apps/android/app/src/main/cpp/libs/$output_arch/" + +mkdir -p "$output_dir" 2> /dev/null + +curl --location -o libsupport.zip $job_repo/simplex-chat-nix-android/$arch-android:lib:support.x86_64-linux/latest/download/1 && \ +unzip -o libsupport.zip && \ +mv libsupport.so "$output_dir" && \ +rm libsupport.zip + +curl --location -o libsimplex.zip $job_repo/simplex-chat-nix-android/$arch-android:lib:simplex-chat.x86_64-linux/latest/download/1 && \ +unzip -o libsimplex.zip && \ +mv libsimplex.so "$output_dir" && \ +rm libsimplex.zip From 65f3fe8afc95208fe7fb12a60d564e87533a7b84 Mon Sep 17 00:00:00 2001 From: Stanislav Dmitrenko <7953703+avently@users.noreply.github.com> Date: Tue, 6 Sep 2022 22:26:52 +0300 Subject: [PATCH 2/7] Fix counter when message is updated (#1023) --- .../java/chat/simplex/app/model/ChatModel.kt | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/apps/android/app/src/main/java/chat/simplex/app/model/ChatModel.kt b/apps/android/app/src/main/java/chat/simplex/app/model/ChatModel.kt index 5d4e8c9040..a9b85c3dc6 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/model/ChatModel.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/model/ChatModel.kt @@ -163,6 +163,10 @@ class ChatModel(val controller: ChatController) { val pItem = chat.chatItems.lastOrNull() if (pItem?.id == cItem.id) { chats[i] = chat.copy(chatItems = arrayListOf(cItem)) + if (pItem.isRcvNew && !cItem.isRcvNew) { + // status changed from New to Read, update counter + decreaseCounterInChat(cInfo.id) + } } res = false } else { @@ -251,6 +255,18 @@ class ChatModel(val controller: ChatController) { return markedRead } + private fun decreaseCounterInChat(chatId: ChatId) { + val chatIndex = getChatIndex(chatId) + if (chatIndex == -1) return + + val chat = chats[chatIndex] + chats[chatIndex] = chat.copy( + chatStats = chat.chatStats.copy( + unreadCount = kotlin.math.max(chat.chatStats.unreadCount - 1, 0), + ) + ) + } + // func popChat(_ id: String) { // if let i = getChatIndex(id) { // popChat_(i) From aa79a3058c11e62b0b2bef6313bb4091953a1011 Mon Sep 17 00:00:00 2001 From: Stanislav Dmitrenko <7953703+avently@users.noreply.github.com> Date: Wed, 7 Sep 2022 12:36:00 +0300 Subject: [PATCH 3/7] android: mute/unmute in a chat menu (#1026) * Mute/unmute in a chat menu * Better naming --- .../simplex/app/views/chat/ChatInfoView.kt | 78 ------------------- .../chat/simplex/app/views/chat/ChatView.kt | 25 +++++- .../app/views/chat/group/GroupChatInfoView.kt | 16 ---- .../app/views/chatlist/ChatListNavLinkView.kt | 32 +++++++- 4 files changed, 55 insertions(+), 96 deletions(-) diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/ChatInfoView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chat/ChatInfoView.kt index 6ed71d2955..dc7deb6b3d 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/chat/ChatInfoView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/chat/ChatInfoView.kt @@ -64,42 +64,10 @@ fun ChatInfoView( }, deleteContact = { deleteContactDialog(chat.chatInfo, chatModel, close) }, clearChat = { clearChatDialog(chat.chatInfo, chatModel, close) }, - changeNtfsState = { enabled -> - changeNtfsState(enabled, chat, chatModel) - }, ) } } -fun changeNtfsState(enabled: Boolean, chat: Chat, chatModel: ChatModel) { - val newChatInfo = when(chat.chatInfo) { - is ChatInfo.Direct -> with (chat.chatInfo) { - ChatInfo.Direct(contact.copy(chatSettings = contact.chatSettings.copy(enableNtfs = enabled))) - } - is ChatInfo.Group -> with(chat.chatInfo) { - ChatInfo.Group(groupInfo.copy(chatSettings = groupInfo.chatSettings.copy(enableNtfs = enabled))) - } - else -> null - } - withApi { - val res = when (newChatInfo) { - is ChatInfo.Direct -> with(newChatInfo) { - chatModel.controller.apiSetSettings(chatType, apiId, contact.chatSettings) - } - is ChatInfo.Group -> with(newChatInfo) { - chatModel.controller.apiSetSettings(chatType, apiId, groupInfo.chatSettings) - } - else -> false - } - if (res && newChatInfo != null) { - chatModel.updateChatInfo(newChatInfo) - if (!enabled) { - chatModel.controller.ntfManager.cancelNotificationsForChat(chat.id) - } - } - } -} - fun deleteContactDialog(chatInfo: ChatInfo, chatModel: ChatModel, close: (() -> Unit)? = null) { AlertManager.shared.showAlertMsg( title = generalGetString(R.string.delete_contact_question), @@ -148,7 +116,6 @@ fun ChatInfoLayout( onLocalAliasChanged: (String) -> Unit, deleteContact: () -> Unit, clearChat: () -> Unit, - changeNtfsState: (Boolean) -> Unit, ) { Column( Modifier @@ -192,18 +159,6 @@ fun ChatInfoLayout( } SectionSpacer() } - - var ntfsEnabled by remember { mutableStateOf(chat.chatInfo.ntfsEnabled) } - SectionView(title = stringResource(R.string.settings_section_title_settings)) { - SectionItemView { - NtfsSwitch(ntfsEnabled) { - ntfsEnabled = !ntfsEnabled - changeNtfsState(ntfsEnabled) - } - } - } - SectionSpacer() - SectionView { SectionItemView { ClearChatButton(clearChat) @@ -350,38 +305,6 @@ fun SimplexServers(text: String, servers: List) { } } -@Composable -fun NtfsSwitch( - ntfsEnabled: Boolean, - toggleNtfs: (Boolean) -> Unit -) { - Row( - Modifier.fillMaxWidth(), - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.SpaceBetween - ) { - Row( - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(8.dp) - ) { - Icon( - Icons.Outlined.Notifications, - stringResource(R.string.notifications), - tint = HighOrLowlight - ) - Text(stringResource(R.string.notifications)) - } - Switch( - checked = ntfsEnabled, - onCheckedChange = toggleNtfs, - colors = SwitchDefaults.colors( - checkedThumbColor = MaterialTheme.colors.primary, - uncheckedThumbColor = HighOrLowlight - ), - ) - } -} - @Composable fun ClearChatButton(clearChat: () -> Unit) { Row( @@ -437,7 +360,6 @@ fun PreviewChatInfoLayout() { ), Contact.sampleData, localAlias = "", - changeNtfsState = {}, developerTools = false, connStats = null, onLocalAliasChanged = {}, diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/ChatView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chat/ChatView.kt index c7c8c06d03..695a8148e1 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/chat/ChatView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/chat/ChatView.kt @@ -216,6 +216,7 @@ fun ChatView(chatModel: ChatModel) { ) } }, + changeNtfsState = { enabled, currentValue -> changeNtfsStatePerChat(enabled, currentValue, chat, chatModel) }, onSearchValueChanged = { value -> if (searchText.value == value) return@ChatLayout val c = chatModel.getChat(chat.chatInfo.id) ?: return@ChatLayout @@ -253,6 +254,7 @@ fun ChatLayout( acceptCall: (Contact) -> Unit, addMembers: (GroupInfo) -> Unit, markRead: (CC.ItemRange, unreadCountAfter: Int?) -> Unit, + changeNtfsState: (Boolean, currentValue: MutableState) -> Unit, onSearchValueChanged: (String) -> Unit, ) { Surface( @@ -279,7 +281,7 @@ fun ChatLayout( } Scaffold( - topBar = { ChatInfoToolbar(chat, back, info, startCall, addMembers, onSearchValueChanged) }, + topBar = { ChatInfoToolbar(chat, back, info, startCall, addMembers, changeNtfsState, onSearchValueChanged) }, bottomBar = composeView, modifier = Modifier.navigationBarsWithImePadding(), floatingActionButton = { floatingButton.value() }, @@ -304,8 +306,10 @@ fun ChatInfoToolbar( info: () -> Unit, startCall: (CallMediaType) -> Unit, addMembers: (GroupInfo) -> Unit, + changeNtfsState: (Boolean, currentValue: MutableState) -> Unit, onSearchValueChanged: (String) -> Unit, ) { + val scope = rememberCoroutineScope() var showMenu by rememberSaveable { mutableStateOf(false) } var showSearch by rememberSaveable { mutableStateOf(false) } val onBackClicked = { @@ -351,6 +355,23 @@ fun ChatInfoToolbar( } } } + + val ntfsEnabled = remember { mutableStateOf(chat.chatInfo.ntfsEnabled) } + menuItems.add { + ItemAction( + if (ntfsEnabled.value) stringResource(R.string.mute_chat) else stringResource(R.string.unmute_chat), + if (ntfsEnabled.value) Icons.Outlined.NotificationsOff else Icons.Outlined.Notifications, + onClick = { + showMenu = false + // Just to make a delay before changing state of ntfsEnabled, otherwise it will redraw menu item with new value before closing the menu + scope.launch { + delay(200) + changeNtfsState(!ntfsEnabled.value, ntfsEnabled) + } + } + ) + } + barButtons.add { IconButton({ showMenu = true }) { Icon(Icons.Default.MoreVert, stringResource(R.string.icon_descr_more_button), tint = MaterialTheme.colors.primary) @@ -839,6 +860,7 @@ fun PreviewChatLayout() { acceptCall = { _ -> }, addMembers = { _ -> }, markRead = { _, _ -> }, + changeNtfsState = { _, _ -> }, onSearchValueChanged = {}, ) } @@ -896,6 +918,7 @@ fun PreviewGroupChatLayout() { acceptCall = { _ -> }, addMembers = { _ -> }, markRead = { _, _ -> }, + changeNtfsState = { _, _ -> }, onSearchValueChanged = {}, ) } diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/GroupChatInfoView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/GroupChatInfoView.kt index 587b3f40aa..e76ef8db3d 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/GroupChatInfoView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/GroupChatInfoView.kt @@ -75,9 +75,6 @@ fun GroupChatInfoView(chatModel: ChatModel, close: () -> Unit) { deleteGroup = { deleteGroupDialog(chat.chatInfo, chatModel, close) }, clearChat = { clearChatDialog(chat.chatInfo, chatModel, close) }, leaveGroup = { leaveGroupDialog(groupInfo, chatModel, close) }, - changeNtfsState = { enabled -> - changeNtfsState(enabled, chat, chatModel) - }, ) } } @@ -127,7 +124,6 @@ fun GroupChatInfoLayout( deleteGroup: () -> Unit, clearChat: () -> Unit, leaveGroup: () -> Unit, - changeNtfsState: (Boolean) -> Unit, ) { Column( Modifier @@ -162,17 +158,6 @@ fun GroupChatInfoLayout( } SectionSpacer() - var ntfsEnabled by remember { mutableStateOf(chat.chatInfo.ntfsEnabled) } - SectionView(title = stringResource(R.string.settings_section_title_settings)) { - SectionItemView { - NtfsSwitch(ntfsEnabled) { - ntfsEnabled = !ntfsEnabled - changeNtfsState(ntfsEnabled) - } - } - } - SectionSpacer() - SectionView { if (groupInfo.canEdit) { SectionItemView { @@ -367,7 +352,6 @@ fun PreviewGroupChatInfoLayout() { members = listOf(GroupMember.sampleData, GroupMember.sampleData, GroupMember.sampleData), developerTools = false, addMembers = {}, showMemberInfo = {}, editGroupProfile = {}, deleteGroup = {}, clearChat = {}, leaveGroup = {}, - changeNtfsState = {}, ) } } diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ChatListNavLinkView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ChatListNavLinkView.kt index b8f4d8b1e4..8754c098eb 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ChatListNavLinkView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ChatListNavLinkView.kt @@ -168,7 +168,7 @@ fun ToggleNotificationsChatAction(chat: Chat, chatModel: ChatModel, ntfsEnabled: if (ntfsEnabled) stringResource(R.string.mute_chat) else stringResource(R.string.unmute_chat), if (ntfsEnabled) Icons.Outlined.NotificationsOff else Icons.Outlined.Notifications, onClick = { - changeNtfsState(!ntfsEnabled, chat, chatModel) + changeNtfsStatePerChat(!ntfsEnabled, mutableStateOf(ntfsEnabled), chat, chatModel) showMenu.value = false } ) @@ -424,6 +424,36 @@ fun groupInvitationAcceptedAlert() { ) } +fun changeNtfsStatePerChat(enabled: Boolean, currentState: MutableState, chat: Chat, chatModel: ChatModel) { + val newChatInfo = when(chat.chatInfo) { + is ChatInfo.Direct -> with (chat.chatInfo) { + ChatInfo.Direct(contact.copy(chatSettings = contact.chatSettings.copy(enableNtfs = enabled))) + } + is ChatInfo.Group -> with(chat.chatInfo) { + ChatInfo.Group(groupInfo.copy(chatSettings = groupInfo.chatSettings.copy(enableNtfs = enabled))) + } + else -> null + } + withApi { + val res = when (newChatInfo) { + is ChatInfo.Direct -> with(newChatInfo) { + chatModel.controller.apiSetSettings(chatType, apiId, contact.chatSettings) + } + is ChatInfo.Group -> with(newChatInfo) { + chatModel.controller.apiSetSettings(chatType, apiId, groupInfo.chatSettings) + } + else -> false + } + if (res && newChatInfo != null) { + chatModel.updateChatInfo(newChatInfo) + if (!enabled) { + chatModel.controller.ntfManager.cancelNotificationsForChat(chat.id) + } + currentState.value = enabled + } + } +} + @Composable fun ChatListNavLinkLayout( chatLinkPreview: @Composable () -> Unit, From 3f5ca84c84d64f78bdd470491fdbbc105c9ce32c Mon Sep 17 00:00:00 2001 From: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com> Date: Wed, 7 Sep 2022 17:20:47 +0100 Subject: [PATCH 4/7] core: fix error reporting of sqlcipher export errors (#1029) --- src/Simplex/Chat/Archive.hs | 17 +++++++++-------- src/Simplex/Chat/View.hs | 5 +++++ tests/ChatTests.hs | 2 ++ 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/src/Simplex/Chat/Archive.hs b/src/Simplex/Chat/Archive.hs index 86c2176f67..f4bcc5ca46 100644 --- a/src/Simplex/Chat/Archive.hs +++ b/src/Simplex/Chat/Archive.hs @@ -15,6 +15,7 @@ where import qualified Codec.Archive.Zip as Z import Control.Monad.Except import Control.Monad.Reader +import Data.Functor (($>)) import qualified Data.Text as T import qualified Database.SQLite3 as SQL import Simplex.Chat.Controller @@ -123,16 +124,16 @@ sqlCipherExport DBEncryptionConfig {currentKey = DBEncryptionKey key, newKey = D atomically $ writeTVar dbEnc $ not (null key') where withDB a err = - liftIO (bracket (SQL.open $ T.pack f) SQL.close a) - `catch` (\(e :: SQL.SQLError) -> log' e >> checkSQLError e) - `catch` (\(e :: SomeException) -> log' e >> throwSQLError e) + liftIO (bracket (SQL.open $ T.pack f) SQL.close a $> Nothing) + `catch` checkSQLError + `catch` (\(e :: SomeException) -> sqliteError' e) + >>= mapM_ (throwDBError . err) where - log' e = liftIO . putStrLn $ "Database error: " <> show e checkSQLError e = case SQL.sqlError e of - SQL.ErrorNotADatabase -> throwDBError $ err SQLiteErrorNotADatabase - _ -> throwSQLError e - throwSQLError :: Show e => e -> m () - throwSQLError = throwDBError . err . SQLiteError . show + SQL.ErrorNotADatabase -> pure $ Just SQLiteErrorNotADatabase + _ -> sqliteError' e + sqliteError' :: Show e => e -> m (Maybe SQLiteError) + sqliteError' = pure . Just . SQLiteError . show exportSQL = T.unlines $ keySQL key diff --git a/src/Simplex/Chat/View.hs b/src/Simplex/Chat/View.hs index 7fa7d0ac34..fbf9878c65 100644 --- a/src/Simplex/Chat/View.hs +++ b/src/Simplex/Chat/View.hs @@ -946,6 +946,8 @@ viewChatError = \case ChatErrorDatabase err -> case err of DBErrorEncrypted -> ["error: chat database is already encrypted"] DBErrorPlaintext -> ["error: chat database is not encrypted"] + DBErrorExport e -> ["error encrypting database: " <> sqliteError' e] + DBErrorOpen e -> ["error opening database after encryption: " <> sqliteError' e] e -> ["chat database error: " <> sShow e] ChatErrorAgent err -> case err of SMP SMP.AUTH -> @@ -958,6 +960,9 @@ viewChatError = \case e -> ["smp agent error: " <> sShow e] where fileNotFound fileId = ["file " <> sShow fileId <> " not found"] + sqliteError' = \case + SQLiteErrorNotADatabase -> "wrong passphrase or invalid database file" + SQLiteError e -> sShow e ttyContact :: ContactName -> StyledString ttyContact = styled $ colored Green diff --git a/tests/ChatTests.hs b/tests/ChatTests.hs index 6a6ea4ac74..983258fd44 100644 --- a/tests/ChatTests.hs +++ b/tests/ChatTests.hs @@ -2788,6 +2788,8 @@ testDatabaseEncryption = withTmpFiles $ do testChatWorking alice bob alice ##> "/_stop" alice <## "chat stopped" + alice ##> "/db password wrongkey nextkey" + alice <## "error encrypting database: wrong passphrase or invalid database file" alice ##> "/db password mykey nextkey" alice <## "ok" alice ##> "/_db encryption {\"currentKey\":\"nextkey\",\"newKey\":\"anotherkey\"}" From 05417fd1e871f07eff0cf4cfb4d7e386fa07f7d1 Mon Sep 17 00:00:00 2001 From: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com> Date: Wed, 7 Sep 2022 17:23:24 +0100 Subject: [PATCH 5/7] nix: ls androidPkgs --- flake.nix | 2 ++ 1 file changed, 2 insertions(+) diff --git a/flake.nix b/flake.nix index f47f53636f..a56a295d3b 100644 --- a/flake.nix +++ b/flake.nix @@ -116,6 +116,8 @@ # find ${androidPkgs.gmp6.override { withStatic = true; }}/lib -name "*.a" -exec cp {} $out/_pkg \; # find ${androidIconv}/lib -name "*.a" -exec cp {} $out/_pkg \; # find ${androidPkgs.stdenv.cc.libc}/lib -name "*.a" -exec cp {} $out/_pkg \; + echo "androidPkgs" + ls -lha ${androidPkgs} find ${androidPkgs.openssl.out}/lib -name "*.so" -exec cp {} $out/_pkg \; ${pkgs.patchelf}/bin/patchelf --remove-needed libunwind.so.1 $out/_pkg/libsimplex.so From 80976112078d5040d2689817ad574eb91fcd7779 Mon Sep 17 00:00:00 2001 From: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com> Date: Wed, 7 Sep 2022 20:06:16 +0100 Subject: [PATCH 6/7] ios: NSE without passphrase in keychain (#1030) --- apps/ios/Shared/Model/ChatModel.swift | 2 ++ apps/ios/Shared/Model/SuspendChat.swift | 18 ++++++++++------- apps/ios/Shared/SimpleXApp.swift | 2 +- .../ios/SimpleX NSE/NotificationService.swift | 20 +++++++++++++------ apps/ios/SimpleXChat/Notifications.swift | 20 +++++++++++++++++++ 5 files changed, 48 insertions(+), 14 deletions(-) diff --git a/apps/ios/Shared/Model/ChatModel.swift b/apps/ios/Shared/Model/ChatModel.swift index d349294a0f..19ba23766f 100644 --- a/apps/ios/Shared/Model/ChatModel.swift +++ b/apps/ios/Shared/Model/ChatModel.swift @@ -53,6 +53,8 @@ final class ChatModel: ObservableObject { static let shared = ChatModel() + static var ok: Bool { ChatModel.shared.chatDbStatus == .ok } + func hasChat(_ id: String) -> Bool { chats.first(where: { $0.id == id }) != nil } diff --git a/apps/ios/Shared/Model/SuspendChat.swift b/apps/ios/Shared/Model/SuspendChat.swift index 33ad5af8ed..499dbbb1f7 100644 --- a/apps/ios/Shared/Model/SuspendChat.swift +++ b/apps/ios/Shared/Model/SuspendChat.swift @@ -19,10 +19,14 @@ let bgSuspendTimeout: Int = 5 // seconds let terminationTimeout: Int = 3 // seconds private func _suspendChat(timeout: Int) { - appStateGroupDefault.set(.suspending) - apiSuspendChat(timeoutMicroseconds: timeout * 1000000) - let endTask = beginBGTask(chatSuspended) - DispatchQueue.global().asyncAfter(deadline: .now() + Double(timeout) + 1, execute: endTask) + if ChatModel.ok { + appStateGroupDefault.set(.suspending) + apiSuspendChat(timeoutMicroseconds: timeout * 1000000) + let endTask = beginBGTask(chatSuspended) + DispatchQueue.global().asyncAfter(deadline: .now() + Double(timeout) + 1, execute: endTask) + } else { + appStateGroupDefault.set(.suspended) + } } func suspendChat() { @@ -47,7 +51,7 @@ func terminateChat() { case .suspending: // suspend instantly if already suspending _chatSuspended() - apiSuspendChat(timeoutMicroseconds: 0) + if ChatModel.ok { apiSuspendChat(timeoutMicroseconds: 0) } case .stopped: () default: _suspendChat(timeout: terminationTimeout) @@ -71,9 +75,9 @@ private func _chatSuspended() { } } -func activateChat(appState: AppState = .active, databaseReady: Bool = true) { +func activateChat(appState: AppState = .active) { suspendLockQueue.sync { appStateGroupDefault.set(appState) - if databaseReady { apiActivateChat() } + if ChatModel.ok { apiActivateChat() } } } diff --git a/apps/ios/Shared/SimpleXApp.swift b/apps/ios/Shared/SimpleXApp.swift index 6061e7ce52..386ae0c431 100644 --- a/apps/ios/Shared/SimpleXApp.swift +++ b/apps/ios/Shared/SimpleXApp.swift @@ -64,7 +64,7 @@ struct SimpleXApp: App { ChatReceiver.shared.start() } let appState = appStateGroupDefault.get() - activateChat(databaseReady: chatModel.chatDbStatus == .ok) + activateChat() if appState.inactive && chatModel.chatRunning == true { updateChats() updateCallInvitations() diff --git a/apps/ios/SimpleX NSE/NotificationService.swift b/apps/ios/SimpleX NSE/NotificationService.swift index 969645e45f..0e8ebd852c 100644 --- a/apps/ios/SimpleX NSE/NotificationService.swift +++ b/apps/ios/SimpleX NSE/NotificationService.swift @@ -105,9 +105,9 @@ class NotificationService: UNNotificationServiceExtension { if let ntfData = userInfo["notificationData"] as? [AnyHashable : Any], let nonce = ntfData["nonce"] as? String, let encNtfInfo = ntfData["message"] as? String, - let _ = startChat() { - logger.debug("NotificationService: receiveNtfMessages: chat is started") - if let ntfMsgInfo = apiGetNtfMessage(nonce: nonce, encNtfInfo: encNtfInfo) { + let dbStatus = startChat() { + if case .ok = dbStatus, + let ntfMsgInfo = apiGetNtfMessage(nonce: nonce, encNtfInfo: encNtfInfo) { logger.debug("NotificationService: receiveNtfMessages: apiGetNtfMessage \(String(describing: ntfMsgInfo), privacy: .public)") if let connEntity = ntfMsgInfo.connEntity { setBestAttemptNtf(createConnectionEventNtf(connEntity)) @@ -118,9 +118,11 @@ class NotificationService: UNNotificationServiceExtension { await PendingNtfs.shared.readStream(id, for: self, msgCount: ntfMsgInfo.ntfMessages.count) deliverBestAttemptNtf() } + return } } - return + } else { + setBestAttemptNtf(createErrorNtf(dbStatus)) } } deliverBestAttemptNtf() @@ -151,20 +153,26 @@ class NotificationService: UNNotificationServiceExtension { } } -func startChat() -> User? { +var chatStarted = false + +func startChat() -> DBMigrationResult? { hs_init(0, nil) + if chatStarted { return .ok } + let (_, dbStatus) = migrateChatDatabase() + if dbStatus != .ok { return dbStatus } if let user = apiGetActiveUser() { logger.debug("active user \(String(describing: user))") do { try setNetworkConfig(getNetCfg()) let justStarted = try apiStartChat() + chatStarted = true if justStarted { try apiSetFilesFolder(filesFolder: getAppFilesDirectory().path) try apiSetIncognito(incognito: incognitoGroupDefault.get()) chatLastStartGroupDefault.set(Date.now) Task { await receiveMessages() } } - return user + return .ok } catch { logger.error("NotificationService startChat error: \(responseError(error), privacy: .public)") } diff --git a/apps/ios/SimpleXChat/Notifications.swift b/apps/ios/SimpleXChat/Notifications.swift index 2a4a1f6b75..6432b36506 100644 --- a/apps/ios/SimpleXChat/Notifications.swift +++ b/apps/ios/SimpleXChat/Notifications.swift @@ -119,6 +119,26 @@ public func createConnectionEventNtf(_ connEntity: ConnectionEntity) -> UNMutabl ) } +public func createErrorNtf(_ dbStatus: DBMigrationResult) -> UNMutableNotificationContent { + var title: String + switch dbStatus { + case .errorNotADatabase: + title = NSLocalizedString("Encrypted message: no passphrase", comment: "notification") + case .error: + title = NSLocalizedString("Encrypted message: database error", comment: "notification") + case .errorKeychain: + title = NSLocalizedString("Encrypted message: keychain error", comment: "notification") + case .unknown: + title = NSLocalizedString("Encrypted message: unexpexted error", comment: "notification") + case .ok: + title = NSLocalizedString("Encrypted message or another event", comment: "notification") + } + return createNotification( + categoryIdentifier: ntfCategoryConnectionEvent, + title: title + ) +} + private func groupMsgNtfTitle(_ groupInfo: GroupInfo, _ groupMember: GroupMember, hideContent: Bool) -> String { hideContent ? NSLocalizedString("Group message:", comment: "notification") From 22ee465d3b5c0f6a0b5cc8b9868d422d4c005581 Mon Sep 17 00:00:00 2001 From: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com> Date: Thu, 8 Sep 2022 07:35:32 +0100 Subject: [PATCH 7/7] nix: update to rename libs dependencies and to remove libunwind from .so files --- flake.nix | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/flake.nix b/flake.nix index a56a295d3b..eac09fc197 100644 --- a/flake.nix +++ b/flake.nix @@ -116,11 +116,25 @@ # find ${androidPkgs.gmp6.override { withStatic = true; }}/lib -name "*.a" -exec cp {} $out/_pkg \; # find ${androidIconv}/lib -name "*.a" -exec cp {} $out/_pkg \; # find ${androidPkgs.stdenv.cc.libc}/lib -name "*.a" -exec cp {} $out/_pkg \; - echo "androidPkgs" - ls -lha ${androidPkgs} + echo ${androidPkgs.openssl} find ${androidPkgs.openssl.out}/lib -name "*.so" -exec cp {} $out/_pkg \; - ${pkgs.patchelf}/bin/patchelf --remove-needed libunwind.so.1 $out/_pkg/libsimplex.so + # remove the .1 and other version suffixes from .so's. Androids linker + # doesn't play nice with them. + for lib in $out/_pkg/*.so; do + for dep in $(${pkgs.patchelf}/bin/patchelf --print-needed "$lib"); do + if [[ "''${dep##*.so}" ]]; then + echo "$lib : $dep -> ''${dep%%.so*}.so" + chmod +w "$lib" + ${pkgs.patchelf}/bin/patchelf --replace-needed "$dep" "''${dep%%.so*}.so" "$lib" + fi + done + done + + for lib in $out/_pkg/*.so; do + chmod +w "$lib" + ${pkgs.patchelf}/bin/patchelf --remove-needed libunwind.so "$lib" + done ${pkgs.tree}/bin/tree $out/_pkg (cd $out/_pkg; ${pkgs.zip}/bin/zip -r -9 $out/pkg-aarch64-android-libsimplex.zip *)