diff --git a/ui/package-lock.json b/ui/package-lock.json index 899ae63ed..49c2586ce 100644 --- a/ui/package-lock.json +++ b/ui/package-lock.json @@ -7360,11 +7360,6 @@ "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==" }, - "hotkeys-js": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/hotkeys-js/-/hotkeys-js-3.8.1.tgz", - "integrity": "sha512-YlhVQtyG9f1b7GhtzdhR0Pl+cImD1ZrKI6zYUa7QLd0zuThiL7RzZ+ANJyy7z+kmcCpNYBf5PjBa3CjiQ5PFpw==" - }, "hpack.js": { "version": "2.1.6", "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", @@ -13484,12 +13479,12 @@ "resolved": "https://registry.npmjs.org/react-ga/-/react-ga-3.3.0.tgz", "integrity": "sha512-o8RScHj6Lb8cwy3GMrVH6NJvL+y0zpJvKtc0+wmH7Bt23rszJmnqEQxRbyrqUzk9DTJIHoP42bfO5rswC9SWBQ==" }, - "react-hotkeys-hook": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/react-hotkeys-hook/-/react-hotkeys-hook-3.0.1.tgz", - "integrity": "sha512-otpd7gPyyz1etP+WtjEpKRFjR9QIBPYBrzpz9i7o6WeURbY9D2Cn5cy2jNIL9OrxaN2ljno3gSXLdvMfsCNgYA==", + "react-hotkeys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/react-hotkeys/-/react-hotkeys-2.0.0.tgz", + "integrity": "sha512-3n3OU8vLX/pfcJrR3xJ1zlww6KS1kEJt0Whxc4FiGV+MJrQ1mYSYI3qS/11d2MJDFm8IhOXMTFQirfu6AVOF6Q==", "requires": { - "hotkeys-js": "3.8.1" + "prop-types": "^15.6.1" } }, "react-icons": { diff --git a/ui/package.json b/ui/package.json index 589e4e77c..896c92e28 100644 --- a/ui/package.json +++ b/ui/package.json @@ -18,7 +18,7 @@ "react-dom": "^16.14.0", "react-drag-listview": "^0.1.8", "react-ga": "^3.3.0", - "react-hotkeys-hook": "^3.0.1", + "react-hotkeys": "^2.0.0", "react-icons": "^4.1.0", "react-image-lightbox": "^5.1.1", "react-jinke-music-player": "^4.21.2", diff --git a/ui/src/audioplayer/Player.js b/ui/src/audioplayer/Player.js index bf5ab2d94..afaff69ac 100644 --- a/ui/src/audioplayer/Player.js +++ b/ui/src/audioplayer/Player.js @@ -6,6 +6,7 @@ import { useAuthState, useDataProvider, useTranslate } from 'react-admin' import ReactJkMusicPlayer from 'react-jinke-music-player' import 'react-jinke-music-player/assets/index.css' import { makeStyles } from '@material-ui/core/styles' +import { GlobalHotKeys } from 'react-hotkeys' import subsonic from '../subsonic' import { scrobble, @@ -17,7 +18,6 @@ import { import themes from '../themes' import config from '../config' import PlayerToolbar from './PlayerToolbar' -import { useHotkeys } from 'react-hotkeys-hook' import { sendNotification, baseUrl } from '../utils' const useStyle = makeStyles((theme) => ({ @@ -72,56 +72,47 @@ const Player = () => { const visible = authenticated && queue.queue.length > 0 const classes = useStyle({ visible }) - const nextSong = () => { + const nextSong = useCallback(() => { const idx = queue.queue.findIndex( (item) => item.uuid === queue.current.uuid ) return idx !== null ? queue.queue[idx + 1] : null - } + }, [queue]) - const prevSong = () => { + const prevSong = useCallback(() => { const idx = queue.queue.findIndex( (item) => item.uuid === queue.current.uuid ) return idx !== null ? queue.queue[idx - 1] : null + }, [queue]) + + const keyMap = { + TOGGLE_PLAY: 'p', + PREV_SONG: 'left', + NEXT_SONG: 'right', + VOL_UP: '=', + VOL_DOWN: '-', } - useHotkeys('space', (e) => { - e.preventDefault() - audioInstance && audioInstance.togglePlay() - }) - - useHotkeys( - 'left', - (e) => { - if (prevSong()) { - e.preventDefault() - audioInstance && audioInstance.playPrev() - } - }, - {}, - [queue] - ) - - useHotkeys('=', () => { - audioInstance.volume = Math.min(1, audioInstance.volume + 0.1) - }) - - useHotkeys('-', () => { - audioInstance.volume = Math.max(0, audioInstance.volume - 0.1) - }) - - useHotkeys( - 'right', - (e) => { - if (nextSong()) { - e.preventDefault() - audioInstance && audioInstance.playNext() - } - }, - {}, - [queue] - ) + const keyHandlers = { + TOGGLE_PLAY: useCallback(() => { + audioInstance && audioInstance.togglePlay() + }, []), + PREV_SONG: useCallback(() => { + if (prevSong()) audioInstance && audioInstance.playPrev() + }, [prevSong]), + NEXT_SONG: useCallback(() => { + if (nextSong()) audioInstance && audioInstance.playNext() + }, [nextSong]), + VOL_UP: useCallback( + () => (audioInstance.volume = Math.min(1, audioInstance.volume + 0.1)), + [] + ), + VOL_DOWN: useCallback( + () => (audioInstance.volume = Math.max(0, audioInstance.volume - 0.1)), + [] + ), + } const defaultOptions = { theme: playerTheme, @@ -292,23 +283,26 @@ const Player = () => { } return ( - { - audioInstance = instance - }} - /> + <> + { + audioInstance = instance + }} + /> + + ) } -export default Player +export { Player } diff --git a/ui/src/audioplayer/PlayerToolbar.js b/ui/src/audioplayer/PlayerToolbar.js index 6083fff9a..15be63bb5 100644 --- a/ui/src/audioplayer/PlayerToolbar.js +++ b/ui/src/audioplayer/PlayerToolbar.js @@ -1,8 +1,8 @@ -import React from 'react' +import React, { useCallback } from 'react' import { useLocation } from 'react-router-dom' import { useGetOne } from 'react-admin' +import { GlobalHotKeys } from 'react-hotkeys' import { StarButton, useToggleStar } from '../common' -import { useHotkeys } from 'react-hotkeys-hook' const Placeholder = () => @@ -12,21 +12,20 @@ const Toolbar = ({ id }) => { const { data, loading } = useGetOne(resource, id) const [toggleStar, toggling] = useToggleStar(resource, data) - useHotkeys( - 's', - () => { - toggleStar() - }, - {}, - [toggleStar] - ) + const keyMap = { TOGGLE_STAR: 's' } + const handlers = { + TOGGLE_STAR: useCallback(() => toggleStar(), [toggleStar]), + } return ( - + <> + + + ) } diff --git a/ui/src/audioplayer/index.js b/ui/src/audioplayer/index.js index 5790eb367..91042b6b1 100644 --- a/ui/src/audioplayer/index.js +++ b/ui/src/audioplayer/index.js @@ -1,3 +1 @@ -import Player from './Player' - -export { Player } +export * from './Player' diff --git a/ui/src/layout/Layout.js b/ui/src/layout/Layout.js index 7a637508f..546c6d835 100644 --- a/ui/src/layout/Layout.js +++ b/ui/src/layout/Layout.js @@ -1,7 +1,8 @@ -import React from 'react' -import { useSelector } from 'react-redux' -import { Layout } from 'react-admin' +import React, { useCallback } from 'react' +import { useDispatch, useSelector } from 'react-redux' +import { Layout, toggleSidebar } from 'react-admin' import { makeStyles } from '@material-ui/core/styles' +import { HotKeys } from 'react-hotkeys' import Menu from './Menu' import AppBar from './AppBar' import Notification from './Notification' @@ -15,15 +16,23 @@ export default (props) => { const theme = useSelector((state) => themes[state.theme] || themes.DarkTheme) const queue = useSelector((state) => state.queue) const classes = useStyles({ addPadding: queue.queue.length > 0 }) + const dispatch = useDispatch() + + const keyMap = { TOGGLE_MENU: 'm' } + const keyHandlers = { + TOGGLE_MENU: useCallback(() => dispatch(toggleSidebar()), [dispatch]), + } return ( - + + + ) } diff --git a/ui/src/layout/Menu.js b/ui/src/layout/Menu.js index 9b7738f76..2ef57cff8 100644 --- a/ui/src/layout/Menu.js +++ b/ui/src/layout/Menu.js @@ -1,12 +1,7 @@ import React, { useState, createElement } from 'react' -import { useSelector, useDispatch } from 'react-redux' +import { useSelector } from 'react-redux' import { useMediaQuery } from '@material-ui/core' -import { - useTranslate, - MenuItemLink, - getResources, - toggleSidebar, -} from 'react-admin' +import { useTranslate, MenuItemLink, getResources } from 'react-admin' import { withRouter } from 'react-router-dom' import LibraryMusicIcon from '@material-ui/icons/LibraryMusic' import ViewListIcon from '@material-ui/icons/ViewList' @@ -14,7 +9,6 @@ import AlbumIcon from '@material-ui/icons/Album' import SubMenu from './SubMenu' import inflection from 'inflection' import albumLists from '../album/albumLists' -import { useHotkeys } from 'react-hotkeys-hook' const translatedResourceName = (resource, translate) => translate(`resources.${resource.name}.name`, { @@ -33,11 +27,6 @@ const Menu = ({ onMenuClick, dense, logout }) => { const open = useSelector((state) => state.admin.ui.sidebarOpen) const translate = useTranslate() const resources = useSelector(getResources) - const dispatch = useDispatch() - - useHotkeys('m', () => { - dispatch(toggleSidebar()) - }) // TODO State is not persisted in mobile when you close the sidebar menu. Move to redux? const [state, setState] = useState({