import 'dart:ui'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:go_router/go_router.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:spotube/collections/spotube_icons.dart'; import 'package:spotube/components/player/player_track_details.dart'; import 'package:spotube/collections/intents.dart'; import 'package:spotube/hooks/use_progress.dart'; import 'package:spotube/provider/playlist_queue_provider.dart'; import 'package:spotube/utils/service_utils.dart'; class PlayerOverlay extends HookConsumerWidget { final String albumArt; const PlayerOverlay({ required this.albumArt, Key? key, }) : super(key: key); @override Widget build(BuildContext context, ref) { final canShow = ref.watch( PlaylistQueueNotifier.provider.select((s) => s != null), ); final playlistNotifier = ref.watch(PlaylistQueueNotifier.notifier); final playlist = ref.watch(PlaylistQueueNotifier.provider); final playing = useStream(PlaylistQueueNotifier.playing).data ?? PlaylistQueueNotifier.isPlaying; final theme = Theme.of(context); final textColor = theme.colorScheme.primary; const radius = BorderRadius.only( topLeft: Radius.circular(10), topRight: Radius.circular(10), ); return GestureDetector( onVerticalDragEnd: (details) { int sensitivity = 8; if (details.primaryVelocity != null && details.primaryVelocity! < -sensitivity) { ServiceUtils.navigate(context, "/player"); } }, child: ClipRRect( borderRadius: radius, child: BackdropFilter( filter: ImageFilter.blur(sigmaX: 15, sigmaY: 15), child: AnimatedContainer( duration: const Duration(milliseconds: 250), width: MediaQuery.of(context).size.width, height: canShow ? 53 : 0, decoration: BoxDecoration( color: theme.colorScheme.secondaryContainer.withOpacity(.8), borderRadius: radius, ), child: AnimatedOpacity( duration: const Duration(milliseconds: 250), opacity: canShow ? 1 : 0, child: Material( type: MaterialType.transparency, child: Column( mainAxisSize: MainAxisSize.min, children: [ HookBuilder( builder: (context) { final progress = useProgress(ref); // animated return TweenAnimationBuilder( duration: const Duration(milliseconds: 250), tween: Tween(begin: 0, end: progress.item1), builder: (context, value, child) { return LinearProgressIndicator( value: value, minHeight: 2, backgroundColor: Colors.transparent, valueColor: AlwaysStoppedAnimation( theme.colorScheme.primary, ), ); }, ); }, ), Expanded( child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Expanded( child: MouseRegion( cursor: SystemMouseCursors.click, child: GestureDetector( onTap: () => GoRouter.of(context).push("/player"), child: PlayerTrackDetails( albumArt: albumArt, color: textColor, ), ), ), ), Row( children: [ IconButton( icon: Icon( SpotubeIcons.skipBack, color: textColor, ), onPressed: playlistNotifier.previous, ), Consumer( builder: (context, ref, _) { return IconButton( icon: playlist?.isLoading == true ? const SizedBox( height: 20, width: 20, child: CircularProgressIndicator(), ) : Icon( playing ? SpotubeIcons.pause : SpotubeIcons.play, color: textColor, ), onPressed: Actions.handler( context, PlayPauseIntent(ref), ), ); }, ), IconButton( icon: Icon( SpotubeIcons.skipForward, color: textColor, ), onPressed: playlistNotifier.next, ), ], ), ], ), ), ], ), ), ), ), ), ), ); } }