From 7a1c7e1eae06ba5fc73df2d74cfdc3aa47b84302 Mon Sep 17 00:00:00 2001 From: angel Date: Sun, 10 Aug 2025 02:06:39 +0000 Subject: [PATCH] feat: Update cover art retrieval to use higher resolution images and enhance download manager with new features --- .env.local | 2 +- app/components/FullScreenPlayer.tsx | 61 +++++++--- app/components/SongRecommendations.tsx | 4 +- app/library/songs/page.tsx | 4 +- app/playlist/[id]/page.tsx | 6 +- app/search/page.tsx | 2 +- hooks/use-favorite-albums.ts | 2 +- hooks/use-offline-downloads.ts | 154 +++++++++++++++++++++---- 8 files changed, 189 insertions(+), 46 deletions(-) diff --git a/.env.local b/.env.local index 28a802d..b060a3b 100644 --- a/.env.local +++ b/.env.local @@ -1 +1 @@ -NEXT_PUBLIC_COMMIT_SHA=3839a1b +NEXT_PUBLIC_COMMIT_SHA=7e6a28e diff --git a/app/components/FullScreenPlayer.tsx b/app/components/FullScreenPlayer.tsx index 988aaa9..8d965ce 100644 --- a/app/components/FullScreenPlayer.tsx +++ b/app/components/FullScreenPlayer.tsx @@ -64,6 +64,22 @@ export const FullScreenPlayer: React.FC = ({ isOpen, onCl const [activeTab, setActiveTab] = useState('player'); const lyricsRef = useRef(null); + // Initialize volume from saved preference when fullscreen opens + useEffect(() => { + if (!isOpen) return; + try { + const savedVolume = localStorage.getItem('navidrome-volume'); + if (savedVolume !== null) { + const vol = parseFloat(savedVolume); + if (!isNaN(vol) && vol >= 0 && vol <= 1) { + setVolume(vol); + const mainAudio = document.querySelector('audio') as HTMLAudioElement | null; + if (mainAudio) mainAudio.volume = vol; + } + } + } catch {} + }, [isOpen]); + // Debug logging for component changes useEffect(() => { console.log('🔍 FullScreenPlayer state changed:', { @@ -128,7 +144,9 @@ export const FullScreenPlayer: React.FC = ({ isOpen, onCl const containerHeight = scrollContainer.clientHeight; const elementTop = currentLyricElement.offsetTop; const elementHeight = currentLyricElement.offsetHeight; - const targetScrollTop = elementTop - (containerHeight / 2) + (elementHeight / 2); + // Position the active lyric higher on the screen (~25% from top) + const focusFraction = 0.25; // 0.5 would be center + const targetScrollTop = elementTop - (containerHeight * focusFraction) + (elementHeight / 2); scrollContainer.scrollTo({ top: Math.max(0, targetScrollTop), @@ -379,6 +397,9 @@ export const FullScreenPlayer: React.FC = ({ isOpen, onCl mainAudio.currentTime = newTime; setCurrentTime(newTime); + try { + localStorage.setItem('navidrome-current-track-time', newTime.toString()); + } catch {} }; const handleVolumeChange = (e: React.ChangeEvent) => { @@ -388,6 +409,9 @@ export const FullScreenPlayer: React.FC = ({ isOpen, onCl const newVolume = parseInt(e.target.value) / 100; mainAudio.volume = newVolume; setVolume(newVolume); + try { + localStorage.setItem('navidrome-volume', newVolume.toString()); + } catch {} }; const handleLyricClick = (time: number) => { @@ -396,6 +420,9 @@ export const FullScreenPlayer: React.FC = ({ isOpen, onCl mainAudio.currentTime = time; setCurrentTime(time); + try { + localStorage.setItem('navidrome-current-track-time', time.toString()); + } catch {} // Update progress bar as well if (duration > 0) { @@ -660,18 +687,18 @@ export const FullScreenPlayer: React.FC = ({ isOpen, onCl className="flex-1 overflow-y-auto" ref={lyricsRef} > -
+
{lyrics.map((line, index) => ( handleLyricClick(line.time)} initial={false} - animate={index === currentLyricIndex ? { scale: 1, opacity: 1 } : index < currentLyricIndex ? { scale: 0.995, opacity: 0.7 } : { scale: 0.99, opacity: 0.5 }} + animate={index === currentLyricIndex ? { scale: 1.06, opacity: 1 } : index < currentLyricIndex ? { scale: 0.985, opacity: 0.75 } : { scale: 0.98, opacity: 0.6 }} transition={{ duration: 0.2 }} - className={`text-base leading-relaxed transition-colors duration-200 break-words cursor-pointer hover:text-foreground px-2 ${ + className={`text-2xl sm:text-3xl leading-relaxed transition-colors duration-200 break-words cursor-pointer hover:text-foreground px-2 ${ index === currentLyricIndex - ? 'text-foreground font-bold text-xl' + ? 'text-foreground font-extrabold leading-tight text-5xl sm:text-6xl' : index < currentLyricIndex ? 'text-foreground/60' : 'text-foreground/40' @@ -680,14 +707,18 @@ export const FullScreenPlayer: React.FC = ({ isOpen, onCl wordWrap: 'break-word', overflowWrap: 'break-word', hyphens: 'auto', - paddingBottom: '4px' + paddingBottom: '4px', + // Subtle glow to make the current line feel elevated + textShadow: index === currentLyricIndex + ? '0 4px 16px rgba(0,0,0,0.7), 0 0 24px rgba(255,255,255,0.16)' + : undefined }} title={`Click to jump to ${formatTime(line.time)}`} > {line.text || '♪'} ))} -
+
@@ -727,8 +758,6 @@ export const FullScreenPlayer: React.FC = ({ isOpen, onCl )}
- - {/* Mobile Tab Bar */}