import { Row } from '@olly/modern-sk'; import { useTranslation } from 'react-i18next'; import { TrackContextMenu } from './TrackContextMenu'; import { AvailabilityBadge } from './AvailabilityBadge'; import { MetadataStatusBadge } from './MetadataStatusBadge'; import { Icon } from '../common/Icon'; import { PlayingIndicator } from '../common/PlayingIndicator'; import { formatDuration } from '../../lib/format'; import { useAppDispatch, useAppSelector } from '../../hooks/useAppDispatch'; import { playNow } from '../../store/slices/queue'; import type { Track } from '../../api/types'; import { getCoverUrl, getTrackCoverUrl } from '../../api/endpoints/streaming'; interface Props { track: Track; index?: number; showAlbum?: boolean; onAddToPlaylist?: (track: Track) => void; onEditMetadata?: (track: Track) => void; onDelete?: (track: Track) => void; } export function TrackRow({ track, index, showAlbum = false, onAddToPlaylist, onEditMetadata, onDelete, }: Props) { const { t } = useTranslation(); const dispatch = useAppDispatch(); const currentTrackId = useAppSelector((s) => s.player.currentTrackId); const isPlaying = useAppSelector((s) => s.player.isPlaying); const token = useAppSelector((s) => s.auth.accessToken); const isActive = currentTrackId === track.id; // Prefer an explicit album art URL; otherwise serve the track's own cover // (needs the token in the query string — `` can't send a header). const artUrl = getCoverUrl(track.albumArtUrl) ?? (token ? getTrackCoverUrl(track.id, token, track.hasCover) : undefined); const handlePlayNow = () => { dispatch( playNow({ trackId: track.id, title: track.title, artistName: track.artistName, albumTitle: track.albumTitle, durationMs: track.durationMs, albumArtUrl: track.albumArtUrl, }), ); }; return ( {isActive && isPlaying ? '▶' : index !== undefined ? index + 1 : ''}
{artUrl ? ( ) : (
)} {isActive && (
)}
{track.title}
{track.artistName} {showAlbum && ` · ${track.albumTitle}`}
{formatDuration(track.durationMs)}
); }