## Fix 1 (MED): Glow-Pulsation rebuildet jetzt wirklich
- now_playing_screen.dart: Cover-Container mit AnimatedBuilder(animation: _glowController) gewrappt — BoxShadow (blur 50–70 / spread 6–12) wird jetzt pro Animations-Tick neu gebaut statt nur bei fremden setStates (Pulsation war vorher nur zufällig über positionStream sichtbar und fror bei Pause/Pufferung ein)
## Fix 2 (MED): Echter Crossfade beim Songwechsel
- _songSub-Listener setzt _hatCover/_coverPfad jetzt SYNCHRON auf false/null (im selben setState) — Hintergrund und Front-Cover zeigen beim Songwechsel kein altes Cover mehr, bis die async Existenz-Prüfung durch ist
- _hintergrundBlur-Key auf den tatsächlichen Cover-Pfad gelegt ('cover-$pfad' statt song.id) — Switcher wechselt erst bei geladenem neuem Cover (Crossfade Gradient→Cover), kein Fade alt→alt + harter Cut mehr
flutter analyze: 0 Issues, Tests 98/98 grün, keine neuen Packages
## Fullscreen-Player (now_playing_screen.dart)
- Glow-Farbe folgt MeloTheme.akzentNotifier (Per-User-Akzent) statt fixem Rot; Listener rebuildet bei Akzentwechsel
- Dynamische Glow-Pulsation: AnimationController (Bordmittel) pulsiert blurRadius 50–70 / spreadRadius 6–12 nur bei Wiedergabe, stillstehend bei Pause
- Blur-Hintergrund crossfaded beim Songwechsel (AnimatedSwitcher 600ms, layoutBuilder mit StackFit.expand, ValueKey je Song)
- existsSync aus dem Build-Pfad entfernt: async _ladeCoverStatus mit try/catch, Guard gegen stale Song-Wechsel
## Fix (Code-Review Finding 3, MED)
- spieleAlsNaechstes: Song bereits in der Queue wird an Position nach dem
aktuellen VERSCHOBEN (inkl. _aktuellerIndex-Anpassung), keine Kopie mehr
- Shuffle: keine Neu-Mischung nach Play-Next — Song wird via
_pinneInShuffleReihenfolge an die nächste Position gepinnt (Index-
Korrektur für Verschiebungen, _shufflePos-Nachführung am Reihenende)
- 3 Tests ergänzt: Verschieben statt Duplizieren, Song von vor dem
aktuellen, Shuffle-Pin (kein Duplikat + naechsterIndex == gepinnter Song)
## Fix (Code-Review Finding 2, HIGH)
- DbHelper.songZurPlaylist: INSERT OR IGNORE (ConflictAlgorithm.ignore) —
Doppel-Tap-Race verletzt PRIMARY KEY (playlist_id, song_id) nicht mehr
- FavoritenService.umschalten: gibt neuen Status zurück, try/catch mit
MeloLogger, Zustand nach Fehler aus DB neu geladen statt blind geflippt
- NowPlayingScreen._toggleFavorit: In-Flight-Guard _toggleLaeuft gegen
parallele Toggles + Statusübernahme aus DB (Quelle der Wahrheit)
## Fix (Code-Review Finding 1, HIGH)
- _baueShuffleReihenfolge: Index 0 nur noch bei Repeat-playlist in die
Shuffle-Reihenfolge aufnehmen (Einzel-Song-Queue)
- naechsterIndex: Sicherheitsnetz gegen stale Reihenfolge — Kandidat ==
aktueller Song bei Repeat-aus liefert null (Queue-Ende) statt denselben
Song erneut
- Test ergänzt: shuffle + repeat aus + 1-Song-Queue → null
## PlayerService
- warteschlange Getter (unveränderliche Kopie) + aktuellerIndex
- spieleAlsNaechstes(Song): fügt nach aktuellem Song ein
- amEndeHinzufuegen(Song): hängt ans Ende an
- verschiebeInWarteschlange(von, nach): Drag-and-Drop mit korrekter Anpassung des aktuellen Index
## WarteschlangeSheet (neu: lib/widgets/warteschlange_sheet.dart)
- Bottom-Sheet: aktuelle Warteschlange, aktueller Song rot markiert (▶)
- Tipp auf Song → sofort abspielen
- ReorderableListView (Bordmittel) zum Umsortieren per Drag
- Leer-Zustand + Titel-Zähler
## MiniPlayer
- Tipp auf den Miniplayer öffnet die Warteschlange (Bottom-Sheet)
Keine neuen Packages, flutter analyze 0 Issues, Tests 4/4
## PlayerService
- Enum Wiederholmodus { aus, titel, playlist } + Getter/Setter
- naechstes(): titel → gleicher Song von vorn (seek 0 + play)
- naechsterIndex(): zentrale Berechnung des nächsten Index
- playlist: nach letztem Song wieder von vorne (auch bei Shuffle: neu mischen)
- aus: Ende der Warteschlange stoppt
- Auto-Next (ProcessingState.completed) läuft über naechstes() → Repeat wirkt auch automatisch
## MiniPlayer
- Repeat-Icon mit 3 Zuständen (repeat / repeat_one), rot wenn aktiv, Wechsel bei Tipp
Keine neuen Packages, flutter analyze 0 Issues, Tests 4/4
## PlayerService
- PlayerService ist jetzt ChangeNotifier (UI hängt per addListener/ListenableBuilder an)
- zufallsmodus Getter + setZufallsmodus(bool)
- Zufallsreihenfolge: alle Queue-Indizes außer dem aktuellen Song, gemischt
- naechstes(): bei Shuffle nächster Song aus Zufallsreihenfolge, ohne Wiederholung bis alle durch
- vorheriges(): geht in der Zufallsreihenfolge zurück
- spiele(): synchronisiert Shuffle-Position (auch bei manueller Auswahl)
## MiniPlayer
- Shuffle-Icon (rot wenn aktiv, Tipp schaltet um)
Keine neuen Packages, flutter analyze 0 Issues, Tests 4/4
## CloudService
- CloudStatus-Enum (verbinde/verbunden/fehler), CloudService extends ChangeNotifier
- verbinde(): Login+Status beim App-Start, setzt Status, notifyListeners
- Getter status/statusText/istVerbunden/verbindungGestartet
- Bestehende Methoden behalten — nur status() → statusDaten() umbenannt (Namenskonflikt mit neuem status-Getter)
## Home-Screen
- _cloud.verbinde() in initState (feuern-und-vergessen) — Verbindung steht beim App-Start, nicht erst beim Tab-Öffnen
## Cloud-Screen
- initState verbindet nicht mehr selbst — zeigt Service-Status via ListenableBuilder
- Status wechselt live: 'Verbinde...' (gelb) → 'Verbunden' (grün) / 'Keine Verbindung' (rot)
- Serverdaten (Playlists/Favoriten/Zähler) laden automatisch, sobald Service verbunden
- Refresh-Button re-verbindet + lädt Zähler neu
- Fallback: ungestarteter Service (Einstellungen-Screen) wird beim Öffnen gestartet
## Neuer Recap-Screen
- lib/screens/recap_screen.dart: Full-Screen mit 7 animierten Seiten (Intro, Top 5 Songs, Top 3 Künstler, Hörzeit, häufigster Tag, Nachtaktive %, Gesamtzahl + Teilen)
- Wrapped-Stil: Verlaufs-Gradienten, große Zahlen mit Count-up-Animation, Fade+Scale-Seitenwechsel, Fortschritts-Punkte, Weiter-Button
- Teilen-Button kopiert Recap-Text in die Zwischenablage (kein neues Package)
## Datenbasis
- lib/services/recap_service.dart: aggregiert lokale Abspiel-Historie zu Top-5-Songs, Top-3-Künstler, Hörzeit, Wochentag, Nacht-%, Gesamtzahl
- Fallback auf Gesamt-Historie wenn im Zieljahr keine Daten; freundlicher Leer-Zustand ohne History
## DB + Tracking
- db_helper.dart: Migration v6→v7 mit neuer Tabelle abspiel_historie (song_id, played_at) + Backfill aus wiedergabe_verlauf
- player_service.dart: registriert jeden Abspielvorgang in der Historie
## Einstieg
- Home-Screen: Karte 'Jahres-Recap 2026' unter der Statistik-Card
- Einstellungen: Kachel 'Jahres-Recap' in Sektion Daten & Privatsphäre
flutter analyze: 0 Issues, Tests 4/4
## HIGH: Background-Service bleibt hängen
- downloadVonUrl: try/finally stellt sicher dass _stopBackgroundService() immer aufgerufen wird
- downloadBatch: try/finally stellt sicher dass _stopBackgroundService() immer aufgerufen wird
- reDownload: try/finally stellt sicher dass _stopBackgroundService() immer aufgerufen wird
## MEDIUM: debugPrint Leak
- HTTP-Response-Body in debugPrint auf max 200 Zeichen gekürzt
- MeloApp von StatelessWidget zu StatefulWidget konvertiert
- _autoScanTimer als globale Variable gespeichert
- Timer wird in _MeloAppState.dispose() gecancelt
- CloudService: static final http.Client _client als Instanzvariable
- Alle http.get/post/put/delete/upload nutzen nun _client statt neuem Client
- DownloadService: gleicher Fix für _retryHttpPost und _retryHttpGet
Build: ✓ flutter analyze
- MusikScanner().scanneMusikOrdner() wird direkt nach Auth-Init aufgerufen
- Timer.periodic alle 3 Stunden für periodischen Scan
- androidStopForegroundOnPause=false für persistente Notification (Issue #8)
Build: ✓ flutter analyze
- Einstellungen > Cloud-Daten loeschen: 'Nur Musik' oder 'Komplett vom Server'
- 3-Sekunden-Gedrueckthalten-Button zur Bestaetigung (Fortschrittsbalken)
- Warnhinweis: Wird SOFORT geloescht, nicht rueckgaengig machbar
- Server: delete-music/delete-all Endpunkte mit Dedup-sicherem Registry-Cleanup
- Loeschen nur des eigenen Kontos (User aus Token, kein IDOR)