import { useTranslation } from 'react-i18next'; import { Play, ListPlus, Heart, Download, ChevronRight, ChevronsRight, User, ListMusic, Star, Share2 } from 'lucide-react'; import { useNavigate } from 'react-router-dom'; import { getAlbum } from '../../api/subsonicLibrary'; import { star, unstar } from '../../api/subsonicStarRating'; import type { SubsonicAlbum } from '../../api/subsonicTypes'; import { useAuthStore } from '../../store/authStore'; import { songToTrack } from '../../utils/playback/songToTrack'; import StarRating from '../StarRating'; import { AlbumToPlaylistSubmenu } from './AlbumArtistToPlaylistSubmenu'; import { MultiAlbumToPlaylistSubmenu } from './MultiAlbumToPlaylistSubmenu'; import type { ContextMenuItemsProps } from './contextMenuItemTypes'; export default function AlbumContextItems(props: ContextMenuItemsProps) { const { type, item, queueIndex, playlistId, playlistSongIndex, shareKindOverride, playTrack, playNext, enqueue, removeTrack, queue, currentTrack, closeContextMenu, starredOverrides, setStarredOverride, lastfmLovedCache, setLastfmLovedForSong, openSongInfo, userRatingOverrides, setKeyboardRating, keyboardRating, playlistSubmenuOpen, setPlaylistSubmenuOpen, cancelPlaylistSubmenuCloseTimer, onPlaylistSubmenuTriggerMouseLeave, playlistSongIds, setPlaylistSongIds, orbitRole, entityRatingSupport, audiomuseNavidromeEnabled, applySongRating, applyAlbumRating, applyArtistRating, handleAction, startRadio, startInstantMix, downloadAlbum, copyShareLink, isStarred, pinToPlaybackServer, navigateLibrary, } = props; const { t } = useTranslation(); const auth = useAuthStore(); const navigate = useNavigate(); const goLibrary = pinToPlaybackServer ? navigateLibrary : (path: string) => { navigate(path); }; return ( <> {type === 'album' && (() => { const album = item as SubsonicAlbum; const albumRatingDisabled = entityRatingSupport === 'track_only'; return ( <>
handleAction(() => goLibrary(`/album/${album.id}`))}> {t('contextMenu.openAlbum')}
handleAction(async () => { const albumData = await getAlbum(album.id); const tracks = albumData.songs.map(songToTrack); if (tracks.length === 0) return; playNext(tracks); })}> {t('contextMenu.playNext')}
handleAction(async () => { const albumData = await getAlbum(album.id); enqueue(albumData.songs.map(songToTrack)); })}> {t('contextMenu.enqueueAlbum')}
handleAction(() => goLibrary(`/artist/${album.artistId}`))}> {t('contextMenu.goToArtist')}
handleAction(() => { const starred = isStarred(album.id, album.starred); setStarredOverride(album.id, !starred); return starred ? unstar(album.id, 'album') : star(album.id, 'album'); })}> {isStarred(album.id, album.starred) ? t('contextMenu.unfavoriteAlbum') : t('contextMenu.favoriteAlbum')}
e.stopPropagation()} > { setKeyboardRating({ kind: 'album', id: album.id, value: r }); applyAlbumRating(album, r); }} />
handleAction(() => copyShareLink('album', album.id))}> {t('contextMenu.shareLink')}
handleAction(() => downloadAlbum(album.name, album.id))}> {t('contextMenu.download')}
{ cancelPlaylistSubmenuCloseTimer(); setPlaylistSongIds([`album:${album.id}`]); setPlaylistSubmenuOpen(true); }} onMouseLeave={onPlaylistSubmenuTriggerMouseLeave} > {t('contextMenu.addToPlaylist')} {playlistSubmenuOpen && playlistSongIds[0] === `album:${album.id}` && ( { setPlaylistSubmenuOpen(false); closeContextMenu(); }} /> )}
); })()} {type === 'multi-album' && (() => { const albums = item as SubsonicAlbum[]; const albumIds = albums.map(a => a.id); const albumRatingDisabled = entityRatingSupport === 'track_only'; const multiAlbumRatingId = [...albumIds].sort().join('\x1e'); const unifiedAlbumRating = (() => { if (albums.length === 0) return 0; const vals = albums.map(a => userRatingOverrides[a.id] ?? a.userRating ?? 0); const first = vals[0]; return vals.every(v => v === first) ? first : 0; })(); return ( <>
{t('contextMenu.selectedAlbums', { count: albums.length })}
handleAction(async () => { // Parallel — Navidrome handles concurrent getAlbum requests fine. const results = await Promise.all(albums.map(a => getAlbum(a.id))); const allTracks = results.flatMap(r => r.songs.map(songToTrack)); enqueue(allTracks); })}> {t('contextMenu.enqueueAlbums', { count: albums.length })}
{ cancelPlaylistSubmenuCloseTimer(); setPlaylistSongIds([`multi-album:${albumIds.join(',')}`]); setPlaylistSubmenuOpen(true); }} onMouseLeave={onPlaylistSubmenuTriggerMouseLeave} > {t('contextMenu.addToPlaylist')} {playlistSubmenuOpen && playlistSongIds[0] === `multi-album:${albumIds.join(',')}` && ( { setPlaylistSubmenuOpen(false); closeContextMenu(); }} /> )}
e.stopPropagation()} > { setKeyboardRating({ kind: 'album', id: multiAlbumRatingId, value: r }); for (const a of albums) applyAlbumRating(a, r); }} />
); })()} ); }