import React, { useState, useEffect, useRef } from 'react'; import { PlayCircle, User, Radio, RefreshCw } from 'lucide-react'; import { getNowPlaying, SubsonicNowPlaying, buildCoverArtUrl } from '../api/subsonic'; import { useAuthStore } from '../store/authStore'; import { usePlayerStore } from '../store/playerStore'; import { useTranslation } from 'react-i18next'; import { useNavigate } from 'react-router-dom'; export default function NowPlayingDropdown() { const { t } = useTranslation(); const navigate = useNavigate(); const [isOpen, setIsOpen] = useState(false); const [nowPlaying, setNowPlaying] = useState([]); const isPlaying = usePlayerStore(s => s.isPlaying); const ownUsername = useAuthStore(s => s.getActiveServer()?.username ?? ''); const [loading, setLoading] = useState(false); const [spinning, setSpinning] = useState(false); const dropdownRef = useRef(null); const fetchNowPlaying = async () => { setLoading(true); try { const data = await getNowPlaying(); setNowPlaying(data); } catch (e) { console.error('Failed to load Now Playing', e); } finally { setLoading(false); } }; const handleRefresh = () => { setSpinning(true); fetchNowPlaying().finally(() => { setTimeout(() => setSpinning(false), 600); }); }; // Poll only while the dropdown is open AND the page is visible. useEffect(() => { if (!isOpen) return; fetchNowPlaying(); const id = setInterval(() => { if (document.visibilityState === 'visible') fetchNowPlaying(); }, 10000); return () => clearInterval(id); }, [isOpen]); // Click outside to close useEffect(() => { function handleClickOutside(event: MouseEvent) { if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) { setIsOpen(false); } } document.addEventListener('mousedown', handleClickOutside); return () => document.removeEventListener('mousedown', handleClickOutside); }, []); // For the current user, trust the local player state — the server keeps stale // "now playing" entries for minutes after playback stops. const visible = nowPlaying.filter(entry => entry.username === ownUsername ? isPlaying : true ); return (
{isOpen && (

{t('nowPlaying.title')}

{loading && visible.length === 0 ? (
{t('nowPlaying.loading')}
) : visible.length === 0 ? (
{t('nowPlaying.nobody')}
) : (
{visible.map((stream, idx) => (
{ if (stream.albumId) { setIsOpen(false); navigate(`/album/${stream.albumId}`); } }} style={{ display: 'flex', gap: '0.75rem', alignItems: 'center', background: 'var(--bg-hover)', padding: '0.5rem', borderRadius: '8px', cursor: stream.albumId ? 'pointer' : 'default' }} >
{stream.coverArt ? ( Cover ) : ( )}
{stream.title}
{stream.artist}
{stream.username} ({stream.playerName || 'Web'}) {stream.minutesAgo > 0 && • {t('nowPlaying.minutesAgo', { n: stream.minutesAgo })}}
))}
)}
)}
); }