import { formatDuration } from '@/web/utils/common' import { css, cx } from '@emotion/css' import player from '@/web/states/player' import { useSnapshot } from 'valtio' import Wave from './Wave' import Icon from '@/web/components/Icon' import useIsMobile from '@/web/hooks/useIsMobile' import useUserLikedTracksIDs, { useMutationLikeATrack } from '@/web/api/hooks/useUserLikedTracksIDs' import toast from 'react-hot-toast' import { memo, useEffect, useMemo, useState } from 'react' import contextMenus, { openContextMenu } from '@/web/states/contextMenus' import regexifyString from 'regexify-string' import { NavLink } from 'react-router-dom' const Actions = ({ track }: { track: Track }) => { const { data: likedTracksIDs } = useUserLikedTracksIDs() const likeATrack = useMutationLikeATrack() // 当右键菜单开启时,让按钮组在鼠标移走了后也能继续显示 const [isContextMenuOpen, setIsContextMenuOpen] = useState(false) const menu = useSnapshot(contextMenus) useEffect(() => { if (menu.type !== 'track' || !menu.dataSourceID) { setIsContextMenuOpen(false) } }, [menu.dataSourceID, menu.type]) return (
e.stopPropagation()}> {/* Context menu */}
{/* Add to playlist */} {/* Like */}
) } function Track({ track, handleClick, }: { track: Track handleClick: (e: React.MouseEvent, trackID: number) => void }) { const { track: playingTrack, state } = useSnapshot(player) return (
handleClick(e, track.id)} onContextMenu={e => handleClick(e, track.id)} className='group relative flex h-14 items-center py-2 text-16 font-medium text-neutral-200 transition duration-300' > {/* Track no */}
{playingTrack?.id === track.id ? ( ) : ( String(track.no).padStart(2, '0') )}
{/* Track name */}
{track?.name} {/* Explicit symbol */} {[1318912, 1310848].includes(track.mark) && ( )} {/* Other artists */} {track?.ar?.length > 1 && (
- {track.ar.slice(1).map((artist, index) => ( {artist.name} {index !== track.ar.length - 2 && ', '} ))}
)}
{/* Desktop menu */} {/* Mobile menu */}
{/* Track duration */}
{formatDuration(track.dt, 'en-US', 'hh:mm:ss')}
) } const TrackList = ({ tracks, onPlay, className, isLoading, placeholderRows = 12, }: { tracks?: Track[] onPlay: (id: number) => void className?: string isLoading?: boolean placeholderRows?: number }) => { const isMobile = useIsMobile() const handleClick = (e: React.MouseEvent, trackID: number) => { if (isLoading) return if (e.type === 'contextmenu') { e.preventDefault() openContextMenu({ event: e, type: 'track', dataSourceID: trackID, options: { useCursorPosition: true, }, }) return } if (isMobile) { onPlay?.(trackID) } else { if (e.detail === 2) onPlay?.(trackID) } } return (
{(isLoading ? [] : tracks)?.map(track => ( ))} {(isLoading ? Array.from(new Array(placeholderRows).keys()) : []).map(index => (
{/* Track no */}
00
{/* Track name */}
PLACEHOLDER1234567
{/* Track duration */}
00:00
))}
) } const memorizedTrackList = memo(TrackList) memorizedTrackList.displayName = 'TrackList' export default memorizedTrackList