forked from retoor/devplacepy
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.
77 lines
2.1 KiB
JavaScript
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));
|
|
});
|