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
+46
View File
@@ -0,0 +1,46 @@
import 'package:flutter_test/flutter_test.dart';
import 'package:melo/settings/app_settings.dart';
import 'package:shared_preferences/shared_preferences.dart';
void main() {
setUp(() => SharedPreferences.setMockInitialValues({}));
group('Meine-Musik-Sektionen', () {
test('sind ohne Auswahl standardmäßig alle aktiv', () async {
final settings = AppSettings();
await settings.init();
expect(settings.meineMusikSektionen,
Set.of(AppSettings.alleMeineMusikSektionen));
});
test('lassen sich einzeln abschalten und bleiben gespeichert', () async {
final settings = AppSettings();
await settings.init();
await settings.setMeineMusikSektionAktiv(
AppSettings.sektionWiedergabelisten, false);
expect(settings.meineMusikSektionen,
{AppSettings.sektionFavoriten, AppSettings.sektionZuletzt});
final neuGeladen = AppSettings();
await neuGeladen.init();
expect(neuGeladen.meineMusikSektionen,
{AppSettings.sektionFavoriten, AppSettings.sektionZuletzt});
});
test('lassen sich wieder einschalten', () async {
final settings = AppSettings();
await settings.init();
await settings.setMeineMusikSektionAktiv(
AppSettings.sektionFavoriten, false);
await settings.setMeineMusikSektionAktiv(
AppSettings.sektionFavoriten, true);
expect(settings.meineMusikSektionen,
Set.of(AppSettings.alleMeineMusikSektionen));
});
});
}
+64
View File
@@ -11,6 +11,7 @@ import 'package:melo/services/offline_mode.dart';
import 'package:melo/services/sync_service.dart';
import 'package:melo/settings/app_settings.dart';
import 'package:melo/settings/settings_screen.dart';
import 'package:shared_preferences/shared_preferences.dart';
/// Token-Ablage ohne Plattform-Kanäle — im Test gibt es keinen sicheren
/// Gerätespeicher.
@@ -44,6 +45,8 @@ Widget _wrap(MeloDb db, Widget child) {
}
void main() {
setUp(() => SharedPreferences.setMockInitialValues({}));
testWidgets('zeigt 0 Songs ohne Bibliothek', (tester) async {
final db = MeloDb(NativeDatabase.memory());
@@ -99,4 +102,65 @@ void main() {
await db.close();
});
testWidgets('zeigt Musik- und Benachrichtigungs-Berechtigung mit Einstellungs-Button',
(tester) async {
final db = MeloDb(NativeDatabase.memory());
await tester.pumpWidget(_wrap(db, const SettingsScreen()));
await tester.pumpAndSettle();
await tester.scrollUntilVisible(
find.text('Benachrichtigungs-Berechtigung'), 200);
await tester.pumpAndSettle();
expect(find.text('Musik-Berechtigung'), findsOneWidget);
expect(find.text('Benachrichtigungs-Berechtigung'), findsOneWidget);
expect(find.text('Einstellungen öffnen'), findsNWidgets(2));
await db.close();
});
testWidgets(
'Meine-Musik-Sektionen sind als Checkboxen an- und abwählbar',
(tester) async {
final db = MeloDb(NativeDatabase.memory());
final settings = AppSettings();
await settings.init();
await tester.pumpWidget(MultiProvider(
providers: [
Provider<MeloDb>.value(value: db),
ChangeNotifierProvider<OfflineMode>.value(value: OfflineMode()),
ChangeNotifierProvider<LibraryService>.value(
value: LibraryService(db)),
ChangeNotifierProvider<AppSettings>.value(value: settings),
ChangeNotifierProvider<BakaAuth>(
create: (_) => BakaAuth(speicher: _MemorySpeicher())),
ChangeNotifierProvider<SyncService>(
create: (context) => SyncService(
db: db,
cloud: MeloCloudService(auth: context.read<BakaAuth>()),
)),
],
child: const MaterialApp(home: SettingsScreen()),
));
await tester.pumpAndSettle();
await tester.scrollUntilVisible(find.text('Wiedergabelisten'), 200);
await tester.pumpAndSettle();
expect(find.text('Favoriten'), findsOneWidget);
expect(find.text('Wiedergabelisten'), findsOneWidget);
expect(find.text('Zuletzt hinzugefügt'), findsOneWidget);
await tester.tap(find.widgetWithText(CheckboxListTile, 'Wiedergabelisten'));
await tester.pumpAndSettle();
expect(
settings.meineMusikSektionen
.contains(AppSettings.sektionWiedergabelisten),
isFalse);
await db.close();
});
}