diff --git a/apps/android/app/build.gradle b/apps/android/app/build.gradle index dd89c25fd..2fd984a2b 100644 --- a/apps/android/app/build.gradle +++ b/apps/android/app/build.gradle @@ -11,8 +11,8 @@ android { applicationId "chat.simplex.app" minSdk 29 targetSdk 32 - versionCode 33 - versionName "2.1.0" + versionCode 34 + versionName "2.1.1" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" ndk { diff --git a/apps/android/app/src/main/java/chat/simplex/app/MainActivity.kt b/apps/android/app/src/main/java/chat/simplex/app/MainActivity.kt index 11ef98ff2..5f301f0fa 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/MainActivity.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/MainActivity.kt @@ -40,6 +40,7 @@ class MainActivity: ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // testJson() + processNotificationIntent(intent, vm.chatModel) setContent { SimpleXTheme { Surface( @@ -105,11 +106,11 @@ fun MainPage(chatModel: ChatModel) { } } -fun processIntent(intent: Intent?, chatModel: ChatModel) { +fun processNotificationIntent(intent: Intent?, chatModel: ChatModel) { when (intent?.action) { NtfManager.OpenChatAction -> { val chatId = intent.getStringExtra("chatId") - Log.d(TAG, "processIntent: OpenChatAction $chatId") + Log.d(TAG, "processNotificationIntent: OpenChatAction $chatId") if (chatId != null) { val cInfo = chatModel.getChat(chatId)?.chatInfo chatModel.clearOverlays.value = true @@ -117,9 +118,15 @@ fun processIntent(intent: Intent?, chatModel: ChatModel) { } } NtfManager.ShowChatsAction -> { - Log.d(TAG, "processIntent: ShowChatsAction") + Log.d(TAG, "processNotificationIntent: ShowChatsAction") + chatModel.chatId.value = null chatModel.clearOverlays.value = true } + } +} + +fun processIntent(intent: Intent?, chatModel: ChatModel) { + when (intent?.action) { "android.intent.action.VIEW" -> { val uri = intent.data if (uri != null) connectIfOpenedViaUri(uri, chatModel) diff --git a/apps/android/app/src/main/java/chat/simplex/app/model/SimpleXAPI.kt b/apps/android/app/src/main/java/chat/simplex/app/model/SimpleXAPI.kt index 93f18e060..21f5722e0 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/model/SimpleXAPI.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/model/SimpleXAPI.kt @@ -34,7 +34,7 @@ import kotlin.concurrent.thread typealias ChatCtrl = Long -open class ChatController(private val ctrl: ChatCtrl, private val ntfManager: NtfManager, val appContext: Context) { +open class ChatController(private val ctrl: ChatCtrl, val ntfManager: NtfManager, val appContext: Context) { var chatModel = ChatModel(this) private val sharedPreferences: SharedPreferences = appContext.getSharedPreferences(SHARED_PREFS_ID, Context.MODE_PRIVATE) @@ -85,10 +85,6 @@ open class ChatController(private val ctrl: ChatCtrl, private val ntfManager: Nt return false } - fun cancelNotificationsForChat(chatId: String) { - ntfManager.cancelNotificationsForChat(chatId) - } - suspend fun sendCmd(cmd: CC): CR { return withContext(Dispatchers.IO) { val c = cmd.cmdString 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 7e083d4d5..50ac85621 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 @@ -35,7 +35,7 @@ fun ChatInfoView(chatModel: ChatModel, close: () -> Unit) { } } -fun deleteContactDialog(chatInfo: ChatInfo, chatModel: ChatModel, close: () -> Unit) { +fun deleteContactDialog(chatInfo: ChatInfo, chatModel: ChatModel, close: (() -> Unit)? = null) { AlertManager.shared.showAlertMsg( title = generalGetString(R.string.delete_contact__question), text = generalGetString(R.string.delete_contact_all_messages_deleted_cannot_undo_warning), @@ -46,14 +46,15 @@ fun deleteContactDialog(chatInfo: ChatInfo, chatModel: ChatModel, close: () -> U if (r) { chatModel.removeChat(chatInfo.id) chatModel.chatId.value = null - close() + chatModel.controller.ntfManager.cancelNotificationsForChat(chatInfo.id) + close?.invoke() } } } ) } -fun clearChatDialog(chatInfo: ChatInfo, chatModel: ChatModel, close: () -> Unit) { +fun clearChatDialog(chatInfo: ChatInfo, chatModel: ChatModel, close: (() -> Unit)? = null) { AlertManager.shared.showAlertMsg( title = generalGetString(R.string.clear_chat_question), text = generalGetString(R.string.clear_chat_warning), @@ -63,7 +64,8 @@ fun clearChatDialog(chatInfo: ChatInfo, chatModel: ChatModel, close: () -> Unit) val updatedChatInfo = chatModel.controller.apiClearChat(chatInfo.chatType, chatInfo.apiId) if (updatedChatInfo != null) { chatModel.clearChat(updatedChatInfo) - close() + chatModel.controller.ntfManager.cancelNotificationsForChat(chatInfo.id) + close?.invoke() } } } 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 8642d79f3..5f353069c 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 @@ -59,7 +59,7 @@ fun ChatView(chatModel: ChatModel) { delay(750L) if (chat.chatItems.isNotEmpty()) { chatModel.markChatItemsRead(chat.chatInfo) - chatModel.controller.cancelNotificationsForChat(chat.id) + chatModel.controller.ntfManager.cancelNotificationsForChat(chat.id) withApi { chatModel.controller.apiChatRead( chat.chatInfo.chatType, 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 47ab21d00..35faab717 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 @@ -16,6 +16,8 @@ import androidx.compose.ui.unit.dp import chat.simplex.app.R import chat.simplex.app.model.* import chat.simplex.app.ui.theme.SimpleXTheme +import chat.simplex.app.views.chat.clearChatDialog +import chat.simplex.app.views.chat.deleteContactDialog import chat.simplex.app.views.chat.item.ItemAction import chat.simplex.app.views.helpers.* import kotlinx.coroutines.delay @@ -90,6 +92,7 @@ fun ContactMenuItems(chat: Chat, chatModel: ChatModel, showMenu: MutableStateОтклонить - Очистить разговор? + Очистить чат? Все сообщения будут удалены - это действие нельзя отменить! Сообщения будут удалены только для вас. Очистить - Очистить разговор + Очистить чат Прочитано diff --git a/apps/android/app/src/main/res/values/strings.xml b/apps/android/app/src/main/res/values/strings.xml index 868e7f72b..3996718c6 100644 --- a/apps/android/app/src/main/res/values/strings.xml +++ b/apps/android/app/src/main/res/values/strings.xml @@ -170,10 +170,10 @@ Reject - Clear conversation? + Clear chat? All messages will be deleted - this cannot be undone! The messages will be deleted ONLY for you. Clear - Clear conversation + Clear chat Mark read diff --git a/blog/20220511-simplex-chat-v2-images-files.md b/blog/20220511-simplex-chat-v2-images-files.md index 0a0b9bfd6..f7c3a263e 100644 --- a/blog/20220511-simplex-chat-v2-images-files.md +++ b/blog/20220511-simplex-chat-v2-images-files.md @@ -33,3 +33,5 @@ Once you install the app, you can connect to anybody: 1. Create your local chat profile - it is not shared with SimpleX servers. It is local to your devices, and it will be shared with your contacts only when you connect. 2. To make a private connection, you need to create a one-time connection link or a QR code via the app. You can show the QR code to your contact in person or via a video call - this is the most secure way to create a connection - or you can share the link via any other channel. Only one user can connect via this link. 3. Once another user scans the QR code or opens the app via the link the connection will be created and you can send end-to-end encrypted messages privately, without anybody knowing you are connected. + +Make a private connection diff --git a/blog/20220524-simplex-chat-better-privacy.md b/blog/20220524-simplex-chat-better-privacy.md new file mode 100644 index 000000000..3a5658640 --- /dev/null +++ b/blog/20220524-simplex-chat-better-privacy.md @@ -0,0 +1,17 @@ +# SimpleX Chat v2.1 - better conversation privacy + +**Published:** May 24, 2022 + +## New in version 2.1 - clearing conversations without deleting contacts + +In this version you can irreversibly delete individual messages after they were deleted by a sender, and also completely clear the conversation. + +The only way to do it before this version was by deleting the contact, now you can keep the connection when you clear the conversation. + + + +See [v1 announcement](./20220112-simplex-chat-v1-released.md) for information on how SimpleX protects the security of the messages. + +See [v2 announcement](./20220511-simplex-chat-v2-images-files.md) for more information about SimpleX platform and how it works. + +Read about SimpleX design in [whitepaper](https://github.com/simplex-chat/simplexmq/blob/master/protocol/overview-tjr.md). diff --git a/blog/README.md b/blog/README.md index 5f60c93c0..75ea1fcc2 100644 --- a/blog/README.md +++ b/blog/README.md @@ -1,5 +1,7 @@ # Blog +May 24, 2022 [Clearing messages for better conversation privacy](./20220524-simplex-chat-better-privacy.md) + May 11, 2022 [Sending images and files in mobile apps](./20220511-simplex-chat-v2-images-files.md) Apr 04, 2022 [Instant notifications for SimpleX Chat mobile apps](./20220404-simplex-chat-instant-notifications.md) diff --git a/blog/images/20220524-clear-chat1.png b/blog/images/20220524-clear-chat1.png new file mode 100644 index 000000000..832084d60 Binary files /dev/null and b/blog/images/20220524-clear-chat1.png differ diff --git a/blog/images/20220524-clear-chat2.png b/blog/images/20220524-clear-chat2.png new file mode 100644 index 000000000..8035cb717 Binary files /dev/null and b/blog/images/20220524-clear-chat2.png differ