/// Artist Track Tile - Track item for artist details library; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../../../../domain/entities/track.dart'; import '../../../../core/theme/colors.dart'; import '../../providers/music_provider.dart'; import '../common/cached_network_image_with_fallback.dart'; class ArtistTrackTile extends ConsumerWidget { final Track track; final int index; final VoidCallback? onTap; const ArtistTrackTile({ required this.track, required this.index, this.onTap, super.key, }); @override Widget build(BuildContext context, WidgetRef ref) { final playerState = ref.watch(playerProvider); final isCurrentlyPlaying = playerState.currentTrack?.id == track.id && playerState.isPlaying; return Container( margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 4), decoration: BoxDecoration( color: AppColors.surface.withOpacity(isCurrentlyPlaying ? 0.8 : 0.4), borderRadius: BorderRadius.circular(12), border: Border.all( color: isCurrentlyPlaying ? AppColors.cyan.withOpacity(0.5) : AppColors.cyan.withOpacity(0.1), width: isCurrentlyPlaying ? 2 : 1, ), boxShadow: isCurrentlyPlaying ? AppColors.cyanGlow : null, ), child: Material( color: Colors.transparent, child: InkWell( onTap: onTap, borderRadius: BorderRadius.circular(12), child: Padding( padding: const EdgeInsets.all(12), child: Row( children: [ // Track number or playing indicator _buildTrackIndicator(isCurrentlyPlaying), const SizedBox(width: 16), // Album art _buildAlbumArt(), const SizedBox(width: 16), // Track info Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( track.title, style: TextStyle( color: isCurrentlyPlaying ? AppColors.cyan : AppColors.onBackground, fontWeight: FontWeight.w600, fontSize: 15, ), maxLines: 1, overflow: TextOverflow.ellipsis, ), if (track.album != null) ...[ const SizedBox(height: 4), Text( track.album!.title, style: const TextStyle( color: AppColors.onSurfaceVariant, fontSize: 13, ), maxLines: 1, overflow: TextOverflow.ellipsis, ), ], ], ), ), // Play count if (track.playCount != null) Padding( padding: const EdgeInsets.only(right: 16), child: _buildPlayCount(), ), // Duration Text( track.formattedDuration, style: const TextStyle( color: AppColors.muted, fontSize: 13, ), ), const SizedBox(width: 12), // Add to queue button _buildAddToQueueButton(ref), ], ), ), ), ), ); } Widget _buildTrackIndicator(bool isPlaying) { return SizedBox( width: 24, child: isPlaying ? _buildPlayingIndicator() : Text( '${index + 1}', style: const TextStyle( color: AppColors.muted, fontSize: 14, fontWeight: FontWeight.w500, ), textAlign: TextAlign.center, ), ); } Widget _buildPlayingIndicator() { return SizedBox( width: 24, child: Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [ _buildBar(0.6), const SizedBox(height: 2), _buildBar(1.0), const SizedBox(height: 2), _buildBar(0.4), ], ), ); } Widget _buildBar(double height) { return AnimatedContainer( duration: const Duration(milliseconds: 300), width: 3, height: 8 * height, decoration: BoxDecoration( color: AppColors.cyan, borderRadius: BorderRadius.circular(2), ), ); } Widget _buildAlbumArt() { return ClipRRect( borderRadius: BorderRadius.circular(8), child: SizedBox( width: 48, height: 48, child: CachedNetworkImageWithFallback( imageUrl: track.imageUrl, fallbackIcon: Icons.album, progressColor: AppColors.cyan, fit: BoxFit.cover, ), ), ); } Widget _buildPlayCount() { final playCount = track.playCount!; String countText; if (playCount >= 1000000) { countText = '${(playCount / 1000000).toStringAsFixed(1)}M'; } else if (playCount >= 1000) { countText = '${(playCount / 1000).toStringAsFixed(1)}K'; } else { countText = playCount.toString(); } return Row( mainAxisSize: MainAxisSize.min, children: [ const Icon( Icons.play_arrow, size: 16, color: AppColors.muted, ), const SizedBox(width: 4), Text( countText, style: const TextStyle( color: AppColors.muted, fontSize: 13, ), ), ], ); } Widget _buildAddToQueueButton(WidgetRef ref) { return IconButton( icon: const Icon( Icons.playlist_add, color: AppColors.muted, size: 20, ), onPressed: () { ref.read(playerProvider.notifier).addToQueue(track); ScaffoldMessenger.of(ref.context).showSnackBar( SnackBar( content: Text('${track.title} added to queue'), duration: const Duration(seconds: 2), backgroundColor: AppColors.surface, behavior: SnackBarBehavior.floating, ), ); }, tooltip: 'Add to queue', splashRadius: 20, ); } }