Selektives Loeschen: auch Funkloch-Gebiete bleiben + Keep-Set haertung
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
This commit is contained in:
parent
ca97613938
commit
2cdb743ce7
9 changed files with 94 additions and 38 deletions
2
VERSION
2
VERSION
|
|
@ -1 +1 @@
|
|||
1236
|
||||
1237
|
||||
|
|
@ -86,14 +86,14 @@
|
|||
<title>Ban Yaro</title>
|
||||
|
||||
<!-- Theme + theme-color Statusleiste vor CSS setzen -->
|
||||
<script src="/js/boot-early.js?v=1236"></script>
|
||||
<script src="/js/boot-early.js?v=1237"></script>
|
||||
|
||||
<!-- CSS: Reihenfolge ist wichtig — ?v= zwingt Browser zur Neuladung -->
|
||||
<link rel="stylesheet" href="/css/design-system.css?v=1236">
|
||||
<link rel="stylesheet" href="/css/layout.css?v=1236">
|
||||
<link rel="stylesheet" href="/css/components.css?v=1236">
|
||||
<link rel="stylesheet" href="/css/utilities.css?v=1236">
|
||||
<link rel="stylesheet" href="/css/lists.css?v=1236">
|
||||
<link rel="stylesheet" href="/css/design-system.css?v=1237">
|
||||
<link rel="stylesheet" href="/css/layout.css?v=1237">
|
||||
<link rel="stylesheet" href="/css/components.css?v=1237">
|
||||
<link rel="stylesheet" href="/css/utilities.css?v=1237">
|
||||
<link rel="stylesheet" href="/css/lists.css?v=1237">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
|
|
@ -612,11 +612,11 @@
|
|||
<div id="modal-container"></div>
|
||||
|
||||
<!-- JS: Reihenfolge ist wichtig — erst Basis, dann Features -->
|
||||
<script src="/js/api.js?v=1236"></script>
|
||||
<script src="/js/ui.js?v=1236"></script>
|
||||
<script src="/js/app.js?v=1236"></script>
|
||||
<script src="/js/worlds.js?v=1236"></script>
|
||||
<script src="/js/offline-indicator.js?v=1236"></script>
|
||||
<script src="/js/api.js?v=1237"></script>
|
||||
<script src="/js/ui.js?v=1237"></script>
|
||||
<script src="/js/app.js?v=1237"></script>
|
||||
<script src="/js/worlds.js?v=1237"></script>
|
||||
<script src="/js/offline-indicator.js?v=1237"></script>
|
||||
|
||||
<!-- Feature-Seiten werden lazy geladen -->
|
||||
|
||||
|
|
@ -626,7 +626,7 @@
|
|||
|
||||
|
||||
<!-- Boot: Offline-Banner + SW-Registration (extrahiert für CSP) -->
|
||||
<script src="/js/boot.js?v=1236"></script>
|
||||
<script src="/js/boot.js?v=1237"></script>
|
||||
|
||||
|
||||
</body>
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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; });
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="color-scheme" content="light dark">
|
||||
<script src="/js/landing-init.js?v=1236"></script>
|
||||
<script src="/js/landing-init.js?v=1237"></script>
|
||||
<title>Ban Yaro — Die Hunde-App für Deutschland, Österreich & Schweiz</title>
|
||||
<meta name="description" content="Ban Yaro: Die kostenlose All-in-One Hunde-App für DACH. Tagebuch, Giftköder-Alarm, Training mit KI, Forum, Wurfbörse, Stammbaum, Inzucht-Check — DSGVO-konform, offline-fähig, ohne App Store.">
|
||||
<meta name="keywords" content="Hunde App, Hunde Community, Wurfbörse, Züchter, Welpen kaufen, Stammbaum Hund, Inzuchtkoeffizient, Hundezucht, Impfpass Hund, Giftköder Alarm, Gassi Community, Hundetraining App, Hunde Forum, Hunde KI, Hundefilm Datenbank, Welpen Marktplatz">
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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):**
|
||||
|
|
|
|||
|
|
@ -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); });
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue