feat: use provider in lyrics screen

This commit is contained in:
Kingkor Roy Tirtho 2024-03-17 14:45:09 +06:00
parent ac8121647b
commit 4d774b6ef1
3 changed files with 38 additions and 29 deletions

View File

@ -12,8 +12,8 @@ import 'package:spotube/extensions/constrains.dart';
import 'package:spotube/extensions/context.dart'; import 'package:spotube/extensions/context.dart';
import 'package:spotube/provider/proxy_playlist/proxy_playlist_provider.dart'; import 'package:spotube/provider/proxy_playlist/proxy_playlist_provider.dart';
import 'package:spotube/provider/spotify/spotify.dart';
import 'package:spotube/services/queries/queries.dart';
import 'package:spotube/utils/type_conversion_utils.dart'; import 'package:spotube/utils/type_conversion_utils.dart';
class PlainLyrics extends HookConsumerWidget { class PlainLyrics extends HookConsumerWidget {
@ -30,8 +30,7 @@ class PlainLyrics extends HookConsumerWidget {
@override @override
Widget build(BuildContext context, ref) { Widget build(BuildContext context, ref) {
final playlist = ref.watch(ProxyPlaylistNotifier.provider); final playlist = ref.watch(ProxyPlaylistNotifier.provider);
final lyricsQuery = final lyricsQuery = ref.watch(syncedLyricsProvider(playlist.activeTrack));
useQueries.lyrics.spotifySynced(ref, playlist.activeTrack);
final mediaQuery = MediaQuery.of(context); final mediaQuery = MediaQuery.of(context);
final textTheme = Theme.of(context).textTheme; final textTheme = Theme.of(context).textTheme;
@ -96,9 +95,9 @@ class PlainLyrics extends HookConsumerWidget {
} }
final lyrics = final lyrics =
lyricsQuery.data?.lyrics.mapIndexed((i, e) { lyricsQuery.value?.lyrics.mapIndexed((i, e) {
final next = final next =
lyricsQuery.data?.lyrics.elementAtOrNull(i + 1); lyricsQuery.value?.lyrics.elementAtOrNull(i + 1);
if (next != null && if (next != null &&
e.time - next.time > e.time - next.time >
const Duration(milliseconds: 700)) { const Duration(milliseconds: 700)) {

View File

@ -13,14 +13,12 @@ import 'package:spotube/hooks/controllers/use_auto_scroll_controller.dart';
import 'package:spotube/components/lyrics/use_synced_lyrics.dart'; import 'package:spotube/components/lyrics/use_synced_lyrics.dart';
import 'package:scroll_to_index/scroll_to_index.dart'; import 'package:scroll_to_index/scroll_to_index.dart';
import 'package:spotube/provider/proxy_playlist/proxy_playlist_provider.dart'; import 'package:spotube/provider/proxy_playlist/proxy_playlist_provider.dart';
import 'package:spotube/provider/spotify/spotify.dart';
import 'package:spotube/services/audio_player/audio_player.dart'; import 'package:spotube/services/audio_player/audio_player.dart';
import 'package:spotube/services/queries/queries.dart';
import 'package:spotube/utils/type_conversion_utils.dart'; import 'package:spotube/utils/type_conversion_utils.dart';
import 'package:stroke_text/stroke_text.dart'; import 'package:stroke_text/stroke_text.dart';
final _delay = StateProvider<int>((ref) => 0);
class SyncedLyrics extends HookConsumerWidget { class SyncedLyrics extends HookConsumerWidget {
final PaletteColor palette; final PaletteColor palette;
final bool? isModal; final bool? isModal;
@ -40,28 +38,18 @@ class SyncedLyrics extends HookConsumerWidget {
final mediaQuery = MediaQuery.of(context); final mediaQuery = MediaQuery.of(context);
final controller = useAutoScrollController(); final controller = useAutoScrollController();
final delay = ref.watch(_delay); final delay = ref.watch(syncedLyricsDelayProvider);
final timedLyricsQuery = final timedLyricsQuery =
useQueries.lyrics.spotifySynced(ref, playlist.activeTrack); ref.watch(syncedLyricsProvider(playlist.activeTrack));
final lyricValue = timedLyricsQuery.data; final lyricValue = timedLyricsQuery.asData?.value;
final isUnSyncLyric = useMemoized( final lyricsState = ref.watch(
() => lyricValue?.lyrics.every((l) => l.time == Duration.zero), syncedLyricsMapProvider(playlist.activeTrack),
[lyricValue],
); );
final currentTime =
final lyricsMap = useMemoized( useSyncedLyrics(ref, lyricsState.asData?.value.lyricsMap ?? {}, delay);
() =>
lyricValue?.lyrics
.map((lyric) => {lyric.time.inSeconds: lyric.text})
.reduce((accumulator, lyricSlice) =>
{...accumulator, ...lyricSlice}) ??
{},
[lyricValue],
);
final currentTime = useSyncedLyrics(ref, lyricsMap, delay);
final textZoomLevel = useState<int>(defaultTextZoom); final textZoomLevel = useState<int>(defaultTextZoom);
final textTheme = Theme.of(context).textTheme; final textTheme = Theme.of(context).textTheme;
@ -70,7 +58,7 @@ class SyncedLyrics extends HookConsumerWidget {
ProxyPlaylistNotifier.provider.select((s) => s.activeTrack), ProxyPlaylistNotifier.provider.select((s) => s.activeTrack),
(previous, next) { (previous, next) {
controller.scrollToIndex(0); controller.scrollToIndex(0);
ref.read(_delay.notifier).state = 0; ref.read(syncedLyricsDelayProvider.notifier).state = 0;
}, },
); );
@ -105,7 +93,7 @@ class SyncedLyrics extends HookConsumerWidget {
), ),
if (lyricValue != null && if (lyricValue != null &&
lyricValue.lyrics.isNotEmpty && lyricValue.lyrics.isNotEmpty &&
isUnSyncLyric == false) lyricsState.asData?.value.static != true)
Expanded( Expanded(
child: ListView.builder( child: ListView.builder(
controller: controller, controller: controller,
@ -202,7 +190,7 @@ class SyncedLyrics extends HookConsumerWidget {
), ),
const Gap(26), const Gap(26),
const Icon(SpotubeIcons.noLyrics, size: 60), const Icon(SpotubeIcons.noLyrics, size: 60),
] else if (isUnSyncLyric == true) ] else if (lyricsState.asData?.value.static == true)
Expanded( Expanded(
child: Center( child: Center(
child: RichText( child: RichText(
@ -235,7 +223,8 @@ class SyncedLyrics extends HookConsumerWidget {
final actions = [ final actions = [
ZoomControls( ZoomControls(
value: delay, value: delay,
onChanged: (value) => ref.read(_delay.notifier).state = value, onChanged: (value) =>
ref.read(syncedLyricsDelayProvider.notifier).state = value,
interval: 1, interval: 1,
unit: "s", unit: "s",
increaseIcon: const Icon(SpotubeIcons.add), increaseIcon: const Icon(SpotubeIcons.add),

View File

@ -54,3 +54,24 @@ class SyncedLyricsNotifier extends FamilyAsyncNotifier<SubtitleSimple, Track?>
@override @override
Map<String, dynamic> toJson(SubtitleSimple data) => data.toJson(); Map<String, dynamic> toJson(SubtitleSimple data) => data.toJson();
} }
final syncedLyricsDelayProvider = StateProvider<int>((ref) => 0);
final syncedLyricsProvider =
AsyncNotifierProviderFamily<SyncedLyricsNotifier, SubtitleSimple, Track?>(
() => SyncedLyricsNotifier(),
);
final syncedLyricsMapProvider =
FutureProvider.family((ref, Track? track) async {
final syncedLyrics = await ref.watch(syncedLyricsProvider(track).future);
final isStaticLyrics =
syncedLyrics.lyrics.every((l) => l.time == Duration.zero);
final lyricsMap = syncedLyrics.lyrics
.map((lyric) => {lyric.time.inSeconds: lyric.text})
.reduce((accumulator, lyricSlice) => {...accumulator, ...lyricSlice});
return (static: isStaticLyrics, lyricsMap: lyricsMap);
});