# GPS2Audio v2.5.7 — Home/Menü/Cover/Playlist-Fixes — Handoff ## Überblick Diese Version baut direkt auf der lokalen Quelle `GPS2Audio_v2_5_6_explorer_about_license_source.zip` auf und entschlackt die Start- und Touransicht, bündelt die Datensicherung, ergänzt frei wählbare Cover-Bilder, behebt die manuelle Wiedergabe als echte Playlist und entfernt einen unnötig prominenten Track-Editor-Schnellzugriff. Sämtliche bestehenden Funktionen (Explorer/MapLibre, manuelles Routenzeichnen, Routingprofile, POI, GPS-Nachführung, Drag-and-drop, PTT, Atmo/Stream-Playlist, Recorder, Backup/Import, About/Lizenz, TourRoute-Persistenz, Ansicht anpassen) bleiben unverändert erreichbar. * `versionName` 2.5.7, `versionCode` 61 (`app/build.gradle.kts`). * Signiert mit dem bestehenden Release-Keystore `/home/user/workspace/GPS2Audio_release_keystore.jks` (Alias `gps2audio_release`) — updatefähig gegenüber jeder vorherigen 2.x-Release. ## Geänderte Verhalten ### A) Manuelle Wiedergabe als echte Playlist `viewmodel/WaypointViewModel.kt` führt einen zentralen Helfer `startManualPlaylistAt(index)` ein, den Play/Skip-zurück/Skip-vor gemeinsam benutzen. Auf der aktuell ausgewählten Tour wird die Reihenfolge von `manualPlaylist()` (= alle aktiven Wegpunkte mit gesetztem `soundUri`, in Tour-/Listenreihenfolge) genutzt; deaktivierte Wegpunkte und Wegpunkte ohne Audio erscheinen gar nicht in der Liste und werden daher übersprungen. Neu: nach natürlichem Ende eines Tracks ruft der Completion-Callback `advanceManualPlaylistAfterCompletion()` auf, das den nächsten Track der Playlist startet, sofern noch einer existiert. Ist die Playlist zu Ende, wird sauber gestoppt (kein Auto-Loop). Single-Mode (`manualPlaySingle`) ist davon ausgenommen und beendet sich wie bisher nach genau einem Clip; die per-Wegpunkt-Play-Buttons rufen weiterhin diesen Pfad auf. Pause/Stop/Skip arbeiten wie bisher, sind aber jetzt auf den neuen Helfer aufgesetzt. PTT-Sperre und Atmo `beforeWaypointAudio` / `afterWaypointAudio` werden auch beim Auto-Advance respektiert. ### B) Tour-Cover-Bild („Bild auswählen") * `data/TourCover.kt`: neue, optionale Property `imageUri: String?`. Backward-kompatibel — alte JSON-/Backup-Stände ohne dieses Feld lesen sich weiterhin sauber (Gson liefert null). * `util/TourCoverImageStore.kt` (neu): kopiert ein vom Nutzer per Android Photo Picker gewähltes Bild nach `filesDir/tour_covers/`, schneidet es mittig quadratisch zu und skaliert es auf max. 1024 px Kantenlänge (JPEG 88). Damit fällt es nicht der SAF-URI-Lebensdauer zum Opfer und kann verlustfrei ins Backup wandern. Keine zusätzlichen Berechtigungen — Photo Picker arbeitet ohne `READ_MEDIA_IMAGES`. * `ui/WaypointListScreen.kt`: `TourCoverDialog` zeigt jetzt einen Abschnitt „Eigenes Bild" mit Button „Bild auswählen" sowie „Bild entfernen" (wenn eines gesetzt ist). Vorschau verwendet das Bild, wenn vorhanden; sonst weiter Icon + Farbverlauf. ActivityResult-Launcher: `ActivityResultContracts.PickVisualMedia` (Bilder-only), kein Aufruf der gefährlichen Lese-Berechtigungen. * `ui/WaypointListScreen.kt`: `TourHeroSection` rendert das Bild zentral zugeschnitten in der Hero-Kachel, sonst weiter Icon + Verlauf. Hilfsfunktion `rememberTourCoverBitmap(path)` cached pro Pfad. * `ui/HomeScreen.kt`: `TourCoverCard` übernimmt sowohl die Palette/Icon-Auswahl aus v2.5.5 als auch das Bild-Cover. Ist ein Bild gesetzt, füllt es die Cover-Kachel (`ContentScale.Crop`); ist nur Icon+Palette gesetzt, wird der entsprechende Verlauf gezeichnet; ohne Cover greift weiter die deterministische Heuristik aus dem Tour-Namen. Damit ist Anforderung F (Cover im Home sichtbar) und der Wunsch nach freiem Bild-Cover gemeinsam erfüllt. `WaypointViewModel.setTourCoverImageFromUri(uri)` schreibt die Persistenz-Operation auf `Dispatchers.IO` und löscht ein vorher gespeichertes Bild der gleichen Tour automatisch. `clearTourCoverForCurrent` und `setTourCoverForCurrent` räumen ein altes Bild ebenfalls auf. ### C) Menü „Datensicherung" `ui/WaypointListScreen.kt` ersetzt die sechs Einzeleinträge „Als JSON exportieren", „JSON importieren", „Als GPX exportieren", „GPX importieren", „Backup erstellen", „Backup importieren" durch einen einzigen Menüpunkt „Datensicherung". Klick öffnet ein `ModalBottomSheet` mit drei klar betitelten Sektionen: * **Komplett-Backup (empfohlen)** — Backup erstellen / importieren * **JSON (nur Wegpunkte / Daten)** — Export / Import * **GPX (Geräte-/Tool-Austausch)** — Export / Import Die bestehenden `rememberLauncherForActivityResult`-Launcher ( `exportJsonLauncher`, `importJsonLauncher`, `exportGpxLauncher`, `importGpxLauncher`, `createBackupZipLauncher`, `importBackupZipLauncher`) werden 1:1 wiederverwendet — keine Verhaltens-Regression bei SAF/ContentResolver, keine neue Berechtigungs-Logik. ### D) Track-Editor-Schnellzugriff entfernt * Der zweite IconButton (Timeline-Icon) aus der Touransicht-TopAppBar ist entfernt. Track-/Routenbearbeitung läuft weiterhin über den Explorer: dort kann jeder Draft im Vollbild-Editor geöffnet werden (`ExplorerScreen.kt` → `onOpenDraft` → `composable("draft/{draftId}")`). * Der Overflow-Menüpunkt „Track-Editor" ist ebenfalls entfernt. ### E) Tour-TabRow entschärft Die `ScrollableTabRow` mit den Tour-Reitern auf der Touransicht ist entfernt — sie hat die primäre Tour-Ansicht dominiert und doppelt mit der Audio-Bibliothek (Home) kollidiert. Tourwechsel bleibt vollständig erreichbar: * Home-Startseite (`HomeScreen`) → Tour-Cards setzen die Tour aktiv und öffnen direkt die Touransicht. * Overflow-Menü → „Touren ordnen…", „Neue Tour", „Tour umbenennen", „Tour löschen" sind weiterhin verfügbar. * „Klassische Ansicht" aus dem Home-Menü öffnet wie bisher dieselbe Touransicht. ### F) Backup/Import inkl. Cover-Bild * `io/BackupExportManager.kt`: pro Tour mit `imageUri` wird die Bilddatei nach `media/covers/.jpg` ins ZIP gepackt; im exportierten JSON ersetzt der relative ZIP-Pfad den absoluten Device-Pfad, damit Importe gerätübergreifend funktionieren. Schlägt die Bild-Kopie fehl, wird das Cover ohne Bild exportiert (Icon+Palette bleiben erhalten — keine Datenverluste). * `io/BackupImportManager.kt`: Cover-Bilder unter `media/covers/` werden auch dann extrahiert, wenn nur die Sektion „Touren und Wegpunkte" gewählt wurde (gehören logisch dazu). Beim Lesen der `tourCovers`-Map wird das ZIP-relative `imageUri` über `TourCoverImageStore.saveFromFile(...)` in die app-interne Ablage übernommen; gelingt das nicht, fällt die Tour automatisch auf ihr Icon+Palette-Cover zurück. Bestehende Backups (v2.5.5/2.5.6) ohne Bild-Cover bleiben vollständig kompatibel. ## Datei-Inventar Neu: * `app/src/main/kotlin/de/waypointaudio/util/TourCoverImageStore.kt` Geändert: * `app/build.gradle.kts` — versionCode/versionName * `app/src/main/kotlin/de/waypointaudio/data/TourCover.kt` — `imageUri` * `app/src/main/kotlin/de/waypointaudio/ui/HomeScreen.kt` — TourCoverCard mit Cover-Übernahme (Icon/Palette/Bild) * `app/src/main/kotlin/de/waypointaudio/ui/WaypointListScreen.kt` — TabRow entfernt, Track-Editor-Aktionen entfernt, Datensicherung-Sheet, Bild-Auswahl-Pfad, Hero mit Bild * `app/src/main/kotlin/de/waypointaudio/viewmodel/WaypointViewModel.kt` — Playlist-Auto-Advance, Cover-Bild-Persistenz * `app/src/main/kotlin/de/waypointaudio/io/BackupExportManager.kt` — Cover-Bilder in ZIP * `app/src/main/kotlin/de/waypointaudio/io/BackupImportManager.kt` — Cover-Bilder aus ZIP, gerätübergreifender Restore Nicht angefasst (No-Regression-Grenzen): `ExplorerScreen*.kt`, `MapScreen.kt`, `RoutePlanner*.kt`, `ManualAudioPlayer.kt`, `LivePtt*`, `Atmo*`, `WaypointStore.kt` (Schema unverändert — neue Property landet via Gson-Default in der bestehenden Map), `MainActivity.kt`, AndroidManifest und alle Foreground-Services. ## Manifest / Berechtigungen Unverändert. Photo Picker arbeitet ohne `READ_MEDIA_IMAGES`. ## Build- und Signaturstatus * Build erfolgreich mit Gradle 8.9 + AGP 8.5.2, JDK 17 (Temurin), compileSdk 35 / buildTools 35.0.0. * APK Signature Scheme v2 verifiziert (apksigner v35.0.0): `Verifies`, ein Signer, Schlüssel-Alias `gps2audio_release` aus `GPS2Audio_release_keystore.jks`. * Paket: `de.waypointaudio` · versionCode `61` · versionName `2.5.7` · minSdk 26 · targetSdk 35. ## Artefakte * `/home/user/workspace/GPS2Audio_v2_5_7_home_menu_cover_playlist_signed.apk` * `/home/user/workspace/GPS2Audio_v2_5_7_home_menu_cover_playlist_source.zip` * `/home/user/workspace/GPS2Audio_v2_5_7_home_menu_cover_playlist_handoff.md` Keystore und Credentials sind **nicht** im Source-ZIP enthalten — nur die bereits existierende `keystore.properties.example` als Vorlage. ## Smoke-Check * `aapt2 dump badging` zeigt `versionName='2.5.7'` und `versionCode='61'`. * `apksigner verify --verbose` meldet `Verifies` (v2 scheme, 1 signer). * Compose-Kompilation aller geänderten Bildschirme ist fehlerfrei durchgelaufen (sonst hätte Gradle abgebrochen). ## Empfohlene manuelle Tests vor Rollout 1. Bestehendes Backup eines v2.5.5/v2.5.6-Stands importieren → Touren, Cover (Icon+Palette), Wegpunkte und Tracks erscheinen wie gewohnt; kein Bild-Cover (es war noch keins). 2. Pro Tour ein Cover-Bild auswählen → Hero und Home-Card zeigen das zugeschnittene Bild; Auswahl überlebt App-Neustart. 3. Backup erstellen, App-Daten löschen, Backup importieren → Cover-Bilder erscheinen wieder. 4. Manuelle Wiedergabe in einer Tour mit ≥3 aktiven Audio-Wegpunkten starten → spielt der Reihe nach durch, stoppt am Ende; Skip-vor/ zurück springt innerhalb der Playlist; einzelner Play-Button auf einer Karte spielt weiterhin nur diesen Clip. 5. Touransicht öffnen → keine Tour-TabRow mehr, kein Track-Editor- Schnellzugriff; Datensicherung-Sheet bündelt JSON/GPX/Backup.