import React, { memo } from 'react'; import { useNavigate } from 'react-router-dom'; import { Play, ListPlus } from 'lucide-react'; import { useTranslation } from 'react-i18next'; import type { SubsonicSong } from '../api/subsonic'; import { usePlayerStore, songToTrack } from '../store/playerStore'; import { enqueueAndPlay } from '../utils/playSong'; import { useDragDrop } from '../contexts/DragDropContext'; import { useOrbitSongRowBehavior } from '../hooks/useOrbitSongRowBehavior'; function fmtDuration(s: number): string { if (!s || !isFinite(s)) return '–'; const m = Math.floor(s / 60); const sec = Math.floor(s % 60); return `${m}:${sec.toString().padStart(2, '0')}`; } interface Props { song: SubsonicSong; } function SongRow({ song }: Props) { const navigate = useNavigate(); const enqueue = usePlayerStore(s => s.enqueue); const openContextMenu = usePlayerStore(s => s.openContextMenu); const isCurrent = usePlayerStore(s => s.currentTrack?.id === song.id); const psyDrag = useDragDrop(); const { orbitActive, addTrackToOrbit } = useOrbitSongRowBehavior(); // In an orbit session both buttons collapse into the orbit-suggest / host-enqueue // path so we don't ship a queue replacement to every guest. const handlePlay = () => { if (orbitActive) { addTrackToOrbit(song.id); return; } enqueueAndPlay(song); }; const handleEnqueue = () => { if (orbitActive) { addTrackToOrbit(song.id); return; } enqueue([songToTrack(song)]); }; return (