diff --git a/backend/main.py b/backend/main.py index cb3a5d4..a8b3f89 100644 --- a/backend/main.py +++ b/backend/main.py @@ -327,7 +327,7 @@ MEDIA_DIR = os.getenv("MEDIA_DIR", "/data/media") os.makedirs(MEDIA_DIR, exist_ok=True) app.mount("/media", StaticFiles(directory=MEDIA_DIR), name="media") -APP_VER = "761" # muss mit APP_VER in app.js übereinstimmen +APP_VER = "762" # muss mit APP_VER in app.js übereinstimmen @app.get("/api/version") async def app_version(): @@ -848,7 +848,7 @@ async def share_target(request: Request): # Weiterleitung zur App mit den Daten return FileResponse( f"{STATIC_DIR}/index.html", - headers={"Cache-Control": "no-cache"} + headers={"Cache-Control": "no-store, no-cache"} ) # Öffentliche Hunde-Profilseite (für NFC-Tags, kein Login nötig) @@ -1182,17 +1182,17 @@ async def public_dog_page(dog_id: int): # ------------------------------------------------------------------ @app.get("/teilen/{token}") async def invite_page(token: str): - return FileResponse(f"{STATIC_DIR}/index.html", headers={"Cache-Control": "no-cache"}) + return FileResponse(f"{STATIC_DIR}/index.html", headers={"Cache-Control": "no-store, no-cache"}) @app.get("/breeder/{zwingername}") async def breeder_profile_page(zwingername: str): - return FileResponse(f"{STATIC_DIR}/index.html", headers={"Cache-Control": "no-cache"}) + return FileResponse(f"{STATIC_DIR}/index.html", headers={"Cache-Control": "no-store, no-cache"}) @app.get("/litters") async def litters_page(): - return FileResponse(f"{STATIC_DIR}/index.html", headers={"Cache-Control": "no-cache"}) + return FileResponse(f"{STATIC_DIR}/index.html", headers={"Cache-Control": "no-store, no-cache"}) # ------------------------------------------------------------------ @@ -1200,7 +1200,7 @@ async def litters_page(): # ------------------------------------------------------------------ @app.get("/widget") async def widget_page(): - return FileResponse(f"{STATIC_DIR}/index.html", headers={"Cache-Control": "no-cache"}) + return FileResponse(f"{STATIC_DIR}/index.html", headers={"Cache-Control": "no-store, no-cache"}) # ------------------------------------------------------------------ @@ -1726,7 +1726,7 @@ async def partner_landing(): """ - return HTMLResponse(content=html, headers={"Cache-Control": "no-cache"}) + return HTMLResponse(content=html, headers={"Cache-Control": "no-store, no-cache"}) # ------------------------------------------------------------------ @@ -1924,8 +1924,8 @@ async def spa_fallback(full_path: str): '', '', ) - return HTMLResponse(content=html, headers={"Cache-Control": "no-cache"}) + return HTMLResponse(content=html, headers={"Cache-Control": "no-store, no-cache"}) return FileResponse( f"{STATIC_DIR}/index.html", - headers={"Cache-Control": "no-cache"} + headers={"Cache-Control": "no-store, no-cache"} ) diff --git a/backend/static/index.html b/backend/static/index.html index 7224f77..7368cc9 100644 --- a/backend/static/index.html +++ b/backend/static/index.html @@ -578,7 +578,7 @@ - + @@ -640,7 +640,8 @@ // Wenn neuer SW die Kontrolle übernimmt → Seite neu laden navigator.serviceWorker.addEventListener('controllerchange', () => { - window.location.reload(); + // location.replace statt reload() — bypassed iOS bfcache + window.location.replace(window.location.href); }); navigator.serviceWorker.addEventListener('message', e => { diff --git a/backend/static/js/app.js b/backend/static/js/app.js index 87d6ada..29bb7fb 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 = '761'; // ← bei jedem Deploy mit Frontend-Änderungen erhöhen +const APP_VER = '762'; // ← bei jedem Deploy mit Frontend-Änderungen erhöhen const APP_VERSION = '1.5.0'; // ← semantische Version, wird bei make release gesetzt const IS_STAGING = location.hostname === 'staging.banyaro.app'; @@ -1045,7 +1045,8 @@ const App = (() => { const keys = await caches.keys(); await Promise.all(keys.map(k => caches.delete(k))); } catch { /* ignorieren */ } - setTimeout(() => location.reload(), 600); + // location.replace bypassed iOS bfcache (reload() stellt alte Seite wieder her) + setTimeout(() => location.replace(location.href), 600); }); } diff --git a/backend/static/sw.js b/backend/static/sw.js index d3b9934..acf1e4f 100644 --- a/backend/static/sw.js +++ b/backend/static/sw.js @@ -3,7 +3,7 @@ Offline-Cache + Push Notifications + Tile-Cache ============================================================ */ -const CACHE_VERSION = 'by-v761'; +const CACHE_VERSION = 'by-v762'; 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 @@ -344,6 +344,10 @@ self.addEventListener('sync', event => { // MESSAGE — Tile-Vorausladung (Offline-Speicherung) + Queue-Steuerung // ---------------------------------------------------------- self.addEventListener('message', event => { + if (event.data?.type === 'SKIP_WAITING') { + self.skipWaiting(); + return; + } if (event.data?.type === 'PROCESS_QUEUE') { event.waitUntil(_processQueue()); return;