import React, { useState } from 'react' import PropTypes from 'prop-types' import { useDispatch } from 'react-redux' import IconButton from '@material-ui/core/IconButton' import Menu from '@material-ui/core/Menu' import MenuItem from '@material-ui/core/MenuItem' import MoreVertIcon from '@material-ui/icons/MoreVert' import { makeStyles } from '@material-ui/core/styles' import { useDataProvider, useNotify, useTranslate } from 'react-admin' import clsx from 'clsx' import { playNext, addTracks, playTracks, shuffleTracks, openAddToPlaylist, openDownloadMenu, openExtendedInfoDialog, DOWNLOAD_MENU_ALBUM, DOWNLOAD_MENU_ARTIST, openShareMenu, } from '../actions' import { LoveButton } from './LoveButton' import config from '../config' import { formatBytes } from '../utils' const useStyles = makeStyles({ noWrap: { whiteSpace: 'nowrap', }, menu: { color: (props) => props.color, }, }) const ContextMenu = ({ resource, showLove, record, color, className, songQueryParams, hideInfo, }) => { const classes = useStyles({ color }) const dataProvider = useDataProvider() const dispatch = useDispatch() const translate = useTranslate() const notify = useNotify() const [anchorEl, setAnchorEl] = useState(null) const options = { play: { enabled: true, needData: true, label: translate('resources.album.actions.playAll'), action: (data, ids) => dispatch(playTracks(data, ids)), }, playNext: { enabled: true, needData: true, label: translate('resources.album.actions.playNext'), action: (data, ids) => dispatch(playNext(data, ids)), }, addToQueue: { enabled: true, needData: true, label: translate('resources.album.actions.addToQueue'), action: (data, ids) => dispatch(addTracks(data, ids)), }, shuffle: { enabled: true, needData: true, label: translate('resources.album.actions.shuffle'), action: (data, ids) => dispatch(shuffleTracks(data, ids)), }, addToPlaylist: { enabled: true, needData: true, label: translate('resources.album.actions.addToPlaylist'), action: (data, ids) => dispatch(openAddToPlaylist({ selectedIds: ids })), }, share: { enabled: config.enableSharing, needData: false, label: translate('ra.action.share'), action: (record) => dispatch(openShareMenu([record.id], resource, record.name)), }, download: { enabled: config.enableDownloads && record.size, needData: false, label: `${translate('ra.action.download')} (${formatBytes(record.size)})`, action: () => { dispatch( openDownloadMenu( record, record.duration !== undefined ? DOWNLOAD_MENU_ALBUM : DOWNLOAD_MENU_ARTIST ) ) }, }, ...(!hideInfo && { info: { enabled: true, needData: true, label: translate('resources.album.actions.info'), action: () => dispatch(openExtendedInfoDialog(record)), }, }), } const handleClick = (e) => { e.preventDefault() setAnchorEl(e.currentTarget) e.stopPropagation() } const handleOnClose = (e) => { e.preventDefault() setAnchorEl(null) e.stopPropagation() } let extractSongsData = function (response) { const data = response.data.reduce( (acc, cur) => ({ ...acc, [cur.id]: cur }), {} ) const ids = response.data.map((r) => r.id) return { data, ids } } const handleItemClick = (e) => { setAnchorEl(null) const key = e.target.getAttribute('value') if (options[key].needData) { dataProvider .getList('song', songQueryParams) .then((response) => { let { data, ids } = extractSongsData(response) options[key].action(data, ids) }) .catch(() => { notify('ra.page.error', 'warning') }) } else { options[key].action(record) } e.stopPropagation() } const open = Boolean(anchorEl) return ( {Object.keys(options).map( (key) => options[key].enabled && ( {options[key].label} ) )} ) } export const AlbumContextMenu = (props) => props.record ? ( ) : null AlbumContextMenu.propTypes = { record: PropTypes.object, discNumber: PropTypes.number, color: PropTypes.string, showLove: PropTypes.bool, } AlbumContextMenu.defaultProps = { showLove: true, addLabel: true, } export const ArtistContextMenu = (props) => props.record ? ( ) : null ArtistContextMenu.propTypes = { record: PropTypes.object, color: PropTypes.string, showLove: PropTypes.bool, } ArtistContextMenu.defaultProps = { showLove: true, addLabel: true, }