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.
63 lines
2.2 KiB
Dart
63 lines
2.2 KiB
Dart
import 'package:shared_preferences/shared_preferences.dart';
|
|
|
|
/// Wie viele Suchbegriffe gemerkt werden. Mehr passen nicht auf den Schirm,
|
|
/// ohne dass die Liste selbst zum Suchproblem wird.
|
|
const verlaufMaximum = 8;
|
|
|
|
/// [verlauf] mit [begriff] vorn: der zuletzt gesuchte Begriff steht oben,
|
|
/// jeder Begriff nur einmal, insgesamt höchstens [verlaufMaximum].
|
|
///
|
|
/// Rein und ohne Speicher — die Reihenfolge-Regeln sind der Teil, der
|
|
/// schiefgehen kann.
|
|
List<String> verlaufMit(List<String> verlauf, String begriff) {
|
|
final neu = begriff.trim();
|
|
if (neu.isEmpty) return List<String>.from(verlauf);
|
|
final ergebnis = [
|
|
neu,
|
|
for (final alt in verlauf)
|
|
if (alt.toLowerCase() != neu.toLowerCase()) alt,
|
|
];
|
|
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 {
|
|
static const _key = 'such_verlauf';
|
|
|
|
static Future<List<String>> laden() async {
|
|
final prefs = await SharedPreferences.getInstance();
|
|
return prefs.getStringList(_key) ?? const [];
|
|
}
|
|
|
|
/// Trägt [begriff] ein und gibt den neuen Verlauf zurück.
|
|
static Future<List<String>> merke(String begriff) async {
|
|
final prefs = await SharedPreferences.getInstance();
|
|
final neu = verlaufMit(prefs.getStringList(_key) ?? const [], begriff);
|
|
await prefs.setStringList(_key, neu);
|
|
return neu;
|
|
}
|
|
|
|
static Future<void> leeren() async {
|
|
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;
|
|
}
|
|
}
|