'use strict'; const version = new URL(self.location.href).searchParams.get('v') || 'dev'; const cacheName = `ft-plus-static-${version}`; const scopeUrl = new URL(self.registration.scope); const corePaths = [ './', 'index.html', 'flutter_bootstrap.js', 'flutter.js', 'main.dart.js', 'manifest.json', 'assets/AssetManifest.bin.json', 'assets/FontManifest.json', ]; const coreUrls = corePaths.map((path) => new URL(path, scopeUrl).href); const staticPrefixes = [ 'assets/', 'canvaskit/', 'icons/', 'splashes/', ]; const staticFiles = new Set(['favicon.ico', 'manifest.json']); const oldFlutterCaches = new Set([ 'flutter-app-cache', 'flutter-app-manifest', 'flutter-temp-cache', ]); self.addEventListener('install', (event) => { event.waitUntil( caches .open(cacheName) .then((cache) => cache.addAll(coreUrls)) .then(() => self.skipWaiting()), ); }); self.addEventListener('activate', (event) => { event.waitUntil( caches .keys() .then((names) => Promise.all( names .filter( (name) => (name.startsWith('ft-plus-static-') && name !== cacheName) || oldFlutterCaches.has(name), ) .map((name) => caches.delete(name)), ), ) .then(() => self.clients.claim()), ); }); self.addEventListener('fetch', (event) => { const request = event.request; if (request.method !== 'GET') { return; } const url = new URL(request.url); if (url.origin !== scopeUrl.origin || !url.pathname.startsWith(scopeUrl.pathname)) { return; } if (request.mode === 'navigate') { event.respondWith(networkFirst(request, coreUrls[0], false)); return; } const relativePath = url.pathname.slice(scopeUrl.pathname.length); if (isCoreUrl(url.href)) { event.respondWith(networkFirst(request)); } else if (relativePath.startsWith('workers/')) { event.respondWith(networkFirst(request)); } else if ( staticPrefixes.some((prefix) => relativePath.startsWith(prefix)) || staticFiles.has(relativePath) ) { event.respondWith(cacheFirst(request)); } }); function isCoreUrl(url) { return coreUrls.includes(url); } async function networkFirst(request, fallbackUrl, cacheResponse = true) { const cache = await caches.open(cacheName); try { const response = await fetch(request); if (cacheResponse && response.ok) { await cache.put(request, response.clone()); } return response; } catch (error) { const cached = await cache.match(request); if (cached) { return cached; } if (fallbackUrl) { const fallback = await cache.match(fallbackUrl); if (fallback) { return fallback; } } throw error; } } async function cacheFirst(request) { const cache = await caches.open(cacheName); const cached = await cache.match(request); if (cached) { return cached; } const response = await fetch(request); if (response.ok) { await cache.put(request, response.clone()); } return response; }