quintodrome/ui/src/common/ContextMenus.js

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

217 lines
5.3 KiB
JavaScript
Raw Normal View History

2020-04-29 17:25:43 -08:00
import React, { useState } from 'react'
import PropTypes from 'prop-types'
import { useDispatch } from 'react-redux'
2020-04-29 16:03:40 -08:00
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'
2020-08-22 19:41:25 -08:00
import { useDataProvider, useNotify, useTranslate } from 'react-admin'
2020-11-18 19:33:34 -09:00
import clsx from 'clsx'
import {
playNext,
addTracks,
playTracks,
shuffleTracks,
openAddToPlaylist,
} from '../actions'
import subsonic from '../subsonic'
import { LoveButton } from './LoveButton'
import config from '../config'
import { formatBytes } from '../utils'
2020-04-29 16:03:40 -08:00
const useStyles = makeStyles({
noWrap: {
whiteSpace: 'nowrap',
},
menu: {
color: (props) => props.color,
},
})
2020-08-14 09:19:32 -08:00
const ContextMenu = ({
resource,
showLove,
2020-08-14 09:19:32 -08:00
record,
color,
2020-11-18 19:33:34 -09:00
className,
2020-08-14 09:19:32 -08:00
songQueryParams,
}) => {
2020-11-18 19:33:34 -09:00
const classes = useStyles({ color })
2020-04-29 17:25:43 -08:00
const dataProvider = useDataProvider()
2020-04-29 16:03:40 -08:00
const dispatch = useDispatch()
2020-04-29 17:25:43 -08:00
const translate = useTranslate()
const notify = useNotify()
2020-04-29 16:03:40 -08:00
const [anchorEl, setAnchorEl] = useState(null)
2020-04-29 16:03:40 -08:00
const options = {
2020-04-29 17:25:43 -08:00
play: {
enabled: true,
2020-08-14 08:11:35 -08:00
needData: true,
label: translate('resources.album.actions.playAll'),
action: (data, ids) => dispatch(playTracks(data, ids)),
2020-04-29 17:25:43 -08:00
},
2020-09-21 16:10:52 -08:00
playNext: {
enabled: true,
2020-09-21 16:10:52 -08:00
needData: true,
label: translate('resources.album.actions.playNext'),
2020-09-21 16:10:52 -08:00
action: (data, ids) => dispatch(playNext(data, ids)),
},
addToQueue: {
enabled: true,
2020-08-14 08:11:35 -08:00
needData: true,
label: translate('resources.album.actions.addToQueue'),
action: (data, ids) => dispatch(addTracks(data, ids)),
},
2020-04-29 17:25:43 -08:00
shuffle: {
enabled: true,
2020-08-14 08:11:35 -08:00
needData: true,
label: translate('resources.album.actions.shuffle'),
action: (data, ids) => dispatch(shuffleTracks(data, ids)),
},
addToPlaylist: {
enabled: true,
2020-08-14 08:11:35 -08:00
needData: true,
label: translate('resources.album.actions.addToPlaylist'),
action: (data, ids) => dispatch(openAddToPlaylist({ selectedIds: ids })),
},
download: {
enabled: config.enableDownloads && record.size,
2020-08-14 08:11:35 -08:00
needData: false,
label: `${translate('resources.album.actions.download')} (${formatBytes(
record.size
)})`,
action: () => subsonic.download(record.id),
2020-04-29 17:25:43 -08:00
},
2020-04-29 16:03:40 -08:00
}
const handleClick = (e) => {
e.preventDefault()
setAnchorEl(e.currentTarget)
2020-05-01 07:27:09 -08:00
e.stopPropagation()
2020-04-29 16:03:40 -08:00
}
const handleOnClose = (e) => {
e.preventDefault()
setAnchorEl(null)
2020-05-01 07:27:09 -08:00
e.stopPropagation()
2020-04-29 16:03:40 -08:00
}
2020-05-29 12:59:38 -08:00
let extractSongsData = function (response) {
const data = response.data.reduce(
(acc, cur) => ({ ...acc, [cur.id]: cur }),
{}
)
2020-05-29 12:59:38 -08:00
const ids = response.data.map((r) => r.id)
return { data, ids }
}
2020-04-29 16:03:40 -08:00
const handleItemClick = (e) => {
setAnchorEl(null)
2020-04-29 17:25:43 -08:00
const key = e.target.getAttribute('value')
2020-08-14 08:11:35 -08:00
if (options[key].needData) {
dataProvider
2020-08-14 08:27:49 -08:00
.getList('albumSong', songQueryParams)
2020-08-14 08:11:35 -08:00
.then((response) => {
let { data, ids } = extractSongsData(response)
options[key].action(data, ids)
})
.catch(() => {
notify('ra.page.error', 'warning')
})
} else {
options[key].action()
}
2020-05-01 07:27:09 -08:00
e.stopPropagation()
2020-04-29 16:03:40 -08:00
}
const open = Boolean(anchorEl)
2020-04-29 16:03:40 -08:00
return (
2020-11-18 19:33:34 -09:00
<span className={clsx(classes.noWrap, className)}>
<LoveButton
2020-08-25 18:48:05 -08:00
record={record}
resource={resource}
visible={config.enableFavourites && showLove}
2020-08-25 18:48:05 -08:00
color={color}
/>
2020-04-29 16:03:40 -08:00
<IconButton
aria-label="more"
aria-controls="context-menu"
aria-haspopup="true"
className={classes.menu}
2020-04-29 16:03:40 -08:00
onClick={handleClick}
2020-05-02 10:50:15 -08:00
size={'small'}
2020-04-29 16:03:40 -08:00
>
<MoreVertIcon fontSize={'small'} />
2020-04-29 16:03:40 -08:00
</IconButton>
<Menu
id="context-menu"
anchorEl={anchorEl}
keepMounted
open={open}
2020-04-29 17:25:43 -08:00
onClose={handleOnClose}
2020-04-29 16:03:40 -08:00
>
{Object.keys(options).map(
(key) =>
options[key].enabled && (
<MenuItem value={key} key={key} onClick={handleItemClick}>
{options[key].label}
</MenuItem>
)
)}
2020-04-29 16:03:40 -08:00
</Menu>
</span>
2020-04-29 16:03:40 -08:00
)
}
export const AlbumContextMenu = (props) =>
props.record ? (
<ContextMenu
{...props}
resource={'album'}
songQueryParams={{
pagination: { page: 1, perPage: -1 },
sort: { field: 'discNumber, trackNumber', order: 'ASC' },
filter: { album_id: props.record.id, disc_number: props.discNumber },
}}
/>
) : null
2020-08-14 08:27:49 -08:00
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 ? (
<ContextMenu
{...props}
resource={'artist'}
songQueryParams={{
pagination: { page: 1, perPage: 200 },
sort: { field: 'album, discNumber, trackNumber', order: 'ASC' },
filter: { album_artist_id: props.record.id },
}}
/>
) : null
2020-08-14 08:27:49 -08:00
ArtistContextMenu.propTypes = {
record: PropTypes.object,
color: PropTypes.string,
showLove: PropTypes.bool,
2020-08-14 08:27:49 -08:00
}
ArtistContextMenu.defaultProps = {
showLove: true,
2020-08-14 08:27:49 -08:00
addLabel: true,
}