add offline support
This commit is contained in:
@@ -0,0 +1,38 @@
|
||||
'use strict';
|
||||
// Serve app files and individually selected route snapshots independently (v2).
|
||||
importScripts('/js/offline-storage.js');
|
||||
|
||||
self.addEventListener('install', event => event.waitUntil(self.skipWaiting()));
|
||||
self.addEventListener('activate', event => event.waitUntil(self.clients.claim()));
|
||||
|
||||
/** Audio seeks need partial responses even when the entire file is stored locally. */
|
||||
async function rangedResponse(response, range) {
|
||||
const bytes = await response.arrayBuffer();
|
||||
const match = /^bytes=(\d*)-(\d*)$/.exec(range);
|
||||
if (!match || (!match[1] && !match[2])) return new Response(null, { status: 416, headers: { 'Content-Range': `bytes */${bytes.byteLength}` } });
|
||||
const start = match[1] ? Number(match[1]) : Math.max(0, bytes.byteLength - Number(match[2]));
|
||||
const end = match[1] ? (match[2] ? Math.min(Number(match[2]), bytes.byteLength - 1) : bytes.byteLength - 1) : bytes.byteLength - 1;
|
||||
if (start > end || start >= bytes.byteLength) return new Response(null, { status: 416, headers: { 'Content-Range': `bytes */${bytes.byteLength}` } });
|
||||
const headers = new Headers(response.headers);
|
||||
headers.set('Content-Range', `bytes ${start}-${end}/${bytes.byteLength}`);
|
||||
headers.set('Content-Length', String(end - start + 1));
|
||||
headers.set('Accept-Ranges', 'bytes');
|
||||
return new Response(bytes.slice(start, end + 1), { status: 206, headers });
|
||||
}
|
||||
|
||||
self.addEventListener('fetch', event => {
|
||||
const request = event.request;
|
||||
const url = new URL(request.url);
|
||||
if (request.method !== 'GET' || url.origin !== self.location.origin
|
||||
|| request.headers.has('X-Wegwichtel-Offline-Download')
|
||||
|| url.pathname === '/api/offline-manifest') return;
|
||||
event.respondWith((async () => {
|
||||
// A complete snapshot is cache-first, avoiding any wait for a failing mobile network.
|
||||
const cached = await self.Wegwichtel.OfflineStore.match(request.url).catch(() => null);
|
||||
if (cached) {
|
||||
const range = request.headers.get('Range');
|
||||
return range ? rangedResponse(cached, range) : cached;
|
||||
}
|
||||
return fetch(request);
|
||||
})());
|
||||
});
|
||||
Reference in New Issue
Block a user