diff --git a/ui/src/audioplayer/Player.js b/ui/src/audioplayer/Player.js index 23957c247..95e4dee17 100644 --- a/ui/src/audioplayer/Player.js +++ b/ui/src/audioplayer/Player.js @@ -23,9 +23,11 @@ import subsonic from '../subsonic' import locale from './locale' import { keyMap } from '../hotkeys' import keyHandlers from './keyHandlers' +import { useWindowSize } from '../common' const Player = () => { const theme = useCurrentTheme() + const size = useWindowSize() const translate = useTranslate() const playerTheme = theme.player?.theme || 'dark' const dataProvider = useDataProvider() @@ -63,16 +65,17 @@ const Player = () => { restartCurrentOnPrev: true, quietUpdate: true, defaultPosition: { - top: 300, - left: 120, + top: size.height - 90, + left: size.width - 90, }, + drag: false, volumeFade: { fadeIn: 200, fadeOut: 200 }, renderAudioTitle: (audioInfo, isMobile) => ( ), locale: locale(translate), }), - [isDesktop, playerTheme, translate] + [isDesktop, playerTheme, translate, size] ) const options = useMemo(() => { diff --git a/ui/src/common/index.js b/ui/src/common/index.js index 98135e8ad..c6e8a3a94 100644 --- a/ui/src/common/index.js +++ b/ui/src/common/index.js @@ -1,5 +1,6 @@ export * from './AddToPlaylistButton' export * from './ArtistLinkField' +export * from './ArtistSimpleList' export * from './BatchPlayButton' export * from './BitrateField' export * from './ContextMenus' @@ -7,11 +8,14 @@ export * from './DateField' export * from './DocLink' export * from './DurationField' export * from './List' +export * from './LoveButton' export * from './MultiLineTextField' export * from './Pagination' export * from './PlayButton' +export * from './QualityInfo' export * from './QuickFilter' export * from './RangeField' +export * from './RatingField' export * from './ShuffleAllButton' export * from './SimpleList' export * from './SizeField' @@ -19,19 +23,16 @@ export * from './SongContextMenu' export * from './SongDatagrid' export * from './SongDetails' export * from './SongTitleField' -export * from './LoveButton' export * from './Title' +export * from './ToggleFieldsMenu' export * from './SongBulkActions' +export * from './SongSimpleList' export * from './useAlbumsPerPage' export * from './useInterval' export * from './useResourceRefresh' -export * from './useToggleLove' -export * from './useTraceUpdate' -export * from './Writable' -export * from './SongSimpleList' -export * from './ArtistSimpleList' -export * from './RatingField' export * from './useRating' export * from './useSelectedFields' -export * from './ToggleFieldsMenu' -export * from './QualityInfo' +export * from './useToggleLove' +export * from './useTraceUpdate' +export * from './useWindowSize' +export * from './Writable' diff --git a/ui/src/common/useWindowSize.js b/ui/src/common/useWindowSize.js new file mode 100644 index 000000000..3a0ce8e1d --- /dev/null +++ b/ui/src/common/useWindowSize.js @@ -0,0 +1,28 @@ +import { useState, useEffect } from 'react' + +// Hook from https://usehooks.com/useWindowSize/ +export function useWindowSize() { + // Initialize state with undefined width/height so server and client renders match + // Learn more here: https://joshwcomeau.com/react/the-perils-of-rehydration/ + const [windowSize, setWindowSize] = useState({ + width: undefined, + height: undefined, + }) + useEffect(() => { + // Handler to call on window resize + function handleResize() { + // Set window width/height to state + setWindowSize({ + width: window.innerWidth, + height: window.innerHeight, + }) + } + // Add event listener + window.addEventListener('resize', handleResize) + // Call handler right away so state gets updated with initial window size + handleResize() + // Remove event listener on cleanup + return () => window.removeEventListener('resize', handleResize) + }, []) // Empty array ensures that effect is only run on mount + return windowSize +}