Bug (Code-Review, P0-nah): dragEnd() wählte die Entscheidungslogik allein
über das Vorzeichen von strecke. Bei bereits vollständig offenem Player
klappte ein schwaches, versehentliches Fingerzittern nach oben (kleine
negative Strecke, weit unter der Wisch-Schwelle) den Player ungewollt zu,
weil das Vorzeichen in den ÖFFNEN-Zweig führte statt in den (korrekten)
Schließen-Zweig, der bei so einer schwachen Geste keine Wirkung hätte.
dragEnd() bekommt jetzt den Pflichtparameter `ausVollbild`, der den
Aufrufer-Kontext explizit benennt statt ihn zu erraten. mini_player.dart
(Öffnen-Geste) ruft mit ausVollbild: false, now_playing_screen.dart
(Schließen-Geste) mit ausVollbild: true.
Test zuerst (RED mit der alten 3-Parameter-Signatur reproduziert, dann
GREEN nach dem Fix): test/player/player_expansion_controller_test.dart.
Bestehende Tests (player_expansion_controller_test.dart,
home_shell_expansion_test.dart) an die neue Signatur angepasst.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SM6e73V9ZethPiqHSocxUA
Zusätzlich test/player/now_playing_heart_test.dart angepasst (Plan-Lücke:
nutzt denselben SongZeile-Tap-Pfad, war nicht in Task 3s Datei-Liste
erwähnt) — Provider ergänzt, Route für die Layout-Prüfung selbst separat
geöffnet, bis Task 5 NowPlayingScreen zu Overlay-Inhalt umbaut.
Budget-Adversarial-Panel (3 Reviewer, unabhängig konvergent) fand einen P0
(AnimatedBuilder.child-Fehlgebrauch macht Blur-Layer nicht live) und mehrere
P1s (State-Persistenz-Widerspruch zur Spec, fehlende Hit-Test-/Accessibility-
Isolation, verworfene Loslass-Geschwindigkeit, fehlendes extendBody, Tests
nur gegen Test-Doppelgänger). Alle behoben: eigene AnimatedBuilder pro
reaktiver Ebene (Reaktivitäts-Regel in Global Constraints), Visibility statt
Conditional-Unmount, IgnorePointer/ExcludeSemantics für Hintergrund-Layer,
echte Fling-Geschwindigkeit, extendBody + BottomNavigationBar-Fade, neuer
Integrationstest gegen das echte HomeShell, State-Persistenz-Test.
Items in song_list.dart und artist_list.dart faden/rutschen beim ersten
Erscheinen gestaffelt statt abrupt ein — angelehnt an HyperOS' fließende
Motion-Sprache. Läuft einmal pro Element, respektiert Reduce-Motion und
deckelt die Verzögerung ab Index 12.
Nach erfolgreichem manuellem Login im "Baka-Konto"-Dialog wird das neue
Passwort jetzt zusätzlich in NavidromeService persistiert (dafür ergänzt:
öffentlicher serverUrl-Getter) — vorher schrieb der Dialog es nur ins
BakaAuth-Token, nie zurück in die lokale Navidrome-Ablage, aus der
autoAnmelden() sich beim nächsten App-Start bedient. Ohne diesen Fix kam
der Auto-Login-Fehler nach Ablauf des 7-Tage-Tokens garantiert wieder.
Zusätzlich hält BakaAuth.letzterAutoLoginFehler jetzt den Fehlertext des
letzten Auto-Login-Versuchs fest, statt ihn zu verwerfen — bisher war aus
der App nicht diagnostizierbar, woran ein Auto-Login scheiterte.
Betraf alle drei Nutzer (Dustin, Baka, Tinker), nicht nur einen: IndexedStack
baut Download-Tab und YT-Suche beim App-Start gleichzeitig, beide loesen
unabhaengig voneinander autoAnmelden() aus. Ohne In-Flight-Absicherung gingen
zwei fast-gleichzeitige Login-Requests an denselben Server, von denen einer
abgelehnt wurde - obwohl die Zugangsdaten korrekt waren.
- BakaAuth.autoAnmelden() haengt einen ueberlappenden Aufruf jetzt an den
bereits laufenden Login-Versuch an, statt einen zweiten Request zu senden.
- Anmelde-Dialog im Download-Tab zeigt den tatsaechlich bekannten
Navidrome-Benutzernamen statt immer "Baka" vorauszufuellen.
- Navidrome-Dialog in den Einstellungen waehlt den zuletzt bekannten
Benutzer vor statt immer "Baka".
- MeloDb.watchRecentlyPlayed(): wertet PlaybackHistory statt dateAddedMs aus,
ein mehrfach gehörter Song erscheint nur einmal, an der Position seines
jüngsten Abspielens (Subquery mit GROUP BY songId / MAX(playedAtMs)).
- "Zuletzt" (Karte + RecentlyPlayedScreen, vormals RecentlyAddedScreen) in
my_music_screen.dart nutzt jetzt watchRecentlyPlayed() statt watchRecent().
- Herz im Vollbild-Player: aus der AppBar-actions-Row entfernt, sitzt jetzt
direkt neben dem Songtitel in _Angaben (now_playing_screen.dart).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012A2pmbnVNPiHdyf2GW8eLP
Tab-Wechsel in HomeShell laufen nur über setState (IndexedStack +
BottomNavigationBar), nie über Navigator.push — eine System-Zurück-Geste
hatte auf Nicht-Start-Tabs also nie eine Route zum Poppen und minimierte
stattdessen die App. build() jetzt in ein PopScope gewickelt, das bei
_index != 0 zuerst zu Tab 0 zurückspringt.
Hermes hat den irreversiblen Löschpfad in melo_cloud.py behoben: Der
Dedup-Zweig von upload() stellt die Datei jetzt aus den hochgeladenen
Bytes wieder her, wenn registry_pfad(sid) leer ist, statt sie zu
verwerfen.
End-to-end verifiziert (eigene Testdatei, Fake-Nutzer, Testdaten danach
restlos entfernt — Registry vor und nach dem Test bei 325 Titeln):
Upload → beide Kopien da · Löschung → beide weg, Download 404 (Bug
reproduziert) · erneuter Upload → beide Kopien zurück, Download
bitgenau identisch mit dem Original.
Damit ist die letzte offene Frage der Spec (A6) beantwortet und keine
Stufe mehr blockiert. Tasks 5-7 des Plans sind entblockt; Tasks 10-12
hängen nur noch an der Produktfrage "wird Feature 2 überhaupt gebaut?"
(0 Playlisten am Server).
Nebenbefund aus dem Test, als Backlog-Notiz festgehalten: _link_user()
legt im Dedup-Zweig einen dritten Hardlink unter users/<user>/ an, den
_entferne_datei_wenn_verwaist() nicht abräumt. Server-Hygiene für
Hermes, kein Datenverlust.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CcDiyJdVRqh1TtJk5JiabX
Spec nach dem Review-Panel-Urteil überarbeitet (alle 17 Aktionspunkte).
Der Umfang schrumpft deutlich: 6→5 Ziele, 4→2 neue Dateien, neue
Dependencies 1→0. SSE, persistente Notification und der beidseitige
Playlist-Merge werden spätere Stufen; der Favoriten-Fix schreibt jetzt
additiv (POST /favorites gestrichen), womit der Datenverlust-Bug
strukturell unmöglich wird statt nur per Regel verhindert.
Implementierungsplan: 13 Tasks nach TDD, Favoriten-Fix zuerst (hängt an
keiner offenen Frage). Gegengelesen und geprüft; die Prüfung fand drei
echte Server-Vertragsfehler, die in den eigenen Tests grün geworden
wären (playlist.id statt id, positions statt song_ids, not_found ohne
error-Feld) — alle korrigiert und am Servercode belegt.
OFFEN: Rückfrage an Dustin zum irreversiblen Löschpfad (siehe Spec,
Abschnitt "OFFENE ENTSCHEIDUNG"). Tasks 5-7 und 10-12 sind bis dahin
als blockiert markiert; Tasks 1-4 können sofort starten.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CcDiyJdVRqh1TtJk5JiabX
Adversariales 5-Reviewer-Panel (Opus) mit 2 Debattenrunden,
Vollständigkeits-Audit, konsolidierter Faktenprüfung (~70 Belege,
keine Halluzination) und Richterurteil.
Ergebnis: SPEC NACHSCHÄRFEN DANN FREIGEBEN. Kein P0 im Geltungsbereich.
17 Aktionspunkte, wichtigste: POST /favorites (Voll-Ersatz) streichen
statt Regel, SSE und beidseitigen Playlist-Merge herausnehmen,
irreversiblen Bestands-Löschpfad benennen (Backlog-P0, Rückfrage an
Dustin offen).
Bemerkenswert: Der vom Panel selbst empfohlene Basis-Snapshot wurde
von der Verifikation als gefährlicher entlarvt als das Problem, das
er lösen sollte — abgelehnt.
Reviewer-Rohtexte bleiben lokal (.gitignore), nur Bericht + Urteil
im Repo.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CcDiyJdVRqh1TtJk5JiabX
Design-Dokument für den neuen anonymen Gast-Zugang zum YouTube-Proxy
(5 Downloads/Tag, keine Cookies) neben dem bestehenden
Baka-Auth-Cloud-Zugang. Mit Dustin im Brainstorming abgestimmt:
geräte-gebundener Gast-Token, bewusste Wahl in der UI, Reset nach
Server-Kalendertag, Suche bleibt unbegrenzt. Server-seitiger Teil
(yt_proxy.py) liegt außerhalb dieses Worktrees — die Spec beschreibt
den Vertrag dafür.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CcDiyJdVRqh1TtJk5JiabX
Root-Cause-Analyse zu Bakas Login-Problem (mit Hermes): Ihr Baka-Auth-
Account existiert, aber Navidrome- und Baka-Auth-Passwort sind
auseinandergelaufen. Der Rückfall-Hinweis erklärt jetzt, dass eine
einmalige manuelle Anmeldung mit dem aktuellen Baka-Passwort die
beiden Passwörter wieder synchronisiert (baka_auth.py macht das bei
jedem erfolgreichen Login automatisch).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CcDiyJdVRqh1TtJk5JiabX
Server-User (Dustin, Baka, Tinker) melden sich beim Öffnen des
YouTube-Bereichs automatisch im Hintergrund mit ihren Navidrome-
Zugangsdaten beim Baka-Konto an (BakaAuth.autoAnmelden) — die
manuelle Anmeldung bleibt nur für Gäste sichtbar. Schlägt die
Auto-Anmeldung fehl, gibt es einen Rückfallweg zur manuellen
Anmeldung, statt den User auszusperren. Login-Buttons vergrößert.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CcDiyJdVRqh1TtJk5JiabX
- openSystemPanel(): Xiaomi-Sound-Settings-Intent zuerst, dann
Settings.ACTION_SOUND_SETTINGS, dann Android-Standard-Intent als
Fallback. Behebt "kein System-Klangeffekte" trotz Dolby Atmos auf
MIUI/HyperOS (POCO X7 Pro), wo der Standard-Intent keine Activity findet.
- Neuer Tab "YT-Suche": YouTube-Suche über den bestehenden
/api/search-Endpunkt des Baka-Proxys, Ergebnisliste mit Thumbnail
(YouTube-CDN), Titel, Dauer und Download-Knopf pro Treffer — derselbe
Download-Weg wie im bestehenden Download-Tab.
574 Tests grün, flutter analyze ohne Befund, Kotlin kompiliert sauber
(gradlew :app:compileDebugKotlin). Xiaomi-Fix konnte nicht auf echter
Hardware getestet werden.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VM2JK5mV7AL1g2Rt6H6h9w
Aus der Workflow-Analyse 2026-08-25: zwei Sessions bekamen kurz
hintereinander denselben Auftrag für diesen Worktree. .claude-worktree-lock
(gitignored) markiert künftig, wenn hier gerade aktiv gearbeitet wird;
Mechanismus ist im melo-app-workflow-Skill dokumentiert (dort auch die
korrigierte Test-Timeout-Vorgabe).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VM2JK5mV7AL1g2Rt6H6h9w
- Tabs: Meine Musik, Suchen, Download, Favoriten (vorher Download vor Suchen)
- "Meine Musik": Schnellzugriffe (Favoriten/Wiedergabelisten/Zuletzt) einzeln
über die Einstellungen abschaltbar
- Audio- und Benachrichtigungs-Berechtigung werden jetzt beim ersten Start
gemeinsam angefragt statt erst bei Bedarf; Hinweisbanner + Einstellungen-
Button bei dauerhafter Verweigerung (auch für Benachrichtigungen neu)
- Cover-Extraktion beim Android-Scan von 512px auf 1024px erhöht, für ein
schärferes Cover im Sperrbildschirm
- Fix: notifyListeners() in LibraryService nur noch bei echter Wertänderung
(verhinderte einen Test-Hang durch den neuen Start-Berechtigungs-Aufruf)
557 Tests grün, flutter analyze ohne Befund.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VM2JK5mV7AL1g2Rt6H6h9w
Die vier zuletzt zurückgestellten Punkte aus der UX-Simulation:
- Abbrechen-Knopf für hängende YouTube-Downloads (Future.any gegen ein
Abbruch-Signal, Anfrage läuft im Hintergrund aus statt die App zu
blockieren)
- Punkt am inaktiven Download-Unterreiter, wenn dort etwas im Hintergrund
läuft (SubTabs bekommt einen optionalen badges-Parameter)
- Versionsnummer unter "Über Melo" (neue Abhängigkeit: package_info_plus)
- Mini-Player führt beim Wischen jetzt sichtbar mit und wertet zusätzlich
zum Schwung auch die zurückgelegte Strecke aus — ein langsames, aber
weites Wischen wurde vorher komplett ignoriert
Dabei drei bestehende Widget-Tests korrigiert, die den Download-Tab ohne
Provider<DownloadService> aufbauten (hauptmenue_test.dart,
home_shell_test.dart, online_screen_test.dart) — lief bisher nur, weil
niemand danach fragte; das neue Badge tut das jetzt app-weit.
550 Tests grün (vorher 539), flutter analyze ohne Befund.
Zweiter Block aus der UX-Simulation (39 Funde insgesamt):
- Songtext-Icon deaktiviert statt totem Knopf, wenn kein Ziel bekannt ist
- Sleep-Timer-Restzeit jetzt auch im Sheet sichtbar, nicht nur im Tooltip
- Drag-Handle in der Warteschlange, Wisch-nach-unten schließt den
Vollbild-Player
- Fehlender Tooltip am Songtext-Sheet-Schließen-Knopf ergänzt
- YouTube-Download: Zeitüberschreitung meldet sich anders als toter Server
- Server-Tab zeigte beim Öffnen kurz fälschlich "nicht verbunden"
- Einstellungen: Favoriten-/Playlisten-Sync von "Speicher" zu
"Musikserver" verschoben, Navidrome-Eintrag erklärt jetzt seinen Zweck
- Kommentar in geteilte_adresse.dart korrigiert (Verhalten unverändert,
dafür gibt es einen Test)
Bewusst zurückgestellt: ServerFavoriteButton bleibt lokal-only (dokumentierte
Architektur-Entscheidung, siehe G3 im UX-Review), Live-Wischgeste am
Mini-Player, YouTube-Download-Abbrechen, Download-Badge im inaktiven
Unterreiter, Versionsnummer (neue Abhängigkeit nötig).
539 Tests grün (vorher 537), flutter analyze ohne Befund.
7 Agenten sind die App als normaler Nutzer durchgegangen (Erststart,
Bibliothek, Download, Suche, Favoriten, Player, Einstellungen) und haben
39 Reibungspunkte gefunden. Erster Block:
- Mehrfachauswahl lief nur im Lieder-/Favoriten-Reiter, nicht in
Kategorie-/Künstler-/Album-Ansichten — jetzt überall, per geteilter
auswahl_leiste.dart
- Zwei unterschiedlich ausgestattete Favoriten-Listen (Tab vs. Playlisten)
vereinheitlicht
- Baka-Login zeigt Ladezustand + Fehler im Dialog statt bis zu 15s stumm
zu bleiben (wie der Navidrome-Login)
- Cache leeren, Navidrome-Abmelden, Download einzeln entfernen fragen jetzt
nach
- Download-Fehlermeldung bei toter Serververbindung nennt den echten Grund
statt "War schon heruntergeladen"
- YouTube-Fehlermeldungen sind jetzt rot statt neutralfarben
- Suche schließt die Tastatur nach Auswahl, nennt den Suchbegriff bei
"Nichts gefunden", einzelne Verlaufseinträge sind entfernbar
- Icon-/Text-Korrekturen (Mikrofon-Icon fälschlich bei Speicherzugriff,
"Online"-Tab existiert nicht, ReplayGain-Jargon)
537 Tests grün (vorher 533), flutter analyze ohne Befund.
P3-Liste aus dem UX-Review: Player nimmt Cover-Farbe auf, "Teilen" aus
YouTube trägt die Adresse in den Downloader ein, Android Auto blättert
durch die Bibliothek, Laufweite der Typografie geschärft, Überschriften
vereinheitlicht. 533 Tests grün, flutter analyze ohne Befund.
Die P2-Liste aus dem Review — Kleinigkeiten, die man einzeln nicht
vermisst und zusammen sofort merkt.
- Das Coverbild wandert beim Oeffnen der Vollbild-Wiedergabe an seinen
Platz, statt dass ein neuer Bildschirm aufspringt.
- Wischen am Mini-Player: nach oben oeffnen, seitwaerts Titelwechsel. Mit
Schwelle, weil der Mini-Player zugleich ein Knopf ist und der Finger
beim Tippen fast immer ein paar Pixel wandert. Nach unten bewusst
unbelegt, damit niemand die Wiedergabe versehentlich wegschiebt.
- Kuenstlerliste mit Bildern und Albenzahl; dahinter eine Kuenstlerseite
mit seinen Alben und darunter allen Titeln (dafuer neu: groupByAlbum).
Bei nur einem Album entfaellt die Zwischenstufe.
- Alphabet-Sprung am rechten Rand, nur bei Namenssortierung und ab 30
Titeln. Umlaute zaehlen zu ihrem Grundbuchstaben, Ziffern und Zeichen
unter "#" — dieselbe Regel wie die Sortierung.
- Mehrfachauswahl per langem Druck, mit "Zur Warteschlange" und "Zu
Wiedergabeliste".
- Abgeschaltete Systemanimationen gelten jetzt ueberall, nicht nur bei den
Lauf-Balken.
- Querformat und Tablet: der Player legt Cover und Bedienung nebeneinander
und begrenzt die Textbreite.
Beim Bauen gefunden: der Alphabet-Sprung landete bei absteigender
Sortierung am Ende eines Buchstaben-Blocks statt an seinem Anfang.
Aus dem Code-Review nachgebessert, sieben Punkte: die Alphabet-Leiste
wurde breiter, je weniger Buchstaben sie hatte (bei einem einzigen 528 dp
— die Songliste waere verschwunden); die neue Kuenstlerseite baute alle
Titel sofort und oeffnete damit bei 300 Titeln ebenso viele Abos; die
Bildlauf-Animation im Songtext stuerzte bei abgeschalteten
Systemanimationen ab; die feste Zeilenhoehe war 64 statt 72 und die
Schriftskalierung an 1.0 statt an einer echten Groesse gemessen; bereits
enthaltene Titel wurden in Wiedergabelisten verschoben statt uebersprungen
und trotzdem mitgezaehlt; ein Fehler im Stapel brach still ab; und die
Zurueck-Geste verliess den Bildschirm, statt die Auswahl zu beenden.
Selbst gefunden: in der Kuenstlerliste hing der Datenbank-Strom an
CategoryService und wurde bei jeder Kategorie-Meldung neu aufgesetzt.
Nebenbei aufgeklaert, warum ein neuer Widget-Test endlos hing: Aufbau in
setUp laeuft ausserhalb der Testzone, die drift-Stroeme liefen dort in
echter Zeit, waehrend pumpAndSettle in Testzeit auf sie wartete. Aufbau in
den Testkoerper verschoben. Der aeltere Haenger im BACKLOG hat eine andere
Ursache (db.close() dort nachweislich ausgeschlossen); die Spur ist
notiert.
500 Tests gruen (vorher 457), flutter analyze ohne Befund, Release-APK
gebaut.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013xAHJTJM6UUqmjUgk1PUEd
Die letzten vier Punkte aus dem Review-Bericht.
G2 — Server-Bereich: Ein Tipp auf ein Album spielte sofort alles ab;
hineinsehen ging nicht. Jetzt Album- und Kuenstler-Ansicht mit Cover,
Kuenstler, Titelzahl, Gesamtdauer, "Abspielen"/"Zufaellig" und der
Titelliste; Antippen startet an dieser Stelle. Dazu "Mehr Alben laden" —
die Liste hoerte bei 50 auf, ohne dass etwas darauf hinwies.
NICHT umgesetzt: den Server-Bereich aus dem Download-Tab loesen (das
widerspricht Commit 34d6d8e, "Auf Wunsch von Dustin") und eine
Server-Suche (die Suche bleibt ausdruecklich rein lokal).
G8 — Songtext: Traegt der Text Zeitmarken, laeuft er mit; die aktive Zeile
ist hervorgehoben, Antippen springt an die Stelle. Ohne Zeitmarken bleibt
es eine Textwand — die App schaut nach, statt zu raten.
G10 — Cover bleiben liegen. Eigener Ordner, einmal geholt. Der Schluessel
haengt an der Album-Kennung, nicht an der Adresse: die traegt bei jedem
App-Start ein neues Token, und der Ordner waere sonst gewachsen, ohne je
einen Treffer zu liefern. Keine neue Abhaengigkeit.
G3 — Das Herz ist bei Server-Titeln nicht mehr ausgegraut, sondern
favorisiert am Server (star/unstar) — dort, wo der Favoriten-Abgleich sie
auch wieder abholt. Offen bleibt der schwere Teil: Wiedergabezaehler,
Historie und Kategorien braeuchten fuer Server-Titel eine Zeile in der
Bibliothek.
Aus dem Code-Review nachgebessert (sieben Punkte): das Herz behielt beim
Titelwechsel seinen Zustand; recycelte Listenzeilen zeigten kurz das Cover
der vorherigen; der neue Songtext bekam bei Server-Titeln die
Abspiel-Adresse statt der Server-Kennung und fand deshalb nie einen Text;
ein einmal fehlgeschlagenes Cover blieb die ganze Sitzung grau; "Server
nicht erreichbar" sah aus wie "Album hat keine Titel", womit der
Wiederholen-Knopf unerreichbar war; die Kuenstler-Ansicht waere immer leer
geblieben, weil getArtist die Titel gar nicht mitliefert; und zwei
gleichzeitige Cover-Abrufe konnten ein zerschnittenes Bild hinterlassen.
Selbst gefunden: das Haekchen "schon geladen" fragte pro Zeile die Platte
ab, bei jedem Positionswechsel neu. Jetzt einmal je Bildschirm.
457 Tests gruen (vorher 433), flutter analyze ohne Befund, Release-APK
gebaut.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013xAHJTJM6UUqmjUgk1PUEd
Bisher landete Musik nur zufaellig auf dem Geraet: was man abspielte, blieb
nebenbei liegen. Gezielt "dieses Album fuer die Zugfahrt" gab es nicht. Und
dieser Zwischenspeicher wuchs unbegrenzt — es gab nur "alles loeschen".
Zwei getrennte Ablagen. Bewusste Downloads liegen NICHT im Cache-Ordner:
den darf Android bei Speichernot jederzeit selbst leeren, und genau das
darf einem mitgenommenen Album nicht passieren. Sie liegen deshalb neben
der Datenbank im Support-Ordner. Die Grenze gilt nur fuer den
Zufalls-Cache; Downloads sind unbegrenzt und werden nie verdraengt.
- Download-Pfeil je Album und Kuenstler, mit Fortschritt und Abbruch
- Rueckfrage ab 30 Titeln samt Groessenschaetzung
- Obergrenze wahlbar (aus / 512 MB / 1 / 2 / 4 / 8 GB), Standard 2 GB;
am laengsten nicht Gehoertes weicht zuerst
- Liste "Heruntergeladen" mit Titel, Kuenstler, Groesse, einzeln oder alle
entfernbar (Schema 10)
- Wiedergabe nimmt erst den Download, dann den Zwischenspeicher
Aus dem Code-Review nachgebessert, vier ernste Punkte: "aus" (0 MB)
schaltete das Aufraeumen ab statt das Zwischenspeichern und liess den
Cache unbegrenzt wachsen; wer sich erst waehrend der Sitzung am Server
anmeldete, konnte gar nichts laden; die Verdraengung konnte Dateien
loeschen, die die laufende Warteschlange schon als Quelle eingetragen
hatte (Abbruch mitten im Album, ohne Rueckfall aufs Streamen); und ein
heruntergeladener Titel wurde beim Abspielen ein zweites Mal in den Cache
geholt. Dazu sechs kleinere und der "zuletzt gehoert"-Stempel, der beim
Aufbau der Warteschlange statt beim Abspielen gesetzt wurde.
Nebenbei aufgeraeumt, weil die Dateien ohnehin offen waren: keine Emoji
als Knoepfe mehr, kein Colors.redAccent und kein grey.shade mehr im
ganzen Projekt, und die Einstellungen heissen nicht mehr "Settings".
433 Tests gruen (vorher 411), flutter analyze ohne Befund, Release-APK
gebaut.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013xAHJTJM6UUqmjUgk1PUEd
Bisher scrollte man durch die Bibliothek und musste raten, wo man ist —
die einzige Rueckmeldung war die Leiste ganz unten.
Drei tanzende Balken ueber dem Coverbild des laufenden Titels, sein Name
in Rot. Die Balken liegen auf dem Cover statt daneben: eine vierte Spalte
haette dem Titel Platz genommen und die Zeile bei jedem Titelwechsel in
der Breite springen lassen. Pausiert bleibt die Markierung stehen, die
Balken stehen still. Bei abgeschalteten Systemanimationen ebenfalls — eine
Endlosschleife ist genau das, was diese Einstellung vermeiden soll.
Die Markierung sitzt in SongZeile und gilt damit in einem Rutsch fuer
Meine Musik, Favoriten, Suche, Kuenstler, Kategorie und "Zuletzt
hinzugefuegt". Warteschlange und Wiedergabeliste bauen ihre Zeilen selbst
(dort steht rechts Entfernen statt Herz und Menue) und haben dasselbe
Zeichen einzeln bekommen.
Nur die laufende Zeile hoert auf den Wiedergabe-Zustand: der meldet auch
den Pufferstand und feuert mehrmals pro Sekunde. Haenge jede sichtbare
Zeile daran, baute sich die halbe Liste staendig neu auf.
Aus dem Code-Review nachgebessert: Startwert fuer den Strom, sonst
erschien die Markierung beim Zurueckscrollen einen Frame zu spaet; die
Zeile aendert beim Wechsel nicht mehr die Form ihres Aufbaus, sonst verlor
das Herz daneben sein Abo und sah kurz leer aus; die Wiedergabeliste
bekam die Markierung ueberhaupt erst (der Changelog hatte sie faelschlich
schon behauptet); der Abdunkel-Schleier nimmt den Eckenradius jetzt
entgegen statt ihn fest zu verdrahten.
Testluecke geschlossen, die der Review benannt hat: geprueft waren nur die
Regel und die Balken je fuer sich, die Verdrahtung dazwischen nicht —
genau dort sassen alle drei Fehler.
411 Tests gruen (vorher 396), flutter analyze ohne Befund, Release-APK
gebaut.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013xAHJTJM6UUqmjUgk1PUEd
Der Suchen-Tab war 59 Zeilen: ein Textfeld ueber einer flachen
Liederliste, nur ueber Titel/Kuenstler/Album. Wer "Nightcore" eingab,
fand alle Titel dieses Kuenstlers untereinander, aber weder den
Kuenstler selbst noch eine gleichnamige Kategorie oder Liste.
- Vier Abschnitte mit Ueberschrift und Trefferzahl. Alben stecken in
"Kategorien" — der Album-Name ist in Melo die erste Kategorie eines
Titels, ein eigener Abschnitt waere dieselbe Liste zweimal.
- Treffer am Wortanfang zuerst, dann alphabetisch.
- Entprellt (250 ms); vorher baute jeder Tastendruck alles neu auf.
- Letzte acht Suchen, gemerkt beim Abschicken, mit Loeschen-Knopf.
- Der Tab folgt jetzt dem Aufbau der uebrigen Tabs (war ein Scaffold
mit eigener AppBar innerhalb eines Tabs).
- Bewusst rein lokal, ohne Server-Abfrage.
Herausgeloest, weil es sonst eine dritte Kopie gegeben haette:
TitelListenScreen ("Ueberschrift + Liederliste", stand zweimal wortgleich
im Baum) und SongZeile (die Suche setzt einzelne Zeilen in ihre
Abschnitte; eine ganze SongList waere dort verschachteltes Scrollen).
Aus dem Code-Review nachgebessert: Suche und Zuordnung benutzen dieselbe
Normalform, sonst zeigte ein Treffer "0 Titel" und oeffnete eine leere
Liste; Kategorien ohne lebende Titel fallen weg; alle Abschnitte sind
gedeckelt; die Drift-Stroeme werden nicht mehr je Rebuild neu abonniert;
das Loeschkreuz erscheint sofort statt nach 250 ms.
Tot geworden und entfernt: MeloDb.searchSongs samt Test.
396 Tests gruen (vorher 360), flutter analyze ohne Befund, Release-APK
gebaut.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013xAHJTJM6UUqmjUgk1PUEd
stop() brach _positionRecordTimer ab. Der Timer entsteht nur einmal im
Konstruktor, war also fuer den Rest der Sitzung weg. Da auch das System
stop() aufruft (Benachrichtigung wegwischen), merkte sich die App danach
keine Hoerposition mehr und scrobbelte nicht — bis zum Neustart und ohne
Hinweis. Der Timer steigt ohnehin selbst aus, solange nichts laeuft;
abgebrochen wird er jetzt nur noch in dispose().
Dazu eine Korrektur am eigenen Review: K4 behauptete, die Alben-Achse sei
verlorengegangen. Sie wurde bewusst durch "Kategorie" ersetzt — der
Album-Name ist in Melo die erste Kategorie eines Titels
(category_list.dart:12, kategorienAusTags). Was wirklich fehlt, ist die
Album-Detailansicht und die Tracknummer, die gar nicht eingelesen wird.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013xAHJTJM6UUqmjUgk1PUEd
Ergebnis einer Durchsicht der App gegen den Massstab "Apple Music".
Alle fuenf Punkte waren keine fehlenden Funktionen, sondern Versprechen,
die die Oberflaeche gab und der Code nicht hielt.
- POST_NOTIFICATIONS fehlte im Manifest. Auf Android 13+ blieb die
Wiedergabe-Benachrichtigung dadurch unsichtbar. Das Recht wird erst
erfragt, wenn wirklich ein Titel laeuft.
- Der Offline-Schalter wurde nirgends gelesen. Er greift jetzt an allen
drei Wegen in die Warteschlange; uebersprungene Titel werden benannt.
- CoverImage kannte nur file://, und der Server-Browser gab die
Cover-Adresse gar nicht erst mit. Server-Titel waren deshalb immer ein
graues Notensymbol.
- Warteschlange entfernen/umsortieren baute die ganze Queue neu auf:
hoerbarer Aussetzer und doppelte Wiedergabe-Zaehlung. Jetzt mutiert nur
der betroffene Eintrag, die Buchfuehrung steht vor dem Player.
- Das Herz bei Server-Titeln legte einen Favoriten mit leerer Kennung an,
der nie in der Liste auftauchte. Es ist jetzt ausgegraut.
Nachgebessert aus dem Code-Review: Offline-Meldung an die Stelle geholt,
wo sie greifen kann; Queue-Buchfuehrung vor den Player gezogen;
Fehlerpfad fuer die Berechtigungs-Abfrage ergaenzt.
360 Tests gruen (vorher 328), flutter analyze ohne Befund, Release-APK
gebaut und POST_NOTIFICATIONS darin nachgeprueft.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013xAHJTJM6UUqmjUgk1PUEd
Auf Wunsch von Dustin. Der Inhalt bleibt unveraendert (YouTube-Downloader
und Server-Bibliothek als Unterreiter), nur die Beschriftung aendert sich.
Die vier Bereiche: Meine Musik, Download, Suchen, Favoriten.
- Symbol ebenfalls zurueck auf Icons.download_outlined/download. Das ist
kein neuer Entwurf: genau dieses Symbol trug der Tab, bevor er in
Commit a625d70 in "Online" umbenannt wurde.
- Die Ueberschrift im Bereich selbst stand noch auf "Online" — ein Tab
"Download", der auf einen Bildschirm "Online" fuehrt, waere verwirrend.
Zieht jetzt nach.
- Tests und Testbeschreibungen entsprechend angepasst.
328 Tests gruen (1 uebersprungen), flutter analyze ohne Befund.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FpPu4nuKjKKeX1RpdDeX81