Add customizable side queue

This commit is contained in:
jeffvli
2022-12-10 16:30:34 -08:00
parent 06d018883b
commit f01de3d1ff
3 changed files with 109 additions and 23 deletions
@@ -3,6 +3,7 @@ import isElectron from 'is-electron';
import { Switch, Select } from '/@/components'; import { Switch, Select } from '/@/components';
import { SettingsOptions } from '/@/features/settings/components/settings-option'; import { SettingsOptions } from '/@/features/settings/components/settings-option';
import { THEME_DATA } from '/@/hooks'; import { THEME_DATA } from '/@/hooks';
import type { SideQueueType } from '/@/store/settings.store';
import { useGeneralSettings, useSettingsStoreActions } from '/@/store/settings.store'; import { useGeneralSettings, useSettingsStoreActions } from '/@/store/settings.store';
import type { AppTheme } from '/@/themes/types'; import type { AppTheme } from '/@/themes/types';
@@ -28,6 +29,11 @@ const FONT_OPTIONS = [
{ label: 'Work Sans', value: 'Work Sans' }, { label: 'Work Sans', value: 'Work Sans' },
]; ];
const SIDE_QUEUE_OPTIONS = [
{ label: 'Fixed', value: 'sideQueue' },
{ label: 'Floating', value: 'sideDrawerQueue' },
];
export const GeneralTab = () => { export const GeneralTab = () => {
const settings = useGeneralSettings(); const settings = useGeneralSettings();
const { setSettings } = useSettingsStoreActions(); const { setSettings } = useSettingsStoreActions();
@@ -176,6 +182,46 @@ export const GeneralTab = () => {
}, },
]; ];
const layoutOptions = [
{
control: (
<Select
data={SIDE_QUEUE_OPTIONS}
defaultValue={settings.sideQueueType}
onChange={(e) => {
setSettings({
general: {
...settings,
sideQueueType: e as SideQueueType,
},
});
}}
/>
),
description: 'The style of the sidebar play queue',
isHidden: false,
title: 'Side play queue style',
},
{
control: (
<Switch
defaultChecked={settings.showQueueDrawerButton}
onChange={(e) => {
setSettings({
general: {
...settings,
showQueueDrawerButton: e.currentTarget.checked,
},
});
}}
/>
),
description: 'Display a hover icon on the right side of the application view the play queue',
isHidden: false,
title: 'Show floating queue hover area',
},
];
return ( return (
<Stack spacing="xl"> <Stack spacing="xl">
{options {options
@@ -195,6 +241,15 @@ export const GeneralTab = () => {
{...option} {...option}
/> />
))} ))}
<Divider />
{layoutOptions
.filter((o) => !o.isHidden)
.map((option) => (
<SettingsOptions
key={`general-${option.title}`}
{...option}
/>
))}
</Stack> </Stack>
); );
}; };
@@ -9,7 +9,7 @@ import { Outlet, useLocation } from 'react-router';
import styled from 'styled-components'; import styled from 'styled-components';
import { AppRoute } from '/@/router/routes'; import { AppRoute } from '/@/router/routes';
import { useAppStore } from '/@/store'; import { useAppStore } from '/@/store';
import { useSettingsStore } from '/@/store/settings.store'; import { useGeneralSettings, useSettingsStore } from '/@/store/settings.store';
import { PlaybackType } from '/@/types'; import { PlaybackType } from '/@/types';
import { constrainRightSidebarWidth, constrainSidebarWidth } from '/@/utils'; import { constrainRightSidebarWidth, constrainSidebarWidth } from '/@/utils';
import { Playerbar } from '/@/features/player'; import { Playerbar } from '/@/features/player';
@@ -120,6 +120,7 @@ export const DefaultLayout = ({ shell }: DefaultLayoutProps) => {
const { setSidebar } = useAppStoreActions(); const { setSidebar } = useAppStoreActions();
const [drawer, drawerHandler] = useDisclosure(false); const [drawer, drawerHandler] = useDisclosure(false);
const location = useLocation(); const location = useLocation();
const { sideQueueType, showQueueDrawerButton } = useGeneralSettings();
const sidebarRef = useRef<HTMLDivElement | null>(null); const sidebarRef = useRef<HTMLDivElement | null>(null);
const rightSidebarRef = useRef<HTMLDivElement | null>(null); const rightSidebarRef = useRef<HTMLDivElement | null>(null);
@@ -136,8 +137,11 @@ export const DefaultLayout = ({ shell }: DefaultLayoutProps) => {
drawerTimeout.clear(); drawerTimeout.clear();
}, [drawerTimeout]); }, [drawerTimeout]);
const showQueueDrawerButton = const isQueueDrawerButtonVisible =
!sidebar.rightExpanded && !drawer && location.pathname !== AppRoute.NOW_PLAYING; showQueueDrawerButton &&
!sidebar.rightExpanded &&
!drawer &&
location.pathname !== AppRoute.NOW_PLAYING;
const showSideQueue = sidebar.rightExpanded && location.pathname !== AppRoute.NOW_PLAYING; const showSideQueue = sidebar.rightExpanded && location.pathname !== AppRoute.NOW_PLAYING;
@@ -249,7 +253,7 @@ export const DefaultLayout = ({ shell }: DefaultLayoutProps) => {
<Layout> <Layout>
<MainContainer <MainContainer
leftSidebarWidth={sidebar.leftWidth} leftSidebarWidth={sidebar.leftWidth}
rightExpanded={showSideQueue} rightExpanded={showSideQueue && sideQueueType === 'sideQueue'}
rightSidebarWidth={sidebar.rightWidth} rightSidebarWidth={sidebar.rightWidth}
> >
{!shell && ( {!shell && (
@@ -270,7 +274,7 @@ export const DefaultLayout = ({ shell }: DefaultLayoutProps) => {
initial={false} initial={false}
mode="wait" mode="wait"
> >
{showQueueDrawerButton && ( {isQueueDrawerButtonVisible && (
<QueueDrawerArea <QueueDrawerArea
key="queue-drawer-button" key="queue-drawer-button"
animate="visible" animate="visible"
@@ -311,24 +315,45 @@ export const DefaultLayout = ({ shell }: DefaultLayoutProps) => {
mode="wait" mode="wait"
> >
{showSideQueue && ( {showSideQueue && (
<RightSidebarContainer <>
key="queue-sidebar" {sideQueueType === 'sideQueue' ? (
animate="open" <RightSidebarContainer
exit="closed" key="queue-sidebar"
initial="closed" animate="open"
variants={queueSidebarVariants} exit="closed"
> initial="closed"
<ResizeHandle variants={queueSidebarVariants}
ref={rightSidebarRef} >
isResizing={isResizingRight} <ResizeHandle
placement="left" ref={rightSidebarRef}
onMouseDown={(e) => { isResizing={isResizingRight}
e.preventDefault(); placement="left"
startResizing('right'); onMouseDown={(e) => {
}} e.preventDefault();
/> startResizing('right');
<SidebarPlayQueue /> }}
</RightSidebarContainer> />
<SidebarPlayQueue />
</RightSidebarContainer>
) : (
<QueueDrawer
key="queue-drawer"
animate="open"
exit="closed"
initial="closed"
variants={queueDrawerVariants}
onMouseLeave={() => {
// The drawer will close due to the delay when setting isReorderingQueue
setTimeout(() => {
if (useAppStore.getState().isReorderingQueue) return;
drawerHandler.close();
}, 50);
}}
>
<DrawerPlayQueue />
</QueueDrawer>
)}
</>
)} )}
</AnimatePresence> </AnimatePresence>
</> </>
@@ -20,11 +20,15 @@ export type DataTableProps = {
rowHeight: number; rowHeight: number;
}; };
type SideQueue = 'sideQueue' | 'sideDrawerQueue';
export interface SettingsState { export interface SettingsState {
general: { general: {
followSystemTheme: boolean; followSystemTheme: boolean;
fontContent: string; fontContent: string;
fontHeader: string; fontHeader: string;
showQueueDrawerButton: boolean;
sideQueueType: SideQueue;
theme: AppTheme; theme: AppTheme;
themeDark: AppTheme; themeDark: AppTheme;
themeLight: AppTheme; themeLight: AppTheme;
@@ -75,6 +79,8 @@ export const useSettingsStore = create<SettingsSlice>()(
followSystemTheme: false, followSystemTheme: false,
fontContent: 'Circular STD', fontContent: 'Circular STD',
fontHeader: 'Gotham', fontHeader: 'Gotham',
showQueueDrawerButton: true,
sideQueueType: 'sideQueue',
theme: AppTheme.DEFAULT_DARK, theme: AppTheme.DEFAULT_DARK,
themeDark: AppTheme.DEFAULT_DARK, themeDark: AppTheme.DEFAULT_DARK,
themeLight: AppTheme.DEFAULT_LIGHT, themeLight: AppTheme.DEFAULT_LIGHT,