Implement service worker offline page

Also, make sure it can be translated.
This commit is contained in:
N-Pex 2025-12-22 12:31:56 +01:00
parent 7cec56fb50
commit af96e3db5f
9 changed files with 601 additions and 115 deletions

View file

@ -1,5 +1,19 @@
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();
@ -40,3 +54,88 @@ self.addEventListener('periodicsync', (event) => {
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");
}