diff --git a/views/index.html b/views/index.html index c13584043bf..dbff801392f 100644 --- a/views/index.html +++ b/views/index.html @@ -729,29 +729,11 @@ console.log('Service worker registered'); reg.addEventListener('updatefound', () => { console.log('Service worker update detected'); + reg.update(); const newWorker = reg.installing; - var reloaded; - - newWorker.addEventListener('statechange', (stateEvent) => { - console.log('New worker state change', stateEvent.currentTarget.state, stateEvent); - - if (stateEvent.currentTarget.state == 'installed') { - // `controller` should be assigned if an active worker already exists - if (navigator.serviceWorker.controller) { - // a new worker was activated, so refresh the page - if (reloaded) { - // needed to prevent reload loops with `update on reload` option in dev tools - return; - } - - console.log('New service worker installed, refreshing'); - reloaded = true; - window.location.reload(true); - } else { - // there was no active worker, so it was cached and no refresh is necessary - console.log('Service worker cached'); - } - } + newWorker.addEventListener('statechange', (state) => { + console.log('New worker state change', state); + window.location.reload(true); }); }); }).catch(function(error) { diff --git a/views/service-worker.js b/views/service-worker.js index ef28360abaf..41b5043897e 100644 --- a/views/service-worker.js +++ b/views/service-worker.js @@ -38,10 +38,57 @@ const CACHE_LIST = [ '/images/logo2.png' ]; -// Open a cache and use `addAll()` with an array of assets to add all of them -// to the cache. Return a promise resolving when all the assets are added. +function returnRangeRequest(request) { + return caches + .open(CACHE) + .then((cache) => { + return cache.match(request.url); + }) + .then((res) => { + if (!res) { + return fetch(request) + .then(res => { + const clonedRes = res.clone(); + return caches + .open(CACHE) + .then(cache => cache.put(request, clonedRes)) + .then(() => res); + }) + .then(res => { + return res.arrayBuffer(); + }); + } + return res.arrayBuffer(); + }) + .then((arrayBuffer) => { + const bytes = /^bytes=(\d+)-(\d+)?$/g.exec( + request.headers.get('range') + ); + if (bytes) { + const start = Number(bytes[1]); + const end = Number(bytes[2]) || arrayBuffer.byteLength - 1; + return new Response(arrayBuffer.slice(start, end + 1), { + status: 206, + statusText: 'Partial Content', + headers: [ + ['Content-Range', `bytes ${start}-${end}/${arrayBuffer.byteLength}`] + ] + }); + } else { + return new Response(null, { + status: 416, + statusText: 'Range Not Satisfiable', + headers: [['Content-Range', `*/${arrayBuffer.byteLength}`]] + }); + } + }); +} + +// Open a cache and `put()` the assets to the cache. +// Return a promise resolving when all the assets are added. function precache() { - return caches.open(CACHE).then(function (cache) { + return caches.open(CACHE) + .then((cache) => { // if any cache requests fail, don't interrupt other requests in progress return Promise.allSettled( CACHE_LIST.map((url) => { @@ -59,50 +106,43 @@ function precache() { }); } -// Open the cache where the assets were stored and search for the requested -// resource. Notice that in case of no matching, the promise still resolves -// but it does with `undefined` as value. -function fromCache(request) { - return caches.open(CACHE).then(function (cache) { - return cache.match(request).then(function (matching) { - return matching || Promise.reject('no-match'); - }); - }); -} - -// Update consists in opening the cache, performing a network request and -// storing the new response data. -function update(request) { - return caches.open(CACHE).then(function (cache) { - return fetch(request).then(function (response) { - return cache.put(request, response); - }); - }); -} - // Try to read the requested resource from cache. // If the requested resource does not exist in the cache, fetch it from // network and cache the response. -function fromCacheOrUpdate(request) { - return caches.open(CACHE).then(function (cache) { - return cache.match(request).then(function (cacheResponse) { - return cacheResponse || fetch(request).then(function (netResponse) { - cache.put(request, netResponse.clone()); - return netResponse; +function fromCache(request) { + return caches.open(CACHE).then((cache) => { + return cache.match(request).then((matching) => { + console.log(matching); + if(matching){ + return matching; + } + + return fetch(request).then((response) => { + // console.log('Response from network is:', response); + cache.put(request, response.clone()); + return response; + }).catch((error) => { + // This catch() will handle exceptions thrown from the fetch() operation. + // Note that a HTTP error response (e.g. 404) will NOT trigger an exception. + // It will return a normal response object that has the appropriate error code set. + console.error('Fetching failed:', error); + + throw error; }); }); }); } // On install, cache some resources. -self.addEventListener('install', function(evt) { - console.log('The service worker is being installed.'); +self.addEventListener('install', (evt) => { + // console.log('The service worker is being installed.'); + self.skipWaiting(); evt.waitUntil(precache()); }); function inCache(request) { let found = false; - CACHE_LIST.forEach( function (e) { + CACHE_LIST.forEach((e) => { if (request.url.endsWith(e)) { found = true; } @@ -110,38 +150,29 @@ function inCache(request) { return found; } -self.addEventListener('fetch', function(evt) { +self.addEventListener('fetch', (evt) => { if (!evt.request.url.startsWith(self.location.origin) || CACHE === 'developmentMode' || !inCache(evt.request) || evt.request.method !== 'GET') { - // console.log('Skipping cache for', evt.request.url); - evt.respondWith(fetch(evt.request)); + //console.log('Skipping cache for ', evt.request.url); + return void evt.respondWith(fetch(evt.request)); + } + if (evt.request.headers.get('range')) { + evt.respondWith(returnRangeRequest(evt.request)); } else { - var request = evt.request; - if (evt.request.headers.has('Range')) { - // Firefox will give an error if it tries to store partial content (206) responses in the cache. - // To mitigate this, strip the `Range` header from the request so a full document (200) is returned. - var strippedHeaders = new Headers(evt.request.headers).delete('Range'); - request = new Request(evt.request, { headers: strippedHeaders }); - } - // console.log('Using cache for', evt.request); - evt.respondWith(fromCacheOrUpdate(request)); + evt.respondWith(fromCache(evt.request)); } }); self.addEventListener('activate', (event) => { event.waitUntil( caches.keys().then((cacheNames) => { - if (!cacheNames) { - // Fallback to an empty array if cache is empty. - // This can occur if the prefetch fails. - return []; - } + return Promise.all( + cacheNames.map((cacheName) => { + if (cacheName !== CACHE) { + // console.log('Deleting out of date cache:', cacheName); + return caches.delete(cacheName); + } + }) + ); + })); - return cacheNames.filter((cacheName) => CACHE !== cacheName); - }).then((unusedCaches) => { - // console.log('DESTROYING CACHE', unusedCaches.join(',')); - return Promise.all(unusedCaches.map((unusedCache) => { - return caches.delete(unusedCache); - })); - }).then(() => self.clients.claim()) - ); -}); \ No newline at end of file +});