Tab-Reihenfolge, konfigurierbare Meine-Musik-Sektionen, Berechtigungen beim Start, schärferes Sperrbildschirm-Cover

- Tabs: Meine Musik, Suchen, Download, Favoriten (vorher Download vor Suchen)
- "Meine Musik": Schnellzugriffe (Favoriten/Wiedergabelisten/Zuletzt) einzeln
  über die Einstellungen abschaltbar
- Audio- und Benachrichtigungs-Berechtigung werden jetzt beim ersten Start
  gemeinsam angefragt statt erst bei Bedarf; Hinweisbanner + Einstellungen-
  Button bei dauerhafter Verweigerung (auch für Benachrichtigungen neu)
- Cover-Extraktion beim Android-Scan von 512px auf 1024px erhöht, für ein
  schärferes Cover im Sperrbildschirm
- Fix: notifyListeners() in LibraryService nur noch bei echter Wertänderung
  (verhinderte einen Test-Hang durch den neuen Start-Berechtigungs-Aufruf)

557 Tests grün, flutter analyze ohne Befund.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VM2JK5mV7AL1g2Rt6H6h9w
This commit is contained in:
Hermes (Server)
2026-08-25 14:17:13 +02:00
co-authored by Claude Sonnet 5
parent 54cb523cf4
commit da012a3dca
12 changed files with 364 additions and 73 deletions
+51 -2
View File
@@ -14,7 +14,7 @@ import 'package:provider/provider.dart';
import 'package:shared_preferences/shared_preferences.dart';
Widget _wrap(MeloDb db, LibraryService lib, PlaylistService playlists,
MeloAudioHandler handler, Widget child) {
MeloAudioHandler handler, Widget child, {AppSettings? settings}) {
return MultiProvider(
providers: [
Provider<MeloDb>.value(value: db),
@@ -22,7 +22,9 @@ Widget _wrap(MeloDb db, LibraryService lib, PlaylistService playlists,
ChangeNotifierProvider<PlaylistService>.value(value: playlists),
Provider<MeloAudioHandler>.value(value: handler),
ChangeNotifierProvider<CategoryService>(create: (_) => CategoryService(db)),
ChangeNotifierProvider<AppSettings>(create: (_) => AppSettings()),
settings == null
? ChangeNotifierProvider<AppSettings>(create: (_) => AppSettings())
: ChangeNotifierProvider<AppSettings>.value(value: settings),
],
child: MaterialApp(home: Scaffold(body: child)),
);
@@ -112,6 +114,31 @@ void main() {
await db.close();
});
testWidgets(
'abgewählte Sektionen fehlen in den Schnellzugriffen, aktive bleiben',
(tester) async {
final db = MeloDb(NativeDatabase.memory());
final lib = LibraryService(db);
final playlists = PlaylistService(db);
final handler = MeloAudioHandler(db: db);
final settings = AppSettings();
await settings.init();
await settings.setMeineMusikSektionAktiv(
AppSettings.sektionWiedergabelisten, false);
await tester.pumpWidget(_wrap(
db, lib, playlists, handler, const MyMusicScreen(),
settings: settings));
await tester.pumpAndSettle();
expect(find.text('Favoriten'), findsOneWidget);
expect(find.text('Zuletzt'), findsOneWidget);
expect(find.text('Wiedergabelisten'), findsNothing);
handler.dispose();
await db.close();
});
testWidgets('Favoriten-Tab zeigt nur favorisierte Songs mit Shuffle',
(tester) async {
final db = MeloDb(NativeDatabase.memory());
@@ -150,4 +177,26 @@ void main() {
handler.dispose();
await db.close();
});
testWidgets(
'Banner mit "Einstellungen"-Button, wenn die Benachrichtigung verweigert ist',
(tester) async {
final db = MeloDb(NativeDatabase.memory());
final lib = LibraryService(db)..notificationPermissionDenied = true;
final playlists = PlaylistService(db);
final handler = MeloAudioHandler(db: db);
await tester.pumpWidget(
_wrap(db, lib, playlists, handler, const MyMusicScreen()));
await tester.pumpAndSettle();
expect(
find.textContaining('Benachrichtigungen für die Wiedergabe'),
findsOneWidget,
);
expect(find.text('Einstellungen'), findsOneWidget);
handler.dispose();
await db.close();
});
}