From e0d6623bf1ae89836baf8e1079c7c312c58b1145 Mon Sep 17 00:00:00 2001 From: Psychotoxical <171614930+Psychotoxical@users.noreply.github.com> Date: Tue, 30 Jun 2026 19:21:21 +0200 Subject: [PATCH] refactor(lyrics): co-locate lyrics feature into features/lyrics (LyricsPane + hooks + cache + lrclib/lyricsplus/netease providers; lyricsStore stays global) --- .../fullscreenPlayer/components/FsLyricsApple.tsx | 6 +++--- src/{ => features/lyrics}/api/lrclib.ts | 0 src/{ => features/lyrics}/api/lyricsplus.ts | 0 src/{ => features/lyrics}/api/netease.ts | 0 .../lyrics}/components/LyricsPane.tsx | 8 ++++---- src/{ => features/lyrics}/hooks/useLyrics.ts | 10 +++++----- .../lyrics}/hooks/useWordLyricsSync.ts | 2 +- src/features/lyrics/index.ts | 15 +++++++++++++++ .../lyrics/utils}/lyricsPersistentCache.ts | 2 +- .../nowPlaying/components/MobilePlayerView.tsx | 2 +- src/features/queue/components/QueuePanel.tsx | 2 +- 11 files changed, 31 insertions(+), 16 deletions(-) rename src/{ => features/lyrics}/api/lrclib.ts (100%) rename src/{ => features/lyrics}/api/lyricsplus.ts (100%) rename src/{ => features/lyrics}/api/netease.ts (100%) rename src/{ => features/lyrics}/components/LyricsPane.tsx (97%) rename src/{ => features/lyrics}/hooks/useLyrics.ts (97%) rename src/{ => features/lyrics}/hooks/useWordLyricsSync.ts (97%) create mode 100644 src/features/lyrics/index.ts rename src/{utils/cache => features/lyrics/utils}/lyricsPersistentCache.ts (97%) diff --git a/src/features/fullscreenPlayer/components/FsLyricsApple.tsx b/src/features/fullscreenPlayer/components/FsLyricsApple.tsx index f31d0c42..717f1aaa 100644 --- a/src/features/fullscreenPlayer/components/FsLyricsApple.tsx +++ b/src/features/fullscreenPlayer/components/FsLyricsApple.tsx @@ -1,10 +1,10 @@ import React, { memo, useCallback, useEffect, useRef, useState } from 'react'; import { usePlayerStore } from '@/features/playback/store/playerStore'; import { useAuthStore } from '@/store/authStore'; -import { useLyrics, type WordLyricsLine } from '@/hooks/useLyrics'; -import { useWordLyricsSync } from '@/hooks/useWordLyricsSync'; +import { useLyrics, type WordLyricsLine } from '@/features/lyrics'; +import { useWordLyricsSync } from '@/features/lyrics'; import { getPlaybackProgressSnapshot, subscribePlaybackProgress } from '@/features/playback/store/playbackProgress'; -import type { LrcLine } from '@/api/lrclib'; +import type { LrcLine } from '@/features/lyrics'; import type { Track } from '@/lib/media/trackTypes'; import { EaseScroller, targetForFraction } from '@/utils/ui/easeScroll'; diff --git a/src/api/lrclib.ts b/src/features/lyrics/api/lrclib.ts similarity index 100% rename from src/api/lrclib.ts rename to src/features/lyrics/api/lrclib.ts diff --git a/src/api/lyricsplus.ts b/src/features/lyrics/api/lyricsplus.ts similarity index 100% rename from src/api/lyricsplus.ts rename to src/features/lyrics/api/lyricsplus.ts diff --git a/src/api/netease.ts b/src/features/lyrics/api/netease.ts similarity index 100% rename from src/api/netease.ts rename to src/features/lyrics/api/netease.ts diff --git a/src/components/LyricsPane.tsx b/src/features/lyrics/components/LyricsPane.tsx similarity index 97% rename from src/components/LyricsPane.tsx rename to src/features/lyrics/components/LyricsPane.tsx index 7848d1af..95b3f423 100644 --- a/src/components/LyricsPane.tsx +++ b/src/features/lyrics/components/LyricsPane.tsx @@ -2,12 +2,12 @@ import { getPlaybackProgressSnapshot, subscribePlaybackProgress } from '@/featur import { useEffect, useRef, useCallback } from 'react'; import { useShallow } from 'zustand/react/shallow'; import { usePlayerStore } from '@/features/playback/store/playerStore'; -import type { LrcLine } from '../api/lrclib'; -import { useLyrics, type WordLyricsLine } from '../hooks/useLyrics'; -import { useAuthStore } from '../store/authStore'; +import type { LrcLine } from '@/features/lyrics/api/lrclib'; +import { useLyrics, type WordLyricsLine } from '@/features/lyrics/hooks/useLyrics'; +import { useAuthStore } from '@/store/authStore'; import { useTranslation } from 'react-i18next'; import type { Track } from '@/lib/media/trackTypes'; -import { EaseScroller, targetForFraction } from '../utils/ui/easeScroll'; +import { EaseScroller, targetForFraction } from '@/utils/ui/easeScroll'; import OverlayScrollArea from '@/ui/OverlayScrollArea'; interface Props { diff --git a/src/hooks/useLyrics.ts b/src/features/lyrics/hooks/useLyrics.ts similarity index 97% rename from src/hooks/useLyrics.ts rename to src/features/lyrics/hooks/useLyrics.ts index 63f6a0cb..caa04a9b 100644 --- a/src/hooks/useLyrics.ts +++ b/src/features/lyrics/hooks/useLyrics.ts @@ -4,13 +4,13 @@ import type { Track } from '@/lib/media/trackTypes'; import { useEffect, useState } from 'react'; import { useShallow } from 'zustand/react/shallow'; import { invoke } from '@tauri-apps/api/core'; -import { fetchLyrics, parseLrc, LrcLine } from '../api/lrclib'; -import { fetchNeteaselyrics } from '../api/netease'; -import { fetchLyricsPlus, hasWordSync } from '../api/lyricsplus'; -import { useAuthStore } from '../store/authStore'; +import { fetchLyrics, parseLrc, LrcLine } from '@/features/lyrics/api/lrclib'; +import { fetchNeteaselyrics } from '@/features/lyrics/api/netease'; +import { fetchLyricsPlus, hasWordSync } from '@/features/lyrics/api/lyricsplus'; +import { useAuthStore } from '@/store/authStore'; import { useOfflineStore } from '@/features/offline'; import { useHotCacheStore } from '@/features/playback/store/hotCacheStore'; -import { getCachedLyrics, putCachedLyrics, lyricsCacheKey } from '../utils/cache/lyricsPersistentCache'; +import { getCachedLyrics, putCachedLyrics, lyricsCacheKey } from '@/features/lyrics/utils/lyricsPersistentCache'; export type LyricsSource = 'server' | 'lrclib' | 'netease' | 'embedded' | 'lyricsplus'; /** diff --git a/src/hooks/useWordLyricsSync.ts b/src/features/lyrics/hooks/useWordLyricsSync.ts similarity index 97% rename from src/hooks/useWordLyricsSync.ts rename to src/features/lyrics/hooks/useWordLyricsSync.ts index f6e99f99..4eea050f 100644 --- a/src/hooks/useWordLyricsSync.ts +++ b/src/features/lyrics/hooks/useWordLyricsSync.ts @@ -1,7 +1,7 @@ import { useEffect, useRef } from 'react'; import { getPlaybackProgressSnapshot, subscribePlaybackProgress } from '@/features/playback/store/playbackProgress'; import type { Track } from '@/lib/media/trackTypes'; -import type { WordLyricsLine } from './useLyrics'; +import type { WordLyricsLine } from '@/features/lyrics/hooks/useLyrics'; interface Args { enabled: boolean; diff --git a/src/features/lyrics/index.ts b/src/features/lyrics/index.ts new file mode 100644 index 00000000..0f892d4f --- /dev/null +++ b/src/features/lyrics/index.ts @@ -0,0 +1,15 @@ +/** + * Lyrics feature — the LyricsPane UI, the lyrics fetch/sync hooks, the + * persistent lyrics cache, and the per-provider lyrics API clients (lrclib, + * lyricsplus/YouLyPlus, netease). Consumed cross-feature by the queue panel, + * the now-playing mobile view, and the fullscreen Apple-style lyrics view. + * + * Stays OUT (global / authStore-family, consumed beyond this feature): the + * `lyricsStore` open/settings state (read by the keyboard-shortcut registry + + * app boot) and `authLyricsSettingsActions` (authStore action module). The + * subsonic 'server' lyrics provider stays in `lib/api/subsonicLyrics`. + */ +export { default as LyricsPane } from './components/LyricsPane'; +export { useLyrics, type WordLyricsLine, type LyricsSource } from './hooks/useLyrics'; +export { useWordLyricsSync } from './hooks/useWordLyricsSync'; +export type { LrcLine } from './api/lrclib'; diff --git a/src/utils/cache/lyricsPersistentCache.ts b/src/features/lyrics/utils/lyricsPersistentCache.ts similarity index 97% rename from src/utils/cache/lyricsPersistentCache.ts rename to src/features/lyrics/utils/lyricsPersistentCache.ts index 805fdd98..2cce460b 100644 --- a/src/utils/cache/lyricsPersistentCache.ts +++ b/src/features/lyrics/utils/lyricsPersistentCache.ts @@ -12,7 +12,7 @@ * - notFound entries: 7 days. Lets the user / server admin add lyrics * later without an indefinite negative cache. */ -import type { CachedLyrics } from '../../hooks/useLyrics'; +import type { CachedLyrics } from '@/features/lyrics/hooks/useLyrics'; const DB_NAME = 'psysonic-lyrics-cache'; const STORE_NAME = 'lyrics'; diff --git a/src/features/nowPlaying/components/MobilePlayerView.tsx b/src/features/nowPlaying/components/MobilePlayerView.tsx index 53ff3e44..fdf75d6c 100644 --- a/src/features/nowPlaying/components/MobilePlayerView.tsx +++ b/src/features/nowPlaying/components/MobilePlayerView.tsx @@ -22,7 +22,7 @@ import { getQueueResolverVersion, subscribeQueueResolver, } from '@/features/playback/store/queueTrackResolver'; -import LyricsPane from '@/components/LyricsPane'; +import { LyricsPane } from '@/features/lyrics'; import { usePlaybackDelayPress } from '@/hooks/usePlaybackDelayPress'; import PlaybackDelayModal from '@/features/playback/components/PlaybackDelayModal'; import PlaybackScheduleBadge from '@/features/playback/components/PlaybackScheduleBadge'; diff --git a/src/features/queue/components/QueuePanel.tsx b/src/features/queue/components/QueuePanel.tsx index 9dbdd5eb..7438e913 100644 --- a/src/features/queue/components/QueuePanel.tsx +++ b/src/features/queue/components/QueuePanel.tsx @@ -18,7 +18,7 @@ import { copyTextToClipboard } from '@/utils/server/serverMagicString'; import { showToast } from '@/utils/ui/toast'; import { useThemeStore } from '@/store/themeStore'; import { useLyricsStore } from '@/store/lyricsStore'; -import LyricsPane from '@/components/LyricsPane'; +import { LyricsPane } from '@/features/lyrics'; import { NowPlayingInfo } from '@/features/nowPlaying'; import { useLuckyMixStore } from '@/features/randomMix'; import { useQueueToolbarStore } from '@/store/queueToolbarStore';