Implement push subscription expiry

This commit is contained in:
nimbleghost 2023-06-02 14:45:05 +02:00
parent 47ad024ec7
commit 0f0074cbab
16 changed files with 272 additions and 102 deletions

View file

@ -32,35 +32,50 @@ self.addEventListener("push", (event) => {
const data = event.data.json();
console.log("[ServiceWorker] Received Web Push Event", { event, data });
const { subscription_id: subscriptionId, message } = data;
broadcastChannel.postMessage(message);
event.waitUntil(
(async () => {
const db = await getDbAsync();
await Promise.all([
(async () => {
await db.notifications.add({
...message,
subscriptionId,
// New marker (used for bubble indicator); cannot be boolean; Dexie index limitation
new: 1,
});
const badgeCount = await db.notifications.where({ new: 1 }).count();
console.log("[ServiceWorker] Setting new app badge count", { badgeCount });
self.navigator.setAppBadge?.(badgeCount);
})(),
db.subscriptions.update(subscriptionId, {
last: message.id,
}),
self.registration.showNotification(formatTitleWithDefault(message, message.topic), {
tag: subscriptionId,
body: formatMessage(message),
if (data.event === "subscription_expiring") {
await self.registration.showNotification("Notifications will be paused", {
body: "Open ntfy to continue receiving notifications",
icon: "/static/images/ntfy.png",
data,
}),
]);
});
} else if (data.event === "message") {
const { subscription_id: subscriptionId, message } = data;
broadcastChannel.postMessage(message);
const db = await getDbAsync();
await Promise.all([
(async () => {
await db.notifications.add({
...message,
subscriptionId,
// New marker (used for bubble indicator); cannot be boolean; Dexie index limitation
new: 1,
});
const badgeCount = await db.notifications.where({ new: 1 }).count();
console.log("[ServiceWorker] Setting new app badge count", { badgeCount });
self.navigator.setAppBadge?.(badgeCount);
})(),
db.subscriptions.update(subscriptionId, {
last: message.id,
}),
self.registration.showNotification(formatTitleWithDefault(message, message.topic), {
tag: subscriptionId,
body: formatMessage(message),
icon: "/static/images/ntfy.png",
data,
}),
]);
} else {
// We can't ignore the push, since permission can be revoked by the browser
await self.registration.showNotification("Unknown notification received from server", {
body: "You may need to update ntfy by opening the web app",
icon: "/static/images/ntfy.png",
data,
});
}
})()
);
});
@ -68,33 +83,38 @@ self.addEventListener("push", (event) => {
self.addEventListener("notificationclick", (event) => {
event.notification.close();
const { message } = event.notification.data;
if (message.click) {
self.clients.openWindow(message.click);
return;
}
const rootUrl = new URL(self.location.origin);
const topicUrl = new URL(message.topic, self.location.origin);
event.waitUntil(
(async () => {
const clients = await self.clients.matchAll({ type: "window" });
const topicClient = clients.find((client) => client.url === topicUrl.toString());
if (topicClient) {
topicClient.focus();
return;
}
const rootUrl = new URL(self.location.origin);
const rootClient = clients.find((client) => client.url === rootUrl.toString());
if (rootClient) {
rootClient.focus();
return;
}
self.clients.openWindow(topicUrl);
if (event.notification.data.event !== "message") {
if (rootClient) {
rootClient.focus();
} else {
self.clients.openWindow(rootUrl);
}
} else {
const { message } = event.notification.data;
if (message.click) {
self.clients.openWindow(message.click);
return;
}
const topicUrl = new URL(message.topic, self.location.origin);
const topicClient = clients.find((client) => client.url === topicUrl.toString());
if (topicClient) {
topicClient.focus();
} else if (rootClient) {
rootClient.focus();
} else {
self.clients.openWindow(topicUrl);
}
}
})()
);
});

View file

@ -42,4 +42,5 @@ class Prefs {
}
}
export default new Prefs(getDb());
const prefs = new Prefs(getDb());
export default prefs;

View file

@ -57,7 +57,6 @@ import { IncorrectPasswordError, UnauthorizedError } from "../app/errors";
import { ProChip } from "./SubscriptionPopup";
import theme from "./theme";
import session from "../app/Session";
import subscriptionManager from "../app/SubscriptionManager";
const Account = () => {
if (!session.exists()) {

View file

@ -58,9 +58,7 @@ const App = () => {
const updateTitle = (newNotificationsCount) => {
document.title = newNotificationsCount > 0 ? `(${newNotificationsCount}) ntfy` : "ntfy";
if ("setAppBadge" in window.navigator) {
window.navigator.setAppBadge(newNotificationsCount);
}
window.navigator.setAppBadge?.(newNotificationsCount);
};
const Layout = () => {

View file

@ -10,7 +10,6 @@ import session from "../app/Session";
import accountApi from "../app/AccountApi";
import { UnauthorizedError } from "../app/errors";
import { webPushRefreshWorker, useWebPushUpdateWorker } from "../app/WebPushWorker";
import notifier from "../app/Notifier";
/**
* Wire connectionManager and subscriptionManager so that subscriptions are updated when the connection