diff --git a/frontend/src/components/player/FullScreenPlayer.tsx b/frontend/src/components/player/FullScreenPlayer.tsx index d9553b4..248883f 100644 --- a/frontend/src/components/player/FullScreenPlayer.tsx +++ b/frontend/src/components/player/FullScreenPlayer.tsx @@ -5,6 +5,7 @@ import { X, Play, Pause, SkipBack, SkipForward, Heart, ListPlus, Share2, Message import { formatDuration } from '@/lib/utils' import { useQuery } from '@tanstack/react-query' import { musicApi } from '@/api/client' +import React from 'react' interface FullScreenPlayerProps { currentMusic: Music @@ -43,7 +44,12 @@ export default function FullScreenPlayer({ onToggleLyrics, onSeek, }: FullScreenPlayerProps) { - // Fetch lyrics when enabled + const [userScrolling, setUserScrolling] = React.useState(false) + const scrollTimeoutRef = React.useRef() + const lyricsContainerRef = React.useRef(null) + const lastScrollTop = React.useRef(0) + + // Fetch lyrics when enabled with caching const { data: lyrics, isLoading: lyricsLoading } = useQuery({ queryKey: ['lyrics', currentMusic.id], queryFn: async () => { @@ -51,44 +57,87 @@ export default function FullScreenPlayer({ return response.data.lyrics }, enabled: showLyrics && !!currentMusic.id, + staleTime: Infinity, // Cache lyrics forever + gcTime: 1000 * 60 * 60 * 24, // 24 hours }) + // Handle manual scroll + const handleScroll = React.useCallback((e: React.UIEvent) => { + const currentScrollTop = e.currentTarget.scrollTop + + // Only set userScrolling if scroll position actually changed (user initiated) + if (Math.abs(currentScrollTop - lastScrollTop.current) > 1) { + setUserScrolling(true) + lastScrollTop.current = currentScrollTop + + // Clear existing timeout + if (scrollTimeoutRef.current) { + clearTimeout(scrollTimeoutRef.current) + } + + // Resume auto-scroll after 5 seconds of no scrolling + scrollTimeoutRef.current = window.setTimeout(() => { + setUserScrolling(false) + }, 5000) + } + }, []) + + // Cleanup timeout on unmount or when lyrics disabled + React.useEffect(() => { + return () => { + if (scrollTimeoutRef.current) { + clearTimeout(scrollTimeoutRef.current) + } + } + }, []) + + // Reset user scrolling when lyrics change or disabled + React.useEffect(() => { + if (!showLyrics) { + setUserScrolling(false) + if (scrollTimeoutRef.current) { + clearTimeout(scrollTimeoutRef.current) + } + } + }, [showLyrics, currentMusic.id]) + + return (
{/* Main Content */}
{/* Large Album Art */} -
+
{currentMusic.thumbnail ? ( {currentMusic.title} ) : ( -
- +
+
)}
{/* Song Info */} -
-

{currentMusic.title}

+
+

{currentMusic.title}

{currentMusic.artist && currentMusic.artist !== 'Unknown' ? ( ) : ( -

+

{currentMusic.artist || 'Unknown Artist'}

)} {currentMusic.album && ( -

{currentMusic.album}

+

{currentMusic.album}

)}
@@ -98,21 +147,27 @@ export default function FullScreenPlayer({ {lyricsLoading ? (

Loading lyrics...

) : lyrics && lyrics.length > 0 ? ( -
+
{lyrics}
{/* Duplicate for seamless loop */} -
- {lyrics} -
+ {!userScrolling && ( +
+ {lyrics} +
+ )}
{/* Gradient overlays for fade effect */}
@@ -144,26 +199,26 @@ export default function FullScreenPlayer({
{/* Controls */} -
+
@@ -171,9 +226,9 @@ export default function FullScreenPlayer({ variant="ghost" size="icon" onClick={onNext} - className="h-12 w-12" + className={showLyrics ? 'h-10 w-10 md:h-12 md:w-12' : 'h-12 w-12'} > - +