diff --git a/src/renderer/api/types.ts b/src/renderer/api/types.ts index 303c00e6..ec6daaa3 100644 --- a/src/renderer/api/types.ts +++ b/src/renderer/api/types.ts @@ -1111,6 +1111,7 @@ export type LyricSearchQuery = { export type LyricGetQuery = { remoteSongId: string; remoteSource: LyricSource; + song: Song; }; export enum LyricSource { diff --git a/src/renderer/features/lyrics/lyrics-actions.tsx b/src/renderer/features/lyrics/lyrics-actions.tsx index 8e4fa9b7..f6455ce1 100644 --- a/src/renderer/features/lyrics/lyrics-actions.tsx +++ b/src/renderer/features/lyrics/lyrics-actions.tsx @@ -1,3 +1,4 @@ +import { Box, Group } from '@mantine/core'; import isElectron from 'is-electron'; import { RiAddFill, RiSubtractFill } from 'react-icons/ri'; import { LyricsOverride } from '/@/renderer/api/types'; @@ -12,10 +13,15 @@ import { interface LyricsActionsProps { onRemoveLyric: () => void; + onResetLyric: () => void; onSearchOverride: (params: LyricsOverride) => void; } -export const LyricsActions = ({ onRemoveLyric, onSearchOverride }: LyricsActionsProps) => { +export const LyricsActions = ({ + onRemoveLyric, + onResetLyric, + onSearchOverride, +}: LyricsActionsProps) => { const currentSong = useCurrentSong(); const { setSettings } = useSettingsStoreActions(); const { delayMs, sources } = useLyricsSettings(); @@ -33,59 +39,75 @@ export const LyricsActions = ({ onRemoveLyric, onSearchOverride }: LyricsActions const isDesktop = isElectron(); return ( - <> - {isDesktop && sources.length ? ( + + + {isDesktop && sources.length ? ( + + ) : null} - ) : null} - - - - - - {isDesktop && sources.length ? ( + + + - ) : null} - + {isDesktop && sources.length ? ( + + ) : null} + + + + {isDesktop && sources.length ? ( + + ) : null} + + ); }; diff --git a/src/renderer/features/lyrics/lyrics.tsx b/src/renderer/features/lyrics/lyrics.tsx index 1ccf6d1f..1f376067 100644 --- a/src/renderer/features/lyrics/lyrics.tsx +++ b/src/renderer/features/lyrics/lyrics.tsx @@ -1,6 +1,7 @@ import { useCallback, useEffect, useState } from 'react'; import { Center, Group } from '@mantine/core'; import { AnimatePresence, motion } from 'framer-motion'; +import { clear } from 'idb-keyval'; import { ErrorBoundary } from 'react-error-boundary'; import { RiInformationFill } from 'react-icons/ri'; import styled from 'styled-components'; @@ -9,7 +10,7 @@ import { SynchronizedLyrics } from './synchronized-lyrics'; import { Spinner, TextTitle } from '/@/renderer/components'; import { ErrorFallback } from '/@/renderer/features/action-required'; import { UnsynchronizedLyrics } from '/@/renderer/features/lyrics/unsynchronized-lyrics'; -import { getServerById, useCurrentSong, usePlayerStore } from '/@/renderer/store'; +import { useCurrentSong, usePlayerStore } from '/@/renderer/store'; import { FullLyricsMetadata, LyricsOverride, @@ -17,6 +18,8 @@ import { UnsynchronizedLyricMetadata, } from '/@/renderer/api/types'; import { LyricsActions } from '/@/renderer/features/lyrics/lyrics-actions'; +import { queryKeys } from '/@/renderer/api/query-keys'; +import { queryClient } from '/@/renderer/lib/react-query'; const ActionsContainer = styled.div` position: absolute; @@ -93,14 +96,11 @@ function isSynchronized( export const Lyrics = () => { const currentSong = useCurrentSong(); - const currentServer = getServerById(currentSong?.serverId); - - const [clear, setClear] = useState(false); const { data, isInitialLoading } = useSongLyricsBySong( { query: { songId: currentSong?.id || '' }, - serverId: currentServer?.id, + serverId: currentSong?.serverId || '', }, currentSong, ); @@ -109,18 +109,41 @@ export const Lyrics = () => { const handleOnSearchOverride = useCallback((params: LyricsOverride) => { setOverride(params); - setClear(false); }, []); - const { data: overrideLyrics, isInitialLoading: isOverrideLoading } = useSongLyricsByRemoteId({ + const handleOnResetLyric = useCallback(() => { + queryClient.resetQueries({ + exact: true, + queryKey: queryKeys.songs.lyrics(currentSong?.serverId, { songId: currentSong?.id }), + }); + }, [currentSong?.id, currentSong?.serverId]); + + const handleOnRemoveLyric = useCallback(() => { + queryClient.setQueryData( + queryKeys.songs.lyrics(currentSong?.serverId, { songId: currentSong?.id }), + (prev: FullLyricsMetadata | undefined) => { + if (!prev) { + return undefined; + } + + return { + ...prev, + lyrics: '', + }; + }, + ); + }, [currentSong?.id, currentSong?.serverId]); + + const { isInitialLoading: isOverrideLoading } = useSongLyricsByRemoteId({ options: { enabled: !!override, }, query: { remoteSongId: override?.id, remoteSource: override?.source, + song: currentSong, }, - serverId: currentServer?.id, + serverId: currentSong?.serverId, }); useEffect(() => { @@ -128,7 +151,6 @@ export const Lyrics = () => { (state) => state.current.song, () => { setOverride(undefined); - setClear(false); }, { equalityFn: (a, b) => a?.id === b?.id }, ); @@ -140,20 +162,12 @@ export const Lyrics = () => { const isLoadingLyrics = isInitialLoading || isOverrideLoading; - const hasNoLyrics = (!data?.lyrics && !overrideLyrics) || clear; + const hasNoLyrics = !data?.lyrics || clear; const lyricsMetadata: | Partial | Partial - | undefined = overrideLyrics - ? { - artist: override?.artist, - lyrics: overrideLyrics, - name: override?.name, - remote: true, - source: override?.source, - } - : data; + | undefined = data; const isSynchronizedLyrics = isSynchronized(lyricsMetadata); @@ -198,7 +212,8 @@ export const Lyrics = () => { )} setClear(true)} + onRemoveLyric={handleOnRemoveLyric} + onResetLyric={handleOnResetLyric} onSearchOverride={handleOnSearchOverride} /> diff --git a/src/renderer/features/lyrics/queries/lyric-query.ts b/src/renderer/features/lyrics/queries/lyric-query.ts index 55a598a7..574e66c6 100644 --- a/src/renderer/features/lyrics/queries/lyric-query.ts +++ b/src/renderer/features/lyrics/queries/lyric-query.ts @@ -1,4 +1,4 @@ -import { UseQueryResult, useQuery } from '@tanstack/react-query'; +import { UseQueryResult, useQuery, useQueryClient } from '@tanstack/react-query'; import { LyricsQuery, QueueSong, @@ -93,6 +93,8 @@ export const useSongLyricsBySong = ( if (!server) throw new Error('Server not found'); if (!song) return null; + console.log('refetching song lyrics'); + if (song.lyrics) { return { artist: song.artists?.[0]?.name, @@ -145,12 +147,35 @@ export const useSongLyricsBySong = ( export const useSongLyricsByRemoteId = ( args: QueryHookArgs>, ): UseQueryResult => { - const { query } = args; + const queryClient = useQueryClient(); + const { query, serverId } = args; return useQuery({ - cacheTime: 1000 * 60 * 10, enabled: !!query.remoteSongId && !!query.remoteSource, onError: () => {}, + onSuccess: (data) => { + if (!data || !query.song) { + return; + } + + const lyricsResult = { + artist: query.song.artists?.[0]?.name, + lyrics: data, + name: query.song.name, + remote: false, + source: query.remoteSource, + }; + + console.log( + 'queryKeys.songs.lyrics(serverId, { songId: query.song.id }) :>> ', + queryKeys.songs.lyrics(serverId, { songId: query.song.id }), + ); + + queryClient.setQueryData( + queryKeys.songs.lyrics(serverId, { songId: query.song.id }), + lyricsResult, + ); + }, queryFn: async () => { const remoteLyricsResult = await lyricsIpc?.getRemoteLyricsByRemoteId( query as LyricGetQuery, @@ -163,6 +188,5 @@ export const useSongLyricsByRemoteId = ( return null; }, queryKey: queryKeys.songs.lyricsByRemoteId(query), - staleTime: 1000 * 60 * 5, }); };