import React, { useEffect, useState, useCallback, useMemo } from 'react'; import { useNavigate } from 'react-router-dom'; import { Play, ListPlus, RefreshCw, Sparkles } from 'lucide-react'; import { useTranslation } from 'react-i18next'; import { SubsonicSong, getRandomSongs, buildCoverArtUrl, coverArtCacheKey, } from '../api/subsonic'; import { useAuthStore } from '../store/authStore'; import { usePlayerStore, songToTrack } from '../store/playerStore'; import CachedImage from '../components/CachedImage'; import SongRail from '../components/SongRail'; import VirtualSongList from '../components/VirtualSongList'; import { playSongNow } from '../utils/playSong'; const RANDOM_RAIL_SIZE = 18; export default function Tracks() { const { t } = useTranslation(); const navigate = useNavigate(); const activeServerId = useAuthStore(s => s.activeServerId); const enqueue = usePlayerStore(s => s.enqueue); const [hero, setHero] = useState(null); const [heroLoading, setHeroLoading] = useState(false); const [random, setRandom] = useState([]); const [randomLoading, setRandomLoading] = useState(true); const rerollHero = useCallback(async () => { setHeroLoading(true); try { const picks = await getRandomSongs(1); if (picks[0]) setHero(picks[0]); } finally { setHeroLoading(false); } }, []); const rerollRandom = useCallback(async () => { setRandomLoading(true); try { const r = await getRandomSongs(RANDOM_RAIL_SIZE); setRandom(r); } finally { setRandomLoading(false); } }, []); useEffect(() => { if (!activeServerId) return; rerollHero(); rerollRandom(); }, [activeServerId, rerollHero, rerollRandom]); const heroCoverUrl = hero?.coverArt ? buildCoverArtUrl(hero.coverArt, 600) : ''; // Hide the hero song from the random rail if the server happens to return it in // both fetches (Navidrome's getRandomSongs sometimes overlaps within a short window). const railSongs = useMemo( () => (hero ? random.filter(s => s.id !== hero.id) : random), [random, hero], ); return (

{t('tracks.title')}

{t('tracks.subtitle')}

{hero && (
{heroCoverUrl ? ( ) : (
)}
{t('tracks.heroEyebrow')}

{hero.title}

hero.artistId && navigate(`/artist/${hero.artistId}`)} >{hero.artist} {hero.album && ( <> ยท hero.albumId && navigate(`/album/${hero.albumId}`)} >{hero.album} )}

)}
); }