Notifications: Group multiple push notifications (#1209)
This commit is contained in:
parent
21dc993463
commit
c218e38abc
@ -45,7 +45,6 @@ self.addEventListener('fetch', (e: FetchEvent) => {
|
|||||||
})());
|
})());
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
self.addEventListener('push', handlePush);
|
self.addEventListener('push', handlePush);
|
||||||
self.addEventListener('notificationclick', handleNotificationClick);
|
self.addEventListener('notificationclick', handleNotificationClick);
|
||||||
self.addEventListener('message', handleClientMessage);
|
self.addEventListener('message', handleClientMessage);
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
import { APP_NAME, DEBUG } from '../config';
|
import { APP_NAME, DEBUG } from '../config';
|
||||||
|
import { debounce } from '../util/schedulers';
|
||||||
|
|
||||||
declare const self: ServiceWorkerGlobalScope;
|
declare const self: ServiceWorkerGlobalScope;
|
||||||
|
|
||||||
@ -32,6 +33,7 @@ type NotificationData = {
|
|||||||
|
|
||||||
const clickBuffer: Record<string, NotificationData> = {};
|
const clickBuffer: Record<string, NotificationData> = {};
|
||||||
const shownNotifications = new Set();
|
const shownNotifications = new Set();
|
||||||
|
let pendingNotifications: Record<number, NotificationData[]> = {};
|
||||||
|
|
||||||
function getPushData(e: PushEvent | Notification): PushData | undefined {
|
function getPushData(e: PushEvent | Notification): PushData | undefined {
|
||||||
try {
|
try {
|
||||||
@ -91,6 +93,55 @@ function showNotification({
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function showNotifications(groupLimit: number = 1) {
|
||||||
|
const count = Object.keys(pendingNotifications).reduce<number>((result, groupId) => {
|
||||||
|
result += pendingNotifications[Number(groupId)].length;
|
||||||
|
return result;
|
||||||
|
}, 0);
|
||||||
|
// if we have more than groupLimit notification groups we send only one notification
|
||||||
|
if (Object.keys(pendingNotifications).length > groupLimit) {
|
||||||
|
await showNotification({
|
||||||
|
title: APP_NAME,
|
||||||
|
body: `You have ${count} new Telegram notifications`,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// Else we send a notification per group
|
||||||
|
await Promise.all(Object.keys(pendingNotifications)
|
||||||
|
// eslint-disable-next-line no-async-without-await/no-async-without-await
|
||||||
|
.map(async (groupId) => {
|
||||||
|
const group = pendingNotifications[Number(groupId)];
|
||||||
|
if (group.length > groupLimit) {
|
||||||
|
return showNotification({
|
||||||
|
title: APP_NAME,
|
||||||
|
body: `You have ${count} notifications from ${group[0].title}`,
|
||||||
|
chatId: Number(groupId),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return Promise.all(group.map(showNotification));
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear all pending notifications
|
||||||
|
pendingNotifications = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
const flushNotifications = debounce(showNotifications, 1000, false);
|
||||||
|
|
||||||
|
async function handleNotification(notification: NotificationData, groupLimit?: number) {
|
||||||
|
// Dont show already triggered notification
|
||||||
|
if (shownNotifications.has(notification.messageId)) {
|
||||||
|
shownNotifications.delete(notification.messageId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const groupId = notification.chatId || 0;
|
||||||
|
if (!pendingNotifications[groupId]) {
|
||||||
|
pendingNotifications[groupId] = [];
|
||||||
|
}
|
||||||
|
pendingNotifications[groupId].push(notification);
|
||||||
|
await flushNotifications(groupLimit);
|
||||||
|
}
|
||||||
|
|
||||||
export function handlePush(e: PushEvent) {
|
export function handlePush(e: PushEvent) {
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
// eslint-disable-next-line no-console
|
// eslint-disable-next-line no-console
|
||||||
@ -106,14 +157,7 @@ export function handlePush(e: PushEvent) {
|
|||||||
if (!data || data.mute === Boolean.True) return;
|
if (!data || data.mute === Boolean.True) return;
|
||||||
|
|
||||||
const notification = getNotificationData(data);
|
const notification = getNotificationData(data);
|
||||||
|
e.waitUntil(handleNotification(notification));
|
||||||
// Dont show already triggered notification
|
|
||||||
if (shownNotifications.has(notification.messageId)) {
|
|
||||||
shownNotifications.delete(notification.messageId);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
e.waitUntil(showNotification(notification));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function focusChatMessage(client: WindowClient, data: { chatId?: number; messageId?: number }) {
|
async function focusChatMessage(client: WindowClient, data: { chatId?: number; messageId?: number }) {
|
||||||
@ -181,7 +225,7 @@ export function handleClientMessage(e: ExtendableMessageEvent) {
|
|||||||
if (e.data.type === 'newMessageNotification') {
|
if (e.data.type === 'newMessageNotification') {
|
||||||
// store messageId for already shown notification
|
// store messageId for already shown notification
|
||||||
const notification: NotificationData = e.data.payload;
|
const notification: NotificationData = e.data.payload;
|
||||||
e.waitUntil(showNotification(notification));
|
e.waitUntil(handleNotification(notification, 3));
|
||||||
shownNotifications.add(notification.messageId);
|
shownNotifications.add(notification.messageId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user