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:
co-authored by
Claude Sonnet 5
parent
54cb523cf4
commit
da012a3dca
@@ -8,6 +8,20 @@ class AppSettings extends ChangeNotifier {
|
||||
static const _keyAutoPlayHeadphones = 'autoplay_kopfhoerer';
|
||||
static const _keyNormalizeVolume = 'gleiche_lautstaerke';
|
||||
static const _keyCacheGrenze = 'cache_grenze_mb';
|
||||
static const _keyMeineMusikSektionen = 'meine_musik_sektionen';
|
||||
|
||||
/// Schnellzugriffe oben in „Meine Musik" — Schlüssel für die
|
||||
/// [meineMusikSektionen]-Auswahl in den Einstellungen.
|
||||
static const sektionFavoriten = 'favoriten';
|
||||
static const sektionWiedergabelisten = 'wiedergabelisten';
|
||||
static const sektionZuletzt = 'zuletzt';
|
||||
|
||||
/// Alle wählbaren Sektionen, in der Reihenfolge, in der sie oben erscheinen.
|
||||
static const alleMeineMusikSektionen = [
|
||||
sektionFavoriten,
|
||||
sektionWiedergabelisten,
|
||||
sektionZuletzt,
|
||||
];
|
||||
|
||||
/// Voreinstellung für den Zwischenspeicher: 2 GB. Groß genug für einige
|
||||
/// hundert Titel, klein genug, um ein Telefon nicht zuzumüllen.
|
||||
@@ -20,6 +34,7 @@ class AppSettings extends ChangeNotifier {
|
||||
bool _autoPlayOnHeadphones = false;
|
||||
bool _normalizeVolume = true;
|
||||
int _cacheGrenzeMb = cacheGrenzeStandardMb;
|
||||
Set<String> _meineMusikSektionen = Set.of(alleMeineMusikSektionen);
|
||||
|
||||
/// "Gleiche Kategorie = gleiches Coverbild" — an: das Cover kommt von der
|
||||
/// ersten Kategorie des Songs, aus: jeder Song zeigt sein eigenes Bild.
|
||||
@@ -39,12 +54,19 @@ class AppSettings extends ChangeNotifier {
|
||||
|
||||
int get cacheGrenzeBytes => _cacheGrenzeMb * 1024 * 1024;
|
||||
|
||||
/// Welche Schnellzugriffe oben in „Meine Musik" angezeigt werden.
|
||||
Set<String> get meineMusikSektionen => _meineMusikSektionen;
|
||||
|
||||
Future<void> init() async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
_groupCoversByCategory = prefs.getBool(_keyGroupCovers) ?? true;
|
||||
_autoPlayOnHeadphones = prefs.getBool(_keyAutoPlayHeadphones) ?? false;
|
||||
_normalizeVolume = prefs.getBool(_keyNormalizeVolume) ?? true;
|
||||
_cacheGrenzeMb = prefs.getInt(_keyCacheGrenze) ?? cacheGrenzeStandardMb;
|
||||
final gespeicherteSektionen = prefs.getStringList(_keyMeineMusikSektionen);
|
||||
_meineMusikSektionen = gespeicherteSektionen == null
|
||||
? Set.of(alleMeineMusikSektionen)
|
||||
: Set.of(gespeicherteSektionen);
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
@@ -79,4 +101,18 @@ class AppSettings extends ChangeNotifier {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
await prefs.setBool(_keyAutoPlayHeadphones, value);
|
||||
}
|
||||
|
||||
/// Blendet eine Schnellzugriff-Sektion oben in „Meine Musik" ein oder aus.
|
||||
Future<void> setMeineMusikSektionAktiv(String sektion, bool aktiv) async {
|
||||
final aktuell = aktiv == _meineMusikSektionen.contains(sektion);
|
||||
if (aktuell) return;
|
||||
_meineMusikSektionen = Set.of(_meineMusikSektionen);
|
||||
aktiv
|
||||
? _meineMusikSektionen.add(sektion)
|
||||
: _meineMusikSektionen.remove(sektion);
|
||||
notifyListeners();
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
await prefs.setStringList(
|
||||
_keyMeineMusikSektionen, _meineMusikSektionen.toList());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -160,6 +160,22 @@ class _SettingsScreenState extends State<SettingsScreen> {
|
||||
),
|
||||
),
|
||||
const Divider(height: 1),
|
||||
const _SectionLabel('Meine Musik'),
|
||||
Consumer<AppSettings>(
|
||||
builder: (context, settings, _) => Column(
|
||||
children: [
|
||||
for (final sektion in AppSettings.alleMeineMusikSektionen)
|
||||
CheckboxListTile(
|
||||
secondary: Icon(_sektionIcon(sektion)),
|
||||
title: Text(_sektionLabel(sektion)),
|
||||
value: settings.meineMusikSektionen.contains(sektion),
|
||||
onChanged: (aktiv) => settings.setMeineMusikSektionAktiv(
|
||||
sektion, aktiv ?? false),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const Divider(height: 1),
|
||||
const _SectionLabel('Darstellung'),
|
||||
Consumer<AppSettings>(
|
||||
builder: (context, settings, _) => SwitchListTile(
|
||||
@@ -301,6 +317,15 @@ class _SettingsScreenState extends State<SettingsScreen> {
|
||||
child: const Text('Einstellungen öffnen'),
|
||||
),
|
||||
),
|
||||
ListTile(
|
||||
leading: const Icon(Icons.notifications_outlined),
|
||||
title: const Text('Benachrichtigungs-Berechtigung'),
|
||||
subtitle: const Text('Für die Steuerung im Sperrbildschirm'),
|
||||
trailing: TextButton(
|
||||
onPressed: openMusicPermissionSettings,
|
||||
child: const Text('Einstellungen öffnen'),
|
||||
),
|
||||
),
|
||||
const Divider(height: 1),
|
||||
const _SectionLabel('Über Melo'),
|
||||
ListTile(
|
||||
@@ -577,6 +602,21 @@ class _SettingsScreenState extends State<SettingsScreen> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Icon und Beschriftung der Schnellzugriff-Sektionen aus [AppSettings].
|
||||
IconData _sektionIcon(String sektion) => switch (sektion) {
|
||||
AppSettings.sektionFavoriten => Icons.favorite,
|
||||
AppSettings.sektionWiedergabelisten => Icons.queue_music,
|
||||
AppSettings.sektionZuletzt => Icons.schedule,
|
||||
_ => Icons.circle,
|
||||
};
|
||||
|
||||
String _sektionLabel(String sektion) => switch (sektion) {
|
||||
AppSettings.sektionFavoriten => 'Favoriten',
|
||||
AppSettings.sektionWiedergabelisten => 'Wiedergabelisten',
|
||||
AppSettings.sektionZuletzt => 'Zuletzt hinzugefügt',
|
||||
_ => sektion,
|
||||
};
|
||||
|
||||
/// Kleine graue Überschrift über einer Einstellungs-Gruppe.
|
||||
class _SectionLabel extends StatelessWidget {
|
||||
const _SectionLabel(this.label);
|
||||
|
||||
Reference in New Issue
Block a user