From e21a54e2bf6331a8efc41f74d5268f7c4b004552 Mon Sep 17 00:00:00 2001 From: Codex Date: Tue, 10 Mar 2026 00:39:58 +0300 Subject: [PATCH] web: group notifications per chat thread --- web/src/utils/webNotifications.ts | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/web/src/utils/webNotifications.ts b/web/src/utils/webNotifications.ts index 5fc7028..e3d7820 100644 --- a/web/src/utils/webNotifications.ts +++ b/web/src/utils/webNotifications.ts @@ -26,15 +26,34 @@ export async function showNotificationViaServiceWorker(params: { if (!registration) { return false; } + const tag = `chat-${params.chatId}`; + const active = await registration.getNotifications({ tag }); + const prevData = active[0]?.data as + | { + unreadCount?: number; + previews?: string[]; + } + | undefined; + const unreadCount = Math.max(0, Number(prevData?.unreadCount ?? 0)) + 1; + const previews = [params.body, ...(prevData?.previews ?? [])] + .filter((item) => item && item.trim().length > 0) + .slice(0, 3); + const extraCount = Math.max(0, unreadCount - previews.length); + const groupedBody = + previews.length <= 1 + ? previews[0] ?? params.body + : `${previews.join("\n")}${extraCount > 0 ? `\n+${extraCount} more` : ""}`; const url = `/?chat=${params.chatId}&message=${params.messageId}`; await registration.showNotification(params.title, { - body: params.body, + body: groupedBody, icon: params.image, - tag: `chat-${params.chatId}`, + tag, data: { chatId: params.chatId, messageId: params.messageId, url, + unreadCount, + previews, }, }); return true;