mirror of
https://github.com/danog/telegram-tt.git
synced 2025-01-05 20:38:50 +01:00
Notifications: Close when read, replace same-chat instead of counter (#1413)
This commit is contained in:
parent
1f36d97607
commit
d291016123
@ -4,7 +4,7 @@ import { ApiUpdate, MAIN_THREAD_ID } from '../../../api/types';
|
|||||||
|
|
||||||
import { ARCHIVED_FOLDER_ID, MAX_ACTIVE_PINNED_CHATS } from '../../../config';
|
import { ARCHIVED_FOLDER_ID, MAX_ACTIVE_PINNED_CHATS } from '../../../config';
|
||||||
import { pick } from '../../../util/iteratees';
|
import { pick } from '../../../util/iteratees';
|
||||||
import { showNewMessageNotification } from '../../../util/notifications';
|
import { closeMessageNotifications, showNewMessageNotification } from '../../../util/notifications';
|
||||||
import { updateAppBadge } from '../../../util/appBadge';
|
import { updateAppBadge } from '../../../util/appBadge';
|
||||||
import {
|
import {
|
||||||
updateChat,
|
updateChat,
|
||||||
@ -42,6 +42,13 @@ addReducer('apiUpdate', (global, actions, update: ApiUpdate) => {
|
|||||||
setGlobal(newGlobal);
|
setGlobal(newGlobal);
|
||||||
|
|
||||||
runThrottledForUpdateAppBadge(() => updateAppBadge(selectCountNotMutedUnread(getGlobal())));
|
runThrottledForUpdateAppBadge(() => updateAppBadge(selectCountNotMutedUnread(getGlobal())));
|
||||||
|
|
||||||
|
if (update.chat.id) {
|
||||||
|
closeMessageNotifications({
|
||||||
|
chatId: update.chat.id,
|
||||||
|
lastReadInboxMessageId: update.chat.lastReadInboxMessageId,
|
||||||
|
});
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,6 +31,11 @@ type NotificationData = {
|
|||||||
icon?: string;
|
icon?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
type CloseNotificationData = {
|
||||||
|
lastReadInboxMessageId?: number;
|
||||||
|
chatId: number;
|
||||||
|
};
|
||||||
|
|
||||||
let lastSyncAt = new Date().valueOf();
|
let lastSyncAt = new Date().valueOf();
|
||||||
const shownNotifications = new Set();
|
const shownNotifications = new Set();
|
||||||
const clickBuffer: Record<string, NotificationData> = {};
|
const clickBuffer: Record<string, NotificationData> = {};
|
||||||
@ -87,14 +92,15 @@ async function playNotificationSound(id: number) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async function showNotification({
|
function showNotification({
|
||||||
chatId,
|
chatId,
|
||||||
messageId,
|
messageId,
|
||||||
body,
|
body,
|
||||||
title,
|
title,
|
||||||
icon,
|
icon,
|
||||||
}: NotificationData) {
|
}: NotificationData) {
|
||||||
const tag = String(chatId || 0);
|
const isFirstBatch = new Date().valueOf() - lastSyncAt < 1000;
|
||||||
|
const tag = String(isFirstBatch ? 0 : chatId || 0);
|
||||||
const options: NotificationOptions = {
|
const options: NotificationOptions = {
|
||||||
body,
|
body,
|
||||||
data: {
|
data: {
|
||||||
@ -107,21 +113,29 @@ async function showNotification({
|
|||||||
tag,
|
tag,
|
||||||
vibrate: [200, 100, 200],
|
vibrate: [200, 100, 200],
|
||||||
};
|
};
|
||||||
const notifications = await self.registration.getNotifications({ tag });
|
|
||||||
if (notifications.length > 0) {
|
|
||||||
const current = notifications[0];
|
|
||||||
const count = current.data.count + 1;
|
|
||||||
options.data.count = count;
|
|
||||||
options.data.messageId = current.data.messageId;
|
|
||||||
options.body = `You have ${count} new messages`;
|
|
||||||
current.close();
|
|
||||||
}
|
|
||||||
return Promise.all([
|
return Promise.all([
|
||||||
playNotificationSound(messageId || chatId || 0),
|
playNotificationSound(messageId || chatId || 0),
|
||||||
self.registration.showNotification(title, options),
|
self.registration.showNotification(title, options),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function closeNotifications({
|
||||||
|
chatId,
|
||||||
|
lastReadInboxMessageId,
|
||||||
|
}: CloseNotificationData) {
|
||||||
|
const notifications = await self.registration.getNotifications();
|
||||||
|
const lastMessageId = lastReadInboxMessageId || Number.MAX_VALUE;
|
||||||
|
notifications.forEach((notification) => {
|
||||||
|
if (
|
||||||
|
notification.tag === '0'
|
||||||
|
|| (notification.data.chatId === chatId && notification.data.messageId <= lastMessageId)
|
||||||
|
) {
|
||||||
|
notification.close();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
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
|
||||||
@ -223,16 +237,16 @@ export function handleClientMessage(e: ExtendableMessageEvent) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (e.data.type === 'newMessageNotification') {
|
if (e.data.type === 'newMessageNotification') {
|
||||||
// Do not show notifications right after sync (when browser is opened)
|
|
||||||
// To avoid stale notifications
|
|
||||||
if (new Date().valueOf() - lastSyncAt < 3000) return;
|
|
||||||
|
|
||||||
// store messageId for already shown notification
|
// store messageId for already shown notification
|
||||||
const notification: NotificationData = e.data.payload;
|
const notification: NotificationData = e.data.payload;
|
||||||
// mark this notification as shown if it was handled locally
|
// mark this notification as shown if it was handled locally
|
||||||
shownNotifications.add(notification.messageId);
|
shownNotifications.add(notification.messageId);
|
||||||
e.waitUntil(showNotification(notification));
|
e.waitUntil(showNotification(notification));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (e.data.type === 'closeMessageNotifications') {
|
||||||
|
e.waitUntil(closeNotifications(e.data.payload));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.onsync = () => {
|
self.onsync = () => {
|
||||||
|
@ -3,7 +3,7 @@ import {
|
|||||||
ApiChat, ApiMediaFormat, ApiMessage, ApiUser,
|
ApiChat, ApiMediaFormat, ApiMessage, ApiUser,
|
||||||
} from '../api/types';
|
} from '../api/types';
|
||||||
import { renderActionMessageText } from '../components/common/helpers/renderActionMessageText';
|
import { renderActionMessageText } from '../components/common/helpers/renderActionMessageText';
|
||||||
import { DEBUG } from '../config';
|
import { DEBUG, IS_TEST } from '../config';
|
||||||
import { getDispatch, getGlobal, setGlobal } from '../lib/teact/teactn';
|
import { getDispatch, getGlobal, setGlobal } from '../lib/teact/teactn';
|
||||||
import {
|
import {
|
||||||
getChatAvatarHash,
|
getChatAvatarHash,
|
||||||
@ -378,6 +378,14 @@ export async function showNewMessageNotification({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function closeMessageNotifications(payload: { chatId: number; lastReadInboxMessageId?: number }) {
|
||||||
|
if (IS_TEST || !navigator.serviceWorker.controller) return;
|
||||||
|
navigator.serviceWorker.controller.postMessage({
|
||||||
|
type: 'closeMessageNotifications',
|
||||||
|
payload,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Notify service worker that client is fully loaded
|
// Notify service worker that client is fully loaded
|
||||||
export function notifyClientReady() {
|
export function notifyClientReady() {
|
||||||
if (!navigator.serviceWorker.controller) return;
|
if (!navigator.serviceWorker.controller) return;
|
||||||
|
Loading…
Reference in New Issue
Block a user