From e47fcfc62eb335926ae0fb6788d28926a122626e Mon Sep 17 00:00:00 2001
From: Jeff <42182408+jeffvli@users.noreply.github.com>
Date: Tue, 28 Mar 2023 14:19:23 -0700
Subject: [PATCH] Add fullscreen player view (#27)
* Add store controls for fullscreen player
* Normalize styles for playback config
* Add fullscreen player component
* Add option component
* Update player controls to use option/popover components
* Add esc hotkey to close player
* Add usePlayerData hook
---
.../components/dropdown-menu/index.tsx | 4 +-
src/renderer/components/index.ts | 1 +
src/renderer/components/option/index.tsx | 32 +++
.../virtual-table/table-config-dropdown.tsx | 84 ++++---
.../now-playing/components/play-queue.tsx | 8 +-
.../components/full-screen-player-image.tsx | 237 ++++++++++++++++++
.../components/full-screen-player-queue.tsx | 129 ++++++++++
.../player/components/full-screen-player.tsx | 194 ++++++++++++++
.../player/components/left-controls.tsx | 32 ++-
.../features/sidebar/components/sidebar.tsx | 15 +-
src/renderer/layouts/default-layout.tsx | 12 +-
.../store/full-screen-player.store.ts | 46 ++++
src/renderer/store/index.ts | 1 +
src/renderer/store/player.store.ts | 6 +
src/renderer/store/settings.store.ts | 20 ++
src/renderer/themes/default.scss | 12 +-
src/renderer/themes/light.scss | 7 +
src/renderer/types.ts | 2 +-
18 files changed, 780 insertions(+), 62 deletions(-)
create mode 100644 src/renderer/components/option/index.tsx
create mode 100644 src/renderer/features/player/components/full-screen-player-image.tsx
create mode 100644 src/renderer/features/player/components/full-screen-player-queue.tsx
create mode 100644 src/renderer/features/player/components/full-screen-player.tsx
create mode 100644 src/renderer/store/full-screen-player.store.ts
diff --git a/src/renderer/components/dropdown-menu/index.tsx b/src/renderer/components/dropdown-menu/index.tsx
index 0d7305d8..5e6bfe4f 100644
--- a/src/renderer/components/dropdown-menu/index.tsx
+++ b/src/renderer/components/dropdown-menu/index.tsx
@@ -73,7 +73,7 @@ const StyledMenuDropdown = styled(MantineMenu.Dropdown)`
border-radius: var(--dropdown-menu-border-radius);
filter: drop-shadow(0 0 5px rgb(0, 0, 0, 50%));
- *:first-child {
+ /* *:first-child {
border-top-left-radius: var(--dropdown-menu-border-radius);
border-top-right-radius: var(--dropdown-menu-border-radius);
}
@@ -81,7 +81,7 @@ const StyledMenuDropdown = styled(MantineMenu.Dropdown)`
*:last-child {
border-bottom-right-radius: var(--dropdown-menu-border-radius);
border-bottom-left-radius: var(--dropdown-menu-border-radius);
- }
+ } */
`;
const StyledMenuDivider = styled(MantineMenu.Divider)`
diff --git a/src/renderer/components/index.ts b/src/renderer/components/index.ts
index 3b4660de..2d3f27b0 100644
--- a/src/renderer/components/index.ts
+++ b/src/renderer/components/index.ts
@@ -34,3 +34,4 @@ export * from './context-menu';
export * from './query-builder';
export * from './rating';
export * from './hover-card';
+export * from './option';
diff --git a/src/renderer/components/option/index.tsx b/src/renderer/components/option/index.tsx
new file mode 100644
index 00000000..a4e90b5b
--- /dev/null
+++ b/src/renderer/components/option/index.tsx
@@ -0,0 +1,32 @@
+import { ReactNode } from 'react';
+import { Flex, Group } from '@mantine/core';
+
+export const Option = ({ children }: any) => {
+ return (
+
+ {children}
+
+ );
+};
+
+interface LabelProps {
+ children: ReactNode;
+}
+
+const Label = ({ children }: LabelProps) => {
+ return {children};
+};
+
+interface ControlProps {
+ children: ReactNode;
+}
+
+const Control = ({ children }: ControlProps) => {
+ return {children};
+};
+
+Option.Label = Label;
+Option.Control = Control;
diff --git a/src/renderer/components/virtual-table/table-config-dropdown.tsx b/src/renderer/components/virtual-table/table-config-dropdown.tsx
index f2e3c0fd..1a21f5a8 100644
--- a/src/renderer/components/virtual-table/table-config-dropdown.tsx
+++ b/src/renderer/components/virtual-table/table-config-dropdown.tsx
@@ -1,11 +1,10 @@
import type { ChangeEvent } from 'react';
-import { Divider, Stack } from '@mantine/core';
import { MultiSelect } from '/@/renderer/components/select';
import { Slider } from '/@/renderer/components/slider';
import { Switch } from '/@/renderer/components/switch';
-import { Text } from '/@/renderer/components/text';
import { useSettingsStoreActions, useSettingsStore } from '/@/renderer/store/settings.store';
import { TableColumn, TableType } from '/@/renderer/types';
+import { Option } from '/@/renderer/components/option';
export const SONG_TABLE_COLUMNS = [
{ label: 'Row Index', value: TableColumn.ROW_INDEX },
@@ -168,42 +167,49 @@ export const TableConfigDropdown = ({ type }: TableConfigDropdownProps) => {
};
return (
-
-
- Table Columns
- column.column)}
- dropdownPosition="top"
- width={300}
- onChange={handleAddOrRemoveColumns}
- />
-
-
- Row Height
-
-
-
-
-
-
+ <>
+ Auto-fit Columns
+
+
+
+
+ Follow current song
+
+
+
+
+
+ `Item size: ${value}`}
+ max={100}
+ min={25}
+ w="100%"
+ onChangeEnd={handleUpdateRowHeight}
+ />
+
+
+
+ column.column)}
+ dropdownPosition="bottom"
+ width={300}
+ onChange={handleAddOrRemoveColumns}
+ />
+
+
+ >
);
};
diff --git a/src/renderer/features/now-playing/components/play-queue.tsx b/src/renderer/features/now-playing/components/play-queue.tsx
index 329faaf9..0a29c2c3 100644
--- a/src/renderer/features/now-playing/components/play-queue.tsx
+++ b/src/renderer/features/now-playing/components/play-queue.tsx
@@ -13,6 +13,7 @@ import {
useAppStoreActions,
useCurrentSong,
useDefaultQueue,
+ usePlayerControls,
usePreviousSong,
useQueueControls,
} from '/@/renderer/store';
@@ -53,6 +54,7 @@ export const PlayQueue = forwardRef(({ type }: QueueProps, ref: Ref) => {
const tableConfig = useTableSettings(type);
const [gridApi, setGridApi] = useState();
const playerType = usePlayerType();
+ const { play } = usePlayerControls();
useEffect(() => {
if (tableRef.current) {
@@ -79,6 +81,8 @@ export const PlayQueue = forwardRef(({ type }: QueueProps, ref: Ref) => {
if (playerType === PlaybackType.LOCAL) {
mpvPlayer.setQueue(playerData);
}
+
+ play();
};
const handleDragStart = () => {
@@ -160,7 +164,7 @@ export const PlayQueue = forwardRef(({ type }: QueueProps, ref: Ref) => {
}
};
- const rowClassRules = useMemo(() => {
+ const rowClassRules = useMemo(() => {
return {
'current-song': (params) => {
return params.data.uniqueId === currentSong?.uniqueId;
@@ -205,11 +209,13 @@ export const PlayQueue = forwardRef(({ type }: QueueProps, ref: Ref) => {
rowDragMultiRow
autoFitColumns={tableConfig.autoFit}
columnDefs={columnDefs}
+ deselectOnClickOutside={type === 'fullScreen'}
getRowId={(data) => data.data.uniqueId}
rowBuffer={50}
rowClassRules={rowClassRules}
rowData={queue}
rowHeight={tableConfig.rowHeight || 40}
+ suppressCellFocus={type === 'fullScreen'}
onCellContextMenu={handleContextMenu}
onCellDoubleClicked={handleDoubleClick}
onColumnMoved={handleColumnChange}
diff --git a/src/renderer/features/player/components/full-screen-player-image.tsx b/src/renderer/features/player/components/full-screen-player-image.tsx
new file mode 100644
index 00000000..16916173
--- /dev/null
+++ b/src/renderer/features/player/components/full-screen-player-image.tsx
@@ -0,0 +1,237 @@
+import { Flex, Stack, Group, Center } from '@mantine/core';
+import { useSetState } from '@mantine/hooks';
+import { AnimatePresence, HTMLMotionProps, motion, Variants } from 'framer-motion';
+import { useEffect } from 'react';
+import { RiAlbumFill } from 'react-icons/ri';
+import { generatePath } from 'react-router';
+import { Link } from 'react-router-dom';
+import styled from 'styled-components';
+import { QueueSong } from '/@/renderer/api/types';
+import { Badge, Text, TextTitle } from '/@/renderer/components';
+import { useFastAverageColor } from '/@/renderer/hooks';
+import { AppRoute } from '/@/renderer/router/routes';
+import { PlayerData, usePlayerData, usePlayerStore } from '/@/renderer/store';
+
+const Image = styled(motion.img)`
+ position: absolute;
+ width: 100%;
+ max-width: 100%;
+ height: 100%;
+ max-height: 100%;
+ object-fit: cover;
+ border-radius: 5px;
+ box-shadow: 2px 2px 10px 2px rgba(0, 0, 0, 40%);
+`;
+
+const ImageContainer = styled(motion.div)`
+ position: relative;
+ display: flex;
+ align-items: center;
+ height: 65%;
+ aspect-ratio: 1/1;
+`;
+
+const imageVariants: Variants = {
+ closed: {
+ opacity: 0,
+ transition: {
+ duration: 0.8,
+ ease: 'linear',
+ },
+ },
+ initial: {
+ opacity: 0,
+ },
+ open: (custom) => {
+ const { isOpen } = custom;
+ return {
+ opacity: isOpen ? 1 : 0,
+ transition: {
+ duration: 0.4,
+ ease: 'linear',
+ },
+ };
+ },
+};
+
+const scaleImageUrl = (url?: string | null) => {
+ return url
+ ?.replace(/&size=\d+/, '&size=800')
+ .replace(/\?width=\d+/, '?width=800')
+ .replace(/&height=\d+/, '&height=800');
+};
+
+const ImageWithPlaceholder = ({ ...props }: HTMLMotionProps<'img'>) => {
+ if (!props.src) {
+ return (
+
+
+
+ );
+ }
+
+ return ;
+};
+
+export const FullScreenPlayerImage = () => {
+ const { queue } = usePlayerData();
+ const currentSong = queue.current;
+ const background = useFastAverageColor(queue.current?.imageUrl, true, 'dominant');
+ const imageKey = `image-${background}`;
+
+ const [imageState, setImageState] = useSetState({
+ bottomImage: scaleImageUrl(queue.next?.imageUrl),
+ current: 0,
+ topImage: scaleImageUrl(queue.current?.imageUrl),
+ });
+
+ useEffect(() => {
+ const unsubSongChange = usePlayerStore.subscribe(
+ (state) => [state.current.song, state.actions.getPlayerData().queue],
+ (state) => {
+ const isTop = imageState.current === 0;
+ const queue = state[1] as PlayerData['queue'];
+
+ const currentImageUrl = scaleImageUrl(queue.current?.imageUrl);
+ const nextImageUrl = scaleImageUrl(queue.next?.imageUrl);
+
+ setImageState({
+ bottomImage: isTop ? currentImageUrl : nextImageUrl,
+ current: isTop ? 1 : 0,
+ topImage: isTop ? nextImageUrl : currentImageUrl,
+ });
+ },
+ { equalityFn: (a, b) => (a[0] as QueueSong)?.id === (b[0] as QueueSong)?.id },
+ );
+
+ return () => {
+ unsubSongChange();
+ };
+ }, [imageState, queue, setImageState]);
+
+ return (
+
+
+
+ {imageState.current === 0 && (
+
+ )}
+
+
+ {imageState.current === 1 && (
+
+ )}
+
+
+
+
+ {currentSong?.name}
+
+
+ {currentSong?.album}{' '}
+
+ {currentSong?.artists?.map((artist, index) => (
+
+ {index > 0 && (
+
+ •
+
+ )}
+
+ {artist.name}
+
+
+ ))}
+
+ {currentSong?.container && (
+
+ {currentSong?.container} {currentSong?.bitRate}
+
+ )}
+ {currentSong?.releaseYear && {currentSong?.releaseYear}}
+
+
+
+ );
+};
diff --git a/src/renderer/features/player/components/full-screen-player-queue.tsx b/src/renderer/features/player/components/full-screen-player-queue.tsx
new file mode 100644
index 00000000..6dcc4206
--- /dev/null
+++ b/src/renderer/features/player/components/full-screen-player-queue.tsx
@@ -0,0 +1,129 @@
+import { Stack, Group, Center, Box } from '@mantine/core';
+import { motion } from 'framer-motion';
+import { HiOutlineQueueList } from 'react-icons/hi2';
+import { RiFileMusicLine, RiFileTextLine, RiInformationFill } from 'react-icons/ri';
+import styled from 'styled-components';
+import { Button, TextTitle } from '/@/renderer/components';
+import { PlayQueue } from '/@/renderer/features/now-playing';
+import {
+ useFullScreenPlayerStore,
+ useFullScreenPlayerStoreActions,
+} from '/@/renderer/store/full-screen-player.store';
+
+const QueueContainer = styled.div`
+ position: relative;
+ display: flex;
+ height: 100%;
+
+ .ag-theme-alpine-dark {
+ --ag-header-background-color: rgba(0, 0, 0, 0%) !important;
+ --ag-background-color: rgba(0, 0, 0, 0%) !important;
+ --ag-odd-row-background-color: rgba(0, 0, 0, 0%) !important;
+ }
+
+ .ag-header {
+ display: none !important;
+ }
+`;
+
+const ActiveTabIndicator = styled(motion.div)`
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ width: 100%;
+ height: 2px;
+ background: var(--main-fg);
+`;
+
+export const FullScreenPlayerQueue = () => {
+ const { activeTab } = useFullScreenPlayerStore();
+ const { setStore } = useFullScreenPlayerStoreActions();
+
+ const headerItems = [
+ {
+ active: activeTab === 'queue',
+ icon: ,
+ label: 'Up Next',
+ onClick: () => setStore({ activeTab: 'queue' }),
+ },
+ {
+ active: activeTab === 'related',
+ icon: ,
+ label: 'Related',
+ onClick: () => setStore({ activeTab: 'related' }),
+ },
+ {
+ active: activeTab === 'lyrics',
+ icon: ,
+ label: 'Lyrics',
+ onClick: () => setStore({ activeTab: 'lyrics' }),
+ },
+ ];
+
+ return (
+
+
+ {headerItems.map((item) => (
+
+
+ {item.active ? : null}
+
+ ))}
+
+ {activeTab === 'queue' ? (
+
+
+
+ ) : activeTab === 'related' ? (
+
+
+
+
+ COMING SOON
+
+
+
+ ) : activeTab === 'lyrics' ? (
+
+
+
+
+ COMING SOON
+
+
+
+ ) : null}
+
+ );
+};
diff --git a/src/renderer/features/player/components/full-screen-player.tsx b/src/renderer/features/player/components/full-screen-player.tsx
new file mode 100644
index 00000000..057d4666
--- /dev/null
+++ b/src/renderer/features/player/components/full-screen-player.tsx
@@ -0,0 +1,194 @@
+import { useLayoutEffect, useRef } from 'react';
+import { Group } from '@mantine/core';
+import { useHotkeys } from '@mantine/hooks';
+import { Variants, motion } from 'framer-motion';
+import { RiArrowDownSLine, RiSettings3Line } from 'react-icons/ri';
+import { useLocation } from 'react-router';
+import styled from 'styled-components';
+import { Button, Option, Popover, Switch, TableConfigDropdown } from '/@/renderer/components';
+import {
+ useCurrentSong,
+ useFullScreenPlayerStore,
+ useFullScreenPlayerStoreActions,
+} from '/@/renderer/store';
+import { useFastAverageColor } from '../../../hooks/use-fast-average-color';
+import { FullScreenPlayerImage } from '/@/renderer/features/player/components/full-screen-player-image';
+import { FullScreenPlayerQueue } from '/@/renderer/features/player/components/full-screen-player-queue';
+
+const Container = styled(motion.div)`
+ z-index: 100;
+ display: flex;
+ justify-content: center;
+ padding: 2rem;
+`;
+
+const ResponsiveContainer = styled.div`
+ display: flex;
+ flex-direction: column;
+ gap: 2rem;
+ width: 100%;
+ max-width: 2560px;
+ margin-top: 70px;
+
+ .full-screen-player-image {
+ max-height: calc(35vh - 90px);
+ }
+
+ @media screen and (min-width: 1080px) {
+ flex-direction: row;
+
+ .full-screen-player-image {
+ max-height: calc(70vh - 90px);
+ }
+ }
+
+ @media screen and (max-height: 800px) and (min-width: 1080px) {
+ .full-screen-player-image {
+ max-height: calc(50vh - 90px);
+ }
+ }
+`;
+
+const BackgroundImageOverlay = styled.div`
+ position: absolute;
+ top: 0;
+ left: 0;
+ z-index: -1;
+ width: 100%;
+ height: 100%;
+ background: linear-gradient(180deg, rgba(20, 21, 23, 40%), var(--main-bg));
+`;
+
+const Controls = () => {
+ const { dynamicBackground, expanded } = useFullScreenPlayerStore();
+ const { setStore } = useFullScreenPlayerStoreActions();
+
+ const handleToggleFullScreenPlayer = () => {
+ setStore({ expanded: !expanded });
+ };
+
+ useHotkeys([['Escape', handleToggleFullScreenPlayer]]);
+
+ return (
+ <>
+
+
+
+
+
+
+
+ Dynamic Background
+
+
+ setStore({
+ dynamicBackground: e.target.checked,
+ })
+ }
+ />
+
+
+
+
+
+
+ >
+ );
+};
+
+const containerVariants: Variants = {
+ closed: {
+ height: 'calc(100vh - 90px)',
+ position: 'absolute',
+ top: '100vh',
+ transition: {
+ duration: 0.5,
+ ease: 'easeInOut',
+ },
+ width: '100vw',
+ y: -100,
+ },
+ open: (custom) => {
+ const { dynamicBackground, background } = custom;
+ return {
+ background: dynamicBackground ? background : 'var(--main-bg)',
+ height: 'calc(100vh - 90px)',
+ left: 0,
+ position: 'absolute',
+ top: 0,
+ transition: {
+ background: {
+ duration: 1,
+ ease: 'easeInOut',
+ },
+ delay: 0.1,
+ duration: 0.5,
+ ease: 'easeInOut',
+ },
+ width: '100vw',
+ y: 0,
+ };
+ },
+};
+
+export const FullScreenPlayer = () => {
+ const { dynamicBackground } = useFullScreenPlayerStore();
+ const { setStore } = useFullScreenPlayerStoreActions();
+
+ const location = useLocation();
+ const isOpenedRef = useRef(null);
+
+ useLayoutEffect(() => {
+ if (isOpenedRef.current !== null) {
+ setStore({ expanded: false });
+ }
+
+ isOpenedRef.current = true;
+ }, [location, setStore]);
+
+ const currentSong = useCurrentSong();
+ const background = useFastAverageColor(currentSong?.imageUrl, true, 'dominant');
+
+ return (
+
+
+ {dynamicBackground && }
+
+
+
+
+
+ );
+};
diff --git a/src/renderer/features/player/components/left-controls.tsx b/src/renderer/features/player/components/left-controls.tsx
index ca7bebf1..4498fc0e 100644
--- a/src/renderer/features/player/components/left-controls.tsx
+++ b/src/renderer/features/player/components/left-controls.tsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import React, { MouseEvent } from 'react';
import { Center, Group } from '@mantine/core';
import { motion, AnimatePresence, LayoutGroup } from 'framer-motion';
import { RiArrowUpSLine, RiDiscLine, RiMore2Fill } from 'react-icons/ri';
@@ -6,7 +6,13 @@ import { generatePath, Link } from 'react-router-dom';
import styled from 'styled-components';
import { Button, Text } from '/@/renderer/components';
import { AppRoute } from '/@/renderer/router/routes';
-import { useAppStoreActions, useAppStore, useCurrentSong } from '/@/renderer/store';
+import {
+ useAppStoreActions,
+ useAppStore,
+ useCurrentSong,
+ useSetFullScreenPlayerStore,
+ useFullScreenPlayerStore,
+} from '/@/renderer/store';
import { fadeIn } from '/@/renderer/styles';
import { LibraryItem } from '/@/renderer/api/types';
import { SONG_CONTEXT_MENU_ITEMS } from '/@/renderer/features/context-menu/context-menu-items';
@@ -35,7 +41,7 @@ const MetadataStack = styled(motion.div)`
overflow: hidden;
`;
-const Image = styled(motion(Link))`
+const Image = styled(motion.div)`
width: 60px;
height: 60px;
filter: drop-shadow(0 0 5px rgb(0, 0, 0, 100%));
@@ -75,6 +81,8 @@ const LineItem = styled.div<{ $secondary?: boolean }>`
export const LeftControls = () => {
const { setSidebar } = useAppStoreActions();
+ const { expanded: isFullScreenPlayerExpanded } = useFullScreenPlayerStore();
+ const setFullScreenPlayerStore = useSetFullScreenPlayerStore();
const hideImage = useAppStore((state) => state.sidebar.image);
const currentSong = useCurrentSong();
const title = currentSong?.name;
@@ -87,6 +95,16 @@ export const LeftControls = () => {
SONG_CONTEXT_MENU_ITEMS,
);
+ const handleToggleFullScreenPlayer = (e: MouseEvent) => {
+ e.stopPropagation();
+ setFullScreenPlayerStore({ expanded: !isFullScreenPlayerExpanded });
+ };
+
+ const handleToggleSidebarImage = (e: MouseEvent) => {
+ e.stopPropagation();
+ setSidebar({ image: true });
+ };
+
return (
@@ -101,8 +119,9 @@ export const LeftControls = () => {
animate={{ opacity: 1, scale: 1, x: 0 }}
exit={{ opacity: 0, x: -50 }}
initial={{ opacity: 0, x: -50 }}
- to={AppRoute.NOW_PLAYING}
+ role="button"
transition={{ duration: 0.3, ease: 'easeInOut' }}
+ onClick={handleToggleFullScreenPlayer}
>
{currentSong?.imageUrl ? (
{
sx={{ position: 'absolute', right: 2, top: 2 }}
tooltip={{ label: 'Expand', openDelay: 500 }}
variant="default"
- onClick={(e) => {
- e.preventDefault();
- setSidebar({ image: true });
- }}
+ onClick={handleToggleSidebarImage}
>
`
+const ImageContainer = styled(motion.div)<{ height: string }>`
position: relative;
height: ${(props) => props.height};
@@ -112,6 +114,12 @@ export const Sidebar = () => {
startIndex: 0,
});
+ const setFullScreenPlayerStore = useSetFullScreenPlayerStore();
+ const { expanded: isFullScreenPlayerExpanded } = useFullScreenPlayerStore();
+ const expandFullScreenPlayer = () => {
+ setFullScreenPlayerStore({ expanded: !isFullScreenPlayerExpanded });
+ };
+
const cq = useContainerQuery({ sm: 300 });
return (
@@ -327,8 +335,9 @@ export const Sidebar = () => {
exit={{ opacity: 0, y: 200 }}
height={sidebar.leftWidth}
initial={{ opacity: 0, y: 200 }}
- to={AppRoute.NOW_PLAYING}
+ role="button"
transition={{ duration: 0.3, ease: 'easeInOut' }}
+ onClick={expandFullScreenPlayer}
>
{upsizedImageUrl ? (
{
tooltip={{ label: 'Collapse', openDelay: 500 }}
variant="default"
onClick={(e) => {
- e.preventDefault();
+ e.stopPropagation();
setSidebar({ image: false });
}}
>
diff --git a/src/renderer/layouts/default-layout.tsx b/src/renderer/layouts/default-layout.tsx
index cef35eb6..69f4217e 100644
--- a/src/renderer/layouts/default-layout.tsx
+++ b/src/renderer/layouts/default-layout.tsx
@@ -11,10 +11,11 @@ import { DrawerPlayQueue, SidebarPlayQueue } from '/@/renderer/features/now-play
import { Playerbar } from '/@/renderer/features/player';
import { Sidebar } from '/@/renderer/features/sidebar/components/sidebar';
import { AppRoute } from '/@/renderer/router/routes';
-import { useAppStore, useAppStoreActions } from '/@/renderer/store';
+import { useAppStore, useAppStoreActions, useFullScreenPlayerStore } from '/@/renderer/store';
import { useSettingsStore, useGeneralSettings } from '/@/renderer/store/settings.store';
import { PlaybackType } from '/@/renderer/types';
import { constrainSidebarWidth, constrainRightSidebarWidth } from '/@/renderer/utils';
+import { FullScreenPlayer } from '/@/renderer/features/player/components/full-screen-player';
if (!isElectron()) {
useSettingsStore.getState().actions.setSettings({
@@ -84,7 +85,7 @@ const ResizeHandle = styled.div<{
right: ${(props) => props.placement === 'right' && 0};
bottom: ${(props) => props.placement === 'bottom' && 0};
left: ${(props) => props.placement === 'left' && 0};
- z-index: 100;
+ z-index: 90;
width: 2px;
height: 100%;
background-color: var(--sidebar-handle-bg);
@@ -147,6 +148,7 @@ export const DefaultLayout = ({ shell }: DefaultLayoutProps) => {
location.pathname !== AppRoute.NOW_PLAYING;
const showSideQueue = sidebar.rightExpanded && location.pathname !== AppRoute.NOW_PLAYING;
+ const { expanded: isFullScreenPlayerExpanded } = useFullScreenPlayerStore();
const queueDrawerButtonVariants: Variants = {
hidden: {
@@ -259,6 +261,12 @@ export const DefaultLayout = ({ shell }: DefaultLayoutProps) => {
>
{!shell && (
<>
+
+ {isFullScreenPlayerExpanded && }
+