Cover-Farbe, Teilen aus YouTube, Android Auto, geschärfte Typografie

P3-Liste aus dem UX-Review: Player nimmt Cover-Farbe auf, "Teilen" aus
YouTube trägt die Adresse in den Downloader ein, Android Auto blättert
durch die Bibliothek, Laufweite der Typografie geschärft, Überschriften
vereinheitlicht. 533 Tests grün, flutter analyze ohne Befund.
This commit is contained in:
Hermes (Server)
2026-08-25 09:09:27 +02:00
parent 490e73ce41
commit 60c57577a3
22 changed files with 1040 additions and 40 deletions
+54 -11
View File
@@ -15,6 +15,7 @@ import '../services/navidrome_service.dart';
import '../services/server_neuheiten.dart';
import '../services/yt_download_service.dart';
import '../shared/sub_tabs.dart';
import '../shared/ueberschrift.dart';
import 'download_einordnung.dart';
import 'server_titel_screen.dart';
import '../shared/theme.dart';
@@ -24,7 +25,19 @@ import '../shared/theme.dart';
/// Titel werden vom [MeloAudioHandler] automatisch lokal zwischengespeichert
/// und stehen danach offline zur Verfügung.
class DownloadsScreen extends StatefulWidget {
const DownloadsScreen({super.key});
const DownloadsScreen({
super.key,
this.adresse,
this.onAdresseUebernommen,
});
/// Adresse aus einem „Teilen"-Aufruf. Wird ins Eingabefeld übernommen und
/// der YouTube-Unterreiter aufgeschlagen.
final String? adresse;
/// Meldet zurück, dass die Adresse angekommen ist — sie soll beim nächsten
/// Wechsel in diesen Bereich nicht erneut auftauchen.
final VoidCallback? onAdresseUebernommen;
@override
State<DownloadsScreen> createState() => _DownloadsScreenState();
@@ -34,27 +47,35 @@ class _DownloadsScreenState extends State<DownloadsScreen> {
/// 0 = YouTube, 1 = Server.
int _subTab = 0;
@override
void didUpdateWidget(DownloadsScreen alt) {
super.didUpdateWidget(alt);
// Eine geteilte Adresse gehört zum YouTube-Bereich; wer gerade beim
// Server war, soll trotzdem dort landen.
if (widget.adresse != null && widget.adresse != alt.adresse) {
setState(() => _subTab = 0);
}
}
@override
Widget build(BuildContext context) {
return SafeArea(
bottom: false,
child: Column(
children: [
const Padding(
padding: EdgeInsets.fromLTRB(20, 16, 20, 4),
child: Align(
alignment: Alignment.centerLeft,
child: Text('Download',
style: TextStyle(fontSize: 24, fontWeight: FontWeight.w700)),
),
),
const Ueberschrift('Download'),
SubTabs(
labels: const ['YouTube', 'Server'],
index: _subTab,
onChanged: (i) => setState(() => _subTab = i),
),
Expanded(
child: _subTab == 0 ? const _YouTubeBereich() : const _ServerBrowser(),
child: _subTab == 0
? _YouTubeBereich(
adresse: widget.adresse,
onAdresseUebernommen: widget.onAdresseUebernommen,
)
: const _ServerBrowser(),
),
],
),
@@ -541,7 +562,10 @@ const _cookiesSchluessel = 'yt_cookies';
/// YouTube-Bereich: Anmeldung am Baka-Konto und Adressfeld für den Download.
class _YouTubeBereich extends StatefulWidget {
const _YouTubeBereich();
const _YouTubeBereich({this.adresse, this.onAdresseUebernommen});
final String? adresse;
final VoidCallback? onAdresseUebernommen;
@override
State<_YouTubeBereich> createState() => _YouTubeBereichState();
@@ -562,6 +586,24 @@ class _YouTubeBereichState extends State<_YouTubeBereich> {
void initState() {
super.initState();
_ladeEinstellungen();
_uebernimmAdresse();
}
@override
void didUpdateWidget(_YouTubeBereich alt) {
super.didUpdateWidget(alt);
if (widget.adresse != null && widget.adresse != alt.adresse) {
_uebernimmAdresse();
}
}
/// Trägt eine geteilte Adresse ins Feld — ohne den Download zu starten.
/// Kategorie und Speicherort will man vorher noch wählen können.
void _uebernimmAdresse() {
final adresse = widget.adresse;
if (adresse == null) return;
_url.text = adresse;
widget.onAdresseUebernommen?.call();
}
Future<void> _ladeEinstellungen() async {
@@ -845,3 +887,4 @@ class _KategorieFeld extends StatelessWidget {
);
}
}