import React, { memo } from 'react'; import { useNavigate } from 'react-router-dom'; import { Play, HardDriveDownload, Check } from 'lucide-react'; import { SubsonicAlbum, buildCoverArtUrl, coverArtCacheKey } from '../api/subsonic'; import { usePlayerStore } from '../store/playerStore'; import { useOfflineStore } from '../store/offlineStore'; import { useAuthStore } from '../store/authStore'; import CachedImage from './CachedImage'; import { playAlbum } from '../utils/playAlbum'; import { useDragDrop } from '../contexts/DragDropContext'; interface AlbumCardProps { album: SubsonicAlbum; selected?: boolean; selectionMode?: boolean; onToggleSelect?: (id: string) => void; showRating?: boolean; selectedAlbums?: SubsonicAlbum[]; } function AlbumCard({ album, selected, selectionMode, onToggleSelect, showRating = false, selectedAlbums = [] }: AlbumCardProps) { const navigate = useNavigate(); const openContextMenu = usePlayerStore(s => s.openContextMenu); const serverId = useAuthStore(s => s.activeServerId ?? ''); const isOffline = useOfflineStore(s => { const meta = s.albums[`${serverId}:${album.id}`]; if (!meta || meta.trackIds.length === 0) return false; return meta.trackIds.every(tid => !!s.tracks[`${serverId}:${tid}`]); }); const coverUrl = album.coverArt ? buildCoverArtUrl(album.coverArt, 300) : ''; const psyDrag = useDragDrop(); const handleClick = () => { if (selectionMode) { onToggleSelect?.(album.id); return; } navigate(`/album/${album.id}`); }; return (
e.key === 'Enter' && handleClick()} onContextMenu={(e) => { e.preventDefault(); if (selectionMode && selectedAlbums.length > 0) { openContextMenu(e.clientX, e.clientY, selectedAlbums, 'multi-album'); } else { openContextMenu(e.clientX, e.clientY, album, 'album'); } }} onMouseDown={e => { if (selectionMode || 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: 'album', id: album.id, name: album.name }), label: album.name, coverUrl: coverUrl || undefined }, me.clientX, me.clientY); } }; const onUp = () => { document.removeEventListener('mousemove', onMove); document.removeEventListener('mouseup', onUp); }; document.addEventListener('mousemove', onMove); document.addEventListener('mouseup', onUp); }} >
{coverUrl ? ( ) : (
)} {isOffline && !selectionMode && (
)} {selectionMode && (
{selected && }
)} {!selectionMode && (
)}

{album.name}

{ if (album.artistId) { e.stopPropagation(); navigate(`/artist/${album.artistId}`); } }} >{album.artist}

{album.year &&

{album.year}

} {showRating && (album.userRating ?? 0) > 0 && (
{'★'.repeat(album.userRating!)}{'☆'.repeat(5 - album.userRating!)}
)}
); } export default memo(AlbumCard);