From acc939c581e072a36a8264b4ade359a0e2262199 Mon Sep 17 00:00:00 2001 From: Kingkor Roy Tirtho Date: Wed, 6 Jul 2022 02:31:19 +0600 Subject: [PATCH] Lyric delay adjust support added theme adjusted for dialogs --- .../Lyrics/LyricDelayAdjustDialog.dart | 74 +++++++++++++++++++ lib/components/Lyrics/SyncedLyrics.dart | 70 ++++++++++++++---- lib/hooks/useSyncedLyrics.dart | 8 +- lib/themes/dark-theme.dart | 1 + 4 files changed, 137 insertions(+), 16 deletions(-) create mode 100644 lib/components/Lyrics/LyricDelayAdjustDialog.dart diff --git a/lib/components/Lyrics/LyricDelayAdjustDialog.dart b/lib/components/Lyrics/LyricDelayAdjustDialog.dart new file mode 100644 index 00000000..222efa01 --- /dev/null +++ b/lib/components/Lyrics/LyricDelayAdjustDialog.dart @@ -0,0 +1,74 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_hooks/flutter_hooks.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:spotube/components/Lyrics/SyncedLyrics.dart'; + +class LyricDelayAdjustDialog extends HookConsumerWidget { + const LyricDelayAdjustDialog({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context, ref) { + final controller = useTextEditingController( + text: ref.read(lyricDelayState).inMilliseconds.toString(), + ); + + double getValue() => + double.tryParse(controller.text.replaceAll("ms", "")) ?? 0; + + return AlertDialog( + title: const Center(child: Text("Adjust Lyrics Delay")), + actions: [ + ElevatedButton( + child: const Text("Cancel"), + onPressed: () { + Navigator.of(context).pop(); + }, + ), + ElevatedButton( + child: const Text("Done"), + onPressed: () { + Navigator.of(context).pop( + Duration( + milliseconds: getValue().toInt(), + ), + ); + }, + ) + ], + content: Row( + mainAxisSize: MainAxisSize.min, + children: [ + IconButton( + icon: const Icon(Icons.remove_rounded), + onPressed: () { + controller.text = "${getValue() - 25}ms"; + }, + ), + Flexible( + child: TextField( + keyboardType: TextInputType.number, + controller: controller, + decoration: const InputDecoration( + isDense: true, + hintText: "Delay in milliseconds", + ), + onSubmitted: (_) { + Navigator.of(context).pop( + Duration( + milliseconds: getValue().toInt(), + ), + ); + }, + ), + ), + IconButton( + icon: const Icon(Icons.add_rounded), + onPressed: () { + controller.text = "${getValue() + 25}ms"; + }, + ), + ], + ), + ); + } +} diff --git a/lib/components/Lyrics/SyncedLyrics.dart b/lib/components/Lyrics/SyncedLyrics.dart index 3ecfb3d5..0276f59d 100644 --- a/lib/components/Lyrics/SyncedLyrics.dart +++ b/lib/components/Lyrics/SyncedLyrics.dart @@ -7,6 +7,7 @@ import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:palette_generator/palette_generator.dart'; import 'package:spotify/spotify.dart'; import 'package:spotube/components/LoaderShimmers/ShimmerLyrics.dart'; +import 'package:spotube/components/Lyrics/LyricDelayAdjustDialog.dart'; import 'package:spotube/components/Lyrics/Lyrics.dart'; import 'package:spotube/components/Shared/PageWindowTitleBar.dart'; import 'package:spotube/components/Shared/SpotubeMarqueeText.dart'; @@ -21,12 +22,19 @@ import 'package:spotube/provider/Playback.dart'; import 'package:scroll_to_index/scroll_to_index.dart'; import 'package:spotube/provider/SpotifyRequests.dart'; +final lyricDelayState = StateProvider( + (ref) { + return Duration.zero; + }, +); + class SyncedLyrics extends HookConsumerWidget { const SyncedLyrics({Key? key}) : super(key: key); @override Widget build(BuildContext context, ref) { final timedLyricsSnapshot = ref.watch(rentanadviserLyricsQuery); + final lyricDelay = ref.watch(lyricDelayState); Playback playback = ref.watch(playbackProvider); final breakpoint = useBreakpoints(); @@ -43,12 +51,15 @@ class SyncedLyrics extends HookConsumerWidget { [lyricValue], ); - final currentTime = useSyncedLyrics(ref, lyricsMap); + final currentTime = useSyncedLyrics(ref, lyricsMap, lyricDelay); final textTheme = Theme.of(context).textTheme; useEffect(() { controller.scrollToIndex(0); + WidgetsBinding.instance.addPostFrameCallback((_) { + ref.read(lyricDelayState.notifier).state = Duration.zero; + }); failed.value = false; return null; }, [playback.track]); @@ -130,7 +141,7 @@ class SyncedLyrics extends HookConsumerWidget { ), ), child: BackdropFilter( - filter: ImageFilter.blur(sigmaX: 15, sigmaY: 15), + filter: ImageFilter.blur(sigmaX: 5, sigmaY: 5), child: Container( color: palette.color.withOpacity(.7), child: SafeArea( @@ -141,20 +152,50 @@ class SyncedLyrics extends HookConsumerWidget { PageWindowTitleBar( foregroundColor: palette.bodyTextColor, ), - Center( - child: SizedBox( + SizedBox( height: breakpoint >= Breakpoints.md ? 50 : 30, - child: playback.track?.name != null && - playback.track!.name!.length > 29 - ? SpotubeMarqueeText( - text: playback.track?.name ?? "Not Playing", - style: headlineTextStyle, - ) - : Text( - playback.track?.name ?? "Not Playing", - style: headlineTextStyle, + child: Material( + type: MaterialType.transparency, + child: Stack( + children: [ + Center( + child: playback.track?.name != null && + playback.track!.name!.length > 29 + ? SpotubeMarqueeText( + text: playback.track?.name ?? + "Not Playing", + style: headlineTextStyle, + ) + : Text( + playback.track?.name ?? "Not Playing", + style: headlineTextStyle, + ), ), - )), + Positioned.fill( + child: Align( + alignment: Alignment.centerRight, + child: IconButton( + tooltip: "Lyrics Delay", + icon: const Icon(Icons.av_timer_rounded), + onPressed: () async { + final delay = await showDialog( + context: context, + builder: (context) => + const LyricDelayAdjustDialog(), + ); + if (delay != null) { + ref + .read(lyricDelayState.notifier) + .state = delay; + } + }, + ), + ), + ), + ], + ), + ), + ), Center( child: Text( artistsToString( @@ -173,6 +214,7 @@ class SyncedLyrics extends HookConsumerWidget { final lyricSlice = lyricValue.lyrics[index]; final isActive = lyricSlice.time.inSeconds == currentTime; + if (isActive) { controller.scrollToIndex( index, diff --git a/lib/hooks/useSyncedLyrics.dart b/lib/hooks/useSyncedLyrics.dart index 5f18014c..26a5291a 100644 --- a/lib/hooks/useSyncedLyrics.dart +++ b/lib/hooks/useSyncedLyrics.dart @@ -2,7 +2,11 @@ import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:spotube/provider/Playback.dart'; -useSyncedLyrics(WidgetRef ref, Map lyricsMap) { +int useSyncedLyrics( + WidgetRef ref, + Map lyricsMap, + Duration delay, +) { final player = ref.watch(playbackProvider.select( (value) => (value.player), )); @@ -19,5 +23,5 @@ useSyncedLyrics(WidgetRef ref, Map lyricsMap) { return () => lol.cancel(); }, [lyricsMap]); - return currentTime.value; + return (Duration(seconds: currentTime.value) + delay).inSeconds; } diff --git a/lib/themes/dark-theme.dart b/lib/themes/dark-theme.dart index 4bbaf3ed..7533996e 100644 --- a/lib/themes/dark-theme.dart +++ b/lib/themes/dark-theme.dart @@ -69,6 +69,7 @@ ThemeData darkTheme({ borderRadius: BorderRadius.circular(18.0), ), ), + dialogTheme: DialogTheme(backgroundColor: backgroundMaterialColor[900]), cardColor: backgroundMaterialColor[800], canvasColor: backgroundMaterialColor[900], );