Files
devplacepy/devplacepy/static/service-worker.js
T
retoor 3c55ae1bb1 feat: add PWA support with push notifications, service worker, and offline page
Implement progressive web app capabilities including VAPID-based push notification infrastructure, service worker with offline caching, PWA install prompt handling, and manifest configuration. Add push.py module for VAPID key generation and notification delivery, PushManager and PwaInstaller JavaScript classes, service worker with precache and push event handling, offline fallback page, and app icons at multiple resolutions.
2026-05-23 08:08:26 +00:00

77 lines
2.1 KiB
JavaScript

// retoor <retoor@molodetz.nl>
const CACHE_NAME = "devplace-shell-v1";
const OFFLINE_URL = "/static/offline.html";
const PRECACHE_URLS = [
OFFLINE_URL,
"/manifest.json",
"/static/icon-192.png",
"/static/icon-512.png",
];
const DEFAULT_URL = "/notifications";
const DEFAULT_ICON = "/static/icon-192.png";
self.addEventListener("install", (event) => {
event.waitUntil(
caches.open(CACHE_NAME).then((cache) => cache.addAll(PRECACHE_URLS)).then(() => self.skipWaiting())
);
});
self.addEventListener("activate", (event) => {
event.waitUntil(
caches.keys()
.then((names) => Promise.all(names.filter((name) => name !== CACHE_NAME).map((name) => caches.delete(name))))
.then(() => self.clients.claim())
);
});
self.addEventListener("fetch", (event) => {
if (event.request.mode !== "navigate") {
return;
}
event.respondWith(
fetch(event.request).catch(() => caches.match(OFFLINE_URL))
);
});
function isClientOpen(url) {
return clients.matchAll().then((matchedClients) =>
matchedClients.some((client) => client.url === url && "focus" in client)
);
}
self.addEventListener("push", (event) => {
event.waitUntil(handlePush(event));
});
async function handlePush(event) {
if (!self.Notification || self.Notification.permission !== "granted") {
return;
}
const data = event.data ? event.data.json() : {};
const url = data.url || DEFAULT_URL;
if (await isClientOpen(url)) {
return;
}
const title = data.title || "DevPlace";
const message = data.message || "You have a new notification.";
const icon = data.icon || DEFAULT_ICON;
await self.registration.showNotification(title, {
body: message,
icon: icon,
badge: icon,
tag: "devplace-notification",
data: data,
});
}
self.addEventListener("notificationclick", (event) => {
event.notification.close();
const url = event.notification.data && event.notification.data.url ? event.notification.data.url : DEFAULT_URL;
event.waitUntil(clients.openWindow(url));
});