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 b32b2bb276..2435f012bd 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 @@ -100,9 +100,14 @@ fun processIntent(intent: Intent?, chatModel: ChatModel) { Log.d(TAG, "processIntent: OpenChatAction $chatId") if (chatId != null) { val cInfo = chatModel.getChat(chatId)?.chatInfo + chatModel.clearOverlays.value = true if (cInfo != null) withApi { openChat(chatModel, cInfo) } } } + NtfManager.ShowChatsAction -> { + Log.d(TAG, "processIntent: ShowChatsAction") + chatModel.clearOverlays.value = true + } "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/ChatModel.kt b/apps/android/app/src/main/java/chat/simplex/app/model/ChatModel.kt index 3eb4ddedfa..cbf3880903 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 @@ -27,6 +27,10 @@ class ChatModel(val controller: ChatController) { var terminalItems = mutableStateListOf() var userAddress = mutableStateOf(null) var userSMPServers = mutableStateOf<(List)?>(null) + + // set when app opened from external intent + var clearOverlays = mutableStateOf(false) + // set when app is opened via contact or invitation URI var appOpenUrl = mutableStateOf(null) var runServiceInBackground = mutableStateOf(true) diff --git a/apps/android/app/src/main/java/chat/simplex/app/model/NtfManager.kt b/apps/android/app/src/main/java/chat/simplex/app/model/NtfManager.kt index d95da55ccc..2d83c79d50 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/model/NtfManager.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/model/NtfManager.kt @@ -14,6 +14,7 @@ class NtfManager(val context: Context) { const val MessageChannel: String = "chat.simplex.app.MESSAGE_NOTIFICATION" const val MessageGroup: String = "chat.simplex.app.MESSAGE_NOTIFICATION" const val OpenChatAction: String = "chat.simplex.app.OPEN_CHAT" + const val ShowChatsAction: String = "chat.simplex.app.SHOW_CHATS" } private val manager: NotificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager @@ -28,6 +29,18 @@ class NtfManager(val context: Context) { )) } + fun cancelNotificationsForChat(chatId: String) { + prevNtfTime.remove(chatId) + manager.cancel(chatId.hashCode()) + val msgNtfs = manager.activeNotifications.filter { + ntf -> ntf.notification.channelId == MessageChannel + } + if (msgNtfs.count() == 1) { + // Have a group notification with no children so cancel it + manager.cancel(0) + } + } + fun notifyMessageReceived(cInfo: ChatInfo, cItem: ChatItem) { Log.d(TAG, "notifyMessageReceived ${cInfo.id}") val now = Clock.System.now().toEpochMilliseconds() @@ -53,6 +66,7 @@ class NtfManager(val context: Context) { .setGroup(MessageGroup) .setGroupAlertBehavior(NotificationCompat.GROUP_ALERT_CHILDREN) .setGroupSummary(true) + .setContentIntent(getSummaryNtfIntent()) .build() with(NotificationManagerCompat.from(context)) { @@ -62,7 +76,7 @@ class NtfManager(val context: Context) { } } - private fun hideSecrets(cItem: ChatItem): String { + private fun hideSecrets(cItem: ChatItem) : String { val md = cItem.formattedText return if (md == null) { cItem.content.text @@ -87,4 +101,16 @@ class NtfManager(val context: Context) { getPendingIntent(uniqueInt, PendingIntent.FLAG_IMMUTABLE) } } + + private fun getSummaryNtfIntent() : PendingIntent{ + Log.d(TAG, "getSummaryNtfIntent") + val uniqueInt = (System.currentTimeMillis() and 0xfffffff).toInt() + val intent = Intent(context, MainActivity::class.java) + .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_SINGLE_TOP or Intent.FLAG_ACTIVITY_CLEAR_TOP) + .setAction(ShowChatsAction) + return TaskStackBuilder.create(context).run { + addNextIntentWithParentStack(intent) + getPendingIntent(uniqueInt, PendingIntent.FLAG_IMMUTABLE) + } + } } 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 53968f7719..1872dbb72f 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 @@ -30,7 +30,7 @@ typealias ChatCtrl = Long open class ChatController(private val ctrl: ChatCtrl, private val ntfManager: NtfManager, val appContext: Context) { var chatModel = ChatModel(this) - private val sharedPreferences: SharedPreferences = appContext.getSharedPreferences(SHARED_PREFS_ID, Context.MODE_PRIVATE) + private val sharedPreferences: SharedPreferences = appContext.getSharedPreferences(SHARED_PREFS_ID, Context.MODE_PRIVATE) init { chatModel.runServiceInBackground.value = getRunServiceInBackground() @@ -73,6 +73,10 @@ 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/ChatView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chat/ChatView.kt index 02b8ab1da6..ef7aea17d7 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 @@ -52,6 +52,7 @@ fun ChatView(chatModel: ChatModel) { delay(1000L) if (chat.chatItems.count() > 0) { chatModel.markChatItemsRead(chat.chatInfo) + chatModel.controller.cancelNotificationsForChat(chat.id) withApi { chatModel.controller.apiChatRead( chat.chatInfo.chatType, diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ChatListView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ChatListView.kt index 44017bc904..1f1c6b912e 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ChatListView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ChatListView.kt @@ -18,6 +18,7 @@ import chat.simplex.app.model.ChatModel import chat.simplex.app.ui.theme.ToolbarDark import chat.simplex.app.ui.theme.ToolbarLight import chat.simplex.app.views.chat.ChatHelpView +import chat.simplex.app.views.newchat.ModalManager import chat.simplex.app.views.newchat.NewChatSheet import chat.simplex.app.views.usersettings.SettingsView import kotlinx.coroutines.CoroutineScope @@ -63,6 +64,11 @@ fun scaffoldController(): ScaffoldController { @Composable fun ChatListView(chatModel: ChatModel) { val scaffoldCtrl = scaffoldController() + if (chatModel.clearOverlays.value) { + scaffoldCtrl.collapse() + ModalManager.shared.closeModal() + chatModel.clearOverlays.value = false + } BottomSheetScaffold( scaffoldState = scaffoldCtrl.state, drawerContent = { SettingsView(chatModel) }, diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/ModalView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/helpers/ModalView.kt index bb10bd639f..298867bc8e 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/ModalView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/helpers/ModalView.kt @@ -43,7 +43,7 @@ class ModalManager { } fun closeModal() { - if (!modalViews.isEmpty()) { + if (modalViews.isNotEmpty()) { modalViews.removeAt(modalViews.count() - 1) } modalCount.value = modalViews.count()