diff --git a/backend/main.py b/backend/main.py index 16a03e5..a1b570f 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 = "988" # muss mit APP_VER in app.js übereinstimmen +APP_VER = "987" # 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 70a91b3..98b2a41 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 = '988'; // ← bei jedem Deploy mit Frontend-Änderungen erhöhen +const APP_VER = '987'; // ← 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/js/pages/diary.js b/backend/static/js/pages/diary.js index c708912..f04bf67 100644 --- a/backend/static/js/pages/diary.js +++ b/backend/static/js/pages/diary.js @@ -6,8 +6,6 @@ window.Page_diary = (() => { - const _CACHE_KEY = 'by_diary_cache'; - // ---------------------------------------------------------- // MODUL-STATE // ---------------------------------------------------------- @@ -326,7 +324,6 @@ window.Page_diary = (() => { async function _load() { const dog = _appState.activeDog; if (!dog) return; - const cacheKey = _CACHE_KEY + '_' + dog.id; try { const params = { limit: LIMIT, offset: _offset }; if (_searchQuery) params.q = _searchQuery; @@ -334,10 +331,6 @@ window.Page_diary = (() => { const batch = await API.diary.list(dog.id, params); _entries = _entries.concat(batch); - if (_offset === 0 && !_searchQuery && !_filterMilestone) { - try { localStorage.setItem(cacheKey, JSON.stringify({ ts: Date.now(), data: batch })); } catch {} - } - // "Mehr laden" anzeigen wenn volle Page geladen wurde const loadMore = _container.querySelector('#diary-load-more'); if (loadMore) { @@ -346,17 +339,7 @@ window.Page_diary = (() => { // Stats-Bar befüllen _renderStatsBar(); - } catch { - try { - const raw = localStorage.getItem(cacheKey); - if (raw) { - const cached = JSON.parse(raw).data || []; - _entries = cached; - _renderStatsBar(); - UI.toast.info('Offline — zeige zuletzt geladene Einträge.'); - return; - } - } catch {} + } catch (err) { UI.toast.error('Einträge konnten nicht geladen werden.'); } } diff --git a/backend/static/js/pages/lost.js b/backend/static/js/pages/lost.js index 37daa9f..086224e 100644 --- a/backend/static/js/pages/lost.js +++ b/backend/static/js/pages/lost.js @@ -5,43 +5,6 @@ window.Page_lost = (() => { - // ---------------------------------------------------------- - // OFFLINE-CACHE - // ---------------------------------------------------------- - const _CACHE_KEY = 'by_lost_cache'; - const _PENDING_KEY = 'by_lost_pending'; - - function _getPending() { - try { return JSON.parse(localStorage.getItem(_PENDING_KEY) || '[]'); } catch { return []; } - } - function _setPending(list) { - try { localStorage.setItem(_PENDING_KEY, JSON.stringify(list)); } catch {} - } - function _addPending(data) { - const list = _getPending(); - const entry = { ...data, id: `pending_${Date.now()}`, _isPending: true, - created_at: new Date().toISOString() }; - list.push(entry); - _setPending(list); - return entry; - } - async function _syncPending() { - if (!navigator.onLine) return; - const list = _getPending(); - if (!list.length) return; - let ok = 0; - for (const item of [...list]) { - try { - const { id: _pid, _isPending, ...payload } = item; - await API.lost.report(payload); - _setPending(_getPending().filter(x => x.id !== item.id)); - ok++; - } catch {} - } - if (ok > 0) { UI.toast.success(`${ok} Meldung(en) synchronisiert.`); _loadReports(); } - } - window.addEventListener('online', _syncPending); - // ---------------------------------------------------------- // MODUL-STATE // ---------------------------------------------------------- @@ -216,14 +179,8 @@ window.Page_lost = (() => { return; } - const pending = _getPending().map(p => ({ - ...p, - distanz_m: _haversine(_userPos.lat, _userPos.lon, p.lat, p.lon), - })); try { - const fetched = await API.lost.list(_userPos.lat, _userPos.lon, 25); - try { localStorage.setItem(_CACHE_KEY, JSON.stringify({ ts: Date.now(), data: fetched })); } catch {} - _reports = [...pending, ...fetched]; + _reports = await API.lost.list(_userPos.lat, _userPos.lon, 25); _renderMarkers(); _renderHeld(); _renderList(); @@ -234,26 +191,6 @@ window.Page_lost = (() => { : 'Keine vermissten Hunde in deiner Nähe (25 km Radius). 🐾'; } } catch { - try { - const raw = localStorage.getItem(_CACHE_KEY); - if (raw) { - _reports = [...pending, ...(JSON.parse(raw).data || [])]; - _renderMarkers(); - _renderHeld(); - _renderList(); - _updateBadge(_reports.length); - if (infoEl) infoEl.textContent = 'Offline — zeige zuletzt geladene Meldungen.'; - return; - } - } catch {} - _reports = pending; - if (pending.length) { - _renderMarkers(); - _renderHeld(); - _renderList(); - _updateBadge(_reports.length); - return; - } UI.toast.error('Meldungen konnten nicht geladen werden.'); } } @@ -395,7 +332,6 @@ window.Page_lost = (() => { Gemeldet ${_fmtDate(r.created_at)} ${r.melder_name ? '· ' + _escape(r.melder_name.split(' ')[0]) : ''} - ${r._isPending ? `
⏳ Sync ausstehend
` : ''} ${_appState.user ? `
@@ -1182,24 +1128,15 @@ window.Page_walks = (() => { const idx = _data.findIndex(w => w.id === walk.id); if (idx !== -1) _data[idx] = { ..._data[idx], ...updated }; UI.toast.success('Treffen aktualisiert.'); - UI.modal.close(); - _renderList(); - _renderMarkers(); } else { - if (!navigator.onLine) { - _addPending(payload); - UI.modal.close(); - UI.toast.success('Offline gespeichert — wird synchronisiert sobald Verbindung besteht.'); - _loadData(); - return; - } const created = await API.walks.create(payload); _data.unshift({ ...created, teilnehmer_count: 0 }); UI.toast.success('Treffen geplant! 🎉'); - UI.modal.close(); - _renderList(); - _renderMarkers(); } + + UI.modal.close(); + _renderList(); + _renderMarkers(); }); }); } diff --git a/backend/static/sw.js b/backend/static/sw.js index d01b2bd..a546b58 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-v988'; +const CACHE_VERSION = 'by-v987'; 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 @@ -119,8 +119,6 @@ const _QUEUEABLE = [ { re: /^\/api\/training\/sessions$/, methods: ['POST'] }, { re: /^\/api\/training\/progress$/, methods: ['POST'] }, { re: /^\/api\/poison$/, methods: ['POST'] }, - { re: /^\/api\/lost\/report$/, methods: ['POST'] }, - { re: /^\/api\/walks$/, methods: ['POST'] }, ]; function _isQueueable(pathname, method) { return _QUEUEABLE.some(q => q.methods.includes(method) && q.re.test(pathname)); @@ -141,9 +139,6 @@ const _CACHEABLE_GET = [ /^\/api\/wiki\/rassen/, /^\/api\/dogs\/\d+\/diary\/stats/, /^\/api\/routes$/, - /^\/api\/places$/, - /^\/api\/breeder\/map-markers$/, - /^\/api\/gassi-zeiten/, // Drei Welten — offline-fähig /^\/api\/streak\/\d+/, /^\/api\/forum\/threads/,