Only show SongContextMenu on hover

This commit is contained in:
Deluan
2020-05-22 20:15:58 -04:00
parent ae847103a2
commit 978e7f2eaa
6 changed files with 88 additions and 24 deletions
+6 -2
View File
@@ -14,8 +14,12 @@ import { useDispatch } from 'react-redux'
import { Card, useMediaQuery } from '@material-ui/core' import { Card, useMediaQuery } from '@material-ui/core'
import { makeStyles } from '@material-ui/core/styles' import { makeStyles } from '@material-ui/core/styles'
import { playTracks } from '../audioplayer' import { playTracks } from '../audioplayer'
import { DurationField, SongDetails, SongDatagridRow } from '../common' import {
import { SongContextMenu } from '../song/SongContextMenu' DurationField,
SongDetails,
SongDatagridRow,
SongContextMenu,
} from '../common'
const useStyles = makeStyles( const useStyles = makeStyles(
(theme) => ({ (theme) => ({
@@ -9,17 +9,24 @@ import StarIcon from '@material-ui/icons/Star'
import StarBorderIcon from '@material-ui/icons/StarBorder' import StarBorderIcon from '@material-ui/icons/StarBorder'
import NestedMenuItem from 'material-ui-nested-menu-item' import NestedMenuItem from 'material-ui-nested-menu-item'
import { addTracks, setTrack } from '../audioplayer' import { addTracks, setTrack } from '../audioplayer'
import { AddToPlaylistMenu } from '../common' import AddToPlaylistMenu from './AddToPlaylistMenu'
import config from '../config' import config from '../config'
const useStyles = makeStyles({ const useStyles = makeStyles({
noWrap: { noWrap: {
whiteSpace: 'nowrap', whiteSpace: 'nowrap',
}, },
menu: {
visibility: (props) => (props.visible ? 'visible' : 'hidden'),
},
star: {
visibility: (props) =>
props.visible || props.starred ? 'visible' : 'hidden',
},
}) })
export const SongContextMenu = ({ className, record, onAddToPlaylist }) => { const SongContextMenu = ({ record, onAddToPlaylist, visible }) => {
const classes = useStyles() const classes = useStyles({ visible, starred: record.starred })
const dispatch = useDispatch() const dispatch = useDispatch()
const translate = useTranslate() const translate = useTranslate()
const notify = useNotify() const notify = useNotify()
@@ -54,7 +61,7 @@ export const SongContextMenu = ({ className, record, onAddToPlaylist }) => {
e.stopPropagation() e.stopPropagation()
} }
const [toggleStar, { toggling: loading }] = useUpdate( const [updateRecord, { loading: updating }] = useUpdate(
'albumSong', 'albumSong',
record.id, record.id,
record, record,
@@ -68,26 +75,36 @@ export const SongContextMenu = ({ className, record, onAddToPlaylist }) => {
} }
) )
const handleToggleStar = (e, record) => { const toggleStar = (record) => {
record.starred = !record.starred record.starred = !record.starred
toggleStar() updateRecord()
}
const handleToggleStar = (e, record) => {
toggleStar(record)
e.stopPropagation() e.stopPropagation()
} }
const open = Boolean(anchorEl) const open = Boolean(anchorEl)
return ( return (
<span className={`${classes.noWrap} ${className}`}> <span className={classes.noWrap}>
{config.enableStarred && !onAddToPlaylist && ( {config.enableStarred && !onAddToPlaylist && (
<IconButton <IconButton
onClick={(e) => handleToggleStar(e, record)} onClick={(e) => handleToggleStar(e, record)}
size={'small'} size={'small'}
disabled={loading} disabled={updating}
className={classes.star}
> >
{record.starred ? <StarIcon /> : <StarBorderIcon />} {record.starred ? <StarIcon /> : <StarBorderIcon />}
</IconButton> </IconButton>
)} )}
<IconButton onClick={handleClick} size={'small'}> <IconButton
onClick={handleClick}
size={'small'}
className={classes.menu}
disabled={updating}
>
<MoreVertIcon /> <MoreVertIcon />
</IconButton> </IconButton>
<Menu <Menu
@@ -119,4 +136,7 @@ export const SongContextMenu = ({ className, record, onAddToPlaylist }) => {
SongContextMenu.propTypes = { SongContextMenu.propTypes = {
record: PropTypes.object, record: PropTypes.object,
onAddToPlaylist: PropTypes.func, onAddToPlaylist: PropTypes.func,
visible: PropTypes.bool,
} }
export default SongContextMenu
+17 -5
View File
@@ -1,17 +1,18 @@
import React from 'react' import React, { useState, isValidElement, cloneElement } from 'react'
import { DatagridRow, useTranslate } from 'react-admin' import { DatagridRow, useTranslate } from 'react-admin'
import { TableRow, TableCell, Typography } from '@material-ui/core' import { TableCell, TableRow, Typography } from '@material-ui/core'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
import RangeField from './RangeField' import RangeField from './RangeField'
const SongDatagridRow = ({ record, children, multiDisc, ...rest }) => { const SongDatagridRow = ({ record, children, multiDisc, ...rest }) => {
const translate = useTranslate() const translate = useTranslate()
const [visible, setVisible] = useState(false)
return ( return (
<> <>
{multiDisc && ( {multiDisc && (
<TableRow> <TableRow>
{record.trackNumber === 1 && ( {record.trackNumber === 1 && (
<TableCell colSpan={children.length + 1}> <TableCell colSpan={children.length + 2}>
<Typography variant="h6"> <Typography variant="h6">
{record.discSubtitle {record.discSubtitle
? translate('message.discSubtitle', { ? translate('message.discSubtitle', {
@@ -26,8 +27,19 @@ const SongDatagridRow = ({ record, children, multiDisc, ...rest }) => {
)} )}
</TableRow> </TableRow>
)} )}
<DatagridRow record={record} {...rest}> <DatagridRow
{children} record={record}
onMouseEnter={() => setVisible(true)}
onMouseLeave={() => setVisible(false)}
{...rest}
>
{React.Children.map(children, (child) =>
child &&
isValidElement(child) &&
child.type.name === 'SongContextMenu'
? cloneElement(child, { visible, ...rest })
: child
)}
</DatagridRow> </DatagridRow>
</> </>
) )
+2
View File
@@ -12,6 +12,7 @@ import DocLink from './DocLink'
import List from './List' import List from './List'
import SongDatagridRow from './SongDatagridRow' import SongDatagridRow from './SongDatagridRow'
import AddToPlaylistMenu from './AddToPlaylistMenu' import AddToPlaylistMenu from './AddToPlaylistMenu'
import SongContextMenu from './SongContextMenu'
export { export {
Title, Title,
@@ -30,4 +31,5 @@ export {
ArtistLinkField, ArtistLinkField,
artistLink, artistLink,
AddToPlaylistMenu, AddToPlaylistMenu,
SongContextMenu,
} }
+16 -4
View File
@@ -2,6 +2,7 @@ import React from 'react'
import { import {
BulkActionsToolbar, BulkActionsToolbar,
Datagrid, Datagrid,
DatagridBody,
DatagridLoading, DatagridLoading,
ListToolbar, ListToolbar,
TextField, TextField,
@@ -11,8 +12,12 @@ import {
import classnames from 'classnames' import classnames from 'classnames'
import { Card, useMediaQuery } from '@material-ui/core' import { Card, useMediaQuery } from '@material-ui/core'
import { makeStyles } from '@material-ui/core/styles' import { makeStyles } from '@material-ui/core/styles'
import { DurationField, SongDetails } from '../common' import {
import { SongContextMenu } from '../song/SongContextMenu' DurationField,
SongDetails,
SongContextMenu,
SongDatagridRow,
} from '../common'
const useStyles = makeStyles( const useStyles = makeStyles(
(theme) => ({ (theme) => ({
@@ -50,6 +55,13 @@ const useStylesListToolbar = makeStyles({
}, },
}) })
const SongsDatagridBody = (props) => (
<DatagridBody {...props} row={<SongDatagridRow />} />
)
const SongsDatagrid = (props) => (
<Datagrid {...props} body={<SongsDatagridBody />} />
)
const PlaylistSongs = (props) => { const PlaylistSongs = (props) => {
const classes = useStyles(props) const classes = useStyles(props)
const classesToolbar = useStylesListToolbar(props) const classesToolbar = useStylesListToolbar(props)
@@ -106,7 +118,7 @@ const PlaylistSongs = (props) => {
size={'small'} size={'small'}
/> />
) : ( ) : (
<Datagrid <SongsDatagrid
expand={!isXsmall && <SongDetails />} expand={!isXsmall && <SongDetails />}
rowClick={null} rowClick={null}
{...controllerProps} {...controllerProps}
@@ -117,7 +129,7 @@ const PlaylistSongs = (props) => {
{isDesktop && <TextField source="artist" />} {isDesktop && <TextField source="artist" />}
<DurationField source="duration" /> <DurationField source="duration" />
<SongContextMenu onAddToPlaylist={onAddToPlaylist} /> <SongContextMenu onAddToPlaylist={onAddToPlaylist} />
</Datagrid> </SongsDatagrid>
)} )}
</Card> </Card>
</div> </div>
+18 -4
View File
@@ -1,6 +1,7 @@
import React from 'react' import React from 'react'
import { import {
Datagrid, Datagrid,
DatagridBody,
Filter, Filter,
FunctionField, FunctionField,
NumberField, NumberField,
@@ -8,12 +9,18 @@ import {
TextField, TextField,
} from 'react-admin' } from 'react-admin'
import { useMediaQuery } from '@material-ui/core' import { useMediaQuery } from '@material-ui/core'
import { DurationField, SimpleList, List, SongDetails } from '../common' import {
DurationField,
SimpleList,
List,
SongDetails,
SongDatagridRow,
SongContextMenu,
} from '../common'
import { useDispatch } from 'react-redux' import { useDispatch } from 'react-redux'
import { setTrack } from '../audioplayer' import { setTrack } from '../audioplayer'
import { SongBulkActions } from './SongBulkActions' import { SongBulkActions } from './SongBulkActions'
import { AlbumLinkField } from './AlbumLinkField' import { AlbumLinkField } from './AlbumLinkField'
import { SongContextMenu } from './SongContextMenu'
const SongFilter = (props) => ( const SongFilter = (props) => (
<Filter {...props}> <Filter {...props}>
@@ -21,6 +28,13 @@ const SongFilter = (props) => (
</Filter> </Filter>
) )
const SongsDatagridBody = (props) => (
<DatagridBody {...props} row={<SongDatagridRow />} />
)
const SongsDatagrid = (props) => (
<Datagrid {...props} body={<SongsDatagridBody />} />
)
const SongList = (props) => { const SongList = (props) => {
const dispatch = useDispatch() const dispatch = useDispatch()
const isXsmall = useMediaQuery((theme) => theme.breakpoints.down('xs')) const isXsmall = useMediaQuery((theme) => theme.breakpoints.down('xs'))
@@ -48,7 +62,7 @@ const SongList = (props) => {
rightIcon={(r) => <SongContextMenu record={r} />} rightIcon={(r) => <SongContextMenu record={r} />}
/> />
) : ( ) : (
<Datagrid <SongsDatagrid
expand={<SongDetails />} expand={<SongDetails />}
rowClick={(id, basePath, record) => dispatch(setTrack(record))} rowClick={(id, basePath, record) => dispatch(setTrack(record))}
> >
@@ -62,7 +76,7 @@ const SongList = (props) => {
)} )}
<DurationField source="duration" /> <DurationField source="duration" />
<SongContextMenu /> <SongContextMenu />
</Datagrid> </SongsDatagrid>
)} )}
</List> </List>
) )