keanu-weblite/public/sw.js
N-Pex 47ebc55f80 Build 94
Preserve the path name for mirror links
2025-12-22 13:23:43 +01:00

142 lines
No EOL
4.7 KiB
JavaScript

var periodicSyncNewMsgReminderText;
const OFFLINE_CACHE = `offline`;
const offlineCacheFiles = ['offline.html','config.json'];
// on install we download the routes we want to cache for offline
self.addEventListener('install', evt => evt.waitUntil(caches.open(OFFLINE_CACHE).then(cache => {
console.log("SW Caching offline files");
self.skipWaiting();
return cache.addAll(offlineCacheFiles);
})));
self.addEventListener("activate", event => {
event.waitUntil(clients.claim());
});
// Notification click event listener
self.addEventListener("notificationclick", (e) => {
e.notification.close();
e.waitUntil(
clients.matchAll({ type: "window" }).then((clientsArr) => {
// If a Window tab matching the targeted URL already exists, focus that;
const hadWindowToFocus = clientsArr.some((windowClient) =>
windowClient.url === e.notification.data.url
? (windowClient.focus(), true)
: false,
);
// Otherwise, open a new tab to the applicable URL and focus it.
if (!hadWindowToFocus)
clients
.openWindow(e.notification.data.url)
.then((windowClient) => (windowClient ? windowClient.focus() : null));
}),
);
});
self.addEventListener("message", (event) => {
periodicSyncNewMsgReminderText = event.data;
});
async function checkNewMessages() {
const cachedCredentials = await caches.open('cachedCredentials');
// Todo...
}
// Install PWA in mobile or web to test if periodicSync notification works
// see browser compatibility: https://developer.mozilla.org/en-US/docs/Web/API/Web_Periodic_Background_Synchronization_API#browser_compatibility
self.addEventListener('periodicsync', (event) => {
if (event.tag === 'check-new-messages') {
let notificationTitle = periodicSyncNewMsgReminderText || "You may have new messages";
self.registration.showNotification(notificationTitle);
event.waitUntil(checkNewMessages());
}
});
self.addEventListener("fetch", (event) => {
if (event.request.mode === 'navigate') {
return event.respondWith(
fetch(event.request).catch((e) => {
console.log("OFFLINE, serve offline page", e);
return serveOfflinePage();
}));
} else if (event.request.url.endsWith("config.json")) {
return fetch(event.request)
.then((response) => {
console.log("Caching a new version of config.json");
let responseClone = response.clone();
caches
.open(OFFLINE_CACHE)
.then((cache) => cache.put(event.request, responseClone));
return response;
})
}
});
async function serveOfflinePage() {
let mirrorUrl = null;
const rConfig = await caches.match("config.json", { cacheName: OFFLINE_CACHE});
if (rConfig) {
const json = await rConfig.json();
const mirrors = json.mirrors;
if (mirrors && Array.isArray(mirrors) && mirrors.length > 0) {
mirrorUrl = json.mirrors[Math.floor(Math.random() * mirrors.length)];
}
}
const offlinePage = await caches.match("offline.html", { cacheName: OFFLINE_CACHE});
if (mirrorUrl && offlinePage) {
let text = await offlinePage.text();
text = text.replaceAll("<!--MIRROR_URL-->", mirrorUrl);
let title = undefined;
let message = undefined;
let redirect = undefined;
await new Promise((resolve, reject) => {
var open = indexedDB.open("ServiceWorker", 1);
open.onerror = function() {
resolve(false);
}
open.onsuccess = function() {
// Start a new transaction
var db = open.result;
var tx = db.transaction("offline_strings", "readonly");
var store = tx.objectStore("offline_strings");
var get1 = store.get("offline_title");
var get2 = store.get("offline_message");
var get3 = store.get("offline_redirect");
get1.onsuccess = function() {
title = get1.result.translation;
};
get2.onsuccess = function() {
message = get2.result.translation;
};
get3.onsuccess = function() {
redirect = get3.result.translation;
};
// Close the db when the transaction is done
tx.oncomplete = function() {
db.close();
resolve(true);
};
}
});
if (title) {
text = text.replaceAll(/<!--OFFLINE_TITLE_START-->(.*?)<!--OFFLINE_TITLE_END-->/g, title);
}
if (message) {
text = text.replaceAll(/<!--OFFLINE_MESSAGE_START-->(.*?)<!--OFFLINE_MESSAGE_END-->/g, message);
}
if (redirect) {
text = text.replaceAll(/<!--OFFLINE_REDIRECT_START-->(.*?)<!--OFFLINE_REDIRECT_END-->/g, redirect);
}
return new Response(text, { headers: {"content-type": "text/html"}});
}
throw new Error("Offline");
}