first commit
This commit is contained in:
109
lib/features/music/presentation/widgets/track_card.dart
Normal file
109
lib/features/music/presentation/widgets/track_card.dart
Normal file
@@ -0,0 +1,109 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user