mirror of
https://github.com/jeffvli/feishin.git
synced 2026-05-10 04:30:25 +02:00
Add customizable side queue
This commit is contained in:
@@ -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,
|
||||||
|
|||||||
Reference in New Issue
Block a user