import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import '../player/audio_handler.dart'; import '../shared/cover.dart'; import 'album_list.dart'; import 'artist_list.dart'; import 'database.dart'; import 'library_service.dart'; import 'permissions.dart'; import 'song_list.dart'; import 'song_media.dart'; /// Bibliotheks-Tab mit drei Unteransichten: alle Songs, Künstler, Alben. /// Scan-Banner/-Fortschritt gelten für alle Unteransichten und liegen daher /// oberhalb der [TabBarView]. class LibraryScreen extends StatelessWidget { const LibraryScreen({super.key}); @override Widget build(BuildContext context) { final lib = context.watch(); return DefaultTabController( length: 3, child: Scaffold( appBar: AppBar( title: const Text('Bibliothek'), actions: [ IconButton( tooltip: addMusicLabel, icon: const Icon(Icons.create_new_folder_outlined), onPressed: lib.scanning ? null : lib.pickFolderAndScan, ), IconButton( tooltip: 'Erneut scannen', icon: const Icon(Icons.refresh), onPressed: lib.scanning ? null : lib.rescan, ), ], bottom: const TabBar( tabs: [ Tab(text: 'Alle'), Tab(text: 'Künstler'), Tab(text: 'Alben'), ], ), ), body: Column( children: [ if (lib.permissionDenied) MaterialBanner( backgroundColor: Colors.red.shade900, content: const Text('Zugriff auf Musik verweigert. ' 'Bitte in den Einstellungen erlauben.'), actions: [ TextButton( onPressed: openMusicPermissionSettings, child: const Text('Einstellungen'), ), ], ), if (lib.scanError != null) MaterialBanner( backgroundColor: Colors.red.shade900, content: Text(lib.scanError!), actions: [ TextButton( onPressed: lib.dismissScanError, child: const Text('Verwerfen'), ), ], ), if (lib.scanning) Padding( padding: const EdgeInsets.all(12), child: Column( children: [ const LinearProgressIndicator(), const SizedBox(height: 6), Text( 'Scanne … ${lib.scanDone}' '${lib.scanTotal > 0 ? ' / ${lib.scanTotal}' : ''}', style: const TextStyle(color: Colors.white54, fontSize: 12), ), ], ), ), const Expanded( child: TabBarView( children: [ _AllSongsTab(), ArtistListScreen(), AlbumListScreen(), ], ), ), ], ), ), ); } } /// "Alle"-Tab: zuletzt hinzugefügt + vollständige Songliste (unverändertes /// Verhalten aus der Zeit vor der Künstler-/Alben-Aufteilung). class _AllSongsTab extends StatelessWidget { const _AllSongsTab(); @override Widget build(BuildContext context) { final db = context.read(); final lib = context.watch(); return Column( children: [ StreamBuilder>( stream: db.watchRecent(limit: 10), builder: (context, snapshot) { final recent = snapshot.data ?? const []; if (recent.isEmpty || lib.scanning) return const SizedBox.shrink(); return _RecentlyAdded(songs: recent); }, ), Expanded( child: StreamBuilder>( stream: db.watchSongs(), builder: (context, snapshot) { if (snapshot.hasError) { return Center( child: Text('Fehler: ${snapshot.error}', style: const TextStyle(color: Colors.white54)), ); } final songs = snapshot.data ?? const []; if (songs.isEmpty && !lib.scanning) { return const _Empty(); } return SongList(songs); }, ), ), ], ); } } /// Horizontal scrollende Leiste mit den zuletzt hinzugefügten Songs. class _RecentlyAdded extends StatelessWidget { const _RecentlyAdded({required this.songs}); final List songs; @override Widget build(BuildContext context) { final handler = context.read(); return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Padding( padding: EdgeInsets.fromLTRB(16, 8, 16, 8), child: Text('Zuletzt hinzugefügt', style: TextStyle(fontSize: 18, fontWeight: FontWeight.w600)), ), SizedBox( height: 140, child: ListView.builder( scrollDirection: Axis.horizontal, padding: const EdgeInsets.symmetric(horizontal: 16), itemCount: songs.length, itemBuilder: (context, i) { final s = songs[i]; return Padding( padding: const EdgeInsets.only(right: 12), child: SizedBox( width: 96, child: InkWell( onTap: () async { try { await playSongs(handler, songs, i); } catch (e) { if (context.mounted) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text('Wiedergabe fehlgeschlagen: $e')), ); } } }, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ CoverImage( artUri: s.coverPath != null ? Uri.file(s.coverPath!) : null, size: 96, radius: 8, ), const SizedBox(height: 4), Text( s.title, maxLines: 1, overflow: TextOverflow.ellipsis, style: const TextStyle(fontSize: 12), ), ], ), ), ), ); }, ), ), ], ); } } class _Empty extends StatelessWidget { const _Empty(); @override Widget build(BuildContext context) { final lib = context.read(); return Center( child: Column( mainAxisSize: MainAxisSize.min, children: [ const Icon(Icons.library_music, size: 64, color: Colors.white24), const SizedBox(height: 12), const Text('Noch keine Musik', style: TextStyle(color: Colors.white54)), const SizedBox(height: 16), FilledButton.icon( icon: const Icon(Icons.create_new_folder_outlined), label: Text(addMusicLabel), onPressed: lib.pickFolderAndScan, ), ], ), ); } }