import { HeartFillIcon } from '@primer/octicons-react' import { InfiniteData } from '@tanstack/react-query' import { useCallback } from 'react' import { useLocation } from 'react-router-dom' import { Virtuoso } from 'react-virtuoso' import { MediaItem } from '../api/jellyfin' import { useDropdownContext } from '../context/DropdownContext/DropdownContext' import { usePlaybackContext } from '../context/PlaybackContext/PlaybackContext' import { useDisplayItems } from '../hooks/useDisplayItems' import { formatDuration } from '../utils/formatDuration' import { JellyImg } from './JellyImg' import { Loader } from './Loader' import { IReviver } from './PlaybackManager' import './PlaylistTrackList.css' import { Skeleton } from './Skeleton' import { Squircle } from './Squircle' import { DeletingIcon, DownloadedIcon, DownloadingIcon, PlaystateAnimationTracklist } from './SvgIcons' export const PlaylistTrackList = ({ tracks, infiniteData = { pageParams: [], pages: [] }, isLoading, playlistId, showType, title, reviver, loadMore, }: { tracks: MediaItem[] infiniteData: InfiniteData | undefined isLoading: boolean playlistId?: string showType?: 'artist' | 'album' title: string reviver?: IReviver loadMore?: () => void }) => { const playback = usePlaybackContext() const location = useLocation() const { displayItems, setRowRefs } = useDisplayItems(tracks, isLoading) const dropdown = useDropdownContext() const handleTrackClick = useCallback( (track: MediaItem, index: number) => { if (playback.currentTrack?.Id === track.Id) { playback.togglePlayPause() } else { playback.setCurrentPlaylist({ pages: infiniteData, title, reviver }) playback.playTrack(index) } }, [playback, infiniteData, reviver, title] ) const renderTrack = (index: number, item: MediaItem | { isPlaceholder: true }) => { if ('isPlaceholder' in item) { return (
  • setRowRefs(index, el)}>
  • ) } const track = item const isActive = dropdown.selectedItem?.Id === item.Id && dropdown.isOpen const trackClass = [ playback.currentTrack?.Id === track.Id ? (playback.isPlaying ? 'playing' : 'paused') : '', isActive ? 'active' : '', ] .filter(Boolean) .join(' ') const isFavorite = track.UserData?.IsFavorite && location.pathname !== '/favorites' return (
  • handleTrackClick(track, index)} key={track.Id} ref={el => setRowRefs(index, el)} onContextMenu={e => dropdown.onContextMenu(e, { item, playlistId })} onTouchStart={e => dropdown.onTouchStart(e, { item, playlistId })} onTouchMove={dropdown.onTouchClear} onTouchEnd={dropdown.onTouchClear} >
    {index + 1}. {track.Name}
    {showType === 'artist' ? (
    {track.Artists && track.Artists.length > 0 ? track.Artists.join(', ') : 'Unknown Artist'}
    ) : showType === 'album' ? (
    {track.Album || 'Unknown Album'}
    ) : ( <>
    {track.Artists && track.Artists.length > 0 ? track.Artists.join(', ') : 'Unknown Artist'}
    {track.Album || 'Unknown Album'}
    )}
    {track.offlineState && (
    {track.offlineState === 'downloading' && (
    )} {track.offlineState === 'downloaded' && (
    )} {track.offlineState === 'deleting' && (
    )} {track.offlineState === 'accepted' && (
    )} {track.offlineState === 'processing' && (
    )} {track.offlineState === 'finished' && (
    )} {track.offlineState === 'uploading' && (
    )}
    )} {isFavorite && (
    )}
    {formatDuration(track.RunTimeTicks || 0)}
  • ) } if (isLoading && tracks.length === 0) { return } if (!isLoading && tracks.length === 0) { return
    No tracks were found
    } return ( ) }