- app.js init(): Hash-Route wird auch ohne Login angesteuert — vorher wurden
anonyme Besucher IMMER auf 'welcome' geworfen, #agb/#datenschutz/#impressum
liefen damit ins Leere (DSGVO-Problem, broken Links aus iOS-App + SEO-Footer).
Auth-pflichtige Seiten schuetzt weiterhin der requiresAuth-Guard in navigate().
- main.py: /agb, /datenschutz, /impressum -> 302 auf die SPA-Hash-Routen
(vor dem SPA-Fallback registriert)
- make bump: v1221
MapLibre-GL-Migration ist verifiziert (Staging) → GL jetzt Default auf allen
deployten Hosts statt nur staging.banyaro.app. localhost/LAN bleibt OSM-Raster
(keine lokalen Tiles), by_map_gl=0 erzwingt weiterhin den Leaflet-Fallback.
Tiles (dach.pmtiles, 15 Länder) + Glyphs liegen nun auch im Prod-Data-Volume.
SW-Bump 1219→1220.
- Scrub-Bug: _radarPause() setzte slider.value zurück, BEVOR der gezogene Wert
gelesen wurde → sprang immer auf 'jetzt'. Jetzt Wert zuerst lesen. Scrubben
stoppt Play + zeigt den Frame der Position (verifiziert: Klick 20%→Frame 2,
Setter→5→Frame 5).
- Breite per JS an .map-statusbar angeglichen (gleiche linke + rechte Kante),
Höhe/Optik an die Pill (kleinerer Play-Button, flacher).
Bisher nur der neueste Frame; jetzt alle ~13-16 RainViewer-Frames (past+nowcast,
10-Min-Schritte) mit Play/Pause + Slider + Zeitstempel (jetzt / +N / -N Min,
Vorhersage-Frames bläulich) — RainToday-artig. Frame-Wechsel smooth via
raster setTiles (kein Flackern), Loop, _radarNowIdx = letzter Vergangenheits-Frame.
Timeline unten-mittig, wird bei Radar-AUS entfernt. Pro-Feature wie das Radar.
Headless verifiziert: 13 Frames, Play scrubbt (12→0→1→2), keine Fehler.
offline-indicator.js: im GL-Offline-Modus (by_offline_tiles) prüft Segment 5
'Karten-Kacheln' jetzt eine gespeicherte Vektor-Region in IndexedDB (statt des
OSM-Raster-Counts, den die GL-Karte nicht nutzt → war falsch-grün). 'Fehlende
nachladen' (Segment 5) stößt im GL-Modus MapOffline.downloadAround(GPS, 5km) an.
- _offlineRegionStored legt dasselbe IDB-Schema/Version an wie map-offline.js
(sonst bricht ein versionsloses open() die Store-Erstellung)
- UI.loadMapLibreUI exportiert (für den FAB-Download)
Headless verifiziert: Flag an, keine Fehler; Segment 5 vor Download grau (0),
nach Download grün (97 Tiles).
Mitglieder-Karte (forum.js): L.map/L.tileLayer(OSM) → UI.map.create, Cluster
+ Marker über die Facade (UI.map.clusterGroup/svgMarker), eigenes Leaflet-/
MarkerCluster-Nachladen raus. destroy() gibt Karte+Gruppe beim Verlassen frei.
Headless verifiziert: GL-Canvas, 2 Mitglieder-Marker, keine Fehler.
places.js (separate 'Hundefreundliche Orte'-Seite) war verwaist — in keiner
Navigation/keinem pages-Registry, nicht erreichbar. Die hundefreundlichen Orte
laufen längst als POI-Marker auf der zentralen GL-Karte (map.js). Auf Renés
Entscheidung gelöscht (JS + CSS-Block in components.css).
Damit laufen ALLE erreichbaren Karten der App auf MapLibre GL.
Eigentliche Ursache von 'Detailkarte zoomt nicht auf die Route': die Karte war
auf dem Gerät gar keine GL-Karte mehr, sondern der Leaflet+OSM-RASTER-Fallback.
Grund: _detailMap (GL-Kontext) wurde beim Schließen des Modals NIE freigegeben —
jede geöffnete Route leakte einen WebGL-Kontext. Nach ~8 wirft MapLibre, und
UI.map.create fällt auf Leaflet+OSM zurück. Genau die Mapnik-Kacheln aus Renés
Screenshots (und die OSM-Attribution, die wir doch loswerden wollten).
Fixes:
- _detailMap modulweit + im onClose des Detail-Modals freigeben.
- routes.js destroy(): _detailMap/_suggestMap/_searchMap + Mini-Maps beim
Verlassen der Seite freigeben.
- ui.js: Offscreen-Snapshot-Kontext nach 15s Leerlauf freigeben (hielt dauerhaft
einen Kontext; Cache bleibt → kein Neu-Rendern).
- _fitRouteMap fittet jetzt aufs 'load'/'idle'-Event der Karte (iOS verwirft ein
fitBounds VOR dem ersten Render) statt nur auf feste Timeouts.
Verifiziert (headless): 12 Detail-Öffnungen in Folge bleiben ALLE GL
(Leaflet:false), GL-Canvas-Zahl bleibt bei 1–2 statt zu wachsen. Vorher leakte
jede Öffnung einen Kontext.
Punkt 3 (Zoom auf die Route): feste Timeouts (0/200/500ms) griffen auf iOS oft
zu früh — der Modal-Container war noch nicht final vermessen, die Karte blieb
beim Start-Zoom (zoom 14, center=Start) hängen statt auf die ganze Route zu
zoomen. Jetzt _fitRouteMap mit ResizeObserver: fittet erneut, SOBALD der
Container seine endgültige Größe hat (Detail + Vorschläge). Facade-fitBounds
prüft jetzt auch clientHeight>0 (0-Höhe ergab schlechten Fit).
Punkt 5 (Navigations-Sperrbildschirm): der 2-Sek-Halten-Handler hing am ganzen
Dim-Overlay → Halten IRGENDWO entsperrte. Jetzt ein eigener Fingerabdruck-Knopf
(rk-nav-unlock-btn) wie beim Aufzeichnen-Dim; nur dort entsperrt es, mit
setPointerCapture. Tippen daneben tut bewusst nichts.
Verifiziert (headless): Detail fittet die ganze Route (v1204, 0 Fehler);
Dim-Hintergrund 2,2s halten → bleibt gesperrt, Knopf 2,2s halten → entsperrt.
Punkt 2 (Routen-Übersicht 'Karte'): _renderRoutesOnMap crashte, weil die
Polyline-Facade kein bindTooltip/on/setStyle/getLatLngs kannte. In
map-gl-mini.js ergänzt — inkl. breiter, fast unsichtbarer Hit-Linie, damit
Routen auf dem Handy gut antippbar sind (Klick → Detail). Hover-Tooltip
(Name+km) + Hover-Highlight.
Punkt 4 (Tagebuch): beide Leaflet/OSM-Karten (Standort-Übersicht +
Einzeleintrag) auf UI.map.create + Facade-Marker migriert. popupopen-Wiring
(kennt die GL-Facade nicht) → Klick-Delegation auf dem Karten-Container.
Karten-Instanzen werden beim View-Wechsel/Verlassen freigegeben (destroy +
_clearDiaryMaps) gegen WebGL-Kontext-Leak. Detail/Übersicht fitten mehrfach
(Container-Timing).
Nebenbei: _loadPraise warf NotFoundError (insertBefore) — #diary-list liegt
in #diary-view-content, nicht direkt in _container. Jetzt vor der Liste in
deren echtem Elternknoten einfügen.
Verifiziert (headless, eingeloggt, echte Daten): Routenkarte 8 Marker klickbar
→ Detail; Detail+Vorschläge zoomen auf die Route; Tagebuch-Karte GL mit 108
Markern, Popup-Klick → Eintrag, keine Fehler.
In der Routenliste fehlte der geografische Kontext — man sah nur die Routen-
form auf grünem Grund, nicht WO sie liegt oder wo sie entlangführt.
Lösung: UI.map.snapshot() rendert pro Track ein PNG aus EINEM geteilten
Offscreen-GL-Kontext (gleicher Style wie die echte Karte: Straßen, Orte,
Wald, Gewässer), zeichnet Route + Start/Ziel-Marker ein und cached das
Ergebnis. So bekommt jede Karte ihren Kontext, ohne bei vielen Listen-
einträgen das WebGL-Kontextlimit (iOS ~8) zu sprengen.
- ui.js: Offscreen-Singleton + serielle Render-Queue + Cache (_glSnapshot)
- routes.js: _buildMiniMap zeigt sofort SVG, upgradet dann aufs PNG
- GL aus → null → SVG-Platzhalter bleibt (Produktion/Flag aus unverändert)
Ein transienter Init-Fehler (Netz-Blip, SW-Update mitten in der Navigation,
Race) setzte page.module={} — der Guard 'if (page.module)' lud die Seite
danach nie mehr nach. Auf einer iOS-PWA, die nie ganz neu lädt, blieb 'Die
Seite funktioniert nicht mehr' damit tagelang hängen, obwohl der eigentliche
Bug (Routen-GL) längst gefixt war.
- echten Fehler nicht mehr verschlucken (console.error)
- page.module bei Exception NICHT mehr tot stellen → nächster Aufruf versucht neu
- 'Erneut versuchen'-Button im Fehler-State
- Routen v1199 in Chromium+WebKit headless verifiziert (Liste/Entdecken/Detail ok)
- Pfeile: rotate als SVG-Pfad-Attribut statt CSS-transform am Element (maplibregl.Marker
überschrieb das transform → Pfeile zeigten alle nach Norden)
- Filter-Panel + Badge: doppeltes class-Attribut (class=X class=hidden) → Browser ignorierte
'hidden' → Filter immer offen + roter Badge immer an. Zu 'X hidden' gemergt.
- transportation nach class: Pfade/Tracks dünn+gestrichelt; Straßen weiß, Breite nach Klasse
(motorway/trunk breit … minor schmal) — Pfade sehen nicht mehr wie Straßen aus
- neue Label-Layer: poi (Kinderspielplatz/Schule… ab Z15) + housenumber (ab Z17), name:de
- Label-Reihenfolge = Kollisions-Priorität (Orte zuerst)
- main.py: /fonts-Mount (Glyph-PBFs aus data/tiles/fonts), Open Sans Regular self-hosted
- map-gl-style.js: glyphs-URL + Label-Layer (Ortsnamen/Straßen/Gewässer, name:de)
- map.js _initMapGL: ScaleControl entfernt (überdeckte die Zoom/Wetter/Zecken-Pill)
Ortsnamen für Orientierung (René), auch bei kleinem Zoom.
_loadOsmLayers verwarf Scan-Anfragen, die während eines laufenden Scans kamen (return).
Bei langsamem Overpass (Handy) ging so der finale Z14-Scan verloren → Marker leer.
Jetzt: _scanQueued merkt die Anfrage vor, finally holt sie nach → letzte Ansicht wird garantiert gescannt.
René: 'geclusterte Marker haben kein Symbol'. Jeder Cluster ist genau eine Kategorie →
weißes Phosphor-Icon in der Cluster-Mitte (icon-size skaliert mit point_count). Keine Glyphs nötig.
René: 'wo die Karten-Buttons auftauchen ist eine Zone die Kartenbedienung verhindert'.
.map-statusbar/.map-speed-dial/.map-crosshair/.map-search-wrap(inactive)/.map-rec-panel(inactive)
fingen Touch in ihrer Bounding-Box → tote Zonen. Jetzt pointer-events:none, nur Buttons auto.
Erklärt die 'reagiert nach kurzer Zeit'-Verzögerung (Drag startet tot, greift erst im Karten-Bereich).
Gilt für beide Engines (verbessert auch Leaflet).
- _loadOsmLayers: kein _map.resize() für GL (löste move→moveend→scan-Loop aus, 'pausenlos')
- _initMapGL: touchZoomRotate.disableRotation() + touchPitch.disable() + container touch-action:none
→ Pinch=reines Zoom, bleibt in der Karte (kein iOS-Page-Zoom), keine ungewollte Drehung
Main-Thread-Rendering von protomaps-leaflet + App-Map-Logik blockiert UI-Thread.
Greift auch bei localStorage-Flag=1. Performance erst lösen, dann reaktivieren.
Statischer Hinweis präzisiert + Toast beim ersten Ausblenden: Funktion bleibt
über 'Weitere Funktionen' (Ausgeblendete Funktionen) abrufbar, wird nicht gelöscht. SW v1173
Falsche Feldnamen: dog.gewicht/dog.alter existieren nicht. Korrekt: gewicht_kg,
und Alter aus geburtstag berechnen (_alterJahre). Beide werden jetzt im Kalorien-
Rechner vorbefüllt. SW v1171
ernaehrung.js: Das Profil (Marke, Portionen, Notizen, Futter-Typ) wird beim Laden
direkt angezeigt, wenn gespeicherte Daten existieren — vorher nur nach Klick auf
'Kalorienbedarf berechnen'. Gespeicherter Tagesbedarf (kcal_tag) wird 1:1 wieder
gezeigt (kein Neu-Rechnen). _berechne → _showResult refaktoriert. SW v1170
Werben-Zuordnung ging verloren, wenn die geworbene Person den ?ref=-Link öffnete,
die App schloss und sich erst später registrierte (sessionStorage flüchtig, v.a.
iOS-PWA). Jetzt: Code früh in boot.js nach localStorage (vor evtl. SW-Reload, der
die URL ersetzt), 30-Tage-Ablauf, Löschung nach Registrierung. SW v1169
Datenkorrektur separat: nacho_sarah Angie (id=4) als 2. Werbung zugeordnet.