// JGA Prag 2026 — Service Worker // Cache-Strategie: cache-first für HTML/Assets, network-first für externe APIs (OSRM) const CACHE_VERSION = 'jga-2026-v1'; const CORE_ASSETS = [ './', './index.html', './tourenplan.html', './tourenplan-mit-tram.html', './wetter.html', './packliste.html', './manifest.json' ]; // Install: alle Core-Files cachen self.addEventListener('install', (event) => { event.waitUntil( caches.open(CACHE_VERSION) .then(cache => cache.addAll(CORE_ASSETS)) .then(() => self.skipWaiting()) ); }); // Activate: alte Caches aufräumen self.addEventListener('activate', (event) => { event.waitUntil( caches.keys() .then(keys => Promise.all( keys.filter(k => k !== CACHE_VERSION).map(k => caches.delete(k)) )) .then(() => self.clients.claim()) ); }); // Fetch: cache-first für eigene Files, network-first für externe APIs self.addEventListener('fetch', (event) => { const url = new URL(event.request.url); // Externe APIs (OSRM, OpenStreetMap, Wetter) → network-first if (url.origin !== self.location.origin) { event.respondWith( fetch(event.request) .then(response => { // Erfolgreich: clone & cache für offline if (response.ok && (url.hostname.includes('openstreetmap') || url.hostname.includes('cartocdn') || url.hostname.includes('unpkg'))) { const clone = response.clone(); caches.open(CACHE_VERSION).then(c => c.put(event.request, clone)); } return response; }) .catch(() => caches.match(event.request)) ); return; } // Eigene Files → cache-first event.respondWith( caches.match(event.request) .then(cached => cached || fetch(event.request) .then(response => { if (response.ok) { const clone = response.clone(); caches.open(CACHE_VERSION).then(c => c.put(event.request, clone)); } return response; }) ) ); });