import React from 'react'; import { useTranslation } from 'react-i18next'; import { AudioLines, ChevronRight, Heart, Play, Square, Trash2 } from 'lucide-react'; import type { ColDef } from '../../utils/useTracklistColumns'; import type { SubsonicSong } from '../../api/subsonicTypes'; import { codecLabel } from '../../utils/componentHelpers/playlistDetailHelpers'; import { formatLastSeen } from '../../utils/componentHelpers/userMgmtHelpers'; import i18n from '../../i18n'; import { formatTrackTime } from '../../utils/format/formatDuration'; import StarRating from '../StarRating'; export interface PlaylistRowCallbacks { activate: (song: SubsonicSong, index: number, e: React.MouseEvent) => void; dblOrbit: (songId: string, e: React.MouseEvent) => void; context: (song: SubsonicSong, realIdx: number, e: React.MouseEvent) => void; mouseDownRow: (realIdx: number, e: React.MouseEvent) => void; mouseEnterRow: (index: number, e: React.MouseEvent) => void; toggleSelect: (songId: string, index: number, shift: boolean) => void; play: (index: number) => void; startPreview: (song: SubsonicSong) => void; toggleStar: (song: SubsonicSong, e: React.MouseEvent) => void; rate: (songId: string, rating: number) => void; remove: (realIdx: number) => void; navArtist: (artistId: string) => void; navAlbum: (albumId: string) => void; } interface Props { song: SubsonicSong; index: number; realIdx: number; visibleCols: ColDef[]; gridStyle: React.CSSProperties; showBitrate: boolean; isActive: boolean; showEq: boolean; isContextActive: boolean; isSelected: boolean; inSelectMode: boolean; isStarred: boolean; ratingValue: number; isPreviewing: boolean; previewStarted: boolean; orbitActive: boolean; cb: PlaylistRowCallbacks; } function PlaylistRow({ song, index: i, realIdx, visibleCols, gridStyle, showBitrate, isActive, showEq, isContextActive, isSelected, inSelectMode, isStarred, ratingValue, isPreviewing, previewStarted, orbitActive, cb, }: Props) { const { t } = useTranslation(); return (
cb.mouseEnterRow(i, e)} onMouseDown={e => cb.mouseDownRow(realIdx, e)} onClick={e => cb.activate(song, i, e)} onDoubleClick={orbitActive ? e => cb.dblOrbit(song.id, e) : undefined} onContextMenu={e => cb.context(song, realIdx, e)} > {visibleCols.map(colDef => { switch (colDef.key) { case 'num': return (
{ e.stopPropagation(); cb.toggleSelect(song.id, i, e.shiftKey); }} /> {showEq ? ( ) : ( {i + 1} )}
); case 'title': return (
{song.title}
); case 'artist': return (
{ if (song.artistId) { e.stopPropagation(); cb.navArtist(song.artistId); } }}>{song.artist}
); case 'album': return (
{ if (song.albumId) { e.stopPropagation(); cb.navAlbum(song.albumId); } }}>{song.album}
); case 'favorite': return (
); case 'rating': return cb.rate(song.id, r)} />; case 'duration': return
{formatTrackTime(song.duration ?? 0)}
; case 'format': return (
{(song.suffix || (showBitrate && song.bitRate)) && {codecLabel(song, showBitrate)}}
); case 'genre': return (
{song.genre ?? '—'}
); case 'playCount': return (
{song.playCount ?? '—'}
); case 'lastPlayed': return (
{song.played ? formatLastSeen(song.played, i18n.language, '—') : '—'}
); case 'bpm': return (
{song.bpm && song.bpm > 0 ? song.bpm : '—'}
); case 'delete': return (
); default: return null; } })}
); } export default React.memo(PlaylistRow);