From 2cdb743ce7750af3806d9a06a3e0762ad3764ab4 Mon Sep 17 00:00:00 2001 From: rene Date: Sat, 6 Jun 2026 13:55:37 +0200 Subject: [PATCH] Selektives Loeschen: auch Funkloch-Gebiete bleiben + Keep-Set haertung MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rene: Funkloecher + Routen waren nach 'Alles loeschen' weiter weg. - Funkloch-Regionen jetzt im Keep-Set (geloescht wird NUR Manuelles); Zonen behalten ihren Fuellstatus (Komplett-Wipe setzt weiter zurueck) - Korridor-Migration beim Loeschen: keepTracks=[{name,track}] schreibt Tracks in Alt-Eintraege ohne r.track (Bestand vor v1236) bzw. legt fehlende Korridor-Regionen an — kein Warten auf Self-Healing - clear() liefert Summary; Toast zeigt 'behalten: Standort, X Routen, Y Funkloch-Gebiete' — Diagnose-Sichtbarkeit fuer Geraetetests Bump v1237 --- VERSION | 2 +- backend/static/index.html | 24 ++++++------- backend/static/js/app.js | 2 +- backend/static/js/map-offline.js | 62 ++++++++++++++++++++++++-------- backend/static/js/pages/map.js | 14 ++++++-- backend/static/landing.html | 2 +- backend/static/sw.js | 2 +- docs/OFFLINE_MAPS_PLAN.md | 9 +++-- tests/js/test-map-offline-r7.js | 15 +++++++- 9 files changed, 94 insertions(+), 38 deletions(-) diff --git a/VERSION b/VERSION index 125a103..96a2d52 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1236 \ No newline at end of file +1237 \ No newline at end of file diff --git a/backend/static/index.html b/backend/static/index.html index b4cd336..fb7fa45 100644 --- a/backend/static/index.html +++ b/backend/static/index.html @@ -86,14 +86,14 @@ Ban Yaro - + - - - - - + + + + + @@ -612,11 +612,11 @@ - - - - - + + + + + @@ -626,7 +626,7 @@ - + diff --git a/backend/static/js/app.js b/backend/static/js/app.js index 512e11d..37a62d1 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 = '1236'; // ← bei jedem Deploy mit Frontend-Änderungen erhöhen +const APP_VER = '1237'; // ← 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/map-offline.js b/backend/static/js/map-offline.js index d743721..e16053f 100644 --- a/backend/static/js/map-offline.js +++ b/backend/static/js/map-offline.js @@ -791,22 +791,54 @@ window.MapOffline = (function () { } // „Alles löschen" — SELEKTIV (René 2026-06-08, spart Vorladezeit): - // BLEIBEN: Standort-Gebiete (Regionen type 'standort'), Korridore der übergebenen - // Routen-Tracks (opts.keepTracks), der Umkreis von opts.center (5 km), Basis-Zooms 0–9 - // (winzig, von allem gebraucht), Marker/Warnungen ('p/') + Glyphs ('f/'). - // GEHEN: manuelle Gebiete/Ausschnitte + Funkloch-Kacheln (Zonen bleiben gemerkt, - // filled:false → Start-Check lädt Nahe automatisch neu). + // BLEIBEN: Standort-Gebiete, FUNKLOCH-Gebiete (automatisch gelernt — wären sonst sofort + // wieder vorzuladen), Korridore der Routen (aus Region-Meta r.track ODER opts.keepTracks), + // der Umkreis von opts.center (5 km), Basis-Zooms 0–9, Marker/Warnungen ('p/') + Glyphs ('f/'). + // GEHEN: nur manuelle Gebiete ('gebiet') + Ausschnitte ('ausschnitt'). + // opts.keepTracks: [{name, track}] oder [track] — Tracks werden in die Korridor-Meta + // MIGRIERT (Bestandsdaten vor v1236 hatten keinen track im Eintrag). // Ohne Keep-Kandidaten (alte Signatur/Tests): kompletter Wipe inkl. Basis-Zooms. + // Liefert {standort, funkloch, korridore} (Anzahl behaltener Gebiete) für den Toast. function clear(opts) { opts = opts || {}; - var keep = {}; + var keep = {}, summary = { standort: 0, funkloch: 0, korridore: 0 }; return _metaGet('regions').then(function (regions) { regions = regions || []; - var keptRegions = regions.filter(function (r) { return r.type === 'standort' || r.type === 'korridor'; }); - regions.forEach(function (r) { - if (r.type === 'standort' && r.radiusKm) _keepRegionKeys(r.lat, r.lon, r.radiusKm, keep); + var keptRegions = regions.filter(function (r) { + return r.type === 'standort' || r.type === 'korridor' || r.type === 'funkloch'; + }); + // Tracks normalisieren: [{name, track}] oder [track] + var tracks = (opts.keepTracks || []).map(function (t) { + return Array.isArray(t) ? { name: null, track: t } : (t || {}); + }).filter(function (o) { return o.track && o.track.length >= 2; }); + + keptRegions.forEach(function (r) { + if ((r.type === 'standort' || r.type === 'funkloch') && r.radiusKm) { + _keepRegionKeys(r.lat, r.lon, r.radiusKm, keep); + summary[r.type]++; + } // Korridor-Keep direkt aus der Region-Meta (r.track) — unabhängig von API/Login. - if (r.type === 'korridor' && r.track && r.track.length >= 2) _keepCorridorKeys(r.track, 1, keep); + if (r.type === 'korridor') { + if (!(r.track && r.track.length >= 2)) { + // Migration: Track aus keepTracks in den Alt-Eintrag übernehmen (Match per Name, + // sonst erster track-loser Kandidat). + var m = tracks.find(function (o) { return o.name && o.name === r.name; }) || tracks[0]; + if (m) { r.track = m.track; } + } + if (r.track && r.track.length >= 2) { _keepCorridorKeys(r.track, 1, keep); summary.korridore++; } + } + }); + // keepTracks ohne passenden Meta-Eintrag → trotzdem behalten + Eintrag anlegen. + tracks.forEach(function (o) { + var known = keptRegions.some(function (r) { + return r.type === 'korridor' && r.track && r.track.length && + _distKm(r.track[0].lat, r.track[0].lon, o.track[0].lat, o.track[0].lon) < 0.3; + }); + if (known) return; + _keepCorridorKeys(o.track, 1, keep); + summary.korridore++; + keptRegions.push({ type: 'korridor', name: o.name || null, lat: o.track[0].lat, lon: o.track[0].lon, + track: o.track, tiles: 0, bytes: 0, pois: 0, savedAt: Date.now() }); }); if (opts.center) { _keepRegionKeys(opts.center.lat, opts.center.lon, 5, keep); @@ -816,10 +848,8 @@ window.MapOffline = (function () { keptRegions.push({ type: 'standort', lat: opts.center.lat, lon: opts.center.lon, radiusKm: 5, tiles: 0, bytes: 0, pois: 0, savedAt: Date.now() }); } + summary.standort = Math.max(summary.standort, 1); } - (opts.keepTracks || []).forEach(function (t) { - if (t && t.length >= 2) _keepCorridorKeys(t, 1, keep); - }); var keepBase = Object.keys(keep).length > 0; if (!keepBase) keptRegions = []; // nichts zu behalten → echter Komplett-Wipe @@ -838,7 +868,9 @@ window.MapOffline = (function () { return _req(META, 'readwrite', function (os) { os.clear(); }).then(function () { var jobs = []; if (zones && zones.length) { - zones.forEach(function (z) { z.filled = false; }); + // Selektiv: Funkloch-Kacheln bleiben → Füllstatus behalten (Start-Check + // verifiziert ohnehin). Komplett-Wipe: alles ungefüllt → Neu-Laden. + if (!keepBase) zones.forEach(function (z) { z.filled = false; }); jobs.push(_metaPut('deadzones', zones)); } if (keptRegions.length) { @@ -848,7 +880,7 @@ window.MapOffline = (function () { } return Promise.all(jobs); }); - }); + }).then(function () { return summary; }); }); } diff --git a/backend/static/js/pages/map.js b/backend/static/js/pages/map.js index 9adc8e0..6fd35bb 100644 --- a/backend/static/js/pages/map.js +++ b/backend/static/js/pages/map.js @@ -2314,7 +2314,8 @@ window.Page_map = (() => { let keepTracks = []; try { keepTracks = ((await API.routes.list()) || []) - .map(r => r.preview_track).filter(t => (t || []).length >= 2); + .map(r => ({ name: r.name, track: r.preview_track })) + .filter(o => (o.track || []).length >= 2); } catch (e) {} // Position: GPS-Fix, sonst letzte bekannte Position (wetter.js et al.) let center = _userPos ? { lat: _userPos.lat, lon: _userPos.lon } : null; @@ -2324,10 +2325,17 @@ window.Page_map = (() => { if (p?.lat != null) center = { lat: p.lat, lon: p.lon }; } catch (e) {} } - await MapOffline.clear({ center, keepTracks }).catch(() => {}); + const sum = await MapOffline.clear({ center, keepTracks }).catch(() => null); _setCoverage(false); UI.modal.close(); - UI.toast.success('Offline-Karten gelöscht — Standort-Gebiet und Routen-Korridore bleiben erhalten.'); + // Sichtbarkeit, WAS behalten wurde — Diagnose-Hilfe für Gerätetests. + const kept = []; + if (sum?.standort) kept.push('Standort'); + if (sum?.korridore) kept.push(`${sum.korridore} Route${sum.korridore === 1 ? '' : 'n'}`); + if (sum?.funkloch) kept.push(`${sum.funkloch} Funkloch-Gebiet${sum.funkloch === 1 ? '' : 'e'}`); + UI.toast.success(kept.length + ? `Manuelle Gebiete gelöscht — behalten: ${kept.join(', ')}.` + : 'Offline-Karten gelöscht.'); // Sicherheitsnetz: falls am Standort nichts zu behalten war (z.B. nie geladen), // Grundversorgung jetzt herstellen. if (_userPos && navigator.onLine) { diff --git a/backend/static/landing.html b/backend/static/landing.html index 7e2b317..956917e 100644 --- a/backend/static/landing.html +++ b/backend/static/landing.html @@ -4,7 +4,7 @@ - + Ban Yaro — Die Hunde-App für Deutschland, Österreich & Schweiz diff --git a/backend/static/sw.js b/backend/static/sw.js index b9d41dc..c3fa9b5 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 = '1236'; +const VER = '1237'; const CACHE_VERSION = `by-v${VER}`; const CACHE_STATIC = `${CACHE_VERSION}-static`; const CACHE_TILES = 'ban-yaro-tiles-v1'; // bleibt über SW-Updates erhalten diff --git a/docs/OFFLINE_MAPS_PLAN.md b/docs/OFFLINE_MAPS_PLAN.md index 274539b..924d927 100644 --- a/docs/OFFLINE_MAPS_PLAN.md +++ b/docs/OFFLINE_MAPS_PLAN.md @@ -132,9 +132,12 @@ laden erst vor Ort). Tests: tests/js/test-map-offline-r6.js. „Alles löschen" löscht nicht mehr alles-und-lädt-neu, sondern **behält** Standort-Gebiete (`type 'standort'` aus der Regions-Meta), die **Korridore der gespeicherten Routen** (`clear({keepTracks})`, Tracks via API.routes.list/preview_track), den 5-km-Umkreis der -aktuellen Position, Basis-Zooms 0–9 sowie Marker/Warnungen + Glyphs. Gelöscht werden manuelle -Gebiete/Ausschnitte + Funkloch-Kacheln (Zonen bleiben gemerkt → Nahe laden automatisch neu). -Ohne Keep-Kandidaten: Komplett-Wipe wie bisher. Batch-Delete in einer Transaktion. +aktuellen Position, Basis-Zooms 0–9 sowie Marker/Warnungen + Glyphs. Seit v1237 bleiben auch FUNKLOCH-Gebiete +(René: sonst sofort wieder Vorladezeit) — gelöscht wird NUR Manuelles ('gebiet'/'ausschnitt'). +Keep-Set ist SELBSTTRAGEND aus der Region-Meta (Korridor-Track ≤60 Pkt im Eintrag, r.track; +Standort-Adoption; keepTracks=[{name,track}] migriert Alt-Einträge). clear() liefert Summary +{standort, funkloch, korridore} → Toast zeigt, was behalten wurde (Diagnose). +Ohne Keep-Kandidaten: Komplett-Wipe (Zonen → ungefüllt). Batch-Delete in einer Transaktion. Tests: r7 (+ r6 angepasst). **🔲 Offen (Backlog):** diff --git a/tests/js/test-map-offline-r7.js b/tests/js/test-map-offline-r7.js index 75c4ee1..70e6dd6 100644 --- a/tests/js/test-map-offline-r7.js +++ b/tests/js/test-map-offline-r7.js @@ -54,6 +54,17 @@ const MO = global.window.MapOffline; const regs = stores.meta.get('regions') || []; if (!regs.length || regs.some(r => r.type === 'gebiet')) throw new Error('Regions-Meta falsch gefiltert'); + // 1b. Funkloch-Gebiet bleibt ebenfalls (René 2026-06-08: nur Manuelles löschen) + await MO.downloadAround(48.5, 12.5, { budgetMB: 0.005, type: 'funkloch' }); + await MO.markDeadZone(48.5, 12.5); + stores.meta.get('deadzones').forEach(z => z.filled = true); + const s1b = await MO.clear(); + console.log('Funkloch-Keep:', JSON.stringify(s1b), '— Zone gefüllt geblieben:', stores.meta.get('deadzones')[0].filled === true); + if (!s1b.funkloch) throw new Error('Funkloch-Gebiet überlebte nicht'); + if (stores.meta.get('deadzones')[0].filled !== true) throw new Error('Zonen-Status fälschlich zurückgesetzt'); + const fzKeys = [...stores.tiles.keys()].filter(k => /^1[0-4]\//.test(k)).length; + if (!fzKeys) throw new Error('Funkloch-Kacheln weg'); + // 2. clear() OHNE keepTracks: Korridor-Keep kommt aus der Region-Meta (r.track) const afterSel = stores.tiles.size; await MO.clear(); @@ -68,7 +79,9 @@ const MO = global.window.MapOffline; await MO.clear(); console.log('Komplett-Wipe: tiles =', stores.tiles.size, '— Zonen:', (stores.meta.get('deadzones') || []).length); if (stores.tiles.size !== 0) throw new Error('Komplett-Wipe unvollständig'); - if ((stores.meta.get('deadzones') || []).length !== 1) throw new Error('Zonen weg'); + const wipeZones = stores.meta.get('deadzones') || []; + if (!wipeZones.length) throw new Error('Zonen weg'); + if (wipeZones.some(z => z.filled)) throw new Error('Komplett-Wipe muss Zonen auf ungefüllt setzen'); console.log('\nALLE RUNDE-7-TESTS BESTANDEN'); })().catch(e => { console.error('FEHLER:', e.message); process.exit(1); });