From 42c618700c5a8aa795a4a1aac57a6d45ca01da8d Mon Sep 17 00:00:00 2001 From: daffinm Date: Sat, 4 Apr 2020 12:18:23 +0100 Subject: [PATCH] Extracted ui callback into reusable demo class. --- README.md | 8 ++++---- index.html | 34 ++-------------------------------- js/sw-client.js | 33 +++++++++++++++++++++++++++++++++ sw.js | 8 +++++--- 4 files changed, 44 insertions(+), 39 deletions(-) diff --git a/README.md b/README.md index 784424e..d9e0181 100644 --- a/README.md +++ b/README.md @@ -16,18 +16,18 @@ feel confident that my apps will work well and I can stop thinking about it. The simple use case here (which I suspect is the main one) is: 1. Publish update to PWA. -1. User is notified next time they: reload/restart the app, or press a 'check for updates' button somewhere in the UI, or the update +1. User is notified next time they: reload/restart the simpleUI, or press a 'check for updates' button somewhere in the UI, or the update is discovered because of some kind of periodic background check (I think that's it). 1. User is given the option to use the update now or later. * Updates cannot be rejected indefinitely in PWA land. * By the time the user hears of the update it has already been installed and is waiting to become active. -1. If the user accepts the update the new service worker version is activated and, once this happens, the app reloads to get +1. If the user accepts the update the new service worker version is activated and, once this happens, the simpleUI reloads to get itself in sync with the new back end. 1. If the user rejects the update they carry on using the old version of the service worker and UI until next time one of the three things mentioned in step 2 happens again. 1. At this point they will get the option, again, to accept or reject the update for the time being. * The fact that they may have rejected an update before should not stop them changing their mind later. -1. The only exception to this is when the app is first accessed and the first version of the service worker is installed +1. The only exception to this is when the simpleUI is first accessed and the first version of the service worker is installed on the user's machine (browser). * At this point the page ('client') will not be controlled, so any update will activate automatically. @@ -38,7 +38,7 @@ The code here attempt so do all of this as simply as possible. Have I missed anything, or misunderstood, or made it too complicated? -## Running and playing with the app +## Running and playing with the simpleUI 1. Run project using `npm start` and goto http://localhost:5001 in Chrome. 1. Open the dev tools console asap and check the console messages to see what's happening. diff --git a/index.html b/index.html index ca0ad5d..5f93021 100644 --- a/index.html +++ b/index.html @@ -70,38 +70,8 @@

Service Worker Test

let message = (underControl ? 'This page IS controlled by a Service Worker' : 'This page is NOT controlled by a Service Worker'); $messages.className = className; $messages.innerHTML = message; - // The callback object - implements an interface (I wish) that enables us to decouple the service worker client from - // the app that's using it. - const app = { - noUpdateFound() { - alert(`No update found\n\nYou are already on the latest version.`); - }, - updateError(err) { - alert(`Error\n\nCannot check for updates.\n\nAre you offline?`); - }, - updateFoundReloadNeeded() { - // Called when an update is found but the client is not controlled by the service worker. This means that - // the update will activate automatically. So the client will need to play catch up with the service worker: - // to reload so that it becomes controlled by it. - // Inform the user with OK dialog and reload when this returns (to give some sense of control). - alert('Update found!\n\nApp will reload when you press OK.'); - app.reload(); - }, - confirmUpdateWithUser(callback) { - if (confirm(`Update available!\n\nAn update is available for this app.\n\nUse it now?`)) { - callback(true); - } - else { - callback(false); - } - }, - reload() { - debug.warn('Reloading app...'); - document.body.style = 'color:red;'; - setTimeout(() => window.location.reload(), 1000); - } - }; - const swc = new ServiceWorkerClient('sw.js', debug, app); + + const swc = new ServiceWorkerClient('sw.js', debug, new SimpleUI(debug)); swc.register(); // The update button const updateButton = document.getElementById('check-for-updates'); diff --git a/js/sw-client.js b/js/sw-client.js index b1159f4..4c61522 100644 --- a/js/sw-client.js +++ b/js/sw-client.js @@ -137,3 +137,36 @@ function ServiceWorkerClient(url, debug, ui) { } } } + +// Demo ui callback object - implements an interface (I wish) that enables us to decouple the service worker +// client from the app that's using it. +function SimpleUI(debug) { + this.noUpdateFound = function () { + alert(`No update found\n\nYou are already on the latest version.`); + }; + this.updateError = function (err) { + alert(`Error\n\nCannot check for updates.\n\nAre you offline?`); + }; + this.updateFoundReloadNeeded = function () { + // Called when an update is found but the client is not controlled by the service worker. This means that + // the update will activate automatically. So the client will need to play catch up with the service worker: + // to reload so that it becomes controlled by it. + // Inform the user with OK dialog and reload when this returns (to give some sense of control). + alert('Update found!\n\nApp will reload when you press OK.'); + this.reload(); + }; + this.confirmUpdateWithUser = function (callback) { + if (confirm(`Update available!\n\nAn update is available for this simpleUI.\n\nUse it now?`)) { + callback(true); + } + else { + callback(false); + } + }; + this.reload = function () { + debug.warn('Reloading app...'); + document.body.style = 'color:red;'; + setTimeout(() => window.location.reload(), 1000); + }; +} + diff --git a/sw.js b/sw.js index 358b7b9..487c09b 100644 --- a/sw.js +++ b/sw.js @@ -69,9 +69,9 @@ self.addEventListener('activate', function(event) { }); // Note: does not matter if you stick the index.html in precache or runtime cache. Does not matter which cache stragegy -// you use. First time the app runs it runs it will not be controlled by a service worker. Because the page loads, then +// you use. First time the simpleUI runs it runs it will not be controlled by a service worker. Because the page loads, then // registers the service worker for the first time, which then installs and activates and starts handling fetches from the -// app clients. +// simpleUI clients. // --- // workbox.precaching.precacheAndRoute([ // {"revision":"001","url":"index.html"}, @@ -86,4 +86,6 @@ workbox.routing.registerRoute( ignoreVary: true, } }) -); \ No newline at end of file +); + +