Files
Wegwichtel/public/offline-worker.js
T
Florian Zumpe 5c4d20bd1d
Sonarqube Scanner / Prepare environment (push) Successful in 19s
Sonarqube Scanner / Build and test (push) Successful in 43s
Sonarqube Scanner / SonarQube analysis (push) Failing after 2m28s
Sonarqube Scanner / Deploy to Server (push) Successful in 16s
fix sonar findings and translation structure
2026-10-01 16:31:46 +02:00

40 lines
2.1 KiB
JavaScript

'use strict';
// Serve app files and individually selected route snapshots independently (v2).
importScripts('/js/texts-de.js', '/js/texts-en.js', '/js/i18n.js', '/js/offline-storage.js');
globalThis.addEventListener('install', event => event.waitUntil(globalThis.skipWaiting()));
globalThis.addEventListener('activate', event => event.waitUntil(globalThis.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]));
let end = bytes.byteLength - 1;
if (match[1] && match[2]) end = Math.min(Number(match[2]), end);
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 });
}
globalThis.addEventListener('fetch', event => {
const request = event.request;
const url = new URL(request.url);
if (request.method !== 'GET' || url.origin !== globalThis.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 globalThis.Wegwichtel.OfflineStore.match(request.url).catch(() => null);
if (cached) {
const range = request.headers.get('Range');
return range ? rangedResponse(cached, range) : cached;
}
return fetch(request);
})());
});