import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../state/providers.dart'; import '../theme/tokens.dart'; import '../widgets/hairline_panel.dart'; import 'browser_screen.dart'; /// Home tab — Recently Played (album-art strip), Recent Tracks, and Rediscover, /// all derived from the local play history (mirrors Ratune's home tab). class HomeScreen extends ConsumerWidget { const HomeScreen({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { final client = ref.watch(subsonicClientProvider); final recentAlbums = ref.watch(recentAlbumsProvider); final recentSongs = ref.watch(recentSongsProvider); final rediscover = ref.watch(rediscoverProvider); return ListView( padding: const EdgeInsets.fromLTRB( RatuneSpacing.lg, RatuneSpacing.xl, RatuneSpacing.lg, RatuneSpacing.lg, ), children: [ HairlinePanel( title: 'Recently Played', child: SizedBox( height: 120, child: recentAlbums.isEmpty ? const _Empty('No listening history yet.') : ListView.separated( scrollDirection: Axis.horizontal, itemCount: recentAlbums.length, separatorBuilder: (_, _) => const SizedBox(width: RatuneSpacing.md), itemBuilder: (_, i) { final rec = recentAlbums[i]; final art = (client != null && rec.coverArt != null) ? client.coverArtUri(rec.coverArt!, size: 240).toString() : null; return GestureDetector( onTap: rec.albumId == null ? null : () => Navigator.of(context).push( MaterialPageRoute( builder: (_) => AlbumScreen(id: rec.albumId!), ), ), child: SizedBox( width: 120, child: ColoredBox( color: RatuneColors.surface, child: art != null ? Image.network(art, fit: BoxFit.cover, gaplessPlayback: true) : const Icon(Icons.album_outlined, color: RatuneColors.dimmed), ), ), ); }, ), ), ), const SizedBox(height: RatuneSpacing.xl), HairlinePanel( title: 'Recent Tracks', padding: const EdgeInsets.symmetric(vertical: RatuneSpacing.md), child: recentSongs.isEmpty ? const Padding( padding: EdgeInsets.all(RatuneSpacing.lg), child: _Empty('Nothing played recently.'), ) : Column( children: [ for (final rec in recentSongs.take(8)) BrowseRow( title: rec.title, trailing: rec.artist, onTap: () => ref .read(playbackProvider.notifier) .playSongs([rec.toSong()]), onPlayNext: () => ref .read(playbackProvider.notifier) .playNext(rec.toSong()), onAddToQueue: () => ref .read(playbackProvider.notifier) .addToQueue(rec.toSong()), ), ], ), ), const SizedBox(height: RatuneSpacing.xl), HairlinePanel( title: 'Rediscover', padding: const EdgeInsets.symmetric(vertical: RatuneSpacing.md), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ if (rediscover.isEmpty) const Padding( padding: EdgeInsets.all(RatuneSpacing.lg), child: _Empty('Listen to more music to unlock suggestions.'), ) else for (final a in rediscover) BrowseRow( title: a.name, onTap: () => Navigator.of(context).push( MaterialPageRoute( builder: (_) => ArtistScreen(id: a.artistId), ), ), ), InkWell( onTap: () => ref.read(rediscoverSeedProvider.notifier).state++, child: const Padding( padding: EdgeInsets.symmetric( horizontal: RatuneSpacing.lg, vertical: RatuneSpacing.md, ), child: Text('↻ re-roll', style: TextStyle(color: RatuneColors.dimmed)), ), ), ], ), ), ], ); } } class _Empty extends StatelessWidget { const _Empty(this.message); final String message; @override Widget build(BuildContext context) => Align( alignment: Alignment.centerLeft, child: Text(message, style: const TextStyle(color: RatuneColors.dimmed)), ); }