UX-Simulation: Mehrfachauswahl überall, Baka-Login, Bestätigungen, Suche

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.
This commit is contained in:
Hermes (Server)
2026-08-25 09:42:41 +02:00
parent 60c57577a3
commit 07acf77ba4
15 changed files with 511 additions and 202 deletions
+17
View File
@@ -20,6 +20,15 @@ List<String> verlaufMit(List<String> verlauf, String begriff) {
return ergebnis.take(verlaufMaximum).toList();
}
/// [verlauf] ohne [begriff] — zum gezielten Entfernen eines einzelnen
/// Eintrags, ohne den ganzen Verlauf zu leeren.
List<String> verlaufOhne(List<String> verlauf, String begriff) {
return [
for (final alt in verlauf)
if (alt.toLowerCase() != begriff.trim().toLowerCase()) alt,
];
}
/// Merkt sich die letzten Suchbegriffe über einen App-Neustart hinweg.
/// Aufbau wie [SortStore]: statische Methoden auf SharedPreferences.
class SuchVerlauf {
@@ -42,4 +51,12 @@ class SuchVerlauf {
final prefs = await SharedPreferences.getInstance();
await prefs.remove(_key);
}
/// Entfernt [begriff] aus dem Verlauf und gibt den neuen Verlauf zurück.
static Future<List<String>> entferne(String begriff) async {
final prefs = await SharedPreferences.getInstance();
final neu = verlaufOhne(prefs.getStringList(_key) ?? const [], begriff);
await prefs.setStringList(_key, neu);
return neu;
}
}