From 03725d66820d6c7049f25af9e5f8e213e8489d11 Mon Sep 17 00:00:00 2001 From: rene Date: Tue, 26 May 2026 15:52:20 +0200 Subject: [PATCH] =?UTF-8?q?Fix:=20Offline-Pfote=20=E2=80=94=20Step=202+3?= =?UTF-8?q?=20tolerant,=20mehr=20Prefetch,=20SW=20by-v1088?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Steps wurden nicht grün weil Probes zu strikt waren (alle 7 Module bzw. 3 URL-Patterns erforderlich) — Cache-Inhalt zum Refresh- Zeitpunkt oft unvollständig. - Step 2 toleriert 1 fehlendes Page-Modul (have >= want-1) - Step 3 verlangt nur noch Profil ODER welcome-dashboard PLUS Diary ODER Health (nicht beides) - Neuer _prefetchPages() lädt alle 10 Page-Module proaktiv beim App-Start — unabhängig von SW-Install-Status - _prefetchData() wird jetzt mehrmals retried (2s, 5s, 10s, 20s), damit hund-spezifische Daten geholt werden sobald _appState.activeDog gesetzt ist --- backend/main.py | 2 +- backend/static/index.html | 16 +++++----- backend/static/js/app.js | 2 +- backend/static/js/offline-indicator.js | 41 ++++++++++++++++++-------- backend/static/sw.js | 2 +- 5 files changed, 39 insertions(+), 24 deletions(-) diff --git a/backend/main.py b/backend/main.py index 99d431c..75b1945 100644 --- a/backend/main.py +++ b/backend/main.py @@ -410,7 +410,7 @@ async def serve_media(path: str, request: _Request): raise _HE(404, "Nicht gefunden.") return _media_response(filepath) -APP_VER = "1087" # muss mit APP_VER in app.js übereinstimmen +APP_VER = "1088" # muss mit APP_VER in app.js übereinstimmen @app.get("/.well-known/assetlinks.json") async def assetlinks(): diff --git a/backend/static/index.html b/backend/static/index.html index 7abc609..71c53fa 100644 --- a/backend/static/index.html +++ b/backend/static/index.html @@ -101,9 +101,9 @@ - - - + + + @@ -625,11 +625,11 @@ - - - - - + + + + + diff --git a/backend/static/js/app.js b/backend/static/js/app.js index 242695f..1c686c8 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 = '1087'; // ← bei jedem Deploy mit Frontend-Änderungen erhöhen +const APP_VER = '1088'; // ← bei jedem Deploy mit Frontend-Änderungen erhöhen const APP_VERSION = '1.6.0'; // ← semantische Version, wird bei make release gesetzt window.APP_VER = APP_VER; // global verfügbar für andere Module (z.B. offline-indicator) window.APP_VERSION = APP_VERSION; diff --git a/backend/static/js/offline-indicator.js b/backend/static/js/offline-indicator.js index 770367f..20951b3 100644 --- a/backend/static/js/offline-indicator.js +++ b/backend/static/js/offline-indicator.js @@ -31,13 +31,15 @@ window.OfflineIndicator = (() => { } }, { step: 2, title: 'Wichtige Seiten', - detail: 'Tagebuch, Karte, Gassi, Erste Hilfe, Notizblock, Ausgaben, Routen', + detail: 'Tagebuch, Gesundheit, Karte, Gassi, Erste Hilfe, Notizen, Ausgaben, Routen', probe: async () => { const c = await _staticCache(); if (!c) return false; - const must = ['diary.js','map.js','walks.js','erste-hilfe.js','notes.js','expenses.js','routes.js']; + const want = ['diary.js','health.js','map.js','walks.js','erste-hilfe.js', + 'notes.js','expenses.js','routes.js']; const urls = (await c.keys()).map(r => r.url); - return must.every(name => urls.some(u => u.includes('/js/pages/' + name))); + const have = want.filter(name => urls.some(u => u.includes('/js/pages/' + name))); + return have.length >= want.length - 1; // 1 Toleranz (falls einzelner Fetch fehlschlug) } }, { step: 3, title: 'Hund-Daten', @@ -46,9 +48,12 @@ window.OfflineIndicator = (() => { const c = await caches.open(CACHE_API).catch(() => null); if (!c) return false; const urls = (await c.keys()).map(r => r.url); - return urls.some(u => /\/api\/dogs\/\d+(\?|$)/.test(u)) - && urls.some(u => /\/api\/dogs\/\d+\/diary/.test(u)) - && urls.some(u => /\/api\/dogs\/\d+\/health/.test(u)); + const hasProfile = urls.some(u => /\/api\/dogs\/\d+(\?|$)/.test(u)) + || urls.some(u => /\/api\/dogs\/\d+\/welcome-dashboard/.test(u)); + const hasDiary = urls.some(u => /\/api\/dogs\/\d+\/diary/.test(u)); + const hasHealth = urls.some(u => /\/api\/dogs\/\d+\/health/.test(u)); + // Profil + mindestens eine Datenquelle (Tagebuch oder Gesundheit) + return hasProfile && (hasDiary || hasHealth); } }, { step: 4, title: 'Weitere Listen', @@ -207,15 +212,21 @@ window.OfflineIndicator = (() => { } catch {} } - // Daten-Prefetch beim App-Start: Listen die offline brauchbar sein müssen, + // Page-Module proaktiv fetchen — falls SW-Install sie noch nicht alle hatte + function _prefetchPages() { + ['diary','health','map','walks','erste-hilfe','notes','expenses','routes','poison','lost'] + .forEach(p => fetch(`/js/pages/${p}.js?v=${window.APP_VER}`).catch(() => {})); + } + + // Daten-Prefetch: Listen die offline brauchbar sein müssen, // auch wenn der User die Seiten noch nie geöffnet hat - async function _prefetchData() { + function _prefetchData() { fetch('/api/expenses').catch(() => {}); fetch('/api/routes').catch(() => {}); fetch('/api/notes').catch(() => {}); - // Hund-spezifische Daten nur wenn aktiver Hund bekannt const dogId = window._appState?.activeDog?.id; if (dogId) { + fetch(`/api/dogs/${dogId}`).catch(() => {}); fetch(`/api/dogs/${dogId}/health`).catch(() => {}); fetch(`/api/dogs/${dogId}/diary?limit=20`).catch(() => {}); } @@ -223,11 +234,15 @@ window.OfflineIndicator = (() => { function init() { refresh(); - _prefetchTiles(); // Karten-Tiles (nur wenn GPS schon erlaubt) - _prefetchData(); // Listen-Daten (Expenses, Routes, Notes, Health) + _prefetchPages(); + _prefetchTiles(); + _prefetchData(); - // Wenn der aktive Hund erst nach init() gesetzt wird → nochmal triggern - setTimeout(() => { _prefetchData(); refresh(); }, 3000); + // Mehrere Retries für hund-spezifische Daten — _appState.activeDog wird oft + // erst nach Login/Hunde-Load gesetzt, manchmal mehrere Sekunden nach Init + [2_000, 5_000, 10_000, 20_000].forEach(delay => { + setTimeout(() => { _prefetchData(); refresh(); }, delay); + }); if (navigator.serviceWorker) { navigator.serviceWorker.addEventListener('message', e => { diff --git a/backend/static/sw.js b/backend/static/sw.js index 16ae848..e52aa25 100644 --- a/backend/static/sw.js +++ b/backend/static/sw.js @@ -4,7 +4,7 @@ ============================================================ */ // ← EINZIGE Stelle für die Version — STATIC_ASSETS und CACHE_VERSION leiten sich ab -const VER = '1087'; +const VER = '1088'; const CACHE_VERSION = `by-v${VER}`; const CACHE_STATIC = `${CACHE_VERSION}-static`; const CACHE_TILES = 'ban-yaro-tiles-v1'; // bleibt über SW-Updates erhalten