Songtext aus Datei-Tags, Warteschlangen-Aktionen, Kategorie-Cover im

Sperrbildschirm und ReplayGain

- DB-Schema 6: lyrics + gain_db
- Songtext bevorzugt lokalen Tag, Server nur als Rueckfall; Song-ID-Bug
  beim Lyrics-Aufruf behoben
- "Als Naechstes spielen" / "Zur Warteschlange hinzufuegen" ohne Eingriff
  in Favoriten oder Wiedergabelisten
- songToMediaItem nimmt eine Cover-Vorgabe: Sperrbildschirm zeigt das
  Kategorie-Cover
- ReplayGain: Tags werden gelesen, laute Titel abgesenkt, abschaltbar

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011snPXPafPC5i87o68H14W7
This commit is contained in:
2026-08-20 18:41:36 +02:00
co-authored by Claude Opus 5
parent 1325badf90
commit 4ebd0a8dd4
17 changed files with 534 additions and 46 deletions
+39 -1
View File
@@ -1,3 +1,4 @@
import 'package:audio_service/audio_service.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
@@ -83,6 +84,15 @@ class SongList extends StatelessWidget {
/// Menü hinter dem Drei-Punkte-Symbol einer Songzeile.
Future<void> _showMenu(BuildContext context, Song song) async {
final handler = context.read<MeloAudioHandler>();
final categories = context.read<CategoryService>();
final settings = context.read<AppSettings>();
final messenger = ScaffoldMessenger.of(context);
MediaItem item() => songToMediaItem(
song,
cover: categories.coverFor(song,
groupByCategory: settings.groupCoversByCategory),
);
await showModalBottomSheet(
context: context,
builder: (sheetContext) => SafeArea(
@@ -97,6 +107,28 @@ class SongList extends StatelessWidget {
SongDetailSheet.show(context, song);
},
),
ListTile(
leading: const Icon(Icons.playlist_play),
title: const Text('Als Nächstes spielen'),
onTap: () async {
Navigator.pop(sheetContext);
await handler.playNext(item());
messenger.showSnackBar(const SnackBar(
content: Text('Läuft als Nächstes')));
},
),
ListTile(
leading: const Icon(Icons.queue),
title: const Text('Zur Warteschlange hinzufügen'),
subtitle: const Text(
'Nur für jetzt — nicht in Favoriten oder Wiedergabelisten'),
onTap: () async {
Navigator.pop(sheetContext);
await handler.addToQueue(item());
messenger.showSnackBar(const SnackBar(
content: Text('Zur Warteschlange hinzugefügt')));
},
),
ListTile(
leading: const Icon(Icons.playlist_add),
title: const Text('Zu Wiedergabeliste hinzufügen'),
@@ -147,7 +179,13 @@ class SongList extends StatelessWidget {
),
onTap: () async {
try {
await playSongs(handler, songs, i);
await playSongs(
handler,
songs,
i,
coverOf: (song) => categories.coverFor(song,
groupByCategory: settings.groupCoversByCategory),
);
} catch (e) {
if (context.mounted) {
ScaffoldMessenger.of(context).showSnackBar(