From ce6bc985be62c91d626fb36907c1cf900e1edb2d Mon Sep 17 00:00:00 2001 From: k1ngsterr1 Date: Sun, 29 Mar 2026 23:12:29 +0500 Subject: [PATCH] =?UTF-8?q?=D0=9F=D1=83=D1=88=D0=B8:=20=D1=83=D1=87=D0=B8?= =?UTF-8?q?=D1=82=D1=8B=D0=B2=D0=B0=D1=82=D1=8C=20mute=20=D0=B8=20=D0=B8?= =?UTF-8?q?=D0=BC=D1=8F=20=D0=BE=D1=82=D0=BF=D1=80=D0=B0=D0=B2=D0=B8=D1=82?= =?UTF-8?q?=D0=B5=D0=BB=D1=8F=20=D0=B8=D0=B7=20payload?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../push/RosettaFirebaseMessagingService.kt | 81 ++++++++++++++++--- 1 file changed, 72 insertions(+), 9 deletions(-) diff --git a/app/src/main/java/com/rosetta/messenger/push/RosettaFirebaseMessagingService.kt b/app/src/main/java/com/rosetta/messenger/push/RosettaFirebaseMessagingService.kt index 18bd950..f32ad54 100644 --- a/app/src/main/java/com/rosetta/messenger/push/RosettaFirebaseMessagingService.kt +++ b/app/src/main/java/com/rosetta/messenger/push/RosettaFirebaseMessagingService.kt @@ -56,14 +56,43 @@ class RosettaFirebaseMessagingService : FirebaseMessagingService() { fun cancelNotificationForChat(context: Context, senderPublicKey: String) { val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager - val normalizedKey = senderPublicKey.trim() - if (normalizedKey.isNotEmpty()) { - notificationManager.cancel(getNotificationIdForChat(normalizedKey)) + val variants = buildDialogKeyVariants(senderPublicKey) + for (key in variants) { + notificationManager.cancel(getNotificationIdForChat(key)) } // Fallback: некоторые серверные payload могут прийти без sender key. // Для них используется ID от пустой строки — тоже очищаем при входе в диалог. notificationManager.cancel(getNotificationIdForChat("")) } + + private fun buildDialogKeyVariants(rawKey: String): Set { + val trimmed = rawKey.trim() + if (trimmed.isBlank()) return emptySet() + + val variants = linkedSetOf(trimmed) + val lower = trimmed.lowercase(Locale.ROOT) + when { + lower.startsWith("#group:") -> { + val groupId = trimmed.substringAfter(':').trim() + if (groupId.isNotBlank()) { + variants.add("group:$groupId") + variants.add(groupId) + } + } + lower.startsWith("group:") -> { + val groupId = trimmed.substringAfter(':').trim() + if (groupId.isNotBlank()) { + variants.add("#group:$groupId") + variants.add(groupId) + } + } + else -> { + variants.add("#group:$trimmed") + variants.add("group:$trimmed") + } + } + return variants + } } /** Вызывается когда получен новый FCM токен Отправляем его на сервер через протокол */ @@ -90,6 +119,8 @@ class RosettaFirebaseMessagingService : FirebaseMessagingService() { // Обрабатываем data payload if (remoteMessage.data.isNotEmpty()) { val data = remoteMessage.data + val notificationTitle = remoteMessage.notification?.title?.trim().orEmpty() + val notificationBody = remoteMessage.notification?.body?.trim().orEmpty() val type = firstNonBlank(data, "type", "event", "action") ?.lowercase(Locale.ROOT) @@ -100,15 +131,26 @@ class RosettaFirebaseMessagingService : FirebaseMessagingService() { "sender_public_key", "from_public_key", "fromPublicKey", + "from", "public_key", "publicKey" ) val senderName = - firstNonBlank(data, "sender_name", "from_title", "sender", "title", "name") + firstNonBlank( + data, + "sender_name", + "sender_title", + "from_title", + "sender", + "title", + "name" + ) + ?: notificationTitle.takeIf { it.isNotBlank() } ?: senderPublicKey?.take(10) ?: "Rosetta" val messagePreview = firstNonBlank(data, "message_preview", "message", "text", "body") + ?: notificationBody.takeIf { it.isNotBlank() } ?: "New message" val isReadEvent = type == "message_read" || type == "read" @@ -152,7 +194,21 @@ class RosettaFirebaseMessagingService : FirebaseMessagingService() { // с неуправляемым notification id. remoteMessage.notification?.let { if (!handledMessageData) { - showSimpleNotification(it.title ?: "Rosetta", it.body ?: "New message") + val senderPublicKey = + firstNonBlank( + remoteMessage.data, + "sender_public_key", + "from_public_key", + "fromPublicKey", + "from", + "public_key", + "publicKey" + ) + showSimpleNotification( + it.title ?: "Rosetta", + it.body ?: "New message", + senderPublicKey + ) } } } @@ -223,8 +279,12 @@ class RosettaFirebaseMessagingService : FirebaseMessagingService() { if (isAppInForeground || !areNotificationsEnabled()) { return } + val senderKey = senderPublicKey?.trim().orEmpty() + if (senderKey.isNotEmpty() && isDialogMuted(senderKey)) { + return + } // Dedup: suppress duplicate pushes within DEDUP_WINDOW_MS - val dedupKey = senderPublicKey?.trim()?.ifEmpty { null } ?: "__simple__" + val dedupKey = senderKey.ifEmpty { "__simple__" } val now = System.currentTimeMillis() val lastTs = lastNotifTimestamps[dedupKey] if (lastTs != null && now - lastTs < DEDUP_WINDOW_MS) { @@ -235,8 +295,8 @@ class RosettaFirebaseMessagingService : FirebaseMessagingService() { createNotificationChannel() // Используем sender-based ID если известен ключ — чтобы cancelNotificationForChat мог убрать уведомление - val notifId = if (!senderPublicKey.isNullOrBlank()) { - getNotificationIdForChat(senderPublicKey.trim()) + val notifId = if (senderKey.isNotEmpty()) { + getNotificationIdForChat(senderKey) } else { (title + body).hashCode() and 0x7FFFFFFF } @@ -318,7 +378,10 @@ class RosettaFirebaseMessagingService : FirebaseMessagingService() { val accountManager = AccountManager(applicationContext) val currentAccount = accountManager.getLastLoggedPublicKey().orEmpty() runBlocking(Dispatchers.IO) { - PreferencesManager(applicationContext).isChatMuted(currentAccount, senderPublicKey) + val preferences = PreferencesManager(applicationContext) + buildDialogKeyVariants(senderPublicKey).any { key -> + preferences.isChatMuted(currentAccount, key) + } } }.getOrDefault(false) }