forked from mystiq/hydrogen-web
improve notifications shown
- use event.waitUntil to prevent default notification - replace notifications for same room - replace notifications when receiving unread=0 with "Read messages" to prevent default notification - don't rely on client.url to figure out if a room is open as FF does not update this field on hash changes.
This commit is contained in:
parent
2de61c5928
commit
f91abe4301
2 changed files with 78 additions and 8 deletions
|
@ -60,7 +60,14 @@ export class ServiceWorkerHandler {
|
||||||
resolve(data.payload);
|
resolve(data.payload);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (data.type === "closeSession") {
|
if (data.type === "hasSessionOpen") {
|
||||||
|
const hasOpen = this._navigation.observe("session").get() === data.payload.sessionId;
|
||||||
|
event.source.postMessage({replyTo: data.id, payload: hasOpen});
|
||||||
|
} else if (data.type === "hasRoomOpen") {
|
||||||
|
const hasSessionOpen = this._navigation.observe("session").get() === data.payload.sessionId;
|
||||||
|
const hasRoomOpen = this._navigation.observe("room").get() === data.payload.roomId;
|
||||||
|
event.source.postMessage({replyTo: data.id, payload: hasSessionOpen && hasRoomOpen});
|
||||||
|
} else if (data.type === "closeSession") {
|
||||||
const {sessionId} = data.payload;
|
const {sessionId} = data.payload;
|
||||||
this._closeSessionIfNeeded(sessionId).finally(() => {
|
this._closeSessionIfNeeded(sessionId).finally(() => {
|
||||||
event.source.postMessage({replyTo: data.id});
|
event.source.postMessage({replyTo: data.id});
|
||||||
|
|
|
@ -185,6 +185,9 @@ self.addEventListener('message', (event) => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const NOTIF_TAG_MESSAGES_READ = "messages_read";
|
||||||
|
const NOTIF_TAG_NEW_MESSAGE = "new_message";
|
||||||
|
|
||||||
async function openClientFromNotif(event) {
|
async function openClientFromNotif(event) {
|
||||||
const clientList = await self.clients.matchAll({type: "window"});
|
const clientList = await self.clients.matchAll({type: "window"});
|
||||||
const {sessionId, roomId} = event.notification.data;
|
const {sessionId, roomId} = event.notification.data;
|
||||||
|
@ -212,11 +215,32 @@ self.addEventListener('notificationclick', event => {
|
||||||
event.waitUntil(openClientFromNotif(event));
|
event.waitUntil(openClientFromNotif(event));
|
||||||
});
|
});
|
||||||
|
|
||||||
self.addEventListener('push', event => {
|
async function handlePushNotification(n) {
|
||||||
const n = event.data.json();
|
|
||||||
console.log("got a push message", n);
|
console.log("got a push message", n);
|
||||||
|
const sessionId = n.session_id;
|
||||||
let sender = n.sender_display_name || n.sender;
|
let sender = n.sender_display_name || n.sender;
|
||||||
if (sender && n.event_id) {
|
if (sender && n.event_id) {
|
||||||
|
const clientList = await self.clients.matchAll({type: "window"});
|
||||||
|
const roomId = n.room_id;
|
||||||
|
const hasFocusedClientOnRoom = !!await findClient(async client => {
|
||||||
|
if (client.visibilityState === "visible" && client.focused) {
|
||||||
|
return await sendAndWaitForReply(client, "hasRoomOpen", {sessionId, roomId});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (hasFocusedClientOnRoom) {
|
||||||
|
console.log("client is focused, room is open, don't show notif");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (const client of clientList) {
|
||||||
|
// if the app is open and focused, don't show a notif when looking at the room already
|
||||||
|
if (client.visibilityState === "visible" && client.focused) {
|
||||||
|
const isRoomOpen = await sendAndWaitForReply(client, "hasRoomOpen", {sessionId, roomId});
|
||||||
|
if (isRoomOpen) {
|
||||||
|
console.log("client is focused, room is open, don't show notif");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
let label;
|
let label;
|
||||||
if (n.room_name) {
|
if (n.room_name) {
|
||||||
label = `${sender} wrote you in ${n.room_name}`;
|
label = `${sender} wrote you in ${n.room_name}`;
|
||||||
|
@ -224,14 +248,44 @@ self.addEventListener('push', event => {
|
||||||
label = `${sender} wrote you`;
|
label = `${sender} wrote you`;
|
||||||
}
|
}
|
||||||
let body = n.content?.body;
|
let body = n.content?.body;
|
||||||
self.registration.showNotification(label, {
|
// close any previous notifications for this room
|
||||||
|
const newMessageNotifs = Array.from(await self.registration.getNotifications({tag: NOTIF_TAG_NEW_MESSAGE}));
|
||||||
|
const notifsForRoom = newMessageNotifs.filter(n => n.data.roomId === roomId);
|
||||||
|
for (const notif of notifsForRoom) {
|
||||||
|
console.log("close previous notification for room");
|
||||||
|
notif.close();
|
||||||
|
}
|
||||||
|
console.log("showing new message notification");
|
||||||
|
await self.registration.showNotification(label, {
|
||||||
body,
|
body,
|
||||||
data: {
|
data: {sessionId, roomId},
|
||||||
sessionId: n.session_id,
|
tag: NOTIF_TAG_NEW_MESSAGE
|
||||||
roomId: n.room_id,
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
} else if (n.unread === 0) {
|
||||||
|
// hide the notifs
|
||||||
|
console.log("unread=0, close all notifs");
|
||||||
|
const notifs = Array.from(await self.registration.getNotifications());
|
||||||
|
for (const notif of notifs) {
|
||||||
|
if (notif.tag !== NOTIF_TAG_MESSAGES_READ) {
|
||||||
|
notif.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const hasVisibleClient = !!await findClient(client => client.visibilityState === "visible");
|
||||||
|
// ensure we always show a notification when no client is visible, see https://goo.gl/yqv4Q4
|
||||||
|
if (!hasVisibleClient) {
|
||||||
|
const readNotifs = Array.from(await self.registration.getNotifications({tag: NOTIF_TAG_MESSAGES_READ}));
|
||||||
|
if (readNotifs.length === 0) {
|
||||||
|
await self.registration.showNotification("New messages that have since been read", {
|
||||||
|
tag: NOTIF_TAG_MESSAGES_READ,
|
||||||
|
data: {sessionId}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.addEventListener('push', event => {
|
||||||
|
event.waitUntil(handlePushNotification(event.data.json()));
|
||||||
});
|
});
|
||||||
|
|
||||||
async function closeSession(sessionId, requestingClientId) {
|
async function closeSession(sessionId, requestingClientId) {
|
||||||
|
@ -264,3 +318,12 @@ function sendAndWaitForReply(client, type, payload) {
|
||||||
client.postMessage({type, id, payload});
|
client.postMessage({type, id, payload});
|
||||||
return promise;
|
return promise;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function findClient(predicate) {
|
||||||
|
const clientList = await self.clients.matchAll({type: "window"});
|
||||||
|
for (const client of clientList) {
|
||||||
|
if (await predicate(client)) {
|
||||||
|
return client;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue