PlaylistDetailScreen zeigt die Songs einer Playlist (watchPlaylistSongs),
erlaubt Entfernen einzelner Songs und Umsortieren per Drag & Drop
(ReorderableListView.builder). Tippen auf einen Song spielt die Playlist
ab dieser Stelle. Leer-Zustand mit Hinweistext.
Da bestehende position-Werte nach Einfügereihenfolge lückenhaft sein
können, schreibt das Umsortieren nicht nur den verschobenen Song um,
sondern vergibt für die gesamte Playlist neue lückenlose Positionen
(0..N-1): MeloDb.reorderAllPlaylistSongs (in einer Transaktion) +
PlaylistService.reorderAll als dünner Wrapper.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Ohne Eintrittspunkt wären Playlisten unbenutzbar, da sie sonst nie Songs
erhalten könnten. SongList bekommt einen zusätzlichen Trailing-Button
(Icons.playlist_add) neben dem Favoriten-Herz, der ein Bottom-Sheet mit
allen Playlisten öffnet ("Neue Playlist" oben, dann bestehende). Antippen
hängt den Song ans Ende der gewählten Playlist an und zeigt eine SnackBar.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
- "Zuletzt hinzugefügt" aus dem alten HomeScreen in die Bibliothek verschoben:
horizontal scrollende Leiste über der vollen Songliste, nur sichtbar wenn
nicht leer und nicht gerade gescannt wird
- home_screen.dart entfernt (Funktionalität jetzt Teil von LibraryScreen)
- HomeShell-Tabs auf die finale Struktur umgestellt: NowPlayingScreen an
Position 0, Playlisten- und Settings-Platzhalter an ihren finalen
Positionen (werden in späteren Tasks durch echte Screens ersetzt)
- BottomNavigationBar-Icons/Labels an die neue Reihenfolge angepasst
- MiniPlayer wird ausgeblendet, solange der Now-Playing-Tab aktiv ist
(redundant, da der Tab selbst schon die volle Wiedergabe-Ansicht zeigt)
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
- songToMediaItem trägt jetzt die Song-UUID in extras['songId'], damit
Downstream-Code (Favoriten-Button, später Playback-History) den echten
Song wiederfinden kann statt nur die file-URI zu haben
- NowPlayingScreen: Schließen-Button entfernt (AppBar-leading), da der
Screen jetzt als eigener Tab läuft statt gepusht zu werden
- FavoriteButton für den aktuellen Song in die AppBar-Actions eingebaut,
reaktiv über einen verschachtelten StreamBuilder<MediaItem?>; ohne
gültige songId (z.B. nichts spielt) wird kein Button gerendert
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
- Filled heart when favorited, outline when not (reactive via watchIsFavorite)
- Wired into every song list tile (library, search, playlists)
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
## Critical Blockers Fixed
- Remove playbackState.addError() which broke audio_service permanently
- Move error handling from audio_handler to song_list where UI context exists
- Display error in SnackBar instead of destroying playback stream
- Add escapeChar parameter to LIKE queries for correct wildcard handling
- Fixes broken search for titles with _ or % characters
- Add dismissScanError() method to allow closing error banner
- Previously banner couldn't be dismissed (missing notifyListeners())
## Improvements
- Remove dead livePaths list, use companions.isNotEmpty instead
- Add initial progress update to show total files when scan starts
- Add tooltip to now_playing_screen Zurück button
- Add proper error handling in song_list with async/await
## Testing
- Add regression test for CRITICAL-1: empty scan doesn't delete songs
- Add regression test for CRITICAL-2: tombstoned files restore on re-scan
- All 11 tests pass
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
## Critical Fixes
- Fix CRITICAL-1: Empty scans no longer delete entire library
- Use timestamp-based tombstone logic instead of path-based
- Only mark missing if livePaths is not empty
- Fix CRITICAL-2: Re-scanned files now return from deleted state
- Add deleted=false to SongsCompanion.insert in both scanners
## High Priority Fixes
- HIGH-1: Fix SQLite variable limit crash on large libraries
- Replace isNotIn() with timestamp comparison (O(1) not O(n))
- HIGH-2: Fix UI freezing during scan
- Throttle progress updates (every 50 files or end of scan)
- HIGH-3: Add error handling for scan failures
- Wrap scanFolders/scanAndroidMediaStore in try/catch
- Display scanError banner in LibraryScreen
- HIGH-4: Add error handling for playback failures
- Wrap loadPlaylist in try/catch
## Medium Priority Fixes
- MEDIUM-1: Replace ! with ?? to handle unknown ProcessingState
- MEDIUM-2: Escape LIKE wildcards in search queries
- MEDIUM-4: Display StreamBuilder errors instead of treating as empty
- MEDIUM-8: Add tooltips to all IconButtons for accessibility
- Add doc comments to public database APIs
## Testing
- Add regression tests for CRITICAL-1 and CRITICAL-2
- All 9 existing tests pass
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>