import 'package:flutter/material.dart'; import 'package:flutter_lucide/flutter_lucide.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; import '../models/playlist.dart'; import '../shared/widgets/main_app_bar_actions.dart'; import '../shared/widgets/server_image.dart'; import '../theme/theme_extension.dart'; import 'playlists_provider.dart'; class PlaylistsListScreen extends ConsumerWidget { const PlaylistsListScreen({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { final fs = Theme.of(context).extension()!; // "all" returns user-created + system mixes. Most useful default // on mobile where the user wants to see for-you/discover alongside // their own playlists in one tap. final list = ref.watch(playlistsListProvider('all')); return Scaffold( backgroundColor: fs.obsidian, appBar: AppBar( backgroundColor: fs.obsidian, elevation: 0, title: Text('Playlists', style: TextStyle(color: fs.parchment)), actions: const [MainAppBarActions(currentRoute: '/playlists')], ), body: list.when( loading: () => const Center(child: CircularProgressIndicator()), error: (e, _) => Center( child: Text('$e', style: TextStyle(color: fs.error)), ), data: (lists) { final items = lists.all; if (items.isEmpty) { return Center( child: Text( 'No playlists yet.', style: TextStyle(color: fs.ash), ), ); } return RefreshIndicator( onRefresh: () async => ref.refresh(playlistsListProvider('all').future), child: ListView.separated( itemCount: items.length, separatorBuilder: (_, __) => Divider(height: 1, color: fs.iron), itemBuilder: (ctx, i) { final p = items[i]; return _PlaylistTile( playlist: p, onTap: () => ctx.push('/playlists/${p.id}', extra: p), ); }, ), ); }, ), ); } } class _PlaylistTile extends StatelessWidget { const _PlaylistTile({required this.playlist, required this.onTap}); final Playlist playlist; final VoidCallback onTap; @override Widget build(BuildContext context) { final fs = Theme.of(context).extension()!; return InkWell( onTap: onTap, child: Padding( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), child: Row(children: [ ClipRRect( borderRadius: BorderRadius.circular(6), child: Container( width: 56, height: 56, color: fs.slate, child: playlist.coverUrl.isEmpty ? Icon(LucideIcons.list_music, color: fs.ash) : ServerImage( url: playlist.coverUrl, fit: BoxFit.cover, fallback: Icon(LucideIcons.list_music, color: fs.ash), ), ), ), const SizedBox(width: 12), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row(children: [ Flexible( child: Text( playlist.name, maxLines: 1, overflow: TextOverflow.ellipsis, style: TextStyle(color: fs.parchment, fontSize: 15), ), ), if (playlist.isSystem) ...[ const SizedBox(width: 8), Container( padding: const EdgeInsets.symmetric( horizontal: 6, vertical: 2), decoration: BoxDecoration( color: fs.iron, borderRadius: BorderRadius.circular(4), ), child: Text( playlist.systemVariant!.replaceAll('_', ' '), style: TextStyle(color: fs.accent, fontSize: 11), ), ), ], ]), const SizedBox(height: 2), Text( '${playlist.trackCount} ${playlist.trackCount == 1 ? "track" : "tracks"}', style: TextStyle(color: fs.ash, fontSize: 12), ), ], ), ), Icon(LucideIcons.chevron_right, color: fs.ash), ]), ), ); } }