Rene: 'wo sieht der Partner welche QR-Codes er hat und wieviele verbraucht
sind?' Neu in 'Meine QR-Codes':
- Kontingent-Zeile zeigt 'X/Y verbraucht' (Codes mit ≥1 bestätigter Registrierung)
- Listen-Button klappt Einzel-Codes auf: #Nr, Kurz-URL, Scans und Status
● verbraucht (mit Registrierungs-Datum) / ◐ gescannt / ○ frei
- Endpoint /partner/my-qr/{id}/codes (owner-gated, keine personenbezogenen
Daten — nur Zähler + Zeitstempel)
Rene: Statistik zählte alles in einen Topf (3 statt 2) und zeigte nicht,
WER sich registriert hat. Jetzt:
- registrations = email_verified=1, attempts = unbestätigte Versuche —
Versuche werden bei späterer Bestätigung automatisch zu Registrierungen
- Admin: 👥-Button pro Kontingent klappt Account-Liste auf (Name, E-Mail,
Datum, ✓ bestätigt/⏳ Versuch, Sticker-Nr #seq) — lazy geladen, admin-only
(personenbezogene Daten); Partner sehen weiter nur Zahlen (Registr. +N)
- Test deckt Versuch→Bestätigung-Übergang und Detail-Endpoint ab
Rene: 'kann nichts prüfen — ich würde den Output erwarten, der auf der
Partner-Seite zu sehen sein wird'. Freigabe-Zeile hat jetzt einen
Vorschau-Toggle, der die Karte 1:1 wie auf #partner rendert (Logo/Initial,
Slogan, Website, Instagram, Bio, Medien-Grid).
Mail-Ursache gefunden: Staging-.env fehlte SMTP_SUPPORT_USER → Code-Default
support@banyaro.de → 535 Auth-Fehler, vom Silent-Catch verschluckt.
.env ergänzt (partner@banyaro.app wie Prod); Submit loggt SMTP-Fehler jetzt
über _log_smtp_failure in failed_emails statt still zu schlucken.
Rene reichte ein Partner-Profil ein und sah als Admin nirgends einen Hinweis:
1. Action-Items kannten Partner-Profile nicht — partner_profiles_pending
(submitted_at gesetzt, approved=0) jetzt im Endpoint + Chip im Admin-Kopf
(Klick -> Partner-Tab). Test ergänzt (7 passed).
2. ADMIN_EMAIL fehlte in BEIDEN .env auf der DS (Prod+Staging) — damit wurden
auch Upgrade-Anfragen-Mails still verschluckt (bekanntes Silent-Skip-Muster).
Auf der DS nachgetragen; greift je beim nächsten Deploy.
Logo-Pfad akzeptierte .heic, öffnete aber direkt mit Pillow (kein HEIF-Opener)
— iPhone-Fotos schlugen fehl. Jetzt convert_media-Vorstufe wie im Foto-Pfad.
Fehlgeschlagene Konvertierungen (HEIC→JPEG, MOV→MP4) brechen mit klarer
Meldung ab statt rohe Dateien zu speichern (MOV wäre als <img> kaputt gerendert).
Test: echter HEIC-Roundtrip (pillow-heif) für Logo + Foto.
Rene: 'Tagebuch Kalenderansicht/Karte nicht mehr da' — Root-Cause: 459cd42
ersetzte style="display:none" durch class="hidden", aber die Show-Pfade
setzten weiter style.display. .hidden hat !important und gewinnt immer
(gleiche Klasse wie Filter-Panel-Hotfix v1242). Prod-Logs bewiesen: kein
einziger /diary/calendar- oder /locations-Request kam je an.
Unsichtbar seit v1102, jetzt per classList gefixt:
- diary: Stats-Bar mit View-Switcher (Liste/Medien/Kalender/Karte) + Medien-Grid neuer Eintrag
- health: KI-Tierarzt-Ergebnis erschien nie
- walks: Challenge-/Stamm-Gassi-Tabs leer
- welcome: iOS-Panel der Desktop-Install-Anleitung
- wiki: Fotos-Mod-Badge + Foto-Fallback (via app.js data-fb show-el/sibling-Handler)
- routes: Filter-Badge; breeder: Fotos-Section
Zweite Fehlerklasse aus demselben Sprint: doppelte class-Attribute
(class="x" id=… class="hidden") — Browser verwirft das zweite Attribut.
87 Vorkommen in 23 Dateien zusammengeführt; betroffene Show/Hide-Pfade
(ev-map, rk-mine/nearby-group, chat-partner-dot, eh-panel, zh-section)
auf classList umgestellt.
Praxistest Rene (Gassirunde Siegenhofen, Loop Start=Ende): _closestIdx suchte
GLOBAL -> am Start war der END-Index genauso nah -> Fortschritt sprang ans
Track-Ende: nie Abbiege-Bellen (keine Turns mehr 'vor' einem), done-Linie
malte sofort alles gruen, 99%.
- _closestIdx: Fenster um den aktuellen Index (-15/+80), global nur beim
ersten Fix (mit Start-Praeferenz bei Quasi-Gleichstand <25m) oder wenn
verloren (>300m). Simulation auf der echten Route: 13/13 Turns feuern
bei 41-49m Vorlauf.
- Gelaufener Weg als BREADCRUMB: gruen = auf der Route, rot = daneben
(Segment-Wechsel nahtlos); done-Linie (Track-Slice-Malen) entfernt —
nie gelaufene Abschnitte bleiben jetzt orange
- Off-Route-Schwelle 50->35m (Klaeffen kam ~5m zu spaet), Abbiege-Ansage 45->50m
Bump v1250
- Standort-Punkt zeigt jetzt einen Kompass-KEGEL (wie Google Maps): CSS-Kegel
im loc-icon (GL + Leaflet), deviceorientation mit webkitCompassHeading (iOS)
bzw. 360-alpha (Android), Glaettung ueber kuerzesten Winkelweg, rAF-throttled.
iOS-Permission via User-Geste (Follow-/Standort-Button startet den Kompass).
- Follow pant nur noch bei brauchbarem Fix (accuracy < 75m) — ungenaue
Positionen liessen die Karte zappeln; GPS-Fixes frischer (maximumAge 2s
statt 5s). Marker aktualisiert weiterhin jeden Fix.
Bump v1249
Rene: aktiviertes Crosshair pannt alle paar Sekunden -> jedes moveend
startete den Scan. Scans aus KARTENBEWEGUNG laufen jetzt erst, wenn sich
das Zentrum >= 20% der Viewport-Breite bewegt hat oder der Zoom wechselt
(bei Z16 ~ alle 100-150m Fussweg). Alle anderen Trigger (Marker
gespeichert, Layer-Toggle, Retry, Init, Scan-Queue) ungebremst.
Bump v1247
position:fixed + safe-area (+70px) wie das Offline-Icon (+110px) statt
absolute im Karten-Container — sitzt jetzt exakt in der Luecke; Offline-
Puls bleibt unveraendert an seinem Platz.
Bump v1246
Wunsch Rene: sichtbarer Follow-Schalter direkt auf der Karte statt nur ueber
das Speed-Dial. Crosshair links unter den Zoom-Reglern (unterhalb des
Offline-Puls-Icons): Tipp = zentrieren + folgen (Button farbig), Karte
ziehen = pausiert (grau). Synchron mit Standort-Speed-Dial-Button und
Aufzeichnungs-Start (beide aktivieren Follow ebenfalls).
Bump v1245
HTMLAudio+preload laedt auf iOS lazy (canplaythrough feuert nie) und verlor
beim ersten Einschalten das Rennen gegen den Probe-Wuff -> Game-Boy-Fallback.
Jetzt: fetch + decodeAudioData in den bestehenden AudioContext (praezises
Timing via BufferSource, offline via SW-Precache); Probe-Wuff 450ms verzoegert.
Synthese bleibt Fallback bei 404/Decode-Fehler.
Bump v1244
Kaputt seit 27a3f95 (2026-06-05, 'Filter standardmaessig zu' setzte die
hidden-KLASSE ins Markup, der Toggle blieb aber auf style.display='').
.hidden = display:none !important (design-system.css) -> Klick wirkte nie.
Import funktionierte weiter (Label+File-Input nativ) — dadurch gemeldet
als 'Filter geht nicht mehr' (Angie + Rene).
Fix: classList.toggle('hidden') im Toggle + konsistent im Suggest-Tab.
Bump v1242
- NavSound (routes.js): WebAudio-Wuff-Synthese (Saegezahn-Sweep + Tiefpass,
kein Asset, laeuft offline); echte Aufnahmen unter /sounds/wuff.mp3 +
klaeffen.mp3 (z.B. von Yaro) werden automatisch bevorzugt
- Abbiege-Erkennung: Turns einmalig aus dem Track (Peilung ueber 15-m-
Stuetzpunkte gegen GPS-Zickzack, >=40 Grad), Ansage bei <=45 m davor,
einmal pro Abbiegepunkt
- Falscher Weg (>50 m, bestehende Warnung): Klaeffen beim Abkommen +
Erinnerung alle 30 s; zurueck auf Route reset
- Toggle im Navi-Header (Lautsprecher-Icon, by_nav_sound, Default AN),
iOS-Audio-Unlock beim Navi-Start + Toggle (Probe-Wuff als Bestaetigung)
Bump v1241
Vorher zaehlte NUR eine aufgezeichnete Tour der letzten 48h (<=50m am POI,
>=2 Punkte) — die aktuelle Geraeteposition floss gar nicht ein.
- DogFriendlyIn: optional user_lat/user_lon (Frontend schickt _userPos mit)
- Beleg-Weg a): Geraetestandort <= 75m am POI (50m Radius + GPS-Toleranz)
-> route_id=None markiert Live-Beleg; Weg b) Tour-Beleg unveraendert
- Fehlermeldung nennt jetzt beide Wege (hin gehen ODER Standort aktivieren)
- pytest 39 passed
Bump v1239
- MapGLMini-Polyline hatte KEIN addLatLng (nur setLatLngs) -> TypeError im
Rec-Overlay: Strecke unsichtbar, Marker fror ein, kein Folgen. Facade
ergaenzt (Leaflet-kompatibel).
- Rec-Overlay (routes.js): Follow-Mode default AN — Karte wandert mit dem
Standort, Drag pausiert, Crosshair-Button (unten rechts) reaktiviert;
erster Fix setzt Zoom 16, danach bleibt der Zoom erhalten
- Zentrale Karte (map.js): Standort-Button aktiviert Follow (+Toast),
dragstart beendet es (beide Engines); GPS-Tracking folgt sanft (easeTo);
Aufzeichnung startet im Follow-Mode, _updateRecMap pant nur noch im Follow
Bump v1238
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
Renes Befund: 'Alles loeschen' wischte weiter alles. Ursachen: (a) Bestands-
Gebiete hatten keine standort-Region (ensureHomeArea legt nur bei FEHLENDER
Kachel los), (b) Korridor-Keys waren nur aus API-Tracks ableitbar -> leeres
Keep-Set = Komplett-Wipe.
- downloadCorridor speichert vereinfachten Track (<=60 Pkt) in der Region-Meta;
clear() baut Korridor-Keep daraus — ohne API/Login/GPS
- Standort-ADOPTION: clear() mit center legt fehlende standort-Region
synthetisch an (Bestandsdaten vor Runde 6)
- map.js: center-Fallback auf by_last_position wenn GPS noch keinen Fix hat
- Test r7 erweitert (clear ohne Optionen haelt Korridor aus Meta), alle gruen
Bump v1236
Renes Modell Punkt 1 war zu eng interpretiert (nur Funkloecher): das Gebiet
um die aktuelle Position gehoert zur Grundversorgung.
- ensureHomeArea(lat,lon): Zentrums-Kachel-Check -> bei Luecke Budget-Download
(type 'standort', Cap-gated)
- Start-Check: Standort raw pruefen (ohne GL-Stack) und bei Bedarf laden
- 'Alles loeschen': Standort-Gebiet wird SOFORT neu geladen (+ Toast) —
vorher war die Offline-Funktionalitaet genau am wichtigsten Ort weg
- Pfote Segment 5: Standort-Kachel da UND Zonen im 50-km-Umkreis gefuellt
(ferne Zonen zaehlen nicht mehr — sie laden erst vor Ort)
- Tests r6 + Regression r1/r3/r4/r5 gruen
Bump v1234
Geraetetest: Karte offline 'nicht verfuegbar' obwohl Pfote ready zeigte —
activate loeschte die alten Static-Caches, waehrend der neue erst im
Hintergrund befuellt wurde; der GL-Stack (maplibre/pmtiles/map-offline)
war zudem nie im Precache, nur nach erster Online-Kartenoeffnung.
- activate: _migrateStaticCaches uebernimmt fehlende Eintraege der alten
Caches unter nacktem Key (Online-Refresh ueberschreibt sie sauber),
DANN erst loeschen
- PRIORITY_PAGES + GL-Karten-Stack (maplibre-gl.js/.css, pmtiles,
map-gl-style, map-offline, map-gl-markers, map-gl-mini)
- generischer Cache-First-Pfad: ignoreSearch-Fallback fuer eigene /js/+/css/
(?v=APP_VER zeigt sonst am Carry-Over/bare-Bestand vorbei)
Bump v1233
Bei schwachem Empfang blieb die App beim Start SEHR LANGE weiss: CSS +
Kern-JS + index.html waren Network-First OHNE Timeout — der Cache griff
nur bei hartem Fetch-Fehler, nicht bei troepfelnder Verbindung.
Jetzt: Promise.race(Netz, 2,5s) -> Cache-Fallback (stale-while-revalidate,
Netz aktualisiert den Cache im Hintergrund weiter). Versions-Updates laufen
weiter ueber x-app-version + controllerchange.
Bump v1232
- Indikator links unter die Zoom-Regler (rechts verdeckte Legenden-Chips)
- Flugmodus bei offener App -> Position raw als Funkloch-Zone (offline-Event)
- Ent-Funklochen: Zonen-Liste im Offline-Modal mit X (removeDeadZone)
- Warnungs-Aktualitaet: _mergeStore Bbox-Replace (aufgehobene Giftkoeder/
gefundene Hunde verschwinden; Fetch-Kreis deckt Bbox via sqrt2 ab;
fresh=null merged nie) + 24h-Refresh im 50km-Umkreis beim Start
- Routen offline nutzbar halten: ensureRouteCorridors beim Start-Check
(Stichproben-Verify, Re-Download aus preview_track, Region-Dedupe)
- Stub-Tests ins Repo: tests/js/ (r1/r3/r4/r5, alle gruen)
Bump v1231
Funkloch-Gedaechtnis = Quelle der Wahrheit, Kacheln = ableitbarer Cache:
- Ephemeres Vorausladen: Prefetch-Kacheln werden bei Aufzeichnungsende
geloescht, wenn die Runde kein Funkloch hatte (nur neue Keys)
- Netz-Probe bei Aufzeichnung (~2min, 6s-Timeout): erkennt Funkloecher auch
in bereits gespeicherten Gebieten (dort kein Remote-Miss als Signal)
- clear() behaelt Zonen (filled=false) -> naechster Online-Start laedt
Funkloch-Gebiete automatisch neu, auch nach 'Alles loeschen'
- Start-Check mit Position: nur Zonen im 50-km-Umkreis, naechste zuerst,
Coverage-Verify (faengt Eviction ab); Pfote Segment 5 = alle Zonen gefuellt
- Coverage-Layer zweifarbig: Funkloch orange, manuell blau + Modal-Legende
- Stub-Tests Runde 4 (Prune/Probe/clear/Naehe/Verify/Faerbung) bestanden
Bump v1230
Geraetetest-Befunde Runde 2:
- Giftkoeder verschwanden offline: /api/places kam aus dem SW-Cache (feste URL)
und verhinderte den allFailed-Fallback, waehrend /api/poison?lat=... (Bbox-URL)
scheiterte -> jetzt faellt jede Quelle EINZELN auf den letzten guten Stand
zurueck (localStorage) + Merge aus dem Offline-Region-Snapshot
- Region-Download speichert jetzt auch /api/poison + /api/lost der Gegend
(p/_poison, p/_lost, anonym; MapOffline.alerts(kind,bbox) als Reader) —
Sicherheitsdaten muessen auch am vorab gespeicherten Urlaubsort da sein
- lost.js Offline-Pfad merged den Region-Snapshot in Cache- und Leer-Fall
- Routen-Korridor war 'unsichtbar' (lag im schon gespeicherten Gebiet):
nach dem Speichern werden die gespeicherten Bereiche blau auf der
Detailkarte eingeblendet; Logik per Node-Stub-Test verifiziert
Bump v1227
Der SW beantwortet nicht-cachebare API-GETs offline mit 503 + JSON-Body,
r.json() wirft dann NICHT -> Erfolgs-Pfad ersetzte Marker durch {detail:...}.
_fetchPois prueft jetzt r.ok + Array.isArray, dadurch greift der
IndexedDB-Fallback (MapOffline.pois) in Phase 1 und Phase 2 behaelt den Bestand.
Bump v1224
- MapOffline.downloadAround speichert zusaetzlich /api/osm/pois je Typ fuer die
Region-Bbox in IndexedDB (Key-Praefix p/, Merge per id — zweite Region loescht
die erste nicht); MapOffline.pois(type,bbox) filtert fuer den Ausschnitt
- map.js Phase-1-Fallback: Fetch fehlgeschlagen (offline) -> gespeicherte
Region-POIs statt leerer Karte; Download-Toast zeigt Marker-Anzahl
- Offline-Banner: nach 5s auf schmale Icon-Leiste eingeklappt (verdeckte die
Karten-Legende); Inline-Styles nach components.css konsolidiert
- Bump v1223
- by_offline_tiles Default AN auf staging.banyaro.app (localStorage/?tilesoffline=1/0 uebersteuert)
- Speed-Dial 'Karte offline speichern': GL -> MapOffline.downloadAround(Kartenmitte, 5km),
Leaflet -> alter Raster-Prefetch (_cacheTiles war seit FAB-Redesign verwaist)
- Glyphs in IndexedDB (Key-Praefix f/) + byt://f/-Protokoll: ueberlebt App-Updates
- OSM-Raster-Prefetch im Offline-Tiles-Modus uebersprungen (GL nutzt das Raster nicht)
- Button-Sichtbarkeit gated: GL ohne Offline-Flag (= Production) zeigt ihn nicht