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:
@@ -92,6 +92,11 @@ class _SearchScreenState extends State<SearchScreen> {
|
||||
if (mounted) setState(() => _verlauf = const []);
|
||||
}
|
||||
|
||||
Future<void> _verlaufEntferne(String begriff) async {
|
||||
final neu = await SuchVerlauf.entferne(begriff);
|
||||
if (mounted) setState(() => _verlauf = neu);
|
||||
}
|
||||
|
||||
void _leeren() {
|
||||
_entprellen?.cancel();
|
||||
_feld.clear();
|
||||
@@ -118,6 +123,7 @@ class _SearchScreenState extends State<SearchScreen> {
|
||||
begriffe: _verlauf,
|
||||
onWaehlen: _uebernimm,
|
||||
onLeeren: _verlaufLeeren,
|
||||
onEntfernen: _verlaufEntferne,
|
||||
)
|
||||
: StreamBuilder<List<Song>>(
|
||||
stream: _songs,
|
||||
@@ -138,7 +144,7 @@ class _SearchScreenState extends State<SearchScreen> {
|
||||
query: _query,
|
||||
);
|
||||
if (treffer.istLeer) {
|
||||
return const _Hinweis('Nichts gefunden');
|
||||
return _Hinweis('Nichts gefunden für „$_query"');
|
||||
}
|
||||
return _Ergebnisse(
|
||||
treffer: treffer,
|
||||
@@ -228,11 +234,13 @@ class _Verlauf extends StatelessWidget {
|
||||
required this.begriffe,
|
||||
required this.onWaehlen,
|
||||
required this.onLeeren,
|
||||
required this.onEntfernen,
|
||||
});
|
||||
|
||||
final List<String> begriffe;
|
||||
final ValueChanged<String> onWaehlen;
|
||||
final VoidCallback onLeeren;
|
||||
final ValueChanged<String> onEntfernen;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@@ -252,6 +260,11 @@ class _Verlauf extends StatelessWidget {
|
||||
ListTile(
|
||||
leading: const Icon(Icons.history),
|
||||
title: Text(begriff),
|
||||
trailing: IconButton(
|
||||
tooltip: '„$begriff" aus dem Verlauf entfernen',
|
||||
icon: const Icon(Icons.close, size: 18),
|
||||
onPressed: () => onEntfernen(begriff),
|
||||
),
|
||||
onTap: () => onWaehlen(begriff),
|
||||
),
|
||||
],
|
||||
@@ -270,6 +283,7 @@ class _Ergebnisse extends StatelessWidget {
|
||||
final List<Song> alleSongs;
|
||||
|
||||
void _oeffne(BuildContext context, String titel, List<Song> songs) {
|
||||
FocusScope.of(context).unfocus();
|
||||
Navigator.of(context).push(MaterialPageRoute(
|
||||
builder: (_) => TitelListenScreen(titel: titel, songs: songs),
|
||||
));
|
||||
@@ -334,9 +348,12 @@ class _Ergebnisse extends StatelessWidget {
|
||||
leading: const Icon(Icons.queue_music),
|
||||
title:
|
||||
Text(liste.name, maxLines: 1, overflow: TextOverflow.ellipsis),
|
||||
onTap: () => Navigator.of(context).push(MaterialPageRoute(
|
||||
builder: (_) => PlaylistDetailScreen(playlist: liste),
|
||||
)),
|
||||
onTap: () {
|
||||
FocusScope.of(context).unfocus();
|
||||
Navigator.of(context).push(MaterialPageRoute(
|
||||
builder: (_) => PlaylistDetailScreen(playlist: liste),
|
||||
));
|
||||
},
|
||||
),
|
||||
],
|
||||
const SizedBox(height: MeloSpace.md),
|
||||
|
||||
Reference in New Issue
Block a user