feat(player): replace bg blur with gradient, proper fg color and align title and artist name

This commit is contained in:
Kingkor Roy Tirtho 2023-04-06 11:13:14 +06:00
parent 36396b7583
commit 159f03e7ca
7 changed files with 158 additions and 136 deletions

View File

@ -11,10 +11,10 @@ import 'package:spotube/provider/playlist_queue_provider.dart';
import 'package:spotube/utils/primitive_utils.dart'; import 'package:spotube/utils/primitive_utils.dart';
class PlayerControls extends HookConsumerWidget { class PlayerControls extends HookConsumerWidget {
final Color? iconColor; final Color? color;
PlayerControls({ PlayerControls({
this.iconColor, this.color,
Key? key, Key? key,
}) : super(key: key); }) : super(key: key);
@ -109,23 +109,26 @@ class PlayerControls extends HookConsumerWidget {
), ),
); );
}, },
activeColor: iconColor, activeColor: color,
inactiveColor: color?.withOpacity(0.15),
), ),
), ),
Padding( Padding(
padding: const EdgeInsets.symmetric( padding: const EdgeInsets.symmetric(
horizontal: 8.0, horizontal: 8.0,
), ),
child: DefaultTextStyle(
style:
theme.textTheme.bodySmall!.copyWith(color: color),
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
Text( Text("$currentMinutes:$currentSeconds"),
"$currentMinutes:$currentSeconds",
),
Text("$totalMinutes:$totalSeconds"), Text("$totalMinutes:$totalSeconds"),
], ],
), ),
), ),
),
], ],
); );
}, },
@ -157,7 +160,7 @@ class PlayerControls extends HookConsumerWidget {
tooltip: "Previous track", tooltip: "Previous track",
icon: Icon( icon: Icon(
SpotubeIcons.skipBack, SpotubeIcons.skipBack,
color: iconColor, color: color,
), ),
onPressed: playlistNotifier.previous, onPressed: playlistNotifier.previous,
), ),
@ -171,7 +174,7 @@ class PlayerControls extends HookConsumerWidget {
) )
: Icon( : Icon(
playing ? SpotubeIcons.pause : SpotubeIcons.play, playing ? SpotubeIcons.pause : SpotubeIcons.play,
color: iconColor, color: color,
), ),
onPressed: Actions.handler<PlayPauseIntent>( onPressed: Actions.handler<PlayPauseIntent>(
context, context,
@ -182,7 +185,7 @@ class PlayerControls extends HookConsumerWidget {
tooltip: "Next track", tooltip: "Next track",
icon: Icon( icon: Icon(
SpotubeIcons.skipForward, SpotubeIcons.skipForward,
color: iconColor, color: color,
), ),
onPressed: playlistNotifier.next, onPressed: playlistNotifier.next,
), ),

View File

@ -144,10 +144,7 @@ class PlaylistHeartButton extends HookConsumerWidget {
), ),
[playlist.images]); [playlist.images]);
final color = usePaletteGenerator( final color = usePaletteGenerator(titleImage).dominantColor;
context,
titleImage,
).dominantColor;
if (me.isLoading || !me.hasData) { if (me.isLoading || !me.hasData) {
return const CircularProgressIndicator(); return const CircularProgressIndicator();

View File

@ -68,7 +68,7 @@ class _PageWindowTitleBarState extends State<PageWindowTitleBar> {
automaticallyImplyLeading: widget.automaticallyImplyLeading, automaticallyImplyLeading: widget.automaticallyImplyLeading,
actions: [ actions: [
...?widget.actions, ...?widget.actions,
const WindowTitleBarButtons(), WindowTitleBarButtons(foregroundColor: widget.foregroundColor),
], ],
backgroundColor: widget.backgroundColor, backgroundColor: widget.backgroundColor,
foregroundColor: widget.foregroundColor, foregroundColor: widget.foregroundColor,
@ -86,7 +86,11 @@ class _PageWindowTitleBarState extends State<PageWindowTitleBar> {
} }
class WindowTitleBarButtons extends HookWidget { class WindowTitleBarButtons extends HookWidget {
const WindowTitleBarButtons({Key? key}) : super(key: key); final Color? foregroundColor;
const WindowTitleBarButtons({
Key? key,
this.foregroundColor,
}) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -110,7 +114,7 @@ class WindowTitleBarButtons extends HookWidget {
final theme = Theme.of(context); final theme = Theme.of(context);
final colors = WindowButtonColors( final colors = WindowButtonColors(
normal: Colors.transparent, normal: Colors.transparent,
iconNormal: theme.colorScheme.onBackground, iconNormal: foregroundColor ?? theme.colorScheme.onBackground,
mouseOver: theme.colorScheme.onBackground.withOpacity(0.1), mouseOver: theme.colorScheme.onBackground.withOpacity(0.1),
mouseDown: theme.colorScheme.onBackground.withOpacity(0.2), mouseDown: theme.colorScheme.onBackground.withOpacity(0.2),
iconMouseOver: theme.colorScheme.onBackground, iconMouseOver: theme.colorScheme.onBackground,
@ -119,7 +123,7 @@ class WindowTitleBarButtons extends HookWidget {
final closeColors = WindowButtonColors( final closeColors = WindowButtonColors(
normal: Colors.transparent, normal: Colors.transparent,
iconNormal: theme.colorScheme.onBackground, iconNormal: foregroundColor ?? theme.colorScheme.onBackground,
mouseOver: Colors.red, mouseOver: Colors.red,
mouseDown: Colors.red[800]!, mouseDown: Colors.red[800]!,
iconMouseOver: Colors.white, iconMouseOver: Colors.white,

View File

@ -66,10 +66,7 @@ class TrackCollectionView<T> extends HookConsumerWidget {
Widget build(BuildContext context, ref) { Widget build(BuildContext context, ref) {
final theme = Theme.of(context); final theme = Theme.of(context);
final auth = ref.watch(AuthenticationNotifier.provider); final auth = ref.watch(AuthenticationNotifier.provider);
final color = usePaletteGenerator( final color = usePaletteGenerator(titleImage).dominantColor;
context,
titleImage,
).dominantColor;
final List<Widget> buttons = [ final List<Widget> buttons = [
if (showShare) if (showShare)

View File

@ -12,6 +12,7 @@ final _paletteColorState = StateProvider<PaletteColor>(
PaletteColor usePaletteColor(String imageUrl, WidgetRef ref) { PaletteColor usePaletteColor(String imageUrl, WidgetRef ref) {
final context = useContext(); final context = useContext();
final theme = Theme.of(context);
final paletteColor = ref.watch(_paletteColorState); final paletteColor = ref.watch(_paletteColorState);
final mounted = useIsMounted(); final mounted = useIsMounted();
@ -25,7 +26,7 @@ PaletteColor usePaletteColor(String imageUrl, WidgetRef ref) {
), ),
); );
if (!mounted()) return; if (!mounted()) return;
final color = Theme.of(context).brightness == Brightness.light final color = theme.brightness == Brightness.light
? palette.lightMutedColor ?? palette.lightVibrantColor ? palette.lightMutedColor ?? palette.lightVibrantColor
: palette.darkMutedColor ?? palette.darkVibrantColor; : palette.darkMutedColor ?? palette.darkVibrantColor;
if (color != null) { if (color != null) {
@ -38,10 +39,7 @@ PaletteColor usePaletteColor(String imageUrl, WidgetRef ref) {
return paletteColor; return paletteColor;
} }
PaletteGenerator usePaletteGenerator( PaletteGenerator usePaletteGenerator(String imageUrl) {
BuildContext context,
String imageUrl,
) {
final palette = useState(PaletteGenerator.fromColors([])); final palette = useState(PaletteGenerator.fromColors([]));
final mounted = useIsMounted(); final mounted = useIsMounted();

View File

@ -1,13 +1,11 @@
import 'dart:ui';
import 'package:auto_size_text/auto_size_text.dart'; import 'package:auto_size_text/auto_size_text.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:palette_generator/palette_generator.dart';
import 'package:spotify/spotify.dart'; import 'package:spotify/spotify.dart';
import 'package:spotube/collections/assets.gen.dart';
import 'package:spotube/collections/spotube_icons.dart'; import 'package:spotube/collections/spotube_icons.dart';
import 'package:spotube/components/player/player_actions.dart'; import 'package:spotube/components/player/player_actions.dart';
import 'package:spotube/components/player/player_controls.dart'; import 'package:spotube/components/player/player_controls.dart';
@ -56,40 +54,64 @@ class PlayerView extends HookConsumerWidget {
[currentTrack?.album?.images], [currentTrack?.album?.images],
); );
final PaletteColor paletteColor = usePaletteColor(albumArt, ref); final palette = usePaletteGenerator(albumArt);
final bgColor = palette.dominantColor?.color ?? theme.colorScheme.primary;
final titleTextColor = palette.dominantColor?.titleTextColor;
final bodyTextColor = palette.dominantColor?.bodyTextColor;
useCustomStatusBarColor( useCustomStatusBarColor(
paletteColor.color, bgColor,
GoRouter.of(context).location == "/player", GoRouter.of(context).location == "/player",
noSetBGColor: true, noSetBGColor: true,
); );
return Scaffold( return IconTheme(
data: theme.iconTheme.copyWith(color: bodyTextColor),
child: Scaffold(
appBar: PageWindowTitleBar( appBar: PageWindowTitleBar(
backgroundColor: Colors.transparent, backgroundColor: Colors.transparent,
foregroundColor: paletteColor.titleTextColor, foregroundColor: titleTextColor,
toolbarOpacity: 1, toolbarOpacity: 1,
leading: BackButton(color: paletteColor.titleTextColor), leading: const BackButton(),
), ),
extendBodyBehindAppBar: true, extendBodyBehindAppBar: true,
body: DecoratedBox( body: Container(
decoration: BoxDecoration( decoration: BoxDecoration(
image: DecorationImage( color: palette.dominantColor?.color,
image: UniversalImage.imageProvider(albumArt), gradient: LinearGradient(
fit: BoxFit.cover, colors: [
palette.dominantColor?.color ?? theme.colorScheme.primary,
palette.mutedColor?.color ?? theme.colorScheme.secondary,
],
transform: const GradientRotation(0.5),
), ),
), ),
child: BackdropFilter( alignment: Alignment.center,
filter: ImageFilter.blur(sigmaX: 15, sigmaY: 15), child: ConstrainedBox(
constraints: const BoxConstraints(maxWidth: 580),
child: SafeArea( child: SafeArea(
child: Padding( child: Padding(
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(8.0),
child: Column( child: Column(
children: [ children: [
ClipRRect( DecoratedBox(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
boxShadow: const [
BoxShadow(
color: Colors.black26,
spreadRadius: 2,
blurRadius: 10,
offset: Offset(0, 0),
),
],
),
child: ClipRRect(
borderRadius: BorderRadius.circular(20), borderRadius: BorderRadius.circular(20),
child: UniversalImage( child: UniversalImage(
path: albumArt, path: albumArt,
placeholder: Assets.albumPlaceholder.path,
),
), ),
), ),
const SizedBox(height: 10), const SizedBox(height: 10),
@ -103,7 +125,7 @@ class PlayerView extends HookConsumerWidget {
currentTrack?.name ?? "Not playing", currentTrack?.name ?? "Not playing",
style: TextStyle( style: TextStyle(
fontSize: 20, fontSize: 20,
color: paletteColor.titleTextColor, color: titleTextColor,
), ),
maxLines: 1, maxLines: 1,
textAlign: TextAlign.start, textAlign: TextAlign.start,
@ -115,7 +137,7 @@ class PlayerView extends HookConsumerWidget {
), ),
style: theme.textTheme.bodyMedium!.copyWith( style: theme.textTheme.bodyMedium!.copyWith(
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
color: paletteColor.bodyTextColor, color: bodyTextColor,
), ),
) )
else else
@ -123,7 +145,7 @@ class PlayerView extends HookConsumerWidget {
currentTrack?.artists ?? [], currentTrack?.artists ?? [],
textStyle: theme.textTheme.bodyMedium!.copyWith( textStyle: theme.textTheme.bodyMedium!.copyWith(
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
color: paletteColor.bodyTextColor, color: bodyTextColor,
), ),
onRouteChange: (route) { onRouteChange: (route) {
GoRouter.of(context).pop(); GoRouter.of(context).pop();
@ -134,7 +156,7 @@ class PlayerView extends HookConsumerWidget {
), ),
), ),
const SizedBox(height: 40), const SizedBox(height: 40),
PlayerControls(iconColor: paletteColor.bodyTextColor), PlayerControls(color: bodyTextColor),
const Spacer(), const Spacer(),
PlayerActions( PlayerActions(
mainAxisAlignment: MainAxisAlignment.spaceEvenly, mainAxisAlignment: MainAxisAlignment.spaceEvenly,
@ -175,6 +197,7 @@ class PlayerView extends HookConsumerWidget {
), ),
), ),
), ),
),
); );
} }
} }

View File

@ -1778,4 +1778,4 @@ packages:
version: "1.12.3" version: "1.12.3"
sdks: sdks:
dart: ">=2.19.2 <3.0.0" dart: ">=2.19.2 <3.0.0"
flutter: ">=3.7.0" flutter: ">=3.3.0"