Fix: Server-Bibliothek lädt nicht + Tab '🌐 Server' abgeschnitten

Bug 2 (Laden schlägt fehl trotz 'ping ok'): Der Code ignorierte das Subsonic-
status-Feld. Navidrome liefert bei falschem Passwort HTTP 200 mit
status:"failed" — ping() meldete dadurch fälschlich Erfolg, getAlben/getArtists
behandelten die Fehlerantwort still als leer ("Erneut versuchen").
- parseSubsonic() wirft NavidromeException bei status:"failed" (mit Servermsg).
- ping() prüft jetzt den Body statt nur HTTP 200.
- getAlben/getArtists reichen den Fehler durch (rethrow) statt [] zu liefern.
- getAlben nutzt getAlbumList2 (ID3, wie getArtists) statt getAlbumList (Folder).
- Server-Tab zeigt die echte Fehlermeldung statt "Keine Alben geladen".

Bug 1 (Tab abgeschnitten -> nur "Serve"): TabBar labelPadding verkleinert
(engere Abstände), Schriftgröße unverändert.

Neue Tests: test/navidrome_parse_test.dart (5). 84/84 grün, analyze sauber.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Tr2UwurtxyJUpWpBSeVmBm
This commit is contained in:
Hermes (Server)
2026-08-20 02:24:37 +02:00
co-authored by Claude Opus 4.8
parent 61e28d128f
commit 3d39e8b922
4 changed files with 183 additions and 33 deletions
+45 -18
View File
@@ -40,6 +40,9 @@ class LibraryScreen extends StatelessWidget {
),
],
bottom: const TabBar(
// Engere Abstände, damit '🌐 Server' nicht abgeschnitten wird
// (4 feste Tabs, gleich breit) — Schriftgröße bleibt unverändert.
labelPadding: EdgeInsets.symmetric(horizontal: 4),
tabs: [
Tab(text: 'Alle'),
Tab(text: 'Künstler'),
@@ -256,6 +259,7 @@ class _NavidromeTabState extends State<_NavidromeTab> {
List<SubsonicArtist> _artists = [];
bool _loading = false;
bool _showArtists = false;
String? _error;
@override
void initState() {
@@ -271,7 +275,10 @@ class _NavidromeTabState extends State<_NavidromeTab> {
if (!_nav.istVerbunden) {
return;
}
setState(() => _loading = true);
setState(() {
_loading = true;
_error = null;
});
try {
final alben = await _nav.getAlben(anzahl: 50);
if (mounted) {
@@ -282,7 +289,10 @@ class _NavidromeTabState extends State<_NavidromeTab> {
}
} catch (e) {
if (mounted) {
setState(() => _loading = false);
setState(() {
_loading = false;
_error = e is NavidromeException ? e.message : 'Verbindungsfehler';
});
}
debugPrint('Fehler beim Laden der Alben: $e');
}
@@ -290,7 +300,10 @@ class _NavidromeTabState extends State<_NavidromeTab> {
Future<void> _loadArtists() async {
if (!_nav.istVerbunden) return;
setState(() => _loading = true);
setState(() {
_loading = true;
_error = null;
});
try {
final artists = await _nav.getArtists();
if (mounted) {
@@ -300,7 +313,12 @@ class _NavidromeTabState extends State<_NavidromeTab> {
});
}
} catch (e) {
if (mounted) setState(() => _loading = false);
if (mounted) {
setState(() {
_loading = false;
_error = e is NavidromeException ? e.message : 'Verbindungsfehler';
});
}
debugPrint('Fehler beim Laden der Künstler: $e');
}
}
@@ -331,21 +349,30 @@ class _NavidromeTabState extends State<_NavidromeTab> {
}
if (_albums.isEmpty) {
final hatFehler = _error != null;
return Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
const Icon(Icons.album, size: 64, color: Colors.white24),
const SizedBox(height: 12),
const Text('Keine Alben geladen',
style: TextStyle(color: Colors.white54)),
const SizedBox(height: 16),
FilledButton.icon(
icon: const Icon(Icons.refresh),
label: const Text('Erneut versuchen'),
onPressed: _loadAlbums,
),
],
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 32),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Icon(hatFehler ? Icons.error_outline : Icons.album,
size: 64,
color: hatFehler ? Colors.redAccent : Colors.white24),
const SizedBox(height: 12),
Text(
hatFehler ? 'Serverfehler: $_error' : 'Keine Alben geladen',
textAlign: TextAlign.center,
style: const TextStyle(color: Colors.white54),
),
const SizedBox(height: 16),
FilledButton.icon(
icon: const Icon(Icons.refresh),
label: const Text('Erneut versuchen'),
onPressed: _loadAlbums,
),
],
),
),
);
}