Files
Melo/BACKLOG.md
Hermes (Server)andClaude Opus 5 490e73ce41 Politur: Wischen, wandernde Cover, Alphabet-Sprung, Mehrfachauswahl
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
2026-08-24 15:09:46 +02:00

4.3 KiB

Backlog

Bekannte offene Punkte, die bewusst zurückgestellt wurden. Nichts hier ist vergessen — es ist entschieden, es später zu machen. Erledigtes wandert raus (die Geschichte steht im CHANGELOG).


🧪 Widget-Test song_detail_sheet_test.dart hängt (übersprungen)

Stand: 2026-08-21 · Auswirkung: nur Tests, die App ist nicht betroffen

Der Test Übernahme eines Online-Vorschlags setzt metadataEdited bleibt beim Aufbau des Widget-Baums hängen und kommt nie zurück — auch nach 13+ Minuten kein Abbruch. Da flutter test alle Dateien in einem Lauf abarbeitet, blockierte er den gesamten Testlauf. Er ist deshalb mit skip: true und einem TODO im Code markiert; der Lauf ist damit wieder in ~20 Sekunden durch.

Fachlich ist nichts ungeprüft: Was der Test absichern sollte, prüft test/library/metadaten_uebernahme_test.dart ohne Widgets — inklusive der Regel, dass eine übernommene Online-Korrektur metadataEdited setzt und den nächsten Bibliotheks-Scan damit überlebt.

Was schon eingegrenzt ist:

Verdacht Ergebnis
http.runWithClient erreicht den State im Modal-Sheet nicht widerlegt — eigene Sonde zeigt MockClient auch im Sheet
drift unter testWidgets blockiert (fehlendes runAsync) widerlegt — upsertSongs + watchSongs().first laufen durch
Einer der Provider blockiert pumpWidget widerlegt — MeloDb, CategoryService, AppSettings einzeln geprüft
db.close() im Teardown (der Hänger aus hauptmenue_test.dart) widerlegt — Entfernen ändert nichts, siehe unten
Zusammenspiel showModalBottomSheet + Providerbaum offen — der Hänger tritt zwischen pumpWidget und dem ersten tap auf

Nicht die Ursache (2026-08-21 geprüft): In hauptmenue_test.dart trat ein Hänger mit derselben Signatur auf. Dort war die Ursache await db.close() nach einem tester.tap — drift plant beim Schließen eine Aufräum-Aufgabe ein, die der Test-Rahmen nicht mehr abarbeitet. Das Rezept dagegen: Dienste per .value bereitstellen (der Baum darf sie nicht schließen), am Testende pumpWidget(SizedBox()) + pump(Duration(milliseconds: 1)), und auf db.close() verzichten. Bei song_detail_sheet_test.dart hilft genau das nicht — dort wurde es angewandt und der Test hängt weiter. Die beiden Hänger haben also unterschiedliche Ursachen.

Neu geprüft (2026-08-24): addTearDown(db.close) entfernt und den Test entsperrt — er hängt unverändert. db.close() ist hier also ausgeschlossen, nicht nur „hilft nicht".

Neue Spur aus einem anderen Hänger (2026-08-24). auswahl_modus_test.dart zeigte dieselbe Signatur: pumpAndSettle kam nie zurück, auch nicht mit gesetzter Zeitgrenze. Ursache dort war, dass Datenbank und Dienste in setUp entstanden. setUp läuft außerhalb der Testzone: die Ströme von drift liefen in echter Zeit, während pumpAndSettle in Testzeit auf sie wartete. Aufbau in den Testkörper verschoben → alle fünf Tests laufen in einer Sekunde durch.

Auf song_detail_sheet_test.dart trifft das nicht unmittelbar zu (dort steht schon alles im Testkörper) — aber http.runWithClient legt eine eigene Zone um den Aufbau. Ob das dieselbe Trennung zwischen echter und Testzeit erzeugt, ist der nächste lohnende Versuch: den Widget-Baum vor runWithClient aufbauen und nur den Netz-Aufruf darin laufen lassen.

Nächster Schritt: Den Testkörper schrittweise abspecken (Providerbaum minimieren, Sheet durch eine normale Route ersetzen) bis der Hänger verschwindet — die letzte entfernte Zutat ist die Ursache. Ein tester.pumpWidget(const SizedBox()) mit anschließendem pump() am Testende hat bei online_screen_test.dart einen verwandten Aufräum-Timer von drift gelöst und ist einen Versuch wert.


📥 Kein Wiederherstellen gelöschter Titel

Stand: 2026-08-21 · Auswirkung: Datenverlust im Fehlerfall möglich

Löschungen wirken über den Geräte-Abgleich in beide Richtungen. Gegen versehentliche Massenlöschung schützt die Sicherheitsbremse (loeschBremseGreift), aber eine einzelne irrtümliche Löschung ist endgültig: Datei und Navidrome-Verknüpfung sind weg, sobald kein Konto den Titel mehr aktiv hat.

Denkbar wäre ein Papierkorb am Server (Datei erst nach X Tagen wirklich löschen). Bewusst nicht gebaut — erst beobachten, ob es in der Praxis gebraucht wird.