import React from 'react'; import { useTranslation } from 'react-i18next'; import { AudioLines, ChevronRight, Heart, Play, Square } from 'lucide-react'; import type { SubsonicSong } from '../../api/subsonicTypes'; import type { Track } from '../../store/playerStoreTypes'; import { usePreviewStore } from '../../store/previewStore'; import { useDragDrop } from '../../contexts/DragDropContext'; import { formatRandomMixDuration } from '../../utils/randomMixHelpers'; interface Props { song: SubsonicSong; idx: number; gridTemplateColumns: string; track: Track; queueSongs: Track[]; isCurrentTrack: boolean; isPlaying: boolean; isContextActive: boolean; orbitActive: boolean; previewingId: string | null; previewAudioStarted: boolean; starredOverrides: Record; isStarred: boolean; customGenreBlacklist: string[]; addedArtist: string | null; addedGenre: string | null; showGenreCol: boolean; isGenreBlocked: boolean; onPlay: () => void; onQueueHint: () => void; onAddTrackToOrbit: (id: string) => void; onOpenContextMenu: (e: React.MouseEvent) => void; onToggleStar: (e: React.MouseEvent) => void; onBlacklistArtist: (artist: string) => void; onBlacklistGenre: (genre: string) => void; } export default function RandomMixTrackRow({ song, idx, gridTemplateColumns, track, queueSongs, isCurrentTrack, isPlaying, isContextActive, orbitActive, previewingId, previewAudioStarted, starredOverrides, isStarred, customGenreBlacklist, addedArtist, addedGenre, showGenreCol, isGenreBlocked, onPlay, onQueueHint, onAddTrackToOrbit, onOpenContextMenu, onToggleStar, onBlacklistArtist, onBlacklistGenre, }: Props) { const { t } = useTranslation(); const psyDrag = useDragDrop(); const artist = song.artist; const genre = song.genre; const isArtistBlocked = !!artist && customGenreBlacklist.some(bg => artist.toLowerCase().includes(bg.toLowerCase())); const isArtistJustAdded = addedArtist === artist; const isGenreJustAdded = addedGenre === genre; const starColor = isStarred ? 'var(--color-star-active, var(--accent))' : 'var(--color-star-inactive, var(--text-muted))'; return (
{ if ((e.target as HTMLElement).closest('button, a, input')) return; if (orbitActive) { onQueueHint(); return; } onPlay(); }} onDoubleClick={orbitActive ? e => { if ((e.target as HTMLElement).closest('button, a, input')) return; onAddTrackToOrbit(song.id); } : undefined} role="row" onContextMenu={onOpenContextMenu} onMouseDown={e => { if (e.button !== 0) return; e.preventDefault(); const sx = e.clientX, sy = e.clientY; const onMove = (me: MouseEvent) => { if (Math.abs(me.clientX - sx) > 5 || Math.abs(me.clientY - sy) > 5) { document.removeEventListener('mousemove', onMove); document.removeEventListener('mouseup', onUp); psyDrag.startDrag({ data: JSON.stringify({ type: 'song', track }), label: song.title }, me.clientX, me.clientY); } }; const onUp = () => { document.removeEventListener('mousemove', onMove); document.removeEventListener('mouseup', onUp); }; document.addEventListener('mousemove', onMove); document.addEventListener('mouseup', onUp); }} >
{isCurrentTrack && isPlaying ? ( ) : ( {idx + 1} )}
{song.title}
{artist ? ( ) : }
{song.album ?? '—'}
{showGenreCol && (
{genre ? ( ) : }
)}
{formatRandomMixDuration(song.duration)}
); }