diff --git a/backend/main.py b/backend/main.py index 9ba2d37..da0e0ae 100644 --- a/backend/main.py +++ b/backend/main.py @@ -408,7 +408,7 @@ async def serve_media(path: str, request: _Request): raise _HE(404, "Nicht gefunden.") return _media_response(filepath) -APP_VER = "982" # muss mit APP_VER in app.js übereinstimmen +APP_VER = "983" # muss mit APP_VER in app.js übereinstimmen @app.get("/.well-known/assetlinks.json") async def assetlinks(): diff --git a/backend/static/js/app.js b/backend/static/js/app.js index b93c518..b33aa1b 100644 --- a/backend/static/js/app.js +++ b/backend/static/js/app.js @@ -3,7 +3,7 @@ Router, State-Management, Navigation, Initialisierung. ============================================================ */ -const APP_VER = '982'; // ← bei jedem Deploy mit Frontend-Änderungen erhöhen +const APP_VER = '983'; // ← bei jedem Deploy mit Frontend-Änderungen erhöhen const APP_VERSION = '1.6.0'; // ← semantische Version, wird bei make release gesetzt const IS_STAGING = location.hostname === 'staging.banyaro.app'; // Cache-Bust-Parameter nach Update-Reload sofort entfernen diff --git a/backend/static/sw.js b/backend/static/sw.js index 8136c8e..6fb938c 100644 --- a/backend/static/sw.js +++ b/backend/static/sw.js @@ -3,12 +3,12 @@ Offline-Cache + Push Notifications + Tile-Cache ============================================================ */ -const CACHE_VERSION = 'by-v982'; +const CACHE_VERSION = 'by-v983'; const CACHE_STATIC = `${CACHE_VERSION}-static`; const CACHE_TILES = 'ban-yaro-tiles-v1'; // bleibt über SW-Updates erhalten const CACHE_API = 'ban-yaro-api-v1'; // API-Response-Cache -// Prioritäts-Seiten: werden pre-gecacht + Stale-While-Revalidate +// Prioritäts-Seiten: werden nach Install im Hintergrund gecacht (nicht blockierend) const PRIORITY_PAGES = [ '/js/pages/admin.js', '/js/pages/erste-hilfe.js', @@ -22,9 +22,9 @@ const PRIORITY_PAGES = [ // index.html wird NICHT pre-gecacht (immer Network-First) const STATIC_ASSETS = [ - '/css/design-system.css?v=980', - '/css/layout.css?v=980', - '/css/components.css?v=980', + '/css/design-system.css?v=982', + '/css/layout.css?v=982', + '/css/components.css?v=982', '/icons/phosphor.svg', '/js/api.js', '/js/ui.js', @@ -34,7 +34,6 @@ const STATIC_ASSETS = [ '/css/MarkerCluster.Default.css', '/manifest.json', '/icons/icon-192.png', - ...PRIORITY_PAGES, ]; // ---------------------------------------------------------- @@ -175,13 +174,22 @@ function _cacheMark(pathname) { // INSTALL — App Shell cachen // ---------------------------------------------------------- self.addEventListener('install', event => { - self.skipWaiting(); // Sofort übernehmen — kein Warten auf Cache-Aufbau + self.skipWaiting(); event.waitUntil( caches.open(CACHE_STATIC) .then(cache => cache.addAll(STATIC_ASSETS)) - .then(() => caches.open(CACHE_API).then(c => - fetch('/api/training/exercises').then(r => { if (r.ok) c.put('/api/training/exercises', r); }).catch(() => {}) - )) + .then(() => { + // Prioritäts-Seiten nicht-blockierend im Hintergrund cachen + caches.open(CACHE_STATIC).then(cache => { + PRIORITY_PAGES.forEach(page => + fetch(page).then(r => { if (r.ok) cache.put(page, r.clone()); }).catch(() => {}) + ); + }); + // Training-Exercises vorwärmen + return caches.open(CACHE_API).then(c => + fetch('/api/training/exercises').then(r => { if (r.ok) c.put('/api/training/exercises', r); }).catch(() => {}) + ); + }) ); }); @@ -310,21 +318,7 @@ self.addEventListener('fetch', event => { return; } - // Prioritäts-Seiten: Stale-While-Revalidate — sofort aus Cache, im Hintergrund aktualisieren - if (PRIORITY_PAGES.includes(url.pathname)) { - event.respondWith( - caches.open(CACHE_STATIC).then(async cache => { - const cached = await cache.match(event.request, { ignoreSearch: true }); - const netFetch = fetch(event.request) - .then(res => { if (res.ok) cache.put(event.request, res.clone()); return res; }) - .catch(() => null); - return cached ?? (await netFetch) ?? new Response('', { status: 503 }); - }) - ); - return; - } - - // CSS, Core-JS + übrige Seiten-Module: Network-First — damit iOS nie veraltete Versionen cached + // CSS, Core-JS + Seiten-Module: Network-First mit ignoreSearch-Fallback für Offline if (url.pathname.startsWith('/css/') || url.pathname.startsWith('/js/pages/') || url.pathname.startsWith('/js/app.js') || url.pathname.startsWith('/js/ui.js') || url.pathname.startsWith('/js/api.js') || url.pathname.startsWith('/js/worlds.js')) {