Fix song context menu "on hover" visibility

This commit is contained in:
Deluan
2020-11-26 15:08:26 -05:00
committed by Deluan Quintão
parent f5808288ab
commit a42fb024be
7 changed files with 100 additions and 61 deletions
-1
View File
@@ -10,7 +10,6 @@ import AlbumDetails from './AlbumDetails'
import AlbumActions from './AlbumActions' import AlbumActions from './AlbumActions'
const AlbumShowLayout = (props) => { const AlbumShowLayout = (props) => {
console.log('show', props)
const { loading, ...context } = useShowContext(props) const { loading, ...context } = useShowContext(props)
const { record } = context const { record } = context
+17 -7
View File
@@ -56,18 +56,26 @@ const useStyles = makeStyles(
toolbar: { toolbar: {
justifyContent: 'flex-start', justifyContent: 'flex-start',
}, },
row: {
'&:hover': {
'& $contextMenu': {
visibility: 'visible',
},
},
},
contextMenu: {
visibility: 'hidden',
},
}), }),
{ name: 'RaList' } { name: 'RaList' }
) )
const AlbumSongs = (props) => { const AlbumSongs = (props) => {
console.log('songs', props)
const listContext = props
const classes = useStyles(props) const classes = useStyles(props)
const dispatch = useDispatch() const dispatch = useDispatch()
const isXsmall = useMediaQuery((theme) => theme.breakpoints.down('xs')) const isXsmall = useMediaQuery((theme) => theme.breakpoints.down('xs'))
const isDesktop = useMediaQuery((theme) => theme.breakpoints.up('md')) const isDesktop = useMediaQuery((theme) => theme.breakpoints.up('md'))
const { id: album_id, data, ids } = listContext const { id: album_id, data, ids } = props
const version = useVersion() const version = useVersion()
return ( return (
<> <>
@@ -75,25 +83,26 @@ const AlbumSongs = (props) => {
classes={{ toolbar: classes.toolbar }} classes={{ toolbar: classes.toolbar }}
actions={props.actions} actions={props.actions}
permanentFilter={{ album_id }} permanentFilter={{ album_id }}
{...listContext} {...props}
/> />
<div className={classes.main}> <div className={classes.main}>
<Card <Card
className={classnames(classes.content, { className={classnames(classes.content, {
[classes.bulkActionsDisplayed]: listContext.selectedIds.length > 0, [classes.bulkActionsDisplayed]: props.selectedIds.length > 0,
})} })}
key={version} key={version}
> >
<BulkActionsToolbar {...listContext}> <BulkActionsToolbar {...props}>
<SongBulkActions /> <SongBulkActions />
</BulkActionsToolbar> </BulkActionsToolbar>
<SongDatagrid <SongDatagrid
expand={isXsmall ? null : <SongDetails />} expand={isXsmall ? null : <SongDetails />}
rowClick={(id) => dispatch(playTracks(data, ids, id))} rowClick={(id) => dispatch(playTracks(data, ids, id))}
{...listContext} {...props}
hasBulkActions={true} hasBulkActions={true}
showDiscSubtitles={true} showDiscSubtitles={true}
contextAlwaysVisible={!isDesktop} contextAlwaysVisible={!isDesktop}
classes={{ row: classes.row }}
> >
{isDesktop && ( {isDesktop && (
<TextField <TextField
@@ -113,6 +122,7 @@ const AlbumSongs = (props) => {
<SongContextMenu <SongContextMenu
source={'starred'} source={'starred'}
sortable={false} sortable={false}
className={classes.contextMenu}
label={ label={
<StarBorderIcon <StarBorderIcon
fontSize={'small'} fontSize={'small'}
+5 -3
View File
@@ -21,7 +21,7 @@ import {
import { makeStyles } from '@material-ui/core/styles' import { makeStyles } from '@material-ui/core/styles'
const useStyles = makeStyles({ const useStyles = makeStyles({
columnIcon: { contextHeader: {
marginLeft: '3px', marginLeft: '3px',
marginTop: '-2px', marginTop: '-2px',
verticalAlign: 'text-top', verticalAlign: 'text-top',
@@ -75,9 +75,11 @@ const ArtistListView = ({ hasShow, hasEdit, hasList, width, ...rest }) => {
sortByOrder={'DESC'} sortByOrder={'DESC'}
className={classes.contextMenu} className={classes.contextMenu}
label={ label={
<StarBorderIcon fontSize={'small'} className={classes.columnIcon} /> <StarBorderIcon
fontSize={'small'}
className={classes.contextHeader}
/>
} }
textAlign={'right'}
/> />
</Datagrid> </Datagrid>
) )
+6 -12
View File
@@ -5,6 +5,7 @@ import { useTranslate } from 'react-admin'
import { IconButton, Menu, MenuItem } from '@material-ui/core' import { IconButton, Menu, MenuItem } from '@material-ui/core'
import { makeStyles } from '@material-ui/core/styles' import { makeStyles } from '@material-ui/core/styles'
import MoreVertIcon from '@material-ui/icons/MoreVert' import MoreVertIcon from '@material-ui/icons/MoreVert'
import clsx from 'clsx'
import { playNext, addTracks, setTrack, openAddToPlaylist } from '../actions' import { playNext, addTracks, setTrack, openAddToPlaylist } from '../actions'
import subsonic from '../subsonic' import subsonic from '../subsonic'
import { StarButton } from './StarButton' import { StarButton } from './StarButton'
@@ -15,9 +16,6 @@ const useStyles = makeStyles({
noWrap: { noWrap: {
whiteSpace: 'nowrap', whiteSpace: 'nowrap',
}, },
menu: {
visibility: (props) => (props.visible ? 'visible' : 'hidden'),
},
}) })
export const SongContextMenu = ({ export const SongContextMenu = ({
@@ -25,9 +23,9 @@ export const SongContextMenu = ({
record, record,
showStar, showStar,
onAddToPlaylist, onAddToPlaylist,
visible, className,
}) => { }) => {
const classes = useStyles({ visible }) const classes = useStyles()
const dispatch = useDispatch() const dispatch = useDispatch()
const translate = useTranslate() const translate = useTranslate()
const [anchorEl, setAnchorEl] = useState(null) const [anchorEl, setAnchorEl] = useState(null)
@@ -88,11 +86,9 @@ export const SongContextMenu = ({
const open = Boolean(anchorEl) const open = Boolean(anchorEl)
return ( return (
<span className={classes.noWrap}> <span className={clsx(classes.noWrap, className)}>
{showStar && ( <StarButton record={record} resource={resource} visible={showStar} />
<StarButton record={record} resource={resource} visible={visible} /> <IconButton onClick={handleClick} size={'small'}>
)}
<IconButton onClick={handleClick} size={'small'} className={classes.menu}>
<MoreVertIcon fontSize={'small'} /> <MoreVertIcon fontSize={'small'} />
</IconButton> </IconButton>
<Menu <Menu
@@ -118,7 +114,6 @@ SongContextMenu.propTypes = {
resource: PropTypes.string.isRequired, resource: PropTypes.string.isRequired,
record: PropTypes.object.isRequired, record: PropTypes.object.isRequired,
onAddToPlaylist: PropTypes.func, onAddToPlaylist: PropTypes.func,
visible: PropTypes.bool,
showStar: PropTypes.bool, showStar: PropTypes.bool,
} }
@@ -126,7 +121,6 @@ SongContextMenu.defaultProps = {
onAddToPlaylist: () => {}, onAddToPlaylist: () => {},
record: {}, record: {},
resource: 'song', resource: 'song',
visible: true,
showStar: true, showStar: true,
addLabel: true, addLabel: true,
} }
+25 -26
View File
@@ -1,23 +1,15 @@
import React, { import React, { isValidElement, useMemo, useCallback } from 'react'
useState,
isValidElement,
cloneElement,
useMemo,
useCallback,
} from 'react'
import { useDispatch } from 'react-redux' import { useDispatch } from 'react-redux'
import { Datagrid, DatagridBody, DatagridRow } from 'react-admin' import { Datagrid, DatagridBody, DatagridRow } from 'react-admin'
import { TableCell, TableRow, Typography } from '@material-ui/core' import { TableCell, TableRow, Typography } from '@material-ui/core'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
import { makeStyles } from '@material-ui/core/styles' import { makeStyles } from '@material-ui/core/styles'
import AlbumIcon from '@material-ui/icons/Album' import AlbumIcon from '@material-ui/icons/Album'
import clsx from 'clsx'
import { playTracks } from '../actions' import { playTracks } from '../actions'
import { AlbumContextMenu } from '../common' import { AlbumContextMenu } from '../common'
const useStyles = makeStyles({ const useStyles = makeStyles({
row: {
cursor: 'pointer',
},
subtitle: { subtitle: {
whiteSpace: 'nowrap', whiteSpace: 'nowrap',
overflow: 'hidden', overflow: 'hidden',
@@ -28,6 +20,17 @@ const useStyles = makeStyles({
verticalAlign: 'text-top', verticalAlign: 'text-top',
marginRight: '4px', marginRight: '4px',
}, },
row: {
cursor: 'pointer',
'&:hover': {
'& $contextMenu': {
visibility: 'visible',
},
},
},
contextMenu: {
visibility: 'hidden',
},
}) })
const DiscSubtitleRow = ({ const DiscSubtitleRow = ({
@@ -37,7 +40,6 @@ const DiscSubtitleRow = ({
contextAlwaysVisible, contextAlwaysVisible,
}) => { }) => {
const classes = useStyles() const classes = useStyles()
const [visible, setVisible] = useState(false)
const handlePlayDisc = (discNumber) => () => { const handlePlayDisc = (discNumber) => () => {
onClick(discNumber) onClick(discNumber)
} }
@@ -45,8 +47,6 @@ const DiscSubtitleRow = ({
<TableRow <TableRow
hover hover
onClick={handlePlayDisc(record.discNumber)} onClick={handlePlayDisc(record.discNumber)}
onMouseEnter={() => setVisible(true)}
onMouseLeave={() => setVisible(false)}
className={classes.row} className={classes.row}
> >
<TableCell colSpan={colSpan}> <TableCell colSpan={colSpan}>
@@ -61,7 +61,8 @@ const DiscSubtitleRow = ({
record={{ id: record.albumId }} record={{ id: record.albumId }}
discNumber={record.discNumber} discNumber={record.discNumber}
showStar={false} showStar={false}
visible={contextAlwaysVisible || visible} className={classes.contextMenu}
visible={contextAlwaysVisible}
/> />
</TableCell> </TableCell>
</TableRow> </TableRow>
@@ -74,9 +75,10 @@ export const SongDatagridRow = ({
firstTracks, firstTracks,
contextAlwaysVisible, contextAlwaysVisible,
onClickDiscSubtitle, onClickDiscSubtitle,
className,
...rest ...rest
}) => { }) => {
const [visible, setVisible] = useState(false) const classes = useStyles()
const fields = React.Children.toArray(children).filter((c) => const fields = React.Children.toArray(children).filter((c) =>
isValidElement(c) isValidElement(c)
) )
@@ -93,17 +95,10 @@ export const SongDatagridRow = ({
)} )}
<DatagridRow <DatagridRow
record={record} record={record}
onMouseMove={() => setVisible(true)}
onMouseLeave={() => setVisible(false)}
{...rest} {...rest}
className={clsx(className, classes.row)}
> >
{fields.map((child, index) => {fields}
index < childCount - 1
? child
: cloneElement(child, {
visible: contextAlwaysVisible || visible,
})
)}
</DatagridRow> </DatagridRow>
</> </>
) )
@@ -124,6 +119,7 @@ SongDatagridRow.defaultProps = {
export const SongDatagrid = ({ export const SongDatagrid = ({
contextAlwaysVisible, contextAlwaysVisible,
showDiscSubtitles, showDiscSubtitles,
classes,
...rest ...rest
}) => { }) => {
const dispatch = useDispatch() const dispatch = useDispatch()
@@ -161,7 +157,8 @@ export const SongDatagrid = ({
return set return set
}, [ids, data, showDiscSubtitles]) }, [ids, data, showDiscSubtitles])
const SongDatagridBody = (props) => ( const SongDatagridBody = (props) => {
return (
<DatagridBody <DatagridBody
{...props} {...props}
row={ row={
@@ -173,10 +170,12 @@ export const SongDatagrid = ({
} }
/> />
) )
return <Datagrid {...rest} body={<SongDatagridBody />} /> }
return <Datagrid {...rest} body={<SongDatagridBody />} classes={classes} />
} }
SongDatagrid.propTypes = { SongDatagrid.propTypes = {
contextAlwaysVisible: PropTypes.bool, contextAlwaysVisible: PropTypes.bool,
showDiscSubtitles: PropTypes.bool, showDiscSubtitles: PropTypes.bool,
classes: PropTypes.object,
} }
+6 -1
View File
@@ -10,7 +10,12 @@ import subsonic from '../subsonic'
const useStyles = makeStyles({ const useStyles = makeStyles({
star: { star: {
color: (props) => props.color, color: (props) => props.color,
visibility: (props) => (props.starred ? 'visible' : 'inherit'), visibility: (props) =>
props.starred
? 'visible'
: props.visible === false
? 'hidden'
: 'inherit',
}, },
}) })
+30
View File
@@ -24,6 +24,26 @@ import { SongBulkActions } from '../common'
import { SongListActions } from './SongListActions' import { SongListActions } from './SongListActions'
import { AlbumLinkField } from './AlbumLinkField' import { AlbumLinkField } from './AlbumLinkField'
import AddToPlaylistDialog from '../dialogs/AddToPlaylistDialog' import AddToPlaylistDialog from '../dialogs/AddToPlaylistDialog'
import { makeStyles } from '@material-ui/core/styles'
import StarBorderIcon from '@material-ui/icons/StarBorder'
const useStyles = makeStyles({
contextHeader: {
marginLeft: '3px',
marginTop: '-2px',
verticalAlign: 'text-top',
},
row: {
'&:hover': {
'& $contextMenu': {
visibility: 'visible',
},
},
},
contextMenu: {
visibility: 'hidden',
},
})
const SongFilter = (props) => ( const SongFilter = (props) => (
<Filter {...props} variant={'outlined'}> <Filter {...props} variant={'outlined'}>
@@ -37,6 +57,7 @@ const SongFilter = (props) => (
) )
const SongList = (props) => { const SongList = (props) => {
const classes = useStyles()
const dispatch = useDispatch() const dispatch = useDispatch()
const isXsmall = useMediaQuery((theme) => theme.breakpoints.down('xs')) const isXsmall = useMediaQuery((theme) => theme.breakpoints.down('xs'))
const isDesktop = useMediaQuery((theme) => theme.breakpoints.up('md')) const isDesktop = useMediaQuery((theme) => theme.breakpoints.up('md'))
@@ -74,6 +95,7 @@ const SongList = (props) => {
expand={<SongDetails />} expand={<SongDetails />}
rowClick={handleRowClick} rowClick={handleRowClick}
contextAlwaysVisible={!isDesktop} contextAlwaysVisible={!isDesktop}
classes={{ row: classes.row }}
> >
<SongTitleField source="title" showTrackNumbers={false} /> <SongTitleField source="title" showTrackNumbers={false} />
{isDesktop && <AlbumLinkField source="album" />} {isDesktop && <AlbumLinkField source="album" />}
@@ -94,6 +116,14 @@ const SongList = (props) => {
source={'starred'} source={'starred'}
sortBy={'starred ASC, starredAt ASC'} sortBy={'starred ASC, starredAt ASC'}
sortByOrder={'DESC'} sortByOrder={'DESC'}
className={classes.contextMenu}
label={
<StarBorderIcon
fontSize={'small'}
className={classes.contextHeader}
/>
}
textAlign={'right'}
/> />
</SongDatagrid> </SongDatagrid>
)} )}