Navidrome-Integration vollständig: Browser-Widget in Home-Screen eingebaut

- NavidromeBrowser-Widget als BottomSheet verfügbar
- Dialog erweitert: "Browser öffnen" zeigt draggable Album/Song-Liste
- Musikserver-Statuspunkt bereits im initState geladen
- Alle 202 Tests grün (Verify-Fix durch isolierte navServer-Zustandsänderung)

Workflow:
1. Nutzer tippt auf Musikserver-Chip (oben im Header)
2. Dialog zeigt Verbindungsstatus + "Browser öffnen"-Button
3. BottomSheet öffnet Album-Liste (0.7..0.95 Höhe, draggable)
4. Download oder Stream direkt von Navidrome möglich

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01M8HvgtKSsaDZ8bjZrYBBms
This commit is contained in:
Hermes (Server)
2026-08-19 06:50:00 +02:00
co-authored by Claude Haiku 4.5
parent 22238138e8
commit 2b10c350f9
+26 -3
View File
@@ -25,6 +25,7 @@ import '../services/auth_service.dart';
import '../services/sync_service.dart'; import '../services/sync_service.dart';
import '../services/realtime_sync_service.dart'; import '../services/realtime_sync_service.dart';
import '../config/app_config.dart'; import '../config/app_config.dart';
import '../widgets/navidrome_browser.dart';
class MeloHome extends StatefulWidget { class MeloHome extends StatefulWidget {
const MeloHome({super.key}); const MeloHome({super.key});
@@ -351,16 +352,22 @@ class _MeloHomeState extends State<MeloHome> with WidgetsBindingObserver {
TextButton(onPressed: () => Navigator.pop(ctx), child: const Text('Schließen')), TextButton(onPressed: () => Navigator.pop(ctx), child: const Text('Schließen')),
if (verbunden) if (verbunden)
TextButton( TextButton(
onPressed: () { onPressed: () async {
Navigator.pop(ctx); Navigator.pop(ctx);
_zeigeServerBrowser(); await _vm.navidrome.loescheZugangsdaten();
_vm.navidromeAlben.clear();
if (mounted) setState(() {});
}, },
child: const Text('Trennen', style: TextStyle(color: MeloTheme.textSekundaer)), child: const Text('Trennen', style: TextStyle(color: MeloTheme.textSekundaer)),
), ),
TextButton( TextButton(
onPressed: () { onPressed: () {
Navigator.pop(ctx); Navigator.pop(ctx);
if (!verbunden) _zeigeServerBrowser(); if (verbunden) {
_zeigeNavidromeBrowser();
} else {
_zeigeServerBrowser();
}
}, },
child: Text( child: Text(
verbunden ? 'Browser öffnen' : 'Verbinden', verbunden ? 'Browser öffnen' : 'Verbinden',
@@ -1620,5 +1627,21 @@ class _MeloHomeState extends State<MeloHome> with WidgetsBindingObserver {
), ),
); );
} }
/// BottomSheet für den Navidrome-Browser
void _zeigeNavidromeBrowser() {
showModalBottomSheet<void>(
context: context,
backgroundColor: MeloTheme.dunkel1,
isScrollControlled: true,
builder: (ctx) => DraggableScrollableSheet(
expand: false,
initialChildSize: 0.7,
minChildSize: 0.4,
maxChildSize: 0.95,
builder: (_, controller) => NavidromeBrowser(vm: _vm),
),
);
}
} }