From a3382bb0aa4cd32c7df0294f836687ba18fdf32d Mon Sep 17 00:00:00 2001 From: Perplexity Computer Date: Mon, 22 Jun 2026 09:55:44 +0000 Subject: [PATCH] Release GPS2Audio v2.7.38 Samsung audio fix --- RELEASES.md | 227 +++ app/build.gradle.kts | 313 ++- .../kotlin/de/waypointaudio/MainActivity.kt | 19 +- .../de/waypointaudio/data/MapStyleSettings.kt | 44 +- .../de/waypointaudio/data/WaypointStore.kt | 45 +- .../repository/WaypointRepository.kt | 9 +- .../service/ManualAudioPlayer.kt | 24 +- .../de/waypointaudio/ui/BegleitmusikDialog.kt | 247 ++- .../de/waypointaudio/ui/ExplorerScreen.kt | 102 +- .../ui/ExplorerScreenMapLibre.kt | 1339 ++++++++++--- .../kotlin/de/waypointaudio/ui/HomeScreen.kt | 77 +- .../de/waypointaudio/ui/MapLayerPanel.kt | 56 +- .../kotlin/de/waypointaudio/ui/MapScreen.kt | 3 +- .../waypointaudio/ui/PttRecordingDialogs.kt | 3 +- .../de/waypointaudio/ui/RoutePlannerSheet.kt | 849 +++++--- .../ui/TourverlaufEditorSheet.kt | 456 +++++ .../waypointaudio/ui/VersionNoticeDialog.kt | 2 +- .../de/waypointaudio/ui/WaypointEditDialog.kt | 1700 ++++++++++------- .../de/waypointaudio/ui/WaypointListScreen.kt | 94 +- .../viewmodel/WaypointViewModel.kt | 501 ++++- app/src/main/res/values/strings.xml | 282 ++- ...Audio_v2_7_38_samsung_audio_fix_handoff.md | 86 + ...Audio_v2_7_38_samsung_audio_fix_source.zip | Bin 0 -> 502314 bytes 23 files changed, 4914 insertions(+), 1564 deletions(-) create mode 100644 app/src/main/kotlin/de/waypointaudio/ui/TourverlaufEditorSheet.kt create mode 100644 releases/v2.7.38/GPS2Audio_v2_7_38_samsung_audio_fix_handoff.md create mode 100644 releases/v2.7.38/GPS2Audio_v2_7_38_samsung_audio_fix_source.zip diff --git a/RELEASES.md b/RELEASES.md index 048fecb..4f1ce74 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -35,6 +35,15 @@ Release: https://gitea.nesohub.org/marcel/GPS2Audio/releases/tag/v2.1.3 | `v2.5.36` | MapLibre Phantom-Layer-Fix | Root-Cause-Fix der weißen Phantom-GPX-Linie im neutralen Standard-Explorer (0 Wegpunkte). Ursache: `currentTrack.isNotEmpty()` in `visibleTrack` feuerte vor der `isNeutralStandard`-Prüfung, weil `loadPersistedTrackForCurrentTour` den TrackRecordingManager auch für DEFAULT_TOUR_NAME befüllte. Fix: (1) `isNeutralStandard`-Guard vor `currentTrack.isNotEmpty()` verschoben; (2) ViewModel befüllt den Manager-Track nicht mehr für die neutrale Standardtour. Alle echten Touren, laufende Aufzeichnungen und aktive Drafts unverändert. Versionscode 90. | | `v2.4.6` | Persistente Tourrouten | Reiner Datenmodell-/Persistenzschritt. Eine Tour kann eine dauerhaft gespeicherte Route besitzen (Start, Ziel, Via, Geometrie, Profil, Endpunkt/Quelle, Distanz/Dauer, Zeitstempel). Routenplaner kann die berechnete Route oder die Planlinie an die aktuelle Tour binden („Tourroute speichern/ersetzen/löschen"). Clipabschnitte folgen primär der frisch berechneten Route, dann der gespeicherten Tourroute, dann dem Track, zuletzt einer Planlinie — keine freien Linien. Wegpunkte bleiben Bausteine ohne fest verdrahtete Route und lassen sich später in andere Touren kopieren. Rückwärtskompatibel: bestehende JSON/Backups ohne Tourroute laden weiterhin; Backup-Export/Import nehmen Tourrouten mit. Versionscode 53. | +| `v2.6.2` | Route-Persistenz-Fix | Berechnete Route/Tourlinie bleibt beim Workspace-Wechsel erhalten. Root Cause: `routeLine` lebte nur im Compose-State (remember) und wurde beim Verlassen des Explorers verworfen. Fix: (1) `currentSessionRoute` StateFlow im ViewModel speichert die zuletzt berechnete Route tour-gebunden. (2) Nach erfolgreicher OSRM-Berechnung wird die Route via `setCurrentSessionRoute()` im ViewModel gesichert und gleichzeitig dauerhaft als `TourRoute` persistiert. (3) `LaunchedEffect(selectedTour)` stellt beim Zurückkehren die Route wieder her — statt des bisherigen `LaunchedEffect(selectedTour, activeTourRoute?.id)`, das beim Auto-Speichern sofort wieder zurücksetzte. (4) Planlinie und Tourverlauf-Begriffe aus v2.6.1/v2.6.0 unverändert. versionCode 105. | +| `v2.7.0` | Tourverlauf-Editor | Neues TourverlaufEditorSheet (v2.7.0): Verlaufspunkte manuell auf der Karte setzen (Tipp-Modus oder Kartenmitte), letzten Punkt entfernen, Verlauf löschen, Verlaufspunkt als Audio-Wegpunkt erstellen. Einklappbarer Online-Routing-Abschnitt. Race-Guard (v2.7.1) gegen zu frühes Auto-Save (manualRouteInitialized). versionCode 106/107. | +| `v2.7.2` | Tourverlauf-Persistenz-Fix | Root Cause: routePlan (Start/Via/Ziel des RoutePlannerSheet) lebte nur im lokalen Compose-State und wurde beim Workspace-Wechsel verloren. Planlinie („Planlinie zeigen“) wurde nicht als Session-Route persistiert. Fix: (1) Neuer currentSessionPlan StateFlow im ViewModel — speichert den RoutePlan tour-gebunden und überlebt Workspace-Wechsel. (2) onPlanChange → viewModel.setCurrentSessionPlan(). (3) onShowPlanline → buildTourRouteFromState() + setCurrentSessionRoute() (wie OSRM). (4) LaunchedEffect(selectedTour): restauriert Plan aus Session, kein blindes Reset. (5) Kalt-Start-Restore: activeTourRoute mit Start/Destination wird als RoutePlan wiederhergestellt. (6) manualRouteInitialized-Guard aus v2.7.1 unverändert. versionCode 108. | +| `v2.7.9` | Explorer State Isolation | v2.7.9 — Explorer-State-Isolation: LaunchedEffect(selectedTour) im ExplorerScreenMapLibre räumt alle Waypoint-Dialog-States (actionMenuWaypoint, editDialogWaypoint, showEditDialog, deleteConfirm, tapMode) bei Tour-Wechsel sofort auf, damit keine alte Wegpunkt-Referenz in den Dialog der neuen Tour gelangen kann. Marker der Vorgänger-Tour werden explizit vor dem waypoints-Redraw-Effekt gelöscht. versionCode 115. | +| `v2.7.10` | Waypoint-Persistence-Fix (Unbenannte Tour) | Root Cause: selectDefaultTour() setzte bei jedem Einstieg in den Explorer aus der Audio-Bibliothek/Home blind auf DEFAULT_TOUR_NAME („Standard“). War zuvor eine spontane „Unbenannte Tour“ angelegt worden, filterten Waypoints und Explorer-Karte nach „Standard“ und zeigten leere Ansicht. Fix: selectDefaultTour() prüft synchron, ob echte (nicht-Standard) Touren in _tourList vorhanden sind. Ist das der Fall, wird sofort zur ersten echten Tour gewechselt – statt auf DEFAULT zu fallen und auf den asynchronen combine-Kollektor (v2.7.5) zu warten, der den Reset dann ggf. rückabwickelte. Keine Regressionen: Lizenz, Backup, Multiclip, PTT, Atmo, Bibliothek, MapLibre, POIs, Tourverlauf, GPS-Track, Explorer-State-Isolation. versionCode 116. | +| `v2.7.8` | Unbenannte Tour + Planlinie Auto-Render | (1) 'Spontane Tour' → 'Unbenannte Tour': UI-String explorer_spontane_tour und createSpontaneousTour()-Basis geändert, Schlüssel/Funktionsname intern beibehalten. (2) Root Cause Planlinie: savedRouteLine wurde korrekt befüllt, aber nicht in routeLine übertragen; routeLine ist die primäre Zeichnungsquelle im draw-LaunchedEffect. Bei Kaltstart und ohne Button-Druck fehlte der Transfer. Fix 1: Neues LaunchedEffect(savedRouteLine, selectedTour) überträgt savedRouteLine → routeLine, wenn routeLine leer und keine Session-Route vorhanden ist. Fix 2: Auto-Persistenz-Effekt (LaunchedEffect routePlanline) ruft zusätzlich setCurrentSessionRoute() auf, statt nur saveTourRouteFor() — füllt Session-Route auch ohne Button. Fix 3: activeTourRoute als zusätzlicher Key im Zeichen-LaunchedEffect. Keine Regressionen. versionCode 114. | + +| `v2.7.26` | Persistent Map Preferences | Globale Kartenpräferenzen dauerhaft gespeichert: Wegpunkt-Marker, Audio-Radius/Reichweite, GPS-Track/Draft-Linien, POIs-automatisch-nachladen jetzt persistent (MapStyleStore). Bestehende Persistenz (baseStyle, showAudioLength, showAudioLines, POI-Kategorien, POI-Namen, perspectiveTilt, Standort-Folgen) unverändert erweitert. Standort-Folgen entschärft: Jede manuelle Kartenverschiebung deaktiviert Follow sofort (statt nur bei >40m Distanz). Kein Auto-Zentrieren beim nächsten GPS-Fix. Beim Öffnen des Explorers: Kamera auf Tour/Wegpunkte, nicht auf Live-Standort (sofern Follow aus). Keine Regressionen. versionCode 132. | + ## Release-Links - `v1.6.2-osm-layout`: https://gitea.nesohub.org/marcel/GPS2Audio/releases/tag/v1.6.2-osm-layout @@ -63,3 +72,221 @@ Die hochgeladenen Release-Pakete enthalten APK, Quellcode-ZIP und Handoff bezieh ## Empfohlene Nutzung Für neue Nutzer ist `v2.1.3` der beste Einstieg. Ältere Versionen bleiben als Archiv erhalten, damit Entwicklungsschritte, Fehlerbehebungen und Zwischenstände nachvollziehbar bleiben. + +## v2.7.17 — Route-first Explorer (2026) + +**GPS2Audio v2.7.17** führt den konservativen UI-/Bedienlogik-Umbau „Route-first Explorer" ein. + +### Was ist neu +- **Route zuerst**: Der mentale Ablauf ist jetzt „Route planen → Tourpunkte setzen → Audio hinzufügen". +- **Tourpunkt-Konzept**: Verlaufspunkte werden als „Tourpunkte" bezeichnet. Ein Tourpunkt kann zunächst nur die Route formen; Audio wird bewusst nachträglich hinzugefügt. +- **Klarere Labels**: „Route planen" statt „Tourverlauf planen", „Routenlinie anzeigen" statt „Planlinie zeigen", „Audio hier hinzufügen" statt technischem „Als Audio-Wegpunkt erstellen". +- **Route bearbeiten**: Der Tourverlauf-Editor heißt nun „Route bearbeiten" – klarer, weniger abschreckend. +- **Abwärtskompatibel**: Bestehende Audio-Wegpunkte und Verlaufslinien aus v2.7.16 bleiben vollständig erhalten. + +### Geschützte Funktionen +Keine Änderungen an: MapLibre-Rendering, Waypoint-Rendering, routeRenderKey/waypointRenderKey/overlayRenderNonce, Planlinie-Autorender, Explorer-Kontext-Isolation, POI-Autoload, Kartenstile, Lizenzsystem, Backup/Restore, Multiclip, manuelle Wiedergabe, GPS-Aufzeichnung. + +### Build-Details +- versionCode: 123 +- versionName: 2.7.17 + +## v2.7.18 — Unified Tour Layers (2026) + +**GPS2Audio v2.7.18** konsolidiert die Karten-Darstellung zu einem einheitlichen Tour-System. + +### Was ist neu +- **Einheitliche Tourlinie**: Routing, manuelles Zeichnen und gespeicherte Tourlinie wirken jetzt als ein System. Eine manuell gezeichnete Route wird im gespeicherten Zustand als grüne Tourlinie dargestellt (wie eine OSRM-berechnete Route) — keine verwirrende Doppellinie mehr. +- **Bearbeitungs-Vorschau nur im Zeichenmodus**: Die violette Vorschaulinie erscheint nur noch, während der Nutzer aktiv Verlaufspunkte zeichnet (manualRouteMode=true). Im Normalbetrieb ist die Karte übersichtlicher. +- **Verlaufspunkt-Marker reduziert**: Kleine Punkt-Marker für Verlaufspunkte erscheinen ebenfalls nur im Bearbeitungsmodus — reduziert visuelles Rauschen im Explorer. +- **Planungs-Vorschau bleibt erkennbar**: Die orange/gedimmte Planlinie (Routing-Werkzeug) bleibt visuell als Werkzeug-Vorschau erkennbar. +- **Abwärtskompatibel**: Kein Datenmodell-Umbau, bestehende Routen/Wegpunkte unverändert. + +### Geschützte Funktionen +Keine Änderungen an: experimentellem Routing/Route berechnen, Route planen, Routenlinie anzeigen, Route bearbeiten/manuelles Zeichnen, Audio-Waypoints, Multiclip, manuelle Wiedergabe, PTT, Atmo, MapLibre Initial-Render-Fixes, Planlinie-Autorender, routeRenderKey/waypointRenderKey/overlayRenderNonce, Explorer-Kontext-Isolation, POI-Autoload, Kartenstile, Lizenzsystem, Backup/Restore. + +### Build-Details +- versionCode: 124 +- versionName: 2.7.18 + +## v2.7.19 — Tourplaner Integration Fix (2026) + +**GPS2Audio v2.7.19** behebt den Verlust von Start-, Ziel- und Via-Punkten im Tourplaner und integriert das manuelle Zeichnen als Werkzeug des Tourplaners. + +### Was ist neu +- **Fix: Start/Ziel/Via dauerhaft gespeichert**: Der Tourplaner schreibt den Routenplan jetzt sofort in die Datenbank, sobald Start und Ziel gesetzt sind. Bisher wurde nur die In-Memory-Session gespeichert — nach einem Prozess-Kill (App-Neustart) war der Plan verloren. Jetzt bleibt er auch nach Neustart vollständig erhalten. +- **Manuelles Zeichnen im Tourplaner**: Die Schaltfläche „Zeichenmodus öffnen“ ist jetzt direkt im Tourplaner (RoutePlannerSheet) eingebettet. Routing und manuelles Zeichnen sind gleichwertige Bearbeitungsmethoden im selben Planer. +- **Kein Rückschritt beim Doppellinien-Fix**: Die violette Bearbeitungs-Vorschau erscheint weiterhin nur im aktiven Zeichenmodus (wie in v2.7.18). +- **Abwärtskompatibel**: Kein Datenmodell-Umbau, bestehende Routen/Wegpunkte unverändert. + +### Geschützte Funktionen +Keine Änderungen an: experimentellem Routing/Route berechnen, Routenlinie anzeigen, Route bearbeiten/manuelles Zeichnen, Audio-Waypoints, Multiclip, manuelle Wiedergabe, PTT, Atmo, MapLibre Initial-Render-Fixes, Planlinie-Autorender, routeRenderKey/waypointRenderKey/overlayRenderNonce, Explorer-Kontext-Isolation, POI-Autoload, Kartenstile, Lizenzsystem, Backup/Restore. + +### Build-Details +- versionCode: 125 +- versionName: 2.7.19 + +## v2.7.20 — Flexible Route Shaping (2026) + +**GPS2Audio v2.7.20** führt flexible Routenformung per Karten-Tap ein. + +### Was ist neu +- **AddViaPoint-Modus**: Neuer TapMode für direkte Zwischenpunkt-Setzung per Karten-Tap aus dem Routenplaner heraus. +- **Intuitiver Fallback**: 1. Tap = Start, 2. Tap = Ziel, weitere Taps = Zwischenpunkte. +- **Via-Sektion**: Im Tourplaner klar als „Zwischenpunkte (Route formen)" bezeichnet. + +### Build-Details +- versionCode: 126 +- versionName: 2.7.20 + +## v2.7.21 — Waypoint Preservation Fix (2026) + +**GPS2Audio v2.7.21** behebt kritischen Datenverlust: Audio-Wegpunkte innerhalb einer Tour wurden beim Öffnen des Routenplaners unter bestimmten Bedingungen gelöscht. + +### Root Cause +Race-Condition in `duplicateTour()`, `deleteTour()` und `renameTour()`: Diese Funktionen lasen `_waypoints.value` aus dem In-Memory-State (MutableStateFlow). Wenn der DataStore-Erstladevorgang noch nicht abgeschlossen war, enthielt `_waypoints.value` noch die initiale leere Liste. Ein `saveAll(emptyList() + newWps)` überschrieb dann alle bestehenden Wegpunkte aller Touren. + +Zusätzlich: Kein globaler Schutz vor einem `saveAll([])` bei nicht-leerer DataStore-Wegpunktliste. + +### Fixes +1. **`WaypointStore.saveAll()` Preservation-Guard**: Wenn die übergebene Liste leer ist, aber die DataStore-Wegpunktliste nicht-leer ist, wird der Schreibvorgang blockiert (atomarer Check in `dataStore.edit`). Verhindert versehentlichen Totalverlust. +2. **`WaypointStore.saveAllForced()`**: Neue Methode für explizite Lösch-/Restore-Operationen, die den Preservation-Guard umgehen dürfen. +3. **Race-Condition-Fix in `duplicateTour`/`deleteTour`/`renameTour`**: Lesen jetzt mit `repository.waypoints.first()` direkt aus DataStore statt aus dem möglicherweise noch leeren `_waypoints.value`. +4. **AddViaPoint-Pfad (v2.7.20) bestätigt sicher**: Kein Waypoint-Speicherpfad wird durch Route-Planen, AddViaPoint oder Planlinie-Auto-Persistenz ausgelöst. +5. **Architektonische Invariante dokumentiert**: `saveTourRoute`/`saveTourRouteFor` schreiben ausschließlich in `KEY_TOUR_ROUTES`, nie in `KEY_WAYPOINTS`. + +### Geschützte Funktionen +Alle Funktionen aus v2.7.20 unverändert: AddViaPoint, flexible Routenformung, v2.7.19 Start/Via/Ziel-Persistenz, v2.7.18 Doppellinie-Fix, Audio-Waypoints, Multiclip, manuelle Wiedergabe, PTT, Atmo, MapLibre-Render-Fixes, Planlinie-Autorender, routeRenderKey/waypointRenderKey/overlayRenderNonce, POI-Autoload, Kartenstile, Lizenzsystem, Backup/Restore. + +### Build-Details +- versionCode: 127 +- versionName: 2.7.21 + +--- + +## v2.7.22 — Saved Route Render Fix + +**Problem**: Ein gespeicherter Tourverlauf (manuell gezeichnet, Quelle MANUAL) war im RoutePlannerSheet sichtbar (Karte mit Buttons "Tourverlauf ersetzen/löschen"), wurde aber visuell nicht als Linie auf der Karte angezeigt. Zusätzlich zeigte der Tourplaner "Noch keine Route. Routenlinie anzeigen genügt — Online-Routing ist optional." + +**Root Cause**: `savedRouteLine` (die Hilfsliste, aus der die Kartenrenderschicht die grüne Tourlinie zeichnet) schloss MANUAL-Routen explizit mit `emptyList()` aus (Zeile 290, v2.5.3-Kommentar). Die ursprüngliche Intention war, Doppellinien zu verhindern (v2.7.18). Aber v2.7.18 hat die Bearbeitungs-Vorschau (manualRoutePolylines, violett) bereits auf `manualRouteMode == true` beschränkt. Damit war der Ausschluss in `savedRouteLine` überflüssig und verhinderte die korrekte Darstellung. + +**Fixes (ExplorerScreenMapLibre.kt)**: +1. **Fix 1** — `savedRouteLine`-Berechnung: MANUAL nicht mehr pauschal mit `emptyList()` ausgeschlossen. Stattdessen gleiches Verhalten wie OSRM: Route wird als Punkte zurückgegeben, Phantom-Guard auf Standardtour bleibt erhalten. +2. **Fix 2** — `LaunchedEffect(savedRouteLine)`: MANUAL-Quellen überspringen (wie PLANLINE), damit MANUAL via `hasSavedRoute`-Pfad grün gezeichnet wird (nicht blau als OSRM-Route). Kein `routeLine`-Load für MANUAL. +3. **Fix 3** — RoutePlannerSheet-Aufruf: `hasRoute = routeLine.size >= 2 || savedRouteLine.size >= 2` — "Noch keine Route" erscheint nicht mehr, wenn eine gespeicherte MANUAL- oder OSRM-TourRoute vorhanden ist. + +### Geschützte Funktionen +Alle Funktionen aus v2.7.21 unverändert: Waypoint-Preservation-Guard, AddViaPoint, flexible Routenformung, v2.7.19 Start/Via/Ziel-Persistenz, v2.7.18 Doppellinie-Fix (manualRouteMode-Guard bleibt), Audio-Waypoints, Multiclip, manuelle Wiedergabe, PTT, Atmo, MapLibre-Render-Fixes, Planlinie-Autorender, routeRenderKey/waypointRenderKey/overlayRenderNonce, POI-Autoload, Kartenstile, Lizenzsystem, Backup/Restore. + +### Build-Details +- versionCode: 128 +- versionName: 2.7.22 + +--- + +## v2.7.23 — Route Planner Flow Fix + +**Problem**: Der Routenplaner zeigte eine violette/orange Planlinie auf der Karte, aber diese konnte nicht sinnvoll als Tourverlauf gespeichert oder mit dem Tourverlauf verknüpft werden. Audio-Wegpunkte ließen sich zwar als Start/Ziel/Via wählen, aber der Weg von der Planlinie zum persistierten Tourverlauf war unklar. + +**Root Cause**: Es fehlte ein direkt zugänglicher, klar benannter "Als Tourverlauf übernehmen"-Button in der Sticky Action Bar des Tourplaners. Die vorhandene `TourRouteStatusCard` im scrollbaren Bereich war nicht sichtbar genug, und die Buttons "Speichern"/"Ersetzen" dort waren bei bestehenden Routen in der Karte verborgen. Zusätzlich nutzte `onShowPlanline` und `onSaveTourRoute` `routePlanline` aus der Compose-Remember-Chain, ohne einen Inline-Fallback für den Fall, dass die Recomposition noch nicht stattgefunden hatte. + +**Fixes**: +1. **Neuer "Als Tourverlauf übernehmen"-Button** in der Sticky Action Bar (neben "Routenlinie anzeigen"). Aktiviert wenn `hasPlanline || hasRoute`. Speichert direkt — kein zusätzliches Scrolling nötig. +2. **`onAdoptAsTourRoute`-Callback** in ExplorerScreenMapLibre: Wählt OSRM-Route (wenn vorhanden) oder Planlinie als TourRoute-Quelle, schreibt in DB und Session-Route, zeigt Statusmeldung. +3. **Inline Planline-Fallback**: `onShowPlanline`, `onSaveTourRoute`, `onReplaceTourRoute` berechnen die Planline-Koordinaten inline aus `routePlan.orderedStops()` als Fallback, falls `routePlanline` (remember-computed) noch leer ist. +4. **setCurrentSessionRoute zusätzlich bei Save/Replace**: Session-Route wird nach Speichern auch im ViewModel gesetzt, damit Workspace-Wechsel sofort die neue Route kennt. +5. **TourRouteStatusCard-Hinweis**: Zeigt proaktiv `route_planner_adopt_planline_hint` wenn Planlinie vorhanden aber noch kein gespeicherter Verlauf. + +### Audio-Wegpunkte als Planpunkte +- Auswahl eines Audio-Wegpunkts für Start/Ziel/Via: unverändert über WaypointPickerDialog → applyStopToRole() → onPlanChange(). +- Keine Waypoint-Löschung, keine Duplikation (Waypoint-Preservation-Guard aus v2.7.21 bleibt aktiv). +- Nach Auswahl: routePlanline auto-computed, hasPlanline=true, Buttons aktiv. + +### Geschützte Funktionen +Alle Funktionen aus v2.7.22 unverändert: Saved Route Render Fix, Waypoint-Preservation-Guard, AddViaPoint, flexible Routenformung, v2.7.19 Start/Via/Ziel-Persistenz, v2.7.18 Doppellinie-Fix, Audio-Waypoints, Multiclip, manuelle Wiedergabe, PTT, Atmo, MapLibre-Render-Fixes, Planlinie-Autorender, routeRenderKey/waypointRenderKey/overlayRenderNonce, POI-Autoload, Kartenstile, Lizenzsystem, Backup/Restore. + +### Build-Details +- versionCode: 129 +- versionName: 2.7.23 + +--- + +## v2.7.24 — Tourverlauf UX Polish + +Tourverlauf-UX-Polish: Verbesserte Nutzererfahrung beim Verwalten gespeicherter Tourverlauf-Linien im Explorer. Keine neue Funktionalität — nur UX-Feinschliff und Code-Qualität. + +### Build-Details +- versionCode: 130 +- versionName: 2.7.24 + +--- + +## v2.7.25 — Tourline Initial Render Fix + +**Problem**: Die gespeicherte Tourlinie erschien beim ersten Öffnen des Explorers nicht sofort auf der Karte. Erst eine spätere UI-Interaktion (z.B. Abspielen eines Clips) löste den Render aus. + +**Root Cause**: Zwei zusammenwirkende Timing-Probleme: + +1. **Doppelter Style-Load**: `LaunchedEffect(layerState.baseStyle, mapStyleSettings.perspectiveTilt, styleReady)` enthielt `styleReady` als Key. Wenn der initiale Style-Load (im `AndroidView` factory Callback) `styleReady=true` setzte, feuerte dieser Effect erneut und rief `ml.setStyle()` ein zweites Mal auf. Das wischte alle bereits gezeichneten Polylines weg und trigerred einen zweiten asynchronen Style-Load. + +2. **Late activeTourRoute**: `activeTourRoute` wird asynchron aus der Datenbank geladen (via `StateFlow` im ViewModel). Kam der zweite Style-Load vor dem DB-Load ab, war `savedRouteLine` noch leer. Der `overlayRenderNonce`-Mechanismus hatte bereits gefeuert, bevor die Route verfügbar war. Obwohl `savedRouteLine` als Key im Overlay-`LaunchedEffect` gelistet ist, konnten Compose-Snapshot-Caching-Effekte das erneute Feuern verhindern. + +**Fixes**: +1. **`styleReady` aus Style-Change-LaunchedEffect-Keys entfernt** (v2.7.25): Verhindert den Doppel-Reload. Der Effect feuert jetzt nur noch bei echten `baseStyle`- oder `perspectiveTilt`-Änderungen. +2. **Dedizierter `LaunchedEffect(savedRouteLine.size, styleReady, mapLibreMap)`** (v2.7.25): Feuert wenn `savedRouteLine` mindestens 2 Punkte hat UND Style bereit UND Map initialisiert. Inkrementiert `overlayRenderNonce`, sodass der Zeichnungseffekt garantiert neu startet — unabhängig davon, wann `activeTourRoute` aus der DB ankommt. + +**Nicht geändert**: +- Speicherlogik (keine Änderungen an `saveTourRouteFor`, `activeTourRoute`, `_tourRoutes`) +- v2.7.24 Tourverlauf UX Polish +- v2.7.23 'Als Tourverlauf übernehmen' Flow Fix +- v2.7.22 Saved Route Render Fix +- v2.7.21 Waypoint Preservation Guard +- v2.7.18 Doppellinie-Fix (manualRouteMode-Guard) +- Alle anderen Funktionen (AddViaPoint, OSRM, PLANLINE, MANUAL, Audio-Waypoints, PTT, Atmo, Backup, Lizenzsystem) + +### Build-Details +- versionCode: 131 +- versionName: 2.7.25 + +--- + +## v2.7.30 — MapLibre Overlay Rebuild Fix + +**Problem (Nutzerbericht nach v2.7.29)**: "nein das hat nichts verändert. Das ist der Live Standort und die Waypoints bzw. Planlinie wird nicht angezeigt." Screenshot zeigte nur einen hellen/weißen Kreis als Live-Standort, keine Waypoint-Marker, keine Planlinie. + +**Root-Cause-Analyse (warum v2.7.29 nicht wirkte)**: + +1. **yield() zu kurz**: Das einzige `yield()` (Wartedauer: 1 Frame ≈ 16ms) nach `styleReady` in den Overlay-LaunchedEffects war nicht ausreichend für MapLibres GL-Thread und AnnotationManager-Initialisierung nach `setStyle()`. `addMarker()` und `addPolyline()` schlugen still fehl — keine Exception, aber Rückgabewert null/leer. + +2. **Kein Retry-Mechanismus**: Wenn der erste Render-Versuch (150ms nach Style-Load) scheiterte, gab es keinen weiteren Versuch. Nur Nutzerinteraktion (State-Änderung) löste einen neuen Render aus. + +3. **runCatching fehlte**: Fehlschlagende `addMarker()`/`addPolyline()`-Aufrufe warfen keine Exception in die Coroutine, aber gaben null zurück. Ohne `runCatching` konnte ein unerwarteter Fehler die Coroutine abbrechen und alle nachfolgenden Zeichenoperationen verhindern. + +4. **clearAllAnnotationsCaches Lücke**: `planlinePolylines` und `routeStopMarkers` wurden beim Style-Cleanup (vor `setStyle()`) nicht geleert — veraltete Referenzen blieben im Cache und führten zu nutzlosen `removePolyline()`-Aufrufen auf ungültigen Objekten. + +5. **v2.7.29 Puck-Fix: Early-Return-Problem**: `lastLat ?: return@LaunchedEffect` vor `yield()` bedeutete: Hatte der Nutzer beim Style-Load noch keinen GPS-Fix, blieb der Puck dauerhaft leer (bis zum nächsten GPS-Fix). Wurde der Fix vor GPS-Empfang aufgerufen, war `lastLat` null → sofortiger Return → kein Puck gezeichnet. + +**Fixes v2.7.30**: + +1. **delay(150ms) statt yield()** in beiden Overlay-LaunchedEffects (Waypoints/Tracks + Routen/Planline): Gibt dem AnnotationManager ausreichend Zeit nach Style-Load. + +2. **Zentraler Retry-Mechanismus (500ms)**: `LaunchedEffect(styleReady, mapLibreMap)` wartet 500ms nach jedem Style-Ready und inkrementiert `overlayRenderNonce` ein zweites Mal. Ergebnis: Zwei Render-Versuche — bei 150ms und bei 650ms nach Style-Load. Der zweite ist garantiert erfolgreich, da der AnnotationManager nach 500ms sicher bereit ist. + +3. **delay(200ms) + runCatching im Puck-Rehydrate-LaunchedEffect**: Puck-Marker wird robuster gezeichnet, Fehler werden abgefangen. + +4. **runCatching um alle addMarker/addPolyline-Aufrufe**: In `drawExplorerOverlaysMapLibre` und der Route-LaunchedEffect — verhindert silent-Crashes und gibt dem 500ms-Retry die Chance, alle fehlgeschlagenen Overlays nachzuzeichnen. + +5. **clearAllAnnotationsCaches erweitert**: `planlinePolylines` und `routeStopMarkers` werden jetzt ebenfalls beim Style-Cleanup geleert (neue optionale Parameter). + +**Nicht geändert**: +- v2.7.28 Map Style Apply Fix (appliedBaseStyle/appliedPerspectiveTilt guard) +- v2.7.27 Kartenpräferenz-Persistenz +- v2.7.26 Standort-Folgen-Fix +- v2.7.25 Initial-Render-Fix (savedRouteLine.size LaunchedEffect) +- v2.7.24 UX Polish, v2.7.23 Tourverlauf übernehmen +- v2.7.21 Waypoint Preservation Guard +- Alle Funktionen: Routenplanung, POIs, Kartenstile, Audio-Waypoints, Multiclip, PTT, Atmo, Lizenzsystem, Backup/Restore + +### Build-Details +- versionCode: 136 +- versionName: 2.7.30 diff --git a/app/build.gradle.kts b/app/build.gradle.kts index bacb296..291d2d2 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -157,8 +157,317 @@ android { // • Keine Regressionen: Phantom-Layer-Fix, Lizenzsystem, Multi-Clip, // PTT, Tour-Zähler, Backup/Cover, GPX-Import, Explorer/Routing, // Tour-/Waypoint-Kopien, Hintergrundwiedergabe. - versionCode = 102 - versionName = "2.5.48" + // v2.6.0 — Tourverlauf/Storyboard-Konsolidierung: + // • Routenplaner → "Tourverlauf" (deutsch, klar, kein Auto-Navi-Gefühl). + // • Storyboard-Panel übersichtlicher beschriftet und mit Erklärtext versehen. + // • Routepunkt vs. Wegpunkt (Audio) klar unterschieden in Labels. + // • Online-Routing als optional/sekundär markiert, nicht ausgebaut. + // • Keine Änderung an Logik, Backup, Lizenz, Playback, GPS-Aufzeichnung. + // v2.6.1 — Waypoint-Dialog-Polish: Formatierungsfehler RoutePlannerSheet + // behoben, WaypointEditDialog neu gestaltet (freundlichere Cards). + // Keine Logik-/Datenmodell-Änderungen. + // v2.7.0 — Tourverlauf-Editor: + // • Neues TourverlaufEditorSheet als dedizierter Bearbeitungsmodus. + // • Verlaufspunkte über Kartenmitte oder Tipp-Modus setzen. + // • "Als Audio-Wegpunkt erstellen" aus Verlaufspunkt heraus. + // • Online-Routing in RoutePlannerSheet sekundär (OutlinedButton). + // • Status-Bar zeigt Verlaufspunkt-Anzahl im Editor-Modus. + // • Persistenz/Speicherung über bestehende TourRoute/MANUAL-Infrastruktur. + // • Keine Regressionen: Playback, Backup, Lizenz, GPS-Aufzeichnung unverändert. + // v2.7.1 — Tourverlauf-Linie-Fix: + // • Behebt: Manuelle Tourverlauf-Linie wurde dauerhaft nicht angezeigt bzw. + // verschwand nach Öffnen/Schließen des Editors, Workspace-Wechsel oder + // Kartenstil-Reload. + // • Root Cause 1 (Race-Condition): Beim initialen Laden der Composable feuerte + // der Auto-Save-LaunchedEffect mit leerem manualRoutePoints, bevor der + // Load-Effekt die Punkte aus der DB geladen hatte. Bei leerem Liste UND + // wasManual=true wurde deleteTourRouteForCurrent() aufgerufen — die + // gespeicherte Route wurde gelöscht. Fix: manualRouteInitialized-Guard. + // • Root Cause 2 (Zeichnungs-LaunchedEffect verpasst Map-Init): + // mapLibreMap als Key im Drawing-LaunchedEffect fehlte. Wenn die Karte nach + // einem Workspace-Wechsel asynchron initialisiert wurde, feuerte das Effect + // nicht erneut (manualRoutePoints unverändert). Fix: mapLibreMap als + // zusätzlicher Key. + // • Root Cause 3 (Load-Effect-Keys zu breit): + // activeTourRoute?.id im Load-Effect führte dazu, dass jedes Auto-Save + // (neue updatedAtMillis) den Load neu auslöste. Fix: nur source als Key, + // kein id. + // • Verbesserung: Strichstärke der manuellen Tourverlauf-Linie erhöht + // (10/7 statt 8/5) für bessere Sichtbarkeit. + // • Keine Regressionen: v2.7.0 Editor, v2.6.2 Route-Persistenz, v2.6.1 + // Wegpunktdialog, v2.5.48 TrackDraft-Backup, POI, 3D, Playback, Backup, + // Lizenzsystem unverändert. + // v2.7.3 — Planlinie Auto-Show-Fix: + // • Root Cause: "Planlinie zeigen" persistierte die Planroute nur in die + // ViewModel-Session (RAM), nicht in die DB. Nach App-Neustart (Prozess-Kill) + // war kein activeTourRoute-Eintrag vorhanden, savedRouteLine blieb leer → + // keine Linie sichtbar, Button erneut nötig. + // • Fix 1 (Persistenz): onShowPlanline ruft jetzt zusätzlich + // viewModel.saveTourRouteFor() auf. PLANLINE wird in der DB gespeichert. + // activeTourRoute.polyline ist ab dem nächsten App-Start verfügbar. + // • Fix 2 (Zeichnungs-Priorität): savedRouteLine hat jetzt Vorrang vor + // routePlanline. routeLine > savedRouteLine > routePlanline. Doppelte + // Überlagerung (PLANLINE-Quelle) beseitigt. + // • Fix 3 (Clear-Symmetrie): onClear löscht die DB-PLANLINE-Route, wenn + // der Nutzer explizit den Planer leert. OSRM/MANUAL bleiben unangetastet. + // • Keine Änderungen an Datenmodell, Backup, Playback, Lizenz. + // v2.7.4 — Planlinie Auto Render: + // • Root Cause 1 behoben: savedRouteLine-Phantom-Guard schloss PLANLINE-Routen auf + // der Standardtour aus (isNeutralStandard). PLANLINE ist bewusste Nutzeraktion, + // kein Phantom — Ausnahme eingefügt. + // • Root Cause 2 behoben: mapLibreMap fehlte als Key im route-drawing-LaunchedEffect. + // Nach Map-Neuinitialisierung (Stylewechsel, Workspace-Rückkehr) wurde die Linie + // nicht neu gezeichnet, obwohl routePlanline befüllt war. + // • Auto-Persistenz: routePlanline ≥ 2 Stopps → automatisch als PLANLINE-TourRoute + // in DB gespeichert, ohne Button-Druck. Button „Planlinie zeigen“ ist nur noch + // Kamera-Fokus. + // • Zeichnungsfarbe: PLANLINE aus savedRouteLine erhält orangene Farbe (wie routePlanline), + // kein falsches Grün mehr. + // • Priorität v2.7.4: routeLine (OSRM) > routePlanline (wenn PLANLINE-Quelle) > + // savedRouteLine (OSRM/andere) > routePlanline (fallback) > keine Linie. + // • Keine Änderungen an Datenmodell, Backup, Playback, Lizenz. + // + // v2.7.5 — Standard-Tour intern (Konzeptkorrektur): + // • Root Cause: DEFAULT_TOUR_NAME="Standard" war bisher in der Audio-Bibliothek + // als vollwertige bearbeitbare Tour sichtbar, was Phantom-/Kontextprobleme + // erzeugen konnte. Standard-Tour ist eine System-Blaupause, kein Nutzerdatensatz. + // • visibleTourList (neu im ViewModel): filtert Standard-Tour aus der UI-Liste, + // sobald mindestens eine echte Tour existiert. tourList intern unverändert. + // • Audio-Bibliothek (HomeScreen): zeigt Standard-Tour nicht mehr im Cover-Grid. + // • Menü (WaypointListScreen): Umbenennen + Duplizieren für Standard-Tour deaktiviert. + // Löschen war bereits gesperrt (unverändert). + // • Auto-Selektion: Beim App-Start mit echten Touren wird automatisch die erste + // echte Tour gewählt statt "Standard". + // • Explorer isNeutralStandard, Backup, Datenmodell, Lizenz: unverändert. + // v2.7.7 — Spontane Tour Autocreate: + // • Root Cause: ExplorerScreenMapLibre.kt zeigte in der Topbar weiterhin + // "Standard" (selectedTour direkt), da die UI-Entkopplung aus v2.7.6 + // (displayTourLabel) dort nicht übernommen wurde. Fix: displayTourLabel + // analog zu ExplorerScreen.kt implementiert. + // • Automatische Tourerstellung beim ersten Wegpunkt im neutralen Explorer: + // upsertFromNeutralExplorer() im ViewModel prüft, ob tourName == + // DEFAULT_TOUR_NAME. Falls ja, erzeugt createSpontaneousTour() eine + // eindeutige "Spontane Tour" (mit Suffix falls Name existiert), ruft + // addTour() auf (inkl. selectedTour-Wechsel) und speichert den Wegpunkt + // in der neuen Tour. Keine DB-Migration, keine neue Tabelle. + // • Betroffen: neuer Wegpunkt per Tap (PlaceNew), POI als Wegpunkt, + // POI zu Storyboard, Explorer-POI-Karte. Bearbeiten bestehender + // Wegpunkte: normaler upsert-Pfad (keine Auto-Tour). + // • Standard-Tour bleibt intern; visibleTourList (v2.7.5) blendet + // sie weiterhin aus, sobald echte Touren existieren. + // • Keine Änderungen an Backup, Lizenz, Playback, PTT, Atmo, GPS-Track. + // v2.7.8 — Unbenannte Tour + Planlinie Auto-Render: + // • 'Spontane Tour' → 'Unbenannte Tour': UI-String explorer_spontane_tour + // und createSpontaneousTour()-Basisname geändert. Schlüssel bleibt für + // risikoarmes Deployment; Funktionsname intern unverändert. + // • Root Cause Planlinie: Beim ersten Rendern nach App-Neustart oder + // Workspace-Rückkehr war savedRouteLine befüllt, wurde aber nicht in + // routeLine übertragen. routeLine ist die primäre Zeichnungsquelle. + // Folge: LaunchedEffect-Zeichnung lief, zog aber savedRouteLine nur + // als sekundären Fallback (grüne Linie). Die sichtbarkeitsblockierende + // Hürde: manuelle Sitzung (Session-Route) fehlte bei Kaltstart. + // • Fix 1: Neues LaunchedEffect(savedRouteLine, selectedTour) überträgt + // savedRouteLine → routeLine, wenn routeLine leer und keine Session-Route + // vorhanden. Damit ist routeLine immer die aktive Zeichnungsquelle. + // • Fix 2: Auto-Persistenz (LaunchedEffect routePlanline) ruft nun + // viewModel.setCurrentSessionRoute() auf, statt nur saveTourRouteFor(). + // Das füllt currentSessionRoute für Workspace-Rückkehr ohne Button-Druck. + // • Fix 3: activeTourRoute als zusätzlicher Key im Zeichen-LaunchedEffect + // (belt-and-suspenders gegen strukturgleiche List-Vergleiche). + // • Keine Regressionen: Lizenz, Backup, Multiclip, PTT, Atmo, Bibliothek, + // MapLibre, POIs, Tourverlauf, GPS-Track, Spontane-Tour-Autocreate. + // v2.7.10 — Waypoint-Persistence-Fix (Unbenannte Tour bleibt nach Verlassen der Karte): + // • Root Cause: selectDefaultTour() wurde bei jedem Einstieg in den Explorer + // aus der Audio-Bibliothek/Home blind auf DEFAULT_TOUR_NAME („Standard“) + // gesetzt. Wenn zuvor eine spontane „Unbenannte Tour“ angelegt worden war, + // filterten Waypoints und Explorer-Karte nach „Standard“ → leere Ansicht. + // • Fix: selectDefaultTour() prüft jetzt vor dem Reset, ob echte (nicht-Standard) + // Touren in _tourList vorhanden sind. Ist das der Fall, wird sofort synchron + // zur ersten echten Tour gewechselt – statt auf DEFAULT zu fallen und auf den + // asynchronen combine-Kollektor (v2.7.5) zu warten, der den Reset dann ggf. + // rückabwickelt. Das vermeidet die Race-Condition, bei der die Explorer-UI + // in einem Recomposition-Zyklus mit leerem Waypoint-Filter gerendert wurde. + // • Keine Regressionen: Lizenz, Backup, Multiclip, PTT, Atmo, Bibliothek, + // MapLibre, POIs, Tourverlauf, GPS-Track, Explorer-State-Isolation (v2.7.9). + // Bestehende echte Touren werden beim Explorer-Öffnen korrekt vorausgewählt + // (war bereits so via async combine-Autoswitch – jetzt deterministisch/synchron). + // v2.7.14 — Explorer Entry Context Fix (Navigations-Bug): + // • Bug: Übersicht → Explorer öffnete nicht neutral, sondern die zuletzt + // bekannte echte Tour. Grund: selectDefaultTour() wählte bei vorhandenen + // echten Touren die erste echte Tour statt DEFAULT_TOUR_NAME. + // • Fix: Neue Funktion selectNeutralTourForNewExplorer() mit _neutralExplorerMode- + // Flag verhindert den automatischen Upgrade durch den combine-Kollektor (v2.7.5) + // und erzwingt bewusst einen leeren Explorer-Kontext aus der Übersicht. + // • Touransicht → Explorer: bleibt unverändert bei der aktiven Tour. + // • selectDefaultTour() für Legacy-Pfade erhalten. Keine Regressionen. + // v2.7.13 Planlinie, v2.7.12 overlayRenderNonce, v2.7.11 waypointRenderKey, + // v2.7.10 Persistenz, v2.7.9 State Isolation alle unberührt. + // v2.7.20 — Flexible Routenformung: + // • Route formen = Start/Ziel/Zwischenpunkte setzen, dann Planlinie oder Online-Route. + // • Neu: Zwischenpunkt direkt per Karten-Tap setzen (neuer AddViaPoint-TapMode). + // • Intuitiver Fallback: 1. Tap = Start, 2. Tap = Ziel, weitere = Zwischenpunkte. + // • Via-Sektion im Tourplaner klar als "Zwischenpunkte (Route formen)" bezeichnet. + // • Freie Linie klar als Fallback gekennzeichnet (UI-Text, kein Verhaltensänderung). + // • Keine Regressionen: v2.7.19 Start/Via/Ziel-Persistenz, v2.7.18 Doppellinie-Fix, + // Audio-Waypoints, PTT, Atmo, Backup, Lizenz, MapLibre-Render-Fixes unverändert. + // v2.7.21 — Waypoint Preservation Fix: + // • Root Cause: Race-Condition in duplicateTour()/deleteTour()/renameTour() liest + // _waypoints.value (könnte noch emptyList() sein vor DataStore-Erstladen) und ruft + // saveAll(leere_liste + newWps) auf — überschreibt alle bestehenden Wegpunkte. + // • Fix 1: saveAll() hat jetzt Preservation-Guard: leere Liste überschreibt niemals + // nicht-leere DataStore-Liste (atomarer Check innerhalb dataStore.edit). + // • Fix 2: saveAllForced() für explizite Lösch-/Restore-Operationen (deleteTour, + // renameTour, Backup-Restore) — bewusster Vollersatz. + // • Fix 3: duplicateTour/deleteTour/renameTour lesen jetzt mit repository.waypoints.first() + // direkt aus DataStore statt aus _waypoints.value. + // • Planlinie/Route-Speicherpfade (saveTourRouteFor) berhren KEY_WAYPOINTS nie. + // • AddViaPoint (v2.7.20) bestätigt sicher: kein Waypoint-Speicherpfad wird ausgelöst. + // • Keine Regressionen: v2.7.20 AddViaPoint, v2.7.19 Start/Via/Ziel-Persistenz, + // v2.7.18 Doppellinie-Fix, Audio-Waypoints, PTT, Atmo, Backup, Lizenz unverändert. + // v2.7.22 — Saved Route Render Fix: + // • Root Cause: savedRouteLine schloss MANUAL-Routen explizit aus (emptyList()), + // damit der v2.7.18 Doppellinien-Fix keine Konflikte erzeugt. Da aber + // manualRoutePolylines (Bearbeitungsvorschau) nur bei manualRouteMode=true + // gezeichnet wird, war das Ausschluss-Kriterium in savedRouteLineüberfüssig + // und verhinderte die Darstellung gespeicherter MANUAL-Routen. + // • Fix 1: MANUAL-Quellen in savedRouteLine eingeschlossen (wie OSRM); Phantom-Guard + // auf Standardtour bleibt. + // • Fix 2: LaunchedEffect(savedRouteLine) überspringt MANUAL (wie PLANLINE), damit + // MANUAL via hasSavedRoute-Pfad grün gezeichnet wird (nicht blau als OSRM). + // • Fix 3: hasRoute im RoutePlannerSheet-Aufruf berücksichtigt savedRouteLine.size, + // damit "Noch keine Route" nicht erscheint wenn eine gespeicherte Route vorhanden ist. + // • Keine Regressionen: v2.7.21 Waypoint-Preservation-Guard, v2.7.18 Doppellinie-Fix, + // PLANLINE, OSRM, AddViaPoint, Audio-Waypoints, PTT, Atmo, Backup, Lizenz unverändert. + // v2.7.26 — Persistent Map Preferences: + // • Globale Kartenpräferenzen dauerhaft gespeichert: Wegpunkt-Marker, Audio-Radius, + // GPS-Track/Draft-Linien, POIs-automatisch-nachladen (autoPoiLoad) jetzt persistent. + // • Bestehende Persistenz (baseStyle, showAudioLength, showAudioLines, POI-Kategorien, + // POI-Namen, Standort-Folgen, perspectiveTilt) unverändert beibehalten und erweitert. + // • Standort-Folgen entschärft: Jede manuelle Kartenverschiebung deaktiviert Standort + // folgen sofort (statt nur bei >40m Distanz). Kein Auto-Rücksprung beim nächsten + // GPS-Fix. Explizite Aktivierung nur per Toggle-Switch oder MyLocation-Button. + // • Beim Öffnen des Explorers mit Tourlinie/Wegpunkten: Kamera auf Tour zentriert, + // nicht auf Live-Standort (sofern Standort folgen aus). + // • Keine Regressionen: v2.7.25 Initial-Render-Fix, v2.7.24 UX Polish, v2.7.23 + // Tourverlauf übernehmen, v2.7.22 Saved Route Render, v2.7.21 Waypoint + // Preservation Guard alle unberührt. + // v2.7.29 — Overlay Rehydrate Fix: + // • Root Cause: Nach setStyle() loescht MapLibre alle Annotations (Marker, + // Polylines, Polygons). overlayRenderNonce++ loest Waypoint-Redraw aus, + // aber myLocationMarker/accuracyPolygon wurden auf null gesetzt und nur durch + // eingehende GPS-Updates (LocationCallback) neu gesetzt — fehlende Interaktion + // bis zum naechsten GPS-Fix fuehrte zu fehlendem/hellem Default-Marker. + // • Fix 1 (Live-Standort): Neuer LaunchedEffect(overlayRenderNonce, styleReady, + // mapLibreMap) zeichnet den Puck sofort aus lastLat/lastLng neu, ohne auf + // naechsten GPS-Fix zu warten. Genauigkeitskreis wird ebenfalls rehydriert. + // • Fix 2 (POI-Marker): overlayRenderNonce als Key im explorerPoiResults- + // LaunchedEffect sichert POI-Redraw nach Style-Load. + // • Alle v2.7.28 Fixes (Map Style Apply Fix, appliedBaseStyle/appliedPerspectiveTilt) + // bleiben vollstaendig erhalten. + // • Keine Regressionen: v2.7.27 Kartenpraeferenz-Persistenz, v2.7.26 + // Standort-Folgen-Fix, v2.7.25 Initial-Render-Fix, v2.7.24 UX Polish, + // v2.7.23 Tourverlauf uebernehmen, v2.7.21 Waypoint Preservation Guard, + // Routenplanung, POIs, Kartenstile, Audio-Waypoints, Multiclip, PTT, Atmo, + // Lizenzsystem, Backup/Restore alle unberuehrt. + // v2.7.32 — Zwei Regressionsfixes: + // • Touren ordnen: Erste und letzte SICHTBARE Tour ließen sich nicht + // mehr verschieben. Ursache: TourReorderDialog arbeitet auf + // visibleTourList (Standard-Tour ausgeblendet), WaypointViewModel.moveTour + // operierte aber auf _tourList inkl. DEFAULT_TOUR_NAME → Off-by-one, + // wenn die Standard-Tour an Index 0 lag. Fix: moveTour interpretiert + // Indizes im sichtbaren Raum und merged zurück, wobei die ausgeblendete + // Standard-Tour ihre relative Position behält. Hidden-Standard-Verhalten + // bleibt erhalten; echte Touren sind alle frei sortierbar. + // • Audioplayer: Der etablierte GPS2Audio-Player (ClipDetailSheet/ + // -Fullscreen) erschien beim manuellen Start eines Tracks/Clips nicht + // mehr. Fix: Neuer LaunchedEffect öffnet die Player-Ansicht automatisch + // für den aktiv abgespielten Wegpunkt, sobald Wiedergabe beginnt. + // • Keine Regressionen: Multi-Clip, Clip-Navigation, Countdown, maximierter + // Detailplayer, Hintergrundwiedergabe, PTT-Pause, Tour-Wiedergabe- + // Persistenz, Explorer/MapLibre, Routing, POIs, Backup, Lizenz unberührt. + // v2.7.33 — UI-Politur Begleitmusik-Dialog (rein gestalterisch): + // • Begleitmusik fühlt sich jetzt wie eine integrierte Musik-Karte der + // Tour an statt wie ein technisches Formular. + // • Neue Status-/Musik-Karte (MusicStatusCard) im Teal/Dark-Stil: + // Tour-Kontext, Aktiv-Status, Kurz-Zusammenfassung + Aktivieren-Schalter. + // • Kompakte Quellen-Chips (Lokale Playlist / Stream), primäre Aktion + // „Musik auswählen" als gefüllter Button, einladender Empty-State + // (MusicEmptyState) statt technischem Text. + // • Verhaltensoptionen mit Klartext-Titeln („Bei Ansagen pausieren", + // „Leiser im Hintergrund", „Weiterlaufen lassen", „Sanft aus-/einblenden") + // unter zusammengefasstem Abschnitt „Verhalten & Optionen". + // • KEINE Änderung an Datenmodell, Speicherung, Backup/Import, Lizenz, + // Playback-Service, PTT, Atmo, Waypoint-/Hintergrundwiedergabe, MapLibre/ + // Explorer oder Routing. validateAndSave + alle Optionen unverändert. + // • Keine Regression zu v2.7.32 (Player-Auto-Open, Tour-Reihenfolge). + // v2.7.34 — UI-Politur „Wegpunkt bearbeiten" (rein gestalterisch): + // • Ruhigeres Layout: kompakte Status-/Kopfkarte oben (Name, Tour, + // Kurzüberblick Position/Audio). + // • „Details" (Name + Tour) immer sichtbar; Position, Audio, Auslösung, + // Wiedergabe-Regeln, Zeitplan und „Kopieren & duplizieren" als + // einklappbare Abschnitte mit Kurz-Zusammenfassung. + // • Kopieren/Duplizieren nach ganz unten verschoben (nicht mehr zwischen + // Basisfeldern und Position); Koordinaten nur bei Bedarf aufgeklappt. + // • Abschnitte mit Validierungsfehlern öffnen sich automatisch. + // • KEINE Änderung an Datenmodell, Speicherung, Backup/Import, Lizenz, + // Playback, Multi-Clip, PTT, Atmo, MapLibre/Explorer oder Routing. + // Validation + Save (confirmButton) und alle Felder unverändert. + // v2.7.35 — UI-Politur Hauptseite/Audio-Bibliothek (rein gestalterisch): + // • Abschnittstitel „Meine Touren" mit Anzahl als Chip rechts. + // • Tour-Karten: feste Textblock-Höhe (gleichmäßige Karten), klare + // Metazeile statt abgeschnittenem Text („Route ge…"). + // • Leere Touren wirken bewusst („Noch leer") statt „0 Wegpunkte". + // • Chips immer sichtbar: Wegpunkt-Zahl bzw. „Noch leer" + „Route" / + // „Keine Route". + // • Live/PTT-Modul optisch zurückgenommen (Einrückung/kompakter) – + // KEINE Verhaltensänderung an LivePttCard. + // • KEINE Änderung an Datenmodell, Speicherung, Backup/Import, Lizenz, + // Playback, Multi-Clip, PTT/Atmo-Verhalten, MapLibre/Explorer, Routing, + // Tour-Reihenfolge oder Player-Auto-Open. + // v2.7.36 — Bugfix: Absturz/ANR nach Backup-Erstellung. + // • Ursache: exportBackupZip() führte Flow-Reads, ZIP-Aufbau und das + // Kopieren aller Mediendateien im viewModelScope auf dem Main-Thread + // aus → ANR ("App reagiert nicht"), obwohl die Datei geschrieben war. + // • Fix: schwere IO läuft jetzt auf Dispatchers.IO (wie der Import-Pfad); + // State-Updates für Erfolg/Fehler bleiben auf Main. Zusätzliche + // Absicherung: unerwartete Fehler werden als nicht-fatale Meldung + // gezeigt statt abzustürzen. + // • KEINE Änderung am Backup-Format/-Inhalt, an der Import-Logik oder an + // anderen Funktionen. + // v2.7.37 — Hörbuch-Gefühl: kurze Stille zwischen Clips/Wegpunkten. + // • Bei der manuellen Sequenz-Wiedergabe (Tour-Play) wird vor dem + // automatischen Start des nächsten Eintrags eine feste Pause von + // 1,7 s eingefügt – sowohl Clip→Clip als auch Wegpunkt→Wegpunkt. + // • Kein UI-Setting, keine Persistenz, kein neues Datenmodell. + // • Gilt NUR für die manuelle Sequenz; NICHT für GPS-getriggerte + // Wiedergabe, PTT, Atmo oder die Einzelclip-Vorschau. + // • Die Pause ist als abbrechbarer Coroutine-Job umgesetzt: Next/Skip + // überspringt sie sofort, Pause/Stop/Tour-Wechsel brechen sie ab – + // kein verspäteter Auto-Start nach dem Stoppen. + // • KEINE Änderung an Backup/Import, Lizenz, Hintergrund-Playback oder + // am Player-Auto-Open. + // + // v2.7.38 — Audio-Zuverlässigkeit (Regressionsfix, insb. Samsung-Tablets): + // • Die v2.7.37-Stille (Auto-Advance-Gap) bleibt erhalten, ist aber jetzt + // STRIKT auf den Auto-Advance nach einem natürlich beendeten Clip + // innerhalb DERSELBEN Tour beschränkt. Der verzögerte Gap-Job prüft vor + // dem Folge-Start, dass weder die Tour gewechselt wurde noch der Nutzer + // pausiert/gestoppt hat – sonst wird er verworfen. + // • Tour-Wechsel (selectTour) und Tour-Löschen (deleteTour) brechen einen + // anstehenden Gap-Job ab, damit kein verspäteter Start in der falschen + // bzw. gelöschten Tour feuert. Aktive Wiedergabe-Persistenz bleibt. + // • ManualAudioPlayer meldet Lade-/Prepare-/Start- und asynchrone + // MediaPlayer-Fehler jetzt über onError zurück. Schlägt der Start fehl + // (z. B. Samsung-SAF-/Codec-Problem), wird der "spielt"-Zustand sauber + // zurückgesetzt und eine Fehlermeldung angezeigt – statt still ohne Ton + // auf "spielt" zu verharren. + // • Erster manueller Start wird nie durch einen Gap-Job verzögert + // (unverändert) und kann nicht von einem alten Gap-Job überschrieben + // werden. + // • Keine Änderung an GPS-Wiedergabe, PTT, Atmo, Einzelclip-Vorschau, + // Hintergrund-Playback, Backup/Import, Lizenz oder Player-Auto-Open. + versionCode = 144 + versionName = "2.7.38" } val storeFilePath = resolveSigningValue("storeFile", "GPS2AUDIO_RELEASE_STORE_FILE") diff --git a/app/src/main/kotlin/de/waypointaudio/MainActivity.kt b/app/src/main/kotlin/de/waypointaudio/MainActivity.kt index 23f3c47..5356591 100644 --- a/app/src/main/kotlin/de/waypointaudio/MainActivity.kt +++ b/app/src/main/kotlin/de/waypointaudio/MainActivity.kt @@ -165,15 +165,18 @@ class MainActivity : ComponentActivity() { // direkt die bestehende Tour-/Waypoint-Ansicht. navController.navigate("list") }, - // v2.5.34 — Explorer-Kontext-Fix: - // Einstieg aus Audio-Bibliothek/Home muss immer neutral - // öffnen. selectDefaultTour() setzt selectedTour auf - // DEFAULT_TOUR_NAME, bevor der Explorer gerendert wird. - // Einstieg aus WaypointListScreen (Tour-Ansicht) behält - // die jeweils aktive Tour — dort wird selectDefaultTour() - // nicht aufgerufen. + // v2.7.14 — Explorer-Kontext-Fix (neutral): + // Einstieg aus Audio-Bibliothek/Home öffnet immer einen + // leeren, neutralen Kontext ("Unbenannte Tour"). + // selectNeutralTourForNewExplorer() setzt selectedTour auf + // DEFAULT_TOUR_NAME und aktiviert den Neutral-Explorer-Flag, + // der verhindert, dass der combine-Kollektor automatisch + // zur ersten echten Tour wechselt. + // Einstieg aus WaypointListScreen (Touransicht) behält + // die jeweils aktive Tour — dort wird keine tour-Reset-Funktion + // aufgerufen. onOpenExplorer = { - viewModel.selectDefaultTour() + viewModel.selectNeutralTourForNewExplorer() navController.navigate("explorer") }, // v2.5.19 — „Track Editor" wurde aus dem Hauptmenü diff --git a/app/src/main/kotlin/de/waypointaudio/data/MapStyleSettings.kt b/app/src/main/kotlin/de/waypointaudio/data/MapStyleSettings.kt index e298ab7..0afb257 100644 --- a/app/src/main/kotlin/de/waypointaudio/data/MapStyleSettings.kt +++ b/app/src/main/kotlin/de/waypointaudio/data/MapStyleSettings.kt @@ -113,7 +113,24 @@ data class PoiLayerSettings( ) /** - * Gespeicherte Karten-Stil-Einstellungen — v2.5.38. + * Persistierte Layer-Overlay-Einstellungen — v2.7.26. + * Alle Overlay-Toggles aus dem MapLayerPanel, die bisher nur im + * Compose-State lebten und bei App-Neustart zurückgesetzt wurden. + * + * @param showMarkers Wegpunkt-Marker anzeigen. + * @param showRadius Audio-Radius/Reichweite anzeigen. + * @param showTrack GPS-Track/Draft-Linien anzeigen. + * @param autoPoiLoadEnabled POIs automatisch nachladen (bei Kamerabewegung). + */ +data class MapLayerOverlaySettings( + val showMarkers: Boolean = true, + val showRadius: Boolean = true, + val showTrack: Boolean = true, + val autoPoiLoadEnabled: Boolean = true, +) + +/** + * Gespeicherte Karten-Stil-Einstellungen — v2.5.38 / v2.7.26. * * @param baseStyle gewählter Basis-Stil (wird persistent gespeichert) * @param showAudioLength ob die visuelle Audio-/Trigger-Länge als @@ -122,6 +139,7 @@ data class PoiLayerSettings( * @param showAudioLines Clip-Längen als projizierte Liniensegmente. * @param routingEndpoint optionaler OSRM-Routing-Endpoint. * @param poiLayers POI-Kategorien-Sichtbarkeit (persistent). + * @param overlayLayers Weitere Layer-Toggles (Marker, Radius, Track, Auto-POI-Load). * * Legacy-Felder (customSatelliteUrl, customTopoUrl, customTerrainDemUrl) werden * weiterhin gelesen, aber nicht mehr in der UI angeboten — für Rückwärts- @@ -137,6 +155,8 @@ data class MapStyleSettings( val showAudioLines: Boolean = true, val routingEndpoint: String = "", val poiLayers: PoiLayerSettings = PoiLayerSettings(), + // v2.7.26 — Persistente Layer-Overlay-Einstellungen + val overlayLayers: MapLayerOverlaySettings = MapLayerOverlaySettings(), ) private val Context.mapStyleDataStore by preferencesDataStore(name = "map_style_settings") @@ -159,6 +179,11 @@ class MapStyleStore(private val context: Context) { val KEY_POI_MOBILITY = booleanPreferencesKey("poi_mobility") // v2.5.42 val KEY_POI_SHOW_NAMES = booleanPreferencesKey("poi_show_names") + // v2.7.26 — Layer-Overlay-Persistenz + val KEY_SHOW_MARKERS = booleanPreferencesKey("show_markers") + val KEY_SHOW_RADIUS = booleanPreferencesKey("show_radius") + val KEY_SHOW_TRACK = booleanPreferencesKey("show_track") + val KEY_AUTO_POI_LOAD = booleanPreferencesKey("auto_poi_load") } val settings: Flow = context.mapStyleDataStore.data.map { prefs -> @@ -179,6 +204,13 @@ class MapStyleStore(private val context: Context) { showGastronomy = prefs[KEY_POI_GASTRONOMY] ?: true, showMobility = prefs[KEY_POI_MOBILITY] ?: true, showPoiNames = prefs[KEY_POI_SHOW_NAMES] ?: false, + ), + // v2.7.26 — Layer-Overlay-Persistenz + overlayLayers = MapLayerOverlaySettings( + showMarkers = prefs[KEY_SHOW_MARKERS] ?: true, + showRadius = prefs[KEY_SHOW_RADIUS] ?: true, + showTrack = prefs[KEY_SHOW_TRACK] ?: true, + autoPoiLoadEnabled = prefs[KEY_AUTO_POI_LOAD] ?: true, ) ) } @@ -212,6 +244,16 @@ class MapStyleStore(private val context: Context) { } } + // v2.7.26 — Layer-Overlay-Persistenz + suspend fun setOverlayLayers(overlay: MapLayerOverlaySettings) { + context.mapStyleDataStore.edit { + it[KEY_SHOW_MARKERS] = overlay.showMarkers + it[KEY_SHOW_RADIUS] = overlay.showRadius + it[KEY_SHOW_TRACK] = overlay.showTrack + it[KEY_AUTO_POI_LOAD] = overlay.autoPoiLoadEnabled + } + } + // v2.5.37 — Legacy-Stubs für Aufrufstellen aus v2.4.x die // noch customSatelliteUrl / customTopoUrl / customTerrainDemUrl schreiben. // Diese Werte werden weiterhin gelesen (Preferences bleiben), diff --git a/app/src/main/kotlin/de/waypointaudio/data/WaypointStore.kt b/app/src/main/kotlin/de/waypointaudio/data/WaypointStore.kt index 9277416..4e3ba29 100644 --- a/app/src/main/kotlin/de/waypointaudio/data/WaypointStore.kt +++ b/app/src/main/kotlin/de/waypointaudio/data/WaypointStore.kt @@ -175,8 +175,45 @@ class WaypointStore(private val context: Context) { } } - /** Speichert die gesamte Wegpunktliste. */ + /** + * Speichert die gesamte Wegpunktliste. + * + * v2.7.21 — Waypoint-Preservation-Guard: + * Wenn [waypoints] leer ist, aber im DataStore bereits Wegpunkte vorhanden + * sind, wird der Schreibvorgang NICHT ausgeführt. Das verhindert, dass eine + * versehentlich leere oder veraltete In-Memory-Liste (`_waypoints.value` + * aus einem Race-Condition-Fenster) bestehende Wegpunkte überschreibt. + * + * Explizites Leeren (Tour-Löschung, Migration) muss [saveAllForced] verwenden. + */ suspend fun saveAll(waypoints: List) { + context.dataStore.edit { prefs -> + // v2.7.21 — Preservation Guard: nie eine leere Liste über eine + // nicht-leere Liste schreiben. Schutz gegen Race-Condition-Verlust. + if (waypoints.isEmpty()) { + val existingJson = prefs[KEY_WAYPOINTS] ?: "[]" + val existingList = runCatching { + gson.fromJson>(existingJson, waypointListType) + }.getOrNull() + if (!existingList.isNullOrEmpty()) { + // Vorhandene Wegpunkte schützen — leere Liste wird NICHT geschrieben. + android.util.Log.w( + "WaypointStore", + "saveAll() mit leerer Liste blockiert: ${existingList.size} bestehende Wegpunkte bleiben erhalten." + ) + return@edit + } + } + prefs[KEY_WAYPOINTS] = gson.toJson(waypoints) + } + } + + /** + * v2.7.21 — Forciertes Speichern ohne Preservation-Guard. + * Nur für explizite Lösch- und Migrationsoperationen verwenden, + * bei denen eine leere Liste das gewünschte Ergebnis ist. + */ + suspend fun saveAllForced(waypoints: List) { context.dataStore.edit { prefs -> prefs[KEY_WAYPOINTS] = gson.toJson(waypoints) } @@ -228,6 +265,12 @@ class WaypointStore(private val context: Context) { * v2.4.6 — Speichert (oder ersetzt) die gespeicherte Route einer Tour. * Setzt [TourRoute.updatedAtMillis] auf die aktuelle Zeit, sofern das * übergebene Objekt nicht selbst einen neueren Zeitstempel mitbringt. + * + * v2.7.21 — Waypoint-Preservation-Invariante: + * Diese Funktion schreibt AUSSCHLIESSLICH in [KEY_TOUR_ROUTES]. + * [KEY_WAYPOINTS] (Audio-Wegpunkte) wird durch diesen Aufruf NIEMALS + * verändert. Tourrouten und Audio-Wegpunkte sind vollständig getrennte + * Speicherbereiche. */ suspend fun saveTourRoute(tourName: String, route: TourRoute) { context.dataStore.edit { prefs -> diff --git a/app/src/main/kotlin/de/waypointaudio/repository/WaypointRepository.kt b/app/src/main/kotlin/de/waypointaudio/repository/WaypointRepository.kt index 255124c..c48e77f 100644 --- a/app/src/main/kotlin/de/waypointaudio/repository/WaypointRepository.kt +++ b/app/src/main/kotlin/de/waypointaudio/repository/WaypointRepository.kt @@ -73,9 +73,16 @@ class WaypointRepository(context: Context) { /** Wegpunkt löschen. */ suspend fun delete(id: String) = store.delete(id) - /** Alle Wegpunkte ersetzen. */ + /** Alle Wegpunkte ersetzen (mit Preservation-Guard gegen leere Liste). */ suspend fun saveAll(waypoints: List) = store.saveAll(waypoints) + /** + * v2.7.21 — Alle Wegpunkte forciert ersetzen (kein Preservation-Guard). + * Nur für explizite Lösch-/Migrations-Operationen (z. B. Tour löschen mit + * Reassignment auf DEFAULT_TOUR_NAME, Backup-Restore-Vollersatz). + */ + suspend fun saveAllForced(waypoints: List) = store.saveAllForced(waypoints) + /** Tourliste persistieren. */ suspend fun saveTours(tours: List) = store.saveTours(tours) diff --git a/app/src/main/kotlin/de/waypointaudio/service/ManualAudioPlayer.kt b/app/src/main/kotlin/de/waypointaudio/service/ManualAudioPlayer.kt index 2f96146..fe7f653 100644 --- a/app/src/main/kotlin/de/waypointaudio/service/ManualAudioPlayer.kt +++ b/app/src/main/kotlin/de/waypointaudio/service/ManualAudioPlayer.kt @@ -82,10 +82,12 @@ class ManualAudioPlayer { fun play( context: Context, soundUri: String, + onError: () -> Unit = {}, onCompletion: () -> Unit = {} ) { if (soundUri.isBlank()) { Log.w(TAG, "Keine Audiodatei angegeben.") + onError() return } @@ -100,14 +102,14 @@ class ManualAudioPlayer { }.onFailure { e -> Log.e(TAG, "Fehler beim Fortsetzen von $soundUri", e) releasePlayer() - loadAndPlay(context, soundUri, onCompletion) + loadAndPlay(context, soundUri, onCompletion, onError) } return } // New or different track → fresh load releasePlayer() - loadAndPlay(context, soundUri, onCompletion) + loadAndPlay(context, soundUri, onCompletion, onError) } // ------------------------------------------------------------------------- @@ -168,12 +170,12 @@ class ManualAudioPlayer { ) { isSingleMode = true singleWaypointId = waypointId - loadAndPlay(context, soundUri) { + loadAndPlay(context, soundUri, onCompletion = { // Natural completion: clear single state, then notify caller isSingleMode = false singleWaypointId = null onCompletion() - } + }) } // ------------------------------------------------------------------------- @@ -183,7 +185,8 @@ class ManualAudioPlayer { private fun loadAndPlay( context: Context, soundUri: String, - onCompletion: () -> Unit + onCompletion: () -> Unit, + onError: () -> Unit = {} ) { runCatching { val uri = Uri.parse(soundUri) @@ -200,9 +203,14 @@ class ManualAudioPlayer { onCompletion() } setOnErrorListener { mp, what, extra -> + // v2.7.38 — Asynchroner MediaPlayer-Fehler (z. B. Samsung- + // spezifische Codec-/SAF-Probleme): Ressourcen freigeben und + // den Aufrufer informieren, damit der "spielt"-Zustand nicht + // ohne Ton hängen bleibt. Log.e(TAG, "MediaPlayer-Fehler: what=$what extra=$extra") mp.release() releasePlayer() + onError() true } } @@ -217,8 +225,14 @@ class ManualAudioPlayer { tour = pendingTour ) }.onFailure { e -> + // v2.7.38 — Synchroner Lade-/Prepare-/Start-Fehler. Auf manchen + // Geräten (insb. Samsung-Tablets) kann prepare()/start() mit + // content://-SAF-URIs fehlschlagen. Bisher blieb der UI-Zustand + // dann fälschlich auf "spielt" ohne Audio. Jetzt: sauber freigeben + // und den Aufrufer benachrichtigen. Log.e(TAG, "Fehler beim Abspielen von $soundUri", e) releasePlayer() + onError() } } diff --git a/app/src/main/kotlin/de/waypointaudio/ui/BegleitmusikDialog.kt b/app/src/main/kotlin/de/waypointaudio/ui/BegleitmusikDialog.kt index 4871cb7..043e8ca 100644 --- a/app/src/main/kotlin/de/waypointaudio/ui/BegleitmusikDialog.kt +++ b/app/src/main/kotlin/de/waypointaudio/ui/BegleitmusikDialog.kt @@ -152,35 +152,31 @@ fun BegleitmusikDialog( .verticalScroll(rememberScrollState()), verticalArrangement = Arrangement.spacedBy(12.dp) ) { - // Tour-Kontext - Text( - stringResource(R.string.music_for_tour, tourName), - style = MaterialTheme.typography.bodySmall, - color = MaterialTheme.colorScheme.onSurfaceVariant + // ─── Status-/Musik-Karte (v2.7.33) ─────────────────────────────── + // Integrierte Karte statt technischem Formular-Kopf: Tour-Kontext, + // Aktiv-Status, Kurz-Zusammenfassung und Aktivieren-Schalter in + // einer visuell zusammenhängenden Einheit. + val summaryText = when { + sourceType == MusicSourceType.LOCAL_PLAYLIST && localPlaylist.size == 1 -> + stringResource(R.string.music_summary_local_one) + sourceType == MusicSourceType.LOCAL_PLAYLIST && localPlaylist.isNotEmpty() -> + stringResource(R.string.music_summary_local, localPlaylist.size) + sourceType == MusicSourceType.STREAM_URL && streamPlaylist.size == 1 -> + stringResource(R.string.music_summary_stream_one) + sourceType == MusicSourceType.STREAM_URL && streamPlaylist.isNotEmpty() -> + stringResource(R.string.music_summary_stream, streamPlaylist.size) + else -> stringResource(R.string.music_summary_empty) + } + MusicStatusCard( + tourName = tourName, + enabled = enabled, + summary = summaryText, + onToggle = { enabled = it } ) - // ─── Aktivieren/Deaktivieren ───────────────────────────────────── - Row( - verticalAlignment = Alignment.CenterVertically, - modifier = Modifier.fillMaxWidth() - ) { - Text( - stringResource(R.string.music_enable), - style = MaterialTheme.typography.bodyLarge, - modifier = Modifier.weight(1f) - ) - Switch(checked = enabled, onCheckedChange = { enabled = it }) - } - - HorizontalDivider() - if (enabled) { - // ─── Quelltyp ───────────────────────────────────────────────── - Text( - stringResource(R.string.music_source_label), - style = MaterialTheme.typography.labelLarge, - color = MaterialTheme.colorScheme.primary - ) + // ─── Quelle ──────────────────────────────────────────────── + SectionLabel(stringResource(R.string.music_section_source)) Row( verticalAlignment = Alignment.CenterVertically, @@ -190,39 +186,33 @@ fun BegleitmusikDialog( selected = sourceType == MusicSourceType.LOCAL_PLAYLIST, onClick = { sourceType = MusicSourceType.LOCAL_PLAYLIST }, label = { Text(stringResource(R.string.music_source_local)) }, - leadingIcon = if (sourceType == MusicSourceType.LOCAL_PLAYLIST) { - { Icon(Icons.Filled.Check, null, Modifier.size(16.dp)) } - } else null + leadingIcon = { + Icon( + if (sourceType == MusicSourceType.LOCAL_PLAYLIST) + Icons.Filled.Check else Icons.Filled.LibraryMusic, + null, Modifier.size(16.dp) + ) + } ) FilterChip( selected = sourceType == MusicSourceType.STREAM_URL, onClick = { sourceType = MusicSourceType.STREAM_URL }, label = { Text(stringResource(R.string.music_source_stream)) }, - leadingIcon = if (sourceType == MusicSourceType.STREAM_URL) { - { Icon(Icons.Filled.Check, null, Modifier.size(16.dp)) } - } else null + leadingIcon = { + Icon( + if (sourceType == MusicSourceType.STREAM_URL) + Icons.Filled.Check else Icons.Filled.Radio, + null, Modifier.size(16.dp) + ) + } ) } // ─── Lokale Playlist ────────────────────────────────────────── if (sourceType == MusicSourceType.LOCAL_PLAYLIST) { - Text( - stringResource(R.string.music_playlist_label), - style = MaterialTheme.typography.labelMedium, - color = MaterialTheme.colorScheme.onSurfaceVariant - ) if (localPlaylist.isEmpty()) { - // Hinweis je nach Verfügbarkeit der Audio-Bibliothek anpassen, - // damit die User wissen, dass sie auch bereits hinzugefügte - // Dateien erneut auswählen können. - Text( - if (audioLibrary.isEmpty()) - stringResource(R.string.music_playlist_empty) - else - stringResource(R.string.music_playlist_empty_with_library), - style = MaterialTheme.typography.bodySmall, - color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.6f) - ) + // Einladender Empty-State statt technischem Hinweis. + MusicEmptyState() } else { localPlaylist.forEachIndexed { idx, item -> Row( @@ -265,7 +255,8 @@ fun BegleitmusikDialog( verticalArrangement = Arrangement.spacedBy(4.dp), modifier = Modifier.fillMaxWidth() ) { - OutlinedButton( + // Primäre Aktion „Musik auswählen" (gefüllter Button). + Button( onClick = { multiPickLauncher.launch( arrayOf("audio/*", "audio/mpeg", "audio/ogg", "audio/flac", "*/*") @@ -325,11 +316,7 @@ fun BegleitmusikDialog( ) if (streamPlaylist.isEmpty()) { - Text( - stringResource(R.string.music_stream_playlist_empty), - style = MaterialTheme.typography.bodySmall, - color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.6f) - ) + MusicEmptyState() } else { streamPlaylist.forEachIndexed { idx, entry -> val displayLabel = entry.name.ifBlank { entry.url } @@ -597,34 +584,31 @@ fun BegleitmusikDialog( HorizontalDivider() - // ─── Verhalten beim Wegpunkt ────────────────────────────────── - Text( - stringResource(R.string.music_behavior_label), - style = MaterialTheme.typography.labelLarge, - color = MaterialTheme.colorScheme.primary - ) + // ─── Verhalten & Optionen (v2.7.33: zusammengefasster Bereich) ─ + SectionLabel(stringResource(R.string.music_section_advanced)) + // Klartext-Titel, gleiche Funktionen wie zuvor. BehaviorOption( selected = behavior == WaypointMusicBehavior.PAUSE_RESUME, - title = stringResource(R.string.music_behavior_pause_resume), + title = stringResource(R.string.music_behavior_pause_resume_plain), description = stringResource(R.string.music_behavior_pause_resume_desc), onClick = { behavior = WaypointMusicBehavior.PAUSE_RESUME } ) BehaviorOption( selected = behavior == WaypointMusicBehavior.FADE_OUT_IN, - title = stringResource(R.string.music_behavior_fade), + title = stringResource(R.string.music_behavior_fade_plain), description = stringResource(R.string.music_behavior_fade_desc), onClick = { behavior = WaypointMusicBehavior.FADE_OUT_IN } ) BehaviorOption( selected = behavior == WaypointMusicBehavior.DUCK_UNDERLAY, - title = stringResource(R.string.music_behavior_duck), + title = stringResource(R.string.music_behavior_duck_plain), description = stringResource(R.string.music_behavior_duck_desc), onClick = { behavior = WaypointMusicBehavior.DUCK_UNDERLAY } ) BehaviorOption( selected = behavior == WaypointMusicBehavior.CONTINUE_UNDERLAY, - title = stringResource(R.string.music_behavior_continue), + title = stringResource(R.string.music_behavior_continue_plain), description = stringResource(R.string.music_behavior_continue_desc), onClick = { behavior = WaypointMusicBehavior.CONTINUE_UNDERLAY } ) @@ -691,11 +675,7 @@ fun BegleitmusikDialog( HorizontalDivider() // ─── Test-Steuerung ─────────────────────────────────────────── - Text( - stringResource(R.string.music_test_label), - style = MaterialTheme.typography.labelLarge, - color = MaterialTheme.colorScheme.primary - ) + SectionLabel(stringResource(R.string.music_test_label)) Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) { FilledIconButton( onClick = { viewModel.toggleMusicPlayback() }, @@ -891,3 +871,132 @@ private fun BehaviorOption( } } } + +/** + * v2.7.33 — Integrierte Status-/Musik-Karte (rein gestalterisch). + * Fasst Tour-Kontext, Aktiv-Status, Kurz-Zusammenfassung und den + * Aktivieren-Schalter in einer Karte im GPS2Audio-Teal/Dark-Stil zusammen. + */ +@Composable +private fun MusicStatusCard( + tourName: String, + enabled: Boolean, + summary: String, + onToggle: (Boolean) -> Unit +) { + Card( + modifier = Modifier.fillMaxWidth(), + shape = androidx.compose.foundation.shape.RoundedCornerShape(14.dp), + colors = CardDefaults.cardColors( + containerColor = if (enabled) + MaterialTheme.colorScheme.secondaryContainer + else + MaterialTheme.colorScheme.surfaceVariant + ), + elevation = CardDefaults.cardElevation(defaultElevation = 1.dp) + ) { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 14.dp, vertical = 12.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(12.dp) + ) { + Icon( + imageVector = if (enabled) Icons.Filled.LibraryMusic else Icons.Filled.MusicNote, + contentDescription = null, + modifier = Modifier.size(28.dp), + tint = if (enabled) + MaterialTheme.colorScheme.onSecondaryContainer + else + MaterialTheme.colorScheme.onSurfaceVariant + ) + Column(modifier = Modifier.weight(1f)) { + Text( + text = stringResource(R.string.music_card_heading), + style = MaterialTheme.typography.titleMedium, + fontWeight = FontWeight.SemiBold, + color = if (enabled) + MaterialTheme.colorScheme.onSecondaryContainer + else + MaterialTheme.colorScheme.onSurface, + maxLines = 1, + overflow = TextOverflow.Ellipsis + ) + Text( + text = stringResource(R.string.music_for_tour, tourName), + style = MaterialTheme.typography.bodySmall, + color = if (enabled) + MaterialTheme.colorScheme.onSecondaryContainer.copy(alpha = 0.8f) + else + MaterialTheme.colorScheme.onSurfaceVariant, + maxLines = 1, + overflow = TextOverflow.Ellipsis + ) + Spacer(Modifier.height(2.dp)) + Text( + text = if (enabled) summary else stringResource(R.string.music_status_off), + style = MaterialTheme.typography.labelMedium, + color = if (enabled) + MaterialTheme.colorScheme.onSecondaryContainer + else + MaterialTheme.colorScheme.onSurface.copy(alpha = 0.7f), + maxLines = 1, + overflow = TextOverflow.Ellipsis + ) + } + Switch(checked = enabled, onCheckedChange = onToggle) + } + } +} + +/** + * v2.7.33 — Einladender Empty-State, wenn noch keine Musik gewählt wurde. + * Ersetzt den technischen „Noch keine Audiodateien"-Hinweis. + */ +@Composable +private fun MusicEmptyState() { + Surface( + modifier = Modifier.fillMaxWidth(), + shape = androidx.compose.foundation.shape.RoundedCornerShape(12.dp), + color = MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.6f) + ) { + Row( + modifier = Modifier.padding(14.dp), + verticalAlignment = Alignment.Top, + horizontalArrangement = Arrangement.spacedBy(12.dp) + ) { + Icon( + imageVector = Icons.Filled.MusicNote, + contentDescription = null, + modifier = Modifier.size(24.dp), + tint = MaterialTheme.colorScheme.primary + ) + Column { + Text( + stringResource(R.string.music_empty_state_title), + style = MaterialTheme.typography.bodyMedium, + fontWeight = FontWeight.Medium, + color = MaterialTheme.colorScheme.onSurface + ) + Spacer(Modifier.height(2.dp)) + Text( + stringResource(R.string.music_empty_state_body), + style = MaterialTheme.typography.bodySmall, + color = MaterialTheme.colorScheme.onSurfaceVariant + ) + } + } + } +} + +/** v2.7.33 — Einheitliche Abschnittsüberschrift im Teal-Akzent. */ +@Composable +private fun SectionLabel(text: String) { + Text( + text = text, + style = MaterialTheme.typography.labelLarge, + fontWeight = FontWeight.SemiBold, + color = MaterialTheme.colorScheme.primary + ) +} diff --git a/app/src/main/kotlin/de/waypointaudio/ui/ExplorerScreen.kt b/app/src/main/kotlin/de/waypointaudio/ui/ExplorerScreen.kt index 6e1bf4f..107df7a 100644 --- a/app/src/main/kotlin/de/waypointaudio/ui/ExplorerScreen.kt +++ b/app/src/main/kotlin/de/waypointaudio/ui/ExplorerScreen.kt @@ -192,15 +192,19 @@ fun ExplorerScreen( val selectedProvider by providerStore.provider.collectAsState(initial = MapProvider.DEFAULT) val settingsStore = remember { ExplorerSettingsStore(context.applicationContext) } - val persistedSettings by settingsStore.settings.collectAsState( - initial = de.waypointaudio.data.ExplorerSettings() + // v2.7.27 — Fix: null initial damit followLocation Restore erst nach echtem DataStore-Emit. + val persistedSettingsOrNull by settingsStore.settings.collectAsState( + initial = null ) + val persistedSettings = persistedSettingsOrNull ?: de.waypointaudio.data.ExplorerSettings() // v2.3.0 — MapLibre/Overlays: persistente Karten-Stil-Einstellungen. val mapStyleStore = remember { MapStyleStore(context.applicationContext) } - val mapStyleSettings by mapStyleStore.settings.collectAsState( - initial = MapStyleSettings() + // v2.7.27 — Fix: null als Initial-Wert, damit Restore erst nach echtem DataStore-Emit feuert. + val mapStyleSettingsOrNull by mapStyleStore.settings.collectAsState( + initial = null ) + val mapStyleSettings = mapStyleSettingsOrNull ?: MapStyleSettings() val scope = rememberCoroutineScope() // Audio-Dauer-Cache je Wegpunkt (URI → Millisekunden). @@ -239,13 +243,13 @@ fun ExplorerScreen( ) } - // Persistente Nachführungs-Einstellung. Erstinitialisierung aus dem DataStore, - // danach: manuelle Map-Bewegung darf das Flag NICHT automatisch zurücksetzen. - var followLocation by remember { mutableStateOf(persistedSettings.followLocation) } + // v2.7.27 — followLocation startet mit true (default); echter Wert aus DataStore via null-safe Emit. + var followLocation by remember { mutableStateOf(true) } var followInitialized by remember { mutableStateOf(false) } - LaunchedEffect(persistedSettings.followLocation) { + LaunchedEffect(persistedSettingsOrNull) { + val loaded = persistedSettingsOrNull ?: return@LaunchedEffect if (!followInitialized) { - followLocation = persistedSettings.followLocation + followLocation = loaded.followLocation followInitialized = true } } @@ -265,14 +269,18 @@ fun ExplorerScreen( var layerState by remember { mutableStateOf(MapLayerState(followLocation = persistedSettings.followLocation)) } - // Initial-Sync der Stil-Einstellungen (einmalig, danach trägt onStateChange). + // v2.7.27 — styleHydrated: true sobald echter DataStore-Wert (nicht null) verarbeitet wurde. var styleHydrated by remember { mutableStateOf(false) } - LaunchedEffect(mapStyleSettings) { + LaunchedEffect(mapStyleSettingsOrNull) { + val loaded = mapStyleSettingsOrNull ?: return@LaunchedEffect if (!styleHydrated) { layerState = layerState.copy( - baseStyle = mapStyleSettings.baseStyle, - showAudioLength = mapStyleSettings.showAudioLength, - showAudioLines = mapStyleSettings.showAudioLines, + baseStyle = loaded.baseStyle, + showAudioLength = loaded.showAudioLength, + showAudioLines = loaded.showAudioLines, + showMarkers = loaded.overlayLayers.showMarkers, + showRadius = loaded.overlayLayers.showRadius, + showTrack = loaded.overlayLayers.showTrack, ) styleHydrated = true } @@ -304,6 +312,25 @@ fun ExplorerScreen( runCatching { mapStyleStore.setShowAudioLines(layerState.showAudioLines) } } } + // v2.7.26 — Layer-Overlay-Toggles persistent speichern (showMarkers, showRadius, showTrack). + LaunchedEffect(layerState.showMarkers, layerState.showRadius, layerState.showTrack) { + if (!styleHydrated) return@LaunchedEffect + val current = mapStyleSettings.overlayLayers + if (layerState.showMarkers != current.showMarkers || + layerState.showRadius != current.showRadius || + layerState.showTrack != current.showTrack) { + runCatching { + mapStyleStore.setOverlayLayers( + de.waypointaudio.data.MapLayerOverlaySettings( + showMarkers = layerState.showMarkers, + showRadius = layerState.showRadius, + showTrack = layerState.showTrack, + autoPoiLoadEnabled = true, // osmdroid-Fallback hat kein autoPoiLoad + ) + ) + } + } + } var showSearchDialog by remember { mutableStateOf(false) } var searchPin by remember { mutableStateOf(null) } @@ -357,6 +384,14 @@ fun ExplorerScreen( // Manager-Track für die neutrale Standardtour nicht als Phantom erscheint. val isNeutralStandard: Boolean = selectedTour == de.waypointaudio.data.Waypoint.DEFAULT_TOUR_NAME + + // v2.7.6 — UI-Entkopplung: DEFAULT_TOUR_NAME ("Standard") wird dem Nutzer + // nicht als interner Konstantenname angezeigt. Im neutralen Explorer-Kontext + // erscheint stattdessen "Spontane Tour". Echte Tournamen bleiben unverändert. + val displayTourLabel: String = + if (isNeutralStandard) stringResource(R.string.explorer_spontane_tour) + else selectedTour + val visibleTrack: List = when { isRecording -> currentTrack activeDraft != null -> activeDraft.points @@ -638,7 +673,13 @@ fun ExplorerScreen( prefillTourName = selectedTour, tourDefaults = tourDefaults, onConfirm = { newWaypoint -> - viewModel.upsert(newWaypoint) + // v2.7.7 — Spontane-Tour-Autocreate (auch im OSM-Explorer-Pfad): + // Neuer Wegpunkt im neutralen Kontext → automatisch echte Tour erzeugen. + if (editDialogWaypoint == null) { + viewModel.upsertFromNeutralExplorer(newWaypoint) + } else { + viewModel.upsert(newWaypoint) + } showEditDialog = false editDialogWaypoint = null editDialogPrefill = null @@ -923,7 +964,7 @@ fun ExplorerScreen( MapModeSegmentedHeader( current = currentMode, onChange = onModeChange, - subtitle = selectedTour + subtitle = displayTourLabel ) } else { Column { @@ -937,7 +978,7 @@ fun ExplorerScreen( Text(stringResource(R.string.explorer_title)) } Text( - text = selectedTour, + text = displayTourLabel, style = MaterialTheme.typography.labelSmall, color = MaterialTheme.colorScheme.onPrimary.copy(alpha = 0.8f) ) @@ -1616,11 +1657,28 @@ internal fun StoryboardPanel( } } Spacer(Modifier.height(8.dp)) - Text( - stringResource(R.string.explorer_storyboard_no_routing_hint), - style = MaterialTheme.typography.labelSmall, - color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.6f) - ) + // v2.6.0 — Erklärtext: Unterschied Tourverlaufspunkte vs. Audio-Wegpunkte + androidx.compose.material3.Surface( + shape = androidx.compose.foundation.shape.RoundedCornerShape(10.dp), + color = MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.55f), + modifier = Modifier.fillMaxWidth() + ) { + androidx.compose.foundation.layout.Column( + modifier = Modifier.padding(horizontal = 12.dp, vertical = 8.dp) + ) { + Text( + stringResource(R.string.explorer_storyboard_explainer), + style = MaterialTheme.typography.labelSmall, + color = MaterialTheme.colorScheme.onSurfaceVariant + ) + Spacer(Modifier.height(2.dp)) + Text( + stringResource(R.string.explorer_storyboard_no_routing_hint), + style = MaterialTheme.typography.labelSmall, + color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.6f) + ) + } + } } } diff --git a/app/src/main/kotlin/de/waypointaudio/ui/ExplorerScreenMapLibre.kt b/app/src/main/kotlin/de/waypointaudio/ui/ExplorerScreenMapLibre.kt index e94da93..429a64c 100644 --- a/app/src/main/kotlin/de/waypointaudio/ui/ExplorerScreenMapLibre.kt +++ b/app/src/main/kotlin/de/waypointaudio/ui/ExplorerScreenMapLibre.kt @@ -195,24 +195,47 @@ fun ExplorerScreenMapLibre( val singlePlayingActive by viewModel.singlePlayingActive.collectAsState() // v2.4.6 — Aktive Tourroute (persistente Route der ausgewählten Tour). val activeTourRoute by viewModel.activeTourRoute.collectAsState() + // v2.6.2 — Session-Route: zuletzt berechnete/geplante Route der aktuellen Tour. + // Überlebt Workspace-Wechsel (lebt im ViewModel), wird beim Tourwechsel geleert. + val currentSessionRoute by viewModel.currentSessionRoute.collectAsState() + // v2.7.2 — Session-Plan: Start/Via/Ziel des RoutePlanners, überlebt Workspace-Wechsel. + val currentSessionPlan by viewModel.currentSessionPlan.collectAsState() val waypoints = allWaypoints.filter { it.tourName.ifBlank { Waypoint.DEFAULT_TOUR_NAME } == selectedTour } + // v2.7.11 — Stabiler Render-Key für Waypoint-Marker: + // Berechnet aus ID, Latitude, Longitude und Anzahl der Wegpunkte. + // Dient als expliziter LaunchedEffect-Key, der garantiert feuert, + // wenn sich der Inhalt der Waypoint-Liste ändert — unabhängig davon, + // ob Kotlins List.equals() ein neues Objekt als "strukturell gleich" + // bewertet (z. B. durch Snapshot-Caching in collectAsState). + val waypointRenderKey = waypoints.joinToString(separator = "|") { + "${it.id}:${it.latitude}:${it.longitude}" + } + val primaryColor = MaterialTheme.colorScheme.primary val primaryArgb = primaryColor.toArgb() val tertiaryArgb = MaterialTheme.colorScheme.tertiary.toArgb() val settingsStore = remember { ExplorerSettingsStore(context.applicationContext) } - val persistedSettings by settingsStore.settings.collectAsState( - initial = de.waypointaudio.data.ExplorerSettings() + // v2.7.27 — Fix: null initial damit followLocation Restore erst nach echtem DataStore-Emit. + val persistedSettingsOrNull by settingsStore.settings.collectAsState( + initial = null ) + val persistedSettings = persistedSettingsOrNull ?: de.waypointaudio.data.ExplorerSettings() val mapStyleStore = remember { MapStyleStore(context.applicationContext) } - val mapStyleSettings by mapStyleStore.settings.collectAsState( - initial = MapStyleSettings() + // v2.7.27 — Fix: null als Initial-Wert, damit LaunchedEffect erst nach echtem + // DataStore-Emit (nicht sofort mit Default-Objekt) die Restore-Logik auslöst. + // Dadurch wird styleHydrated NICHT durch das Default-Objekt gesetzt, sondern + // erst wenn wirkliche DataStore-Daten ankommen. + val mapStyleSettingsOrNull by mapStyleStore.settings.collectAsState( + initial = null ) + // Nicht-nullable Alias für Stellen, die keinen Restore benötigen (nur Lesen). + val mapStyleSettings = mapStyleSettingsOrNull ?: MapStyleSettings() val scope = rememberCoroutineScope() // Audio-Dauer-Cache je Wegpunkt-URI. @@ -231,6 +254,8 @@ fun ExplorerScreenMapLibre( var showRoutingInfo by remember { mutableStateOf(false) } var showRoutePlanner by remember { mutableStateOf(false) } + // v2.7.0 — Tourverlauf-Editor-Sheet + var showTourverlaufEditor by remember { mutableStateOf(false) } var routeLine by remember { mutableStateOf>(emptyList()) } var routeStatus by remember { mutableStateOf(null) } var routeLoading by remember { mutableStateOf(false) } @@ -249,6 +274,13 @@ fun ExplorerScreenMapLibre( val isNeutralStandard: Boolean = selectedTour == de.waypointaudio.data.Waypoint.DEFAULT_TOUR_NAME + // v2.7.7 — UI-Entkopplung (MapLibre-Variante): DEFAULT_TOUR_NAME ("Standard") wird + // dem Nutzer nicht als interner Konstantenname angezeigt. Im neutralen Explorer-Kontext + // erscheint stattdessen "Spontane Tour". Echte Tournamen bleiben unverändert. + val displayTourLabel: String = + if (isNeutralStandard) stringResource(R.string.explorer_spontane_tour) + else selectedTour + // v2.4.6 — Gespeicherte Tourroute als sekundäre Quelle für Clip-Linien // und als Visualisierung, wenn keine aktuelle Route/Planlinie aktiv ist. // v2.5.3 — Manuelle Routen werden separat (als manualRoutePolylines) @@ -257,30 +289,133 @@ fun ExplorerScreenMapLibre( // v2.5.35 — Im neutralen Standard-Kontext (isNeutralStandard + keine Aufzeichnung // + kein Draft) wird savedRouteLine explizit leer gehalten, damit keine alte // persistierte TourRoute als Phantom-Linie erscheint. Daten werden NICHT gelöscht. + // v2.7.4 — PLANLINE-Routen sind explizit vom Nutzer für diese Tour gespeichert + // und dürfen auch auf der Standardtour angezeigt werden (kein Phantom-Schutz nötig). + // Phantom-Guard gilt weiterhin für OSRM/TRACK/IMPORTED-Quellen auf der neutralen + // Standardtour, damit keine zufälligen alten Routen erscheinen. val savedRouteLine: List = remember(activeTourRoute, isNeutralStandard, isRecording) { val r = activeTourRoute - if (r == null || r.source == de.waypointaudio.data.RouteSourceKind.MANUAL) emptyList() - // Phantom-Guard: Für die Standardtour keine gespeicherte Route zeigen, - // solange keine Aufzeichnung läuft (aktiver Draft wird unten behandelt). + if (r == null) emptyList() + // v2.7.4 — PLANLINE explizit ausgenommen: Planlinien sind nutzerseitig + // bewusst gesetzt und sollen auf der Standardtour immer sichtbar sein. + else if (r.source == de.waypointaudio.data.RouteSourceKind.PLANLINE) + r.polyline.map { LatLng(it.lat, it.lon) } + // v2.7.22 — MANUAL-Routen werden wie OSRM-Routen via savedRouteLine + // als grüne Tourlinie gerendert (hasSavedRoute-Pfad). Das doppelte + // Zeichnen wird durch den manualRouteMode-Guard in der manuellen + // Render-Schicht verhindert (manualRoutePolylines nur bei mode=true). + // Phantom-Guard gilt für MANUAL auf der Standardtour weiterhin. + else if (r.source == de.waypointaudio.data.RouteSourceKind.MANUAL) { + if (isNeutralStandard && !isRecording) emptyList() + else r.polyline.map { LatLng(it.lat, it.lon) } + } + // Phantom-Guard: Alle anderen Quellen (OSRM, TRACK, IMPORTED) auf der + // Standardtour ohne laufende Aufzeichnung unterdrücken. else if (isNeutralStandard && !isRecording) emptyList() else r.polyline.map { LatLng(it.lat, it.lon) } } - // Beim Wechsel der ausgewählten Tour: Plan und berechnete Route verwerfen, + // v2.6.2 — Beim Wechsel der ausgewählten Tour: Plan und berechnete Route verwerfen, // damit der Routenplaner nicht eine fremde Route der Vortour zeigt. - // - // v2.5.2 — Wenn die neue Tour eine gespeicherte TourRoute hat, wird deren - // Profil als Default in den frischen Plan übernommen. So bleibt das - // Fortbewegungsmittel beim Neuberechnen konsistent zur gespeicherten Route. - LaunchedEffect(selectedTour, activeTourRoute?.id) { - val storedProfile = RoutingProfile.fromKey(activeTourRoute?.profile) - routePlan = RoutePlan(profile = storedProfile) + // WICHTIG: activeTourRoute?.id wurde BEWUSST aus den Keys entfernt (v2.6.2-Fix). + // Früher löste das automatische Speichern der Session-Route einen activeTourRoute- + // Wechsel aus, der sofort wieder routeLine leerte. Jetzt wird der Reset nur noch + // beim Tourwechsel (selectedTour) ausgelöst. Das Profil-Update erfolgt separat. + LaunchedEffect(selectedTour) { + // v2.7.2 — Kein blindes Reset auf RoutePlan(): erst prüfen, ob ein + // Session-Plan für diese Tour gespeichert ist, und ihn dann wiederherstellen. + // Profil wird im nachfolgenden LaunchedEffect gesetzt, falls Plan leer. + val savedPlan = currentSessionPlan + if (savedPlan != null && savedPlan.first == selectedTour) { + routePlan = savedPlan.second + } else { + routePlan = RoutePlan() // Profil wird im nächsten LaunchedEffect gesetzt + } routeLine = emptyList() routeStatus = null lastComputedDistanceMeters = null lastComputedDurationSeconds = null lastComputedEndpoint = "" } + // v2.5.2/v2.6.2 — Profil der gespeicherten Tourroute in den Plan übernehmen, + // aber OHNE routeLine zu leeren. Nur wirksam wenn Plan noch kein Ziel hat + // (d. h. nicht vom Nutzer manuell befüllt wurde). + LaunchedEffect(activeTourRoute?.profile) { + val storedProfile = RoutingProfile.fromKey(activeTourRoute?.profile) + if (routePlan.start == null && routePlan.destination == null) { + routePlan = routePlan.copy(profile = storedProfile) + } + } + // v2.6.2 — Session-Route wiederherstellen, wenn der Nutzer aus einem anderen + // Workspace zurückkehrt. Bedingungen: + // 1. Es gibt eine gespeicherte Session-Route für die aktuelle Tour. + // 2. routeLine ist leer (kein parallel aktiver Berechnungslauf). + // 3. Die Session-Route enthält Geometrie (mindestens 2 Punkte). + // Falls alle Bedingungen erfüllt: routeLine aus der Session-Route wiederherstellen. + LaunchedEffect(currentSessionRoute, selectedTour) { + val (sessionTour, sessionRoute) = currentSessionRoute ?: return@LaunchedEffect + if (sessionTour != selectedTour) return@LaunchedEffect + if (routeLine.size >= 2) return@LaunchedEffect + if (sessionRoute.polyline.size < 2) return@LaunchedEffect + // v2.7.9 — PLANLINE-Session-Routen überspringen: Diese werden vom Zeichnungseffekt + // direkt über savedRouteLine/routePlanline in orange gezeichnet. Das Laden in + // routeLine würde sie blau als berechnete OSRM-Route darstellen. + if (sessionRoute.source == de.waypointaudio.data.RouteSourceKind.PLANLINE) return@LaunchedEffect + routeLine = sessionRoute.polyline.map { LatLng(it.lat, it.lon) } + // Metadaten ebenfalls wiederherstellen, damit "Tourverlauf speichern" wieder + // korrekte Werte übergibt. + lastComputedDistanceMeters = sessionRoute.distanceMeters + lastComputedDurationSeconds = sessionRoute.durationSeconds + lastComputedEndpoint = sessionRoute.endpoint + } + // v2.7.2 — Session-Plan wiederherstellen, wenn der Nutzer aus einem anderen + // Workspace zurückkehrt und kein Plan gesetzt ist. + // Bedingungen: Session-Plan vorhanden, passend zur Tour, routePlan noch leer. + LaunchedEffect(currentSessionPlan, selectedTour) { + val (planTour, savedPlan) = currentSessionPlan ?: return@LaunchedEffect + if (planTour != selectedTour) return@LaunchedEffect + // Nur wiederherstellen, wenn der lokale Plan noch leer ist (kein manuelles + // Update laufend) — verhindert Überschreiben bei laufendem Nutzer-Edit. + if (routePlan.start == null && routePlan.destination == null) { + routePlan = savedPlan + } + } + // v2.7.2 — Plan aus persistierter TourRoute (PLANLINE/OSRM) wiederherstellen, + // wenn weder Session-Plan noch lokaler Plan vorliegen. Das passiert nur beim + // ersten Öffnen nach App-Start (Cold Start), wenn die TourRoute Start/Ziel kennt. + // MANUAL-Routen werden nicht als Plan interpretiert. + LaunchedEffect(activeTourRoute, selectedTour) { + val r = activeTourRoute ?: return@LaunchedEffect + if (r.source == de.waypointaudio.data.RouteSourceKind.MANUAL) return@LaunchedEffect + val rStart = r.start ?: return@LaunchedEffect + val rDest = r.destination ?: return@LaunchedEffect + // Nur wenn kein Plan gesetzt ist (weder Session noch lokal). + if (currentSessionPlan != null) return@LaunchedEffect + if (routePlan.start != null || routePlan.destination != null) return@LaunchedEffect + val restoredPlan = RoutePlan( + start = RouteStop( + latitude = rStart.latitude, longitude = rStart.longitude, + label = rStart.label.ifBlank { "Start" }, + source = RouteStopSource.SEARCH + ), + destination = RouteStop( + latitude = rDest.latitude, longitude = rDest.longitude, + label = rDest.label.ifBlank { "Ziel" }, + source = RouteStopSource.SEARCH + ), + via = r.via.map { vs -> + RouteStop( + latitude = vs.latitude, longitude = vs.longitude, + label = vs.label.ifBlank { "Via" }, + source = RouteStopSource.SEARCH + ) + }, + profile = RoutingProfile.fromKey(r.profile) + ) + routePlan = restoredPlan + // Im ViewModel sichern, damit spätere Workspace-Rückkehr ihn kennt. + viewModel.setCurrentSessionPlan(selectedTour, restoredPlan) + } // Planlinie wird automatisch aus dem Plan abgeleitet — Luftlinie zwischen // Start/Via/Ziel. Sie ersetzt die Route nur, wenn keine echte Route da ist // (kein konfigurierter Endpunkt oder Fehler). @@ -288,12 +423,152 @@ fun ExplorerScreenMapLibre( routePlan.orderedStops().map { LatLng(it.latitude, it.longitude) } .takeIf { it.size >= 2 } ?: emptyList() } + + // v2.7.13 — Stabiler Render-Key für den Route/Planlinien-Overlay-Effekt. + // Berechnet aus activeTourRoute-Attributen (ID, source, Punktanzahl), sowie + // savedRouteLine.size und routePlanline.size. Garantiert, dass der + // Route-Overlay-LaunchedEffect feuert wenn sich Routenänderungen ergeben, + // auch wenn List.equals()-Snapshot-Caching eine Re-Composition verzögert. + // Insbesondere feuert er nach DB-Load von activeTourRoute (PLANLINE), damit + // die orange Planlinie beim initialen Öffnen des Explorers sofort sichtbar ist. + val routeRenderKey: String = run { + val r = activeTourRoute + val routeKey = if (r != null) + "${r.id}|${r.source}|${r.polyline.size}" + else + "none" + "$routeKey|sl=${savedRouteLine.size}|pl=${routePlanline.size}|rl=${routeLine.size}" + } + val routingPoiCtx = LocalContext.current + // v2.7.4 — Auto-Persistenz: Sobald routePlan ≥ 2 Stopps hat (Start+Ziel oder + // Start+Via als Minimum), wird die Planlinie automatisch als PLANLINE-TourRoute + // in die DB gespeichert. Das macht den Button „Planlinie zeigen“ zur blossen + // Kamera-Aktion — die Sichtbarkeit hängt nicht mehr davon ab. + // Bedingung: Kein aktuell berechnetes routeLine (OSRM hat Vorrang). + // Bedingung: Kein OSRM/MANUAL activeTourRoute (würde Nutzerroute überschreiben). + // v2.7.21 — Waypoint-Preservation-Invariante für alle Planlinie/Route-Persistenz-Effekte: + // saveTourRouteFor() und setCurrentSessionRoute() schreiben AUSSCHLIESSLICH in + // KEY_TOUR_ROUTES (separater DataStore-Key). KEY_WAYPOINTS (Audio-Wegpunkte) wird + // durch diese Effekte NIEMALS verändert. Die Planlinie-Auto-Persistenz ist sicher. + LaunchedEffect(routePlanline, selectedTour) { + if (routePlanline.size < 2) return@LaunchedEffect + if (routeLine.size >= 2) return@LaunchedEffect // OSRM hat Vorrang + val current = activeTourRoute + // Nicht auto-speichern, wenn eine OSRM- oder MANUAL-Route die Oberhand hat + if (current != null && + current.source != de.waypointaudio.data.RouteSourceKind.PLANLINE) return@LaunchedEffect + // Planline aufbauen und persistieren + val label = routingPoiCtx.getString(R.string.tour_route_source_planline) + val planlineRoute = buildTourRouteFromState( + plan = routePlan, + routeLine = emptyList(), + routePlanline = routePlanline, + distanceMeters = null, + durationSeconds = null, + endpoint = label, + planlineSourceLabel = label + ) ?: return@LaunchedEffect + // v2.7.8 — Session-Route ebenfalls setzen, damit Workspace-Rückkehr die + // Planlinie wiederherstellt (currentSessionRoute überlebt Navigation im Prozess). + viewModel.setCurrentSessionRoute(selectedTour, planlineRoute) + // v2.7.19 — FIX: Planlinie inkl. Start/Via/Ziel auch in die DB schreiben, + // damit sie nach einem Prozess-Kill (App-Neustart) aus activeTourRoute + // vollständig wiederhergestellt werden kann. Ohne diesen DB-Schreibvorgang + // überlebte der Plan nur in-memory (currentSessionPlan/currentSessionRoute) + // und war nach einem Prozess-Kill verloren. buildTourRouteFromState übergibt + // plan.start/destination/via korrekt in TourRoute.start/.destination/.via. + // v2.7.21 — Diese Funktion berührt KEINE Wegpunkte (KEY_WAYPOINTS). + viewModel.saveTourRouteFor(selectedTour, planlineRoute) + } + + // v2.7.8 — Auto-Render: Wenn eine gespeicherte Route/Planlinie vorhanden ist + // (activeTourRoute mit Geometrie), aber routeLine noch leer ist (kein OSRM-Lauf + // in dieser Session), wird routeLine automatisch aus savedRouteLine initialisiert. + // Dies macht die Linie sofort beim Öffnen des Explorers sichtbar, ohne Button-Druck. + // Bedingung: routeLine leer UND savedRouteLine befüllt UND kein Session-Restore + // bereits ausstehend (currentSessionRoute wird separat verarbeitet). + // Der Effekt läuft bei jedem activeTourRoute-Wechsel neu, um Tourverlaufsdaten + // korrekt zu laden wenn der Nutzer zwischen Touren wechselt. + // v2.7.8 — Auto-Render: Wenn eine gespeicherte Route vorhanden ist, aber routeLine + // noch leer ist, wird routeLine aus savedRouteLine initialisiert (nur für OSRM/TRACK- + // Quellen). PLANLINE-Quellen werden direkt vom Zeichnungseffekt über hasSavedRoute + // gezeichnet (mit korrekter oranger Farbe), ohne routeLine zu befüllen. + // v2.7.9 — PLANLINE explizit ausgenommen: savedRouteLine für PLANLINE-Quellen + // NICHT in routeLine laden, damit das Zeichnen über den hasSavedRoute-Pfad läuft + // (orange Farbe) und nicht als berechnete OSRM-Route (blau) erscheint. + // Der hasSavedRoute-Pfad im Zeichnungseffekt (zeile ~964) ist die einzige Darstellung + // für PLANLINE-Routen nach App-Start — kein routeLine nötig. + LaunchedEffect(savedRouteLine, selectedTour) { + if (savedRouteLine.size < 2) return@LaunchedEffect + // Nur wenn noch keine Route in dieser Session berechnet/geladen wurde. + if (routeLine.size >= 2) return@LaunchedEffect + // v2.7.9 — PLANLINE-Quellen überspringen: Zeichnungseffekt liest savedRouteLine direkt. + // Das garantiert die korrekte orange Darstellung ohne Umweg über routeLine. + if (activeTourRoute?.source == de.waypointaudio.data.RouteSourceKind.PLANLINE) return@LaunchedEffect + // v2.7.22 — MANUAL-Quellen überspringen: wie PLANLINE wird savedRouteLine direkt + // im hasSavedRoute-Pfad des Render-Effekts grün gezeichnet. Laden in routeLine + // würde MANUAL als blaue OSRM-Route darstellen (falsche Farbe/Semantik). + if (activeTourRoute?.source == de.waypointaudio.data.RouteSourceKind.MANUAL) return@LaunchedEffect + // Session-Route hat Vorrang — wird in separatem LaunchedEffect(currentSessionRoute, selectedTour) geladen. + // Wenn Session-Route da ist, nicht überschreiben. + val sessionRouteAvailable = viewModel.currentSessionRoute.value + ?.let { it.first == selectedTour && it.second.polyline.size >= 2 } == true + if (sessionRouteAvailable) return@LaunchedEffect + routeLine = savedRouteLine + } + // MapLibre-spezifische State-Halter var mapView by remember { mutableStateOf(null) } var mapLibreMap by remember { mutableStateOf(null) } var styleReady by remember { mutableStateOf(false) } + // v2.7.12 — Nonce, der nach jedem erfolgreichen Style-Load inkrementiert wird. + // Stellt sicher, dass der Overlay-LaunchedEffect nach Map/Style-Ready ohne + // Benutzerinteraktion feuert, selbst wenn alle anderen Keys stabil bleiben. + var overlayRenderNonce by remember { mutableStateOf(0) } + // v2.7.28 — appliedBaseStyle / appliedPerspectiveTilt: Welcher Stil + Tilt tatsächlich + // zuletzt per ml.setStyle() auf die Karte angewendet wurde. null = noch nichts. + // Dient als Single Source of Truth, um Doppel-Applies zu erkennen: + // Wenn layerState.baseStyle != appliedBaseStyle ODER perspectiveTilt geändert, + // muss setStyle() aufgerufen werden. + var appliedBaseStyle by remember { mutableStateOf(null) } + var appliedPerspectiveTilt by remember { mutableStateOf(null) } + + // v2.7.25 — Initial-Render-Fix: Wenn savedRouteLine nach dem ersten Style-Load + // aus der DB ankommt (activeTourRoute wird asynchron geladen), feuert der + // Overlay-LaunchedEffect möglicherweise nicht mehr, weil sein savedRouteLine-Key + // sich zwar ändert, aber durch Compose-Snapshot-Caching oder einen bereits + // abgelaufenen styleReady/overlayRenderNonce-Zyklus nicht mehr detektiert wird. + // Diese LaunchedEffect-Guard feuert dediziert, wenn savedRouteLine >= 2 Punkte + // hat UND der Style bereit ist — und erhöht den Nonce, damit der Zeichnungseffekt + // garantiert neu startet. Minimale Wirkung: nur wenn Karte und Stil bereit sind + // und eine gespeicherte Route vorliegt. + LaunchedEffect(savedRouteLine.size, styleReady, mapLibreMap) { + if (!styleReady) return@LaunchedEffect + if (mapLibreMap == null) return@LaunchedEffect + if (savedRouteLine.size < 2) return@LaunchedEffect + overlayRenderNonce++ + } + + // v2.7.30 — Zentraler Overlay-Rebuild-Mechanismus: Verzögerter Retry-Nonce. + // Root Cause: Nach setStyle() und overlayRenderNonce++ haben LaunchedEffects + // nur delay(150ms) Zeit. Falls MapLibre-AnnotationManager noch nicht bereit ist, + // scheitern addMarker/addPolyline still. Dieses LaunchedEffect wartet 500ms nach + // jedem Style-Ready und löst einen zweiten Render-Durchlauf aus. So werden + // Waypoints, Planlinie und Live-Standort garantiert gezeichnet, auch wenn der + // erste Versuch zum falschen Zeitpunkt kam. + // Duplikat-Schutz: drawExplorerOverlaysMapLibre leert vor dem Neuzeichnen alle + // alten Annotations — kein Double-Draw. + LaunchedEffect(styleReady, mapLibreMap) { + if (!styleReady) return@LaunchedEffect + if (mapLibreMap == null) return@LaunchedEffect + // Warte 500ms nach Style-Load, dann zweiten Rebuild ausloesen. + // Dieser Effekt feuert bei JEDEM Style-Ready-Wechsel (initial + Stilwechsel). + kotlinx.coroutines.delay(500) + if (!styleReady) return@LaunchedEffect // Style wurde zwischenzeitlich gewechselt + overlayRenderNonce++ + } // Annotation-Caches: wir entfernen/erzeugen pro Update neu, halten aber die // Referenzen zu den eigenen Annotations, um sie gezielt löschen zu können. @@ -328,7 +603,8 @@ fun ExplorerScreenMapLibre( val snackbarHostState = remember { SnackbarHostState() } // v2.5.45 — Auto-POI-Load State - var autoPoiLoadEnabled by remember { mutableStateOf(true) } // standardmäßig aktiviert + // v2.7.26 — Initialisierung aus persistiertem Wert; überschrieben nach styleHydrated. + var autoPoiLoadEnabled by remember { mutableStateOf(true) } // überschrieben beim ersten DataStore-Lesen var poiAutoLoadJob by remember { mutableStateOf(null) } var lastAutoLoadLat by remember { mutableStateOf(null) } var lastAutoLoadLon by remember { mutableStateOf(null) } @@ -346,11 +622,13 @@ fun ExplorerScreenMapLibre( ) } - var followLocation by remember { mutableStateOf(persistedSettings.followLocation) } + // v2.7.27 — followLocation startet mit default true; echter Wert kommt aus DataStore. + var followLocation by remember { mutableStateOf(true) } var followInitialized by remember { mutableStateOf(false) } - LaunchedEffect(persistedSettings.followLocation) { + LaunchedEffect(persistedSettingsOrNull) { + val loaded = persistedSettingsOrNull ?: return@LaunchedEffect if (!followInitialized) { - followLocation = persistedSettings.followLocation + followLocation = loaded.followLocation followInitialized = true } } @@ -373,11 +651,72 @@ fun ExplorerScreenMapLibre( var manualRoutePoints by remember { mutableStateOf>(emptyList()) } var selectedRoutePointIndex by remember { mutableStateOf(null) } var showRoutePointDialog by remember { mutableStateOf(false) } + // v2.7.1 — Guard gegen Race-Condition beim Auto-Save: + // Auto-Save darf die gespeicherte Route erst löschen/überschreiben, + // nachdem die initiale Ladephase aus der DB abgeschlossen ist. + // Ohne diesen Guard kann ein leeres `manualRoutePoints` (Initialwert) + // die persistierte MANUAL-Route auf der DB löschen, bevor der + // LaunchedEffect sie geladen hat. + var manualRouteInitialized by remember { mutableStateOf(false) } - // Beim Tour-Wechsel: bestehende manuelle Route laden. + // Beim Tour-Wechsel: Modus zurücksetzen (selectedTour als einziger Key, + // damit dieser Reset nur beim echten Tour-Wechsel passiert, nicht bei + // jedem Auto-Save-induzierten activeTourRoute-Update). + // v2.7.9 — Erweitert: Alle Waypoint-Edit-States werden bei Tour-Wechsel bereinigt, + // damit alte Wegpunkte der Vorgänger-Tour nicht bearbeitbar bleiben. Das betrifft: + // - tapMode (inkl. MoveWaypoint, PlaceNew, DrawRoutePoint, MoveRoutePoint) + // - actionMenuWaypoint, editDialogWaypoint, showEditDialog, deleteConfirm + // So kann keine alte Waypoint-Referenz aus einer anderen Tour in den Dialog gelangen. + LaunchedEffect(selectedTour) { + if (manualRouteMode) manualRouteMode = false + // v2.7.9 — Alle tapMode-Varianten zurücksetzen, nicht nur Route-Modi. + // Verhindert: MoveWaypoint(oldId) bleibt aktiv nach Tour-Wechsel → würde + // beim nächsten Karten-Tap einen Wegpunkt aus der alten Tour verschieben. + if (tapMode !is TapModeMl.None) { + tapMode = TapModeMl.None + } + // v2.7.9 — Waypoint-Dialog-States bei Tour-Wechsel leeren. + actionMenuWaypoint = null + editDialogWaypoint = null + showEditDialog = false + deleteConfirm = null + editDialogPrefill = null + selectedRoutePointIndex = null + showRoutePointDialog = false + } + + // v2.7.9 — MapLibre-Marker explizit leeren bei Tour-Wechsel: + // Falls ein Recomposition-Zyklus zwischen selectedTour-Änderung und + // waypoints-Update liegt, könnten kurzzeitig alte Marker sichtbar sein. + // Dieser Effekt räumt sofort auf, ohne auf waypoints-Änderung zu warten. + // Die Neuzeichnung erfolgt danach durch LaunchedEffect(waypoints, ...) mit der + // korrekt gefilterten Waypoint-Liste der neuen Tour. + LaunchedEffect(selectedTour) { + val ml = mapLibreMap ?: return@LaunchedEffect + if (!styleReady) return@LaunchedEffect + // Wegpunkt-Marker und Polygone der alten Tour entfernen. + for (m in waypointMarkers) runCatching { ml.removeMarker(m) } + waypointMarkers.clear() + waypointMarkerIdToWaypoint.clear() + for (p in waypointRadiusPolygons) runCatching { ml.removePolygon(p) } + waypointRadiusPolygons.clear() + // Planline- und Routen-Polylines der alten Tour entfernen. + for (pl in routePolylines) runCatching { ml.removePolyline(pl) } + routePolylines.clear() + for (pl in planlinePolylines) runCatching { ml.removePolyline(pl) } + planlinePolylines.clear() + for (m in routeStopMarkers) runCatching { ml.removeMarker(m) } + routeStopMarkers.clear() + } + + // Beim Tour-Wechsel oder Route-Wechsel: gespeicherte manuelle Route laden. // v2.5.35 — Phantom-Guard: Für die Standardtour keine manuelle Route laden, // die aus einem früheren Zeichnen-Vorgang ohne explizite Tour-Auswahl stammt. - LaunchedEffect(selectedTour, activeTourRoute?.id, activeTourRoute?.source) { + // v2.7.1 — activeTourRoute?.id entfernt aus Keys: Auto-Save-induzierte + // activeTourRoute-Updates (gleiches id, gleiche source) lösen keinen Reload aus. + // Nur echter source-Wechsel (MANUAL ↔ OSRM) oder Tour-Wechsel (selectedTour) + // triggern ein Reload. Dadurch bleibt die Linie stabil während der Editor offen ist. + LaunchedEffect(selectedTour, activeTourRoute?.source) { val r = activeTourRoute manualRoutePoints = if ( r?.source == de.waypointaudio.data.RouteSourceKind.MANUAL @@ -385,19 +724,19 @@ fun ExplorerScreenMapLibre( ) { r.polyline.map { LatLng(it.lat, it.lon) } } else emptyList() - // Modus aufheben, damit man nicht versehentlich weiterzeichnet - if (manualRouteMode) manualRouteMode = false - if (tapMode is TapModeMl.DrawRoutePoint || tapMode is TapModeMl.MoveRoutePoint) { - tapMode = TapModeMl.None - } - selectedRoutePointIndex = null - showRoutePointDialog = false + // v2.7.1 — Initialized-Guard setzen, nachdem die DB-Route geladen wurde. + manualRouteInitialized = true } // Auto-Save: jede Änderung der manuellen Route in TourRoute persistieren. // Beim Leeren wird die Tourroute entfernt (nur, wenn sie zuvor MANUAL war — // berechnete Routen bleiben unangetastet). - LaunchedEffect(manualRoutePoints, selectedTour) { + // v2.7.1 — Guard: Auto-Save nur ausführen, wenn die initiale Ladephase + // abgeschlossen ist (manualRouteInitialized = true). Verhindert, dass ein + // leeres manualRoutePoints die persistierte Route auf der DB löscht, + // bevor der Load-Effekt die Punkte aus der DB gesetzt hat. + LaunchedEffect(manualRoutePoints, selectedTour, manualRouteInitialized) { + if (!manualRouteInitialized) return@LaunchedEffect val currentSaved = activeTourRoute val wasManual = currentSaved?.source == de.waypointaudio.data.RouteSourceKind.MANUAL if (manualRoutePoints.isEmpty()) { @@ -426,17 +765,27 @@ fun ExplorerScreenMapLibre( var layerState by remember { mutableStateOf(MapLayerState(followLocation = persistedSettings.followLocation)) } + // v2.7.27 — styleHydrated: true sobald echter DataStore-Wert (nicht null) verarbeitet wurde. + // Verhindert, dass Persist-Effekte (LaunchedEffect auf layerState.*) vor dem initialen + // Restore schreiben und so die gespeicherten Werte mit Defaults überschreiben. var styleHydrated by remember { mutableStateOf(false) } - LaunchedEffect(mapStyleSettings) { + LaunchedEffect(mapStyleSettingsOrNull) { + val loaded = mapStyleSettingsOrNull ?: return@LaunchedEffect + // Nur beim ERSTEN echten DataStore-Emit (styleHydrated=false) Restore durchführen. + // Da mapStyleSettingsOrNull=null beim Start ist, kann dieser Block nicht durch + // das Default-Objekt fälschlicherweise ausgelöst werden. if (!styleHydrated) { - // v2.5.38 — Beim ersten Laden alle persistierten Einstellungen übernehmen, - // inkl. baseStyle (Kartentyp-Persistenz) und poiLayers. + // v2.7.27 — Vollständige Restore-Logik: baseStyle + alle Layer-Toggles + POI + autoLoad. layerState = layerState.copy( - baseStyle = mapStyleSettings.baseStyle, - showAudioLength = mapStyleSettings.showAudioLength, - showAudioLines = mapStyleSettings.showAudioLines, - poiLayers = mapStyleSettings.poiLayers, + baseStyle = loaded.baseStyle, + showAudioLength = loaded.showAudioLength, + showAudioLines = loaded.showAudioLines, + poiLayers = loaded.poiLayers, + showMarkers = loaded.overlayLayers.showMarkers, + showRadius = loaded.overlayLayers.showRadius, + showTrack = loaded.overlayLayers.showTrack, ) + autoPoiLoadEnabled = loaded.overlayLayers.autoPoiLoadEnabled styleHydrated = true } } @@ -476,6 +825,41 @@ fun ExplorerScreenMapLibre( lastAutoLoadCats = null de.waypointaudio.util.ExplorerPoiClient.clearCache() } + // v2.7.26 — Layer-Overlay-Toggles persistent speichern (showMarkers, showRadius, showTrack). + LaunchedEffect(layerState.showMarkers, layerState.showRadius, layerState.showTrack) { + if (!styleHydrated) return@LaunchedEffect + val current = mapStyleSettings.overlayLayers + if (layerState.showMarkers != current.showMarkers || + layerState.showRadius != current.showRadius || + layerState.showTrack != current.showTrack) { + runCatching { + mapStyleStore.setOverlayLayers( + de.waypointaudio.data.MapLayerOverlaySettings( + showMarkers = layerState.showMarkers, + showRadius = layerState.showRadius, + showTrack = layerState.showTrack, + autoPoiLoadEnabled = autoPoiLoadEnabled, + ) + ) + } + } + } + // v2.7.26 — Auto-POI-Load persistent speichern. + LaunchedEffect(autoPoiLoadEnabled) { + if (!styleHydrated) return@LaunchedEffect + if (autoPoiLoadEnabled != mapStyleSettings.overlayLayers.autoPoiLoadEnabled) { + runCatching { + mapStyleStore.setOverlayLayers( + de.waypointaudio.data.MapLayerOverlaySettings( + showMarkers = layerState.showMarkers, + showRadius = layerState.showRadius, + showTrack = layerState.showTrack, + autoPoiLoadEnabled = autoPoiLoadEnabled, + ) + ) + } + } + } // v2.5.38 — POI-Sichtbarkeit auf den geladenen MapLibre-Style anwenden. // Greift auf heuristische Layer-ID-Präfixe des OpenMapTiles-Schemas zurück. // Wenn ein Layer nicht existiert, passiert nichts (kein Crash). @@ -507,7 +891,11 @@ fun ExplorerScreenMapLibre( // dann alte entfernen. So gibt es keine sichtbare Lücke (kein Flackern) beim // Kartennachladen. Außerdem: maximale Anzahl angezeigter Marker auf 280 begrenzt, // benannte und wichtige Subtypen werden priorisiert. - LaunchedEffect(explorerPoiResults, styleReady, showPoiNames) { + // v2.7.29 — overlayRenderNonce als Key: Stellt sicher, dass POI-Marker nach + // jedem Style-Load (setStyle/Kartenstilwechsel) neu gezeichnet werden, ohne auf + // neue POI-Ergebnisse warten zu muessen. Verhindert fehlende POI-Marker nach + // Outdoor/Dunkel/3D-Wechsel. + LaunchedEffect(explorerPoiResults, styleReady, showPoiNames, overlayRenderNonce) { if (!styleReady) return@LaunchedEffect val ml = mapLibreMap ?: return@LaunchedEffect if (explorerPoiResults.isEmpty()) { @@ -635,21 +1023,47 @@ fun ExplorerScreenMapLibre( // CLASSIC nutzt weiterhin den raster-JSON-Weg. // Phantom-Layer-Cleanup vor setStyle: alle Annotations-Caches leeren, // damit nach styleReady=true ein kompletter Rehydration-Durchlauf startet. + // v2.7.25 — styleReady BEWUSST aus den Keys entfernt: styleReady als Key löste + // einen Doppel-Reload aus, da der initiale Style-Load (im AndroidView factory + // Callback) styleReady=true setzte, was diesen Effect erneut triggerte und + // ml.setStyle() ein zweites Mal aufrief. Das wischte bereits gezeichnete + // Linien weg und störte den Initial-Render der Tourlinie. Nur echte + // Style/Tilt-Wechsel sollen einen Reload auslösen. + // v2.7.28 — styleReady + mapLibreMap + appliedBaseStyle als zusätzliche Keys: + // Behebt den Bug: Wenn layerState.baseStyle bereits auf den gespeicherten Wert + // (z.B. OUTDOOR) gesetzt wird BEVOR styleReady=true (factory-Callback noch + // ausstehend), feuert der Effect, gibt aber return zurück. Wenn dann styleReady=true + // wird, ändert sich layerState.baseStyle NICHT mehr → Effect feuert nicht erneut. + // Lösung: styleReady und mapLibreMap als Keys hinzufügen. Guard gegen Doppel-Apply: + // appliedBaseStyle verfolgt, welcher Stil tatsächlich auf die Karte angewendet + // wurde. Nur wenn layerState.baseStyle != appliedBaseStyle wird setStyle() aufgerufen. LaunchedEffect( layerState.baseStyle, mapStyleSettings.perspectiveTilt, - styleReady + styleReady, + mapLibreMap ) { val ml = mapLibreMap ?: return@LaunchedEffect if (!styleReady) return@LaunchedEffect + // v2.7.28 — Doppel-Apply-Schutz: Wurde dieser Stil + Tilt bereits angewendet? + // Verhindert, dass der initiale Style-Load (factory) + Style-Change-Effect + // denselben Stil zweimal setzen und Overlays wegwischen. + // Für 3D-Stile muss auch ein Tilt-Änderung einen Reload auslösen. + val currentTilt = if (layerState.baseStyle == MapBaseStyle.CITY_3D || + layerState.baseStyle == MapBaseStyle.TERRAIN_3D || + layerState.baseStyle == MapBaseStyle.PERSPECTIVE) + mapStyleSettings.perspectiveTilt else 0 + if (layerState.baseStyle == appliedBaseStyle && currentTilt == (appliedPerspectiveTilt ?: 0)) return@LaunchedEffect // Phantom-Layer-Cleanup vor Stilwechsel. styleReady = false + // v2.7.30 — planlinePolylines + routeStopMarkers ebenfalls leeren (v2.7.29-Lücke). clearAllAnnotationsCaches( waypointMarkers, waypointMarkerIdToWaypoint, waypointRadiusPolygons, trackMarkers, trackMarkerIdToIndex, trackPolylines, routePolylines, audioLinePolylines, - manualRoutePolylines, manualRouteMarkers, manualRouteMarkerIdToIndex + manualRoutePolylines, manualRouteMarkers, manualRouteMarkerIdToIndex, + planlinePolylines, routeStopMarkers ) myLocationMarker = null accuracyPolygon = null @@ -661,17 +1075,22 @@ fun ExplorerScreenMapLibre( mapStyleSettings.perspectiveTilt.toDouble().coerceIn(0.0, 60.0) } else 0.0 + val targetStyle = layerState.baseStyle + val targetTilt = if (targetStyle == MapBaseStyle.CITY_3D || + targetStyle == MapBaseStyle.TERRAIN_3D || + targetStyle == MapBaseStyle.PERSPECTIVE) + mapStyleSettings.perspectiveTilt else 0 val onStyleReady: (Style) -> Unit = { loadedStyle -> // v2.5.37 — 3D Stadt: Gebäude-Extrusion hinzufügen falls building-Layer vorhanden. // Robust: wenn Source/Layer fehlt, kein Crash — einfach 2D-Fallback. - if (layerState.baseStyle == MapBaseStyle.CITY_3D) { + if (targetStyle == MapBaseStyle.CITY_3D) { try { addBuildingExtrusionIfAvailable(loadedStyle) } catch (_: Exception) { /* 2D-Fallback: Layer existiert nicht */ } } // v2.5.38 — POI-Layer-Sichtbarkeit nach Style-Load anwenden. - if (layerState.baseStyle != MapBaseStyle.CLASSIC && - layerState.baseStyle != MapBaseStyle.SATELLITE) { + if (targetStyle != MapBaseStyle.CLASSIC && + targetStyle != MapBaseStyle.SATELLITE) { try { applyPoiLayerVisibility(loadedStyle, layerState.poiLayers) } catch (_: Exception) { /* Kein Crash wenn Layer nicht vorhanden */ } @@ -679,7 +1098,15 @@ fun ExplorerScreenMapLibre( // Kamera-Pitch setzen. val pos = ml.cameraPosition ml.cameraPosition = CameraPosition.Builder(pos).tilt(pitchDeg).build() + // v2.7.28 — appliedBaseStyle + appliedPerspectiveTilt nach erfolgreichem + // setStyle aktualisieren. Verhindert, dass dieser Effekt denselben + // Stil+Tilt erneut anwendet und Overlays wegwischt. + appliedBaseStyle = targetStyle + appliedPerspectiveTilt = targetTilt styleReady = true + // v2.7.12 — Nonce nach Stil-Reload erhöhen, damit Overlay-LaunchedEffect + // auch dann neu feuert, wenn styleReady bereits true war. + overlayRenderNonce++ } when (layerState.baseStyle) { @@ -717,9 +1144,31 @@ fun ExplorerScreenMapLibre( } // Berechnete Routenlinie + Planlinie + Stop-Marker als eigene Polyline-Schicht. - LaunchedEffect(routeLine, routePlanline, routePlan, showRouteOverlay, styleReady, savedRouteLine) { + // v2.7.4 — mapLibreMap als zusätzlicher Key: Nach Map-Neuinitialisierung + // (z. B. Stylewechsel, Workspace-Rückkehr) wird die Planlinie/Route sofort + // neu gezeichnet, auch wenn sich routePlanline/savedRouteLine nicht geändert haben. + // v2.7.8 — activeTourRoute als zusätzlicher Key: Stellt sicher, dass der + // Zeichnungseffekt immer dann feuert, wenn sich die persistierte Touränderung (DB) + // ändert — unabhängig davon ob savedRouteLine strukturell gleich blieb. + // v2.7.13 — routeRenderKey + overlayRenderNonce als zusätzliche Keys: + // • routeRenderKey: Stabiler String-Key aus activeTourRoute-ID/source/pointCount + // + savedRouteLine.size + routePlanline.size. Garantiert Feuer auch wenn + // List.equals()-Snapshot-Caching die Recomposition unterbindet. + // • overlayRenderNonce: Stellt sicher, dass der Effekt nach jedem Style-Load + // (auch initialem) neu feuert. Behebt das Problem, dass die Planlinie + // nicht initial gezeichnet wurde, wenn activeTourRoute nach dem Style-Load + // aus der DB ankam und das addPolyline() still scheiterte weil der + // MapLibre-AnnotationManager noch nicht vollständig initialisiert war. + // • yield() nach styleReady-Guard: Gibt dem MapLibre-AnnotationManager + // Initialisierungszeit nach onStyleLoaded, analog zum Waypoint-Effekt. + LaunchedEffect(routeLine, routePlanline, routePlan, showRouteOverlay, styleReady, savedRouteLine, mapLibreMap, activeTourRoute, routeRenderKey, overlayRenderNonce) { val ml = mapLibreMap ?: return@LaunchedEffect if (!styleReady) return@LaunchedEffect + // v2.7.30 — delay(150) statt yield(): Gibt MapLibre-AnnotationManager + // ausreichend Zeit nach onStyleLoaded. yield() war zu kurz und ließ + // addPolyline() still fehlschlagen. Analog zur Waypoint-Render-Fix-Logik. + kotlinx.coroutines.delay(150) + if (!styleReady) return@LaunchedEffect // Erneut prüfen nach dem delay for (pl in routePolylines) runCatching { ml.removePolyline(pl) } routePolylines.clear() for (pl in planlinePolylines) runCatching { ml.removePolyline(pl) } @@ -729,101 +1178,93 @@ fun ExplorerScreenMapLibre( if (!showRouteOverlay) return@LaunchedEffect - // v2.4.5 — Planlinie (Luftlinie zwischen Stops) wird NUR gezeichnet, - // wenn keine berechnete Route vorhanden ist. Sobald eine echte - // Routing-Polyline existiert, ist die Planlinie redundant und - // optisch störend (parallel-laufende dünne Linie auf der Route). + // v2.4.5 — Planlinie (Luftlinie zwischen Stops) wird NUR gezeichnet, wenn + // weder eine berechnete Route noch eine gespeicherte Tourroute vorhanden ist. + // Priorität: routeLine > savedRouteLine > routePlanline. + // v2.7.3 — savedRouteLine hat Vorrang vor routePlanline: für OSRM-Routen soll + // die exakte Geometrie aus der DB gezeigt werden, nicht die Luftlinie. Für + // PLANLINE-Routen ist savedRouteLine identisch mit routePlanline, wird aber + // sofort beim App-Start verfügbar (ohne async Plan-Restore), was eine kurze + // weiße Lücke beim Zurückkehren vermeidet. + // v2.7.4 — routePlanline hat Vorrang vor savedRouteLine, wenn: + // (a) Die TourRoute eine PLANLINE-Quelle ist (savedRouteLine = Luftlinie, + // routePlanline ebenfalls, aber routePlanline ist aktueller nach Plan-Änderung) + // (b) routePlanline ≥ 2 Punkte hat (ein gültiger Plan liegt vor) + // Das verhindert, dass eine alte DB-Linie noch sichtbar ist, wenn der User + // gerade neue Stops eingegeben hat (aber der Auto-Save-Effect noch nicht gefeuert hat). val hasComputedRoute = routeLine.size >= 2 - if (!hasComputedRoute && routePlanline.size >= 2) { - val halo = ml.addPolyline( - PolylineOptions() - .addAll(routePlanline) - .color(0xFFFFFFFF.toInt()) - .width(7f) - .alpha(0.7f) - ) - val line = ml.addPolyline( - PolylineOptions() - .addAll(routePlanline) - .color(0xFFFF9800.toInt()) - .width(4f) - .alpha(0.55f) - ) - planlinePolylines += halo - planlinePolylines += line + // v2.7.4: routePlanline hat Priorität über savedRouteLine bei PLANLINE-Quelle + val hasFreshPlanline = routePlanline.size >= 2 && + activeTourRoute?.source == de.waypointaudio.data.RouteSourceKind.PLANLINE + val hasSavedRoute = savedRouteLine.size >= 2 && !hasFreshPlanline + // routePlanline als eigene Linie zeigen, wenn: + // a) kein OSRM routeLine, kein savedRouteLine (ursprüngliches Verhalten) + // b) ODER wenn hasFreshPlanline (PLANLINE-Quelle, routePlanline bevorzugt) + // v2.7.30 — runCatching: Planlinie und Routen robust gegen AnnotationManager-Fehler. + if (!hasComputedRoute && (!hasSavedRoute || hasFreshPlanline) && routePlanline.size >= 2) { + runCatching { ml.addPolyline(PolylineOptions().addAll(routePlanline).color(0xFFFFFFFF.toInt()).width(7f).alpha(0.7f)) } + .getOrNull()?.let { planlinePolylines += it } + runCatching { ml.addPolyline(PolylineOptions().addAll(routePlanline).color(0xFFFF9800.toInt()).width(4f).alpha(0.55f)) } + .getOrNull()?.let { planlinePolylines += it } } // v2.4.6 — Gespeicherte Tourroute zeichnen, wenn keine aktuell berechnete // Route vorhanden ist. Sobald `routeLine` aktiv ist, übernimmt diese, // damit Live-Berechnung > gespeicherte Tourroute (sichtbare Priorität // entspricht der Clip-Linien-Priorität). - if (routeLine.size < 2 && savedRouteLine.size >= 2) { - val halo = ml.addPolyline( - PolylineOptions() - .addAll(savedRouteLine) - .color(0xFFFFFFFF.toInt()) - .width(8f) - .alpha(0.75f) - ) - val line = ml.addPolyline( - PolylineOptions() - .addAll(savedRouteLine) - // Sichtbar unterscheidbar: tieferes Grün für „dauerhaft gespeichert". - .color(0xFF2E7D32.toInt()) - .width(5f) - .alpha(0.9f) - ) - routePolylines += halo - routePolylines += line + // v2.7.3 — savedRouteLine zeigt PLANLINE und OSRM gleichermaßen sofort nach + // App-Start, auch wenn der async Plan-Restore noch nicht abgeschlossen ist. + // v2.7.4 — PLANLINE-Quelle bekommt dieselbe orangene Farbe wie routePlanline, + // damit die Linie vor und nach dem App-Neustart gleich aussieht. Nur + // OSRM/TRACK/IMPORTED bekommen die grüne "gespeichert"-Färbung. + // v2.7.18 — Unified Tour Layers: MANUAL-Quelle bekommt dieselbe primäre + // Tourlinie (grün) wie OSRM — beide sind "Tourlinie", nur durch unterschied- + // liches Werkzeug entstanden. Die violette Bearbeitungs-Vorschau (manualRoute- + // Polylines) erscheint nur noch im aktiven Zeichenmodus (manualRouteMode). + if (!hasComputedRoute && hasSavedRoute) { + val isPlanlineSource = activeTourRoute?.source == de.waypointaudio.data.RouteSourceKind.PLANLINE + // v2.7.18: MANUAL bekommt dieselbe grüne Tourlinie wie OSRM (einheitliches + // Tour-System). PLANLINE bleibt orange/gedimmt als Planungs-Vorschau. + val lineColor = if (isPlanlineSource) 0xFFFF9800.toInt() else 0xFF2E7D32.toInt() + val lineWidth = if (isPlanlineSource) 4f else 5f + val lineAlpha = if (isPlanlineSource) 0.55f else 0.9f + val haloWidth = if (isPlanlineSource) 7f else 8f + val haloAlpha = if (isPlanlineSource) 0.7f else 0.75f + // v2.7.30 — runCatching: savedRouteLine-Polylines robust. + runCatching { ml.addPolyline(PolylineOptions().addAll(savedRouteLine).color(0xFFFFFFFF.toInt()).width(haloWidth).alpha(haloAlpha)) } + .getOrNull()?.let { routePolylines += it } + runCatching { ml.addPolyline(PolylineOptions().addAll(savedRouteLine).color(lineColor).width(lineWidth).alpha(lineAlpha)) } + .getOrNull()?.let { routePolylines += it } } if (routeLine.size >= 2) { - val halo = ml.addPolyline( - PolylineOptions() - .addAll(routeLine) - .color(0xFFFFFFFF.toInt()) - .width(9f) - .alpha(0.85f) - ) - val line = ml.addPolyline( - PolylineOptions() - .addAll(routeLine) - .color(0xFF1976D2.toInt()) - .width(6f) - .alpha(0.95f) - ) - routePolylines += halo - routePolylines += line + // v2.7.30 — runCatching: routeLine-Polylines robust. + runCatching { ml.addPolyline(PolylineOptions().addAll(routeLine).color(0xFFFFFFFF.toInt()).width(9f).alpha(0.85f)) } + .getOrNull()?.let { routePolylines += it } + runCatching { ml.addPolyline(PolylineOptions().addAll(routeLine).color(0xFF1976D2.toInt()).width(6f).alpha(0.95f)) } + .getOrNull()?.let { routePolylines += it } } val iconFactory = IconFactory.getInstance(context) // Stop-Marker für Start/Via/Ziel + // v2.7.30 — runCatching: Stop-Marker robust. routePlan.start?.let { s -> val bm = routeStopBitmap(RouteStopKind.START, context) - routeStopMarkers += ml.addMarker( - MarkerOptions() - .position(LatLng(s.latitude, s.longitude)) - .title("Start: ${s.label}") - .icon(iconFactory.fromBitmap(bm)) - ) + runCatching { + ml.addMarker(MarkerOptions().position(LatLng(s.latitude, s.longitude)).title("Start: ${s.label}").icon(iconFactory.fromBitmap(bm))) + }.getOrNull()?.let { routeStopMarkers += it } } routePlan.via.forEachIndexed { idx, v -> val bm = routeStopBitmap(RouteStopKind.VIA, context, label = (idx + 1).toString()) - routeStopMarkers += ml.addMarker( - MarkerOptions() - .position(LatLng(v.latitude, v.longitude)) - .title("Via ${idx + 1}: ${v.label}") - .icon(iconFactory.fromBitmap(bm)) - ) + runCatching { + ml.addMarker(MarkerOptions().position(LatLng(v.latitude, v.longitude)).title("Via ${idx + 1}: ${v.label}").icon(iconFactory.fromBitmap(bm))) + }.getOrNull()?.let { routeStopMarkers += it } } routePlan.destination?.let { d -> val bm = routeStopBitmap(RouteStopKind.DESTINATION, context) - routeStopMarkers += ml.addMarker( - MarkerOptions() - .position(LatLng(d.latitude, d.longitude)) - .title("Ziel: ${d.label}") - .icon(iconFactory.fromBitmap(bm)) - ) + runCatching { + ml.addMarker(MarkerOptions().position(LatLng(d.latitude, d.longitude)).title("Ziel: ${d.label}").icon(iconFactory.fromBitmap(bm))) + }.getOrNull()?.let { routeStopMarkers += it } } } @@ -831,8 +1272,19 @@ fun ExplorerScreenMapLibre( // Stille Routenpunkte (kleine, dunkle Kreise) + verbindende Linie. // Diese Punkte sind KEINE Wegpunkte und werden niemals in der // Wegpunktliste, Track-Liste oder Storyboard erscheinen. + // v2.7.1 — mapLibreMap als zusätzlicher Key: Wenn die Karte nach einem + // Workspace-Wechsel neu initialisiert wird (mapLibreMap wechselt von null + // auf eine neue Instanz), müssen die Polylines neu gezeichnet werden. + // Ohne diesen Key würde das LaunchedEffect nach dem Map-Ready-Callback + // nicht feuern, da manualRoutePoints sich nicht verändert hat. + // v2.7.18 — Unified Tour Layers: Die violette Bearbeitungs-Vorschaulinie + // wird NUR im aktiven Zeichenmodus (manualRouteMode == true) gezeigt. + // Im gespeicherten Zustand (manualRouteMode == false) übernimmt die grüne + // savedRouteLine die Darstellung — keine Doppellinie mehr. Verlaufspunkt- + // Marker werden weiterhin gezeigt, aber nur im Bearbeitungsmodus (damit + // die Karte im Normalbetrieb nicht mit kleinen Punkten übersät wird). LaunchedEffect(manualRoutePoints, manualRouteMode, styleReady, - selectedRoutePointIndex, primaryArgb) { + selectedRoutePointIndex, primaryArgb, mapLibreMap) { val ml = mapLibreMap ?: return@LaunchedEffect if (!styleReady) return@LaunchedEffect for (pl in manualRoutePolylines) runCatching { ml.removePolyline(pl) } @@ -841,29 +1293,34 @@ fun ExplorerScreenMapLibre( manualRouteMarkers.clear() manualRouteMarkerIdToIndex.clear() - if (manualRoutePoints.size >= 2) { + // v2.7.18 — Bearbeitungs-Vorschaulinie nur im aktiven Zeichenmodus. + // Im gespeicherten Zustand (mode=false) wird die Tourlinie bereits durch + // savedRouteLine (grün) dargestellt — violette Kopie entfällt. + if (manualRouteMode && manualRoutePoints.size >= 2) { + // Bearbeitungsvorschau: violett, deutlich sichtbar als "wird gerade gezeichnet". val halo = ml.addPolyline( PolylineOptions() .addAll(manualRoutePoints) .color(0xFFFFFFFF.toInt()) - .width(8f) - .alpha(0.75f) + .width(10f) + .alpha(0.80f) ) val line = ml.addPolyline( PolylineOptions() .addAll(manualRoutePoints) - // Klar unterscheidbar von OSRM-Routen (blau) und gespeicherten - // Tourrouten (grün): violett für "manuell gezeichnet". + // Bearbeitungs-Vorschau: violett, klar unterscheidbar von der + // gespeicherten Tourlinie (grün) und OSRM-Route (blau). .color(0xFF6A1B9A.toInt()) - .width(5f) - .alpha(0.95f) + .width(7f) + .alpha(0.97f) ) manualRoutePolylines += halo manualRoutePolylines += line } - // Punkt-Marker pro Routenpunkt – klein, ohne Audio-/Wegpunkt-Bezug. - if (manualRoutePoints.isNotEmpty()) { + // Verlaufspunkt-Marker: nur im aktiven Bearbeitungsmodus als interaktive + // Punkte zeigen. Im Normalbetrieb nicht nötig — reduziert visuelles Rauschen. + if (manualRouteMode && manualRoutePoints.isNotEmpty()) { val iconFactory = IconFactory.getInstance(context) val sizePx = (context.resources.displayMetrics.density * 14).toInt() manualRoutePoints.forEachIndexed { idx, p -> @@ -872,7 +1329,7 @@ fun ExplorerScreenMapLibre( val marker = ml.addMarker( MarkerOptions() .position(p) - .title("Routenpunkt ${idx + 1}") + .title("Verlaufspunkt ${idx + 1}") .icon(iconFactory.fromBitmap(bm)) ) manualRouteMarkers += marker @@ -883,8 +1340,28 @@ fun ExplorerScreenMapLibre( // Haupt-Overlay-Refresh: Wegpunkte, Tracks, Audiozonen, Audio-Längen-Linien, // sowie der Search-Pin. + // v2.7.11 — mapLibreMap und waypointRenderKey als zusätzliche Keys: + // • mapLibreMap: Stellt sicher, dass Marker gezeichnet werden, sobald + // die MapLibre-Instanz verfügbar wird — auch wenn alle anderen Keys + // (waypoints, styleReady) sich nicht geändert haben. + // • waypointRenderKey: Stabiler String-Key aus ID+Lat+Lon aller Waypoints. + // Garantiert, dass der Effekt feuert, wenn ein Waypoint hinzugefügt, + // verschoben oder gelöscht wird — unabhängig von Kotlins List.equals(). + // Verhindert die "N+1"-Verzögerung, bei der der neueste Marker erst + // nach dem nächsten Speichern sichtbar wurde. + // v2.7.12 — overlayRenderNonce als zusätzlicher Key: + // • Wird nach jedem erfolgreichen Style-Load (initial + Stilwechsel) inkrementiert. + // • Stellt sicher, dass der Effekt feuert, sobald Map/Style bereit ist — + // ohne Nutzerinteraktion. Behebt das Problem, dass Waypoints erst nach + // dem ersten Tap auf den Waypoint-Button sichtbar wurden. + // • Ein kurzes delay(50) nach dem styleReady-Guard gibt dem MapLibre + // Annotation-Manager Zeit, sich vollständig zu initialisieren, bevor + // drawExplorerOverlaysMapLibre aufgerufen wird. + // v2.7.13 — routeRenderKey als zusätzlicher Key: + // • Stellt sicher, dass clipLineGeometry aktuell ist wenn activeTourRoute + // aus der DB geladen wird (relevant für Clip-Längenlinien). LaunchedEffect( - waypoints, + waypointRenderKey, primaryArgb, actionMenuWaypoint?.id, visibleTrack, @@ -897,10 +1374,19 @@ fun ExplorerScreenMapLibre( routePlanline, savedRouteLine, manualRoutePoints, - styleReady + styleReady, + mapLibreMap, + overlayRenderNonce, + routeRenderKey ) { val ml = mapLibreMap ?: return@LaunchedEffect if (!styleReady) return@LaunchedEffect + // v2.7.30 — delay(150) statt yield(): Gibt MapLibre-AnnotationManager + // ausreichend Zeit zur vollständigen GL-Initialisierung nach onStyleLoaded. + // yield() (1 Frame) war zu kurz — addMarker() schlug still fehl und + // Waypoints/Puck wurden nicht gezeichnet. 150ms reichen zuverlässig. + kotlinx.coroutines.delay(150) + if (!styleReady) return@LaunchedEffect // Erneut prüfen nach dem delay drawExplorerOverlaysMapLibre( ml = ml, context = context, @@ -950,6 +1436,82 @@ fun ExplorerScreenMapLibre( ) } + // v2.7.31 — Dedizierter Marker-Retry nach 650ms: + // Root Cause: Nach setStyle() kann addMarker() im 150ms-Fenster still fehlschlagen, + // auch wenn addPolygon() bereits funktioniert (der AnnotationManager initialisiert + // Polygon-Layer vor Symbol-Layer). Resultat: Radius sichtbar, Marker fehlt. + // Dieser Effekt prüft 650ms nach Style-Ready, ob Waypoints vorhanden aber keine + // Marker gezeichnet wurden — und löst dann einen gezielten Rebuild aus. + // Idempotent: drawExplorerOverlaysMapLibre leert vor dem Neuzeichnen alle + // alten Annotations (inkl. ggf. vorhandener Polygone) — kein Double-Draw. + LaunchedEffect(styleReady, mapLibreMap, overlayRenderNonce) { + if (!styleReady) return@LaunchedEffect + if (mapLibreMap == null) return@LaunchedEffect + kotlinx.coroutines.delay(650) + if (!styleReady) return@LaunchedEffect + // Nur triggern wenn showMarkers=true, Waypoints vorhanden aber Marker-Cache leer: + // Das bedeutet addMarker() ist beim vorigen Versuch still fehlgeschlagen. + // waypoints is already filtered by selectedTour (see top of composable). + if (layerState.showMarkers && waypoints.isNotEmpty() && waypointMarkers.isEmpty()) { + overlayRenderNonce++ + } + } + + // v2.7.30 — Robuster Puck-Rehydrate nach Style-Load. + // Root Cause (v2.7.29): yield() war zu kurz; addMarker() schlug nach setStyle() + // still fehl, wenn der AnnotationManager noch nicht vollständig initialisiert war. + // Zusätzlich: early-return bei lastLat==null verhinderte den Puck-Draw selbst + // wenn später GPS-Fix eintraf (kein Retry-Mechanismus). + // Fix v2.7.30: + // 1. delay(200) statt yield() — gibt GL-Thread und AnnotationManager ausreichend Zeit. + // 2. runCatching um addMarker — verhindert silent-Crash im Coroutine-Scope. + // 3. Retry: Nach dem delay nochmals styleReady prüfen (kann sich geändert haben). + // 4. Kein early-return bei lastLat==null — LaunchedEffect arbeitet mit snapshot + // der letzten bekannten Koordinaten; wenn kein GPS-Fix: Puck wird spaäter + // vom LocationCallback gesetzt (bestehende Logik). Der Effekt zeichnet + // nur, wenn Koordinaten bekannt sind. + LaunchedEffect(overlayRenderNonce, styleReady, mapLibreMap) { + if (!styleReady) return@LaunchedEffect + val ml = mapLibreMap ?: return@LaunchedEffect + // delay(200): AnnotationManager braucht mehr Zeit als yield() nach Style-Load. + kotlinx.coroutines.delay(200) + if (!styleReady) return@LaunchedEffect // Erneut prüfen: Style könnte wechseln + val lat = lastLat ?: return@LaunchedEffect // Kein GPS-Fix: LocationCallbackübernimmt + val lng = lastLng ?: return@LaunchedEffect + val gp = LatLng(lat, lng) + // Alten Marker sicher entfernen (nach setStyle() bereits vom MapLibre geleert). + myLocationMarker?.let { runCatching { ml.removeMarker(it) } } + // v2.7.30 — runCatching: Verhindert silent-Crash wenn AnnotationManager + // noch nicht bereit ist. Marker wird null bei Fehler — LocationCallback + // setzt ihn beim nächsten GPS-Fix korrekt. + myLocationMarker = runCatching { + ml.addMarker( + MarkerOptions() + .position(gp) + .title("Mein Standort") + .icon( + puckBitmap?.let { bm -> IconFactory.getInstance(context).fromBitmap(bm) } + ?: IconFactory.getInstance(context).defaultMarker() + ) + ) + }.getOrNull() + // Genauigkeitskreis ebenfalls neu zeichnen. + accuracyPolygon?.let { runCatching { ml.removePolygon(it) } } + accuracyPolygon = null + val radius = lastAccuracyM?.toDouble() ?: 0.0 + if (radius > 0.0) { + accuracyPolygon = runCatching { + ml.addPolygon( + PolygonOptions() + .addAll(circleLatLng(lat, lng, radius, 60)) + .fillColor((primaryArgb and 0x00FFFFFF) or 0x33000000) + .strokeColor(primaryArgb) + .alpha(0.4f) + ) + }.getOrNull() + } + } + // Standort-Updates: My-Marker, Genauigkeitskreis, ggf. Follow. DisposableEffect(hasPermission) { if (!hasPermission) return@DisposableEffect onDispose { } @@ -1255,6 +1817,25 @@ fun ExplorerScreenMapLibre( Spacer(Modifier.width(6.dp)) Text(stringResource(R.string.explorer_route_point_delete)) } + // v2.7.0 — Verlaufspunkt als Audio-Wegpunkt erstellen. + Button( + onClick = { + editDialogWaypoint = null + editDialogPrefill = Pair(pt.latitude, pt.longitude) + showEditDialog = true + showRoutePointDialog = false + selectedRoutePointIndex = null + }, + colors = ButtonDefaults.buttonColors( + containerColor = MaterialTheme.colorScheme.primaryContainer, + contentColor = MaterialTheme.colorScheme.onPrimaryContainer + ), + modifier = Modifier.fillMaxWidth() + ) { + Icon(Icons.Filled.AddLocation, contentDescription = null, modifier = Modifier.size(16.dp)) + Spacer(Modifier.width(6.dp)) + Text(stringResource(R.string.tourverlauf_editor_as_waypoint)) + } } }, confirmButton = { @@ -1307,7 +1888,17 @@ fun ExplorerScreenMapLibre( prefillTourName = selectedTour, tourDefaults = tourDefaults, onConfirm = { newWaypoint -> - viewModel.upsert(newWaypoint) + // v2.7.7 — Spontane-Tour-Autocreate: + // Wenn ein NEUER Wegpunkt (editDialogWaypoint == null) im neutralen + // Explorer-Kontext gesetzt wird, erzeugt upsertFromNeutralExplorer + // automatisch eine echte "Spontane Tour" und speichert den Wegpunkt darin. + // Beim Bearbeiten eines bestehenden Wegpunkts (editDialogWaypoint != null) + // wird der normale upsert-Pfad verwendet. + if (editDialogWaypoint == null) { + viewModel.upsertFromNeutralExplorer(newWaypoint) + } else { + viewModel.upsert(newWaypoint) + } showEditDialog = false editDialogWaypoint = null editDialogPrefill = null @@ -1324,6 +1915,52 @@ fun ExplorerScreenMapLibre( ) } + // v2.7.0 — Tourverlauf-Editor-Sheet. + if (showTourverlaufEditor) { + TourverlaufEditorSheet( + routePoints = manualRoutePoints, + isDrawing = tapMode is TapModeMl.DrawRoutePoint, + tourName = selectedTour, + lastSelectedPointIndex = selectedRoutePointIndex, + onAddCenterPoint = { + val ml = mapLibreMap + val center = ml?.cameraPosition?.target + if (center != null) { + manualRoutePoints = manualRoutePoints + LatLng(center.latitude, center.longitude) + } else if (lastLat != null && lastLng != null) { + manualRoutePoints = manualRoutePoints + LatLng(lastLat!!, lastLng!!) + } + }, + onToggleDrawMode = { + manualRouteMode = !manualRouteMode + tapMode = if (manualRouteMode) TapModeMl.DrawRoutePoint else TapModeMl.None + }, + onRemoveLast = { + if (manualRoutePoints.isNotEmpty()) { + manualRoutePoints = manualRoutePoints.dropLast(1) + } + }, + onClear = { + manualRoutePoints = emptyList() + manualRouteMode = false + tapMode = TapModeMl.None + }, + onCreateWaypointFromPoint = { point -> + editDialogWaypoint = null + editDialogPrefill = Pair(point.latitude, point.longitude) + showEditDialog = true + showTourverlaufEditor = false + }, + onOpenOnlineRouting = { + showTourverlaufEditor = false + showRoutePlanner = true + }, + onDismiss = { + showTourverlaufEditor = false + } + ) + } + if (showRoutePlanner) { val locationLatLon: Pair? = lastLat?.let { lat -> lastLng?.let { lon -> lat to lon } @@ -1334,7 +1971,11 @@ fun ExplorerScreenMapLibre( RoutePlannerSheet( plan = routePlan, routeStatus = routeStatus, - hasRoute = routeLine.size >= 2, + // v2.7.22 — hasRoute schließt gespeicherte Routen (savedRouteLine) ein, + // damit das Sheet nicht "Noch keine Route" zeigt, wenn eine MANUAL- oder + // OSRM-TourRoute gespeichert ist, aber routeLine noch leer ist (kein + // aktiver OSRM-Lauf in dieser Session). + hasRoute = routeLine.size >= 2 || savedRouteLine.size >= 2, hasPlanline = routePlanline.size >= 2, isLoading = routeLoading, routingEndpoint = mapStyleSettings.routingEndpoint, @@ -1346,6 +1987,8 @@ fun ExplorerScreenMapLibre( // bliebe die alte Linie sichtbar, obwohl die Stops sich geändert haben. routeLine = emptyList() if (routeStatus != null) routeStatus = null + // v2.7.2 — Plan im ViewModel speichern, damit er Workspace-Wechsel überlebt. + viewModel.setCurrentSessionPlan(selectedTour, newPlan) }, onComputeRoute = { // v2.4.4: Wenn kein Endpunkt gesetzt ist, geben wir keinen @@ -1388,6 +2031,27 @@ fun ExplorerScreenMapLibre( de.waypointaudio.util.OsrmRoutingClient.formatDistance(result.distanceMeters), de.waypointaudio.util.OsrmRoutingClient.formatDuration(result.durationSeconds) ) + // v2.6.2 — Berechnete Route im ViewModel sichern, damit sie + // nach einem Workspace-Wechsel wiederhergestellt werden kann. + // buildTourRouteFromState() benötigt routePlanline — wird + // inline berechnet (routeLine ist bereits gesetzt). + val sessionPlanline = routePlan.orderedStops() + .map { LatLng(it.latitude, it.longitude) } + .takeIf { it.size >= 2 } ?: emptyList() + val sessionRoute = buildTourRouteFromState( + plan = routePlan, + routeLine = routeLine, + routePlanline = sessionPlanline, + distanceMeters = result.distanceMeters, + durationSeconds = result.durationSeconds, + endpoint = endpoint, + planlineSourceLabel = routingPoiCtx.getString( + R.string.tour_route_source_planline + ) + ) + if (sessionRoute != null) { + viewModel.setCurrentSessionRoute(selectedTour, sessionRoute) + } }.onFailure { ex -> routeLine = emptyList() lastComputedDistanceMeters = null @@ -1421,19 +2085,57 @@ fun ExplorerScreenMapLibre( }, onShowPlanline = { routeLine = emptyList() - if (routePlanline.size >= 2) { + // v2.7.23 — Planlinie aus routePlanline (remember(routePlan)) lesen. + // Falls routePlanline noch leer ist aber Plan komplett: inline berechnen als Fallback. + val activePlanline = if (routePlanline.size >= 2) routePlanline + else routePlan.orderedStops() + .map { LatLng(it.latitude, it.longitude) } + .takeIf { it.size >= 2 } ?: emptyList() + if (activePlanline.size >= 2) { routeStatus = routingPoiCtx.getString(R.string.route_planner_planline_active) val ml = mapLibreMap if (ml != null) { - val mid = routePlanline[routePlanline.size / 2] + val mid = activePlanline[activePlanline.size / 2] ml.animateCamera(CameraUpdateFactory.newLatLngZoom(mid, 13.0)) } + // v2.7.2 — Planlinie als Session-Route persistieren, damit sie + // nach Workspace-Wechsel wieder sichtbar ist (savedRouteLine-Fallback). + // v2.7.3 — Zusätzlich dauerhaft in die DB schreiben (activeTourRoute), + // damit die Planlinie auch nach App-Neustart automatisch sichtbar ist. + // savedRouteLine liest activeTourRoute.polyline und zeigt sie sofort + // beim nächsten App-Start, noch bevor der async Plan-Restore läuft. + val planlineRoute = buildTourRouteFromState( + plan = routePlan, + routeLine = emptyList(), + routePlanline = activePlanline, + distanceMeters = null, + durationSeconds = null, + endpoint = routingPoiCtx.getString(R.string.tour_route_source_planline), + planlineSourceLabel = routingPoiCtx.getString(R.string.tour_route_source_planline) + ) + if (planlineRoute != null) { + viewModel.setCurrentSessionRoute(selectedTour, planlineRoute) + // v2.7.3 — DB-Persistenz: sicherstellen, dass die Planlinie + // auch nach einem App-Neustart (Prozess-Kill) sichtbar bleibt. + viewModel.saveTourRouteFor(selectedTour, planlineRoute) + } } }, onClear = { routePlan = RoutePlan() routeLine = emptyList() routeStatus = null + // v2.6.2 — Session-Route ebenfalls leeren: wenn der Nutzer + // explizit „Planer leeren“ wählt, soll keine Route wiederhergestellt werden. + viewModel.clearCurrentSessionRoute() + // v2.7.2 — Session-Plan leeren. + viewModel.clearCurrentSessionPlan() + // v2.7.3 — DB-PLANLINE-Route löschen, wenn der Nutzer explizit + // leert, damit sie nach App-Neustart nicht wieder erscheint. + // OSRM/MANUAL-Routen bleiben unangetastet (bewusste Nutzeraktion). + if (activeTourRoute?.source == de.waypointaudio.data.RouteSourceKind.PLANLINE) { + viewModel.deleteTourRouteForCurrent() + } }, onConfigureEndpoint = { showRoutePlanner = false @@ -1499,10 +2201,15 @@ fun ExplorerScreenMapLibre( currentTourName = selectedTour, savedTourRoute = activeTourRoute, onSaveTourRoute = { + // v2.7.23 — Inline Planline als Fallback wenn routePlanline noch nicht recomposed + val effectivePlanline = if (routePlanline.size >= 2) routePlanline + else routePlan.orderedStops() + .map { LatLng(it.latitude, it.longitude) } + .takeIf { it.size >= 2 } ?: emptyList() val route = buildTourRouteFromState( plan = routePlan, routeLine = routeLine, - routePlanline = routePlanline, + routePlanline = effectivePlanline, distanceMeters = lastComputedDistanceMeters, durationSeconds = lastComputedDurationSeconds, endpoint = lastComputedEndpoint, @@ -1510,14 +2217,20 @@ fun ExplorerScreenMapLibre( ) if (route != null) { viewModel.saveTourRouteForCurrent(route) + viewModel.setCurrentSessionRoute(selectedTour, route) routeStatus = routingPoiCtx.getString(R.string.tour_route_saved_msg, selectedTour) } }, onReplaceTourRoute = { + // v2.7.23 — Inline Planline als Fallback wenn routePlanline noch nicht recomposed + val effectivePlanline = if (routePlanline.size >= 2) routePlanline + else routePlan.orderedStops() + .map { LatLng(it.latitude, it.longitude) } + .takeIf { it.size >= 2 } ?: emptyList() val route = buildTourRouteFromState( plan = routePlan, routeLine = routeLine, - routePlanline = routePlanline, + routePlanline = effectivePlanline, distanceMeters = lastComputedDistanceMeters, durationSeconds = lastComputedDurationSeconds, endpoint = lastComputedEndpoint, @@ -1525,17 +2238,97 @@ fun ExplorerScreenMapLibre( ) if (route != null) { viewModel.saveTourRouteForCurrent(route) + viewModel.setCurrentSessionRoute(selectedTour, route) routeStatus = routingPoiCtx.getString(R.string.tour_route_replaced_msg, selectedTour) } }, onDeleteTourRoute = { viewModel.deleteTourRouteForCurrent() + // v2.6.2 — Auch die Session-Route löschen, damit kein + // Wiederherstellungsversuch nach dem nächsten Workspace-Wechsel erfolgt. + viewModel.clearCurrentSessionRoute() + // v2.7.2 — Session-Plan ebenfalls leeren. + viewModel.clearCurrentSessionPlan() + routePlan = RoutePlan() + routeLine = emptyList() routeStatus = routingPoiCtx.getString(R.string.tour_route_deleted_msg, selectedTour) }, currentLocationLatLon = locationLatLon, mapCenterLatLon = mapCenterLatLon, availableWaypoints = waypoints, - onDismiss = { showRoutePlanner = false } + onDismiss = { showRoutePlanner = false }, + // v2.7.19 — Manuelles Zeichnen aus dem Tourplaner öffnen. + // Schließt den Tourplaner und öffnet den TourverlaufEditorSheet. + // Die Funktion bleibt vollständig erhalten; der Einstieg ist jetzt + // logisch im Tourplaner verankert statt als separater FAB. + onOpenDrawMode = { + showRoutePlanner = false + showTourverlaufEditor = true + }, + // v2.7.20 — Zwischenpunkt direkt per Karten-Tap setzen. + // Schließt den Sheet und aktiviert AddViaPoint-TapMode. + // Wenn kein Start/Ziel vorhanden: Modus trotzdem aktivieren — + // der erste Tap wird dann als Start gewertet (via intuitivem Fallback). + onStartAddViaOnMap = { + showRoutePlanner = false + tapMode = TapModeMl.AddViaPoint + }, + // v2.7.23 — Route Planner Flow Fix: Planlinie/Route direkt als Tourverlauf übernehmen. + // Wird aufgerufen wenn Nutzer den neuen "Als Tourverlauf übernehmen" Button drückt. + // Funktioniert unabhängig davon, ob bereits eine gespeicherte Route existiert: + // - Wenn routeLine >= 2 (OSRM erfolgt): berechnete Route als OSRM-TourRoute speichern. + // - Sonst wenn routePlanline >= 2 (plan komplett): Planlinie als PLANLINE-TourRoute speichern. + // - Setzt routeStatus mit klar lesbarem Feedback. + // Waypoint-Preservation-Invariante bleibt gewahrt: nur KEY_TOUR_ROUTES wird geschrieben. + onAdoptAsTourRoute = { + val ml = mapLibreMap + val planline = routePlanline + val line = routeLine + when { + line.size >= 2 -> { + // OSRM-Route verfügbar: als OSRM-TourRoute speichern + val route = buildTourRouteFromState( + plan = routePlan, + routeLine = line, + routePlanline = planline, + distanceMeters = lastComputedDistanceMeters, + durationSeconds = lastComputedDurationSeconds, + endpoint = lastComputedEndpoint, + planlineSourceLabel = routingPoiCtx.getString(R.string.tour_route_source_planline) + ) + if (route != null) { + viewModel.saveTourRouteFor(selectedTour, route) + viewModel.setCurrentSessionRoute(selectedTour, route) + routeStatus = routingPoiCtx.getString(R.string.route_planner_adopted_route) + } + } + planline.size >= 2 -> { + // Planlinie (Luftlinie) als PLANLINE-TourRoute speichern + val route = buildTourRouteFromState( + plan = routePlan, + routeLine = emptyList(), + routePlanline = planline, + distanceMeters = null, + durationSeconds = null, + endpoint = routingPoiCtx.getString(R.string.tour_route_source_planline), + planlineSourceLabel = routingPoiCtx.getString(R.string.tour_route_source_planline) + ) + if (route != null) { + viewModel.saveTourRouteFor(selectedTour, route) + viewModel.setCurrentSessionRoute(selectedTour, route) + routeStatus = routingPoiCtx.getString(R.string.route_planner_adopted_planline) + // Kamera auf Planlinienmitte zentrieren + if (ml != null) { + val mid = planline[planline.size / 2] + ml.animateCamera(CameraUpdateFactory.newLatLngZoom(mid, 13.0)) + } + } + } + else -> { + routeStatus = routingPoiCtx.getString(R.string.route_planner_adopt_none) + } + } + } ) } @@ -1558,7 +2351,8 @@ fun ExplorerScreenMapLibre( tourName = selectedTour, isActive = true ) - viewModel.upsert(newWp) + // v2.7.7 — POI als Wegpunkt im neutralen Kontext → Spontane Tour + viewModel.upsertFromNeutralExplorer(newWp) }, onAddPoiToStoryboard = { poi -> val newWp = Waypoint( @@ -1571,7 +2365,8 @@ fun ExplorerScreenMapLibre( tourName = selectedTour, isActive = true ) - viewModel.upsert(newWp) + // v2.7.7 — POI zu Storyboard im neutralen Kontext → Spontane Tour + viewModel.upsertFromNeutralExplorer(newWp) showStoryboardSheet = true }, onComputeRoute = { @@ -1597,6 +2392,17 @@ fun ExplorerScreenMapLibre( de.waypointaudio.util.OsrmRoutingClient.formatDistance(result.distanceMeters), de.waypointaudio.util.OsrmRoutingClient.formatDuration(result.durationSeconds) ) + // v2.6.2 — Auch Legacy-POI-Route im ViewModel sichern. + val legacyRoute = de.waypointaudio.data.TourRoute( + polyline = result.polyline.map { + de.waypointaudio.data.TourRoutePoint(it.first, it.second) + }, + source = de.waypointaudio.data.RouteSourceKind.OSRM, + endpoint = endpoint, + distanceMeters = result.distanceMeters, + durationSeconds = result.durationSeconds + ) + viewModel.setCurrentSessionRoute(selectedTour, legacyRoute) }.onFailure { routeLine = emptyList() routeStatus = routingPoiCtx.getString(R.string.routing_compute_error) @@ -1813,7 +2619,7 @@ fun ExplorerScreenMapLibre( MapModeSegmentedHeader( current = currentMode, onChange = onModeChange, - subtitle = selectedTour, + subtitle = displayTourLabel, contentColor = MaterialTheme.colorScheme.onSurface ) } else { @@ -1829,7 +2635,7 @@ fun ExplorerScreenMapLibre( Text(stringResource(R.string.explorer_title)) } Text( - text = selectedTour, + text = displayTourLabel, style = MaterialTheme.typography.labelSmall, color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.65f) ) @@ -1932,33 +2738,44 @@ fun ExplorerScreenMapLibre( ) { Icon(Icons.Filled.MovieFilter, contentDescription = stringResource(R.string.explorer_storyboard_open)) } - SmallFloatingActionButton( - onClick = { showRoutePlanner = true }, - containerColor = neutralFabContainer, - contentColor = neutralFabContent - ) { - Icon(Icons.Filled.AltRoute, contentDescription = stringResource(R.string.route_planner_open)) - } - // v2.5.3 — FAB für „Route zeichnen". Toggle: an = Tap setzt - // stille Routenpunkte, aus = normale Karten-Tap-Logik. + // v2.7.16 — Route planen FAB (wiederhergestellt): direkter Einstieg in RoutePlannerSheet. + // Start/Ziel/Via, Planlinie, Online-Routing. War in v2.7.15 fälschlich entfernt worden. SmallFloatingActionButton( onClick = { - manualRouteMode = !manualRouteMode - tapMode = if (manualRouteMode) TapModeMl.DrawRoutePoint - else TapModeMl.None + showRoutePlanner = !showRoutePlanner }, - containerColor = if (manualRouteMode) + containerColor = if (showRoutePlanner) + MaterialTheme.colorScheme.secondaryContainer + else + neutralFabContainer, + contentColor = if (showRoutePlanner) + MaterialTheme.colorScheme.onSecondaryContainer + else + neutralFabContent + ) { + Icon( + Icons.Filled.AltRoute, + contentDescription = stringResource(R.string.route_planner_fab_hint) + ) + } + // v2.7.0 — Tourverlauf-Editor-FAB: manuelles Setzen/Zeichnen von Verlaufspunkten. + // Öffnet das TourverlaufEditorSheet; aktiver Tipp-Modus färbt den FAB ein. + SmallFloatingActionButton( + onClick = { + showTourverlaufEditor = !showTourverlaufEditor + }, + containerColor = if (showTourverlaufEditor || manualRouteMode) MaterialTheme.colorScheme.tertiaryContainer else neutralFabContainer, - contentColor = if (manualRouteMode) + contentColor = if (showTourverlaufEditor || manualRouteMode) MaterialTheme.colorScheme.onTertiaryContainer else neutralFabContent ) { Icon( Icons.Filled.Edit, - contentDescription = stringResource(R.string.explorer_mode_draw_route) + contentDescription = stringResource(R.string.tourverlauf_editor_fab_hint) ) } if (isRecording) { @@ -2061,18 +2878,36 @@ fun ExplorerScreenMapLibre( MapBaseStyle.CLASSIC, MapBaseStyle.SATELLITE -> Style.Builder().fromJson(buildClassicOsmStyleJson()) else -> Style.Builder().fromUri("https://tiles.openfreemap.org/styles/positron") } + val initialTargetStyle = layerState.baseStyle + val initialTargetTilt = if (initialTargetStyle == MapBaseStyle.CITY_3D || + initialTargetStyle == MapBaseStyle.TERRAIN_3D || + initialTargetStyle == MapBaseStyle.PERSPECTIVE) + mapStyleSettings.perspectiveTilt else 0 ml.setStyle(initialStyleBuilder) { loadedStyle -> // 3D-Extrusion für CITY_3D beim initialen Laden. - if (layerState.baseStyle == MapBaseStyle.CITY_3D || - layerState.baseStyle == MapBaseStyle.TERRAIN_3D || - layerState.baseStyle == MapBaseStyle.PERSPECTIVE) { + if (initialTargetStyle == MapBaseStyle.CITY_3D || + initialTargetStyle == MapBaseStyle.TERRAIN_3D || + initialTargetStyle == MapBaseStyle.PERSPECTIVE) { try { addBuildingExtrusionIfAvailable(loadedStyle) } catch (_: Exception) {} val pos2 = ml.cameraPosition ml.cameraPosition = CameraPosition.Builder(pos2) .tilt(mapStyleSettings.perspectiveTilt.toDouble().coerceIn(0.0, 60.0)) .build() } + // v2.7.28 — appliedBaseStyle + appliedPerspectiveTilt nach + // initialem Style-Load setzen. Markiert, welcher Stil + // tatsächlich geladen wurde, damit der Style-Change-LaunchedEffect + // einen etwaigen gespeicherten Stil (z.B. OUTDOOR) erneut + // anwenden kann, falls dieser vor styleReady=true in + // layerState gesetzt wurde. + appliedBaseStyle = initialTargetStyle + appliedPerspectiveTilt = initialTargetTilt styleReady = true + // v2.7.12 — Initialen Overlay-Draw ohne Nutzerinteraktion + // auslösen: Nonce erhöhen, damit Overlay-LaunchedEffect + // garantiert neu feuert, auch wenn waypoints/styleReady + // sich nicht verändert haben. + overlayRenderNonce++ } // Klick-Handler für Wegpunkt-/Track-Marker. ml.setOnMarkerClickListener { m -> @@ -2167,6 +3002,36 @@ fun ExplorerScreenMapLibre( selectedRoutePointIndex = null true } + is TapModeMl.AddViaPoint -> { + // v2.7.20 — Zwischenpunkt/Route-formen per Karten-Tap. + // Kein Audio-Waypoint, kein manualRoutePoint. + // Intuitiver Fallback: + // - Kein Start: erster Tap = Start + // - Kein Ziel: zweiter Tap = Ziel + // - Start+Ziel vorhanden: Tap = Via/Zwischenpunkt + val coordLabel = "%.4f,%.4f".format(java.util.Locale.US, p.latitude, p.longitude) + val newStop = RouteStop( + latitude = p.latitude, + longitude = p.longitude, + label = coordLabel, + source = RouteStopSource.MAP_CENTER + ) + val newPlan = when { + routePlan.start == null -> + routePlan.copy(start = newStop.copy(label = "Start $coordLabel")) + routePlan.destination == null -> + routePlan.copy(destination = newStop.copy(label = "Ziel $coordLabel")) + else -> + routePlan.copy(via = routePlan.via + newStop.copy(label = "Zwischenpunkt $coordLabel")) + } + routePlan = newPlan + routeLine = emptyList() + if (routeStatus != null) routeStatus = null + viewModel.setCurrentSessionPlan(selectedTour, newPlan) + // Modus aktiv lassen (weitere Zwischenpunkte/Start/Ziel setzbar) + // Nutzer kann per Cancel-Chip abbrechen. + true + } TapModeMl.None -> false } } @@ -2185,21 +3050,16 @@ fun ExplorerScreenMapLibre( showEditDialog = true true } - // Folow-disable bei manueller Bewegung: + // v2.7.26 — Follow-disable bei manueller Bewegung: + // Jede bewusste Wischgeste schaltet Standort folgen sofort aus, + // unabhängig davon wie weit die Kamera vom Live-Standort entfernt ist. + // Der Nutzer soll die Karte stabil halten können, ohne dass Follow + // bei der nächsten GPS-Meldung wieder zentriert. ml.addOnMoveListener(object : org.maplibre.android.maps.MapLibreMap.OnMoveListener { override fun onMoveBegin(detector: org.maplibre.android.gestures.MoveGestureDetector) { + // Jede Wischgeste deaktiviert Follow sofort. if (followLocation) { - val lat = lastLat; val lng = lastLng - if (lat != null && lng != null) { - val tgt = ml.cameraPosition.target - if (tgt != null) { - val dLat = kotlin.math.abs(tgt.latitude - lat) - val dLng = kotlin.math.abs(tgt.longitude - lng) - if (dLat > 0.00040 || dLng > 0.00040) { - followLocation = false - } - } - } + followLocation = false } } override fun onMove(detector: org.maplibre.android.gestures.MoveGestureDetector) {} @@ -2296,6 +3156,8 @@ fun ExplorerScreenMapLibre( stringResource(R.string.explorer_mode_draw_route_active) is TapModeMl.MoveRoutePoint -> stringResource(R.string.explorer_route_point_move_active) + is TapModeMl.AddViaPoint -> + stringResource(R.string.explorer_tap_add_via_active) TapModeMl.None -> null } if (tapHint != null) { @@ -2314,6 +3176,7 @@ fun ExplorerScreenMapLibre( val statusIcon = when { isRecording -> Icons.Filled.FiberManualRecord activeDraft != null -> Icons.Filled.Timeline + manualRouteMode || manualRoutePoints.isNotEmpty() -> Icons.Filled.Edit else -> Icons.Filled.Place } val statusText = when { @@ -2324,12 +3187,17 @@ fun ExplorerScreenMapLibre( R.string.explorer_status_draft_compact, activeDraft.markedCount, activeDraft.pointCount ) + // v2.7.0 — Verlaufspunkte im Status anzeigen, wenn Editor aktiv/Punkte gesetzt. + manualRouteMode || manualRoutePoints.isNotEmpty() -> stringResource( + R.string.tourverlauf_editor_point_count, manualRoutePoints.size + ) else -> stringResource( R.string.explorer_status_compact, waypoints.size ) } val statusTint = when { isRecording -> MaterialTheme.colorScheme.error + manualRouteMode || manualRoutePoints.isNotEmpty() -> MaterialTheme.colorScheme.tertiary else -> MaterialTheme.colorScheme.primary } Icon( @@ -2406,6 +3274,8 @@ fun ExplorerScreenMapLibre( }, onShowRoutingInfo = { showRoutingInfo = true }, onShowRoutePlanner = { showRoutePlanner = true }, + // v2.7.15 — Tourverlauf-Editor-Einstieg vom Layer-Panel aus + onShowTourverlaufEditor = { showTourverlaufEditor = true }, // v2.5.45 — Auto-Load-Toggle poiAutoLoadEnabled = autoPoiLoadEnabled, onPoiAutoLoadChange = { enabled -> @@ -2687,7 +3557,8 @@ fun ExplorerScreenMapLibre( name = poi.displayName, tourName = selectedTour, ) - viewModel.upsert(newWp) + // v2.7.7 — Explorer-POI im neutralen Kontext → Spontane Tour + viewModel.upsertFromNeutralExplorer(newWp) selectedExplorerPoi = null explorerPoiSnackbar = "\"${poi.displayName}\" als Wegpunkt angelegt." }) { @@ -2725,12 +3596,18 @@ private sealed interface TapModeMl { data object DrawRoutePoint : TapModeMl /** v2.5.3 — Verschieben eines Routenpunkts an Index [index] der Polyline. */ data class MoveRoutePoint(val index: Int) : TapModeMl + /** v2.7.20 — Zwischenpunkt-Modus: Tippen fügt Via-Stop zur RoutePlan hinzu. */ + data object AddViaPoint : TapModeMl } // ─────────────────────────────────────────────────────────────────────────── // Overlay-Renderer (MapLibre Annotation API) // ─────────────────────────────────────────────────────────────────────────── +// v2.7.30 — clearAllAnnotationsCaches: planlinePolylines + routeStopMarkers ergänzt. +// In v2.7.29 fehlten diese beiden Listen: Nach setStyle() blieben veraltete +// planlinePolylines-Referenzen im Cache, die beim nächsten Render zu +// removePolyline()-Aufrufen auf ungültigen Objekten führten (stiløer Fehler). private fun clearAllAnnotationsCaches( waypointMarkers: MutableList, waypointMarkerIdToWaypoint: MutableMap, @@ -2743,6 +3620,9 @@ private fun clearAllAnnotationsCaches( manualRoutePolylines: MutableList? = null, manualRouteMarkers: MutableList? = null, manualRouteMarkerIdToIndex: MutableMap? = null, + // v2.7.30 — Neu: planlinePolylines + routeStopMarkers ergänzt + planlinePolylines: MutableList? = null, + routeStopMarkers: MutableList? = null, ) { waypointMarkers.clear() waypointMarkerIdToWaypoint.clear() @@ -2755,6 +3635,8 @@ private fun clearAllAnnotationsCaches( manualRoutePolylines?.clear() manualRouteMarkers?.clear() manualRouteMarkerIdToIndex?.clear() + planlinePolylines?.clear() // v2.7.30 + routeStopMarkers?.clear() // v2.7.30 } @Suppress("LongParameterList") @@ -2804,24 +3686,13 @@ private fun drawExplorerOverlaysMapLibre( val iconFactory = IconFactory.getInstance(context) // Track-Polyline (Halo + Linie). + // v2.7.30 — runCatching: Verhindert silent-Crash wenn AnnotationManager noch nicht bereit. if (track.size >= 2) { val pts = track.map { LatLng(it.latitude, it.longitude) } - val halo = ml.addPolyline( - PolylineOptions() - .addAll(pts) - .color(0xFFFFFFFF.toInt()) - .width(10f) - .alpha(0.85f) - ) - val line = ml.addPolyline( - PolylineOptions() - .addAll(pts) - .color(trackArgb) - .width(6f) - .alpha(1.0f) - ) - trackPolylines += halo - trackPolylines += line + runCatching { ml.addPolyline(PolylineOptions().addAll(pts).color(0xFFFFFFFF.toInt()).width(10f).alpha(0.85f)) } + .getOrNull()?.let { trackPolylines += it } + runCatching { ml.addPolyline(PolylineOptions().addAll(pts).color(trackArgb).width(6f).alpha(1.0f)) } + .getOrNull()?.let { trackPolylines += it } } if (track.isNotEmpty()) { @@ -2841,11 +3712,10 @@ private fun drawExplorerOverlaysMapLibre( else -> trackArgb } val bm = trackPointBitmap(sizePx, color, isSelected) - val marker = ml.addMarker( - MarkerOptions() - .position(gp) - .icon(iconFactory.fromBitmap(bm)) - ) + // v2.7.30 — runCatching: Track-Marker robust gegen AnnotationManager-Nicht-Bereitschaft. + val marker = runCatching { + ml.addMarker(MarkerOptions().position(gp).icon(iconFactory.fromBitmap(bm))) + }.getOrNull() ?: return@forEachIndexed trackMarkers += marker trackMarkerIdToIndex[marker.id] = idx } @@ -2898,38 +3768,41 @@ private fun drawExplorerOverlaysMapLibre( de.waypointaudio.util.AudioLengthBucket.MEDIUM -> 5f else -> 4f } - val halo = ml.addPolyline( - PolylineOptions() - .addAll(segPoints) - .color(0xFFFFFFFF.toInt()) - .width(w + 3f) - .alpha(0.85f) - ) - val line = ml.addPolyline( - PolylineOptions() - .addAll(segPoints) - .color(color) - .width(w) - .alpha(0.95f) - ) - audioLinePolylines += halo - audioLinePolylines += line + // v2.7.30 — runCatching um addPolyline: Audio-Linien robust. + runCatching { ml.addPolyline(PolylineOptions().addAll(segPoints).color(0xFFFFFFFF.toInt()).width(w + 3f).alpha(0.85f)) } + .getOrNull()?.let { audioLinePolylines += it } + runCatching { ml.addPolyline(PolylineOptions().addAll(segPoints).color(color).width(w).alpha(0.95f)) } + .getOrNull()?.let { audioLinePolylines += it } } } + // v2.7.31 — Waypoint Marker Visibility Fix: Render in 2 separate passes. + // Pass 1: Radius polygons only. Polygons must be added BEFORE markers so that + // MapLibre's legacy annotation manager places them on a lower Z layer. + // In v2.7.30 the mixed loop worked for the polygon but addMarker() could fail + // silently (AnnotationManager not fully ready) leaving only the radius visible. + if (showRadius) { + for (wp in waypoints) { + if (wp.radiusMeters > 0) { + runCatching { + ml.addPolygon( + PolygonOptions() + .addAll(circleLatLng(wp.latitude, wp.longitude, wp.radiusMeters.toDouble(), 48)) + .fillColor((primaryArgb and 0x00FFFFFF) or 0x40000000) + .strokeColor(primaryArgb) + .alpha(0.5f) + ) + }.getOrNull()?.let { waypointRadiusPolygons += it } + } + } + } + + // Pass 2: Waypoint markers — drawn AFTER all polygons so they render on top. + // v2.7.31: runCatching preserved; if addMarker() fails (AnnotationManager not + // ready), the marker is skipped here and the 650ms dedicated marker-retry + // LaunchedEffect will trigger a re-draw via overlayRenderNonce++. for (wp in waypoints) { val gp = LatLng(wp.latitude, wp.longitude) - if (showRadius && wp.radiusMeters > 0) { - val circle = ml.addPolygon( - PolygonOptions() - .addAll(circleLatLng(wp.latitude, wp.longitude, wp.radiusMeters.toDouble(), 48)) - .fillColor((primaryArgb and 0x00FFFFFF) or 0x40000000) - .strokeColor(primaryArgb) - .alpha(0.5f) - ) - waypointRadiusPolygons += circle - } - val isSelected = wp.id == selectedId val durationMs = if (showAudioLength) { audioDurationsMs[wp.soundUri] ?: 0L @@ -2939,24 +3812,28 @@ private fun drawExplorerOverlaysMapLibre( } else { waypointDotPlain(primaryArgb, density, isSelected) } - val marker = ml.addMarker( - MarkerOptions() - .position(gp) - .title(wp.name.ifBlank { "Wegpunkt" }) - .icon(iconFactory.fromBitmap(bm)) - ) + val marker = runCatching { + ml.addMarker( + MarkerOptions() + .position(gp) + .title(wp.name.ifBlank { "Wegpunkt" }) + .icon(iconFactory.fromBitmap(bm)) + ) + }.getOrNull() ?: continue waypointMarkers += marker waypointMarkerIdToWaypoint[marker.id] = wp } if (searchPin != null) { val pinBm = makeSearchPinBitmapShared(96) - val pinMarker = ml.addMarker( - MarkerOptions() - .position(searchPin) - .icon(iconFactory.fromBitmap(pinBm)) - ) - searchPinMarkerRef(pinMarker) + // v2.7.30 — runCatching: Search-Pin robust. + runCatching { + ml.addMarker( + MarkerOptions() + .position(searchPin) + .icon(iconFactory.fromBitmap(pinBm)) + ) + }.getOrNull()?.let { searchPinMarkerRef(it) } } } diff --git a/app/src/main/kotlin/de/waypointaudio/ui/HomeScreen.kt b/app/src/main/kotlin/de/waypointaudio/ui/HomeScreen.kt index 1913300..dfc285e 100644 --- a/app/src/main/kotlin/de/waypointaudio/ui/HomeScreen.kt +++ b/app/src/main/kotlin/de/waypointaudio/ui/HomeScreen.kt @@ -74,7 +74,9 @@ fun HomeScreen( val store = remember(context) { HomeModulesSettingsStore(context.applicationContext) } val scope = rememberCoroutineScope() - val tourList by viewModel.tourList.collectAsState() + // v2.7.5 — visibleTourList blendet Standard-Tour (Blueprint) aus, sobald echte + // Touren vorhanden sind. Intern bleibt Standard-Tour als Fallback erhalten. + val tourList by viewModel.visibleTourList.collectAsState() val waypoints by viewModel.waypoints.collectAsState() val tourRoutes by viewModel.tourRoutes.collectAsState() val tourCovers by viewModel.tourCovers.collectAsState() @@ -240,16 +242,24 @@ fun HomeScreen( ) Spacer(Modifier.width(8.dp)) Text( - text = "Touren", + text = "Meine Touren", style = MaterialTheme.typography.titleMedium, fontWeight = FontWeight.SemiBold, modifier = Modifier.weight(1f) ) - Text( - text = "${tourList.size}", - style = MaterialTheme.typography.labelMedium, - color = MaterialTheme.colorScheme.onSurfaceVariant - ) + Box( + modifier = Modifier + .clip(RoundedCornerShape(50)) + .background(MaterialTheme.colorScheme.primary.copy(alpha = 0.15f)) + .padding(horizontal = 10.dp, vertical = 3.dp) + ) { + Text( + text = "${tourList.size}", + style = MaterialTheme.typography.labelMedium, + fontWeight = FontWeight.Medium, + color = MaterialTheme.colorScheme.primary + ) + } } // ─ Cover-Grid ─ @@ -522,8 +532,14 @@ private fun TourCoverCard( } } - // Text-Block - Column(modifier = Modifier.padding(12.dp)) { + // Text-Block — feste Struktur (Titel, eine Metazeile, Chips-Zeile), + // damit alle Karten gleich hoch wirken und nichts abgeschnitten wird. + val isEmptyTour = waypointCount == 0 + Column( + modifier = Modifier + .padding(12.dp) + .heightIn(min = 86.dp) + ) { Text( text = tourName, style = MaterialTheme.typography.titleSmall, @@ -536,26 +552,34 @@ private fun TourCoverCard( Text( text = subtitleFor(waypointCount, hasRoute), style = MaterialTheme.typography.labelSmall, - color = MaterialTheme.colorScheme.onSurfaceVariant, + color = if (isEmptyTour) MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.7f) + else MaterialTheme.colorScheme.onSurfaceVariant, maxLines = 1, overflow = TextOverflow.Ellipsis ) - Spacer(Modifier.height(8.dp)) + Spacer(Modifier.weight(1f)) Row( horizontalArrangement = Arrangement.spacedBy(6.dp), verticalAlignment = Alignment.CenterVertically ) { - Badge( - icon = Icons.Filled.PinDrop, - text = "$waypointCount" - ) - if (hasRoute) { + if (isEmptyTour) { Badge( - icon = Icons.Filled.Route, - text = "Route", - tint = MaterialTheme.colorScheme.tertiary + icon = Icons.Filled.Add, + text = "Noch leer", + tint = MaterialTheme.colorScheme.onSurfaceVariant + ) + } else { + Badge( + icon = Icons.Filled.PinDrop, + text = "$waypointCount" ) } + Badge( + icon = Icons.Filled.Route, + text = if (hasRoute) "Route" else "Keine Route", + tint = if (hasRoute) MaterialTheme.colorScheme.tertiary + else MaterialTheme.colorScheme.onSurfaceVariant + ) } } } @@ -710,10 +734,13 @@ private fun PttModuleCard( // Wiederverwendung der bestehenden LivePttCard (volle Funktion: Mic-Permission, // Aufnahmen, Geräte). Die Card wird hier nur in einen Wrapper gehüllt, der // Abstände/Form an die übrige Bibliothek-Oberfläche anpasst. + // v2.7.35 — Live/PTT optisch zurückgenommen: an den Bibliothek-Rand + // eingerückt und vertikal kompakter, damit es die Touren nicht dominiert. + // KEINE Verhaltensänderung an der LivePttCard selbst. LivePttCard( pttManager = pttManager, onOpenRecordings = onOpenRecordings, - modifier = Modifier.padding(horizontal = 0.dp, vertical = 6.dp) + modifier = Modifier.padding(horizontal = 12.dp, vertical = 4.dp) ) } @@ -869,11 +896,11 @@ private fun ToggleRow( /* ───────────────────────────── Helpers ─────────────────────────────────── */ -private fun subtitleFor(waypointCount: Int, hasRoute: Boolean): String { - val parts = mutableListOf() - parts.add("$waypointCount Wegpunkte") - if (hasRoute) parts.add("Route gespeichert") - return parts.joinToString(" · ") +private fun subtitleFor(waypointCount: Int, hasRoute: Boolean): String = when { + waypointCount == 0 -> "Noch leer · füge Wegpunkte hinzu" + waypointCount == 1 -> if (hasRoute) "1 Wegpunkt · Route geplant" else "1 Wegpunkt" + else -> if (hasRoute) "$waypointCount Wegpunkte · Route geplant" + else "$waypointCount Wegpunkte" } private fun atmoSourceLabel(type: MusicSourceType): String = when (type) { diff --git a/app/src/main/kotlin/de/waypointaudio/ui/MapLayerPanel.kt b/app/src/main/kotlin/de/waypointaudio/ui/MapLayerPanel.kt index 2143754..2da7b81 100644 --- a/app/src/main/kotlin/de/waypointaudio/ui/MapLayerPanel.kt +++ b/app/src/main/kotlin/de/waypointaudio/ui/MapLayerPanel.kt @@ -17,6 +17,7 @@ import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.verticalScroll import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.AltRoute +import androidx.compose.material.icons.filled.Edit import androidx.compose.material.icons.filled.Explore import androidx.compose.material.icons.filled.DarkMode import androidx.compose.material.icons.filled.GpsFixed @@ -106,6 +107,8 @@ fun MapLayerFab( onPerspectiveTiltChange: (Int) -> Unit = {}, onShowRoutingInfo: () -> Unit = {}, onShowRoutePlanner: () -> Unit = {}, + // v2.7.15 — Unified Tourverlauf-Editor-Einstieg (zusammengeführt aus RoutePlanner + Editor) + onShowTourverlaufEditor: () -> Unit = {}, // v2.5.45 — Auto-POI-Load-Toggle poiAutoLoadEnabled: Boolean = true, onPoiAutoLoadChange: (Boolean) -> Unit = {}, @@ -546,10 +549,11 @@ fun MapLayerFab( } } - // v2.4.2 — Routenplaner-Eintrag im Layer-Panel. + // v2.7.16 — Route planen (wiederhergestellt): direkter Einstieg in RoutePlannerSheet. + // Start/Ziel/Via, Planlinie, Online-Routing. War in v2.7.15 fälschlich entfernt. Surface( shape = RoundedCornerShape(12.dp), - color = MaterialTheme.colorScheme.primaryContainer.copy(alpha = 0.55f), + color = MaterialTheme.colorScheme.secondaryContainer.copy(alpha = 0.65f), modifier = Modifier.fillMaxWidth() ) { Row( @@ -560,23 +564,63 @@ fun MapLayerFab( Icons.Filled.AltRoute, contentDescription = null, modifier = Modifier.size(20.dp), + tint = MaterialTheme.colorScheme.onSecondaryContainer + ) + Spacer(Modifier.width(10.dp)) + Column(modifier = Modifier.weight(1f)) { + Text( + stringResource(R.string.route_planner_menu_title), + style = MaterialTheme.typography.titleSmall, + color = MaterialTheme.colorScheme.onSecondaryContainer + ) + Text( + stringResource(R.string.route_planner_menu_subtitle), + style = MaterialTheme.typography.labelSmall, + color = MaterialTheme.colorScheme.onSecondaryContainer.copy(alpha = 0.78f) + ) + } + TextButton(onClick = { + showSheet = false + onShowRoutePlanner() + }) { + Text(stringResource(R.string.route_planner_menu_open)) + } + } + } + // v2.7.15 / v2.7.16 — Tourverlauf bearbeiten: manuelles Zeichnen/Setzen von Verlaufspunkten. + Surface( + shape = RoundedCornerShape(12.dp), + color = MaterialTheme.colorScheme.primaryContainer.copy(alpha = 0.55f), + modifier = Modifier.fillMaxWidth() + ) { + Row( + modifier = Modifier.padding(horizontal = 12.dp, vertical = 10.dp), + verticalAlignment = Alignment.CenterVertically + ) { + Icon( + Icons.Filled.Edit, + contentDescription = null, + modifier = Modifier.size(20.dp), tint = MaterialTheme.colorScheme.onPrimaryContainer ) Spacer(Modifier.width(10.dp)) Column(modifier = Modifier.weight(1f)) { Text( - stringResource(R.string.route_planner_open_short), + stringResource(R.string.tourverlauf_menu_title), style = MaterialTheme.typography.titleSmall, color = MaterialTheme.colorScheme.onPrimaryContainer ) Text( - stringResource(R.string.route_planner_subtitle), + stringResource(R.string.tourverlauf_menu_subtitle), style = MaterialTheme.typography.labelSmall, color = MaterialTheme.colorScheme.onPrimaryContainer.copy(alpha = 0.78f) ) } - TextButton(onClick = onShowRoutePlanner) { - Text(stringResource(R.string.route_planner_open)) + TextButton(onClick = { + showSheet = false + onShowTourverlaufEditor() + }) { + Text(stringResource(R.string.tourverlauf_menu_open)) } } } diff --git a/app/src/main/kotlin/de/waypointaudio/ui/MapScreen.kt b/app/src/main/kotlin/de/waypointaudio/ui/MapScreen.kt index f52fa80..6e306e9 100644 --- a/app/src/main/kotlin/de/waypointaudio/ui/MapScreen.kt +++ b/app/src/main/kotlin/de/waypointaudio/ui/MapScreen.kt @@ -130,7 +130,8 @@ fun MapScreen( ) { val allWaypoints by viewModel.waypoints.collectAsState() val selectedTour by viewModel.selectedTour.collectAsState() - val tourList by viewModel.tourList.collectAsState() + // v2.7.5 — visibleTourList: Standard-Tour in Kartenansicht-Kontext ausblenden + val tourList by viewModel.visibleTourList.collectAsState() val tourDefaults by viewModel.tourDefaults.collectAsState() val currentTrack by viewModel.currentTrack.collectAsState() val isRecording by viewModel.isRecording.collectAsState() diff --git a/app/src/main/kotlin/de/waypointaudio/ui/PttRecordingDialogs.kt b/app/src/main/kotlin/de/waypointaudio/ui/PttRecordingDialogs.kt index b0c72ee..21be38d 100644 --- a/app/src/main/kotlin/de/waypointaudio/ui/PttRecordingDialogs.kt +++ b/app/src/main/kotlin/de/waypointaudio/ui/PttRecordingDialogs.kt @@ -455,7 +455,8 @@ fun WaypointChooserDialog( onDismiss: () -> Unit ) { val context = LocalContext.current - val tourList by viewModel.tourList.collectAsState() + // v2.7.5 — visibleTourList: Standard-Tour wird aus PTT-Ziel-Dropdown ausgeblendet + val tourList by viewModel.visibleTourList.collectAsState() val selectedTour by viewModel.selectedTour.collectAsState() val allWaypoints by viewModel.waypoints.collectAsState() val currentLocation by viewModel.currentLocation.collectAsState() diff --git a/app/src/main/kotlin/de/waypointaudio/ui/RoutePlannerSheet.kt b/app/src/main/kotlin/de/waypointaudio/ui/RoutePlannerSheet.kt index 85e9c19..8e903e8 100644 --- a/app/src/main/kotlin/de/waypointaudio/ui/RoutePlannerSheet.kt +++ b/app/src/main/kotlin/de/waypointaudio/ui/RoutePlannerSheet.kt @@ -1,5 +1,8 @@ package de.waypointaudio.ui +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.animation.expandVertically +import androidx.compose.animation.shrinkVertically import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column @@ -31,19 +34,26 @@ import androidx.compose.material.icons.filled.DirectionsWalk import androidx.compose.material.icons.filled.Close import androidx.compose.material.icons.filled.Delete import androidx.compose.material.icons.filled.Edit +import androidx.compose.material.icons.filled.ExpandLess +import androidx.compose.material.icons.filled.ExpandMore import androidx.compose.material.icons.filled.Flag +import androidx.compose.material.icons.filled.Gesture import androidx.compose.material.icons.filled.MovieFilter import androidx.compose.material.icons.filled.MyLocation import androidx.compose.material.icons.filled.Place import androidx.compose.material.icons.filled.PinDrop +import androidx.compose.material.icons.filled.Route import androidx.compose.material.icons.filled.Save +import androidx.compose.material.icons.filled.Science import androidx.compose.material.icons.filled.Search import androidx.compose.material.icons.filled.Settings import androidx.compose.material.icons.filled.Timeline import androidx.compose.material3.AlertDialog import androidx.compose.material3.AssistChip +import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.AssistChipDefaults import androidx.compose.material3.Button +import androidx.compose.material3.OutlinedButton import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.ExperimentalMaterial3Api @@ -66,6 +76,7 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import de.waypointaudio.R @@ -76,19 +87,34 @@ import de.waypointaudio.util.OverpassPoiClient import kotlinx.coroutines.launch /** - * v2.4.2 — Explorer-Routenplaner als ModalBottomSheet. + * v2.4.2 — Explorer-Tourverlauf-Planer als ModalBottomSheet. + * v2.7.17 — Route-first Explorer: Umbenennung Verlaufspunkte -> Tourpunkte, + * UI-Sprache: „Route planen", „Tourpunkt", „Audio hinzufügen". Keine Logik-Änderungen. + * v2.6.0 — Umbenannt von Routenplaner auf Tourverlauf. Begriffe angepasst. + * v2.6.1 — Layout-Fix: Endpoint-Karte neu strukturiert. Langer URL-Text + * bricht nicht mehr vertikal in einzelne Buchstaben um. „Konfigurieren"- + * Button in eigene Zeile unterhalb der URL verschoben; URL zeigt jetzt + * maxLines=1 mit horizontalem Ellipsis. Keine Logik-Änderungen. + * v2.7.24 — Tourverlauf UX Polish: + * - Freie Linie als PRIMÄRES Werkzeug oben, visuell hervorgehoben (kein "Fallback"-Label). + * - Route über Punkte formen als zweite klare Option. + * - Experimentelles Online-Routing in einklappbarem Bereich nachrangig platziert. + * - Sticky Action Bar vereinfacht: "Als Tourverlauf übernehmen" primär. + * - Keine Logik-Änderungen, kein Regressionsrisiko. * * Bewusste Gestaltungsentscheidungen: * - Eigenständige Komponente, keine Vermischung mit dem alten * [RoutingPoiSheet] (v2.3.1 Info-Sheet bleibt für Backward-Compat erhalten). * - State (Plan, Status, Route-Polyline) wird vom Aufrufer * ([ExplorerScreenMapLibre]) gehalten — der Sheet ist reine UI. - * - Stops können aus mehreren Quellen kommen (Standort, Kartenmitte, + * - Verlaufspunkte können aus mehreren Quellen kommen (Standort, Kartenmitte, * Wegpunkt, POI, manuell, Suche) — siehe [RouteStopSource]. - * - „Route berechnen“ wird **nur auf Nutzerklick** ausgelöst (sparsam, - * kein Polling, keine Auto-Berechnung). - * - Wenn kein Endpunkt konfiguriert ist: klare Meldung + Planlinien- - * Fallback (Luftlinie zwischen den Stops, ohne Netzwerk). + * - „Route berechnen" ist optional/sekundär; wird **nur auf Nutzerklick** + * ausgelöst. Die Planlinie genügt für den Tourverlauf. + * - Online-Routing (OSRM) bleibt funktional, wird aber als optional + * und experimentell eingestuft — kein Ausbau geplant. + * - Wenn kein Endpunkt konfiguriert: klare Meldung + Planlinie + * (Luftlinie zwischen den Verlaufspunkten, ohne Netzwerk). */ @OptIn(ExperimentalMaterial3Api::class) @Composable @@ -121,6 +147,22 @@ fun RoutePlannerSheet( mapCenterLatLon: Pair?, availableWaypoints: List, onDismiss: () -> Unit, + // v2.7.19 — Manuelles Zeichnen als integriertes Bearbeitungs-Werkzeug des Tourplaners. + // Öffnet den TourverlaufEditorSheet direkt aus dem Tourplaner heraus, ohne + // separaten FAB/Einstieg. Der Tourplaner ist der zentrale Ort für Route planen/bearbeiten. + onOpenDrawMode: () -> Unit = {}, + // v2.7.20 — Zwischenpunkt per Karten-Tap setzen. + // Schließt den Sheet und aktiviert den AddViaPoint-TapMode auf der Karte. + // Ist null/kein Kontext verfügbar, wenn Start und Ziel nicht gesetzt sind — der + // Callback wird im Sheet trotzdem immer angeboten, der Status-Hinweis übernimmt + // die Führung. + onStartAddViaOnMap: () -> Unit = {}, + // v2.7.23 — Planlinie/Route direkt als Tourverlauf übernehmen. + // Speichert die aktuell sichtbare Planlinie (oder berechnete Route) dauerhaft + // als Tourverlauf. Aktiviert wenn Start+Ziel gesetzt (hasPlanline oder hasRoute). + // Dies ist der primäre Weg, um eine Planlinie in den persistierten Tourverlauf + // zu überführen — unabhängig davon, ob bereits eine gespeicherte Route existiert. + onAdoptAsTourRoute: () -> Unit = {}, ) { val sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true) val ctx = LocalContext.current @@ -133,6 +175,9 @@ fun RoutePlannerSheet( var showManualPicker by remember { mutableStateOf(null) } var showSaveTourDialog by remember { mutableStateOf(false) } + // v2.7.24 — Online-Routing-Bereich standardmäßig eingeklappt (experimentell/nachrangig) + var onlineRoutingExpanded by remember { mutableStateOf(false) } + fun applyStopToRole(role: RouteStopRole, stop: RouteStop) { val next = when (role) { RouteStopRole.START -> plan.copy(start = stop) @@ -147,11 +192,8 @@ fun RoutePlannerSheet( // werden die Aktionsbuttons unter der Gestenleiste/Soft-Keys // versteckt — siehe Nutzerfeedback 2026-05-23). // - Der Hauptinhalt scrollt vertikal, damit auch auf kleinen - // Displays alle Bereiche (Endpunkt, Start, Via, Ziel, Anzeige, - // Status) erreichbar bleiben. - // - Primäre Aktionen ('Route berechnen' / 'Planlinie') liegen jetzt - // in einer Sticky Bottom Action Bar oberhalb der scrollbaren - // Detailansicht, sodass sie nie aus dem Sichtfeld rutschen. + // Displays alle Bereiche erreichbar bleiben. + // - Primäre Aktionen liegen jetzt in einer Sticky Bottom Action Bar. ModalBottomSheet( onDismissRequest = onDismiss, sheetState = sheetState @@ -168,7 +210,8 @@ fun RoutePlannerSheet( .padding(horizontal = 16.dp, vertical = 4.dp), verticalAlignment = Alignment.CenterVertically ) { - Icon(Icons.Filled.AltRoute, contentDescription = null, modifier = Modifier.size(22.dp)) + Icon(Icons.Filled.Timeline, contentDescription = null, modifier = Modifier.size(22.dp), + tint = MaterialTheme.colorScheme.primary) Spacer(Modifier.width(8.dp)) Column(modifier = Modifier.weight(1f)) { Text( @@ -178,7 +221,9 @@ fun RoutePlannerSheet( Text( stringResource(R.string.route_planner_subtitle), style = MaterialTheme.typography.labelSmall, - color = MaterialTheme.colorScheme.onSurfaceVariant + color = MaterialTheme.colorScheme.onSurfaceVariant, + maxLines = 2, + overflow = TextOverflow.Ellipsis ) } IconButton(onClick = onDismiss) { @@ -196,251 +241,284 @@ fun RoutePlannerSheet( .padding(top = 4.dp, bottom = 8.dp), verticalArrangement = Arrangement.spacedBy(10.dp) ) { - // Endpoint-Status-Karte - // v2.4.4: bei fehlendem Endpunkt erscheint hier ein klar - // sichtbarer Quick-Setup-Button („OSRM-Demo nutzen") plus - // Hinweis, dass dieser nur für Tests gedacht ist und Limits hat. - // Damit muss der Nutzer nicht erst in ein zweites Sheet wechseln, - // um Routing nutzen zu können. - Surface( - shape = RoundedCornerShape(12.dp), - color = if (routingEndpoint.isBlank()) - MaterialTheme.colorScheme.errorContainer.copy(alpha = 0.45f) - else MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.55f), - modifier = Modifier.fillMaxWidth() - ) { - Column( - modifier = Modifier.padding(horizontal = 12.dp, vertical = 10.dp), - verticalArrangement = Arrangement.spacedBy(6.dp) + + // ═══════════════════════════════════════════════════════════ + // PRIMÄR: Tourverlauf frei zeichnen + // Das erste und robusteste Werkzeug — kein Netz, kein Server. + // v2.7.24: Visuell als Primär-Card hervorgehoben (primary-Farbe), + // kein "Fallback"-Label. + // ═══════════════════════════════════════════════════════════ + Surface( + shape = RoundedCornerShape(14.dp), + color = MaterialTheme.colorScheme.primaryContainer.copy(alpha = 0.55f), + modifier = Modifier.fillMaxWidth() ) { - Row(verticalAlignment = Alignment.CenterVertically) { - Icon( - if (routingEndpoint.isBlank()) Icons.Filled.Settings else Icons.Filled.AltRoute, - contentDescription = null, - modifier = Modifier.size(18.dp) + Column( + modifier = Modifier.padding(horizontal = 14.dp, vertical = 12.dp), + verticalArrangement = Arrangement.spacedBy(8.dp) + ) { + Row(verticalAlignment = Alignment.CenterVertically) { + Icon( + Icons.Filled.Gesture, + contentDescription = null, + modifier = Modifier.size(20.dp), + tint = MaterialTheme.colorScheme.primary + ) + Spacer(Modifier.width(8.dp)) + Column(modifier = Modifier.weight(1f)) { + Text( + stringResource(R.string.route_planner_draw_section_title), + style = MaterialTheme.typography.titleSmall, + fontWeight = FontWeight.SemiBold, + color = MaterialTheme.colorScheme.onSurface + ) + Text( + "Werkzeug 1", + style = MaterialTheme.typography.labelSmall, + color = MaterialTheme.colorScheme.primary + ) + } + } + Text( + stringResource(R.string.route_planner_draw_section_hint), + style = MaterialTheme.typography.bodySmall, + color = MaterialTheme.colorScheme.onSurfaceVariant ) - Spacer(Modifier.width(10.dp)) - Column(modifier = Modifier.weight(1f)) { - Text( - if (routingEndpoint.isBlank()) - stringResource(R.string.route_planner_endpoint_not_configured) - else routingEndpoint, - style = MaterialTheme.typography.labelMedium, - maxLines = 2, - overflow = TextOverflow.Ellipsis - ) - Text( - stringResource(R.string.route_planner_attribution), - style = MaterialTheme.typography.labelSmall, - color = MaterialTheme.colorScheme.onSurfaceVariant - ) - } - TextButton(onClick = onConfigureEndpoint) { - Text(stringResource(R.string.route_planner_endpoint_configure)) - } - } - if (routingEndpoint.isBlank()) { Button( - onClick = onUseDemoEndpoint, + onClick = { onOpenDrawMode() }, colors = ButtonDefaults.buttonColors( containerColor = MaterialTheme.colorScheme.primary, contentColor = MaterialTheme.colorScheme.onPrimary ), modifier = Modifier.fillMaxWidth() ) { - Icon(Icons.Filled.AltRoute, contentDescription = null, modifier = Modifier.size(16.dp)) + Icon( + Icons.Filled.Gesture, + contentDescription = null, + modifier = Modifier.size(16.dp) + ) Spacer(Modifier.width(6.dp)) - Text(stringResource(R.string.route_planner_use_demo_endpoint)) + Text(stringResource(R.string.route_planner_draw_open_editor)) + } + } + } + + HorizontalDivider( + modifier = Modifier.padding(vertical = 2.dp), + color = MaterialTheme.colorScheme.outlineVariant.copy(alpha = 0.4f) + ) + + // ═══════════════════════════════════════════════════════════ + // SEKUNDÄR: Route über Punkte formen + // Start / Via / Ziel — Verlauf über definierte Punkte steuern. + // ═══════════════════════════════════════════════════════════ + Surface( + shape = RoundedCornerShape(14.dp), + color = MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.5f), + modifier = Modifier.fillMaxWidth() + ) { + Column( + modifier = Modifier.padding(horizontal = 14.dp, vertical = 12.dp), + verticalArrangement = Arrangement.spacedBy(8.dp) + ) { + Row(verticalAlignment = Alignment.CenterVertically) { + Icon( + Icons.Filled.Route, + contentDescription = null, + modifier = Modifier.size(20.dp), + tint = MaterialTheme.colorScheme.secondary + ) + Spacer(Modifier.width(8.dp)) + Column(modifier = Modifier.weight(1f)) { + Text( + stringResource(R.string.route_planner_section_via), + style = MaterialTheme.typography.titleSmall, + fontWeight = FontWeight.Medium, + color = MaterialTheme.colorScheme.onSurface + ) + Text( + "Werkzeug 2", + style = MaterialTheme.typography.labelSmall, + color = MaterialTheme.colorScheme.secondary + ) + } } Text( - stringResource(R.string.route_planner_use_demo_endpoint_hint), + stringResource(R.string.route_planner_shaping_section_hint), + style = MaterialTheme.typography.bodySmall, + color = MaterialTheme.colorScheme.onSurfaceVariant + ) + + // START + Text( + stringResource(R.string.route_planner_section_start), + style = MaterialTheme.typography.labelMedium, + color = MaterialTheme.colorScheme.onSurfaceVariant + ) + RouteStopRow( + stop = plan.start, + roleLabel = stringResource(R.string.route_planner_role_start), + roleIcon = Icons.Filled.PinDrop, + placeholder = stringResource(R.string.route_planner_empty_start), + onChoose = { pickerForRole = RouteStopRole.START }, + onClear = { onPlanChange(plan.copy(start = null)) }, + showOrderControls = false + ) + + // VIA-Liste + Text( + stringResource(R.string.route_planner_section_via_points), + style = MaterialTheme.typography.labelMedium, + color = MaterialTheme.colorScheme.onSurfaceVariant + ) + if (plan.via.isEmpty()) { + Text( + stringResource(R.string.route_planner_empty_via), + style = MaterialTheme.typography.bodySmall, + color = MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.8f) + ) + } else { + Column(verticalArrangement = Arrangement.spacedBy(6.dp)) { + plan.via.forEachIndexed { idx, via -> + RouteStopRow( + stop = via, + roleLabel = stringResource(R.string.route_planner_role_via, idx + 1), + roleIcon = Icons.Filled.AddLocationAlt, + placeholder = "", + onChoose = null, + onClear = { + val list = plan.via.toMutableList() + list.removeAt(idx) + onPlanChange(plan.copy(via = list)) + }, + showOrderControls = true, + isFirst = idx == 0, + isLast = idx == plan.via.lastIndex, + onMoveUp = { + if (idx > 0) { + val list = plan.via.toMutableList() + val tmp = list[idx - 1]; list[idx - 1] = list[idx]; list[idx] = tmp + onPlanChange(plan.copy(via = list)) + } + }, + onMoveDown = { + if (idx < plan.via.lastIndex) { + val list = plan.via.toMutableList() + val tmp = list[idx + 1]; list[idx + 1] = list[idx]; list[idx] = tmp + onPlanChange(plan.copy(via = list)) + } + } + ) + } + } + } + // Aktionen: Punkt via Sheet-Picker oder Karten-Tap + Row( + horizontalArrangement = Arrangement.spacedBy(4.dp), + modifier = Modifier.fillMaxWidth() + ) { + TextButton( + onClick = { pickerForRole = RouteStopRole.VIA }, + modifier = Modifier.weight(1f) + ) { + Icon(Icons.Filled.AddLocationAlt, contentDescription = null, modifier = Modifier.size(16.dp)) + Spacer(Modifier.width(6.dp)) + Text(stringResource(R.string.route_planner_add_via)) + } + // v2.7.20 — Punkt auf Karte tippen + OutlinedButton( + onClick = { onStartAddViaOnMap() }, + modifier = Modifier.weight(1f) + ) { + Icon(Icons.Filled.PinDrop, contentDescription = null, modifier = Modifier.size(14.dp)) + Spacer(Modifier.width(4.dp)) + Text( + stringResource(R.string.route_planner_shaping_activate), + style = MaterialTheme.typography.labelSmall, + maxLines = 2 + ) + } + } + + // ZIEL + Text( + stringResource(R.string.route_planner_section_destination), + style = MaterialTheme.typography.labelMedium, + color = MaterialTheme.colorScheme.onSurfaceVariant + ) + RouteStopRow( + stop = plan.destination, + roleLabel = stringResource(R.string.route_planner_role_destination), + roleIcon = Icons.Filled.Flag, + placeholder = stringResource(R.string.route_planner_empty_destination), + onChoose = { pickerForRole = RouteStopRole.DESTINATION }, + onClear = { onPlanChange(plan.copy(destination = null)) }, + showOrderControls = false + ) + } + } + + // Layer-Anzeigeschalter + Surface( + shape = RoundedCornerShape(12.dp), + color = MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.5f), + modifier = Modifier.fillMaxWidth() + ) { + Column( + modifier = Modifier.padding(horizontal = 12.dp, vertical = 10.dp), + verticalArrangement = Arrangement.spacedBy(4.dp) + ) { + Row(verticalAlignment = Alignment.CenterVertically) { + Icon(Icons.Filled.Timeline, contentDescription = null, modifier = Modifier.size(16.dp)) + Spacer(Modifier.width(8.dp)) + Text( + stringResource(R.string.route_planner_layer_section), + modifier = Modifier.weight(1f), + style = MaterialTheme.typography.labelMedium + ) + androidx.compose.material3.Switch( + checked = showRouteOverlay, + onCheckedChange = onShowRouteOverlayChange + ) + } + Text( + stringResource(R.string.route_planner_layer_hint), style = MaterialTheme.typography.labelSmall, color = MaterialTheme.colorScheme.onSurfaceVariant ) - } else if (routingEndpoint.contains("router.project-osrm.org")) { - Text( - stringResource(R.string.routing_endpoint_demo_warning), - style = MaterialTheme.typography.labelSmall, - color = MaterialTheme.colorScheme.error - ) - } - } - } - - // v2.5.2 — Routingprofil (Auto/Fahrrad/Fußgänger) - // - // Kompakter Segment-Switch im Look des v2.5.1-Designs: - // - Drei gleichwertige Pillen, aktive Auswahl mit Primary-Farbe. - // - Ändert den Plan-State (RoutePlan.profile) – die Route selbst - // wird beim Wechsel verworfen, damit die Karte nicht eine - // Auto-Route für eine Fußgänger-Auswahl zeigt. - Text( - stringResource(R.string.route_planner_profile_section), - style = MaterialTheme.typography.labelMedium, - color = MaterialTheme.colorScheme.onSurfaceVariant - ) - RoutingProfileSelector( - selected = plan.profile, - onSelectedChange = { newProfile -> - if (newProfile != plan.profile) { - onPlanChange(plan.copy(profile = newProfile)) - } - } - ) - Text( - stringResource(R.string.route_planner_profile_hint), - style = MaterialTheme.typography.labelSmall, - color = MaterialTheme.colorScheme.onSurfaceVariant - ) - - // START - Text( - stringResource(R.string.route_planner_section_start), - style = MaterialTheme.typography.labelMedium, - color = MaterialTheme.colorScheme.onSurfaceVariant - ) - RouteStopRow( - stop = plan.start, - roleLabel = stringResource(R.string.route_planner_role_start), - roleIcon = Icons.Filled.PinDrop, - placeholder = stringResource(R.string.route_planner_empty_start), - onChoose = { pickerForRole = RouteStopRole.START }, - onClear = { onPlanChange(plan.copy(start = null)) }, - showOrderControls = false - ) - - // VIA-Liste - Text( - stringResource(R.string.route_planner_section_via), - style = MaterialTheme.typography.labelMedium, - color = MaterialTheme.colorScheme.onSurfaceVariant - ) - if (plan.via.isEmpty()) { - Text( - stringResource(R.string.route_planner_empty_via), - style = MaterialTheme.typography.bodySmall, - color = MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.8f) - ) - } else { - Column(verticalArrangement = Arrangement.spacedBy(6.dp)) { - plan.via.forEachIndexed { idx, via -> - RouteStopRow( - stop = via, - roleLabel = stringResource(R.string.route_planner_role_via, idx + 1), - roleIcon = Icons.Filled.AddLocationAlt, - placeholder = "", - onChoose = null, - onClear = { - val list = plan.via.toMutableList() - list.removeAt(idx) - onPlanChange(plan.copy(via = list)) - }, - showOrderControls = true, - isFirst = idx == 0, - isLast = idx == plan.via.lastIndex, - onMoveUp = { - if (idx > 0) { - val list = plan.via.toMutableList() - val tmp = list[idx - 1]; list[idx - 1] = list[idx]; list[idx] = tmp - onPlanChange(plan.copy(via = list)) - } - }, - onMoveDown = { - if (idx < plan.via.lastIndex) { - val list = plan.via.toMutableList() - val tmp = list[idx + 1]; list[idx + 1] = list[idx]; list[idx] = tmp - onPlanChange(plan.copy(via = list)) - } + // v2.4.5: Legende spiegelt das tatsächliche Verhalten — + // berechnete Route ODER Planlinie, nicht beides parallel. + Row( + horizontalArrangement = Arrangement.spacedBy(8.dp), + modifier = Modifier.padding(top = 4.dp) + ) { + if (hasRoute) { + LineLegendChip( + color = 0xFF1976D2.toInt(), + label = stringResource(R.string.route_planner_legend_route), + solid = true + ) + } else if (hasPlanline) { + LineLegendChip( + color = 0xFFFF9800.toInt(), + label = stringResource(R.string.route_planner_legend_planline), + solid = false + ) + } else { + LineLegendChip( + color = 0xFF1976D2.toInt(), + label = stringResource(R.string.route_planner_legend_route), + solid = true + ) + LineLegendChip( + color = 0xFFFF9800.toInt(), + label = stringResource(R.string.route_planner_legend_planline), + solid = false + ) } - ) - } - } - } - TextButton(onClick = { pickerForRole = RouteStopRole.VIA }) { - Icon(Icons.Filled.AddLocationAlt, contentDescription = null, modifier = Modifier.size(16.dp)) - Spacer(Modifier.width(6.dp)) - Text(stringResource(R.string.route_planner_add_via)) - } - - // ZIEL - Text( - stringResource(R.string.route_planner_section_destination), - style = MaterialTheme.typography.labelMedium, - color = MaterialTheme.colorScheme.onSurfaceVariant - ) - RouteStopRow( - stop = plan.destination, - roleLabel = stringResource(R.string.route_planner_role_destination), - roleIcon = Icons.Filled.Flag, - placeholder = stringResource(R.string.route_planner_empty_destination), - onChoose = { pickerForRole = RouteStopRole.DESTINATION }, - onClear = { onPlanChange(plan.copy(destination = null)) }, - showOrderControls = false - ) - - // Layer-Anzeigeschalter - Surface( - shape = RoundedCornerShape(12.dp), - color = MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.5f), - modifier = Modifier.fillMaxWidth() - ) { - Column( - modifier = Modifier.padding(horizontal = 12.dp, vertical = 10.dp), - verticalArrangement = Arrangement.spacedBy(4.dp) - ) { - Row(verticalAlignment = Alignment.CenterVertically) { - Icon(Icons.Filled.Timeline, contentDescription = null, modifier = Modifier.size(16.dp)) - Spacer(Modifier.width(8.dp)) - Text( - stringResource(R.string.route_planner_layer_section), - modifier = Modifier.weight(1f), - style = MaterialTheme.typography.labelMedium - ) - androidx.compose.material3.Switch( - checked = showRouteOverlay, - onCheckedChange = onShowRouteOverlayChange - ) - } - Text( - stringResource(R.string.route_planner_layer_hint), - style = MaterialTheme.typography.labelSmall, - color = MaterialTheme.colorScheme.onSurfaceVariant - ) - // v2.4.5: Legende spiegelt das tatsächliche Verhalten — - // berechnete Route ODER Planlinie, nicht beides parallel. - // Solange noch keine Route/Planlinie existiert, zeigen wir - // beide Chips zur Orientierung. - Row( - horizontalArrangement = Arrangement.spacedBy(8.dp), - modifier = Modifier.padding(top = 4.dp) - ) { - if (hasRoute) { - LineLegendChip( - color = 0xFF1976D2.toInt(), - label = stringResource(R.string.route_planner_legend_route), - solid = true - ) - } else if (hasPlanline) { - LineLegendChip( - color = 0xFFFF9800.toInt(), - label = stringResource(R.string.route_planner_legend_planline), - solid = false - ) - } else { - LineLegendChip( - color = 0xFF1976D2.toInt(), - label = stringResource(R.string.route_planner_legend_route), - solid = true - ) - LineLegendChip( - color = 0xFFFF9800.toInt(), - label = stringResource(R.string.route_planner_legend_planline), - solid = false - ) } } } - } if (routeStatus != null) { Text( @@ -456,11 +534,199 @@ fun RoutePlannerSheet( ) } + // ═══════════════════════════════════════════════════════════ + // EXPERIMENTELL / NACHRANGIG: Online-Routing + // v2.7.24: Eingeklappter Bereich — abhängig von externem Dienst, + // offline nicht nötig. Routing-Endpunkt, Profil und + // "Route berechnen" sind hier gebündelt. + // ═══════════════════════════════════════════════════════════ + HorizontalDivider( + modifier = Modifier.padding(vertical = 2.dp), + color = MaterialTheme.colorScheme.outlineVariant.copy(alpha = 0.4f) + ) + Surface( + shape = RoundedCornerShape(12.dp), + color = MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.35f), + modifier = Modifier.fillMaxWidth() + ) { + Column(modifier = Modifier.fillMaxWidth()) { + // Header-Zeile: klickbar zum Auf-/Zuklappen + TextButton( + onClick = { onlineRoutingExpanded = !onlineRoutingExpanded }, + modifier = Modifier.fillMaxWidth() + ) { + Icon( + Icons.Filled.Science, + contentDescription = null, + modifier = Modifier.size(16.dp), + tint = MaterialTheme.colorScheme.onSurfaceVariant + ) + Spacer(Modifier.width(8.dp)) + Column(modifier = Modifier.weight(1f)) { + Text( + stringResource(R.string.route_planner_online_routing_section), + style = MaterialTheme.typography.labelMedium, + color = MaterialTheme.colorScheme.onSurface + ) + Text( + stringResource(R.string.route_planner_online_routing_hint), + style = MaterialTheme.typography.labelSmall, + color = MaterialTheme.colorScheme.onSurfaceVariant, + maxLines = 2, + overflow = TextOverflow.Ellipsis + ) + } + Icon( + if (onlineRoutingExpanded) Icons.Filled.ExpandLess else Icons.Filled.ExpandMore, + contentDescription = null, + modifier = Modifier.size(18.dp), + tint = MaterialTheme.colorScheme.onSurfaceVariant + ) + } + + // Aufklappbarer Inhalt + AnimatedVisibility( + visible = onlineRoutingExpanded, + enter = expandVertically(), + exit = shrinkVertically() + ) { + Column( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 12.dp) + .padding(bottom = 10.dp), + verticalArrangement = Arrangement.spacedBy(8.dp) + ) { + // Endpoint-Status-Karte + // v2.4.4: bei fehlendem Endpunkt erscheint hier ein klar + // sichtbarer Quick-Setup-Button plus Hinweis. + // v2.6.1 Layout-Fix: URL-Text und Konfigurieren-Button getrennt. + Surface( + shape = RoundedCornerShape(10.dp), + color = if (routingEndpoint.isBlank()) + MaterialTheme.colorScheme.errorContainer.copy(alpha = 0.45f) + else MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.55f), + modifier = Modifier.fillMaxWidth() + ) { + Column( + modifier = Modifier.padding(horizontal = 12.dp, vertical = 10.dp), + verticalArrangement = Arrangement.spacedBy(6.dp) + ) { + Row( + verticalAlignment = Alignment.CenterVertically, + modifier = Modifier.fillMaxWidth() + ) { + Icon( + if (routingEndpoint.isBlank()) Icons.Filled.Settings else Icons.Filled.AltRoute, + contentDescription = null, + modifier = Modifier.size(18.dp) + ) + Spacer(Modifier.width(8.dp)) + // v2.6.1: weight(1f) stellt sicher, dass der Text die + // volle verbleibende Breite nutzt und nie auf 0 gedrückt wird. + Column(modifier = Modifier.weight(1f)) { + Text( + if (routingEndpoint.isBlank()) + stringResource(R.string.route_planner_endpoint_not_configured) + else routingEndpoint, + style = MaterialTheme.typography.labelMedium, + maxLines = 1, + overflow = TextOverflow.Ellipsis + ) + Text( + stringResource(R.string.route_planner_attribution), + style = MaterialTheme.typography.labelSmall, + color = MaterialTheme.colorScheme.onSurfaceVariant, + maxLines = 2, + overflow = TextOverflow.Ellipsis + ) + } + } + // v2.6.1: Konfigurieren-Button in eigene Zeile + TextButton( + onClick = onConfigureEndpoint, + modifier = Modifier.fillMaxWidth() + ) { + Icon(Icons.Filled.Settings, contentDescription = null, modifier = Modifier.size(14.dp)) + Spacer(Modifier.width(6.dp)) + Text( + stringResource(R.string.route_planner_endpoint_configure), + maxLines = 1, + overflow = TextOverflow.Ellipsis + ) + } + if (routingEndpoint.isBlank()) { + Button( + onClick = onUseDemoEndpoint, + colors = ButtonDefaults.buttonColors( + containerColor = MaterialTheme.colorScheme.primary, + contentColor = MaterialTheme.colorScheme.onPrimary + ), + modifier = Modifier.fillMaxWidth() + ) { + Icon(Icons.Filled.AltRoute, contentDescription = null, modifier = Modifier.size(16.dp)) + Spacer(Modifier.width(6.dp)) + Text(stringResource(R.string.route_planner_use_demo_endpoint)) + } + Text( + stringResource(R.string.route_planner_use_demo_endpoint_hint), + style = MaterialTheme.typography.labelSmall, + color = MaterialTheme.colorScheme.onSurfaceVariant + ) + } else if (routingEndpoint.contains("router.project-osrm.org")) { + Text( + stringResource(R.string.routing_endpoint_demo_warning), + style = MaterialTheme.typography.labelSmall, + color = MaterialTheme.colorScheme.error + ) + } + } + } + + // v2.5.2 — Routingprofil (Auto/Fahrrad/Fußgänger) + Text( + stringResource(R.string.route_planner_profile_section), + style = MaterialTheme.typography.labelMedium, + color = MaterialTheme.colorScheme.onSurfaceVariant + ) + RoutingProfileSelector( + selected = plan.profile, + onSelectedChange = { newProfile -> + if (newProfile != plan.profile) { + onPlanChange(plan.copy(profile = newProfile)) + } + } + ) + Text( + stringResource(R.string.route_planner_profile_hint), + style = MaterialTheme.typography.labelSmall, + color = MaterialTheme.colorScheme.onSurfaceVariant + ) + + // "Online-Route berechnen" — jetzt im experimentellen Bereich + OutlinedButton( + onClick = onComputeRoute, + enabled = plan.isComplete && !isLoading, + modifier = Modifier.fillMaxWidth() + ) { + if (isLoading) { + CircularProgressIndicator( + modifier = Modifier.size(14.dp), + strokeWidth = 2.dp, + ) + Spacer(Modifier.width(8.dp)) + } else { + Icon(Icons.Filled.AltRoute, contentDescription = null, modifier = Modifier.size(16.dp)) + Spacer(Modifier.width(6.dp)) + } + Text(stringResource(R.string.route_planner_compute)) + } + } + } + } + } + // v2.4.6 — Tourrouten-Status & Aktionen - // - Zeigt klar an, ob eine Tourroute für die aktuelle Tour - // gespeichert ist (inkl. Distanz/Dauer/Aktualisierungszeit). - // - Aktionen: Speichern (wenn berechnete Route da, aber noch keine - // gespeicherte), Ersetzen (überschreibt explizit) und Löschen. if (currentTourName != null) { TourRouteStatusCard( tourName = currentTourName, @@ -473,9 +739,7 @@ fun RoutePlannerSheet( ) } - // Storyboard/Tour-Integration — bleibt im Scroll-Bereich, - // weil sie nur bei vollständigem Plan erscheint und kein - // Primärziel jedes Aufrufs ist. + // Storyboard/Tour-Integration if (plan.isComplete) { Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) { Button( @@ -505,9 +769,7 @@ fun RoutePlannerSheet( } } - // Footer-Aktionen (Löschen / Schließen) — bleiben im - // Scroll-Bereich, damit die Sticky-Bar unten nur die - // Hauptaktionen 'Route berechnen' / 'Planlinie' enthält. + // Footer-Aktionen (Löschen / Schließen) Row(modifier = Modifier.fillMaxWidth()) { TextButton(onClick = onClear, modifier = Modifier.weight(1f)) { Icon(Icons.Filled.Delete, contentDescription = null, modifier = Modifier.size(16.dp)) @@ -520,9 +782,10 @@ fun RoutePlannerSheet( } } // Ende Scroll-Column - // Sticky Bottom Action Bar — liegt oberhalb der Systemnavigation - // (navigationBarsPadding) und enthält die primären Aktionen, - // damit sie nie aus dem Sichtfeld rutschen. + // Sticky Bottom Action Bar + // v2.7.24: Vereinfacht — primäre Aktion "Als Tourverlauf übernehmen", + // sekundär "Verlaufslinie anzeigen". Online-Route berechnen ist jetzt + // im experimentellen Bereich oben und erscheint nicht mehr hier. Surface( color = MaterialTheme.colorScheme.surface, tonalElevation = 6.dp, @@ -535,47 +798,37 @@ fun RoutePlannerSheet( .padding(horizontal = 16.dp, vertical = 10.dp), verticalArrangement = Arrangement.spacedBy(6.dp) ) { - Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) { - // v2.4.4: Button bleibt klickbar, sobald der Plan - // vollständig ist — auch wenn kein Endpunkt konfiguriert - // ist. Der Aufrufer (Explorer) zeigt in diesem Fall - // einen klaren Status mit Verweis auf den Demo-Quick- - // Setup oder die Endpunkt-Einrichtung. So vermeiden wir - // den toten/grauen Button ohne sichtbaren Grund. - Button( - onClick = onComputeRoute, - enabled = plan.isComplete && !isLoading, - colors = ButtonDefaults.buttonColors( - containerColor = MaterialTheme.colorScheme.primary, - contentColor = MaterialTheme.colorScheme.onPrimary - ), - modifier = Modifier.weight(1f) - ) { - if (isLoading) { - CircularProgressIndicator( - modifier = Modifier.size(14.dp), - strokeWidth = 2.dp, - color = MaterialTheme.colorScheme.onPrimary - ) - Spacer(Modifier.width(8.dp)) - } else { - Icon(Icons.Filled.AltRoute, contentDescription = null, modifier = Modifier.size(16.dp)) - Spacer(Modifier.width(6.dp)) - } - Text(stringResource(R.string.route_planner_compute)) - } - Button( + // v2.7.23: "Als Tourverlauf übernehmen" als primäre Aktion. + // v2.7.24: Alleinige primäre Aktion in der Sticky Bar. + Button( + onClick = onAdoptAsTourRoute, + enabled = (hasPlanline || hasRoute) && !isLoading, + colors = ButtonDefaults.buttonColors( + containerColor = MaterialTheme.colorScheme.primary, + contentColor = MaterialTheme.colorScheme.onPrimary + ), + modifier = Modifier.fillMaxWidth() + ) { + Icon(Icons.Filled.Save, contentDescription = null, modifier = Modifier.size(16.dp)) + Spacer(Modifier.width(6.dp)) + Text( + stringResource(R.string.route_planner_adopt_planline), + style = MaterialTheme.typography.labelMedium + ) + } + // Sekundär: Verlaufslinie anzeigen (nur wenn Start+Ziel gesetzt) + if (plan.isComplete) { + OutlinedButton( onClick = onShowPlanline, - enabled = plan.isComplete && !isLoading, - colors = ButtonDefaults.buttonColors( - containerColor = MaterialTheme.colorScheme.tertiaryContainer, - contentColor = MaterialTheme.colorScheme.onTertiaryContainer - ), - modifier = Modifier.weight(1f) + enabled = !isLoading, + modifier = Modifier.fillMaxWidth() ) { Icon(Icons.Filled.Timeline, contentDescription = null, modifier = Modifier.size(16.dp)) - Spacer(Modifier.width(6.dp)) - Text(stringResource(R.string.route_planner_planline)) + Spacer(Modifier.width(4.dp)) + Text( + stringResource(R.string.route_planner_planline), + style = MaterialTheme.typography.labelMedium + ) } } } @@ -1150,7 +1403,7 @@ private fun SaveAsTourDialog( }, confirmButton = { TextButton( - onClick = { onConfirm(name.trim().ifBlank { "Routenentwurf" }) } + onClick = { onConfirm(name.trim().ifBlank { "Tourentwurf" }) } ) { Icon(Icons.Filled.Save, contentDescription = null, modifier = Modifier.size(16.dp)) Spacer(Modifier.width(6.dp)) @@ -1174,6 +1427,9 @@ private fun SaveAsTourDialog( * - Ersetzen: überschreibt eine vorhandene gespeicherte Route mit der * aktuell sichtbaren (verhindert versehentliches Überschreiben). * - Löschen: entfernt die gespeicherte Tourroute. + * + * v2.6.1: tour_route_source-Text (enthält ggf. lange URL) mit maxLines=1 + * und Ellipsis, damit langer Endpunkt-Name nicht umbricht. */ @Composable private fun TourRouteStatusCard( @@ -1233,11 +1489,13 @@ private fun TourRouteStatusCard( color = MaterialTheme.colorScheme.onSurfaceVariant ) if (savedRoute.endpoint.isNotBlank()) { + // v2.6.1: maxLines=1 + Ellipsis — langer Endpunkt-URL + // bricht nicht mehr vertikal um Text( stringResource(R.string.tour_route_source, savedRoute.endpoint), style = MaterialTheme.typography.labelSmall, color = MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.75f), - maxLines = 2, + maxLines = 1, overflow = TextOverflow.Ellipsis ) } @@ -1289,12 +1547,19 @@ private fun TourRouteStatusCard( } } } + // v2.7.23 — Zeige Hinweis wann Speichern möglich ist if (!hasUsableLive && savedRoute == null) { Text( stringResource(R.string.tour_route_hint_compute_first), style = MaterialTheme.typography.labelSmall, color = MaterialTheme.colorScheme.onSurfaceVariant ) + } else if (hasUsableLive && savedRoute == null) { + Text( + stringResource(R.string.route_planner_adopt_planline_hint), + style = MaterialTheme.typography.labelSmall, + color = MaterialTheme.colorScheme.primary.copy(alpha = 0.85f) + ) } } } diff --git a/app/src/main/kotlin/de/waypointaudio/ui/TourverlaufEditorSheet.kt b/app/src/main/kotlin/de/waypointaudio/ui/TourverlaufEditorSheet.kt new file mode 100644 index 0000000..4d1d44a --- /dev/null +++ b/app/src/main/kotlin/de/waypointaudio/ui/TourverlaufEditorSheet.kt @@ -0,0 +1,456 @@ +package de.waypointaudio.ui + +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.animation.expandVertically +import androidx.compose.animation.fadeIn +import androidx.compose.animation.fadeOut +import androidx.compose.animation.shrinkVertically +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.navigationBarsPadding +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.foundation.verticalScroll +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.AddLocation +import androidx.compose.material.icons.filled.AltRoute +import androidx.compose.material.icons.filled.CheckCircle +import androidx.compose.material.icons.filled.Close +import androidx.compose.material.icons.filled.Delete +import androidx.compose.material.icons.filled.Edit +import androidx.compose.material.icons.filled.ExpandLess +import androidx.compose.material.icons.filled.ExpandMore +import androidx.compose.material.icons.filled.HeadsetMic +import androidx.compose.material.icons.filled.Info +import androidx.compose.material.icons.filled.PinDrop +import androidx.compose.material.icons.filled.TouchApp +import androidx.compose.material.icons.filled.Undo +import androidx.compose.material3.AlertDialog +import androidx.compose.material3.Button +import androidx.compose.material3.ButtonDefaults +import androidx.compose.material3.Card +import androidx.compose.material3.CardDefaults +import androidx.compose.material3.Divider +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.ModalBottomSheet +import androidx.compose.material3.OutlinedButton +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.material3.TextButton +import androidx.compose.material3.rememberModalBottomSheetState +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.dp +import de.waypointaudio.R +import org.maplibre.android.geometry.LatLng + +/** + * v2.7.0 — Tourverlauf-Editor-BottomSheet. + * v2.7.17 — Route-first: Sprache: Routenpunkte statt Verlaufspunkte, + * "Audio hier hinzufügen" statt technischem "Als Audio-Wegpunkt erstellen". + * Keine Logik-Änderungen. + * + * Klarer Bearbeitungsmodus für den Tourverlauf: + * - Verlaufspunkte direkt auf der Karte setzen (Tipp-Modus oder Kartenmitte) + * - Punkte per Dialog entfernen/verschieben (bestehende Logik) + * - "Als Audio-Wegpunkt erstellen" für einen Verlaufspunkt + * - Letzten Punkt entfernen / Verlauf komplett löschen + * - Einklappbarer "Optional: Online-Route berechnen"-Abschnitt (→ öffnet RoutePlannerSheet) + * + * Wiederverwendete Bausteine: + * - manualRoutePoints / TourRoute / RouteSourceKind.MANUAL (Persistenz, Auto-Save) + * - WaypointEditDialog (Audio-Wegpunkt erstellen) + * - RoutePlannerSheet (Online-Routing, optional/einklappbar) + * + * Keine Regressionen: Logik, Playback, Backup, Lizenz, GPS-Aufzeichnung unverändert. + */ +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun TourverlaufEditorSheet( + /** Aktuelle Verlaufspunkte (manualRoutePoints). */ + routePoints: List, + /** True wenn Tipp-Modus für neuen Punkt aktiv. */ + isDrawing: Boolean, + /** Name der ausgewählten Tour (für Kontext-Labels). */ + tourName: String, + /** Letzter bekannter Verlaufspunkt, aus dem ein Audio-Wegpunkt erstellt werden soll. */ + lastSelectedPointIndex: Int?, + + // Callbacks + /** Punkt an der Kartenmitte hinzufügen. */ + onAddCenterPoint: () -> Unit, + /** Tipp-Modus zum Setzen per Kartentap umschalten. */ + onToggleDrawMode: () -> Unit, + /** Letzten Punkt entfernen. */ + onRemoveLast: () -> Unit, + /** Gesamten Verlauf löschen. */ + onClear: () -> Unit, + /** Für einen Verlaufspunkt einen Audio-Wegpunkt erstellen. */ + onCreateWaypointFromPoint: (LatLng) -> Unit, + /** Online-Routing öffnen (RoutePlannerSheet). */ + onOpenOnlineRouting: () -> Unit, + /** Sheet schließen. */ + onDismiss: () -> Unit, +) { + val sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = false) + var showClearConfirm by remember { mutableStateOf(false) } + var onlineRoutingExpanded by remember { mutableStateOf(false) } + + val pointCount = routePoints.size + + ModalBottomSheet( + onDismissRequest = onDismiss, + sheetState = sheetState, + shape = RoundedCornerShape(topStart = 16.dp, topEnd = 16.dp), + ) { + Column( + modifier = Modifier + .fillMaxWidth() + .verticalScroll(rememberScrollState()) + .padding(horizontal = 16.dp) + .navigationBarsPadding() + .padding(bottom = 16.dp), + verticalArrangement = Arrangement.spacedBy(12.dp) + ) { + // ─── Header ─────────────────────────────────────────────────── + Row( + modifier = Modifier.fillMaxWidth(), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.SpaceBetween + ) { + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(8.dp) + ) { + Icon( + Icons.Filled.Edit, + contentDescription = null, + modifier = Modifier.size(22.dp), + tint = MaterialTheme.colorScheme.primary + ) + Column { + Text( + stringResource(R.string.tourverlauf_editor_title), + style = MaterialTheme.typography.titleMedium, + fontWeight = FontWeight.Bold + ) + // v2.7.15 — Untertitel: Beschreibung des konsolidierten Einstiegs + Text( + stringResource(R.string.tourverlauf_menu_subtitle), + style = MaterialTheme.typography.bodySmall, + color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.6f) + ) + if (tourName.isNotBlank()) { + Text( + tourName, + style = MaterialTheme.typography.labelSmall, + color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.45f) + ) + } + } + } + IconButton(onClick = onDismiss) { + Icon(Icons.Filled.Close, contentDescription = stringResource(R.string.tourverlauf_editor_close)) + } + } + + // ─── Erklärtext ─────────────────────────────────────────────── + Card( + colors = CardDefaults.cardColors( + containerColor = MaterialTheme.colorScheme.secondaryContainer.copy(alpha = 0.7f) + ), + modifier = Modifier.fillMaxWidth() + ) { + Row( + modifier = Modifier.padding(10.dp), + horizontalArrangement = Arrangement.spacedBy(8.dp), + verticalAlignment = Alignment.Top + ) { + Icon( + Icons.Filled.Info, + contentDescription = null, + modifier = Modifier.size(16.dp).padding(top = 2.dp), + tint = MaterialTheme.colorScheme.onSecondaryContainer.copy(alpha = 0.8f) + ) + Text( + stringResource(R.string.tourverlauf_editor_hint), + style = MaterialTheme.typography.bodySmall, + color = MaterialTheme.colorScheme.onSecondaryContainer + ) + } + } + + // ─── Punkt-Zähler ───────────────────────────────────────────── + Surface( + shape = RoundedCornerShape(12.dp), + color = if (pointCount > 0) + MaterialTheme.colorScheme.tertiaryContainer + else + MaterialTheme.colorScheme.surfaceVariant, + modifier = Modifier.fillMaxWidth() + ) { + Row( + modifier = Modifier.padding(horizontal = 14.dp, vertical = 10.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(8.dp) + ) { + Icon( + if (pointCount > 0) Icons.Filled.CheckCircle else Icons.Filled.PinDrop, + contentDescription = null, + modifier = Modifier.size(18.dp), + tint = if (pointCount > 0) + MaterialTheme.colorScheme.tertiary + else + MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.5f) + ) + Text( + if (pointCount > 0) + stringResource(R.string.tourverlauf_editor_point_count, pointCount) + else + stringResource(R.string.tourverlauf_editor_no_points), + style = MaterialTheme.typography.bodyMedium, + color = if (pointCount > 0) + MaterialTheme.colorScheme.onTertiaryContainer + else + MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.7f) + ) + } + } + + // ─── Punkt setzen ───────────────────────────────────────────── + Text( + "Routenpunkt hinzufügen", + style = MaterialTheme.typography.labelMedium, + color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.65f), + modifier = Modifier.padding(top = 4.dp) + ) + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.spacedBy(8.dp) + ) { + // Kartenmitte-Button + Button( + onClick = { + onAddCenterPoint() + }, + colors = ButtonDefaults.buttonColors( + containerColor = MaterialTheme.colorScheme.primaryContainer, + contentColor = MaterialTheme.colorScheme.onPrimaryContainer + ), + modifier = Modifier.weight(1f) + ) { + Icon(Icons.Filled.PinDrop, contentDescription = null, modifier = Modifier.size(16.dp)) + Spacer(Modifier.width(4.dp)) + Text(stringResource(R.string.tourverlauf_editor_add_center)) + } + + // Tipp-Modus-Toggle + Button( + onClick = onToggleDrawMode, + colors = ButtonDefaults.buttonColors( + containerColor = if (isDrawing) + MaterialTheme.colorScheme.tertiary + else + MaterialTheme.colorScheme.secondaryContainer, + contentColor = if (isDrawing) + MaterialTheme.colorScheme.onTertiary + else + MaterialTheme.colorScheme.onSecondaryContainer + ), + modifier = Modifier.weight(1f) + ) { + Icon(Icons.Filled.TouchApp, contentDescription = null, modifier = Modifier.size(16.dp)) + Spacer(Modifier.width(4.dp)) + Text( + if (isDrawing) "Tipp-Modus aktiv" else stringResource(R.string.tourverlauf_editor_add_tap) + ) + } + } + + // ─── Aktionen ───────────────────────────────────────────────── + if (pointCount > 0) { + Text( + "Tourpunkt-Aktionen", + style = MaterialTheme.typography.labelMedium, + color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.65f), + modifier = Modifier.padding(top = 4.dp) + ) + + // Als Audio-Wegpunkt erstellen + val targetPoint = lastSelectedPointIndex?.let { routePoints.getOrNull(it) } + ?: routePoints.lastOrNull() + if (targetPoint != null) { + OutlinedButton( + onClick = { onCreateWaypointFromPoint(targetPoint) }, + modifier = Modifier.fillMaxWidth() + ) { + Icon( + Icons.Filled.HeadsetMic, + contentDescription = null, + modifier = Modifier.size(16.dp), + tint = MaterialTheme.colorScheme.primary + ) + Spacer(Modifier.width(6.dp)) + Text(stringResource(R.string.tourverlauf_editor_as_waypoint)) + } + } + + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.spacedBy(8.dp) + ) { + // Letzten Punkt entfernen + OutlinedButton( + onClick = onRemoveLast, + enabled = pointCount > 0, + colors = ButtonDefaults.outlinedButtonColors( + contentColor = MaterialTheme.colorScheme.secondary + ), + modifier = Modifier.weight(1f) + ) { + Icon(Icons.Filled.Undo, contentDescription = null, modifier = Modifier.size(16.dp)) + Spacer(Modifier.width(4.dp)) + Text(stringResource(R.string.tourverlauf_editor_remove_last)) + } + + // Verlauf löschen + OutlinedButton( + onClick = { showClearConfirm = true }, + colors = ButtonDefaults.outlinedButtonColors( + contentColor = MaterialTheme.colorScheme.error + ), + modifier = Modifier.weight(1f) + ) { + Icon(Icons.Filled.Delete, contentDescription = null, modifier = Modifier.size(16.dp)) + Spacer(Modifier.width(4.dp)) + Text(stringResource(R.string.tourverlauf_editor_clear)) + } + } + } + + // ─── Optional: Online-Routing ────────────────────────────────── + Divider(modifier = Modifier.padding(vertical = 4.dp)) + Surface( + shape = RoundedCornerShape(12.dp), + color = MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.6f), + modifier = Modifier.fillMaxWidth() + ) { + Column { + // Header — einklappbar + Row( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 14.dp, vertical = 10.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.SpaceBetween + ) { + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(8.dp) + ) { + Icon( + Icons.Filled.AltRoute, + contentDescription = null, + modifier = Modifier.size(18.dp), + tint = MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.7f) + ) + Text( + stringResource(R.string.tourverlauf_online_routing_section), + style = MaterialTheme.typography.labelLarge, + color = MaterialTheme.colorScheme.onSurfaceVariant + ) + } + IconButton( + onClick = { onlineRoutingExpanded = !onlineRoutingExpanded }, + modifier = Modifier.size(32.dp) + ) { + Icon( + if (onlineRoutingExpanded) Icons.Filled.ExpandLess else Icons.Filled.ExpandMore, + contentDescription = if (onlineRoutingExpanded) "Schließen" else "Aufklappen", + tint = MaterialTheme.colorScheme.onSurfaceVariant + ) + } + } + + AnimatedVisibility( + visible = onlineRoutingExpanded, + enter = expandVertically() + fadeIn(), + exit = shrinkVertically() + fadeOut() + ) { + Column( + modifier = Modifier.padding(start = 14.dp, end = 14.dp, bottom = 12.dp), + verticalArrangement = Arrangement.spacedBy(8.dp) + ) { + Text( + stringResource(R.string.tourverlauf_online_routing_hint), + style = MaterialTheme.typography.bodySmall, + color = MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.8f) + ) + OutlinedButton( + onClick = { + onlineRoutingExpanded = false + onOpenOnlineRouting() + }, + modifier = Modifier.fillMaxWidth() + ) { + Icon( + Icons.Filled.AltRoute, + contentDescription = null, + modifier = Modifier.size(16.dp) + ) + Spacer(Modifier.width(6.dp)) + Text(stringResource(R.string.route_planner_open)) + } + } + } + } + } + + Spacer(Modifier.height(8.dp)) + } + } + + // Lösch-Bestätigungsdialog + if (showClearConfirm) { + AlertDialog( + onDismissRequest = { showClearConfirm = false }, + title = { Text(stringResource(R.string.tourverlauf_editor_clear_confirm)) }, + confirmButton = { + Button( + onClick = { + onClear() + showClearConfirm = false + }, + colors = ButtonDefaults.buttonColors( + containerColor = MaterialTheme.colorScheme.error, + contentColor = MaterialTheme.colorScheme.onError + ) + ) { + Text(stringResource(R.string.delete)) + } + }, + dismissButton = { + TextButton(onClick = { showClearConfirm = false }) { + Text(stringResource(R.string.cancel)) + } + } + ) + } +} diff --git a/app/src/main/kotlin/de/waypointaudio/ui/VersionNoticeDialog.kt b/app/src/main/kotlin/de/waypointaudio/ui/VersionNoticeDialog.kt index 3c1cfa1..303c860 100644 --- a/app/src/main/kotlin/de/waypointaudio/ui/VersionNoticeDialog.kt +++ b/app/src/main/kotlin/de/waypointaudio/ui/VersionNoticeDialog.kt @@ -82,7 +82,7 @@ fun VersionNoticeDialogHost() { fontWeight = FontWeight.SemiBold ) Text( - text = stringResource(R.string.version_notice_body_v2538), + text = stringResource(R.string.version_notice_body_v2720), style = MaterialTheme.typography.bodyMedium ) Row( diff --git a/app/src/main/kotlin/de/waypointaudio/ui/WaypointEditDialog.kt b/app/src/main/kotlin/de/waypointaudio/ui/WaypointEditDialog.kt index c1d4304..b181ad4 100644 --- a/app/src/main/kotlin/de/waypointaudio/ui/WaypointEditDialog.kt +++ b/app/src/main/kotlin/de/waypointaudio/ui/WaypointEditDialog.kt @@ -7,8 +7,11 @@ import androidx.activity.compose.rememberLauncherForActivityResult import androidx.activity.result.contract.ActivityResultContracts import java.util.Calendar import java.util.Locale +import androidx.compose.animation.animateContentSize +import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.* import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.foundation.verticalScroll import androidx.compose.material.icons.Icons @@ -18,6 +21,15 @@ import androidx.compose.material.icons.filled.ArrowUpward import androidx.compose.material.icons.filled.AudioFile import androidx.compose.material.icons.filled.CalendarMonth import androidx.compose.material.icons.filled.Delete +import androidx.compose.material.icons.filled.GpsFixed +import androidx.compose.material.icons.filled.ContentCopy +import androidx.compose.material.icons.filled.Headphones +import androidx.compose.material.icons.filled.KeyboardArrowDown +import androidx.compose.material.icons.filled.KeyboardArrowUp +import androidx.compose.material.icons.filled.MusicNote +import androidx.compose.material.icons.filled.MyLocation +import androidx.compose.material.icons.filled.Place +import androidx.compose.material.icons.filled.RadioButtonChecked import androidx.compose.material.icons.filled.Schedule import androidx.compose.material.icons.filled.SwapHoriz import androidx.compose.material3.* @@ -29,6 +41,7 @@ import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.input.KeyboardType +import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import de.waypointaudio.R import de.waypointaudio.data.AudioClip @@ -61,6 +74,15 @@ private fun Int?.toDisplayTimeString(): String { /** * Dialog for creating and editing a waypoint. * + * v2.6.1 — UI-Polish: + * - Klar gegliederte Abschnitte als Cards (Basis, Position, Audio, Auslösung, Wiedergabe, Zeitplan). + * - Audio-Bereich prominenter: freundlicher Empty-State mit Icon + Aufruf-Text. + * - Radius-Label „Auslösebereich" statt „Radius (Meter)". + * - Pflichtfeld-Fehler dezenter (kein aggressives Pink), Validation identisch. + * - Technische Hinweistexte (Dezimalgrad) reduziert und als sekundäre Info. + * - GPS-Vorausfüll-Hinweis freundlicher formuliert. + * - Keine Logik-Änderungen: alle Felder, Callbacks, Validation, Clips, Lizenz-Gate. + * * @param waypoint Existing waypoint (null = create new) * @param prefillLatLng Pre-filled GPS coordinates (lat, lon). * Only used for new waypoints (waypoint == null). @@ -92,7 +114,6 @@ fun WaypointEditDialog( val isNew = waypoint == null // v2.5.32 — Feature-Gate: Multi-Clip-Waypoints erfordern Profi-Zugang. - // Der Wert liest den Compose-State direkt, reagiert reaktiv auf Lizenzimport. val licenseStatus = LicenseStatusProvider.status val canMultiClip = LicenseFeatureAccess.canUseMultiClip(licenseStatus) @@ -115,18 +136,14 @@ fun WaypointEditDialog( var radiusStr by remember { mutableStateOf(waypoint?.radiusMeters?.toInt()?.toString() ?: "50") } // v2.5.12 — Multi-Clip-Editor. - // Initial aus effectiveClips() befüllen, sodass alte Wegpunkte ohne audioClips - // ihren Legacy-soundUri als ersten Clip vorfinden. val clips = remember { mutableStateListOf().apply { waypoint?.effectiveClips()?.let { addAll(it) } } } - // Index des Clips, der durch den nächsten Picker-Treffer ersetzt werden soll. - // null = ein neuer Clip wird angehängt. var replaceTargetIndex by remember { mutableStateOf(null) } - // Tour name: use existing waypoint's tour, or prefill for new, fallback to default + // Tour name val initialTour = when { waypoint != null -> waypoint.tourName.ifBlank { Waypoint.DEFAULT_TOUR_NAME } prefillTourName.isNotBlank() -> prefillTourName @@ -135,37 +152,32 @@ fun WaypointEditDialog( var tourName by remember { mutableStateOf(initialTour) } var tourMenuExpanded by remember { mutableStateOf(false) } - // Build the selectable tour list: existing tours + current value if not yet in list val selectableTours = remember(existingTours, tourName) { val base = if (existingTours.isEmpty()) listOf(Waypoint.DEFAULT_TOUR_NAME) else existingTours if (tourName !in base) base + tourName else base } - // Basic field validation errors + // Validation errors var nameError by remember { mutableStateOf(false) } var latError by remember { mutableStateOf(false) } var lngError by remember { mutableStateOf(false) } var radiusError by remember { mutableStateOf(false) } - // --- Playback rules state – inherit tour defaults for new waypoints --- + // Playback rules state val defaultMode = if (waypoint == null) tourDefaults.playbackMode else waypoint.playbackMode val defaultMaxCount = if (waypoint == null && tourDefaults.playbackMode == PlaybackMode.LIMITED_COUNT) tourDefaults.maxPlayCount.toString() else waypoint?.maxPlayCount?.toString() ?: "" var playbackMode by remember { mutableStateOf(defaultMode) } - var maxPlayCountStr by remember { - mutableStateOf(defaultMaxCount) - } + var maxPlayCountStr by remember { mutableStateOf(defaultMaxCount) } var maxPlayCountError by remember { mutableStateOf(false) } var currentPlayCount by remember { mutableStateOf(waypoint?.playCount ?: 0) } - // Scheduler: stored as millis / minutes (nullable = not set) + // Scheduler var scheduleEnabled by remember { mutableStateOf(waypoint?.scheduleEnabled ?: false) } var scheduleStartMillis by remember { mutableStateOf(waypoint?.scheduleStartMillis) } var scheduleEndMillis by remember { mutableStateOf(waypoint?.scheduleEndMillis) } var allowedStartMinutes by remember { mutableStateOf(waypoint?.allowedStartMinutes) } var allowedEndMinutes by remember { mutableStateOf(waypoint?.allowedEndMinutes) } - - // Schedule validation errors var scheduleRangeError by remember { mutableStateOf(false) } // GPS pre-fill on change @@ -176,8 +188,7 @@ fun WaypointEditDialog( } } - // Audio file picker — v2.5.12: erzeugt einen neuen Clip oder ersetzt - // die Audio-Quelle eines bestehenden Clips. Steuerung über [replaceTargetIndex]. + // Audio file picker val audioPickerLauncher = rememberLauncherForActivityResult( contract = ActivityResultContracts.OpenDocument() ) { uri: Uri? -> @@ -197,7 +208,6 @@ fun WaypointEditDialog( clips[tgt] = old.copy( uri = pickedUri, displayFileName = pickedName, - // Titel nur dann automatisch übernehmen, wenn noch keiner gesetzt war title = old.title.ifBlank { pickedName } ) } else { @@ -216,18 +226,13 @@ fun WaypointEditDialog( } } - // Helper: open DatePickerDialog followed by TimePickerDialog, result via callback - fun showDateTimePicker( - initialMillis: Long?, - onResult: (Long) -> Unit - ) { + fun showDateTimePicker(initialMillis: Long?, onResult: (Long) -> Unit) { val cal = Calendar.getInstance().also { c -> if (initialMillis != null) c.timeInMillis = initialMillis } DatePickerDialog( context, { _, year, month, day -> - // After date is picked, open time picker TimePickerDialog( context, { _, hour, minute -> @@ -244,7 +249,7 @@ fun WaypointEditDialog( }, cal.get(Calendar.HOUR_OF_DAY), cal.get(Calendar.MINUTE), - true // 24-hour format + true ).show() }, cal.get(Calendar.YEAR), @@ -253,20 +258,13 @@ fun WaypointEditDialog( ).show() } - // Helper: open TimePickerDialog, result in minutes (0..1439) - fun showTimePicker( - initialMinutes: Int?, - onResult: (Int) -> Unit - ) { + fun showTimePicker(initialMinutes: Int?, onResult: (Int) -> Unit) { val h = (initialMinutes ?: 0) / 60 val m = (initialMinutes ?: 0) % 60 TimePickerDialog( context, - { _, hour, minute -> - onResult(hour * 60 + minute) - }, - h, m, - true // 24-hour format + { _, hour, minute -> onResult(hour * 60 + minute) }, + h, m, true ).show() } @@ -274,7 +272,8 @@ fun WaypointEditDialog( onDismissRequest = onDismiss, title = { Text( - stringResource(if (isNew) R.string.add_waypoint else R.string.edit_waypoint) + stringResource(if (isNew) R.string.add_waypoint else R.string.edit_waypoint), + style = MaterialTheme.typography.titleLarge ) }, text = { @@ -282,704 +281,747 @@ fun WaypointEditDialog( modifier = Modifier .verticalScroll(rememberScrollState()) .fillMaxWidth(), - verticalArrangement = Arrangement.spacedBy(12.dp) + verticalArrangement = Arrangement.spacedBy(10.dp) ) { - // GPS pre-fill notice + + // --------------------------------------------------------------- + // GPS-Vorausfüll-Hinweis (freundlicher) + // --------------------------------------------------------------- if (isNew && prefillLatLng != null) { Surface( - color = MaterialTheme.colorScheme.primaryContainer, - shape = MaterialTheme.shapes.small + color = MaterialTheme.colorScheme.primaryContainer.copy(alpha = 0.7f), + shape = RoundedCornerShape(10.dp), + modifier = Modifier.fillMaxWidth() ) { - Text( - "📍 Koordinaten aus aktuellem GPS-Standort vorausgefüllt.", - style = MaterialTheme.typography.bodySmall, - color = MaterialTheme.colorScheme.onPrimaryContainer, - modifier = Modifier.padding(horizontal = 8.dp, vertical = 4.dp) - ) + Row( + modifier = Modifier.padding(horizontal = 10.dp, vertical = 8.dp), + verticalAlignment = Alignment.CenterVertically + ) { + Icon( + Icons.Filled.GpsFixed, + contentDescription = null, + modifier = Modifier.size(16.dp), + tint = MaterialTheme.colorScheme.primary + ) + Spacer(Modifier.width(8.dp)) + Text( + "GPS-Standort als Position vorausgefüllt", + style = MaterialTheme.typography.bodySmall, + color = MaterialTheme.colorScheme.onPrimaryContainer + ) + } } } - // Tour-Vorgaben-Hinweis für neue Wegpunkte + + // Tour-Vorgaben-Hinweis if (isNew && tourDefaults.playbackMode != de.waypointaudio.data.PlaybackMode.EVERY_ENTRY) { Surface( - color = MaterialTheme.colorScheme.secondaryContainer, - shape = MaterialTheme.shapes.small + color = MaterialTheme.colorScheme.secondaryContainer.copy(alpha = 0.6f), + shape = RoundedCornerShape(10.dp), + modifier = Modifier.fillMaxWidth() ) { Text( text = stringResource(R.string.waypoint_inherits_tour_defaults), style = MaterialTheme.typography.bodySmall, color = MaterialTheme.colorScheme.onSecondaryContainer, - modifier = Modifier.padding(horizontal = 8.dp, vertical = 4.dp) + modifier = Modifier.padding(horizontal = 10.dp, vertical = 8.dp) ) } } - // Name - OutlinedTextField( - value = name, - onValueChange = { name = it; nameError = false }, - label = { Text(stringResource(R.string.waypoint_name)) }, - isError = nameError, - supportingText = if (nameError) {{ Text("Pflichtfeld") }} else null, - singleLine = true, - modifier = Modifier.fillMaxWidth() + // --------------------------------------------------------------- + // STATUS-/KOPFKARTE: Name, Tour, Kurzüberblick (Position/Audio) + // --------------------------------------------------------------- + WaypointHeaderCard( + name = name, + tourName = tourName.ifBlank { Waypoint.DEFAULT_TOUR_NAME }, + positionSummary = positionSummary(latStr, lngStr), + audioSummary = audioSummary(clips.size) ) // --------------------------------------------------------------- - // Tour-Zuordnung + // ABSCHNITT 1: Details (Name + Tour) – immer sichtbar // --------------------------------------------------------------- - Text( - text = stringResource(R.string.tour_section_label), - style = MaterialTheme.typography.titleSmall, - fontWeight = FontWeight.SemiBold, - color = MaterialTheme.colorScheme.primary - ) + WaypointSectionCard { + WaypointSectionLabel( + icon = Icons.Filled.Place, + text = "Details" + ) + Spacer(Modifier.height(8.dp)) - // Tour dropdown – selectableTours als Auswahlhilfe, - // aber freie Texteingabe ist ebenfalls möglich - ExposedDropdownMenuBox( - expanded = tourMenuExpanded, - onExpandedChange = { tourMenuExpanded = it } - ) { + // Name (prominent) OutlinedTextField( - value = tourName, - onValueChange = { tourName = it }, - label = { Text(stringResource(R.string.tour_name_label)) }, - placeholder = { Text(Waypoint.DEFAULT_TOUR_NAME) }, - trailingIcon = { - ExposedDropdownMenuDefaults.TrailingIcon(expanded = tourMenuExpanded) - }, + value = name, + onValueChange = { name = it; nameError = false }, + label = { Text(stringResource(R.string.waypoint_name)) }, + isError = nameError, + supportingText = if (nameError) { + { Text("Name ist erforderlich", color = MaterialTheme.colorScheme.error) } + } else null, singleLine = true, - modifier = Modifier - .menuAnchor() - .fillMaxWidth() - ) - ExposedDropdownMenu( - expanded = tourMenuExpanded, - onDismissRequest = { tourMenuExpanded = false } - ) { - selectableTours.forEach { t -> - DropdownMenuItem( - text = { Text(t) }, - onClick = { - tourName = t - tourMenuExpanded = false - } - ) - } - } - } - Text( - text = stringResource(R.string.tour_name_hint), - style = MaterialTheme.typography.bodySmall, - color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.55f) - ) - - // --------------------------------------------------------------- - // v2.5.16 — Wegpunkt kopieren (nur im Bearbeiten-Modus sichtbar) - // Direkt unter der Tour-Zuordnung, damit der Aktionsbereich - // ohne Scrollen auffindbar ist. Wird nur gezeigt, wenn der - // Aufrufer einen Copy-Callback liefert (Player/Playback nicht). - // --------------------------------------------------------------- - if (waypoint != null && onCopyToOtherTour != null) { - WaypointCopySection( - currentTour = tourName, - existingTours = existingTours, - onCopy = { target -> - onCopyToOtherTour(target) - onDismiss() - } - ) - } - - HorizontalDivider(modifier = Modifier.padding(vertical = 4.dp)) - - // Coordinates - Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) { - OutlinedTextField( - value = latStr, - onValueChange = { latStr = it; latError = false }, - label = { Text("Lat") }, - isError = latError, - keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Decimal), - singleLine = true, - modifier = Modifier.weight(1f) - ) - OutlinedTextField( - value = lngStr, - onValueChange = { lngStr = it; lngError = false }, - label = { Text("Lng") }, - isError = lngError, - keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Decimal), - singleLine = true, - modifier = Modifier.weight(1f) - ) - } - - // Coordinates format hint - Text( - "Dezimalgrad, z. B. 48.137154 · 11.576124", - style = MaterialTheme.typography.bodySmall, - color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.55f) - ) - - // Radius - OutlinedTextField( - value = radiusStr, - onValueChange = { radiusStr = it; radiusError = false }, - label = { Text(stringResource(R.string.waypoint_radius)) }, - isError = radiusError, - supportingText = if (radiusError) {{ Text("Ganzzahl > 0") }} else null, - keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number), - singleLine = true, - modifier = Modifier.fillMaxWidth() - ) - - // --------------------------------------------------------------- - // v2.5.12 — Audio-Clips (Mehrfach-Auswahl + Reihenfolge) - // v2.5.32 — Multi-Clip-Gate: Hauptclip (idx 0) immer frei, - // Zusatzclips (idx > 0) nur mit Profi-Zugang bearbeiten. - // --------------------------------------------------------------- - Text( - text = "Audio-Clips", - style = MaterialTheme.typography.titleSmall, - fontWeight = FontWeight.SemiBold, - color = MaterialTheme.colorScheme.primary - ) - - // v2.5.32 — Profi-Hinweis: nur anzeigen, wenn Zusatzclips vorhanden - // und kein Profi-Zugang. Daten werden nicht gelöscht. - if (!canMultiClip && clips.size > 1) { - Surface( - color = MaterialTheme.colorScheme.secondaryContainer, - shape = MaterialTheme.shapes.small, + textStyle = MaterialTheme.typography.bodyLarge.copy(fontWeight = FontWeight.Medium), modifier = Modifier.fillMaxWidth() + ) + + Spacer(Modifier.height(6.dp)) + + // Tour-Dropdown + ExposedDropdownMenuBox( + expanded = tourMenuExpanded, + onExpandedChange = { tourMenuExpanded = it } ) { + OutlinedTextField( + value = tourName, + onValueChange = { tourName = it }, + label = { Text(stringResource(R.string.tour_name_label)) }, + placeholder = { Text(Waypoint.DEFAULT_TOUR_NAME) }, + trailingIcon = { + ExposedDropdownMenuDefaults.TrailingIcon(expanded = tourMenuExpanded) + }, + singleLine = true, + modifier = Modifier + .menuAnchor() + .fillMaxWidth() + ) + ExposedDropdownMenu( + expanded = tourMenuExpanded, + onDismissRequest = { tourMenuExpanded = false } + ) { + selectableTours.forEach { t -> + DropdownMenuItem( + text = { Text(t) }, + onClick = { + tourName = t + tourMenuExpanded = false + } + ) + } + } + } + Text( + text = stringResource(R.string.tour_name_hint), + style = MaterialTheme.typography.labelSmall, + color = MaterialTheme.colorScheme.onSurfaceVariant + ) + } + + // --------------------------------------------------------------- + // ABSCHNITT 2: Position (einklappbar – nur Koordinaten bei Bedarf) + // --------------------------------------------------------------- + WaypointExpandableSection( + icon = Icons.Filled.MyLocation, + title = "Position", + summary = positionSummary(latStr, lngStr), + initiallyExpanded = latError || lngError, + highlight = latError || lngError + ) { + Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) { + OutlinedTextField( + value = latStr, + onValueChange = { latStr = it; latError = false }, + label = { Text("Breitengrad") }, + isError = latError, + keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Decimal), + singleLine = true, + modifier = Modifier.weight(1f) + ) + OutlinedTextField( + value = lngStr, + onValueChange = { lngStr = it; lngError = false }, + label = { Text("Längengrad") }, + isError = lngError, + keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Decimal), + singleLine = true, + modifier = Modifier.weight(1f) + ) + } + if (latError || lngError) { Text( - text = LicenseFeatureAccess.MSG_MULTI_CLIP, - style = MaterialTheme.typography.bodySmall, - color = MaterialTheme.colorScheme.onSecondaryContainer, - modifier = Modifier.padding(horizontal = 8.dp, vertical = 6.dp) + "Gültige Koordinaten eingeben (z. B. 48.137 · 11.576)", + style = MaterialTheme.typography.labelSmall, + color = MaterialTheme.colorScheme.error + ) + } else { + Text( + "Dezimalgrad · z. B. 48.137154 / 11.576124", + style = MaterialTheme.typography.labelSmall, + color = MaterialTheme.colorScheme.onSurfaceVariant ) } } - if (clips.isEmpty()) { - Text( - text = stringResource(R.string.no_sound_selected), - style = MaterialTheme.typography.bodySmall, - color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.55f) - ) - } else { - clips.forEachIndexed { idx, clip -> - // v2.5.32: Zusatzclips (idx > 0) sind ohne Profi-Zugang - // lesbar (Daten bleiben erhalten), aber nicht bearbeitbar. - val isExtraClip = idx > 0 - val clipEditable = !isExtraClip || canMultiClip + // --------------------------------------------------------------- + // ABSCHNITT 3: Audio-Clips (einklappbar) + // --------------------------------------------------------------- + WaypointExpandableSection( + icon = Icons.Filled.MusicNote, + title = "Audio", + summary = audioSummary(clips.size), + initiallyExpanded = clips.isEmpty() + ) { + // v2.5.32 — Profi-Hinweis + if (!canMultiClip && clips.size > 1) { Surface( - tonalElevation = 1.dp, - shape = MaterialTheme.shapes.small, + color = MaterialTheme.colorScheme.secondaryContainer.copy(alpha = 0.7f), + shape = RoundedCornerShape(8.dp), modifier = Modifier.fillMaxWidth() ) { - Column( - modifier = Modifier - .fillMaxWidth() - .padding(8.dp), - verticalArrangement = Arrangement.spacedBy(4.dp) - ) { - // Kopfzeile: Position + (primary)-Marker - Row( - verticalAlignment = Alignment.CenterVertically, + Text( + text = LicenseFeatureAccess.MSG_MULTI_CLIP, + style = MaterialTheme.typography.bodySmall, + color = MaterialTheme.colorScheme.onSecondaryContainer, + modifier = Modifier.padding(horizontal = 8.dp, vertical = 6.dp) + ) + } + Spacer(Modifier.height(4.dp)) + } + + if (clips.isEmpty()) { + // Freundlicher Empty-State + Column( + modifier = Modifier + .fillMaxWidth() + .padding(vertical = 8.dp), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.spacedBy(4.dp) + ) { + Icon( + Icons.Filled.AudioFile, + contentDescription = null, + modifier = Modifier.size(32.dp), + tint = MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.5f) + ) + Text( + "Noch kein Audio-Clip hinzugefügt", + style = MaterialTheme.typography.bodyMedium, + color = MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.7f) + ) + Text( + "Wähle eine Audio-Datei, die am Wegpunkt abgespielt wird.", + style = MaterialTheme.typography.bodySmall, + color = MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.5f) + ) + } + } else { + Column(verticalArrangement = Arrangement.spacedBy(6.dp)) { + clips.forEachIndexed { idx, clip -> + val isExtraClip = idx > 0 + val clipEditable = !isExtraClip || canMultiClip + Surface( + tonalElevation = 2.dp, + shape = RoundedCornerShape(10.dp), + color = MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.45f), modifier = Modifier.fillMaxWidth() ) { - Text( - text = "Clip ${idx + 1}" + if (clip.isPrimary) " · Hauptclip" else "", - style = MaterialTheme.typography.labelMedium, - color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.7f), - modifier = Modifier.weight(1f) - ) - if (clipEditable) { - // Reihenfolge nach oben / unten - IconButton( - onClick = { - if (idx > 0) { - val tmp = clips[idx - 1] - clips[idx - 1] = clips[idx] - clips[idx] = tmp - } - }, - enabled = idx > 0 - ) { - Icon( - Icons.Filled.ArrowUpward, - contentDescription = "Nach oben", - modifier = Modifier.size(18.dp) - ) - } - IconButton( - onClick = { - if (idx < clips.size - 1) { - val tmp = clips[idx + 1] - clips[idx + 1] = clips[idx] - clips[idx] = tmp - } - }, - enabled = idx < clips.size - 1 - ) { - Icon( - Icons.Filled.ArrowDownward, - contentDescription = "Nach unten", - modifier = Modifier.size(18.dp) - ) - } - } - } - - // Titel-Feld - OutlinedTextField( - value = clip.title, - onValueChange = { newTitle -> - if (clipEditable) clips[idx] = clip.copy(title = newTitle) - }, - label = { Text("Titel") }, - placeholder = { Text(clip.displayFileName.ifBlank { "Audio-Clip" }) }, - singleLine = true, - readOnly = !clipEditable, - modifier = Modifier.fillMaxWidth() - ) - - // Dateiname (Quelle) als kleiner Hinweis - if (clip.displayFileName.isNotBlank()) { - Text( - text = clip.displayFileName, - style = MaterialTheme.typography.bodySmall, - color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.55f), - maxLines = 2 - ) - } else if (!clip.hasAudio) { - Text( - text = "Keine Audio-Datei zugewiesen", - style = MaterialTheme.typography.bodySmall, - color = MaterialTheme.colorScheme.error - ) - } - - if (clipEditable) { - // Aktions-Zeile - Row( - verticalAlignment = Alignment.CenterVertically, - modifier = Modifier.fillMaxWidth() + Column( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 10.dp, vertical = 8.dp), + verticalArrangement = Arrangement.spacedBy(4.dp) ) { - // Aktiv-Schalter - Text( - text = "Aktiv", - style = MaterialTheme.typography.bodySmall, - modifier = Modifier.weight(1f) - ) - Switch( - checked = clip.isActive, - onCheckedChange = { checked -> - clips[idx] = clip.copy(isActive = checked) - } - ) - // Audio ersetzen - IconButton(onClick = { - replaceTargetIndex = idx - audioPickerLauncher.launch(arrayOf("audio/*")) - }) { + // Kopfzeile + Row( + verticalAlignment = Alignment.CenterVertically, + modifier = Modifier.fillMaxWidth() + ) { Icon( - Icons.Filled.SwapHoriz, - contentDescription = "Audio ersetzen", - modifier = Modifier.size(20.dp) + Icons.Filled.AudioFile, + contentDescription = null, + modifier = Modifier.size(14.dp), + tint = MaterialTheme.colorScheme.primary.copy(alpha = 0.8f) ) - } - // Clip löschen - IconButton(onClick = { - clips.removeAt(idx) - }) { - Icon( - Icons.Filled.Delete, - contentDescription = "Clip löschen", - modifier = Modifier.size(20.dp), - tint = MaterialTheme.colorScheme.error - ) - } - } - - // Als Hauptclip markieren (nur sinnvoll, wenn noch nicht primary) - if (!clip.isPrimary && clip.hasAudio) { - TextButton(onClick = { - // Alle Clips zurücksetzen, dann diesen markieren - for (i in clips.indices) { - clips[i] = clips[i].copy(isPrimary = (i == idx)) - } - }) { + Spacer(Modifier.width(4.dp)) Text( - text = "Als Hauptclip festlegen", - style = MaterialTheme.typography.bodySmall + text = "Clip ${idx + 1}" + if (clip.isPrimary) " · Hauptclip" else "", + style = MaterialTheme.typography.labelSmall, + color = MaterialTheme.colorScheme.onSurfaceVariant, + modifier = Modifier.weight(1f) + ) + if (clipEditable) { + IconButton( + onClick = { + if (idx > 0) { + val tmp = clips[idx - 1] + clips[idx - 1] = clips[idx] + clips[idx] = tmp + } + }, + enabled = idx > 0, + modifier = Modifier.size(32.dp) + ) { + Icon( + Icons.Filled.ArrowUpward, + contentDescription = "Nach oben", + modifier = Modifier.size(16.dp) + ) + } + IconButton( + onClick = { + if (idx < clips.size - 1) { + val tmp = clips[idx + 1] + clips[idx + 1] = clips[idx] + clips[idx] = tmp + } + }, + enabled = idx < clips.size - 1, + modifier = Modifier.size(32.dp) + ) { + Icon( + Icons.Filled.ArrowDownward, + contentDescription = "Nach unten", + modifier = Modifier.size(16.dp) + ) + } + } + } + + // Titel-Feld + OutlinedTextField( + value = clip.title, + onValueChange = { newTitle -> + if (clipEditable) clips[idx] = clip.copy(title = newTitle) + }, + label = { Text("Clip-Titel") }, + placeholder = { Text(clip.displayFileName.ifBlank { "Audio-Clip" }) }, + singleLine = true, + readOnly = !clipEditable, + modifier = Modifier.fillMaxWidth() + ) + + // Dateiname + if (clip.displayFileName.isNotBlank()) { + Text( + text = clip.displayFileName, + style = MaterialTheme.typography.labelSmall, + color = MaterialTheme.colorScheme.onSurfaceVariant, + maxLines = 1, + overflow = TextOverflow.Ellipsis + ) + } else if (!clip.hasAudio) { + Text( + text = "Keine Audio-Datei zugewiesen", + style = MaterialTheme.typography.labelSmall, + color = MaterialTheme.colorScheme.error ) } + + if (clipEditable) { + // Aktions-Zeile + Row( + verticalAlignment = Alignment.CenterVertically, + modifier = Modifier.fillMaxWidth() + ) { + Text( + text = "Aktiv", + style = MaterialTheme.typography.bodySmall, + modifier = Modifier.weight(1f) + ) + Switch( + checked = clip.isActive, + onCheckedChange = { checked -> + clips[idx] = clip.copy(isActive = checked) + } + ) + IconButton(onClick = { + replaceTargetIndex = idx + audioPickerLauncher.launch(arrayOf("audio/*")) + }) { + Icon( + Icons.Filled.SwapHoriz, + contentDescription = "Audio ersetzen", + modifier = Modifier.size(20.dp) + ) + } + IconButton(onClick = { + clips.removeAt(idx) + }) { + Icon( + Icons.Filled.Delete, + contentDescription = "Clip löschen", + modifier = Modifier.size(20.dp), + tint = MaterialTheme.colorScheme.error.copy(alpha = 0.8f) + ) + } + } + + if (!clip.isPrimary && clip.hasAudio) { + TextButton(onClick = { + for (i in clips.indices) { + clips[i] = clips[i].copy(isPrimary = (i == idx)) + } + }) { + Text( + text = "Als Hauptclip festlegen", + style = MaterialTheme.typography.labelSmall + ) + } + } + } } - } // end clipEditable + } } } } + + Spacer(Modifier.height(6.dp)) + + // Audio-Hinzufügen-Button (prominent) + if (canMultiClip || clips.isEmpty()) { + Button( + onClick = { + replaceTargetIndex = null + audioPickerLauncher.launch(arrayOf("audio/*")) + }, + colors = ButtonDefaults.buttonColors( + containerColor = MaterialTheme.colorScheme.secondaryContainer, + contentColor = MaterialTheme.colorScheme.onSecondaryContainer + ), + modifier = Modifier.fillMaxWidth() + ) { + Icon( + Icons.Filled.Add, + contentDescription = null, + modifier = Modifier.size(18.dp) + ) + Spacer(Modifier.width(8.dp)) + Text( + if (clips.isEmpty()) "Audio-Clip auswählen" + else "Weiteren Clip hinzufügen" + ) + } + } else if (clips.isNotEmpty()) { + OutlinedButton( + onClick = { + replaceTargetIndex = 0 + audioPickerLauncher.launch(arrayOf("audio/*")) + }, + modifier = Modifier.fillMaxWidth() + ) { + Icon( + Icons.Filled.SwapHoriz, + contentDescription = null, + modifier = Modifier.size(18.dp) + ) + Spacer(Modifier.width(8.dp)) + Text("Hauptclip-Audio wechseln") + } + } } - // "Neuen Clip hinzufügen" – startet Picker im Anhängen-Modus. - // v2.5.32: Nur anzeigen wenn Profi-Zugang vorhanden ODER noch kein - // Clip (Hauptclip hinzufügen ist immer frei). - if (canMultiClip || clips.isEmpty()) { - OutlinedButton( - onClick = { - replaceTargetIndex = null - audioPickerLauncher.launch(arrayOf("audio/*")) - }, - modifier = Modifier.fillMaxWidth() - ) { - Icon( - Icons.Filled.Add, - contentDescription = null, - modifier = Modifier.size(18.dp) - ) - Spacer(Modifier.width(8.dp)) - Text( - if (clips.isEmpty()) stringResource(R.string.choose_sound) - else "Weiteren Clip hinzufügen" - ) - } - } else if (clips.isNotEmpty()) { - // Hauptclip-Audio-Wechsel bleibt immer möglich (index 0) - OutlinedButton( - onClick = { - replaceTargetIndex = 0 - audioPickerLauncher.launch(arrayOf("audio/*")) - }, - modifier = Modifier.fillMaxWidth() - ) { - Icon( - Icons.Filled.SwapHoriz, - contentDescription = null, - modifier = Modifier.size(18.dp) - ) - Spacer(Modifier.width(8.dp)) - Text("Hauptclip-Audio wechseln") - } - } - - HorizontalDivider(modifier = Modifier.padding(vertical = 4.dp)) - // --------------------------------------------------------------- - // Playback rules + // ABSCHNITT 4: Auslösung (Radius, einklappbar) // --------------------------------------------------------------- - Text( - text = stringResource(R.string.playback_rules_section), - style = MaterialTheme.typography.titleSmall, - fontWeight = FontWeight.SemiBold, - color = MaterialTheme.colorScheme.primary - ) - - // Mode selection via DropdownMenu - var modeMenuExpanded by remember { mutableStateOf(false) } - val modeLabel = when (playbackMode) { - PlaybackMode.EVERY_ENTRY -> stringResource(R.string.playback_mode_every_entry) - PlaybackMode.ONCE -> stringResource(R.string.playback_mode_once) - PlaybackMode.LIMITED_COUNT -> stringResource(R.string.playback_mode_limited) - } - ExposedDropdownMenuBox( - expanded = modeMenuExpanded, - onExpandedChange = { modeMenuExpanded = it } + WaypointExpandableSection( + icon = Icons.Filled.RadioButtonChecked, + title = "Auslösung", + summary = radiusStr.trim().let { if (it.isBlank()) "—" else "$it m Auslösebereich" }, + initiallyExpanded = radiusError, + highlight = radiusError ) { OutlinedTextField( - value = modeLabel, - onValueChange = {}, - readOnly = true, - label = { Text(stringResource(R.string.playback_mode_label)) }, - trailingIcon = { - ExposedDropdownMenuDefaults.TrailingIcon(expanded = modeMenuExpanded) - }, - modifier = Modifier - .menuAnchor() - .fillMaxWidth() - ) - ExposedDropdownMenu( - expanded = modeMenuExpanded, - onDismissRequest = { modeMenuExpanded = false } - ) { - DropdownMenuItem( - text = { Text(stringResource(R.string.playback_mode_every_entry)) }, - onClick = { - playbackMode = PlaybackMode.EVERY_ENTRY - modeMenuExpanded = false - } - ) - DropdownMenuItem( - text = { Text(stringResource(R.string.playback_mode_once)) }, - onClick = { - playbackMode = PlaybackMode.ONCE - modeMenuExpanded = false - } - ) - DropdownMenuItem( - text = { Text(stringResource(R.string.playback_mode_limited)) }, - onClick = { - playbackMode = PlaybackMode.LIMITED_COUNT - modeMenuExpanded = false - } - ) - } - } - - // Max count – only visible for LIMITED_COUNT - if (playbackMode == PlaybackMode.LIMITED_COUNT) { - OutlinedTextField( - value = maxPlayCountStr, - onValueChange = { maxPlayCountStr = it; maxPlayCountError = false }, - label = { Text(stringResource(R.string.playback_max_count_label)) }, - placeholder = { Text(stringResource(R.string.playback_max_count_hint)) }, - isError = maxPlayCountError, - supportingText = if (maxPlayCountError) { - { Text(stringResource(R.string.playback_max_count_error)) } + value = radiusStr, + onValueChange = { radiusStr = it; radiusError = false }, + label = { Text("Auslösebereich (Meter)") }, + isError = radiusError, + supportingText = if (radiusError) { + { Text("Ganzzahl > 0", color = MaterialTheme.colorScheme.error) } } else null, keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number), singleLine = true, modifier = Modifier.fillMaxWidth() ) + Text( + "Audio wird ausgelöst, sobald du diesen Bereich betrittst.", + style = MaterialTheme.typography.labelSmall, + color = MaterialTheme.colorScheme.onSurfaceVariant + ) } - // Counter display + reset (edit mode only) - if (!isNew) { - Row( - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.SpaceBetween, - modifier = Modifier.fillMaxWidth() - ) { - Text( - text = stringResource(R.string.playback_count_info, currentPlayCount), - style = MaterialTheme.typography.bodySmall, - color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.7f) - ) - TextButton(onClick = { currentPlayCount = 0 }) { - Text( - text = stringResource(R.string.playback_count_reset), - style = MaterialTheme.typography.bodySmall - ) - } - } - } - - HorizontalDivider(modifier = Modifier.padding(vertical = 4.dp)) - // --------------------------------------------------------------- - // Scheduler + // ABSCHNITT 5: Wiedergabe-Regeln (einklappbar) // --------------------------------------------------------------- - Text( - text = stringResource(R.string.schedule_section), - style = MaterialTheme.typography.titleSmall, - fontWeight = FontWeight.SemiBold, - color = MaterialTheme.colorScheme.primary - ) - - Row( - verticalAlignment = Alignment.CenterVertically, - modifier = Modifier.fillMaxWidth() + WaypointExpandableSection( + icon = Icons.Filled.Headphones, + title = stringResource(R.string.playback_rules_section), + summary = when (playbackMode) { + PlaybackMode.EVERY_ENTRY -> stringResource(R.string.playback_mode_every_entry) + PlaybackMode.ONCE -> stringResource(R.string.playback_mode_once) + PlaybackMode.LIMITED_COUNT -> stringResource(R.string.playback_mode_limited) + }, + initiallyExpanded = maxPlayCountError, + highlight = maxPlayCountError ) { - Text( - text = stringResource(R.string.schedule_enabled_label), - modifier = Modifier.weight(1f), - style = MaterialTheme.typography.bodyMedium - ) - Switch( - checked = scheduleEnabled, - onCheckedChange = { scheduleEnabled = it } - ) - } - - if (scheduleEnabled) { - - // ---- Start date/time ---- - Text( - text = stringResource(R.string.schedule_start_label), - style = MaterialTheme.typography.bodySmall, - color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.7f) - ) - Row( - horizontalArrangement = Arrangement.spacedBy(8.dp), - verticalAlignment = Alignment.CenterVertically, - modifier = Modifier.fillMaxWidth() + var modeMenuExpanded by remember { mutableStateOf(false) } + val modeLabel = when (playbackMode) { + PlaybackMode.EVERY_ENTRY -> stringResource(R.string.playback_mode_every_entry) + PlaybackMode.ONCE -> stringResource(R.string.playback_mode_once) + PlaybackMode.LIMITED_COUNT -> stringResource(R.string.playback_mode_limited) + } + ExposedDropdownMenuBox( + expanded = modeMenuExpanded, + onExpandedChange = { modeMenuExpanded = it } ) { - OutlinedButton( - onClick = { - showDateTimePicker(scheduleStartMillis) { millis -> - scheduleStartMillis = millis - scheduleRangeError = false - } + OutlinedTextField( + value = modeLabel, + onValueChange = {}, + readOnly = true, + label = { Text(stringResource(R.string.playback_mode_label)) }, + trailingIcon = { + ExposedDropdownMenuDefaults.TrailingIcon(expanded = modeMenuExpanded) }, - modifier = Modifier.weight(1f) + modifier = Modifier + .menuAnchor() + .fillMaxWidth() + ) + ExposedDropdownMenu( + expanded = modeMenuExpanded, + onDismissRequest = { modeMenuExpanded = false } ) { - Icon( - Icons.Filled.CalendarMonth, - contentDescription = null, - modifier = Modifier.size(16.dp) + DropdownMenuItem( + text = { Text(stringResource(R.string.playback_mode_every_entry)) }, + onClick = { playbackMode = PlaybackMode.EVERY_ENTRY; modeMenuExpanded = false } ) - Spacer(Modifier.width(6.dp)) - Text( - text = if (scheduleStartMillis != null) - scheduleStartMillis.toDisplayDateString() - else - stringResource(R.string.schedule_pick_start), - maxLines = 1 + DropdownMenuItem( + text = { Text(stringResource(R.string.playback_mode_once)) }, + onClick = { playbackMode = PlaybackMode.ONCE; modeMenuExpanded = false } + ) + DropdownMenuItem( + text = { Text(stringResource(R.string.playback_mode_limited)) }, + onClick = { playbackMode = PlaybackMode.LIMITED_COUNT; modeMenuExpanded = false } ) - } - if (scheduleStartMillis != null) { - TextButton(onClick = { - scheduleStartMillis = null - scheduleRangeError = false - }) { - Text(stringResource(R.string.schedule_clear_start)) - } } } - // ---- End date/time ---- - Text( - text = stringResource(R.string.schedule_end_label), - style = MaterialTheme.typography.bodySmall, - color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.7f) - ) - Row( - horizontalArrangement = Arrangement.spacedBy(8.dp), - verticalAlignment = Alignment.CenterVertically, - modifier = Modifier.fillMaxWidth() - ) { - OutlinedButton( - onClick = { - showDateTimePicker(scheduleEndMillis) { millis -> - scheduleEndMillis = millis - scheduleRangeError = false - } - }, - modifier = Modifier.weight(1f) - ) { - Icon( - Icons.Filled.CalendarMonth, - contentDescription = null, - modifier = Modifier.size(16.dp) - ) - Spacer(Modifier.width(6.dp)) - Text( - text = if (scheduleEndMillis != null) - scheduleEndMillis.toDisplayDateString() - else - stringResource(R.string.schedule_pick_end), - maxLines = 1 - ) - } - if (scheduleEndMillis != null) { - TextButton(onClick = { - scheduleEndMillis = null - scheduleRangeError = false - }) { - Text(stringResource(R.string.schedule_clear_end)) - } - } - } - - // Range validation error - if (scheduleRangeError) { - Text( - text = stringResource(R.string.schedule_end_before_start_error), - style = MaterialTheme.typography.bodySmall, - color = MaterialTheme.colorScheme.error + if (playbackMode == PlaybackMode.LIMITED_COUNT) { + Spacer(Modifier.height(4.dp)) + OutlinedTextField( + value = maxPlayCountStr, + onValueChange = { maxPlayCountStr = it; maxPlayCountError = false }, + label = { Text(stringResource(R.string.playback_max_count_label)) }, + placeholder = { Text(stringResource(R.string.playback_max_count_hint)) }, + isError = maxPlayCountError, + supportingText = if (maxPlayCountError) { + { Text(stringResource(R.string.playback_max_count_error), color = MaterialTheme.colorScheme.error) } + } else null, + keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number), + singleLine = true, + modifier = Modifier.fillMaxWidth() ) } - // ---- Daily time window ---- - Text( - text = stringResource(R.string.schedule_daily_label), - style = MaterialTheme.typography.bodySmall, - color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.7f) - ) - - // Daily start time - Row( - horizontalArrangement = Arrangement.spacedBy(8.dp), - verticalAlignment = Alignment.CenterVertically, - modifier = Modifier.fillMaxWidth() - ) { - OutlinedButton( - onClick = { - showTimePicker(allowedStartMinutes) { minutes -> - allowedStartMinutes = minutes - } - }, - modifier = Modifier.weight(1f) + if (!isNew) { + Spacer(Modifier.height(4.dp)) + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.SpaceBetween, + modifier = Modifier.fillMaxWidth() ) { - Icon( - Icons.Filled.Schedule, - contentDescription = null, - modifier = Modifier.size(16.dp) - ) - Spacer(Modifier.width(6.dp)) Text( - text = if (allowedStartMinutes != null) - allowedStartMinutes.toDisplayTimeString() - else - stringResource(R.string.schedule_pick_daily_start), - maxLines = 1 + text = stringResource(R.string.playback_count_info, currentPlayCount), + style = MaterialTheme.typography.bodySmall, + color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.7f) ) - } - if (allowedStartMinutes != null) { - TextButton(onClick = { allowedStartMinutes = null }) { - Text(stringResource(R.string.schedule_clear_window)) + TextButton(onClick = { currentPlayCount = 0 }) { + Text( + text = stringResource(R.string.playback_count_reset), + style = MaterialTheme.typography.bodySmall + ) } } } - - // Daily end time - Row( - horizontalArrangement = Arrangement.spacedBy(8.dp), - verticalAlignment = Alignment.CenterVertically, - modifier = Modifier.fillMaxWidth() - ) { - OutlinedButton( - onClick = { - showTimePicker(allowedEndMinutes) { minutes -> - allowedEndMinutes = minutes - } - }, - modifier = Modifier.weight(1f) - ) { - Icon( - Icons.Filled.Schedule, - contentDescription = null, - modifier = Modifier.size(16.dp) - ) - Spacer(Modifier.width(6.dp)) - Text( - text = if (allowedEndMinutes != null) - allowedEndMinutes.toDisplayTimeString() - else - stringResource(R.string.schedule_pick_daily_end), - maxLines = 1 - ) - } - if (allowedEndMinutes != null) { - TextButton(onClick = { allowedEndMinutes = null }) { - Text(stringResource(R.string.schedule_clear_window)) - } - } - } - - // Info: daily window can cross midnight - Text( - text = stringResource(R.string.schedule_daily_midnight_hint), - style = MaterialTheme.typography.bodySmall, - color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.55f) - ) } - // v2.5.16 — Kopiersektion wurde in den oberen Tour-Bereich - // verschoben und ist dort gut sichtbar. + // --------------------------------------------------------------- + // ABSCHNITT 6: Zeitplan (einklappbar) + // --------------------------------------------------------------- + WaypointExpandableSection( + icon = Icons.Filled.Schedule, + title = stringResource(R.string.schedule_section), + summary = if (scheduleEnabled) "Aktiv" else "Aus", + initiallyExpanded = scheduleRangeError, + highlight = scheduleRangeError + ) { + Row( + verticalAlignment = Alignment.CenterVertically, + modifier = Modifier.fillMaxWidth() + ) { + Text( + text = stringResource(R.string.schedule_enabled_label), + modifier = Modifier.weight(1f), + style = MaterialTheme.typography.bodyMedium + ) + Switch( + checked = scheduleEnabled, + onCheckedChange = { scheduleEnabled = it } + ) + } + + if (scheduleEnabled) { + Spacer(Modifier.height(4.dp)) + + Text( + text = stringResource(R.string.schedule_start_label), + style = MaterialTheme.typography.labelSmall, + color = MaterialTheme.colorScheme.onSurfaceVariant + ) + Row( + horizontalArrangement = Arrangement.spacedBy(8.dp), + verticalAlignment = Alignment.CenterVertically, + modifier = Modifier.fillMaxWidth() + ) { + OutlinedButton( + onClick = { + showDateTimePicker(scheduleStartMillis) { millis -> + scheduleStartMillis = millis + scheduleRangeError = false + } + }, + modifier = Modifier.weight(1f) + ) { + Icon(Icons.Filled.CalendarMonth, contentDescription = null, modifier = Modifier.size(16.dp)) + Spacer(Modifier.width(6.dp)) + Text( + text = if (scheduleStartMillis != null) scheduleStartMillis.toDisplayDateString() + else stringResource(R.string.schedule_pick_start), + maxLines = 1 + ) + } + if (scheduleStartMillis != null) { + TextButton(onClick = { scheduleStartMillis = null; scheduleRangeError = false }) { + Text(stringResource(R.string.schedule_clear_start)) + } + } + } + + Text( + text = stringResource(R.string.schedule_end_label), + style = MaterialTheme.typography.labelSmall, + color = MaterialTheme.colorScheme.onSurfaceVariant + ) + Row( + horizontalArrangement = Arrangement.spacedBy(8.dp), + verticalAlignment = Alignment.CenterVertically, + modifier = Modifier.fillMaxWidth() + ) { + OutlinedButton( + onClick = { + showDateTimePicker(scheduleEndMillis) { millis -> + scheduleEndMillis = millis + scheduleRangeError = false + } + }, + modifier = Modifier.weight(1f) + ) { + Icon(Icons.Filled.CalendarMonth, contentDescription = null, modifier = Modifier.size(16.dp)) + Spacer(Modifier.width(6.dp)) + Text( + text = if (scheduleEndMillis != null) scheduleEndMillis.toDisplayDateString() + else stringResource(R.string.schedule_pick_end), + maxLines = 1 + ) + } + if (scheduleEndMillis != null) { + TextButton(onClick = { scheduleEndMillis = null; scheduleRangeError = false }) { + Text(stringResource(R.string.schedule_clear_end)) + } + } + } + + if (scheduleRangeError) { + Text( + text = stringResource(R.string.schedule_end_before_start_error), + style = MaterialTheme.typography.labelSmall, + color = MaterialTheme.colorScheme.error + ) + } + + Text( + text = stringResource(R.string.schedule_daily_label), + style = MaterialTheme.typography.labelSmall, + color = MaterialTheme.colorScheme.onSurfaceVariant + ) + + Row( + horizontalArrangement = Arrangement.spacedBy(8.dp), + verticalAlignment = Alignment.CenterVertically, + modifier = Modifier.fillMaxWidth() + ) { + OutlinedButton( + onClick = { + showTimePicker(allowedStartMinutes) { minutes -> allowedStartMinutes = minutes } + }, + modifier = Modifier.weight(1f) + ) { + Icon(Icons.Filled.Schedule, contentDescription = null, modifier = Modifier.size(16.dp)) + Spacer(Modifier.width(6.dp)) + Text( + text = if (allowedStartMinutes != null) allowedStartMinutes.toDisplayTimeString() + else stringResource(R.string.schedule_pick_daily_start), + maxLines = 1 + ) + } + if (allowedStartMinutes != null) { + TextButton(onClick = { allowedStartMinutes = null }) { + Text(stringResource(R.string.schedule_clear_window)) + } + } + } + + Row( + horizontalArrangement = Arrangement.spacedBy(8.dp), + verticalAlignment = Alignment.CenterVertically, + modifier = Modifier.fillMaxWidth() + ) { + OutlinedButton( + onClick = { + showTimePicker(allowedEndMinutes) { minutes -> allowedEndMinutes = minutes } + }, + modifier = Modifier.weight(1f) + ) { + Icon(Icons.Filled.Schedule, contentDescription = null, modifier = Modifier.size(16.dp)) + Spacer(Modifier.width(6.dp)) + Text( + text = if (allowedEndMinutes != null) allowedEndMinutes.toDisplayTimeString() + else stringResource(R.string.schedule_pick_daily_end), + maxLines = 1 + ) + } + if (allowedEndMinutes != null) { + TextButton(onClick = { allowedEndMinutes = null }) { + Text(stringResource(R.string.schedule_clear_window)) + } + } + } + + Text( + text = stringResource(R.string.schedule_daily_midnight_hint), + style = MaterialTheme.typography.labelSmall, + color = MaterialTheme.colorScheme.onSurfaceVariant + ) + } + } + + // --------------------------------------------------------------- + // ABSCHNITT 7: Kopieren & duplizieren (einklappbar, ganz unten) + // v2.5.16 — Kopiersektion (nur im Bearbeiten-Modus) + // --------------------------------------------------------------- + if (waypoint != null && onCopyToOtherTour != null) { + WaypointExpandableSection( + icon = Icons.Filled.ContentCopy, + title = "Kopieren & duplizieren", + summary = "In andere Tour oder hier duplizieren", + initiallyExpanded = false + ) { + WaypointCopySectionBody( + currentTour = tourName, + existingTours = existingTours, + onCopy = { target -> + onCopyToOtherTour(target) + onDismiss() + } + ) + } + } } }, confirmButton = { @@ -993,10 +1035,8 @@ fun WaypointEditDialog( lngError = lng == null || lng !in -180.0..180.0 radiusError = radius == null || radius <= 0f - // --- Tour name validation: fallback to default if blank --- val safeTourName = tourName.trim().ifBlank { Waypoint.DEFAULT_TOUR_NAME } - // --- Playback rule validation --- var maxCount: Int? = null if (playbackMode == PlaybackMode.LIMITED_COUNT) { maxCount = maxPlayCountStr.trim().toIntOrNull() @@ -1005,7 +1045,6 @@ fun WaypointEditDialog( maxPlayCountError = false } - // --- Schedule validation --- scheduleRangeError = if (scheduleEnabled) { scheduleStartMillis != null && scheduleEndMillis != null && @@ -1016,11 +1055,6 @@ fun WaypointEditDialog( maxPlayCountError || scheduleRangeError if (!hasError) { - // v2.5.12 — Clips über withClips() konsistent in audioClips + - // Legacy-soundUri/-soundName spiegeln. Filtere Clips ohne URI - // (z. B. wenn der User auf "+" geklickt, aber dann den Picker - // abgebrochen hat — solche Phantom-Clips entstehen hier zwar - // nicht, aber wir bleiben defensiv). val cleanClips = clips.filter { it.hasAudio } val base = (waypoint ?: Waypoint()).copy( name = name.trim(), @@ -1028,7 +1062,6 @@ fun WaypointEditDialog( longitude = lng!!, radiusMeters = radius!!, tourName = safeTourName, - // Playback rules playbackMode = playbackMode, maxPlayCount = if (playbackMode == PlaybackMode.LIMITED_COUNT) maxCount else null, playCount = currentPlayCount, @@ -1039,8 +1072,6 @@ fun WaypointEditDialog( allowedEndMinutes = if (scheduleEnabled) allowedEndMinutes else null ) val withAudio = if (cleanClips.isEmpty()) { - // Keine Clips mehr — Legacy-Felder leeren, damit kein - // Geister-Audio aus alten Daten zurückbleibt. base.copy(audioClips = emptyList(), soundUri = "", soundName = "") } else { base.withClips(cleanClips) @@ -1059,6 +1090,218 @@ fun WaypointEditDialog( ) } +// --------------------------------------------------------------- +// Hilfsfunktionen für Card-Layout v2.6.1 +// --------------------------------------------------------------- + +/** + * Einheitliche Abschnittskarte für den WaypointEditDialog. + * Gibt dem Dialog eine strukturierte, ruhigere Optik mit + * klarer visueller Trennung der Inhalte. + */ +@Composable +private fun WaypointSectionCard( + content: @Composable ColumnScope.() -> Unit +) { + Surface( + shape = RoundedCornerShape(12.dp), + color = MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.35f), + tonalElevation = 1.dp, + modifier = Modifier.fillMaxWidth() + ) { + Column( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 12.dp, vertical = 12.dp), + content = content + ) + } +} + +/** + * Abschnitts-Label mit Icon und Text, Teal-Akzentfarbe (primary). + */ +@Composable +private fun WaypointSectionLabel( + icon: androidx.compose.ui.graphics.vector.ImageVector, + text: String +) { + Row(verticalAlignment = Alignment.CenterVertically) { + Icon( + icon, + contentDescription = null, + modifier = Modifier.size(16.dp), + tint = MaterialTheme.colorScheme.primary + ) + Spacer(Modifier.width(6.dp)) + Text( + text = text, + style = MaterialTheme.typography.titleSmall, + fontWeight = FontWeight.SemiBold, + color = MaterialTheme.colorScheme.primary + ) + } +} + +// --------------------------------------------------------------- +// v2.7.34 — Ruhigeres Layout: Kopfkarte + einklappbare Abschnitte +// --------------------------------------------------------------- + +/** Kurzformel für die Positionsanzeige (Kopfkarte / Abschnittszusammenfassung). */ +private fun positionSummary(latStr: String, lngStr: String): String { + val lat = latStr.trim().replace(',', '.').toDoubleOrNull() + val lng = lngStr.trim().replace(',', '.').toDoubleOrNull() + return if (lat != null && lng != null) { + "%.5f · %.5f".format(Locale.US, lat, lng) + } else { + "Noch keine Position" + } +} + +/** Kurzformel für die Audioanzeige (Kopfkarte / Abschnittszusammenfassung). */ +private fun audioSummary(clipCount: Int): String = when (clipCount) { + 0 -> "Kein Audio" + 1 -> "1 Audio-Clip" + else -> "$clipCount Audio-Clips" +} + +/** + * Kompakte Status-/Kopfkarte oben im Dialog. Zeigt den Wegpunkt-Namen (oder + * einen Platzhalter), die aktuelle Tour und einen kurzen Überblick über + * Position und Audio. Reine Anzeige – keine Eingaben, keine Logik. + */ +@Composable +private fun WaypointHeaderCard( + name: String, + tourName: String, + positionSummary: String, + audioSummary: String +) { + Surface( + shape = RoundedCornerShape(14.dp), + color = MaterialTheme.colorScheme.secondaryContainer, + tonalElevation = 2.dp, + modifier = Modifier.fillMaxWidth() + ) { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 14.dp, vertical = 12.dp), + verticalAlignment = Alignment.CenterVertically + ) { + Icon( + Icons.Filled.Place, + contentDescription = null, + tint = MaterialTheme.colorScheme.onSecondaryContainer, + modifier = Modifier.size(28.dp) + ) + Spacer(Modifier.width(12.dp)) + Column(modifier = Modifier.weight(1f)) { + Text( + text = name.ifBlank { "Neuer Wegpunkt" }, + style = MaterialTheme.typography.titleMedium, + fontWeight = FontWeight.SemiBold, + color = MaterialTheme.colorScheme.onSecondaryContainer, + maxLines = 1, + overflow = TextOverflow.Ellipsis + ) + Text( + text = "Tour: $tourName", + style = MaterialTheme.typography.bodySmall, + color = MaterialTheme.colorScheme.onSecondaryContainer.copy(alpha = 0.85f), + maxLines = 1, + overflow = TextOverflow.Ellipsis + ) + Spacer(Modifier.height(2.dp)) + Text( + text = "$positionSummary · $audioSummary", + style = MaterialTheme.typography.labelSmall, + color = MaterialTheme.colorScheme.onSecondaryContainer.copy(alpha = 0.75f), + maxLines = 1, + overflow = TextOverflow.Ellipsis + ) + } + } + } +} + +/** + * Einklappbarer Abschnitt im Stil der [WaypointSectionCard]. Der Kopf zeigt + * Icon, Titel und – wenn eingeklappt – eine kurze Zusammenfassung; ein Tippen + * auf den Kopf klappt den Inhalt auf/zu. So bleibt der Dialog ruhig, ohne + * Funktionen zu verstecken. + * + * @param initiallyExpanded Startzustand (z. B. true bei Validierungsfehlern). + * @param highlight Hebt den Kopf in der Fehlerfarbe hervor. + */ +@Composable +private fun WaypointExpandableSection( + icon: androidx.compose.ui.graphics.vector.ImageVector, + title: String, + summary: String, + initiallyExpanded: Boolean = false, + highlight: Boolean = false, + content: @Composable ColumnScope.() -> Unit +) { + var expanded by remember { mutableStateOf(initiallyExpanded) } + val accent = if (highlight) MaterialTheme.colorScheme.error + else MaterialTheme.colorScheme.primary + Surface( + shape = RoundedCornerShape(12.dp), + color = MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.35f), + tonalElevation = 1.dp, + modifier = Modifier.fillMaxWidth() + ) { + Column( + modifier = Modifier + .fillMaxWidth() + .animateContentSize() + .padding(horizontal = 12.dp, vertical = 12.dp) + ) { + Row( + verticalAlignment = Alignment.CenterVertically, + modifier = Modifier + .fillMaxWidth() + .clickable { expanded = !expanded } + ) { + Icon( + icon, + contentDescription = null, + modifier = Modifier.size(16.dp), + tint = accent + ) + Spacer(Modifier.width(6.dp)) + Column(modifier = Modifier.weight(1f)) { + Text( + text = title, + style = MaterialTheme.typography.titleSmall, + fontWeight = FontWeight.SemiBold, + color = accent + ) + if (!expanded && summary.isNotBlank()) { + Text( + text = summary, + style = MaterialTheme.typography.labelSmall, + color = MaterialTheme.colorScheme.onSurfaceVariant, + maxLines = 1, + overflow = TextOverflow.Ellipsis + ) + } + } + Icon( + if (expanded) Icons.Filled.KeyboardArrowUp else Icons.Filled.KeyboardArrowDown, + contentDescription = if (expanded) "Einklappen" else "Aufklappen", + tint = MaterialTheme.colorScheme.onSurfaceVariant + ) + } + if (expanded) { + Spacer(Modifier.height(8.dp)) + content() + } + } + } +} + /** * v2.5.16 — Kopiersektion für den Bearbeiten-Dialog. * @@ -1074,7 +1317,7 @@ fun WaypointEditDialog( */ @OptIn(ExperimentalMaterial3Api::class) @Composable -private fun WaypointCopySection( +private fun WaypointCopySectionBody( currentTour: String, existingTours: List, onCopy: (targetTour: String) -> Unit, @@ -1084,81 +1327,74 @@ private fun WaypointCopySection( existingTours.filter { it.isNotBlank() && it != effectiveCurrent } } - HorizontalDivider(modifier = Modifier.padding(vertical = 4.dp)) - Text( - text = "Wegpunkt kopieren", - style = MaterialTheme.typography.titleSmall, - fontWeight = FontWeight.SemiBold, - color = MaterialTheme.colorScheme.primary - ) - Text( - text = "Erzeugt eine eigenständige Kopie mit allen Clips. Das Original " + - "bleibt unverändert. Die Kopie wird ans Ende der Zieltour gehängt.", - style = MaterialTheme.typography.bodySmall, - color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.65f) - ) + Column { + Text( + text = "Erzeugt eine eigenständige Kopie mit allen Clips. Das Original " + + "bleibt unverändert. Die Kopie wird ans Ende der Zieltour gehängt.", + style = MaterialTheme.typography.bodySmall, + color = MaterialTheme.colorScheme.onSurfaceVariant + ) + Spacer(Modifier.height(8.dp)) - if (otherTours.isNotEmpty()) { - var copyTargetMenuExpanded by remember { mutableStateOf(false) } - var copyTarget by remember(otherTours) { mutableStateOf(otherTours.first()) } - Row( - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(8.dp) - ) { - ExposedDropdownMenuBox( - expanded = copyTargetMenuExpanded, - onExpandedChange = { copyTargetMenuExpanded = it }, - modifier = Modifier.weight(1f) + if (otherTours.isNotEmpty()) { + var copyTargetMenuExpanded by remember { mutableStateOf(false) } + var copyTarget by remember(otherTours) { mutableStateOf(otherTours.first()) } + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(8.dp) ) { - OutlinedTextField( - value = copyTarget, - onValueChange = {}, - readOnly = true, - label = { Text("Ziel-Tour") }, - trailingIcon = { - ExposedDropdownMenuDefaults.TrailingIcon( - expanded = copyTargetMenuExpanded - ) - }, - singleLine = true, - modifier = Modifier - .menuAnchor() - .fillMaxWidth() - ) - ExposedDropdownMenu( + ExposedDropdownMenuBox( expanded = copyTargetMenuExpanded, - onDismissRequest = { copyTargetMenuExpanded = false } + onExpandedChange = { copyTargetMenuExpanded = it }, + modifier = Modifier.weight(1f) ) { - otherTours.forEach { t -> - DropdownMenuItem( - text = { Text(t) }, - onClick = { - copyTarget = t - copyTargetMenuExpanded = false - } - ) + OutlinedTextField( + value = copyTarget, + onValueChange = {}, + readOnly = true, + label = { Text("Ziel-Tour") }, + trailingIcon = { + ExposedDropdownMenuDefaults.TrailingIcon(expanded = copyTargetMenuExpanded) + }, + singleLine = true, + modifier = Modifier + .menuAnchor() + .fillMaxWidth() + ) + ExposedDropdownMenu( + expanded = copyTargetMenuExpanded, + onDismissRequest = { copyTargetMenuExpanded = false } + ) { + otherTours.forEach { t -> + DropdownMenuItem( + text = { Text(t) }, + onClick = { + copyTarget = t + copyTargetMenuExpanded = false + } + ) + } } } + FilledTonalButton(onClick = { onCopy(copyTarget) }) { + Text("Kopieren") + } } - FilledTonalButton(onClick = { onCopy(copyTarget) }) { - Text("Kopieren") - } + } else { + Text( + text = "Es ist noch keine weitere Tour vorhanden. Du kannst diesen " + + "Wegpunkt aber in der aktuellen Tour '" + effectiveCurrent + "' duplizieren.", + style = MaterialTheme.typography.bodySmall, + color = MaterialTheme.colorScheme.onSurfaceVariant + ) } - } else { - Text( - text = "Es ist noch keine weitere Tour vorhanden. Du kannst diesen " + - "Wegpunkt aber in der aktuellen Tour „$effectiveCurrent“ duplizieren.", - style = MaterialTheme.typography.bodySmall, - color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.65f) - ) - } - // Zweite Aktion: Duplizieren in derselben Tour. Immer verfügbar, auch - // wenn keine andere Tour existiert — deckt den Single-Tour-Fall ab. - OutlinedButton( - onClick = { onCopy(effectiveCurrent) }, - modifier = Modifier.fillMaxWidth() - ) { - Text("In dieser Tour duplizieren („$effectiveCurrent“)") + Spacer(Modifier.height(6.dp)) + OutlinedButton( + onClick = { onCopy(effectiveCurrent) }, + modifier = Modifier.fillMaxWidth() + ) { + Text("In dieser Tour duplizieren (" + effectiveCurrent + ")") + } } } diff --git a/app/src/main/kotlin/de/waypointaudio/ui/WaypointListScreen.kt b/app/src/main/kotlin/de/waypointaudio/ui/WaypointListScreen.kt index 0bcf6cc..56f60fd 100644 --- a/app/src/main/kotlin/de/waypointaudio/ui/WaypointListScreen.kt +++ b/app/src/main/kotlin/de/waypointaudio/ui/WaypointListScreen.kt @@ -90,7 +90,9 @@ fun WaypointListScreen( ) { val context = LocalContext.current val waypoints by viewModel.waypoints.collectAsState() - val tourList by viewModel.tourList.collectAsState() + // v2.7.5 — visibleTourList blendet Standard-Tour aus der UI aus (Tabs, Dialoge), + // sobald echte Touren vorhanden sind. Intern bleibt sie als Fallback erhalten. + val tourList by viewModel.visibleTourList.collectAsState() val selectedTour by viewModel.selectedTour.collectAsState() val serviceRunning by viewModel.serviceRunning.collectAsState() val errorMessage by viewModel.errorMessage.collectAsState() @@ -160,6 +162,33 @@ fun WaypointListScreen( // statt als Bottom-Sheet angezeigt. Minimize stellt den Sheet-Modus // wieder her, ohne den Player-Zustand zu verlieren. var clipDetailFullscreen by remember { mutableStateOf(false) } + + // v2.7.32 — Player-Sichtbarkeits-Regression behoben. + // Wird ein Track/Clip manuell gestartet (Karten-Play-Button oder + // ManualPlayerBar), soll der etablierte GPS2Audio-Player (ClipDetailSheet / + // -Fullscreen) wieder automatisch erscheinen. Zuvor öffnete sich die + // Detailansicht nur durch Tippen auf die Karte; bei manuellem Start blieb + // der Player unsichtbar, obwohl Audio lief. + // Der Effekt folgt dem aktiv abgespielten Wegpunkt und öffnet die Ansicht, + // sobald Wiedergabe beginnt. Die bestehende Auto-Follow-Logik (Clip-Wechsel + // innerhalb geöffneter Ansicht) und manuelles Schließen bleiben unberührt: + // Schließt der Nutzer die Ansicht, wird sie erst beim nächsten Start eines + // anderen Wegpunkts wieder geöffnet. + val activePlaybackWaypointId: String? = when { + singlePlayingWaypointId != null -> singlePlayingWaypointId + manualPlaying -> currentPlayable?.waypointId + else -> null + } + LaunchedEffect(activePlaybackWaypointId) { + val activeId = activePlaybackWaypointId + if (activeId != null && + clipDetailWaypointId != activeId && + filteredWaypoints.any { it.id == activeId } + ) { + clipDetailWaypointId = activeId + } + } + var showOverflowMenu by remember { mutableStateOf(false) } var showAboutDialog by remember { mutableStateOf(false) } var showWakeLockDialog by remember { mutableStateOf(false) } @@ -459,22 +488,65 @@ fun WaypointListScreen( showNewTourDialog = true } ) + // v2.7.5 — Umbenennen/Duplizieren für Standard-Tour (Blueprint) sperren + val isSystemTour = selectedTour == Waypoint.DEFAULT_TOUR_NAME DropdownMenuItem( - text = { Text(stringResource(R.string.tour_rename)) }, - leadingIcon = { Icon(Icons.Filled.Edit, null) }, + text = { + Text( + stringResource(R.string.tour_rename), + color = if (isSystemTour) + MaterialTheme.colorScheme.onSurface.copy(alpha = 0.38f) + else + LocalContentColor.current + ) + }, + leadingIcon = { + Icon( + Icons.Filled.Edit, + null, + tint = if (isSystemTour) + MaterialTheme.colorScheme.onSurface.copy(alpha = 0.38f) + else + LocalContentColor.current + ) + }, onClick = { - showOverflowMenu = false - showRenameTourDialog = true - } + if (!isSystemTour) { + showOverflowMenu = false + showRenameTourDialog = true + } + }, + enabled = !isSystemTour ) // v2.5.15 — Tour als Variante duplizieren + // v2.7.5 — Duplizieren der Standard-Tour gesperrt DropdownMenuItem( - text = { Text("Tour duplizieren…") }, - leadingIcon = { Icon(Icons.Filled.ContentCopy, null) }, + text = { + Text( + "Tour duplizieren…", + color = if (isSystemTour) + MaterialTheme.colorScheme.onSurface.copy(alpha = 0.38f) + else + LocalContentColor.current + ) + }, + leadingIcon = { + Icon( + Icons.Filled.ContentCopy, + null, + tint = if (isSystemTour) + MaterialTheme.colorScheme.onSurface.copy(alpha = 0.38f) + else + LocalContentColor.current + ) + }, onClick = { - showOverflowMenu = false - showDuplicateTourDialog = true - } + if (!isSystemTour) { + showOverflowMenu = false + showDuplicateTourDialog = true + } + }, + enabled = !isSystemTour ) if (selectedTour == Waypoint.DEFAULT_TOUR_NAME) { // Standard-Tour kann nicht gelöscht werden – Eintrag deaktiviert diff --git a/app/src/main/kotlin/de/waypointaudio/viewmodel/WaypointViewModel.kt b/app/src/main/kotlin/de/waypointaudio/viewmodel/WaypointViewModel.kt index 896a9b5..1a94864 100644 --- a/app/src/main/kotlin/de/waypointaudio/viewmodel/WaypointViewModel.kt +++ b/app/src/main/kotlin/de/waypointaudio/viewmodel/WaypointViewModel.kt @@ -37,6 +37,7 @@ import java.util.Locale import java.util.UUID import de.waypointaudio.io.BackupImportManager import de.waypointaudio.io.ImportExportManager +import de.waypointaudio.ui.RoutePlan import de.waypointaudio.repository.WaypointRepository import de.waypointaudio.service.BackgroundMusicManager import de.waypointaudio.service.LivePttManager @@ -46,10 +47,13 @@ import de.waypointaudio.service.TrackRecordingManager import de.waypointaudio.service.WaypointLocationService import de.waypointaudio.service.MusicPlaybackState import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.first +import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.launch import kotlinx.coroutines.tasks.await import kotlinx.coroutines.withTimeout @@ -121,12 +125,42 @@ class WaypointViewModel(application: Application) : AndroidViewModel(application private val _tourList = MutableStateFlow>(listOf(Waypoint.DEFAULT_TOUR_NAME)) val tourList: StateFlow> = _tourList.asStateFlow() + /** + * v2.7.5 — Öffentlich sichtbare Tourliste für die UI (Audio-Bibliothek, Tabs). + * Die Standard-Tour (DEFAULT_TOUR_NAME) wird ausgeblendet, sobald mindestens + * eine echte (benutzerdefinierte) Tour existiert. Intern bleibt DEFAULT_TOUR_NAME + * stets als Fallback erhalten — Daten werden nicht gelöscht. + * Wenn keine echten Touren vorhanden sind, wird DEFAULT_TOUR_NAME als + * einziger Eintrag angezeigt (leerer Zustand für neue Nutzer). + */ + val visibleTourList: StateFlow> = _tourList + .map { list -> + val realTours = list.filter { it != Waypoint.DEFAULT_TOUR_NAME } + if (realTours.isEmpty()) listOf(Waypoint.DEFAULT_TOUR_NAME) else realTours + } + .stateIn( + scope = viewModelScope, + started = SharingStarted.Eagerly, + initialValue = listOf(Waypoint.DEFAULT_TOUR_NAME) + ) + /** * Set of tour names that have been deleted optimistically. * The combine collector must not re-add these from waypoint-derived tours. */ private val _deletedTours = mutableSetOf() + /** + * v2.7.14 — Neutral-Explorer-Modus-Flag. + * Wenn true, unterdrückt der combine-Kollektor den automatischen Upgrade + * von DEFAULT_TOUR_NAME zur ersten echten Tour. Das ermöglicht einen + * bewusst leeren Explorer-Einstieg aus der Übersicht/Audio-Bibliothek. + * Wird durch selectNeutralTourForNewExplorer() aktiviert und durch + * selectTour(echte Tour) oder upsertFromNeutralExplorer() wieder deaktiviert. + */ + @Volatile + private var _neutralExplorerMode: Boolean = false + /** * Aktuell ausgewählte Tour (für Tabs und Filter). */ @@ -163,6 +197,19 @@ class WaypointViewModel(application: Application) : AndroidViewModel(application private val _manualPlaying = MutableStateFlow(false) val manualPlaying: StateFlow = _manualPlaying.asStateFlow() + // v2.7.37 — Kurze Stille zwischen Clips/Wegpunkten bei der manuellen + // Sequenz-Wiedergabe ("Hörbuch-Gefühl"). Nur im Auto-Advance-Pfad der + // Tour-/Sequenz-Wiedergabe; NICHT bei GPS, PTT, Atmo oder Einzelclip-Vorschau. + // Bewusst kein UI-Setting und keine Persistenz — fester interner Wert. + private var manualGapJob: Job? = null + + /** Bricht eine laufende Auto-Advance-Pause ab, sodass kein verzögerter + * Start nach Stop/Pause/Skip/Tour-Wechsel mehr feuert. */ + private fun cancelManualGap() { + manualGapJob?.cancel() + manualGapJob = null + } + /** Name of the waypoint currently loaded in the manual player (null = nothing loaded). */ private val _manualCurrentName = MutableStateFlow(null) val manualCurrentName: StateFlow = _manualCurrentName.asStateFlow() @@ -265,6 +312,66 @@ class WaypointViewModel(application: Application) : AndroidViewModel(application get() = _activeTourRoute private val _activeTourRoute = MutableStateFlow(null) + // ─── Session-Route (v2.6.2) ─────────────────────────────────────────────── + // Hält die zuletzt im Explorer berechnete/geplante Route (OSRM oder Planlinie) + // für die aktuelle Tour. Überlebt Navigation/Workspace-Wechsel, da im ViewModel + // gespeichert. Wird beim Tourwechsel oder explizitem Löschen geleert. + // Kein Datenbankschreiben — dient ausschließlich der Session-Wiederherstellung. + // Enthält: tourName (zur Validierung) + TourRoute-Objekt. + private val _currentSessionRoute = + MutableStateFlow?>(null) + val currentSessionRoute: StateFlow?> = + _currentSessionRoute.asStateFlow() + + /** + * v2.6.2 — Speichert die aktuell berechnete/geplante Route für die laufende + * Explorer-Session. Wird nicht in die Datenbank geschrieben, sondern dient + * der Wiederherstellung der Kartenvisualisierung nach einem Workspace-Wechsel. + * Zusätzlich wird die Route dauerhaft als Tourroute persistiert, damit sie + * auch nach App-Neustart sichtbar ist. + */ + fun setCurrentSessionRoute( + tourName: String, + route: de.waypointaudio.data.TourRoute + ) { + _currentSessionRoute.value = tourName to route + // Gleichzeitig dauerhaft persistieren, damit activeTourRoute beim Zurückkehren + // die Route enthält und savedRouteLine sie als Backup zeichnet. + saveTourRouteFor(tourName, route) + } + + /** + * v2.6.2 — Löscht die Session-Route (z. B. beim Tourwechsel oder explizitem + * Löschen durch den Nutzer). Berührt nicht die persistente Tourroute. + */ + fun clearCurrentSessionRoute() { + _currentSessionRoute.value = null + } + + // ─── Session-Plan (v2.7.2) ─────────────────────────────────────────────── + // Hält den zuletzt genutzten RoutePlan (Start/Via/Ziel) pro Tour. + // Überlebt Navigation/Workspace-Wechsel, da im ViewModel gespeichert. + // Wird beim echten Tourwechsel geleert. Kein DB-Schreiben. + private val _currentSessionPlan = + MutableStateFlow?>(null) + val currentSessionPlan: StateFlow?> = + _currentSessionPlan.asStateFlow() + + /** + * v2.7.2 — Speichert den aktuellen RoutePlan für die laufende Session. + * Wird bei jedem Plan-Update aufgerufen (Start/Via/Ziel-Änderung). + */ + fun setCurrentSessionPlan(tourName: String, plan: RoutePlan) { + _currentSessionPlan.value = tourName to plan + } + + /** + * v2.7.2 — Löscht den Session-Plan (beim Tourwechsel oder explizitem Leeren). + */ + fun clearCurrentSessionPlan() { + _currentSessionPlan.value = null + } + // ─── Tour-Cover (v2.5.5) ────────────────────────────────────────────────── // Persistente Map tourName → TourCover. Wenn keine Auswahl existiert, // behält die UI ihre deterministische Standard-Optik (siehe TourHeroSection). @@ -301,6 +408,16 @@ class WaypointViewModel(application: Application) : AndroidViewModel(application if (current.isNotBlank() && current !in combined) { _selectedTour.value = combined.firstOrNull() ?: Waypoint.DEFAULT_TOUR_NAME } + // v2.7.5 — Wenn Standard-Tour ausgewählt ist, aber echte Touren existieren, + // automatisch zur ersten echten Tour wechseln. Standard bleibt interner Fallback. + // v2.7.14 — Wenn _neutralExplorerMode aktiv ist, wird dieser Upgrade NICHT + // durchgeführt: Explorer soll leer/neutral bleiben (Einstieg aus Übersicht). + if (_selectedTour.value == Waypoint.DEFAULT_TOUR_NAME && !_neutralExplorerMode) { + val firstReal = combined.firstOrNull { it != Waypoint.DEFAULT_TOUR_NAME } + if (firstReal != null) { + _selectedTour.value = firstReal + } + } } } // Begleitmusik-Einstellungen für die initiale Tour laden @@ -329,10 +446,15 @@ class WaypointViewModel(application: Application) : AndroidViewModel(application _activeTourRoute.value = map[_selectedTour.value] } } - // Beim Tourwechsel die aktive Tourroute aktualisieren. + // Beim Tourwechsel die aktive Tourroute und Session-Route aktualisieren. viewModelScope.launch { _selectedTour.collect { tour -> _activeTourRoute.value = _tourRoutes.value[tour] + // v2.6.2 — Session-Route leeren, wenn der Nutzer die Tour wechselt. + // So zeigt der Explorer nach einem Tourwechsel keine fremde Route. + _currentSessionRoute.value = null + // v2.7.2 — Session-Plan leeren beim Tourwechsel. + _currentSessionPlan.value = null } } // v2.5.5 — Tour-Cover beobachten. @@ -415,13 +537,59 @@ class WaypointViewModel(application: Application) : AndroidViewModel(application /** * v2.5.34 — Explorer-Kontext-Fix: - * Setzt die ausgewählte Tour auf den neutralen Standard zurück. - * Wird aufgerufen, wenn der Explorer aus der Audio-Bibliothek/Home - * geöffnet wird, damit kein zuletzt aktiver Tour-Kontext übernommen wird. + * Setzt die ausgewählte Tour auf den neutralen Standard zurück, + * AUSSER wenn bereits echte (nicht-Standard) Touren existieren – + * dann wird direkt die erste echte Tour gewählt. + * + * v2.7.10 — Waypoint-Persistence-Fix: + * Wenn eine spontane "Unbenannte Tour" im Explorer erzeugt wurde und der + * Nutzer den Explorer verlässt und erneut öffnet, darf selectDefaultTour() + * nicht blind auf DEFAULT zurückspringen und die frisch erstellten Wegpunkte + * hinter einem Tour-Filter verstecken. Stattdessen: Wenn echte Touren + * vorhanden sind, sofort zur ersten echten Tour wechseln (gleiche Logik wie + * im combine-Kollektor, aber synchron, um Race Conditions zu vermeiden). + * * Der GPS-Dienst und die Wiedergabe werden dabei NICHT unterbrochen. */ fun selectDefaultTour() { - selectTour(de.waypointaudio.data.Waypoint.DEFAULT_TOUR_NAME) + val knownTours = _tourList.value + val firstReal = knownTours.firstOrNull { it != de.waypointaudio.data.Waypoint.DEFAULT_TOUR_NAME } + if (firstReal != null) { + // Echte Touren existieren – direkt zur ersten echten Tour wechseln. + // Kein Rücksprung auf DEFAULT_TOUR_NAME, damit Wegpunkte sichtbar bleiben. + selectTour(firstReal) + } else { + // Keine echten Touren – Standard-Tour ist der einzig sinnvolle Zustand. + selectTour(de.waypointaudio.data.Waypoint.DEFAULT_TOUR_NAME) + } + } + + /** + * v2.7.14 — Neutraler Explorer-Start aus der Übersicht/Audio-Bibliothek. + * + * Setzt selectedTour explizit auf DEFAULT_TOUR_NAME ("Unbenannte Tour") und + * aktiviert den Neutral-Explorer-Modus-Flag, der den automatischen Upgrade + * durch den combine-Kollektor (v2.7.5-Logik) verhindert. + * + * Konzept: + * - Explorer aus Audio-Bibliothek/Übersicht → diese Funktion → leerer Kontext + * - Explorer aus Touransicht/WaypointListScreen → selectTour(tourName) bleibt unverändert + * + * Der Flag wird zurückgesetzt, sobald: + * a) der Nutzer einen Wegpunkt im neutralen Kontext setzt (upsertFromNeutralExplorer) + * b) der Nutzer explizit eine echte Tour über selectTour() auswählt + */ + fun selectNeutralTourForNewExplorer() { + _neutralExplorerMode = true + // Direkt auf DEFAULT setzen; selectTour() würde den Guard auslösen (DEFAULT nicht in + // knownTours wenn nur echte Touren existieren), daher direktes Assignment. + _selectedTour.value = de.waypointaudio.data.Waypoint.DEFAULT_TOUR_NAME + musicManager.loadTour(de.waypointaudio.data.Waypoint.DEFAULT_TOUR_NAME) + viewModelScope.launch { + loadMusicSettingsForCurrentTour() + loadTourDefaultsForCurrentTour() + loadPersistedTrackForCurrentTour() + } } fun selectTour(tourName: String) { @@ -429,6 +597,17 @@ class WaypointViewModel(application: Application) : AndroidViewModel(application val knownTours = _tourList.value val safeTarget = if (tourName in knownTours || knownTours.isEmpty()) tourName else knownTours.first() + // v2.7.14 — Wechsel zu einer echten Tour deaktiviert den Neutral-Explorer-Modus. + if (safeTarget != de.waypointaudio.data.Waypoint.DEFAULT_TOUR_NAME) { + _neutralExplorerMode = false + } + // v2.7.38 — Audio-Zuverlässigkeit: Ein evtl. anstehender Auto-Advance- + // Gap-Job gehört zur alten Tour. Beim Tour-Wechsel abbrechen, damit kein + // verspäteter Start in der falschen Tour feuert. Aktiv laufende + // Wiedergabe bleibt davon unberührt (Persistenz, s. u.). + if (safeTarget != _selectedTour.value) { + cancelManualGap() + } _selectedTour.value = safeTarget // v2.5.30 — Playback-Persistenz beim Tour-Wechsel: // Laufende Wiedergabe (manuell oder GPS-gesteuert) wird beim blossen @@ -467,7 +646,12 @@ class WaypointViewModel(application: Application) : AndroidViewModel(application // Use direct assignment instead of selectTour() to avoid triggering // music-loading coroutine before the tour list is fully stable. _selectedTour.value = trimmed + // v2.7.14 — Neue echte Tour erstellt: Neutral-Explorer-Modus deaktivieren. + if (trimmed != de.waypointaudio.data.Waypoint.DEFAULT_TOUR_NAME) { + _neutralExplorerMode = false + } // Reset manual player state + cancelManualGap() manualPlayer.stop() _manualPlaying.value = false _manualCurrentName.value = null @@ -493,20 +677,78 @@ class WaypointViewModel(application: Application) : AndroidViewModel(application return true } + /** + * v2.7.7 — Spontane-Tour-Autocreate (v2.7.8: "Unbenannte Tour"): + * Erzeugt eine neue echte Tour mit eindeutigem Namen ("Unbenannte Tour", + * "Unbenannte Tour 2", usw.) und wählt sie sofort als selectedTour. + * Wird aufgerufen, wenn im neutralen Explorer-Kontext (selectedTour == + * DEFAULT_TOUR_NAME) der erste Wegpunkt gesetzt wird. + * Rückgabe: der Name der neu erzeugten Tour. + * Interner Funktionsname bleibt createSpontaneousTour() für minimales Risiko. + */ + fun createSpontaneousTour(): String { + val base = "Unbenannte Tour" + val existing = _tourList.value + var candidate = base + var counter = 2 + while (candidate in existing) { + candidate = "$base $counter" + counter++ + } + addTour(candidate) // setzt auch _selectedTour auf candidate + return candidate + } + + /** + * v2.7.7 — Upsert-Wrapper für den neutralen Explorer-Kontext. + * Wenn [waypoint].tourName == DEFAULT_TOUR_NAME (neutral), wird automatisch + * eine neue Spontane Tour erzeugt, [waypoint] auf diese Tour umgeschrieben + * und erst dann gespeichert. Danach ist selectedTour = neue Tour. + * In allen anderen Kontexten verhält sich diese Funktion identisch zu [upsert]. + */ + fun upsertFromNeutralExplorer(waypoint: Waypoint) { + val isNeutral = waypoint.tourName.ifBlank { Waypoint.DEFAULT_TOUR_NAME } == Waypoint.DEFAULT_TOUR_NAME + if (isNeutral) { + val newTourName = createSpontaneousTour() + val adjusted = waypoint.copy(tourName = newTourName) + upsert(adjusted) + } else { + upsert(waypoint) + } + } + /** * Verschiebt eine Tour in der Tab-Reihenfolge. * Index-Verschiebung: from → to. Ungültige Indizes werden ignoriert. * Persistiert die neue Reihenfolge sofort. */ fun moveTour(fromIndex: Int, toIndex: Int) { - val current = _tourList.value.toMutableList() - if (fromIndex !in current.indices || toIndex !in current.indices) return + // v2.7.32 — Bugfix: Die Reorder-UI (TourReorderDialog) arbeitet auf + // visibleTourList (Standard-Tour ausgeblendet), moveTour operierte aber + // direkt auf _tourList (inkl. DEFAULT_TOUR_NAME). Lag die Standard-Tour + // an Index 0, ergab sich ein Off-by-one, wodurch die erste und letzte + // SICHTBARE Tour faktisch nicht mehr verschoben werden konnten. + // Fix: Indizes beziehen sich auf die sichtbare Liste; die ausgeblendete + // Standard-Tour behält ihre relative Position in _tourList. + val full = _tourList.value + val visible = full.filter { it != Waypoint.DEFAULT_TOUR_NAME } + if (fromIndex !in visible.indices || toIndex !in visible.indices) return if (fromIndex == toIndex) return - val item = current.removeAt(fromIndex) - current.add(toIndex, item) - _tourList.value = current + + val reorderedVisible = visible.toMutableList() + val item = reorderedVisible.removeAt(fromIndex) + reorderedVisible.add(toIndex, item) + + // Merge zurück nach _tourList: ausgeblendete Standard-Tour(en) an ihrer + // ursprünglichen relativen Position erhalten, sichtbare Touren in neuer + // Reihenfolge einsetzen. + val iter = reorderedVisible.iterator() + val merged = full.map { name -> + if (name == Waypoint.DEFAULT_TOUR_NAME) name else iter.next() + } + _tourList.value = merged viewModelScope.launch { - runCatching { repository.saveTours(current) } + runCatching { repository.saveTours(merged) } .onFailure { e -> android.util.Log.e("WaypointViewModel", "Fehler beim Speichern der Tour-Reihenfolge", e) } @@ -558,10 +800,13 @@ class WaypointViewModel(application: Application) : AndroidViewModel(application viewModelScope.launch { val updated = current.map { if (it == oldName) trimmed else it } repository.saveTours(updated) - val updatedWps = _waypoints.value.map { + // v2.7.21 — Race-Condition-Fix: Direkt aus DataStore lesen. + val freshWps = runCatching { repository.waypoints.first() } + .getOrDefault(_waypoints.value) + val updatedWps = freshWps.map { if (it.tourName == oldName) it.copy(tourName = trimmed) else it } - repository.saveAll(updatedWps) + repository.saveAllForced(updatedWps) // v2.4.6 — Tourroute-Eintrag mitziehen, damit die Route nicht // verwaist unter dem alten Namen liegen bleibt. runCatching { repository.renameTourRouteKey(oldName, trimmed) } @@ -596,7 +841,14 @@ class WaypointViewModel(application: Application) : AndroidViewModel(application } } - /** Speichert/ersetzt die Route für eine konkrete Tour (nicht zwingend die aktive). */ + /** + * Speichert/ersetzt die Route für eine konkrete Tour (nicht zwingend die aktive). + * + * v2.7.21 — Waypoint-Preservation-Invariante: + * Diese Funktion schreibt AUSSCHLIESSLICH in KEY_TOUR_ROUTES. + * Audio-Wegpunkte (KEY_WAYPOINTS) werden durch diesen Aufruf NIEMALS verändert. + * Der Routenplaner darf diese Funktion frei nutzen. + */ fun saveTourRouteFor(tourName: String, route: de.waypointaudio.data.TourRoute) { viewModelScope.launch { runCatching { @@ -726,6 +978,10 @@ class WaypointViewModel(application: Application) : AndroidViewModel(application val nextTour = current.firstOrNull() ?: Waypoint.DEFAULT_TOUR_NAME if (_selectedTour.value == tourName) { // Reset manual player state + // v2.7.38 — Auch den anstehenden Auto-Advance-Gap-Job abbrechen, + // sonst startet er 1,7 s nach dem Stop fälschlich erneut Audio + // gegen die gerade gelöschte Tour. + cancelManualGap() manualPlayer.stop() _manualPlaying.value = false _manualCurrentName.value = null @@ -739,10 +995,17 @@ class WaypointViewModel(application: Application) : AndroidViewModel(application viewModelScope.launch { runCatching { repository.saveTours(current) - val updatedWps = _waypoints.value.map { + // v2.7.21 — Race-Condition-Fix: Direkt aus DataStore lesen statt + // _waypoints.value, um sicherzustellen, dass keine Wegpunkte verloren + // gehen, falls _waypoints.value noch nicht vollständig geladen ist. + val freshWps = runCatching { repository.waypoints.first() } + .getOrDefault(_waypoints.value) + val updatedWps = freshWps.map { if (it.tourName == tourName) it.copy(tourName = Waypoint.DEFAULT_TOUR_NAME) else it } - repository.saveAll(updatedWps) + // Forciert schreiben, da dies eine bewusste Mutations-Operation ist + // (Tour-Löschung mit Reassignment auf DEFAULT_TOUR_NAME). + repository.saveAllForced(updatedWps) // Clear GPS track for the deleted tour repository.clearGpsTrack(tourName) // v2.4.6 — Gespeicherte Tourroute beim Löschen entfernen @@ -885,7 +1148,13 @@ class WaypointViewModel(application: Application) : AndroidViewModel(application else base.withClips(newClips) } if (newWps.isNotEmpty()) { - repository.saveAll(_waypoints.value + newWps) + // v2.7.21 — Race-Condition-Fix: Statt _waypoints.value (könnte noch + // leer sein, wenn der DataStore-Lade-Coroutine noch nicht feuerte) + // direkt aus dem DataStore lesen. Das garantiert die vollständige + // Wegpunktliste und verhindert versehentlichen Datenverlust. + val currentWps = runCatching { repository.waypoints.first() } + .getOrDefault(_waypoints.value) + repository.saveAll(currentWps + newWps) } // Tour-Cover, Tour-Route und Tour-Defaults referenziell mitkopieren. runCatching { @@ -1193,49 +1462,68 @@ class WaypointViewModel(application: Application) : AndroidViewModel(application ) { viewModelScope.launch { val ctx = getApplication() - val gpsTracks = runCatching { repository.gpsTracks.first() }.getOrDefault(emptyMap()) - val tourDefaultsMap = runCatching { - repository.tourDefaults.first() - }.getOrDefault(emptyMap()) - val musicSettingsMap = runCatching { - musicStore.settingsFlow.first() - }.getOrDefault(emptyMap()) + // v2.7.36 FIX: Das gesamte Backup (Flow-Reads, ZIP-Aufbau und das + // chunk-weise Kopieren aller Mediendateien) lief bisher direkt im + // viewModelScope auf dem Main-Dispatcher. Bei Backups mit Medien + // blockierte das den UI-Thread für Sekunden → ANR ("App reagiert + // nicht / Absturz"), obwohl die Datei erfolgreich geschrieben wurde. + // Wie der Import-Pfad läuft die schwere IO jetzt auf Dispatchers.IO; + // die State-Updates für Erfolg/Fehler bleiben danach auf Main. + val result = runCatching { + kotlinx.coroutines.withContext(kotlinx.coroutines.Dispatchers.IO) { + val gpsTracks = runCatching { repository.gpsTracks.first() }.getOrDefault(emptyMap()) + val tourDefaultsMap = runCatching { + repository.tourDefaults.first() + }.getOrDefault(emptyMap()) + val musicSettingsMap = runCatching { + musicStore.settingsFlow.first() + }.getOrDefault(emptyMap()) - val pkgInfo = runCatching { - ctx.packageManager.getPackageInfo(ctx.packageName, 0) - }.getOrNull() - @Suppress("DEPRECATION") - val versionCode = pkgInfo?.let { - runCatching { it.longVersionCode.toInt() } - .getOrDefault(it.versionCode) - } ?: 0 + val pkgInfo = runCatching { + ctx.packageManager.getPackageInfo(ctx.packageName, 0) + }.getOrNull() + @Suppress("DEPRECATION") + val versionCode = pkgInfo?.let { + runCatching { it.longVersionCode.toInt() } + .getOrDefault(it.versionCode) + } ?: 0 - val tourRoutesMap = runCatching { repository.tourRoutes.first() }.getOrDefault(emptyMap()) - val tourCoversMap = runCatching { repository.tourCovers.first() }.getOrDefault(emptyMap()) - // v2.5.48 — Echte TrackDraft-Objekte für Backup lesen (nicht gpsTracks). - val trackDraftsSnapshot = runCatching { repository.trackDrafts.first() }.getOrDefault(emptyList()) + val tourRoutesMap = runCatching { repository.tourRoutes.first() }.getOrDefault(emptyMap()) + val tourCoversMap = runCatching { repository.tourCovers.first() }.getOrDefault(emptyMap()) + // v2.5.48 — Echte TrackDraft-Objekte für Backup lesen (nicht gpsTracks). + val trackDraftsSnapshot = runCatching { repository.trackDrafts.first() }.getOrDefault(emptyList()) + + val input = de.waypointaudio.io.BackupExportManager.BackupInput( + waypoints = _waypoints.value, + tours = _tourList.value, + tourDefaults = tourDefaultsMap, + gpsTracks = gpsTracks, + musicSettings = musicSettingsMap, + tourRoutes = tourRoutesMap, + tourCovers = tourCoversMap, + trackDrafts = trackDraftsSnapshot, + appVersionName = pkgInfo?.versionName ?: "", + appVersionCode = versionCode + ) + val selection = de.waypointaudio.io.BackupExportManager.BackupSelection( + toursAndWaypoints = toursAndWaypoints, + trackDrafts = trackDrafts, + mediaAndAtmo = mediaAndAtmo, + settings = settings + ) + de.waypointaudio.io.BackupExportManager.writeBackup( + ctx, uri, selection, input + ) + } + }.getOrElse { e -> + // Falls trotz interner Absicherung etwas Unerwartetes durchschlägt + // (z. B. SecurityException auf der Ziel-URI): nicht abstürzen, + // sondern als nicht-fataler Fehler melden. + de.waypointaudio.io.BackupExportManager.BackupResult( + errorMessage = "Backup-Fehler: ${e.localizedMessage ?: e.javaClass.simpleName}" + ) + } - val input = de.waypointaudio.io.BackupExportManager.BackupInput( - waypoints = _waypoints.value, - tours = _tourList.value, - tourDefaults = tourDefaultsMap, - gpsTracks = gpsTracks, - musicSettings = musicSettingsMap, - tourRoutes = tourRoutesMap, - tourCovers = tourCoversMap, - trackDrafts = trackDraftsSnapshot, - appVersionName = pkgInfo?.versionName ?: "", - appVersionCode = versionCode - ) - val selection = de.waypointaudio.io.BackupExportManager.BackupSelection( - toursAndWaypoints = toursAndWaypoints, - trackDrafts = trackDrafts, - mediaAndAtmo = mediaAndAtmo, - settings = settings - ) - val result = de.waypointaudio.io.BackupExportManager.writeBackup( - ctx, uri, selection, input - ) if (result.errorMessage != null) { _errorMessage.value = result.errorMessage } else { @@ -1352,7 +1640,9 @@ class WaypointViewModel(application: Application) : AndroidViewModel(application // ---- Persistieren ---- runCatching { if (toursAndWaypoints) { - repository.saveAll(payload.mergedWaypoints) + // v2.7.21 — Backup-Restore ist ein forcierter Vollersatz; Preservation-Guard + // nicht anwenden (mergedWaypoints kann leer sein bei leeren Backups). + repository.saveAllForced(payload.mergedWaypoints) if (payload.mergedTours != existingTours) { repository.saveTours(payload.mergedTours) } @@ -1567,6 +1857,17 @@ class WaypointViewModel(application: Application) : AndroidViewModel(application _singlePlayingActive.value = false } + // v2.7.37 — Während der Stille-Pause läuft kein MediaPlayer, der State + // ist aber "playing". Pause-Tippen soll dann die Auto-Advance-Pause + // abbrechen und nicht neu starten. + if (manualGapJob != null) { + cancelManualGap() + _manualPlaying.value = false + stopProgressTicker(keepSnapshot = true) + musicManager.afterWaypointAudio() + return + } + if (manualPlayer.isPlaying) { manualPlayer.pause() _manualPlaying.value = false @@ -1655,6 +1956,10 @@ class WaypointViewModel(application: Application) : AndroidViewModel(application */ private fun startPlayableAt(sequence: List, seqIndex: Int) { if (sequence.isEmpty()) return + // v2.7.37 — Jede neue Playback-Entscheidung (Skip/Play/Resume) bricht + // eine evtl. laufende Auto-Advance-Stille ab, damit kein verspäteter + // Start den frisch gewählten Clip überschreibt. + cancelManualGap() val safeIdx = seqIndex.coerceIn(0, sequence.size - 1) val item = sequence[safeIdx] _manualIndex.value = item.waypointIndex - 1 @@ -1684,7 +1989,18 @@ class WaypointViewModel(application: Application) : AndroidViewModel(application title = title, tour = _selectedTour.value ) - manualPlayer.play(ctx, item.uri) { + manualPlayer.play(ctx, item.uri, onError = { + // v2.7.38 — Wiedergabe konnte nicht starten (z. B. Samsung-SAF-/ + // Codec-Fehler). Zustand sauber zurücksetzen statt "spielt" ohne + // Ton anzuzeigen, und den Nutzer informieren. + cancelManualGap() + _manualPlaying.value = false + _manualCurrentName.value = null + _currentPlayable.value = null + stopProgressTicker(keepSnapshot = false) + musicManager.afterWaypointAudio() + _errorMessage.value = "Audio konnte nicht abgespielt werden. Bitte erneut versuchen." + }) { if (!autoAdvance) { _manualPlaying.value = false _manualCurrentName.value = null @@ -1712,9 +2028,57 @@ class WaypointViewModel(application: Application) : AndroidViewModel(application return@play } val nextItem = nextSeq[nextIdx] - _currentPlayable.value = nextItem - _manualIndex.value = nextItem.waypointIndex - 1 - playFromCurrentPlayable(autoAdvance = true) + // v2.7.37 — Kurze Stille vor dem nächsten Eintrag (Hörbuch-Gefühl). + // Läuft als abbrechbarer Job: Pause/Stop/Skip/Tour-Wechsel rufen + // cancelManualGap() und verhindern so einen verspäteten Auto-Start. + // Die Sequenz wird NACH der Pause erneut ausgewertet, da sich der + // Zustand (PTT, gelöschte Wegpunkte, deaktivierte Clips) während der + // Wartezeit ändern kann. + // + // v2.7.38 — Audio-Zuverlässigkeit (Samsung-Regressionsfix): + // Die Gap ist STRIKT auf den Auto-Advance NACH einem natürlich + // beendeten Clip beschränkt. Sie darf den Folge-Clip nur dann + // starten, wenn währenddessen weder die Tour gewechselt wurde noch + // der Nutzer pausiert/gestoppt hat. Andernfalls wird der verzögerte + // Start verworfen, statt den Zustand fälschlich auf "spielt" zu + // lassen oder Audio in der falschen Tour zu starten. + val gapTour = _selectedTour.value + cancelManualGap() + manualGapJob = viewModelScope.launch { + delay(MANUAL_GAP_MS) + manualGapJob = null + // Tour gewechselt während der Stille → kein Auto-Advance. + // Laufende/zukünftige Wiedergabe der anderen Tour nicht stören; + // nur den eigenen verspäteten Start verwerfen. + if (_selectedTour.value != gapTour) { + return@launch + } + // Nutzer hat während der Stille pausiert/gestoppt + // (z. B. Pause-Tippen, Stop, neuer Single-Clip) → nicht starten. + if (!_manualPlaying.value || manualPlayer.isSingleMode) { + return@launch + } + if (pttManager.pttActive.value) { + _manualPlaying.value = false + stopProgressTicker(keepSnapshot = true) + return@launch + } + val seqAfterGap = playableSequence() + val resolvedIdx = seqAfterGap.indexOfFirst { it.compoundId == nextItem.compoundId } + if (resolvedIdx < 0) { + // Nächster Eintrag existiert nicht mehr → sauber stoppen. + _manualPlaying.value = false + _manualCurrentName.value = null + _currentPlayable.value = null + stopProgressTicker(keepSnapshot = false) + musicManager.afterWaypointAudio() + return@launch + } + val resolved = seqAfterGap[resolvedIdx] + _currentPlayable.value = resolved + _manualIndex.value = resolved.waypointIndex - 1 + playFromCurrentPlayable(autoAdvance = true) + } } startProgressTicker() } @@ -1737,6 +2101,7 @@ class WaypointViewModel(application: Application) : AndroidViewModel(application /** Stop manual playback completely (both playlist and single mode). */ fun manualStop() { + cancelManualGap() manualPlayer.stop() _manualPlaying.value = false _singlePlayingWaypointId.value = null @@ -1816,6 +2181,11 @@ class WaypointViewModel(application: Application) : AndroidViewModel(application val wpName = waypoint.name.ifBlank { "Wegpunkt" } val displayName = if (clipTitle.isBlank()) wpName else "$wpName · $clipTitle" + // v2.7.37 — Einzelclip-Vorschau übernimmt: eine evtl. laufende + // Auto-Advance-Stille der Tour-Sequenz abbrechen, sonst würde der + // verzögerte Start die Vorschau überschreiben. + cancelManualGap() + // Tour-Play beenden, falls aktiv. if (_manualPlaying.value && !manualPlayer.isSingleMode) { manualPlayer.stop() @@ -2362,5 +2732,12 @@ class WaypointViewModel(application: Application) : AndroidViewModel(application * Akku spürbar gegenüber häufigeren Ticks. */ private const val PROGRESS_TICK_MS = 500L + + /** + * v2.7.37 — Feste Stille-Pause vor dem automatischen Start des nächsten + * Eintrags in der manuellen Sequenz-Wiedergabe (Clip→Clip und + * Wegpunkt→Wegpunkt). Gibt der Wiedergabe ein hörbuchartiges Gefühl. + */ + private const val MANUAL_GAP_MS = 1700L } } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 8d65e2c..46877cf 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -251,6 +251,10 @@ Viele Grüße Neu in 2.5.23: Lizenzimport-Regression-Fix. Erstimport nach Neuinstallation funktioniert wieder zuverlässig. Dateiauswahl nutzt wieder OpenDocument() (echter Datei-Browser) statt GetContent() (das auf manchen Geräten nur Medien anzeigt). Reimport derselben Datei nach „Lizenz entfernen“ funktioniert via importNonce-Mechanismus. Fehlermeldungen (aus v2.5.22) bleiben differenziert. Geräte-ID und alle anderen Funktionen aus v2.5.21/v2.5.22 bleiben unverändert. Neu in 2.5.21: Lizenz-Re-Import-Bugfix und Geräte-ID. Der Lizenzimport funktioniert jetzt zuverlässig auch nach Entfernen und erneutem Importieren einer Lizenzdatei. Außerdem zeigt der Lizenz-Bereich jetzt eine Geräte-ID an (SHA-256-Hash) — für spätere optionale gerätegebundene Lizenzen. In dieser Version ist keine harte Gerätebindung aktiv. Alle bisherigen Funktionen aus v2.5.20 bleiben unverändert. Neu in 2.5.19: Menü- und UX-Politur. Der Eintrag „Track Editor" wurde aus dem Hauptmenü entfernt – die Funktion ist über den Explorer weiterhin vollständig erreichbar. „Klassische Ansicht" heißt jetzt „Bearbeitungsmodus" (klarere Begriffswahl). „Touren ordnen" liegt jetzt im Menü der Audio-Bibliothek (Hauptseite) und nicht mehr in der einzelnen Touransicht. Tour-Cover (Bild, Icon, Palette) werden weiterhin als Teil des ZIP-Backups exportiert und beim Import wiederhergestellt. Alle bisherigen Funktionen – additiver GPX-Import, Lizenz/Pro/About, Multi-Clip, Sequenzplayer, Countdown, maximierbarer Player, Tour duplizieren, Waypoint kopieren, Explorer/MapLibre/Routing, PTT/Atmo, Hintergrundwiedergabe – bleiben unverändert. + + Neu in 2.7.16 (RoutePlanner Restore): Der direkte Routen-Planer (Start/Ziel/Via, Planlinie, Online-Routing) war in v2.7.15 faelschlicherweise entfernt worden. Er ist jetzt wiederhergestellt. Es gibt nun zwei klar benannte Einstiege: (1) "Route planen" (AltRoute-Icon, blau) = RoutePlannerSheet mit Start/Ziel/Via, Planlinie und optionalem Online-Routing via OSRM; (2) "Tourverlauf bearbeiten" (Stift-Icon) = TourverlaufEditorSheet fuer manuelles Zeichnen/Setzen von Verlaufspunkten. Beide sind als FAB auf der Karte und im Layer-Panel zugaenglich. Karten-Rendering, Waypoints, Planlinie, Explorer-Kontext-Isolation: keine Aenderung. + Neu in 2.7.15 (Tourverlauf-Menü-Merge): Die beiden Menüpunkte „Tourverlauf Anpassung“ (Routenplaner) und „Tourverlauf bearbeiten“ (Editor) sind zu einem einzigen Einstieg zusammengeführt. Es gibt jetzt nur noch einen FAB-Knopf „Tourverlauf“ im Explorer — der öffnet den Tourverlauf-Editor, der Zeichnen, Punkte setzen und (optional) Online-Routing in einem Sheet bietet. Das Layer-Panel zeigt ebenfalls nur noch den einheitlichen Tourverlauf-Einstieg. Alle internen Funktionen (Planlinie, Online-Routing via OSRM, Speichern/Löschen des Tourverlaufs) bleiben vollständig erhalten. Karten-Rendering, Waypoints, Planlinie, Explorer-Kontext-Isolation: keine Änderung. + Neu in 2.6.0 (Tourverlauf/Storyboard): Der bisherige Routenplaner heißt jetzt „Tourverlauf“ — klar als manueller Verlauf ohne Auto-Navi-Erwartung. Verlaufspunkte (stille Orientierungspunkte) und Audio-Wegpunkte werden in Labels und Erklärtexten klar unterschieden. Online-Routing (OSRM) bleibt erhalten, wird aber als optional/experimentell eingestuft — die Planlinie genügt für den Tourverlauf. Das Storyboard-Panel erklärt den Unterschied: Tourverlaufspunkte = Linie, Wegpunkte = Audio. Keine Änderung an Logik, Backup, Lizenz, radiusbasiertem Playback oder GPS-Aufzeichnung. Alle v2.5.48-Funktionen bleiben vollständig erhalten. Neu in 2.5.1: Design-Harmonisierung der sekundären Bereiche. Die Tour-/Waypoint-Ansicht, klassische Hauptansicht, PTT-Bereich, Atmo/Stream-Playlist, Track-Entwürfe, Backup/Import sowie About-Dialog nutzen jetzt die gleiche GPS2Audio-Farbwelt wie die neue Startseite: dunkle Surface-Karten, türkise Primäraktionen, magenta/destruktiv, grün/aktiv, weichere Cards und kompaktere Listen. Tabs, Top-App-Bars und Dialoge wirken ruhiger und moderner, ohne dass Funktionen entfallen: Explorer, MapLibre, Routenplaner, POI, PTT, Atmo/Stream-Playlist, Recorder, Backup/Import, About/PayPal, Drag-and-drop/Sortierung, TourRoute-Persistenz und Classic-Fallback bleiben unverändert erreichbar. Wegpunkte lassen sich weiterhin direkt per Drag-and-drop verschieben. Neu in 2.4.0: MapLibre Engine Cutover — der Explorer rendert jetzt aktiv mit MapLibre Native (org.maplibre.gl 11.x), nicht mehr mit osmdroid. Wegpunkte, Standort/Follow, Trigger-Radius/Audiozone, GPS-Track, Drafts, Storyboard, Routing/POI-MVP, Suche und Tap-Editiermodus sind 1:1 portiert. Echter Pitch/Tilt für den Perspektiv-Modus über MapLibre-Kamera. Clip-Längenlinien werden ab jetzt nur noch entlang einer bekannten Geometrie (aufgezeichneter Track/Draft oder berechnete OSRM-Route) gezeichnet — keine freien Projektionen mehr. Bestehende Funktionen (Backup, PTT, Atmo, Audio-Bibliothek, Touren ordnen, Drag-and-drop, About/PayPal) unverändert. Der osmdroid-Renderer bleibt im Quelltext als dokumentierter Fallback erhalten, ist aber nicht mehr sichtbar verdrahtet. @@ -310,17 +314,19 @@ Viele Grüße Info / Quelle Satellit nutzt standardmäßig ESRI World Imagery (kostenfrei für persönliche/nicht-kommerzielle Nutzung, Attribution „Tiles © Esri\"). Eigene Tile-URL ist möglich, z. B. self-hosted oder ein anderer Anbieter. Es werden keine kostenpflichtigen APIs erzwungen. Perspektive aktiv: geneigte Kameraansicht als Vorschau. Echtes 3D-Terrain (DEM) folgt mit dem MapLibre-Native-Renderer. - Routenplaner - Folgt — kein externer Routingdienst aktiv. Self-hosted OSRM/Valhalla/GraphHopper geplant. + Tourverlauf-Planer + Kein externer Routingdienst aktiv. Online-Routing optional via Self-hosted OSRM/Valhalla/GraphHopper. MapLibre Demotiles (frei) - Routenplaner folgt - GPS2Audio v2.3.0 enthält bewusst keine Routing-Engine. Ein vollwertiger Routenplaner würde entweder einen externen, kostenpflichtigen Dienst benötigen (vermieden) oder eine self-hosted Engine (z. B. OSRM, Valhalla, GraphHopper) bzw. einen Offline-Routing-Ansatz. Die nächste Version bindet eine der genannten Engines an – das vorhandene Storyboard bleibt Eingabe. + Tourverlauf-Planer + GPS2Audio verwendet keinen Navigations-Routenplaner. Der Tourverlauf wird manuell gesetzt — keine Online-Routing-Pflicht, keine Kosten. Optionales Online-Routing via Self-hosted OSRM/Valhalla/GraphHopper kann konfiguriert werden. Tiles © Esri Satellit: eigene Tile-Quelle Audio-Dauer: %1$s Explorer + + Unbenannte Tour Explorer öffnen Karte · Standort · Wegpunkte (read-only) Standort nicht verfügbar — Berechtigung oder GPS prüfen. @@ -347,22 +353,25 @@ Viele Grüße Tap-Modus abbrechen Karteneditor (Track / Drafts) - - Karte · Standort · Wegpunkte · GPS-Aufzeichnung · Drafts · Storyboard + + Karte · Standort · Wegpunkte · GPS-Aufzeichnung · Drafts · Tourverlauf Aufzeichnung läuft · %1$d Punkte Draft aktiv: %1$s · %2$d Punkte · %3$d markiert Aufgenommene Tracks (Drafts) Aufgenommene Tracks Wähle einen Draft, um seine Punkte direkt im Explorer zu sehen und zu bearbeiten. Detaillierte Bearbeitung im Vollbild-Editor weiterhin verfügbar. - Storyboard / Routenplanung - Storyboard / Routenplanung - Bring die Wegpunkte der aktuellen Tour in eine gewünschte Reihenfolge und speichere sie als neue (oder bestehende) Tour. Kein Straßen-Routing — eine konzeptionelle Tour-Zusammenstellung. + + Tourverlauf (Storyboard) + Tourverlauf + Ordne die Audio-Wegpunkte entlang der Route in die gewünschte Reihenfolge. Tourpunkte ohne Audio formen die Linie, Wegpunkte mit Audio lösen den Ton aus. Zieltour (Name) - Keine Wegpunkte in der aktuellen Tour. Lege erst welche im Explorer an. + Keine Wegpunkte in der aktuellen Tour. Lege erst Wegpunkte im Explorer an. Nach oben Nach unten Reihenfolge übernehmen - Hinweis: Es wird keine externe Routing-Engine verwendet (keine API, keine Kosten). Das Storyboard ist eine geordnete Wegpunkt-Liste — Entwurfsstatus. + Tourpunkte ohne Audio formen die Routenlinie. Wegpunkte mit Audio lösen den Ton aus. Audio kann jederzeit nachträglich hinzugefügt werden. + + Route zuerst: Tourpunkte formen die Linie. Audio wird bewusst an einzelne Punkte angehängt. Trackpunkt %1$d Aktiviere zuerst einen Draft im Drafts-Sheet, um Trackpunkte zu bearbeiten. Tippe die neue Position an — der gewählte Trackpunkt wird dorthin verschoben. @@ -454,6 +463,25 @@ Viele Grüße Tour: %1$s Begleitmusik aktivieren + + Musik zur Tour + Aktiv für diese Tour + Aus – tippe zum Aktivieren + %1$d Titel in der Playlist + 1 Titel in der Playlist + %1$d Sender / Streams + 1 Sender / Stream + Noch keine Musik ausgewählt + Musik auswählen + Diese Tour hat noch keine Musik + Lege Titel aus deiner Bibliothek oder vom Gerät an – oder füge einen Radio-Stream hinzu. Die Musik begleitet die Tour und tritt bei Ansagen automatisch in den Hintergrund. + Quelle + Bibliothek + Dateien + Stream + Verhalten & Optionen + Bei Ansagen + Musikquelle Lokale Playlist @@ -509,6 +537,12 @@ Viele Grüße Normal unterlegen Musik läuft auf normaler Lautstärke parallel zum Wegpunkt-Ton. + + Bei Ansagen pausieren + Sanft aus- und einblenden + Leiser im Hintergrund + Weiterlaufen lassen + Fade-Dauer: %1$d ms Lautstärke während Wegpunkt: %1$d %% @@ -704,8 +738,8 @@ Viele Grüße MapLibre · Engine v2.4 - Routing & POI - Routing & Online-POI (MVP) + Tourverlauf & POI + Tourverlauf & Online-POI POI-Suche (online) z. B. „bäckerei", „museum", „bahnhof" Suchen @@ -713,64 +747,76 @@ Viele Grüße Keine POIs gefunden. Suche fehlgeschlagen — bitte Verbindung/Server prüfen. POI-Quelle: OpenStreetMap · Overpass/Nominatim · Bitte sparsam abfragen. - Als Wegpunkt - Ins Storyboard + Als Audio-Wegpunkt + In Tourverlauf %1$s entfernt - Routing-Endpunkt (OSRM-kompatibel) + Optionaler Routing-Endpunkt (OSRM-kompatibel) URL, z. B. https://router.project-osrm.org (Demo, Limits) oder eigene self-hosted Instanz. Speichern - Routing-Endpunkt nicht konfiguriert — Storyboard-Linie wird als Luftlinie/Planlinie angezeigt. + Kein Routing-Endpunkt — Tourverlauf wird als Planlinie (Luftlinie) angezeigt. Online-Routing optional. Demo-OSRM-Server (router.project-osrm.org) hat Rate-Limits und ist nicht für Produktion gedacht. - Route berechnen + Route berechnen (optional) Route wird berechnet … Routenberechnung fehlgeschlagen — Endpunkt prüfen. Mindestens zwei Wegpunkte im Storyboard nötig. Route geladen (%1$s · %2$s). Planlinie (Luftlinie). Für echte Straßenrouten Endpunkt konfigurieren. - - Routenplanung - Start, Via-Punkte und Ziel wählen, Route berechnen oder Planlinie nutzen. - Routenplanung öffnen - Routenplaner - Start - Via-Stopps - Ziel - Noch kein Start gewählt - Noch kein Ziel gewählt - Keine Via-Stopps. Beliebige Zwischenstopps lassen sich oben hinzufügen. - Start wählen - Ziel wählen - Via-Stopp hinzufügen - Plan zurücksetzen - Route berechnen - Nur Planlinie zeigen - Planlinie wird angezeigt. - Planlinie ist eine Luftlinie zwischen den Stops — sie folgt keinen Straßen. - Route: %1$s · %2$s - Planlinie: %1$s (Luftlinie) - Als Tour-Entwurf speichern - Tour-Entwurf %1$s gespeichert. - Tour-Entwurf konnte nicht gespeichert werden. - Tour-Entwurf speichern + + Tourverlauf erstellen + Zeichne zuerst den Verlauf deiner Tour. Audio-Punkte setzt du danach. + Tourverlauf öffnen + Route + Start der Route + Route über Punkte formen + Ziel der Route + Wo beginnt die Tour? + Wo endet die Tour? + Noch keine Punkte gesetzt. Tippe Punkte auf die Karte, um den Verlauf zu lenken. Keine Audio-Punkte. + Start der Route wählen + Ziel der Route wählen + Punkt hinzufügen + Verlauf zurücksetzen + Online-Route berechnen + Verlaufslinie anzeigen + Routenlinie wird angezeigt (Luftlinie zwischen den Tourpunkten). + Routenlinie = direkte Linie zwischen den Tourpunkten. Für Straßen-Routing: optionalen OSRM-Endpunkt konfigurieren. + Berechnete Route: %1$s · %2$s + Tourlinie: %1$s (Luftlinie) + Als Tourentwurf speichern + Tourentwurf %1$s gespeichert. + Tourentwurf konnte nicht gespeichert werden. + Tourentwurf speichern Name der neuen Tour - Punkte als Wegpunkte übernehmen + Tourpunkte mit Audio versehen + + Tourverlauf frei zeichnen + Das ursprüngliche Werkzeug: Linie direkt auf der Karte zeichnen — kein Netz, kein Server nötig. Ideal für freie Routen abseits der Straße. (Intern auch als Fallback verfügbar, wenn kein Routing möglich ist.) + Tourverlauf frei zeichnen + + Route über Punkte formen + Tippe Punkte auf die Karte, um den Verlauf zu lenken. Das erzeugt keine Audio-Punkte. Start/Ziel müssen zuerst gesetzt sein. + Punkt auf Karte tippen + Modus aktiv — nächster Tipp auf die Karte setzt einen Formungspunkt. + Zuerst Start und Ziel setzen, dann Punkte ergänzen. + Karte antippen → Zwischenpunkt setzen (kein Audio-Waypoint). Abbrechen: Cancel. %1$d Wegpunkte hinzugefügt. - Noch keine berechnete Route. Endpunkt konfigurieren und berechnen, oder Planlinie nutzen. - Routing-Endpunkt nicht konfiguriert — nur Planlinie verfügbar. - Endpunkt einrichten - Bereit. Stops wählen und berechnen. + Noch kein Verlauf sichtbar. Freie Linie zeichnen oder Punkte setzen — Online-Routing ist optional. + Kein Routing-Endpunkt gesetzt. Online-Routing ist optional. + Routing-Endpunkt einrichten + Tourpunkte setzen, dann Routenlinie anzeigen. Online-Routing ist optional. Start - Via %1$d + Formungspunkt %1$d + Formungspunkte Ziel - Quelle wählen + Punkt-Quelle wählen Aktueller Standort Aktueller Standort: noch keine Position Kartenmitte - Vorhandenen Wegpunkt wählen + Audio-Wegpunkt als Tourpunkt Keine Wegpunkte in dieser Tour Online-POI suchen - Eigene Koordinate eingeben + Koordinate manuell eingeben Ortssuche (Nominatim) Koordinate eingeben Breitengrad (Lat) @@ -783,65 +829,102 @@ Viele Grüße Mein Standort Kartenmitte Eigene Koordinate - Routing fehlgeschlagen — Endpunkt prüfen. - Routing fehlgeschlagen: %1$s — Endpunkt oder Netzwerk prüfen. - Kein Routing-Endpunkt gesetzt. Mit „OSRM-Demo nutzen\" startest du sofort einen Testlauf, oder richte unter „Endpunkt einrichten\" einen eigenen Server ein. - OSRM-Demo nutzen - Setzt einen öffentlichen OSRM-Testserver (router.project-osrm.org). Nur für Tests/Demo, Rate-Limits, keine Garantie. Bitte sparsam verwenden. - Demo-Endpunkt aktiv (router.project-osrm.org). Jetzt „Route berechnen\" drücken. + Online-Routing fehlgeschlagen — Endpunkt prüfen. Planlinie weiterhin verfügbar. + Online-Routing fehlgeschlagen: %1$s — Endpunkt oder Netzwerk prüfen. Planlinie weiterhin verfügbar. + Kein Routing-Endpunkt gesetzt — Planlinie (Luftlinie) ist verfügbar. Optional: Mit „OSRM-Demo“ starten oder eigenen Server einrichten. + OSRM-Demo (optional, experimentell) + Setzt einen öffentlichen OSRM-Testserver (router.project-osrm.org). Nur für Tests/Demo, Rate-Limits, keine Garantie. Online-Routing ist nicht notwendig — die Planlinie genügt für den Tourverlauf. + Demo-Endpunkt aktiv (router.project-osrm.org). Jetzt „Route berechnen“ drücken oder Planlinie nutzen. OSRM-Demo-URL einsetzen Erlaubt: Basis-URL (https://router.project-osrm.org) oder vollständig mit Pfad /route/v1/driving. Wird intern normalisiert. - Routen-Darstellung - Route/Planlinie anzeigen - Wenn aktiviert, werden berechnete Route, Planlinie und Stop-Marker auf der Karte gezeichnet. - Berechnete Route + Routenlinie auf Karte + Tourlinie / Planlinie anzeigen + Wenn aktiviert, werden Routenlinie und Tourpunkt-Marker auf der Karte gezeichnet. + Berechnete Route (optional) Planlinie (Luftlinie) - Als Start - Als Via - Als Ziel + Als Startpunkt + Als Tourpunkt + Als Endpunkt Punkt verwenden - Treffer wird als Stopp dem Routenplaner hinzugefügt. + Treffer wird als Tourpunkt der Route hinzugefügt. Gesuchten Ort übernehmen - Routing optional via OSRM-kompatiblem Endpunkt — sparsam abfragen. - + Online-Routing optional — Planlinie braucht keinen Server. Sparsam abfragen. + Fortbewegungsmittel Auto Fahrrad Fußgänger - Wird für die Routing-Anfrage verwendet (driving/cycling/walking) und mit der gespeicherten Tourroute übernommen. - Routing für „%1$s\" fehlgeschlagen: %2$s — Endpunkt oder Netzwerk prüfen. - Kein Routing-Endpunkt gesetzt (Profil: %1$s). Mit „OSRM-Demo nutzen\" startest du sofort einen Testlauf, oder richte unter „Endpunkt einrichten\" einen eigenen Server ein. + Nur relevant wenn Online-Routing (OSRM) genutzt wird. Planlinie benötigt kein Profil. + Online-Routing für „%1$s“ fehlgeschlagen: %2$s — Endpunkt oder Netzwerk prüfen. + Kein Routing-Endpunkt gesetzt (Profil: %1$s) — Planlinie verfügbar. Optional: OSRM-Demo oder eigener Server. Profil: %1$s - - Tourroute „%1$s" - Keine Tourroute gespeichert. + + Gespeicherter Tourverlauf „%1$s“ + Kein Tourverlauf gespeichert. aktualisiert %1$s Quelle: %1$s - Tourroute speichern - Tourroute ersetzen - Tourroute löschen - Erst Route berechnen oder Planlinie zeigen — dann lässt sich die Tourroute dauerhaft speichern. - Tourroute für „%1$s" gespeichert. - Tourroute für „%1$s" ersetzt. - Tourroute für „%1$s" gelöscht. - Gespeicherte Tourroute geladen (%1$s). + Tourverlauf speichern + Tourverlauf ersetzen + Tourverlauf löschen + Erst Planlinie zeigen oder Route berechnen — dann kann der Tourverlauf dauerhaft gespeichert werden. + + Experimentelles Online-Routing + Abhängig von externem OSRM-Dienst. Offline nicht nötig — freie Linie und Punkte formen funktionieren ohne Netz. + + Als Tourverlauf übernehmen + Speichert die aktuelle Planlinie (oder berechnete Route) dauerhaft als Tourverlauf der aktiven Tour. + Tourverlauf übernommen (Planlinie). + Tourverlauf übernommen (berechnete Route). + Zuerst Start und Ziel setzen, dann Tourverlauf übernehmen. + Tourverlauf für „%1$s“ gespeichert. + Tourverlauf für „%1$s“ ersetzt. + Tourverlauf für „%1$s“ gelöscht. + Gespeicherter Tourverlauf geladen (%1$s). Planlinie GPS-Track - - Station hinzufügen - Route zeichnen - Route zeichnen: Tippe auf die Karte, um den Wegverlauf zu setzen. Nur Stationen spielen Audio ab. - Route zeichnen: Wegverlauf setzen. Nur Stationen spielen Audio ab. - Routenpunkt + + Audio-Wegpunkt hinzufügen + Tourverlauf zeichnen + Tourverlauf zeichnen: Tippe auf die Karte, um Verlaufspunkte zu setzen. Nur Audio-Wegpunkte lösen Klänge aus. + Tourverlauf: Verlaufslinie setzen. Nur Audio-Wegpunkte lösen Klänge aus. + Tourverlaufspunkt Verschieben Löschen - Tippe die neue Position an — der Routenpunkt wird dorthin verschoben. - Manuell gezeichnete Route - Manuelle Route gelöscht. - Manuelle Route gespeichert (%1$d Punkte). - Manuelle Route löschen + Tippe die neue Position an — der Verlaufspunkt wird dorthin verschoben. + + + + Route bearbeiten + Routenpunkte setzen · Audio später hinzufügen + Bearbeiten + Routenpunkte + Tourpunkte formen die Routenlinie. Sie lösen kein Audio aus. Audio wird über "Als Audio-Wegpunkt erstellen" bewusst hinzugefügt. + %1$d Routenpunkt(e) gesetzt + Noch keine Routenpunkte. Tippe auf die Karte oder nutze "Hier setzen". + Punkt hier setzen + Karte antippen (Punkte setzen) + Letzten Punkt entfernen + Verlauf löschen + Gesamten Tourverlauf löschen? + Audio hier hinzufügen + Erstellt einen Audio-Wegpunkt an diesem Tourpunkt. + Editor schließen + Route bearbeiten + Optional: Online-Route berechnen + OSRM/Straßen-Routing ist optional. Der manuelle Tourverlauf ist die Hauptmethode. + Route bearbeiten + + Route planen + Route planen + Start/Ziel/Via, Planlinie, Online-Routing (OSRM) + Planer öffnen + Tourverlauf gespeichert (%1$d Punkte). + Manuell gezeichneter Tourverlauf + Tourverlauf gelöscht. + Tourverlauf gespeichert (%1$d Punkte). + Tourverlauf löschen Manuell gezeichnet Neu in 2.3.1: Wegpunkt-Dialog spielt Clips jetzt direkt ab statt „auf Kartenmitte verschieben". Karten-UI deutlich entschlackt: nur noch Icon-FABs und kompakte Status-Chips. Clip-Längenlinien projizieren die Audiodauer als farbige Segmente auf die Karte (Layer schaltbar). Neue Routing & Online-POI-Sektion: konfigurierbarer OSRM-Endpunkt + Overpass-POI-Suche (frei, sparsam). MapLibre-Pipeline weiter vorbereitet; aktives Rendering bleibt osmdroid. @@ -951,4 +1034,17 @@ Viele Grüße als Wegpunkt angelegt. Neu in 2.5.40: Echter Explorer-POI-Layer über Overpass-API — Sehenswürdigkeiten, Gastronomie, Mobilität, Infrastruktur direkt aus OpenStreetMap laden (kostenlos, kein API-Key, rate-limit-freundlich, nur auf Nutzer-Aktion). Antippen eines POI-Markers öffnet Detail-Sheet mit Name, Kategorie, Entfernung, Tags und Option „Als Wegpunkt“. Kompass-Button in der rechten Werkzeugleiste: setzt Karten-Ausrichtung auf Norden (Bearing 0) mit Animation. Rechte Werkzeugleiste neu geordnet — kein Überlappen der Buttons mehr. Alle v2.5.39-Fixes (Scroll, Attribution, Kartenstil-Persistenz) bleiben erhalten. + + Audio vorhanden + Kein Audio (nur Routenpunkt) + Audio hinzufügen + Audio bearbeiten + + Neu in 2.7.17 (Route-first Explorer): Die Planung folgt jetzt dem mentalen Modell „Route zuerst, Audio danach". Der Routen-Planer heißt jetzt „Route planen"; Verlaufspunkte werden als „Tourpunkte" bezeichnet. Der „Tourverlauf bearbeiten"-Editor wird als „Route bearbeiten" geführt. Audio wird bewusst nachträglich per „Audio hier hinzufügen" einem Tourpunkt zugewiesen. Bestehende Audio-Wegpunkte bleiben vollständig erhalten und abwärtskompatibel. Keine Änderung an Logik, Backup, Lizenz, MapLibre-Rendering, Waypoint-Playback oder GPS-Aufzeichnung. + + + Neu in 2.7.18 (Unified Tour Layers): Routing, manuelles Zeichnen und Audio-Wegpunkte wirken jetzt als ein gemeinsames Tour-System. Die manuelle Tourlinie wird nicht mehr doppelt gezeichnet — im gespeicherten Zustand zeigt die Karte eine einheitliche grüne Tourlinie (egal ob manuell gezeichnet oder per OSRM berechnet). Die violette Bearbeitungs-Vorschau erscheint nur noch im aktiven Zeichenmodus. Audio-Trigger-Zonen bleiben als Radius erhalten. Keine Änderung an Logik, Backup, Lizenz, MapLibre-Rendering, Routing, Waypoint-Playback oder GPS-Aufzeichnung. + Neu in 2.7.20 (Flexible Routenformung): Der Tourplaner ist jetzt klar auf “Route formen” ausgerichtet. Zwischenpunkte lenken die Route – sie sind keine Audio-Punkte. Neu: Zwischenpunkt direkt auf der Karte setzen (Schaltfläche “Zwischenpunkt auf Karte tippen”). Die freie Linie ist klar als Fallback gekennzeichnet. Start/Ziel/Via-Persistenz aus v2.7.19 bleibt vollständig erhalten. Keine Änderung an Audio-Waypoints, Multiclip, PTT, Atmo, Backup, Lizenz oder MapLibre-Rendering. + Neu in 2.7.19 (Tourplaner Integration Fix): Start, Ziel und Via-Ziele bleiben im Tourplaner dauerhaft gespeichert — auch nach App-Neustart. Der Tourplaner schreibt den Plan jetzt sofort in die Datenbank, sobald Start und Ziel gesetzt sind. Außerdem: Manuelles Zeichnen ist direkt im Tourplaner zugänglich (Schaltfläche “Zeichenmodus öffnen”). Routing per OSRM und manuelles Zeichnen sind gleichwertige Bearbeitungsmethoden im selben Planer. Die violette Vorschaulinie erscheint weiterhin nur im aktiven Zeichenmodus (kein Rückschritt in 2.7.18). + diff --git a/releases/v2.7.38/GPS2Audio_v2_7_38_samsung_audio_fix_handoff.md b/releases/v2.7.38/GPS2Audio_v2_7_38_samsung_audio_fix_handoff.md new file mode 100644 index 0000000..c487075 --- /dev/null +++ b/releases/v2.7.38/GPS2Audio_v2_7_38_samsung_audio_fix_handoff.md @@ -0,0 +1,86 @@ +# GPS2Audio v2.7.38 — Handoff (Audio Regression Fix) + +**Date:** 2026-06-22 +**Base:** v2.7.37 (versionCode 143) → **v2.7.38 (versionCode 144)** +**Source:** `/home/user/workspace/GPS2Audio_v2737_from_gitea/src` +**Priority honored:** Audio reliability over preserving the silent gap. The gap is kept, but made strictly safe. + +--- + +## Suspected root cause + +The only functional change in v2.7.37 was a hidden ~1.7 s silent gap between manual sequence items, implemented as a delayed coroutine (`manualGapJob`) launched inside the `manualPlayer.play(...)` natural-completion callback. The gap itself is correctly scoped to post-completion auto-advance. The regression — "audio broken, especially on Samsung tablets" — comes from **two unsafe state interactions introduced/left open by that delayed job, plus a pre-existing silent-failure path that the gap made far more visible**: + +1. **Stale auto-advance across tour switch / tour delete.** + `selectTour()` deliberately preserves running playback (v2.5.30) and did **not** cancel a pending gap job. `deleteTour()` stopped the player but also did **not** cancel the gap job. So a gap job scheduled in tour A could fire ~1.7 s later after the user switched to / deleted tour A, calling `playFromCurrentPlayable(autoAdvance=true)` and setting `_manualPlaying=true` against stale `_currentPlayable` — leaving the UI in a "playing" state with the wrong audio or no audio. + +2. **Gap job did not re-validate user intent before firing.** + The delayed job only re-checked PTT and whether the next item still exists. It did **not** check whether the user had paused/stopped or switched to single-clip mode during the silence, so it could resurrect playback the user had just stopped. + +3. **Silent load/start failure left state as "playing".** + `ManualAudioPlayer.loadAndPlay()` uses raw `MediaPlayer` with synchronous `prepare()`/`start()` and **no error feedback to the caller**. On some devices (notably Samsung tablets) `prepare()`/`start()` on `content://` SAF URIs, or an async `MediaPlayer` error, fails — the player released silently while the ViewModel had already set `_manualPlaying=true`. Result: UI shows "playing", no sound, no error. The v2.7.37 gap (which chains auto-advance starts) made this dead-end far more reachable across a sequence. + +--- + +## Exact fixes + +### `app/src/main/kotlin/de/waypointaudio/viewmodel/WaypointViewModel.kt` +- **`playFromCurrentPlayable(autoAdvance)` — gap job hardened.** Capture `gapTour = _selectedTour.value` when scheduling. After the `delay`, before advancing, the job now aborts if: + - the selected tour changed during the silence (`_selectedTour.value != gapTour`) — no start in the wrong tour; + - the user is no longer playing or has entered single mode (`!_manualPlaying.value || manualPlayer.isSingleMode`) — no resurrection after pause/stop/preview. + PTT and "next item removed" checks unchanged. This makes the gap **strictly post-completion auto-advance within the same tour**. +- **`playFromCurrentPlayable` — `onError` wired.** `manualPlayer.play(...)` is now called with an `onError` callback that cancels any gap, resets `_manualPlaying`/`_manualCurrentName`/`_currentPlayable`, stops the ticker, calls `musicManager.afterWaypointAudio()`, and surfaces `_errorMessage` ("Audio konnte nicht abgespielt werden. Bitte erneut versuchen."). No more silent "playing-with-no-audio". +- **`selectTour()`** — cancels a pending gap job on an actual tour change (`if (safeTarget != _selectedTour.value) cancelManualGap()`), without stopping active playback (persistence preserved). +- **`deleteTour()`** — calls `cancelManualGap()` alongside the existing `manualPlayer.stop()` reset when the deleted tour is selected. + +### `app/src/main/kotlin/de/waypointaudio/service/ManualAudioPlayer.kt` +- **`play(...)`** gains an optional `onError: () -> Unit = {}` (placed before `onCompletion` so the trailing-lambda completion call sites stay valid). Fires `onError()` on blank URI. +- **`loadAndPlay(...)`** gains optional `onError`; fires it both on the synchronous `runCatching{}.onFailure` (prepare/start failure) and inside `setOnErrorListener` (async MediaPlayer error), after releasing resources. +- **`startSingleLoad(...)`** updated to named `onCompletion =` argument (behavior identical; single-clip preview/GPS unaffected since `onError` defaults to no-op). + +### `app/build.gradle.kts` +- `versionCode 143 → 144`, `versionName "2.7.37" → "2.7.38"`, with a v2.7.38 changelog comment block. + +**First manual playback is unchanged and still immediate** — the gap only exists in the auto-advance callback after a clip ends, never on the initial `startPlayableAt` → `playFromCurrentPlayable` path. `cancelManualGap()` is still called at the top of `startPlayableAt`, so Play/Resume/Next/Prev/Skip cannot be suppressed by a pending gap. + +--- + +## Playback paths reviewed + +| Path | Verdict | +|---|---| +| Manual sequence play/pause/resume/next/prev/stop | **Fixed/hardened** (above). `cancelManualGap()` confirmed on every control path. | +| Auto-advance silent gap (v2.7.37) | **Kept but made strictly safe** (same-tour, still-playing, post-completion only). | +| Single clip preview (`manualPlaySingleClip` / `playSingle` / `startSingleLoad`) | Reviewed — unchanged behavior; `onError` defaults to no-op. No change needed. | +| GPS-triggered playback (`service/AudioPlayer.kt`) | Separate class, not touched by these edits. No change needed. | +| PTT suppression / interruption coordinator | Reviewed — gap job and play paths still honor `pttManager.pttActive`; coordinator pause/resume unchanged. | +| Atmo / background music (`BackgroundMusicPlayer`, `musicManager`) | Not touched. `afterWaypointAudio()`/`beforeWaypointAudio()` calls preserved. | +| Background manual playback (`ManualPlaybackService`) | Not touched; start/stop/meta lifecycle unchanged. | +| Tour switch / delete playback persistence (v2.5.30) | Preserved — active playback still survives a plain tour switch; only the stale *pending gap* is cancelled. | +| Player auto-open (v2.7.32) | Not touched. | + +--- + +## Build / test results + +- **Signed APK: NOT BUILT — toolchain unavailable in this environment.** + - No Android SDK (`/home/user/tools/android-sdk` missing). + - No Gradle (`gradlew` execs `/home/user/tools/gradle/bin/gradle`, which does not exist; `/home/user/tools/` is absent). + - No keystore (`keystore.properties` points to `/home/user/workspace/GPS2Audio_release_keystore_v2.jks`, which is missing). + - The Gradle release signing config itself is intact in `app/build.gradle.kts` (reads `keystore.properties` or `GPS2AUDIO_RELEASE_*` env vars), so a signed universal release APK **will** build on a properly provisioned machine: `./gradlew :app:assembleRelease` with the keystore + SDK present. +- **Compilation:** could not run (no SDK/Gradle). Changes were made minimal and verified by manual review for Kotlin correctness: + - `play(...)` parameter order changed so the existing trailing-lambda completion call site still binds to `onCompletion`; the new ViewModel call passes `onError = { ... }` (named) + trailing `onCompletion` lambda. + - All three `loadAndPlay(...)` call sites match the updated 4-arg signature. +- **Recommended manual QA on a Samsung tablet:** (1) play a tour clip and let it auto-advance — verify ~1.7 s gap then next clip; (2) during the gap, switch tours — verify no audio starts in the new tour and no stuck "playing"; (3) during the gap, delete the tour — verify clean stop; (4) during the gap, tap pause/stop — verify it stays stopped; (5) force a bad/unreadable clip — verify error toast appears and state resets instead of silent "playing"; (6) first manual play — verify it starts immediately with no delay. + +--- + +## Artifacts + +- **Clean source ZIP:** `/home/user/workspace/GPS2Audio_v2738_artifacts/GPS2Audio_v2.7.38_src.zip` + - 136 files. Excludes `.gradle`, `.idea`, `.kotlin`, all `build/` dirs, APK/AAB/JKS/keystore binaries, `.class`/`.dex`, and `.git`. + - **Also excludes `keystore.properties` and `local.properties`** — `keystore.properties` contained plaintext signing passwords (do not redistribute); `local.properties` is machine-specific. Recreate both from the build machine's secrets when building. +- **This handoff:** `/home/user/workspace/GPS2Audio_v2738_artifacts/HANDOFF_v2.7.38.md` + +## Constraints honored +Preserved v2.7.32 (tour ordering + player auto-open), v2.7.33 (Begleitmusik UI), v2.7.34 (waypoint edit UI), v2.7.35 (home UI), v2.7.36 (backup export IO fix), v2.7.37 gap (kept, made safe), and Explorer/MapLibre/routing/POI/settings/license/PTT/Atmo/multiclip/background playback. No refactors, no data-model changes. diff --git a/releases/v2.7.38/GPS2Audio_v2_7_38_samsung_audio_fix_source.zip b/releases/v2.7.38/GPS2Audio_v2_7_38_samsung_audio_fix_source.zip new file mode 100644 index 0000000000000000000000000000000000000000..7ad2b89a6cc859af400b2b2560406f459be707c7 GIT binary patch literal 502314 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%0A4GyMSxq(Ql7KO4KPwCF5Ef5>Evj<)h7|^ zi*!V3F8vYD*(vpm=A76mnnI9Th}^Jk&s^vZC~U`lIOZWtD&X?S64m|Y0GnwLrr%Zj zRel8Aw_5^$6$2o&>l`}ILDfRPs7t-OPc_K)J%n56nN#iT=}-k-f=YAW<0hV`x~=q! z4%m++5Lp5)EHiC4Q&pm+rG*MI21=u$k;-~C@+@gZw3e19GqgwW^PXwZrDs;tH%~)o zP~Ts!WCc%`I*Qjfago}Q?Qcv)?HQT_My(1H7xLew&IK6O-tKLuHab3vWtE?$Ik`d- z5|cbE7cfBj-XoC~t`pD7?qSkOA0Ff^vcYxV{W+Y8{oO5yNc{51NA`|@j*Zw)&ZEBf z1w8Bg9M^puc)ggpy&Qf|-F}Y!yG=PcnluE;cf32gXA1m`QwB-W8g9Z5>Lv~fN)Ewf zWI!c!OSkTc>{dxG)W!5q5gZ0((5rs5Sk5<6r1I8h|NgmhO&p3pyMn3_BX~eoZUK_t zPwhh*+xmqDPfTr?x)B3T?6tU#Gvvu_SW%WHBql)`=SGT&Sx^kTnF)}Pn95sDTkE1R zc<%(+_4uTmz+?b*lysYqeo0BMP;4|u_+-YES(giVdHpy#(h`(OC#=7p3UMv~e&Im? z{vK-^z?~6Gq5ZQ>*!?axVR@5ifg9FcBNCVSE7}_D_$;lZXR8dFawH6IuEQRfa|J2#FNk1tElU$^hFxp-Jd)fn<~3& zm2Vj`zYHx^Wcg$TE%JEW?Fv;ao9{sv+u|!B5h*Mj3?ilQtg?gKWA={)#aI-iaIu?0 zG3ULsv}?R$PQ)0)g67Q(&1OzfA87D#r|=T{0wv9c(+XGF2VEo@WtJbv`V+_vRW3Y{ zzk7D21lG@?X`b_ufON?N8^kHi^ZTCL>7eNEwgb@7&zPs#0G%_QTNK^xMfv9kD#Q(B~k(_tTn` z>YzOWyenwl0RBlVgspuSJyxcsmoQD?#iWsRCF1PLJf9xCK@!Q^^#LHl{pnxyBZI({ zdykM-=`{VG83AfMwfgoe34l{1do))hLiQP%G8EolawpsRn0|0E+tNwxFs8?)MYC zZgA%O1J8h><9}6#lVVB7I3sH7i}3~J5xOeuU<-{p{K9~78)x_pO3L_Cg=gqS2gWPi zlgZ@t-~SoX42U7?D@<^+EIK&s$l zu_wJGtw!~0PePROuQwc5LOQiM-S7cq`MlZ(=^bf#U_XTrrNxI=6q z-wLXiUZ6fWKaq38jK_s-UDJ0w+aW7<6w&&x8JXQsNCL=cZ5!vO#Oj2? zf^GB-CS*@tBrpE};_m_TAbd=^zjDGc<#!;}2?6N})&sf&<5W~p_C?JtFx~HJ9I{ad z<+z9}Wu0Osd>cIZq%kY2pNwRXzjK4+2tJP9aI|bdYPfNrq$s9SUyZ5hRawfSzpq~x z^H+12f^#SXIIh~Q>NY1;N2X_Ye~u5vcE#{~?|J{P%A9iN`0%lW;g(s) zR$x)Q2IWuF=ECvfHXAx5v&p?Fh>c3*m1249a2PM%0xOT*X=U zMx+qb??20?$+dI)_;R2TI{A4ShQsBOvKJ)DG-UbwyJ;{b?B!ehh64R* zqYSyH;Pwd+@e#afB0pYfO;ivYlh5#KY1mpWGUxo8vX2Of)tkNvc3Ejez}mwG=R&vJ z?uiA;9+s9P3kmh<)LS;R#9VVW-vZ14*zKbL0dT$??^ZQLJ=%>W16m(3+qMxVWDQy7 zoe8m}h_F2LOZ9G|V=Rz#H-$FlSlr&(X`~3QN>=1NuHq~O_mY)5WR8l2wkh4dqI#aX z>s;HyJBhcPzxf2|MzQ0LWqn}b@P0~bw8h6c}5*A5|2){}Q;kFOf{Iv{A(aIdzg zNdYoSOX2qw-7d-9$QA)%p=uPs&lg?b6x@y~j31`}x1tOBk)b1ZLmrS&vii^=?dGlZ z-2P#B&1X3g)}jwVtCY+$-6m|7^qANd|DejQ+%6)EaQ$}i*r=Q1w^%rqDyyO@e;>UN ze+)MWO8QtX8m`OmUbYIB)H?b#Z;-bD~krvQZx&D8LId-m4AO! zHya<(@|t)~A)`jBYJz8HctxMTevx$Rd@N++hD`+I=GeNMjyn0Hm-=K@DML4H-;Q`X z$G|`saGL4J0;~SlJa|_Xp=`TUDiTwhv2L{>S+oz1iRGUMprIb7#dZprbr;}$;!YIj zq#&jNxkm6Ufwb54)_VE%;IQf|ye&|fKo+~ds*V_VNStQ&B2(%OK`dH17rJX@n8|cj z0WSmq^gk^i>6_k-)SJ4v+3NuLRm^AjE3-wq~27I6MdMCUd(UJQ$PMOAmwK6 z6fKM$XO{o$2(Z(g~vNb=x3F@RL+^3Fip*|#_IXKJw%KN)9XL(yh|$fDj(s*$^I#bN%Qu8*0|sH##+3ceEL}YxRaVf@}|dlO6jFFSpuBm^>TTg%ZJn$fLa4abOr z?uSwi)etVVDhXR#=h1mDu`pB{_M!|9EP{yr==Jm$x9ccfd_~z|h(T+=9erPca&@6J zK-_(!UWY7}SPmMZ?>)nWo{_K}G&(O@V;Pldtnr0_xQDJWvmI#Y1Z<{Ht;cLWJgdA$r{HTg})(%HP8wu>`SB&j^C{Me`)C^N)2^_VW)GfDRcAJkR)&!y2v z>cDD(>E3Z*_FmXG=Ljbs5~2xL)1`kjRFw}AlKbN8D|nqD_bD#7dSjUUHY6^{#BV6_ zAocR3iolHcGK?MG=g%SYgme#-L*2?P1&d2JO{*02y{g`#t4O3w3|I`kd_kcHSyQzw zG8zRd$h@U3@1hGL+JnSq6Y1h|CKw{5LZ?@YlJcANB)yN7M&S zTv;FHVRlaMi9^jTl2tZ{5fn5yCsc=y)*8+qnwJ~Y_hY}Z&C+gU7k5hD*vA25{_w6L zkLRSIk@Z@-CM`;jT|(dDKljs?#5uH|`T~i-bHlpSa`eCrde3nlnrJ55;dh|z^dNn& ze=O459FjVN%D~n+ckIfRJ{`YDU35Edss`r{Lo9gMw7NWYINQ`39PIXCZ?kp+nH$s| z0F$~>_fhRwH9`y;3I-qY4U11>oyrRVd^uN`td|?s|NL zP2Jk{g=BM|jWnu-=jpV*w`H7DieBLfN-z#hc>IkCdT}=}{LT#kF?n&LFT7GU z@2uQR@HMUTBp~k6dNsU1eG~p^@+#ixwD++W?jU~#L>qPlF9174b9%KgwJ}ud%#t>? z@*d6Fik+M^<6xFCv$}tK+eE)&{TQlta{#xIyKWj{?SKqOH-NV@7FU+&i|1BIaJSOf zjD+J?2V80>w{7YI8^BI)$#&(+Cn(_#r|9xt{!Hex>#7p0hL6_2BVFgT_gOi=&d@ES zi7Z@+r{jRj=W~j!d{ePT8~<~alxDG_avyvEn`#asy@SQw@s@+^)Zljh7ix*hyKt5) zl0;^H+yNvkuuDg6@KzntB+E-Qy3mf|cv}@u=q|mjV%LQf59t=tvp}NKthZgFNZ0MX zCU*)hROr^`U)sjp+ia3xn}>5W{+JPL+Rw8;LEhNvq^=44X@FYe`t%TusP$V(m8m2@ zbHE5Z$x16zs;?Axyg@{Q|5Vf6z<+)We5K67d=C2f+x=Y9v2$JU)7yue3bA&UDn27@ zU!1U`pcs&v|07>r$T~whekqY+SD}}ZuK2rYNqYU}H^Awn3T%6bxXmeSpXvS%j(qReEhxc+IA!mOCa~GDFy5AFbNO| zG%8b7Z0Ic3zZV^%L>&`qEH*dWRD&P@G(s91G9!;rtxi_godUY9&30&HF>;e}$IW{c zRh?u#C*ioog-`$Yz5)9y7o!JFHARd|$NIv$!oJRk*Nr9Q7Pooe4f;TRXem_HH?=`1 zHMueY^b&eK`=J(rt7X!ZCs~7jj`aSxkz>e?vZF}i&dsF+!v0}HofG@yhCX;G;rj?u zrrx0m*(w(&+2wI~@YZ~Clbrrj`^-;uXACfE=bQe(X$6G<|8@udM+`S(#tHB8_00#V zr*@A3%}f=HC=Q;h=v#c=GE;^Gb zZC`72B257E`h!t(w&*a)%2sTY#?oTBoK4u4l?tKUo$_3I(n%0nbWnLfw42iMpx+5I zL>W2;)nY^f<4bcWBwPlgJX~INKID^puVE9@+kI8J%#2jN7)^U+vauve-}2tvqIf{5 zeYJIItFipzo#EJ7Fbu2VMOHZi)w3NYUy#N^R$WFMwgsENNt(t9aetsm}{ ziPib$wnKo z3{*OUUiY`NPT!Y{To3Dg031|vQK}OlX7>#dZKYvM%okcD^4Evu_e}Zc7Dqp!% z8G>Xa)R-Ok%$FI_-FvY!#rNkdwieE3-QPH3+K`J&5?2tNVOKLS z*illkm-+8&(mW)oJ}!>TMTv$9>C7B4P0TC_&CDz*O$k?mfM-|a$-TCWd{OmWbUlmx zzD7jZvRBh+;z;9khkwb&Mt<*jv=htr%xK%jgTDwKVqYcX!kr)+|B4&ljd+V+QsvFp zh3O6!^Q=nTQ>xn#V@}O`n5*q$51eJ};cN5-0SO=Wq#+ggovv@nQ>CObT*$-4*cCnWc;y#5vk)z%JoB&LPz)($pn8#H7jaJyOBc zIZchsEPQcfr6cl&0TY5oZarFF9128}Hy27IOCThK`z#8MTC@5SO@T>PvR*8GgH5(T z5NG&6Erjh}vOHqS&p&0zC*;SPWP?R;M1%K#tQSgsi`t=rLd@TLS}>TK`VDR8OX_iD z$CdFEJo-R-HHD_33~oyt=dV(TTfcJ-Xd)ktja~F2>Mb9LUK#*!6*3d=p*_z1pvz=x z--=ucSOEKUek3uu+E2*O)u;<`=TO3!zPD2jLiWq49XwiAhdGA&e9EsDLAT!EY4uX~ zh{P>WoZuf#%Wg2ZeurIoNm@`gJt`9GyK{&TfXU5 zl0)*-#JEVZyJUl2)|mnxzVkc5O*$mF)clI7r{ZkyBdj$gQzHHR$E?X={N84{gnG}d ze*)Bp_ZovLj#7j9J^js6UfZn`31tK8Ar0eQ|3$jBNE^kiOExgC-hV3a z$&h_@MA~b__>bcEewfJ8KeOTiIWc(tE%fQ=i!hFLQcLJUV9-7Hru^q~)fw59Hl0Y4 zKn;-)CrzuquSNkhsEA|i9C|ju*$lC!#kNN4C2CP1*ie(rnw~Zb$1+vrQ?r<4xqX># zf2jRH4J53->&K8A-?MMYAEn27 zRbum=*P%~H$D@kwhjdm*mAy1qh2TVv4+y3XkBD{8Jw3QhQg0`2T`VR9gV-mtB8*M; zTsLIqi|{0%`x*jjSnfz+Vdn6Rls(Mg-B;nrAtG{TcpeMMEgkz$_$GtyfSx(QM=U`7 zjvkmO0m#d$PH`W-PTwpkT8O~dsH$H+Aw2p}F)r<;Z+bh-nA03(rAffB-c}bHYcR6G z0fBQ4O35R}T0Z&;Ozj+eC7N>h0Z$t>H{<^-zQD7dmW9s}p?h}!IFIV9;>sSKq!d7r zO7G>%qAuMdPP!}o^sC~e&+a|;--&sqJkqlMvY>tVpw({=zciTu%GyAqcg<{zS`Rhy z(&(3HK;Q~y7MVNs&_T+-%3dsygKNo}K&&SDGs6~Vk;=wT!2pwunfKL5D{WU{_Vq-Q zhxinSmJ#)U67seqsBW4+Quu~Y_t@l;OPKJeYsm|2HZa?bix4bE?5pRFw@)BWfrgBp zj`GTywXB|0{NWdW3yqSnu!<$KH_Es{+?2>zU%_GZ1a79O463EtzDJ{AyQ!sOAr}3; z1V<4J&3`+WwotUlN_4kiO`szhP{-9i^tsPM^jNM?7#ffd*Aam309k+dRe`Bo`@%e(Y`M&4ok1{Qh|FcWFU4UweUk(9-6lu`iO z)BB;}#kuFFsBeEQ1>}Se>(mc-H3(gW>slBodO>KM0v(gE3foqtDIA(=DQ9FyYJ%66=$)YaUif0Mr7V%bm0+x9jP-A=8^N;EcIG%v@c0Gy#7d(c+ zF{yLeKhoK9tjsI;i>;}R!xn~*cp8*7Woc!Kx%8{-gz*FbJIenEV#rMneaQ;$j`0~W zcK_7s%Xsy%8pazSdWJ@tXy$LI<|C0unmdd0kSRn6OO)Rt^vQ(>N{5v^M zOdVubS=Bs_^aq=QP46`iH2}KbZK5EhteOwAr}f3^2KHaVX|u`PfE@s7Z4=8W zwe-ThkV}E0Wbl!(crL`h(H6V9x~qckjt!M&V#2v;1jw%r@ zaAH(kA~$dcRyp`skTK=GF3D3MH}{M`)khv@lVYpp>+9dAG6S*dAnJA#7jvuu35d$K zmbFmZT?P#t2+T@J_-ty#m3&B|J#c_&w?%z4jas@GI=-7HAQIEFqh7IcM7p$r{C_VUU{br1uGTy{IPhyc4#^tL1Lo!H@B3G#?xp@ zCvS4N(C_)LIBUues)+!m#H+{@naCmhg$Gj-hy%-XBhxy9rQAyNGbXVM8F8E@rtq++ z=bHU3%odN5s&<5A=bPV(kGF=%=%`7!AamjK0W_u{c&8G>fgN{?Z_T$}kF&?BwL(X# z7-4z`S{CXQj;n0u{?h;6<_E;{A!9M4(+fF;aqb@)?rSlA_GHhHEssI%lS!-c;?+A? z7wHwjR{-&3Ep#)2x#grsbNV~QvjTQL5uynC=RRZxwuTml z+5yi9bRy%GlU};oM>Gy|aLmL(k(*qTQ$Q}f0(Z-kba2jCsg8jvY{S%q#Nh0yCy*g~+fL517}p>>ZBZ z{!kACl)G~Pe@oxGW)yw$v*3o3F11H`5PfgCKWBLmmEz>ji=mdeD_C!e*?!*I6WmZE znCY%FNPRUxsxos>xNh~XfYbqbN<&=J_G5+I_Ql!ReM@tSr`?H31~w8lUS~*(w*?pi z;T-GDwmE=Z>#DaxnD77(7IQdk|KR<#Mq&^~mj-h9|@3K&>4$0$>8w4&4KxRD>`9&dK13P`6Pdz2+35+H%a72ua(K!Ld=g1EWlno$Z$*q+xoDOB=nWPk04qjO0^tJLohr$$;9VH-^Z-pr zWldwcKNXp#6pL;EyYf1#vPO}(_St$lJyaHE;WUB7x`WHdt7PN-BZ0$8l>}-VhqfKM zYF|S#M~UQ-)2>N*!u4Y%{X1y^h3-gw_?01LZ=TQ&Uyt5u?#?vCV?NolS_q@@he`^j z?QX~Tee4~&q7`X|w1(I8$O6p2K=8BPNZa^+fY(`|j3Rv~r?nJ~e3AN*2DdNK?|ML@ z@o71V2mB#|BMg~pH-7rt-<^nO+U|W8H4)zA#D6?nz6ft#){J|@?F?cf0YoVFN`Z5tEM_>kX$chfo3~3{eRA{kA71;%h?Xqbu^I)l zpe(VBqvu@A^mjV`9I{CM+V$TQ+H(bhBA% z`I7>?KM=p-zv4xJ#zc<{r9nl}yRdlh_e6NCza)k4T#W53Am_zB1BVEmNXRGtX#y+& zJ^0>yDs-&J;W_&oLX4tv960P_1~floD&~-04$7kUC8yT_gHc>mx{6VZiw6V%Y|%l0 zQu;wV?hY&3Z_MzQX$^0Ycd}*lptUfw@Z$pJ+7ttK8{0HHhX3iSd5k+%27Q7tb3eat z_a^MNvjm&Ml8b?6;Pym+%b!P6n7&H`Zj;@T1NQA{Oh7ZI^lsBVGvcyPwGn3)Lz66~j#c+y_7%<%C=EEpsC=$g50|0C&W)8#4Q7BMB z@G`CxVJzK{ga0%}Rp?C>u=Yld;PaAQ%-%u z)hGYyD|?g~##_+4*9Z6H1KNsq+-j1Np`N*-h=TX?MpQf!j$|!OI5MvV&FGwD_F3#r zd;Qkm#^i{Dx^XJ#YJ~d|Ha2s8H{$V|Di0_wvzm1o=Hz)BKGjyK#98XKNOkEZmygy< zz1(FE0z6n`NMh8&!Xs8jdDDtRVptN9$*;T#kUfS4y0MUwHO@?Jg^-1Bsx$4@r;pYD zI^ZT`r|+uqnBpHTPw`tto~dKG0Ga7kLziGqdoj^r-vHgn7D3l|H+=C#e&&}l!Kt6C zoGxkh`JHeVEcz^q(CxI2_^9NmLov0}7QTId;LJ*Jari(wk}!LamjuRy-15os_*E7< zZDDwxUeW27SoYP7*JBe&b(sM~34K>EQx8;S(g-Zc!OGpp$qQ}dcc1Lc7)5Gb*&6m| z>E(v7im`&WC+4&jr-%X;{UV499uZ7+D0P=B#0tKA)tL<2{5Bx9$uXQ}JEkXad~2lW zCF>58KQ4Xdp$^wx&%Jps>@6$52h){x4yMlZ=Mq;lBJ=G*<(p(iz5lVuhTAq5}b#47wYUjf1^yn^Ja70e5D$Yi!S~i;~UK0$TOI3K2;nMthPYy z*FT3YC?6=S>XGAFCp(6x3AL5cBVVm)z)F))yLPbh5C(3Nh7>X-MV_ybaV_s*q477^ zxF7x_0t{;0GBrtcVGc>d7BcMGNrR@v>rnyOt_jSZta3{*l}G3Eraq^*ySU93-m+|u zQ0W%euKM-Jq@=jzg*CN^x2(PzGoBe1mSnc?DIlXL#b%&nv`?wW?oucQ9vcf#&J3%( ze}%Bk{aB}BR|yd$re6cQ!iaT63b)EBccGUgJqHk{3$C@i9Hf90jV|LXj>h?ZfzFA5HX^=j{|kPov-x8H4E@LZ2cEq=HOywA!Z^A59SHjQF@5+uNcW0Hgw6N9a4Sc+M=>~Qlb32vv$Z?A)zb+JyYkSP z>HM9UmC!#E!-$2e&?P2^U7StDKKY_+B|_0k|6}?;7sb=dfcPu-)-U)Dp2us^xA&4po6%t?MuI^NZp@1BEbzQH+6# zbj8BU_V##tx;#8Te=}`8274Ayn6tr<6RzQ2J*~DrLSb7b^+H(B*_1g7DOWth{@ire zH)46$%Ma89<=*I324_9Cl}S1h^&jp67)BLO-_?1=0#I6&+GQucky^Zpsc>wQ<1ZCPANNsIw%xi|s>ev~EQl?nQ>tBfh z-88I4>uGGMH|{&GFSeSv%>t*Zd`(XAPvMq>Nhf;wWlYiUv(K)i(REVPwA;+9=xxEW zew@;|k+qjA!!`}xumvj{l|Nlf!&>wv_+E?0(rtAlr%LxOyeJ!2(Wyi+oKInoN?s&y zj^3&y(N)uRDeAB-ztw133B6IPRZXE^d&$=-@n_O2qF4`fFD#(3H2_GaEo5YS3?#>y zV90dlpw_kBnNJxxfri6Lbme6E&^e8!F>V|p@-J&ynzdW5-Nqs%c#>$Ur`P*tYj*bG z@Y4}04#_^#1D0}AwvdoBr6qr0MVP45d%{DZx-5PuDYyhOQj+h z*mbj;d0M7w14GsR4**m^tG~$k=B9t;_^&wOYhJnR&gauNG;K3V89MV`Q+rTXj=5-C zTz>9*NCLa3aB1=9b_uzPtCe$n)5@oGStAz4?lUzxaf2HhCzN#Q0@a~`l@1AK}PfyRWX)#LmGR`O#0 zKF3+L^S*|e+`TYgCx(IuPb$LEV4~~Y??QawEq0g$*5sHVH1Za)3V&5(yg<(mik|$_ zAxGz~>_hk}LaV4sdyun&_Nht&Tje);hm8kvH5i@qXY(*hPUnd_Yk_6QLQ$h%b^{Ch zH$L2tyit<-5}^Ra@Ahxdxx+I)pfZE-que1)=>YIvgP~CfL+fl{iRD6_n?5%Y> zxjs`pdu!WJu8*{iy>)D=QZIoLaYAuyZ5P=Uza&4|YuGULQ;pn%J&Fevby5Hb zX8*kVJDNWgLAu}$w2XXXP^{uC1zlSTEt}8%vAEOgK109!#P9o4A8mWmA3wDOc!_u6 zjd=2g#>ub(n2+)jrWloP=dYdKUpWF!(-T*eq%;)uru2_?>qdc^_r~+rt&063re_@u z@@I|)S=oUXMc$j!QM-jIpf4QPHle+ry`D{58?1$*@}~T^{)+tR)6GvUqH9H8_aY7p zL@upWyGxfsM9RoOQfIW+)B;~4_JcoPe%NpQd108l@M9NI(lAh)50@VEf_2Bq{SE2Ky z@6iusN=^D^UFqIzYF+6**YKLsz1fZW(tV**OGx(?-tKV3#+8jV{1x=49(fjBz`BI) z!$ET>e41Kspgey*99}(rI-A8Yuu^(^k@!=J+?n#;iwpZ@l=6$pKG>%usl~Sk+Sz6~ z3|ixP{DATgU5Np@`dt$DknuO<-?m|?V%{S0Xg&$(j?8XLsYDI)J*EKN)Y5+%do7pu z(DXdc&BU87oLAzi zITwR)&gBG3Z6)sz&L$x!k!SwknnxK`1RGMEKmsbkN8&AXK>eeLnMK;@duruHJ@xl`(FL{&GDaw1uKk%nCYgo>mwX&c1waF~AtDskTr8|93nPgQHEZ^8} zBI$9=`frSMkm`55?5Eq=IG;2-M|z2?MR^A(gDZ7Xs(DE$3^V7!{CR_$D zwdqT{pHI~o(+C$@g(jaW+a11RYs?zkfeVzDk+m)Mtx>MRDGX~*ZV9~6gguep3i1}q z?S)cvOZBK}r-3WKR8x)coTGWmJtVH_5qr@!M>X$k3zJu=cnaYKVQ#uPz!VW(&!h=x zboUEMF1LJ&cUB4nHs!_Nh0*2@i|FnbM2YZT`D5XCBI6SXE&+M7Oq1BXz}X81oStIa z6`eLVcpeexU7ECU zsC~g)~ zyf3?1M9^S0%(vVZ5P4}H^-T@D5eGve`zy4+d=mHEt)^;P$Bm4|AKqR)vQghiHh) zqqNiV@KH_rCQYz*WCc&d2_N8u=e{eN%3xCAMS1p9M((*r8y}=g!I40=xTd_|jlPyl ziq4yN$6Oj;7e372$(y1JidYil=O~coBnx&jV)vYm4sj>g_W)u76)5x3h%mkw1>SO+ zrwsS2@VcA{d@TA^F*D!v67QNHNq;GA03W9~QI>B8M7~hD$ifG;sz&!_-W>OjO(Ibv zBPQd8Poh+hZpPFdk#z!E)w{3-h!(xZ%1%3~3L^G>gx@1XvQ@ zx@J_3Ou{x6QNp>hr3?-ExY#~R$K+g0-;_eqsf5+mMt_v&+Gh%OcPNmG>C{(;fY{TGmp`uoT$5`Gbuz^r_@fu%p&G z7GVBIOLd9?i+>bfaL;}ElcN)AVzNIh!y}WUv&V&e>E_Fw!tT(8{X-JQOJwn$Lz>SM z{S;Rq=Ah!A$^;H5n5)G=4|;?__=;kdF;6!JG))oF7G$M7&YHmYmf{x%H7m(YTvuU+ zi8e;5k#!}+#s+skgV>G+wp33j?#EblFEhv#Q!iM>uPjbfwnUAT6M{t5DJLD?KN{j9 zxIsmwSVN94q-Rn0>$KH5xyF9DB_iR|A{ZX&2biM!@yFWp3gHV2$=U8U)Zvski+w}g;~M7GT*!TF079&j2`!=2w5kaM~T3?Y`arrWLoz5-GRt}-tJ)EUIf0~ zlNx1dvAqq@S3HcMn=uaJi^vzxNX&5q!j{9nR!YH^zQFLM-N^dU`GyJDS~8w3oaylvxz*Mqd$fI_LL0^RshQHH`{7#+RE7)}*D`Flk}8G`Us-g?E-TiIM$Jjzu0ZJJ7_$$MQnP3XK;W0pQL|Mk;HunX6R{znLa=CwK9BtGR)xP#*D z3=MQB&pqWH3U~+~LvP^aqPRvUHzEY0N%N2)#b*-ugk50XFErDs`}kKOnkWA);e$y) zrpy`J_u@%E^rB&lp}XYm0$-qNHif+cDP|x#Et#fOweN3%;T>(H$n>am0R5XC_^!@35mldPB$*0J&f3CT}OZiu{J@=zn3b zH$nYoPrPLwoIib}PAfcRy}=;6iQJ_>_AtshhfRU60+XGhx<}(HKEQt-T3@CH$~WoX z>QW)S@x+HB`)3>Nr0^H8BeWXm^_cXYM2mQ$2!0!Ru*KA^=7#J^$GBM%xBYneE*%9X zUV?fh<}(qF&$L=LdGfM;;%ApQpcc*${28|@+VE$LZp)td2^v6${5l*8 z_3-%oMR$PO?GU)Gm+5=g{7t8m-Prru*O^wB&Zv0OmSaaRzfhOs1qAFW#OpGI>$>S< zzB199S4;PsBUU@Lufg83?+e)1+Y0;IfZoVsTh{>!uL1{m4Bx~2@X>(g5C@h-yS7}I z(UR#t!&Nuk5#Adx-N@2CN z`M|w5o0){{= zQ*?cLj2`-S0wY+U-_xK2mBaLp-UXlePr|7qby788ePfXNC5A@NnJb|=9$Y4Z5y@63jz#AT)edlgI0DW=3->pFc;lWg)2Q^~wY{87@C zzzpQbyVePr;8|%EB`6ZQa$Dnh6RX#db4+G}`N` zf2#8fA7Rk<(`TvTpT2|cp1MUqJxE<>3+4j#hUQc1d`DUe_2-(kAxdxF$uQ7=lj+8? zTl)5xEfTu!L~HBmNWJk5SqjihaH$&-dQT5__s^c5o*Y~#7t?&5%GR}HwR8EoUb8YA zTpsKmo7GNLti9c2ky2>uBeIciYiGl4ma!Q+FufT%79#%^${lHf#7R-%Q;0FCwLsYtPhW%UGgnk{0vVRlK#`LcTMGA#A&6sm}$ zq-6T4^Vii<=2fYu)YnN`x14sbO8vBSOQ)oBPigHjtzd_hE3$Q94f?dJ?5c2EczS`d zI>sv!6|QWVQe_PmDpl;`X3GX>6Jj($)IPdJtoVKZl@AK3g~tjZP^Z({Xq4EoNOJ9B zRCeQ2Lm2$Zo&5Bk#4%whxWub5myJUe-PVz6g3av8nGv_KY(s~jVcih*yN@aN245;2 zsYDc|#kz=7b)&)gqVc0lC#oZzS)oP^WxGnY(;6?KzMO4$x4$amXIfF2X}0w}-kGDT zMFjff?P3h`HVOO$kw(!{r^T>qDWOUebAGCeHF<-lQGwX-b zl{p$PT|udP?vV$2Tjo07V2{v~iTyx{#d&h$6+b2)1l)9ZejBzFoIsx!&u^(+H_(8^ zzH@nu(~ciZ7QrZ|$cZStv4xYVf}Fe&^DS+MDp0A`1m7CaW*fwqvfRM? zj~^QbuF8)~^<}*@)t&VsFXM}*h|-T%(5bhob!ww3O~0=F5f+g!9+<0p>&`_qUg|W` zh(2j=l@2LYB2~UL85jbZY&Ix#+)4SE24}m6S=U8paAvBNHN7bASbwY=kynLUCp5}S z*uAiAqtbhATUpH?soC~uwvmLJ2|^_3)^Fk%j?2J&S=OLrw7G)&sZ!4(p-Q!7!XMPI zN2p>I_zbF)39uPa&7q=V4Wsk*3LFDV1=px|gJvskUycX0*KYM&cImMCX?>}(v8;ry z#e8K^iLPYCt%@P=s4JXzB=e{yq+-v*4@~TV1~!v>@B>Zok>gp5K)=!57*te!A68c0 zp}3`v;YW1jvWc?B)v$LO#NLk>)_1#2+CN=~pz`21G35gjQ`CjI*yA6dsFF^1z1Oic zlWwRIw-3(VgbysKHOtBh7cY8Q<`PCPOkvEae`$-lJS$MmoQSCt zPHhj5obyvB^?$hgUkJ<3F_(I)V{dYK=0K1Z9PZ}|ez3wk=`c-_3sKfiiO>-96f(oY%o59{$C=%VA(0ibfBfx#h$QqB1&5J#JPKv322cdC zE1U$mXbkqsj|n^mXtCY-oFSfX(sO!{St6ng7cuE7z9U#hXGac>n0S$4So1iy0JG8i zy(#EKURIAWC3MQ7Y>iMkr=zy05ze>yo3=NdPY_>vtM_1Q)KRU;Kih_9*?y1?Rry$2J3fp)lhCH>Rl{)p**%a<$WkL8%Zl?E?89hC_Ac?6%`%BV4Tl9Kl&5Bw;{&< zYbKF6)MsjxtzKp5MJEK^t=ET#TTi}x^3{V5<}%5CeDLV2M_(Rv>@-gI4t7sWBHIU_ z?|oSyvirq@KYZmNa`EEi;^5Mxa(MXY;LF1tl_!S>e>gmJP&qt3Ke)(I**<)@_4$`M zDu4LH;e$O_Tb>-8pa0n;^5v85!`*y`4*sxx@aS^~k^L7J&rBMh?{4pXxt*i2|K+3o zFTZpR%I?X&Nn`KHAHI0BpKr(R-u|wu9nX*UPmaEQnj4g@!v|Xr@`LhV?~BhLJ?uDF zq+xMEv;@PX4-3)eI75oFKZtv;=u2_!mdZL}m5RX3+!D>XTw?nT$p|B-=aVpy3bpy& z^A{IKdsio?mj{LKo-bm5a1u)WF<0Huv!j!5i&gp8zRU@2zJIoR{;cr!nHODK-rYO8 z{Bz-5#EnM@ZO>2MSiX63^sLx{eP1RakDvJ0wqAU{`<-RHzV}{Phw9*8&W>T*6y860 zJ%@#1qkjy`@?vlItoY3_tblj`YJ{!-yU)*dkG?%Ae6;7y<{pUemTzd~9v>YRYdS$~ zcj}L9HC@80xjZ<(+BT4GcnP_!?G-2srD0&m$1`7GvJ(5jp~lhloYlAjF8Let_U(2mz0@TKUur|M=Vg2OrXn zIRcgqF9lsc zk9qVg0*e);fx*UYR4F>Kn}6AzmMoF(b{8DA;C3ZzvG~d~@RM=0^Ic)_Na*+izic(g zWrIkpS&|II>-$m9Tk~B$p~+v~8GEcupQF;|>@Zi0WgHkK%mFv>@%lH6a=m~J^Hy26gcZ6wi3v~BaBZbIf4-iv2x8Tr6^N< zvcGaT&Jlwj;h2VE<7HBYNc6e1qu$!%n+s%$#_BxZ758*5Z&B;sbvhLjLruj1$*LTK zGc-;Yvcnl$xPz{hIO1a<8f?&{#$B=yi^ZXkuFCz_MIn1y>nsXKe)mu=2ljvdH~aSN z;sFWkOguY=-UYX?Oh$CQhkluk<`3{5MBs}{9@UFYc3}UG2gn}@!M-H3mns;AP4$Ri zY~lh%##3X~mz+m9ce=EjnoJ__O_)3i@5Aq(c~QbiJ=k500uPP*U6JzlgPOTQDz>x* z`iwc>Dw!$x=Kf{~kFqX8F4o*=ttT9zoRiri_OIC{nhm%&>muM}IT^>Wxf64jj0k>I zF(m7{ud>{*9O79wHZPd63zbGvOgcX_A7<3LHtxA_b}=lej3R!O%giOY7-MOXG(NgN z)lyS992TOb@@A`hodsZ z%RYeGYF$Z_THml#c^NnKI?NB!Bj+GxY~kX@Px9%~GCrvO^~on{^O~J6GQhXyAmmm6yDqkoBPZlrJLGGp~CfP5OMyrvh6K1o#Y4wRcT-zhfRO zl3U=RIqcOT!dKD_vA7y0i5$Nc@^2uW#ko837Fk0P zou{rs@)lL+Yv$$UhUL-r-WLxaZCf90Z9P2v;-U4?!~G|ZcK580uBND!56!a9?8U)X}2dH`7e6?I31)O{Dw4nc>`5}Ee7KV#=y&_+|8NKS+LVGL{t!R8klA}YF7^nebM zIuH9GFznzzSyxop#{>qOlyl-A|N7r0U^_h~G*(GG#WqP_V(k}4Y;^bY6t)~XXXr?- z$_JyPC_!WK0Ph}hG8ttwF!+q^MIL!Pe!6MMJYsAS`WCi@3kqfKB@?wZzNxxs)rS5X zxqpxiA`Q&u04+L=(u59j>7)qu^6wPA2EWopf@l%!A$S4KNG|g#_Q9ufi_%>CAzD4T zpkTa-t@#*V?NP#$IBUm0>Ex}5{ry?y*qC)$^!CuhTje*sAx;E$RF37Fom%zvXFV_0 zMpF~me(H_6%tP2NapX|g#evD%n%?h}~Hqngf!q6lz@RK*WpS)?3f3xxioan>S8y9HJd64_< zhAux#sB1U(L^tyCL(%uIdG4o?H;K#_Yh1yLVc`W@(?uK?T1{7_Zt~exJyE56?>QQz zPnM7{y&SNpWH)6_6!$6Kh!Y3dEm<2mY`w8eIx3LhpWOWdvk8p$pD#{Nx(Bc4VU%ok zk7oGa4fgHXzvO;{BLgAZMJ9Wy=OCinO(2}UFbX)*aG8K^ny-`@1-2iOtZPcXOJM|xgwRF8!K_!rp!WB4obMfZNJ z%*y>28niTzcl#x$@%`r*Js-r6FE`jre`fnty!-9^b@n4tlW!ZpvzO37n0GN#Klt+^ z_2MH+5CFr#*~RYR=6*O>ppx4?8^NGTTXP}>+C>1fBVY#;kqTXmDdyseDDL~k(b}ci zkN)X&o*V^jSd*X;VcWc^(vCjgo%=gGgDLFuj?=&aJHfl~Mm%|=$Baxq2-_>#e%%Z*1GpofGgXA;YXirPDBoicSS0%bf>O zJN!TTI=kS?H+2CJE#@!pUkPz*o#aIlG?DJ0YgF!Mh#(`&*q~L z@klx?+eKqWYFA4!k}tl9I5xzK-3UbMSB}6Db(`9f&EVqnw)z%e$r;vnamouzY(s}y z#W_UlA;+jE?u#_-bRggY5}Kb}fv!76!=*%Hur+QNmLIkkf!Ac<#1TqRoArk7I}O7# zz1T@tL+{p~lXq7<_xY5v%?r;o7{4jqbJL)qwoKbgN?H=qrp`d>CsFNt33EsbiyF6l z`&*O)65id!J={(A{koSms+RlVO)w2T2hv$OMZ43OxRDT-8qARf^bI6#)L*^v{54a! zHX`nW@K_Qb#{v1|$7lLbuBjFGhF2jB)8dNuSE&MR_?W*M|D*y?SiT z#qRQQ%Tq77si(?s zo3-V%cBCo=EnFnG#E58eFgqAp{!-QiFGOOxK-`GQh2aFgK(~_D^QnI;;-xY?t_>FU zg;uAQ9!`0-tkm&AtB4km`~}Hm3rVaavG&3l<_;5%E0`0Q7-|}H#xl)C*dXI~<|YQq zQH-wc3nelT2V?92XacBR{z;gvz832%UX00ym=aqTp~KZ$-;GZ=xlDjIA(i8VVxV0+pvOj2-|62F+E}LhRKs1-KcbAeX41i8W zMP8~t89?C1*p|S78}ET01Y(i0H1@(srs>T?fe$=z={N8NpBn)Goj?!au-I*WLcWZRo%bzTDefE~~zzgM`C$6HM zPYc0~kjDu*bV>r*H|1V(PfQjg9qTf(>TvRfBi)Q0f}&A*RQ;O#=3H>PPS2fYJ`?s1 zHUaCXGF+tZ>2L_d!5+JIs5>^@=`&IsU`GJ>bx;Peq3hpS7u`uE5%|-nxmDjN-lXLuaFOAoSwg zwtgsAo~wb*D@iEa-qbOpQ-XNDlJlV|y7!!=&#Sl>roCQ+i=is39YN{B{Nxks=CxMo z%73HEuYrM=pgHBVuN1Tn-8rgI>zr&{FY93GdRZ1puF1Hk-`Fs`G&PO}sTzujNLl!M zHOgci9Ije?UoYAjQ0$ZFR6Xb`{Ulg^bgHMKF`L&5v3%-N1I4eL?7G3TY<(;jpsF?T zGLzc}0Q_F%E{$cK5gP^KrT`+y6nj+$Ooqj7dCC{JC8}UQY!_`)?zQN)PZiCL?feF< zpO{4dD>IiLnKmWc?39D4t%g{ph14i3FAo+oMqVi9$N;5OVP~2sUdL5MzjjMazbb-# zhiMd~pl|^ToA-*43~LC4b;2T8qEnW~LRi7N)zSAQ4v_9ET0PkM<(dGYY3MjAIzk4} znz2%H;aN@XvXg6ycG4vYS!>&{A*_aCnv0yOoRYqVH$bYWO!O;JavNY=SWw98 zU|hW0O!2haRcX|;Os&ePrhRAY7LL3Lk6VQ`LvcfX6gro+~~ z-lA9m8bnN6G z)LQv()g~gd##`2cPv8AsvkLbOcHz_2YKnLwTy_xX#B>_<7NapYTr+mw|J`U_1^lv7 z1;paelfSa-$)f+K#MMw*Y1yukTN~-}*)aD@9fA@3(me>0o4a44k)$P--$rg*)u1N4 zH#ZT$Kv1H!yJ2p;8gvf)K!t|TEuXgXHwyc6)j_UauM)U#C+D5oCP&Oz!0mOE)6mRM zuERO{B1zP~7*=@@4knoX?(XMcjNlu1#Ww7*6N%#!p@U%Gi^LZ2GY=%`uN0AM4@Ze| z#-r=xKcfl6aP5@_56ujs@l&TD*t(FOn3@A@t415&ks+Y`)XlaBePMyrup?)DDBu|D z#aN_1^~2Zg0^q=g6PkeGFUP$G_dzCJ|SDrt$)j$udb z#n?|i(Z;re!fQJdYt=(3R>0GAtF=>kSG^=e21P;jCVgxQ0qd8D-&@riA);Uy(2Y(3k7AY4-JQ?7lDIy= zW|jX@N4eP=7w4$F%_&m^Gp5@>DYQ^8XoVWXZlod>X`4D?#^W34i$$V&h0!=0-n;$? zLOQIju@A!c50YmS$F@c+NhW@BwDT z=}h0n|Lp20MoMYJT=pFD{9*=qwVQ9uD5n?%EWF@HQzp35Jsoln1`v?}_nsHY02$z3@HZbSdyooaReyi2xaaAd2ST;C zS|e}`7HEOOq5?1_+}cN}=^_aeZ%UZX$TNzc#*5kM2r)^M-W=YdhHGJwQy-)$^kP{M z%Pf9BpeO0~m`wS(bn8CT{_Y(gJwLiU*uUC4eQ|QBRS*W~-m)t7)04dejVK3p{|4mx z=*{Y+557A%|MS(s$>sTR+HK=6yToNlsBwQzUNH&n=RAf3Xu#X&J@G>i-RiFf;zYW_rFunHV9S_bS>7jA zm1cRmRH-ATlut-;Qm_Dv-5rl3KF0GIPCIn(V;I9)coR2*Rzv{iMPMK0>=OcUQ6JF;#UfGz9Y zD3T-1$f*0TAPrrHLf>zs}!5U%54KC$;=L zMHQC@bK*_=q+%$=cKYu0TD_^*Qqj?A|4G#H6smA#JnYW0!?F#=Q39b0C zKK*bS4umLytHTbORI`$c%kzWX=T|SzkBtiWXoPm-S6n2HDz8dGd}qDP6m>twZw3D{ zmPjvsqL1pH;CY3Yvqv@sUCWL|`ZcOVYm4Mj;_GBKsgV-7%aOvuulbg2rY z`&|qU-d;0Y(W$w^ zY8R=iSrp#v2&~M{q|eZ2EIq?PEkfDF_|%FrVC$y2*o%kxl12zycd*!v5m-tL632c& zf(1w1&?RovwoJGNqSQKpMOrB8?H^T2t^DOXNfqmkszrZQI5nry1k2LWC`v4Y58v?d zYn|u%D?YPtRcm22R!^B0g{5$(kG!jNJFiQbqV_rr6K;m2o~CTb6roGnU6&1EX_Blx z?Thu-HRC$f*uGU-q#(0g!gqIHP2FAI0jYwyQ&7ZL;yg%PD5)~hiycF!LmP+jv2Dwv z-78ffY>NnL+*?Euo{R}Pu*vfoPHd~~iJnT!Q%)JtizZz|15ELHAga4WN(q^PE^p%Sbv{)`7c}ai9kH3dHyqn%k`kifQ_b9&*X@Mf=sw+QOAr^faUTX)s?fd4Pc>DfjG7K$d7G)->+t(l zrIr&=L2Rt1TU(L+q5vgQ4XfsSS{J|zOD!+`^pIRZuBf=dz|u6Cv?}YKz3S@@ELB$? z&1B3>_^&N?*+ieS2*#VoG3=y>Y!friU~F2){wvCIIE3W|8hznYob*>hQ`RFyiCC24_Acyhye;O@gZ&(KjA&AjA!?A%5by~6SV9Ikca ztW+s~x{eXd_{e{@5p)O?E(JnA6Vi*SvNc}0Q`d>V+ejaD8-1`;?b}+?J(lVTrmNo? z%dVa@zntVsb}+k!tQQ!Sa=_e1o3WOzI|cFP!`qZJXZI|_+r>b#0S#d>2KSs)>-uZB1Xrc>GJLuE z3gM+o@E_;Kf>C4eA9RPbz9SY)i+7zItDP+!g8;cYk`!kc^J9`K*5Io7^3|0qwm(sZYg zrf`49&q?W}!GEx$r@XURmR~q1_x^U|tXSWD9y#b?@4PgrzFNUjXLDiEHyBpC1>Qjg0PlmZ?gpJLU9-r4Spi-W84gNql> z532IG)$or~4G{;`v>R8 zyMJD1V}=WxL9o0rd#5LtM<*{1?xjJ<1pHv(7$N(ns5HK>;#T7fm871n;8L>|bEB~# zKWIZ)^P{Vt`-~+KPl0%uJGClJ7M$U(ip=u@nddHom8dQA4qU+$d`Gh-i{*pz1gpUv z((~!cqiDMi?*hmYQ+uC2V>K2%RZwT)V_Ey{l)N#vI&JU!u}}s#SrAJ9aF{PIS;QrH z6!g5>ecKvWT4RX~WusQ{p(a8>cqN|Jaigvg%A>md{@?`6C>M*b!Fz)eF#d#tThlH)6#Z;F8M&E0?_ch#At|6f2doK!7TuWP7e>{!*!%D5neY?I)c#Ygy`f9je zXV;ZoK9&g~qwlgE_+WYO)&>LL)Ml7L2rRLz9^994*-S<^4a+V8uvqs>>yRT(BZ~)< zsn7q*Vry$SLa6HH3^*krY1H4^hqV1K9o6I0PuU@P#bHV#_S{FPXMVk)6m$q0@OT2O(hp`n z4rKb-CVRA%K8uM?`t0}WnLvGHt=|uKe!ul#*y@Rjf@(?t!)nOND*! z^C6GMAXZA?&36Jug4Ij7tmug+eU&F3-G*4OiqmV7Jch9dOGEhZBHTy`a!4r@i5*r1 zS6C7)$el2ma3*Yc&@$DC=^Mn4jG+lr-t`kc!+pV7dm0X|W4cM-M9Ljpg`!Uv^e&=Q zrrkp4PQ=+r>lBOqQ;CQ1kN`2h3!_oG);R;YF1h7?!rHez_N2#JaG1jo`h6Y@+4jzZ z&s!Z9A}D}%5Pm9>eqCeQF18!M=OA1_+k;o(6k$Dp7+OEOKP*6$3x*qP5%l@B7XZs( z``&^_ot`ALDHrezvK`xy~F+9-A=Y&7)2vBug;6*6LrsEm1t!DR7y)R+c3Icf}0 z=>{&drmIfX+bhAkpz@n5IT9N>{bFP6l~;GJF8xaNRS;Azw#7KoB5GSXG`d}3T@6@5 zhlkKsfnD~gOl)l(qlToaRAZ|hu3Rl{?(>-?!L{Qt#aN zkYn41%v>99#Hlyb4JoU$F0fSDXLQ-?nS}LArLL}$o^*ge5M!4}UT2Apbz2T1cA#Q#01R!2Epy$elwk8nM6f^1FM$QVEfylP8CQF6aiEKP;lVUk2A~ z2n=IFP)QY^f zV?D`Kan|*yIVi)y_dl5M4VKV>Xgb5F@fnDOfhChqLA(M9%8%8@!mlOXBrlhktSP$L z~eZl>RHXP#vG?vnpCjvfZoSK4%7^ z?FVI+e!Zr;9^W-nKdDk*!jQh->%6>rC;r|`anH=l`yKKWG=HvizPbIE-_zMv?ohqV z%v88h|0h1v?0?-Gvik{NaFWNFkaFM2wa5v-!7BCK;QX~8qi2Xr%1&9wgmwLEybeaN zZv0J2xO$#+@mj-d>3HTYBC_fA-=HeVF}V+W%VvuN+e=ROr=xZ&O;`y7vxSEKP+U%L zux<44!vO0I_5l7lT+F9vZRKeVXji5C(`T6Dw6vP7j$%FQ%bH%A_8{Olo$3_or;7xA zeuhZz5Y)3_k%hcM>`}Vy6T@k-ngxVUnr4)In+-i|@#K%Wae^IV1L&Dbr{-Fn1A@{< z)Una>W8sVPI9K(@P`AY}Dk3j%acb7@w(+Tp?QY}Jdt1BBw9c<+ePPS(?p+U>(M;E6 z6n1p=f@eiXkh`{-T74geqeGt8-)j@Gn8__wxn5kkT?x&uJsdpuXx9G&9J`oz|9&3 zvcLfMbm<}4S^ps^jA37pWt7fJ+EcfbLm9M3dF*rM1yere!8(g_d`CZXC7aPV!g$=%PGHlE%1 z={{h-s@fd72nX|Y9o(}RKDU_%cLfk@~@jJN)n7bAuzb1#lDz4{`S)@a=O@?usV zI_ey5XJfTtj*q@H1yXFRk|Af`WK5vLT3IIrI_dAS_sl^^=?bJ$c=zKxN9a&}>5CR; zT@o(}eBx%}g8ohQZIpktQd29x!CTd0 zlDy4tkl@04dyl0$H}kV_PR4E6W7-<~$KU=J`IQ8zJdeA>qpKN}g$eV=wAg1>>a-BZ ze!c({-TPioev5im@okSZ*DMmvuonRy(bMY>Z`{@-dcXGBTD`4Zasa{~EQNPyYdYt+ z6!Jo{#iMp@hNW7flI{_vi&<*fmVZsov+vqu6wyeo*J|WE8*877%9Z#%*oyPH=lz%q(TnFwZ8Bmg8H)tbX3?u zF>vGZ>Cr{z-fhHgpvQp-(>7X59tpcA`>As{v=vk~Y|yaN%g1u$qf}TvoWtFcY3L1w z$fmnZv{kjI=gvxx>C3tyBqH?U(uc7On70^_f7mk*14-K6;_lzIB*kLS!3Mkg`)CyK z1YcFe$R}){Cpd*cjCyR3eeXxmftm0P18%yAS)bo5VmM<@j`p5jqTAFp9wdo0QYm6X zI2zb~-24nviVtC4~cV@mzECzoNmXMm=UvxEJ-gpDcoLJfqQS z;}~?GLMx|y1Eep11S55P_xBh*3^&-bkeUSBJ5W^77C}Y`IJ0>7Y~&3YO-A2~psC{g zf2_rL$$A2iI>|3}gY8~Jzq^W_2;AOa*Nf#vw$Hi`iYPBD(Sk@eIgdGFz621?IN`Z!_s{q zMlVfwETf|E18IitDmhdUg7J|*b-#_gMJF>4ZZTd0$);)L;4F<3 zK1s3_ltgeoOlcwfd52MU8@ZJ9p~SJv0~>6O=$}%Q%~?vcNrB$zq}C4i?Cww}G1<>_fy!JkA0-DPS}HW@W8#wPv29NTPo zI&6C+K9%38FVa}N{W&WHu9?G&MtSX#&H?c8=lWyS%5C+d)Wz2rad}JItxes|Jt9N6 zKZuVhp0ubKAk*&YOOh0*>`#YIK(yfqv3QCVR&ohM2bNUJ41;f{VITd&)u9EW`4-q7 z(2C2j$&9rVan!5D>Jdw4Ly{nWMwv~icBH+SKI@cp>Wl`)S%$&5JEwF~UhoFiRm4GL zqXU=@W4w&n#e*0G89ecB7c=&4M;WA}Ry2Qf<(2wL1feAgKb~!y>-wp|j;;#%tsZvoyAyRoQz}PQiVN@h-Pb zrFNz%VK(i{M)Sz3iw(JlvZnAV5XX9^dns+hMh@fvSnqd#N5D;iFTmP}Ab@&Z%qOTv zLsNLn?*4CVYN{Y;g>tqiO#wHvuFTcm%mcIm;odduK^Y;7A**bLvgK@wI;c%gGmFFpNFJ+T|=Z8^+1&IGBfU@<|fH=`( zdszmD&f6gu4a$vC1v9n8{$-6dm%vu{nNVe)$m3JL=Ku#wt;E=XO(CY7qdnU0+5sge z4z>#k;#y#*GY=&w?w2;OK8!x<2lrLMihGG5UjYBRxe~V9jibfjTo_hwd)nqqkVz6E zasE^YYnBi_m8qMeF6=jB*K}o!h!fouf;%~*9pw(N;pm}j@U?$g#cKq8WO+|f` z&K^U$p2i!4`j;dO{i41w$%?G$xf)}QbhQuloKckwd#?+Rxl5{Y;`CwMi!*jRgJ1iL z5Ix=z8|_2)V1l0#B5%_~q(;I?6R`uA^)J$vnj~0n+l?%SwRHE?X22}6+mCE3MvCRM z&^zzgHb>9vfeESSq%y=|9}1K5>V0{y$c__(mIPDDUQMx}+|QZ*UG@)I9zv!rxdyj_ z7}3?EZVqLEwNL8gSiu$H)^dkx~BeLht!Dh`kLNeO} zny~^BERz`sqqVx*X<4Flbs0DG#_`@Rri=c zf|7vwnku6S-q9El&;nZP5*GdxL@LAPk@}^QsecE1-YH-Kiz$g8^AMh-SJN!WUyHW` zlcD#VeRl(Mfq$fxda_{RH;j#jvw*IRi`XeO1Q9X>A{+Qk(uU0)$u%?l#LCxkn z{HVN*)dAXwP1T+8gh=%M1do_LZQ1b(sCYnz8?fF-=EM+ zenA{Ldn54E-FZatR6k_6J9Q<$Rcc3T6V+jZWuOtSN)?s2$xbvcx6;t1gq^#IkR2tE z2|&564uuhA{!ow~f#lI6R9ww7$=M@NqlNA)RWQwD zT9S`?@IQN#{d&|Z*Zu$8%kcQib04L%)Vz31g-hL7hi`pUKye~*$x%aJG>R@vwGYfx z&Cl)7s?{vYoq#7V%0KB^3-J+0Hf*35;MXjU*|0qUUvfN&HzfkS0-o)10LWhP#AWsLP|%Qh@e z`-PaFi!aWX4+@B*5F)LKyh0Kyz)ik14MMf|s{jtS95R%+r&4?UA>hxVQ4ff>&HlLUmhc<$;vxD3Uxk#TF%k@J(+j((`t-SzMsD|Nu(D~YUu3i}LaE|r2l7Q5OOMb%)lEmQGzPEekrJZQScQ3&TzMu!DzB}`*cnF;G@_k`9kdtRu@u@Ap~Up1bYY~XEmD&7or zPvq6Mo81vd5qM=@$7rkC2J96p#}y_>*n<4Xy@pPGy091XmYCCrrR!Q}$Lg=iyF4Ds zHajXO`^5+B>~qMF90QZD7;U=MvBal)O0no~<@?KNT7Y z2w-YfTE(M_KQWdXxtI~_-7dMk1R0#^{)_yPhA;NdxL2W!UZ-5@%^2CY85>c8=+gKI z*T5^6!WbP^vdGu!QM2!=Q!YOJB$BRZCu6u#W?Ig01Zj`;4-F+#j*7K61MS>nHnCzh zC-cqjyll^I_KU~ues}1jpdo&qUcpZ`P$tYLEvx(B5kj%&6n0c=(BnT|Lo6wfCDz~r z0$!RaSyr==^)DYCYC>z3#1yabhk!6pee({34N9F$9$236r=|1vSl$T-H3zb+tbs<* z`wOq~TFSq#^a*hDZU}7kd_Oo^+{IK{byJ7@=9B%n|E++)4ggQ|ou~dgr|9{U*d2Nh zUz-{JRdk|SSCZFByHvjd>vEi44=hjr13W8ir8JP{Q4qjj@L&oUbYF}sDM`Oz?ELU* z2%T^v=jjsb_v)D~xl8C`q0tG!Z}d2^bwwJ*QqO4ucZ7i}a-a2Ik1KWJIjLnF1zv|5 zdRo>FLlk*O)5lW(K6aDL<`a%%a3HJfVFP(1CqXo;0bVDW^=a)jsD>q1B}8h851TgnSx(yA`> z$2#o5?I%daNssOqSvAUYHAHPnM~Q)@1A8y9rs#!Zw%GR|DCD|#R!nQ5xc9-prJ!D4|$w355t|Orag@gk#LH0 z!%)4=*GQL}oZnaHAKiM=4Nd3H(xSSO-6-txuLFTT7;)Xhd|${S0cp?gI^q6OcEl~O^uKzsJfUPWznepWKdTdcDF#3;Gcg|pu0sV!Zcz1eIOg5A4D{vSs}$3jMA{)X7&63s<$c_Rt=D_3CV2&DY(CF@ray%#-G zfBsG|10AP09>$Gj$*7Mo|F+&>O^&539;oI|6k;SfA*%TtthO7{7(;0&iakm*niv^-DyxeGW^9J4 zCCF0beuee;9Lv^#gI!6&uO)Gli&ap(8<2=xt|C9B=wM3%fVg~za|kDODLGEDNV!d7 zi4(;xutT3I)eeL}lOvK?(IH-!bKil&I{;WrqA<|(t>ETDHK2SGW_q=#RHI2Gjb?E{ z^wW(doEXWc!or6fX0G?`{7i8QC>h6SAx}AsH3gKCD!(^lxRO}CI55PI3QSD@Iu#R7rP;6HoZJW zV1E;s(v*mfetl4F_>d>)#CiL|X;psSQ4p~Rr28nGDI=qOj3H~X1W|GMymnC#+Li)0 zuWyoKf)7is8exo}RFcjQZmf6H`}+w|i9C_10wCU7-{cVzzw!$VNX~rJSZspX#%SJ{ z!;>s~f6o5aTH+6n)G-%7aosFr*(e@gJwKGe4d|Y1Ad_ zAgEOX5#C`4cya$`{j17kDVSd3z2Lc)o00I&K!UHmPa$Ia)io8M~WVJ2JXkGb*{cshIz3vo*7JuoSa4wsW*} zWw3QqSAzxuUH;*+`TDoqyfc|H@=AU-i=1TGO2iIWcS6(4jZra)5Eyjx1 zWc1`+Z9-468-Ec8Mpst1YMjskQq#Ur3i~lW;d8y`oH2NBc}ESLvJG{#3VM}75lEfHmvTJ;4wTP?Kd3Zz3y|3I8n9v26E!{-A_-a%ONa`> z`El|jVhLL3PTbUl#dSlO5kpMh|M0)Av`98nAEsIp()|Y9J~}Oyh99-pNsei9cyE)&e~_Y`%48={)!@~PkZ>zytnoE zrMV#W+K%%O*?B6UOKO|7sp!ztJSt)4*QlB(_{<89Lc{qx>~g8eDuidc#eEA16n7FkX;rEetYZp_f-HZBj0Vaa*%X`**GLqZf$LCOmDyuShBZGc)rn6 zUuzm>YgQ!If9BV>6~12@uq+PRwE@dV*m}A@az(;Zqv!v|rA!H-FLi1N05yO7>$UVc zi70qAV{wT~HkkSPwQzpFd-;QtgKR__B)Dw4{{DW+{=lx*8&VyT2NfaPnT>^P=Jyjz zBw%@T^y%kXXb8clqUs?I;b`dKf(_oVwK5M11Z7%CZ$gdk{q?XP>FP51HxA2WU6jNd znpY)C%W*7JN|jnYIfz=G%fUIQH8h{N_BAi~EO%a3Vjtg_NV|w2pf7fSF4>PwJuI?F zPQls<`iV-q$(;;XJe5g_1AQp@@k0?tX-XtJ?#zxYTzT&&KHQ_U?$wShoi4~S{{5TT_t*=W=Ni|I2WtnbsTcpP>TifBn+Mys0fLPjLaqx}0j0S_;l3w>h zRV2i+At29OK*FbOruv)%!!m8(g>QoGH5Ys_#090og9fH`2|wU_jvGV0+%O0-Zn%V) zeAmGzjf3E|iW21@7y}|9+LYVQaW{Fx@JHb7>-M^l|CL4PuK_d?l{O(wjvNTbgit(6 zUw^80C3X9YN^nE+3L1nw?}&wiH#iyjHjI=SuNf0rZXk(c@XiIyFk0aTL&4!mTb$V= z%7&@}gi%>Y7xK%t`|kKfH88!i`|RVGGcu%U|hBaYud zu8-etoq9j|tB`V%7S)u&w)Vw{G?_9Eg^L?2auWeJiVGV!F#?WLEs2si*Cz#Wcw(W_ zb}DqLD?|yt8O4NUT3t5XDog~&jS%zu=Y73zFqwF#tivJrVM=(>n@~9CPxhz3`;X@p zyPjg%U7%J4;V;MpwnO4cAxJ>U%8H5?bvDT z%%*|gaNyeCsd@Pp@(LS)<3%k4BIb!M3ef_%UaDj?PbhFSWu-e#yRkFTEy@7p)((}6 zDh+ih&;d<*Owi5W$w1F={h@hT%Fe1*R`%6+B?mM{T;L(AKSfs52nwo83%RuJ$@FL8 zWotA2^YW3yAZ$U(|BMi^@Pl|DEr{Xi+PTzP1H4gse}8}f-sf$2jxgs3mc3<;a2unW zym-?)*!6`^v;~uLybG}5uuuC`dv-Yj!FJcVrauF-*8`;deY(cv+cZ&4ts?p2btBBP z3V$^0VF(rnOtT+Jz|aSdlOGN}PMax}doR^FEa8gh_;?x%XVT|I0I~fJsADSkkp~x|_{)-@Ct1)NNQgBPaUey@BD2CqO zcj=;hb#lY>mlvxYgqA|Pk zkZa(&Eqrco@8{Z#lWa9nQSst^-)9GaX`;-P6= zt+vtOI{d4?=)pO|;4Ob(#!&)WDF1#chKkKrzRay^gcdH4-a6as;<+7p00U{8^Dj}) z!78-q`}#d6w9V|&dChKCX85egq|y{3!aHr)-4v~%?|cF^GR?+Z=L#>6XqFD03gH5^ z>RN%*$kJkhY5I_9F1I}a3j_fO{vZ}OXqGE*c4tU4j#{v%)D7Xn{=sHHse`V;;#;7R zci3#2)Y^eT7@&u z%O?h@`V?B=HD&E11P^eX=5co_#zicMyIfHHVM~N-VBZ-F=c+j1ySon}}H4#WtyPoniGy*7Cg`S6J?f!TBeNs>oFnm&G8=HVbaCgs|? zG|*)7s=OUtC2LbosS(iT;P?wg0?m+cnyi!G(l#5WjV$D>0;v)K6KpSX|mnKihGj!kXf!wzz|SnfzGDC{@w=v5QT#*6*)DE@4=zVnT^T??gcmV&Jc>jl6Qkeq16Wg?si<)3<%CwbOynd*&a@W(n+ zZ{E5=bdm9#c$wQx8sa3OsMx(JqAynD>chTvYX-?K09rW9z1WtNFR=&6T<;>36#hpB z@*>wKPL3MunMaRsZfpLQ@v2cobnw?qaRxg`1ZAkOQOVon{^NLmU&QJvR)c(}Ko!;o zI5K7OQ4TuUnoL8PFYLg+m=lx9@)srhayIl)w1TdXYkcyp;w%R%QYhWk?nr+wZa>F_ zmgznZifW7$j*XOJFG-MDh;f00^9H|+o~X_+^5D?qzi%*^Jk*wq zaLp$ve_T&4`(TN#IDcOUJHcI;HTF8csi{ytjFI!uwK4YAiZFM`vyeUQvipVJY3HB? zolcC9+3sUhPM!?(fAUzHH<8>OVAz>D8KdAraL`1gvqdgm^2vf^LfkU*zB7&6uN2TR z2k}#BXOI;yfYxz2FjO9IDem9pO0Sl9+J95Ry2mAj+e!5rq%ChREXIs8JV^{f>yHeRYh*HtNtM*rygu5 zj8!J#3OEEn=UZo091GeB3~<6Pd=LS{)Cy`M-hamhjb+kIC&;A_sU?dUdRLsRh*?}q z65=EsU*NT}U&pXX-T2u&7SNx+*y|qLkRF%6V5oJ?&xXUx8n|&uW)OMtcM}}xc4W7O z-*%$VVthm_TF9~3rpvcx_u}V>T-~}N~+>aS+qF9I{C z3AMo~_vE6u$9;`yE?v4AW`8$33K~`lpGAZJJo4T3 z%X(eDSm}G+K6u=C$g9;(n~{T2$2P9Dq-@D`7dwjqjEOHHo<2rCz8j(6u|Sm<0v#$^ zR$g0|t|c%WQK>3nng>kVA?BbaZq-u zxXB+hlOVS!pA(wdp~USFYbE7|lYH+4Ca&HiL|2`qCR60CRgd|2W5|dkcaFp|AM6Cu zS2xwCU4<-}8wTe@U+c^+YoEf8>|gQO4Vng)_zL+ro}_)<5;v-zdu;d-gD{PX`Yqa~ zOc>vUX)7kwK8D{GnFg4H8|9DNt-&0OM!h;hyjx8DCNw{s)0Gc``sC???S(d~Z7_gtoC{#nq)PciY_snWN3Y zm7~k^$rse3o??S#PJbPj+bh78P@fq_y*ZtkC}bUAsa>i~qr}b1F8^_Suk0)Vc`+JK z`Mg|>c{jNMnWzUQ`uPyN^YoRo*a!#eeSxYK5AX*1X2Jk`o9E`-Y#nh1c!KTIo4yfb z){~Y`_H0z@XlC?NiWtH*hz7hi^Cxsa2Nu*2r8Kudo=h1E;GxU**ZgiUqEV*16$I$Y zwQNYEcrjhU)xG`>V(y^>wzr(2p&2RrSCx#aH_p}Svo?T2Sy1;^e`ByK&vj+cxU);u zT{^P*aGhW}xhn>>wH>sz{;{R~&<(rt{Gs{>luOo^SBCJn^yaKlre}gcndE(NPc%NS z3G}0tbn_W-Z{)N$LgoXG$9D0WGtSza>fg(VNxlM0C+qrs6@o#@I|!ap`X^OCrkjPq zt>c{ft&H9VJ)>L2qE+uPM|#Qy}c&A0`6CD1@XpEN)~68{B|6)`rowRCZG zcQ8{ix3e}jv9_~z^Zx&2_J0GjIy(-B9q4_pstuhfkO_+$_Q53AbQ}s6%%K$7;(6H{ z-9Z^tx$NTAWa%T=VCyvkLJJ=tqXMG!Ck&1(ii@H$EmW7|4;~QuEyv5 zEO>QyAw^kXo?iLTQ|z;*G(&j_5^TT2mZ2WCU~u*#lY=m0!lEa<#nZ(fQNs7x{ce)GpayCAl~jWZv|662wKrp`v^iK{Si zENP_@+qH|?;23K(xVw}QDX7f!At+)wG1FN=9jwN-cc15ec_}sLJX=a0 zZAbwf-L>L$gdB!-rl1z+!}S2ZaLY99iCWRgaiIfnOvyiDP=`b3kxEGvT|!4H^_QOilD6g5%Xe5_iCDu2yfUBeggQ8EpJV zI-{3VWr3!5>s;rUHzS>?)pCYa;_kLp4II`{qNS@+uGSuVxXwy5%7>C znUDAzelZOG0H~j#5YC8a+Q?nhDcGOR5+%|U!Z4yCDegar`;sJ+Axr^wyG5dI*|KI( z&v?_&U8H%XStwu;#nWq*^}iPC_Rq{(r^F$oA*7RsGe(eS(fy*(RG^j1>zKko$U7FT zgimph!#k2|=0y|SX2;L2kFh%>hf>~w1x$?GImi?V%e6I=RaDN^N5os`j)ELw!L^xj z>ezHl@G~Itj-cOzO_CQ&X;FsvZpF#w@zWdG#mtX@Q?!F==jn80ss}e@P|>hTDF%Lp zFKS&#cRrv;5A zid#r(4I?Z{n@DeKJ4~O2211o=4{xj_p+I$WvaXY#R1vAziUQU>Hto*Yf|eVh0_7)? zbFt1Os#-6HD%tMZ3S*)A0%U{_=Qpm2RT!Zf!51R|$WCcZDZ;RqSulPDjd#G#2s;Kk zVaR7kX$Y0o#qMcJTavn8NqUFNO9Z!w&^}R$!fJ544w%NJRQ96^2qz6tjluXM+7IB- zKr~hsK7f(@JT0N1#h8|$Nr8Y8?Zq=lmOA$8gSJT4h5wso40C`NH3hP0Mh-wx|QGN)~b`uZa)B{4yRBl_oSw<|ISh19bs>~}AiA$#UyhM%plYWDlhq8Y;|gI!Le~FtkPk}dEFp|ClG%xy!Zu3S+`j17#Ok0 zfAbiIsWKO@2omJ5^RFKPA)~hoF3ox)uVLfMTG`slO!5m{yaW9oA+;I^M_yPdN6s|%DTy- zhtsjw@R%rd?TUawTg1e1T7Xi7pf{Iy@M;@LRT}qXbncRX2gt}>1Z4f~gXgDvFqJ|@ z`<%jLfsl7&cx%_~&6-p4d?lQ(pL;!hKM`;D`D#i?m~RtYXs~#eh!fhNFV&8>TkDG~&D0vTf7imEI<`N}{BBdxi^C{xL`f zc6vjtlyzm}u<^5!3K9}{k8@-hk~OFE?>;Cgc~CDvhCl96A}Fw%hS=vO#Zj&Bh^mKz zl&WjR=LP#{0Tsh6-gOh;4Rch!O)_*~lsGxLu4wuaif@OSX|U4a=%-)G7$M=nbD#Yu z56(hjBC5ufU)!r;=*w15dcIhz$}m0;7Y-{-`v4XmDFTKY9P97)B2+k7BZ^Wr@n9wQHuwC274+qJ7!A0rq-}zHHPZon#VipT!z~d zGDk8Mco`+a{5wj{&hjfZcW_b1ss5H+;Synz-h7g{`*nc3=O%In`g~RtsK9 zucssihDli`)}j3yv{}0E9`S$TsLFy7e@F!5_NM{))~7UF+{^f!kP<|8RW{&rBp+M|oeUVPU7;ru*nCSTt)lvcUYrmS1WFR87ZSBO z9v_Fu$m@E7KTYAzM#?`I*8uH0ZX)sA{r$w3XF^=ZT*nwH^oAYu%s%Y(XA4f?sBr+LO3C{=MP~nQtEsd48&Su)(UP@u|m;uh>r~!c4^0x(HGut zl%~clhyExx*TD~QFxMre7Voll9YISL49@3;9|;Z~(|#$Q)i6&;kL7LU*fI0OlLJqG zUbV0B%Nsssd4YJ1Hp!>1!<+e5c9rjbHn8i0?aow$r(3;8d}dpbkN(3%o#vm|7a7YY z|A0z0%QC|jNvDkK;{;;*AZ*bci?O!Lw%PD6_=UNrV(f06>0bX%Q(N}Zof`Y!nzpYi zTrVCQ|1?Bbejl*Xt06vwz>cez&5z=~zVz_RaHl~e0(@M#dnFt_OVUs781X`UA63_0 z_s1h6i`vU(-JxVy8?dx)13D+oD7eV9{B(hR2X?5UJgDoEmb)p-Da2OV8ysa^f~Zr! zeRl%Z3g;~n80Bu*RLel}YIhcji60uZqYKY1G6WC9X=5iNCdqEKmEsbxW}teg*?~u# zg$HwG9$@)9qz5D0QJR&1%8l#q)1e>|PgUgWX_#w|Fa6_vCx#E$?HBBSD#Y^1tTzX6 zAfR>R|1M>(VeaB;?dYK3=w@wd{(n-2<(j`8wmFdcZdK(RRg9*kb%=zJ|Cxist1K%3 z@wNsV;Qiv#L6%LXk@oJThC5n@JnOV#^o}U-+v1!|b*n1WpQPQmjED@+c(>pZ+=G+k zjGKWcMpDLSyoMRl{q)b9=TNWeyhv;e4`=YGeIZ!vFyTzuF_fSZ zYmVaG2lh<*>q($I$ssr}ac$W7b_fCX^vP*PzBq3pN#*dTIT}x(FPNZNWR&`WFcs|3 zm=(vXww!D`nBUcGJ@k&c%atNFGFbahPiOh6=VYjpX!36gt2T&)R$>pRaLdM7LXL3( zGf(0uL6hp6I&6@9D+Uzj#Nx0?a@S}MZMRxeigBIJ4=7;}2z#@9;+(>gmGJ1>)+O6g z5oHD+c|lC7iu2x0SaQ9QM~J2cT?NQJCGw^-y!dh-znc6g>cY)^q5>3>(onv7ahz>A zUh1@Vz-)H;!3!OJ{7V5J_8{ut^gO2`tvrzETNGO~z3R7N{QhmaAg zW>FeZn!B8gOtfefVuDnqrfi@p1%CDIm*9FhD{`g7&)(SMgx2M<3O{(rDpfo{f7CHFiBht>ui|NY#9vx@#wiMIl zGa^)k-7h!}g~{M!!77FdgZq-P;bb@nd zbtFWb(_3CA9zhq%a(aM{gcC4v2%9%<1$uGl>JD1`O6*h&t3)=o3q)nM-HjbXmjeiq zB!(Yy)GlS1;DU3z67df@4KDfLiu1G}RCF@KuM&bSIl3xTXLofe{-t%WB7gmlOkGFG zM%3j81zKe3Vqi`EzBrgJH)M(`tif9G03q@^oQ|X!rz#`I^lT1b4jMAHih(N81WLWX zfc6;I933QR$!S;9vGeI@R7(X|cC8nJi(D$I<~O?M5{6sr`~JN{E;uHL>}D&}plPYr zzn3B8Bs_6Fl8}I%t~nNRd$?quKaHlsHdWftcDK3@uLG>P2fk^m{E5ji#mt}*s{W*P zQb}uJE})SgR*9_pgS(Pc)uZU_#4?=aH7?DnEdQ|(C+Qah(WmxmMN~}ON?Ls5(fjb+ z_TqLMlj(vnz=sIj$eJOZz)%7(_U?*OG1K!oQN>Kf zzi(IzovQu?y26B)By9$pS{I#DR2P{1TRZO437OAVA=Az)lYe*+3qgu;xxQG+JJQ;h zRqeM8Yr2*k=u`>j7OH(eL7Z21HR@5x#5+4#jdb{O?Rdr+9IJB``5qEXKTnM4V2)K^ zM~~0hP{yFHlE)`E8DA#y2Xebz)=I+>OfRyPa__ z!DCgq0V1zA2&$9y;|r6yF4mJ7vM2G_`)P)T!!-ehT>^Vg?3_3PD8@|}yv^;EabA8Snii|%MUm$V(r zSRB_Jh(**WZl7n>vnFHKL1++1+ZR5eg0b+v1g$w%MWrmBg(x!=gDZHk` zu|#@MB;L1wIu)DHHafF_QwJDFd)TUap-|uvv&gj4#(XGRS|Ei$NF}Tm{Kyn01~vEWv7{j4@Mj*2 zn32~>N;h@4rZ>=g+>-{52AceQzhUw=&0>oDfur*!{B)mZ6zz}BHpBUd&2@t9?e z)ShMY=VLANN`yXsG9Ot$_Tzjrrv|SOZjO=uM}3Xi;s`9T)4t(lA?;4_KZJ_c9Xt?- zRjZ7>X|Wp^S8i0OmxbbCxtuwh$<~gqxc#m+$_BaVv{GD za<6sC5)Fja`t_qpD*`rk0A|+dVq53g2|0e{W@M>zX5!DaL-=;}MqGmRv$iXAuV|Cm z=;i{a+)&v0%oS;>^v{FWcG-cy0rLGfc{LDd^1x${n5|xh6bTxX@{l_$*A*EaEn{x; zrJHWsZotBR1}fSf9k#@cZlOtci*em5W<;;2=ZL<@CD)C<0nw$rEzWi*1~k03Jb%aT z`-uy%xCJX9P-4)(gdgO>0BAzIT(RfkxryZlj*^htk%{^vaxr1f^B zT?Ya}#{&Zr{x9yixR;Ziql>wVs;P^)xr4m1lbp4Qi~0Y8`fByITyP~*{MR&>nK&qb z5Ernd53{u*$gz8*@$M}`QaG-hxM0piO2Z^DD;Ue9>PcQmUz|x_#P^sK0}czXGOs3U zf8E$@Ls`{AW?#+D%uY@5c>_``UAU5yQHo(4j(29x$TG#NC`w{8VYGRJnck=hOQ zkAS>7KYyZB-0Xh`btaW@)BbYS#*n0-FhAb}nnr1*2Q&Y-boi}%1tibv+YW>rDRy0jCj8HVHKS8q?}}mT)Zxal&yv^+Qo+1xxg@ z8ab0m zJAx;=ZGWO|>C!_rys0sddL08%&C6&}tlZzHB_(r+a)kwfEkqDj;p|pE+B`WIprD#s zog^RmGq5&uEihoJN}Rw5r}#Swvyt91&$Rb#OqOorB|cluoM*$Um3+^cPSf$pB|{Xw zrtX;+=J~=(fAGN?!<4a2KZ&3UjmvQ2uME6Aj>F`SPX_*_;sxzGgG4EP_Uuf&#yHRH zn$aN4YU0PayUumlfH{QEp6H8a}qjhf8BY)8bXKRC(NG`6= z1P<~P35Y%vs2+(&S(4Xo)oPQpzr$mKPZ0gIB8Z$j9Sl~86sKF7UKUfUDbl zQCsz>OpG@Uv6U^>OKg8JR;>djfOR>3h%;jN3STY8LAIq;(Y*MKrO*%E3vJ%xNaVjs zNZXnm3wLZ~b}-&dELBPM-oMDBot*G5d(|bsIh|rQQ;?dXzqC3_I+_@DT54})MWJ$d78fhV4da&L! zuAyUfgo96RyQPmbDE=f>uZ+g_OcV-YPdc^zv}o0kz$Q6BluqI86xT0Mt9Vnyh!P*+ z%)T6AhB57DwrDLR?%*e6n#bPQJ#fdc;wXe(&k6D1lypoza3Nz}A+;71wZx-W!*27Y z3$L#H2*LmH%}+pYEUnI-OM@x-&&rux#0m);b(GDBI#O%4jM4 z=#f8^kU56CPfrOxaWxHh=Zq;xf|e$C{Is6*?rdLt3_L)~a&CjmJ@n77R@a1|U3Z@; zy;PF!uGp_71?CJ>vs-9tOvhe$_o?alsFFoczT``oe@R#2)a`nqbeP0m4IP#aZ9o;Z zIw$eqHLifGAbN6P!Wm9CZH~)*3a^vt_o~v@4%}+bDCW^l&MUL!7CTtG)%mHDOQ*Qe zegN~t?ZvX$A{6>K-D+q{!i3L|L!{NXOP25V3)Nh<93}gwgH!qJJ)zOwuy>;6K^t$YI>!o`BiQCDClPD1~or_ z4Wig8%15UIdolPd<&I;YH%T8d=UhlXSRlsFtKkp*_UVW+%Am(V(FA3_WW2j*JIqHEDt#K2; zpF0Vg2A~)HisH^yB6BA8sYae*T&?!dEQAh#Djn<&lW^+99Paj=#n^HW?^RMn zGgxD(EE1keCG&f|9f<{^)T@)g;>)MaHcMB#MOcoXk;1k zdqr4_e^1aQgjt6*yLx=Ikxz^~Ks*_Y_lQ31whTCDeAl$hFC{aBZEdWbj!m82_?S)! zt`6!BCZ;?a`URb}k0l-g6|@T#q{sIeVIlf=$8S=H2>lvnmHhH9S6}&}Y$9D2l;9i; z@c_$~I{z?qN=OKydW82u;cu-*afqYb<+>B_+4fPLSP@yiEq;yMb~W3GMykCE^gW;< z-97V~+JfynMU{s+%noe2m!?ForC~7oOuxWwx0)9>0m%;<+``6W`0tzXX)kfO*+N9S zYSmVd<}mZBTKHGF1jUU=_IC7O%`A02K1>`zfNVZ+QoD61xSfxztxTBoED-lyKijR2 z7r!tn^31qsCT%%_xAW&+_|V)9_~$1{BZ8aIc+O1?!(T2Lnf^m~aji_CzpG``89HUx z{30cC+_DtnG$^3D;ZjT_Dyu(Mvc;|UPB8nRQ zPf7X>6;pl2oa(FJm|h3a-7D4|K_=5C3~As6>s}?II({4`b7W4r4ZldiSiFZM{pW~s zfq<1ufc9ldwtFjGGg8A8dgZz<_-}y> zUOHjxq()%xFD+#`>Gm{n1gR5m-qO806##$zwgCr?$U%DV@-Dd&1!y!)Zr2d&3CJ1gpB=j zYp=SyHA_dRi&@zW)PBATg`@Gnxg4`0Sy;1M}tr3)4Q96huQ4aMeOu2br-!82B> zuNdJv%&>(YhO{SuE!?L<&JlFSQGt*oXfCTdYv4elY1Iqq`@a4-kVmMCGDv z4O<~xd)LDKK;bFLxh+W}ge?F&nD_Nk)g|j*La=V_f16u7RX%&d=HvHTc7H^Qz&bO# zVtR}0n(f;3yL^4ClqKeMy3+eaRV!f?`~g9Ikfc*lO0gDc>5tACcFs{w1bVa&u@muY zl~#hoqvPJY)9YWZFWz1Ka^5>T5}(D37Y*!WQJGKsJmQOMCFq$ah&|J zcHeW%`_6sHnZ?QBu0S`a^CCpWNcA}XNWF{bCHJWH*{fXPqbi3wv|SCVJcTrhJWgwF zo(PaGyUZTR6mCkXUW^o~gE9p|43#j5YN~EPcal&=Z@=i&=MqY|l9!fTByupO8cIi~ ziEd0%NizeKQ8XCI1Sbgfj{+JZ^HOn{;LDk~7<@#P#ftA_d0J4#g?JG_4QR3BBn{Lp z6(%U1?gOzOh!7?0So9P0uVa&U4kYSgBnOCXdWZ)H&Oz+P(7wE=ohJB*|6CiJ_FI{n z!9pk#K(h0nJ8jQ-cK+>G_>T@h@9__DxmWI2w_%@md>`Q~f?7zXcRc2Y*v3I2xwS#v z!#|gV^Ncj}2cIvdJPGgCw!A;g`cAV!wXaa(2O637`GubhJ0 zM{O9OfhB)qhdI`t_P7ATerc!ypO)0Kj<^eOLuy1&#wq|%&`wM0PN=h(ibI)8{&eRE zY{6opcKThU=kyhTN@G!h`)wXhYKSQHD(f_Qw4@$zpP_A8@#$B48;->N9hmxq=jIMH zX43zP?#4wK!9=&nvk(z`wDIvTOe8qf;C5HIie{6Jt>R2j*ag&Pf^MZ?VOrO zPYCYfhks^y4PnwoHK)3aR{7=*brXy#&QA{BT$e!~%4|+L(jW~qu!hV~Y$r}4YtN7d znG@Sa*P7!eYK)VKnW9Sx7R|rlMU9R57rY3nos+>j^qf21UaYY!P89u|>xEr58TV&( zC=68c@Xws4GB7!6_*0q>v{$Q+Pp??btG(KnY8R|9fDTGM&ugBbI$y;y?BwQ*e!BiCl=(Lqb;Z za=Sn})aM5+??59sxtQ0R{wzIKp#xPD-zfL{S>_;PmloP?Ncr6OZC?AIK>ste3ZFFT zs|=S4Wa8U$tag%&3ks;QDp0-*@$@cvPH15sEv`X zLH-)EU$8mu*0ZBPTQq|!+*h+z`&uu&+3&%>bD7+C8A!O^T%uBI_9Z%3u*V`R5ea_Xp&gZ-m z4WUbZ4=H&bqSpuYPJc$pGO_!<6Nn=|Q=nhyD~Ubm<1@Yb{H3;hh;#`oBl1%@prNsi z8_({Pp%*r&Et$>nxKgsI=l*2+l-K z=VW17G*%kRcu*GqY$Y0XcGzmJUm-&4l_C6H#d+mXuB4yC$48KGG5Y^hTGfXSC)mDo zP+}Vw(($S)58O0H(4Y<`vS-mw`*OeV$Vv1uRMfLeKH4mio&BK>oIuz{rra-Utw>RC z1+xSVeE5q^5vRTL)06X~PPx;W#&%VT-k2)f*#|>D{9=5HY6te+(PaUKNaPSs;0>Iv zP{C6qAQur&rR>qcj`-RrB~!Q1Z1+2zI6_0eJH zhjQNP6sdOGiS;#WZp3{tdiWB@++W!{1Eq!LeTsXe#zyZ6zt;15o7UW23MopTNZ1WB*jz`x#DTgkvaIU6 z*$Fb!uzE91Lww3(#e6_DCoCB>p_5k;CVC6~0=JxIBa;TR5}V4V&~8f0 zj_Y=Xozu0whNqg6*kSis@BCfww9~}FTf`h+5hx$i-HE0P_~IyDqx9joGJ{$8jZn+l zv1w~8vwp?gxg5!`O>vw#6l)0k(ZXtC0j8XS(5Y;Vtu!z%;{>r0mcYw_;7clp(ug;P z%o`3RtI;xO=dhsuT2q(&owQy?LyC6=*a71t37|AANY&?_cvd4TaxZb(aY=pj5l$ zd~XEHq;{*$V8_^rF;zG;=u|wq!zd3a}mA<7Bp^QD#DQB;@ zbUnzQPw)Yu3dG+TsV#!=@f4uDy30}@v&Ql z%3aAAEF0K0<^8${!R#k*sX7?MgiTqgDg}i%N7%E&-5Cr_{y;}f;Aw=6cVxM)lA(Hd zm;FtT6ML!08j+@Lb{5+NJzlf5B&UM#c9!xuPEzS1H~ zK(lt)7fUh7ACq|#b^5br)U%FqZicglv>ML55IgQQPI*+PlT1!+-^YUZQX1FQd@4VdRgvBb z12GOtRP^fmvPMAIBR*m(uLU4;pTY z1v{7Kro=(0K6RBq1?KLK1U8v-_e70TKAvV{s_Z151)hJ=^o^TT+nW)DgCnlyXyru(Xp>RxQ71X^Jm9<9bLlI|$7rT<@5*9p z%7Bhg$iy>o$rl*BT*(kg-}Ki_NrioL&r{WA;Q55P9JS}%c**^j-IZub{)~*pq}SXn zW*%RA0j{kcub`^Ri!}Lu?q6g!fV`GUP~OzwarVj<{Qr3oFJFjfo3Q!n*VP=0`0jBD zE=T`+bBfT|g%Z!Q8I8@Tr)=DvCG7dp6|0$o_(?;2sOiqFyS&@zuDVs+@^x)^sNw(T zkT-U+HOZ-@FEwj{+I4Ob5~$^9Y&3uybED?fnRSOpbE<{(zhJ|!?pPl&wVw=^Z`$Uq zEi$1Dc|@cJDzTNwB3Ri9m)ChqsJCDcCG4Hx?B(-fozz zn-ZF@A4}p5UR6F{!1-mD-+q6X=hD-T!$`iHsrXY`KMypuxiRUOz5+F7l1Aqt$rcu@ z>a545L0x#R#YAFw1QMysD)G?OkBeZ)AKnNHow#j*kgid1CA4x!Vl$D*Crul0rn5=T z4M{RzX4%b@4R)Jdz?+ot)lGD7sXc+9@rdiiU17!N&cPyJ|IU?6W&Aa@it}M+AIP$CW6GzUwQ3Xtg?%m6;f7U=dQ0 zJ2A1K!n6TYRf{?@bO0Hd2q7~f6%kn|fU0YH*w$v}b>D60scp;b7|$`gKfry>j-DES zqAxjXaQATc@E9_IqDYC+Y8Env<Q$?Gb&o1=#4(S2|wSek*sSv_}=ln%6S0M?;*p zxn~^o$QUI|AiA3O`$B2r4+ywBiV7lI=UiXVa6BVPkX5d{~GJJecK6ZWl1i~8p zo6vWTectiY92j>jpwl|xJ}FA`mL5mS;@Upa3COM%{6KaiU_zC}cY60N(Ck2qEI5|T z6shpELx9&W4|2*j3nazRNOp`KwawEsx1$S(5T(c!0_jAYvga6<5u&#`p1garVaA`` zUX#{WH$-Y-6g}^R&ALP<$zPU^j|jV^S@$`-Qpza03k>r#S8+59N3%qn@G_#+i;?E; z1eb6;YfdVLR8?-oRIlj=UQR~i1R31{;#JyeyJQoA?YfVA+j2SVW&TyLI}~1=Qmpkp z;E`i11nuC9$JN0X18K_5ogt#G@ObNPlNhQo+j>BTt$*)lSrVQTL(#%u4c=HC)@Jw= zq0z>>z&=TUrX0&7L!RH5db-{7zEY7Hi0)~s>_BL|qYlVkTY6QFhky+6?cH}H#WdljjneagJ+K4WAGF0FJGZsb zMgK%#2@58TobzmpEv}3^m;iu<{Cw|`i9&c*YfK{=3Z#!wDvcq^;;e)zh4Ly2B=-&S zV4mhMzAI21O2W2y$wL^3z4Y^M5)2vnBmT<>!+#qZ7!fjp7pmS(2vHmb`SYcp%ZC4$ zj$i!z8wZAc_~R6x6mjgs9~1Rp&uUu>S4jkAkHgLEeOXYdu?N}1pbu2BdnBDRZ((-h zbAPNMyZ6`s{r`epjih3lqLLbeZGjFxA_hLz@SSf1c_eOqAJ%*_o5)Z�|}{NvFlg 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�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 Kqb;C8(EkC%c;AKq literal 0 HcmV?d00001