Push: обработка read-событий в тихих уведомлениях

This commit is contained in:
2026-04-05 14:10:43 +05:00
parent 9d04ec07e8
commit b8c5529b29

View File

@@ -73,10 +73,13 @@ class RosettaFirebaseMessagingService : FirebaseMessagingService() {
val variants = buildDialogKeyVariants(senderPublicKey)
for (key in variants) {
notificationManager.cancel(getNotificationIdForChat(key))
lastNotifTimestamps.remove(key)
}
// Fallback: некоторые серверные payload могут прийти без sender key.
// Для них используется ID от пустой строки — тоже очищаем при входе в диалог.
notificationManager.cancel(getNotificationIdForChat(""))
lastNotifTimestamps.remove("__no_sender__")
lastNotifTimestamps.remove("__simple__")
}
private fun buildDialogKeyVariants(rawKey: String): Set<String> {
@@ -196,8 +199,14 @@ class RosettaFirebaseMessagingService : FirebaseMessagingService() {
when {
isReadEvent -> {
if (!dialogKey.isNullOrBlank()) {
cancelNotificationForChat(applicationContext, dialogKey)
val keysToClear = collectReadDialogKeys(data, dialogKey, senderPublicKey)
if (keysToClear.isEmpty()) {
Log.d(TAG, "READ push received but no dialog key in payload: $data")
} else {
keysToClear.forEach { key ->
cancelNotificationForChat(applicationContext, key)
}
Log.d(TAG, "READ push cleared notifications for keys=$keysToClear")
}
handledByData = true
}
@@ -541,6 +550,44 @@ class RosettaFirebaseMessagingService : FirebaseMessagingService() {
return null
}
/**
* Builds a robust list of dialog keys for silent READ pushes.
* Server payloads may evolve (dialog/from/to/peer/group_* aliases), so we parse
* all known aliases and exclude current account public key.
*/
private fun collectReadDialogKeys(
data: Map<String, String>,
parsedDialogKey: String?,
parsedSenderKey: String?
): Set<String> {
val currentAccount = AccountManager(applicationContext).getLastLoggedPublicKey().orEmpty().trim()
val candidates = linkedSetOf<String>()
fun addCandidate(raw: String?) {
val value = raw?.trim().orEmpty()
if (value.isBlank()) return
if (currentAccount.isNotBlank() && value == currentAccount) return
candidates.add(value)
}
addCandidate(parsedDialogKey)
addCandidate(parsedSenderKey)
addCandidate(firstNonBlank(data, "dialog", "dialog_key", "dialogPublicKey", "dialog_public_key"))
addCandidate(firstNonBlank(data, "peer", "peer_key", "peerPublicKey", "peer_public_key", "chat", "chat_key"))
addCandidate(firstNonBlank(data, "to", "toPublicKey", "to_public_key", "dst", "dst_public_key"))
addCandidate(firstNonBlank(data, "from", "fromPublicKey", "from_public_key", "src", "src_public_key"))
// Group aliases from some server payloads
val groupId = firstNonBlank(data, "group", "group_id", "groupId")
if (!groupId.isNullOrBlank()) {
addCandidate(groupId)
addCandidate("group:$groupId")
addCandidate("#group:$groupId")
}
return candidates
}
private fun isAvatarInNotificationsEnabled(): Boolean {
return runCatching {
runBlocking(Dispatchers.IO) {