diff --git a/public/pwa_offline.html b/public/pwa_offline.html new file mode 100644 index 00000000..6a3d52dc --- /dev/null +++ b/public/pwa_offline.html @@ -0,0 +1,149 @@ + + + + + You are offline + + + + + +
+
+ + + A raccoon peeking out of a bin, looking confused + +
+
+

+ 404 + You are offline +

+

+ This content is not available offline. +

+ +
+
+ + + diff --git a/public/service_worker.js b/public/service_worker.js index 1f13f0f8..3735a89b 100644 --- a/public/service_worker.js +++ b/public/service_worker.js @@ -1,3 +1,14 @@ +const OFFLINE_CACHE_NAME = "offline"; +// Bumping this version will force an update of the service worker +// eslint-disable-next-line @typescript-eslint/no-unused-vars +const OFFLINE_PAGE_VERSION = 1; +const OFFLINE_CACHE_PATHS = [ + "/pwa_offline.html", + "/images/errors/small/404.png", + "/images/errors/medium/404.png", + "/images/errors/original/404.png" +]; + self.addEventListener('push', function (event) { if (event.data) { const notification = event.data.json(); @@ -23,3 +34,31 @@ self.addEventListener('notificationclick', async event => { console.warn(`Unhandled notification tag: ${event.notification.tag}`); } }); + +self.addEventListener('install', function (event) { + event.waitUntil( + (async () => { + const cache = await caches.open(OFFLINE_CACHE_NAME); + await cache.addAll(OFFLINE_CACHE_PATHS); + })() + ); + // Immediately activate new versions of the service worker instead of waiting + self.skipWaiting(); +}); + +self.addEventListener('fetch', function (event) { + event.respondWith( + (async () => { + try { + // Try to load the resource + return await fetch(event.request); + } catch (error) { + // Show an error page if offline + console.log("Fetch failed; returning offline page instead.", error); + + const cache = await caches.open(OFFLINE_CACHE_NAME); + return await cache.match(OFFLINE_CACHE_PATHS[0]); + } + })() + ); +});