From 620b810191651857043fc99dd3a4caabb6a2a2e3 Mon Sep 17 00:00:00 2001 From: jeffvli Date: Wed, 25 Jun 2025 21:25:29 -0700 Subject: [PATCH] add option to set local lyric priority --- src/i18n/locales/en.json | 2 ++ .../features/lyrics/queries/lyric-query.ts | 29 ++++++++++++++----- .../components/playback/lyric-settings.tsx | 22 ++++++++++++++ src/renderer/store/settings.store.ts | 2 ++ 4 files changed, 47 insertions(+), 8 deletions(-) diff --git a/src/i18n/locales/en.json b/src/i18n/locales/en.json index 0727e63d..f56c5897 100644 --- a/src/i18n/locales/en.json +++ b/src/i18n/locales/en.json @@ -536,6 +536,8 @@ "floatingQueueArea_description": "display a hover icon on the right side of the screen to view the play queue", "followLyric": "follow current lyric", "followLyric_description": "scroll the lyric to the current playing position", + "preferLocalLyrics": "prefer local lyrics", + "preferLocalLyrics_description": "prefer local lyrics over remote lyrics when available", "font": "font", "font_description": "sets the font to use for the application", "fontType": "font type", diff --git a/src/renderer/features/lyrics/queries/lyric-query.ts b/src/renderer/features/lyrics/queries/lyric-query.ts index 3973e190..e4e91cd1 100644 --- a/src/renderer/features/lyrics/queries/lyric-query.ts +++ b/src/renderer/features/lyrics/queries/lyric-query.ts @@ -86,7 +86,7 @@ export const useSongLyricsBySong = ( song: QueueSong | undefined, ): UseQueryResult => { const { query } = args; - const { fetch } = useLyricsSettings(); + const { fetch, preferLocalLyrics } = useLyricsSettings(); const server = getServerById(song?.serverId); return useQuery({ @@ -97,6 +97,9 @@ export const useSongLyricsBySong = ( if (!server) throw new Error('Server not found'); if (!song) return null; + let localLyrics: FullLyricsMetadata | null | StructuredLyric[] = null; + let remoteLyrics: FullLyricsMetadata | null | StructuredLyric[] = null; + if (hasFeature(server, ServerFeature.LYRICS_MULTIPLE_STRUCTURED)) { const subsonicLyrics = await api.controller .getStructuredLyrics({ @@ -106,7 +109,7 @@ export const useSongLyricsBySong = ( .catch(console.error); if (subsonicLyrics?.length) { - return subsonicLyrics; + localLyrics = subsonicLyrics; } } else if (hasFeature(server, ServerFeature.LYRICS_SINGLE_STRUCTURED)) { const jfLyrics = await api.controller @@ -117,7 +120,7 @@ export const useSongLyricsBySong = ( .catch((err) => console.log(err)); if (jfLyrics) { - return { + localLyrics = { artist: song.artists?.[0]?.name, lyrics: jfLyrics, name: song.name, @@ -126,7 +129,7 @@ export const useSongLyricsBySong = ( }; } } else if (song.lyrics) { - return { + localLyrics = { artist: song.artists?.[0]?.name, lyrics: formatLyrics(song.lyrics), name: song.name, @@ -135,12 +138,16 @@ export const useSongLyricsBySong = ( }; } + if (preferLocalLyrics && localLyrics) { + return localLyrics; + } + if (fetch) { const remoteLyricsResult: InternetProviderLyricResponse | null = await lyricsIpc?.getRemoteLyricsBySong(song); if (remoteLyricsResult) { - return { + remoteLyrics = { ...remoteLyricsResult, lyrics: formatLyrics(remoteLyricsResult.lyrics), remote: true, @@ -148,6 +155,14 @@ export const useSongLyricsBySong = ( } } + if (remoteLyrics) { + return remoteLyrics; + } + + if (localLyrics) { + return localLyrics; + } + return null; }, queryKey: queryKeys.songs.lyrics(server?.id || '', query), @@ -183,9 +198,7 @@ export const useSongLyricsByRemoteId = ( ); }, queryFn: async () => { - const remoteLyricsResult = await lyricsIpc?.getRemoteLyricsByRemoteId( - query as LyricGetQuery, - ); + const remoteLyricsResult = await lyricsIpc?.getRemoteLyricsByRemoteId(query as any); if (remoteLyricsResult) { return formatLyrics(remoteLyricsResult); diff --git a/src/renderer/features/settings/components/playback/lyric-settings.tsx b/src/renderer/features/settings/components/playback/lyric-settings.tsx index 0e0caf56..972f7d46 100644 --- a/src/renderer/features/settings/components/playback/lyric-settings.tsx +++ b/src/renderer/features/settings/components/playback/lyric-settings.tsx @@ -43,6 +43,28 @@ export const LyricSettings = () => { }), title: t('setting.followLyric', { postProcess: 'sentenceCase' }), }, + { + control: ( + { + setSettings({ + lyrics: { + ...settings, + preferLocalLyrics: e.currentTarget.checked, + }, + }); + }} + /> + ), + description: t('setting.preferLocalLyrics', { + context: 'description', + postProcess: 'sentenceCase', + }), + isHidden: !isElectron(), + title: t('setting.preferLocalLyrics', { postProcess: 'sentenceCase' }), + }, { control: (