diff --git a/addon/components/service-worker-update-notify.js b/addon/components/service-worker-update-notify.js index 17bc2fc..95d4f85 100644 --- a/addon/components/service-worker-update-notify.js +++ b/addon/components/service-worker-update-notify.js @@ -1,17 +1,53 @@ -import Ember from 'ember' +import Component from '@ember/component'; +import { isEmpty } from '@ember/utils'; +import { task, timeout } from 'ember-concurrency'; + import layout from '../templates/components/service-worker-update-notify' import serviceWorkerHasUpdate from '../utils/service-worker-has-update' -export default Ember.Component.extend({ +export default Component.extend({ layout, + pollingInterval: 1200000, // 20 minutes in ms tagName: '', hasUpdate: false, - didInsertElement() { + /** + * Delay attaching the updateHandler to prevent users from + * seeing a new build notification immediately on page load. + */ + setupTask: task(function*() { + const hasServiceWorker = 'serviceWorker' in navigator; + const supportsPromises = 'Promise' in window; + + if (hasServiceWorker && supportsPromises) { + yield timeout(this.pollingInterval); + this._attachUpdateHandler(); + + const polling = this.pollingTask.perform(); + + this.set('polling', polling); + } + }).on('didInsertElement'), + + pollingTask: task(function*() { + while (true) { + const reg = yield navigator.serviceWorker.register('/sw.js', { scope: '/' }); + + reg.update(); + + yield timeout(this.pollingInterval); + } + }), + + _attachUpdateHandler() { serviceWorkerHasUpdate().then(hasUpdate => { - this.set('hasUpdate', hasUpdate) - }) - }, -}) + if (!isEmpty(this.polling)) { + this.polling.cancel(); + } + + this.set('hasUpdate', hasUpdate); + }); + } +}); diff --git a/package.json b/package.json index 8589baa..8b10061 100644 --- a/package.json +++ b/package.json @@ -2,15 +2,17 @@ "name": "ember-service-worker-update-notify", "version": "1.0.2", "description": "Update notification for service workers", - "keywords": ["ember-addon", "ember-service-worker-plugin"], + "keywords": [ + "ember-addon", + "ember-service-worker-plugin" + ], "license": "MIT", "author": "Damian Senn ", "directories": { "doc": "doc", "test": "tests" }, - "repository": - "https://github.com/topaxi/ember-service-worker-update-notify.git", + "repository": "https://github.com/topaxi/ember-service-worker-update-notify.git", "scripts": { "build": "ember build", "start": "ember server", @@ -32,6 +34,7 @@ "ember-cli-shims": "^1.1.0", "ember-cli-sri": "^2.1.0", "ember-cli-uglify": "^1.2.0", + "ember-concurrency": "^0.8.21", "ember-disable-prototype-extensions": "^1.1.2", "ember-export-application-global": "^2.0.0", "ember-load-initializers": "^1.0.0", @@ -39,6 +42,9 @@ "ember-source": "~2.14.1", "loader.js": "^4.2.3" }, + "peerDependencies": { + "ember-concurrency": "^0.8.21" + }, "engines": { "node": "^4.5 || 6.* || >= 7.*" }, diff --git a/service-worker-registration/index.js b/service-worker-registration/index.js index 386f2ea..279386e 100644 --- a/service-worker-registration/index.js +++ b/service-worker-registration/index.js @@ -1,24 +1,30 @@ import { addSuccessHandler } from 'ember-service-worker/service-worker-registration' -window.hasServiceWorkerUpdate = - 'Promise' in window - ? new Promise(function hasServiceWorkerUpdate(resolve) { - addSuccessHandler(function emberServiceWorkerUpdateNotifyRegistration( - reg, - ) { - reg.onupdatefound = function serviceWorkerHasFoundUpdate() { - const { installing } = reg +function hasServiceWorkerUpdate(resolve) { + addSuccessHandler(function(reg) { + reg.onupdatefound = function() { + const { installing } = reg; - installing.onstatechange = function installingServiceWorkerStateChange() { - if (installing.state === 'installed') { - resolve(navigator.serviceWorker.controller !== null) - } - } - } - }) - }) - : { - then: function() { - return false - }, + installing.onstatechange = function() { + if (installing.state === 'activated') { + resolve(navigator.serviceWorker.controller !== null) + } } + } + }); +} + +// https://caniuse.com/#search=Promise +// IE11 (2.5%) and Opera Mini (2.3%) do not support Promises +const arePromisesSupported = 'Promise' in window; +const disablePolyfill = ({ + then: function() { + return false; + } +}); + +window.hasServiceWorkerUpdate = + arePromisesSupported + ? new Promise(hasServiceWorkerUpdate) + : disablePolyfill +