mirror of
https://github.com/Psychotoxical/psysonic.git
synced 2026-07-22 07:15:47 +00:00
463d3e0c5b
* refactor(fullscreen-player): H5 — extract FsLyricsApple + FsLyricsRail + useWordLyricsSync
The two lyrics views become own files under components/fullscreenPlayer/.
Their identical word-sync imperative DOM-update useEffect (only differing in
the .fsa-/.fsr- class prefix) collapses into the shared useWordLyricsSync
hook with a classPrefix arg.
FullscreenPlayer.tsx: 911 → 613 LOC.
* refactor(fullscreen-player): H5 — extract FsArt + FsPortrait + FsSeekbar
The three visual subcomponents move into own files. formatTime moves into
utils/fullscreenPlayerHelpers.ts so FsSeekbar keeps using it.
FullscreenPlayer.tsx: 613 → 421 LOC.
* refactor(fullscreen-player): H5 — extract FsLyricsMenu + FsPlayBtn
The lyrics-settings popover and the isolated play/pause button move into
own files. FullscreenPlayer drops the now-unused lucide-react icons
(Play/Pause/Moon/Sunrise/Music) and the PlaybackDelayModal +
PlaybackScheduleBadge imports — both used only by FsPlayBtn now.
FullscreenPlayer.tsx: 421 → 304 LOC.
* refactor(fullscreen-player): H5 — extract useFsDynamicAccent + useFsArtistPortrait + useFsIdleFade
Pulls three state+effect islands out of FullscreenPlayer:
- useFsDynamicAccent owns the cover-blob fetch + extractCoverColors call
plus the module-level artKey → accent cache that makes same-album song
switches instant.
- useFsArtistPortrait fetches getArtistInfo().largeImageUrl for the right-
side portrait, returning '' until resolved (or when no artistId).
- useFsIdleFade flips isIdle true after 3 s of inactivity, exposes a
throttled mousemove handler, and binds Escape to the provided callback.
FullscreenPlayer.tsx: 304 → 228 LOC.
41 lines
1.4 KiB
TypeScript
41 lines
1.4 KiB
TypeScript
import { useCallback, useEffect, useRef, useState } from 'react';
|
|
|
|
/** Idle-fade system — flips `isIdle` true after 3 s of no user activity.
|
|
* Returns the boolean plus a mousemove handler that's throttled to one reset
|
|
* per ~200 ms so cleanup/start timers don't fire on every mouse pixel.
|
|
* Also resets on key presses and triggers `onEscape` when the user hits Esc. */
|
|
export function useFsIdleFade(onEscape: () => void) {
|
|
const [isIdle, setIsIdle] = useState(false);
|
|
const idleTimer = useRef<ReturnType<typeof setTimeout> | null>(null);
|
|
|
|
const resetIdle = useCallback(() => {
|
|
setIsIdle(false);
|
|
if (idleTimer.current) clearTimeout(idleTimer.current);
|
|
idleTimer.current = setTimeout(() => setIsIdle(true), 3000);
|
|
}, []);
|
|
|
|
const lastMoveTime = useRef(0);
|
|
const handleMouseMove = useCallback(() => {
|
|
const now = Date.now();
|
|
if (now - lastMoveTime.current < 200) return;
|
|
lastMoveTime.current = now;
|
|
resetIdle();
|
|
}, [resetIdle]);
|
|
|
|
useEffect(() => {
|
|
resetIdle();
|
|
return () => { if (idleTimer.current) clearTimeout(idleTimer.current); };
|
|
}, [resetIdle]);
|
|
|
|
useEffect(() => {
|
|
const onKey = (e: KeyboardEvent) => {
|
|
resetIdle();
|
|
if (e.key === 'Escape') onEscape();
|
|
};
|
|
window.addEventListener('keydown', onKey);
|
|
return () => window.removeEventListener('keydown', onKey);
|
|
}, [onEscape, resetIdle]);
|
|
|
|
return { isIdle, handleMouseMove };
|
|
}
|