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 StarIcon from '@material-ui/icons/Star' import StarBorderIcon from '@material-ui/icons/StarBorder' import { makeStyles } from '@material-ui/core/styles' import { useDataProvider, useNotify, useRefresh, useTranslate, useUpdate, } from 'react-admin' import { addTracks, playTracks, shuffleTracks } from '../audioplayer' import { openAddToPlaylist } from '../dialogs/dialogState' import subsonic from '../subsonic' const useStyles = makeStyles({ noWrap: { whiteSpace: 'nowrap', }, menu: { color: (props) => props.color, visibility: (props) => (props.visible ? 'visible' : 'hidden'), }, star: { visibility: (props) => props.visible || props.starred ? 'visible' : 'hidden', }, }) const ContextMenu = ({ resource, showStar, record, color, visible, songQueryParams, }) => { const classes = useStyles({ color, visible, starred: record.starred }) const dataProvider = useDataProvider() const dispatch = useDispatch() const translate = useTranslate() const notify = useNotify() const refresh = useRefresh() const [anchorEl, setAnchorEl] = useState(null) const options = { play: { needData: true, label: 'resources.album.actions.playAll', action: (data, ids) => dispatch(playTracks(data, ids)), }, addToQueue: { needData: true, label: 'resources.album.actions.addToQueue', action: (data, ids) => dispatch(addTracks(data, ids)), }, shuffle: { needData: true, label: 'resources.album.actions.shuffle', action: (data, ids) => dispatch(shuffleTracks(data, ids)), }, addToPlaylist: { needData: true, label: 'resources.album.actions.addToPlaylist', action: (data, ids) => dispatch(openAddToPlaylist({ selectedIds: ids })), }, download: { needData: false, label: 'resources.album.actions.download', action: () => subsonic.download(record.id), }, } 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('albumSong', songQueryParams) .then((response) => { let { data, ids } = extractSongsData(response) options[key].action(data, ids) }) .catch(() => { notify('ra.page.error', 'warning') }) } else { options[key].action() } e.stopPropagation() } const [toggleStarred, { loading: updating }] = useUpdate( resource, record.id, { ...record, starred: !record.starred, }, { undoable: false, onFailure: (error) => { console.log(error) notify('ra.page.error', 'warning') refresh() }, } ) const handleToggleStar = (e) => { toggleStarred() e.stopPropagation() } const open = Boolean(anchorEl) return ( {showStar && ( {record.starred ? ( ) : ( )} )} {Object.keys(options).map((key) => ( {translate(options[key].label)} ))} ) } export const AlbumContextMenu = (props) => ( ) AlbumContextMenu.propTypes = { record: PropTypes.object, discNumber: PropTypes.number, visible: PropTypes.bool, color: PropTypes.string, showStar: PropTypes.bool, } AlbumContextMenu.defaultProps = { visible: true, showStar: true, addLabel: true, } export const ArtistContextMenu = (props) => ( ) ArtistContextMenu.propTypes = { record: PropTypes.object, visible: PropTypes.bool, color: PropTypes.string, showStar: PropTypes.bool, } ArtistContextMenu.defaultProps = { visible: true, showStar: true, addLabel: true, }