@@ -187,6 +191,8 @@
import NamespaceService from './services/namespace'
import authTypes from './models/authTypes'
+ import swEvents from './ServiceWorker/events'
+
export default {
name: 'app',
@@ -201,6 +207,11 @@
userMenuActive: false,
authTypes: authTypes,
isOnline: true,
+
+ // Service Worker stuff
+ updateAvailable: false,
+ registration: null,
+ refreshing: false,
}
},
beforeMount() {
@@ -226,6 +237,17 @@
if (auth.user.authenticated && auth.user.infos.type === authTypes.USER && (this.$route.params.name === 'home' || this.namespaces.length === 0)) {
this.loadNamespaces()
}
+
+ // Service worker communication
+ document.addEventListener(swEvents.SW_UPDATED, this.showRefreshUI, { once: true })
+
+ navigator.serviceWorker.addEventListener(
+ 'controllerchange', () => {
+ if (this.refreshing) return;
+ this.refreshing = true;
+ window.location.reload();
+ }
+ );
},
watch: {
// call the method again if the route changes
@@ -261,6 +283,17 @@
setFullPage() {
this.fullpage = true;
},
+ showRefreshUI (e) {
+ console.log('recieved refresh event', e)
+ this.registration = e.detail;
+ this.updateAvailable = true;
+ },
+ refreshApp () {
+ this.updateExists = false;
+ if (!this.registration || !this.registration.waiting) { return; }
+ // Notify the service worker to actually do the update
+ this.registration.waiting.postMessage('skipWaiting');
+ },
},
}
diff --git a/src/ServiceWorker/events.json b/src/ServiceWorker/events.json
new file mode 100644
index 00000000..73ac1c51
--- /dev/null
+++ b/src/ServiceWorker/events.json
@@ -0,0 +1,3 @@
+{
+ "SW_UPDATED": "swUpdated"
+}
\ No newline at end of file
diff --git a/src/ServiceWorker/sw.js b/src/ServiceWorker/sw.js
index 32c114a0..8d772494 100644
--- a/src/ServiceWorker/sw.js
+++ b/src/ServiceWorker/sw.js
@@ -19,3 +19,24 @@ workbox.routing.registerRoute(
new RegExp('.*'),
new workbox.strategies.StaleWhileRevalidate()
);
+
+// This code listens for the user's confirmation to update the app.
+self.addEventListener('message', (e) => {
+ if (!e.data) {
+ return;
+ }
+
+ switch (e.data) {
+ case 'skipWaiting':
+ self.skipWaiting();
+ break;
+ default:
+ // NOOP
+ break;
+ }
+});
+
+workbox.core.clientsClaim();
+// The precaching code provided by Workbox.
+self.__precacheManifest = [].concat(self.__precacheManifest || []);
+workbox.precaching.precacheAndRoute(self.__precacheManifest, {});
diff --git a/src/registerServiceWorker.js b/src/registerServiceWorker.js
index 0ee6d40f..ef9b0eb1 100644
--- a/src/registerServiceWorker.js
+++ b/src/registerServiceWorker.js
@@ -1,13 +1,12 @@
/* eslint-disable no-console */
import { register } from 'register-service-worker'
+import swEvents from './ServiceWorker/events'
if (process.env.NODE_ENV === 'production') {
register(`${process.env.BASE_URL}sw.js`, {
ready () {
- console.log(
- 'App is being served from cache by a service worker.'
- )
+ console.log('App is being served from cache by a service worker.')
},
registered () {
console.log('Service worker has been registered.')
@@ -18,8 +17,12 @@ if (process.env.NODE_ENV === 'production') {
updatefound () {
console.log('New content is downloading.')
},
- updated () {
+ updated (registration) {
console.log('New content is available; please refresh.')
+ // Send an event with the updated info
+ document.dispatchEvent(
+ new CustomEvent(swEvents.SW_UPDATED, { detail:registration })
+ )
},
offline () {
console.log('No internet connection found. App is running in offline mode.')
diff --git a/src/styles/theme.scss b/src/styles/theme.scss
index a6cb8bf1..b724a7c0 100644
--- a/src/styles/theme.scss
+++ b/src/styles/theme.scss
@@ -288,3 +288,18 @@ h1,h2,h3,h4,h5,h6{
height: 18px;
}
}
+
+.update-notification {
+ margin: 1em;
+ display: flex;
+ align-items: center;
+ background: $warning;
+ padding: 0 0 0 .5em;
+ border-radius: $radius;
+ font-size: .9em;
+ color: darken($dark, 5);
+
+ .button {
+ margin-left: .5em;
+ }
+}