Files
Melo/lib/library/such_verlauf.dart
Hermes (Server) 07acf77ba4 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.
2026-08-25 09:42:41 +02:00

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;
}
}