navidrome/ui/src/common/SongContextMenu.js

151 lines
3.8 KiB
JavaScript

import React, { useState } from 'react'
import PropTypes from 'prop-types'
import { useDispatch } from 'react-redux'
import { useTranslate } from 'react-admin'
import { IconButton, Menu, MenuItem } from '@material-ui/core'
import { makeStyles } from '@material-ui/core/styles'
import MoreVertIcon from '@material-ui/icons/MoreVert'
import clsx from 'clsx'
import {
playNext,
addTracks,
setTrack,
openAddToPlaylist,
openExtendedInfoDialog,
openDownloadMenu,
DOWNLOAD_MENU_SONG,
openShareMenu,
} from '../actions'
import { LoveButton } from './LoveButton'
import config from '../config'
import { formatBytes } from '../utils'
const useStyles = makeStyles({
noWrap: {
whiteSpace: 'nowrap',
},
})
export const SongContextMenu = ({
resource,
record,
showLove,
onAddToPlaylist,
className,
}) => {
const classes = useStyles()
const dispatch = useDispatch()
const translate = useTranslate()
const [anchorEl, setAnchorEl] = useState(null)
const options = {
playNow: {
enabled: true,
label: translate('resources.song.actions.playNow'),
action: (record) => dispatch(setTrack(record)),
},
playNext: {
enabled: true,
label: translate('resources.song.actions.playNext'),
action: (record) => dispatch(playNext({ [record.id]: record })),
},
addToQueue: {
enabled: true,
label: translate('resources.song.actions.addToQueue'),
action: (record) => dispatch(addTracks({ [record.id]: record })),
},
addToPlaylist: {
enabled: true,
label: translate('resources.song.actions.addToPlaylist'),
action: (record) =>
dispatch(
openAddToPlaylist({
selectedIds: [record.mediaFileId || record.id],
onSuccess: (id) => onAddToPlaylist(id),
})
),
},
share: {
enabled: config.enableSharing,
label: translate('ra.action.share'),
action: (record) => {
dispatch(openShareMenu([record.id], 'song', record.title))
},
},
download: {
enabled: config.enableDownloads,
label: `${translate('ra.action.download')} (${formatBytes(record.size)})`,
action: (record) => {
dispatch(openDownloadMenu(record, DOWNLOAD_MENU_SONG))
},
},
info: {
enabled: true,
label: translate('resources.song.actions.info'),
action: (record) => dispatch(openExtendedInfoDialog(record)),
},
}
const handleClick = (e) => {
setAnchorEl(e.currentTarget)
e.stopPropagation()
}
const handleClose = (e) => {
setAnchorEl(null)
e.stopPropagation()
}
const handleItemClick = (e) => {
e.preventDefault()
setAnchorEl(null)
const key = e.target.getAttribute('value')
options[key].action(record)
e.stopPropagation()
}
const open = Boolean(anchorEl)
return (
<span className={clsx(classes.noWrap, className)}>
<LoveButton
record={record}
resource={resource}
visible={config.enableFavourites && showLove}
/>
<IconButton onClick={handleClick} size={'small'}>
<MoreVertIcon fontSize={'small'} />
</IconButton>
<Menu
id={'menu' + record.id}
anchorEl={anchorEl}
open={open}
onClose={handleClose}
>
{Object.keys(options).map(
(key) =>
options[key].enabled && (
<MenuItem value={key} key={key} onClick={handleItemClick}>
{options[key].label}
</MenuItem>
)
)}
</Menu>
</span>
)
}
SongContextMenu.propTypes = {
resource: PropTypes.string.isRequired,
record: PropTypes.object.isRequired,
onAddToPlaylist: PropTypes.func,
showLove: PropTypes.bool,
}
SongContextMenu.defaultProps = {
onAddToPlaylist: () => {},
record: {},
resource: 'song',
showLove: true,
addLabel: true,
}