110 lines
3.7 KiB
Dart
110 lines
3.7 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|
import 'package:just_audio/just_audio.dart';
|
|
import '../../../../core/theme/app_colors.dart';
|
|
import '../../domain/models/track_model.dart';
|
|
import '../providers/music_providers.dart';
|
|
|
|
class TrackCard extends ConsumerWidget {
|
|
const TrackCard({
|
|
required this.track,
|
|
super.key,
|
|
});
|
|
|
|
final TrackModel track;
|
|
|
|
@override
|
|
Widget build(BuildContext context, WidgetRef ref) {
|
|
final theme = Theme.of(context);
|
|
final player = ref.watch(audioPlayerProvider);
|
|
final currentTrack = ref.watch(currentTrackProvider);
|
|
final isPlaying = ref.watch(isPlayingProvider).value ?? false;
|
|
final isCurrent = currentTrack?.id == track.id;
|
|
|
|
return Container(
|
|
decoration: BoxDecoration(
|
|
color: isCurrent ? AppColors.surfaceLight : Colors.transparent,
|
|
border: Border.all(color: isCurrent ? AppColors.neonRed : AppColors.border),
|
|
),
|
|
margin: const EdgeInsets.only(bottom: 12),
|
|
child: InkWell(
|
|
onTap: () => _handlePlay(ref, player),
|
|
child: Padding(
|
|
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
|
|
child: Row(
|
|
children: [
|
|
// Cover / Icon
|
|
Container(
|
|
width: 56,
|
|
height: 56,
|
|
color: AppColors.black,
|
|
child: Center(
|
|
child: Icon(
|
|
isCurrent && isPlaying ? Icons.graphic_eq : Icons.music_note,
|
|
color: isCurrent ? AppColors.neonRed : AppColors.white,
|
|
size: 28,
|
|
),
|
|
),
|
|
),
|
|
const SizedBox(width: 16),
|
|
// Info
|
|
Expanded(
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text(
|
|
track.title.toUpperCase(),
|
|
style: theme.textTheme.titleLarge?.copyWith(fontSize: 16, letterSpacing: 1),
|
|
maxLines: 1,
|
|
overflow: TextOverflow.ellipsis,
|
|
),
|
|
const SizedBox(height: 4),
|
|
Text(
|
|
'${track.username.toUpperCase()} // ${track.genreTag.toUpperCase()}',
|
|
style: theme.textTheme.bodySmall?.copyWith(color: AppColors.grey, fontSize: 10),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
// Plays & Action
|
|
Column(
|
|
crossAxisAlignment: CrossAxisAlignment.end,
|
|
children: [
|
|
Text(
|
|
'${track.plays} PLAYS',
|
|
style: theme.textTheme.bodySmall?.copyWith(fontSize: 9, fontWeight: FontWeight.bold),
|
|
),
|
|
const SizedBox(height: 4),
|
|
Icon(
|
|
isCurrent && isPlaying ? Icons.pause_circle_filled : Icons.play_circle_filled,
|
|
color: AppColors.white,
|
|
size: 32,
|
|
),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
Future<void> _handlePlay(WidgetRef ref, AudioPlayer player) async {
|
|
final currentTrack = ref.read(currentTrackProvider);
|
|
|
|
if (currentTrack?.id == track.id) {
|
|
if (player.playing) {
|
|
await player.pause();
|
|
} else {
|
|
await player.play();
|
|
}
|
|
} else {
|
|
ref.read(currentTrackProvider.notifier).state = track;
|
|
await player.setUrl(track.audioUrl);
|
|
await player.play();
|
|
// Increment play count
|
|
ref.read(musicControllerProvider.notifier).incrementPlays(track.id);
|
|
}
|
|
}
|
|
}
|