mirror of
https://github.com/jeffvli/feishin.git
synced 2026-07-21 18:06:30 +02:00
support vertical play queue layout
This commit is contained in:
@@ -28,6 +28,23 @@
|
||||
grid-template-columns: 80px 1fr var(--right-sidebar-width);
|
||||
}
|
||||
|
||||
.main-content-container.vertical-layout {
|
||||
grid-template-areas:
|
||||
'sidebar .'
|
||||
'sidebar right-sidebar';
|
||||
grid-template-rows: minmax(0, 1fr) var(--right-sidebar-height);
|
||||
grid-template-columns: var(--sidebar-width) 1fr;
|
||||
}
|
||||
|
||||
.main-content-container.sidebar-collapsed.vertical-layout {
|
||||
grid-template-columns: 80px 1fr;
|
||||
}
|
||||
|
||||
.main-content-container.vertical-layout #sidebar-queue {
|
||||
border-top: 1px solid alpha(var(--theme-colors-border), 0.5);
|
||||
border-left: 0;
|
||||
}
|
||||
|
||||
.main-content-body {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
|
||||
@@ -16,6 +16,7 @@ import {
|
||||
useAppStore,
|
||||
useAppStoreActions,
|
||||
useGlobalExpanded,
|
||||
useSideQueueLayout,
|
||||
useSideQueueType,
|
||||
} from '/@/renderer/store';
|
||||
import { constrainRightSidebarWidth, constrainSidebarWidth } from '/@/renderer/utils';
|
||||
@@ -24,56 +25,77 @@ import { Spinner } from '/@/shared/components/spinner/spinner';
|
||||
const MINIMUM_SIDEBAR_WIDTH = 260;
|
||||
|
||||
export const MainContent = ({ shell }: { shell?: boolean }) => {
|
||||
const { collapsed, leftWidth, rightExpanded, rightWidth } = useAppStore(
|
||||
const { collapsed, leftWidth, rightExpanded, rightHeight, rightWidth } = useAppStore(
|
||||
(state) => ({
|
||||
collapsed: state.sidebar.collapsed,
|
||||
leftWidth: state.sidebar.leftWidth,
|
||||
rightExpanded: state.sidebar.rightExpanded,
|
||||
rightHeight: state.sidebar.rightHeight,
|
||||
rightWidth: state.sidebar.rightWidth,
|
||||
}),
|
||||
shallow,
|
||||
);
|
||||
const { setSideBar } = useAppStoreActions();
|
||||
const sideQueueType = useSideQueueType();
|
||||
const sideQueueLayout = useSideQueueLayout();
|
||||
const [isResizing, setIsResizing] = useState(false);
|
||||
const [isResizingRight, setIsResizingRight] = useState(false);
|
||||
|
||||
const rightSidebarRef = useRef<HTMLDivElement | null>(null);
|
||||
const mainContentRef = useRef<HTMLDivElement | null>(null);
|
||||
const initialRightWidthRef = useRef<string>(rightWidth);
|
||||
const initialRightHeightRef = useRef<string>(rightHeight);
|
||||
const initialMouseXRef = useRef<number>(0);
|
||||
const initialMouseYRef = useRef<number>(0);
|
||||
const wasCollapsedDuringDragRef = useRef<boolean>(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (mainContentRef.current && !isResizing && !isResizingRight) {
|
||||
mainContentRef.current.style.setProperty('--sidebar-width', leftWidth);
|
||||
mainContentRef.current.style.setProperty('--right-sidebar-width', rightWidth);
|
||||
mainContentRef.current.style.setProperty('--right-sidebar-height', rightHeight);
|
||||
initialRightWidthRef.current = rightWidth;
|
||||
initialRightHeightRef.current = rightHeight;
|
||||
}
|
||||
}, [leftWidth, rightWidth, isResizing, isResizingRight]);
|
||||
}, [leftWidth, rightWidth, rightHeight, isResizing, isResizingRight]);
|
||||
|
||||
const startResizing = useCallback(
|
||||
(position: 'left' | 'right', mouseEvent?: MouseEvent) => {
|
||||
(position: 'left' | 'right' | 'top', mouseEvent?: MouseEvent) => {
|
||||
if (position === 'left') {
|
||||
setIsResizing(true);
|
||||
wasCollapsedDuringDragRef.current = false;
|
||||
} else {
|
||||
setIsResizingRight(true);
|
||||
if (mainContentRef.current && rightSidebarRef.current && mouseEvent) {
|
||||
const currentWidth =
|
||||
mainContentRef.current.style.getPropertyValue('--right-sidebar-width');
|
||||
if (currentWidth) {
|
||||
initialRightWidthRef.current = currentWidth;
|
||||
if (position === 'top') {
|
||||
const currentHeight =
|
||||
mainContentRef.current.style.getPropertyValue('--right-sidebar-height');
|
||||
if (currentHeight) {
|
||||
initialRightHeightRef.current = currentHeight;
|
||||
} else {
|
||||
initialRightHeightRef.current = rightHeight;
|
||||
}
|
||||
initialMouseYRef.current = mouseEvent.clientY;
|
||||
} else {
|
||||
const currentWidth =
|
||||
mainContentRef.current.style.getPropertyValue('--right-sidebar-width');
|
||||
if (currentWidth) {
|
||||
initialRightWidthRef.current = currentWidth;
|
||||
} else {
|
||||
initialRightWidthRef.current = rightWidth;
|
||||
}
|
||||
initialMouseXRef.current = mouseEvent.clientX;
|
||||
}
|
||||
} else {
|
||||
if (position === 'top') {
|
||||
initialRightHeightRef.current = rightHeight;
|
||||
} else {
|
||||
initialRightWidthRef.current = rightWidth;
|
||||
}
|
||||
initialMouseXRef.current = mouseEvent.clientX;
|
||||
} else {
|
||||
initialRightWidthRef.current = rightWidth;
|
||||
}
|
||||
}
|
||||
},
|
||||
[rightWidth],
|
||||
[rightHeight, rightWidth],
|
||||
);
|
||||
|
||||
const stopResizing = useCallback(() => {
|
||||
@@ -87,14 +109,22 @@ export const MainContent = ({ shell }: { shell?: boolean }) => {
|
||||
setIsResizing(false);
|
||||
wasCollapsedDuringDragRef.current = false;
|
||||
} else if (isResizingRight && mainContentRef.current) {
|
||||
const finalWidth =
|
||||
mainContentRef.current.style.getPropertyValue('--right-sidebar-width');
|
||||
if (finalWidth) {
|
||||
setSideBar({ rightWidth: finalWidth });
|
||||
if (sideQueueLayout === 'vertical') {
|
||||
const finalHeight =
|
||||
mainContentRef.current.style.getPropertyValue('--right-sidebar-height');
|
||||
if (finalHeight) {
|
||||
setSideBar({ rightHeight: finalHeight });
|
||||
}
|
||||
} else {
|
||||
const finalWidth =
|
||||
mainContentRef.current.style.getPropertyValue('--right-sidebar-width');
|
||||
if (finalWidth) {
|
||||
setSideBar({ rightWidth: finalWidth });
|
||||
}
|
||||
}
|
||||
setIsResizingRight(false);
|
||||
}
|
||||
}, [isResizing, isResizingRight, setSideBar]);
|
||||
}, [isResizing, isResizingRight, setSideBar, sideQueueLayout]);
|
||||
|
||||
const resize = useCallback(
|
||||
(mouseMoveEvent: any) => {
|
||||
@@ -118,15 +148,30 @@ export const MainContent = ({ shell }: { shell?: boolean }) => {
|
||||
mainContentRef.current.style.setProperty('--sidebar-width', constrainedWidth);
|
||||
}
|
||||
} else if (isResizingRight) {
|
||||
const initialWidth = Number(initialRightWidthRef.current.split('px')[0]);
|
||||
const initialMouseX = initialMouseXRef.current;
|
||||
const deltaX = mouseMoveEvent.clientX - initialMouseX;
|
||||
const newWidth = initialWidth - deltaX;
|
||||
const width = `${constrainRightSidebarWidth(newWidth)}px`;
|
||||
mainContentRef.current.style.setProperty('--right-sidebar-width', width);
|
||||
if (sideQueueLayout === 'vertical') {
|
||||
const initialHeight = Number(initialRightHeightRef.current.split('px')[0]);
|
||||
const initialMouseY = initialMouseYRef.current;
|
||||
const deltaY = mouseMoveEvent.clientY - initialMouseY;
|
||||
const containerHeight = mainContentRef.current.clientHeight;
|
||||
const minHeight = 220;
|
||||
const maxHeight = Math.max(minHeight, containerHeight - 200);
|
||||
const newHeight = initialHeight - deltaY;
|
||||
const clampedHeight = Math.min(Math.max(newHeight, minHeight), maxHeight);
|
||||
mainContentRef.current.style.setProperty(
|
||||
'--right-sidebar-height',
|
||||
`${clampedHeight}px`,
|
||||
);
|
||||
} else {
|
||||
const initialWidth = Number(initialRightWidthRef.current.split('px')[0]);
|
||||
const initialMouseX = initialMouseXRef.current;
|
||||
const deltaX = mouseMoveEvent.clientX - initialMouseX;
|
||||
const newWidth = initialWidth - deltaX;
|
||||
const width = `${constrainRightSidebarWidth(newWidth)}px`;
|
||||
mainContentRef.current.style.setProperty('--right-sidebar-width', width);
|
||||
}
|
||||
}
|
||||
},
|
||||
[isResizing, isResizingRight, setSideBar],
|
||||
[isResizing, isResizingRight, setSideBar, sideQueueLayout],
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
@@ -145,6 +190,10 @@ export const MainContent = ({ shell }: { shell?: boolean }) => {
|
||||
[styles.shell]: shell,
|
||||
[styles.sidebarCollapsed]: collapsed,
|
||||
[styles.sidebarExpanded]: !collapsed,
|
||||
[styles.verticalLayout]:
|
||||
rightExpanded &&
|
||||
sideQueueType === 'sideQueue' &&
|
||||
sideQueueLayout === 'vertical',
|
||||
})}
|
||||
id="main-content"
|
||||
ref={mainContentRef}
|
||||
|
||||
@@ -14,6 +14,11 @@
|
||||
}
|
||||
}
|
||||
|
||||
.right-sidebar-container.vertical-layout {
|
||||
border-top: 1px solid alpha(var(--theme-colors-border), 0.5);
|
||||
border-left: 0;
|
||||
}
|
||||
|
||||
.queue-drawer {
|
||||
border-radius: var(--theme-radius-lg);
|
||||
}
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import clsx from 'clsx';
|
||||
import { forwardRef, Ref } from 'react';
|
||||
|
||||
import styles from './right-sidebar.module.css';
|
||||
|
||||
import { SidebarPlayQueue } from '/@/renderer/features/now-playing/components/sidebar-play-queue';
|
||||
import { ResizeHandle } from '/@/renderer/features/shared/components/resize-handle';
|
||||
import { useAppStore, useSideQueueType } from '/@/renderer/store';
|
||||
import { useAppStore, useSideQueueLayout, useSideQueueType } from '/@/renderer/store';
|
||||
|
||||
// const queueDrawerVariants: Variants = {
|
||||
// closed: (windowBarStyle) => ({
|
||||
@@ -46,7 +47,7 @@ import { useAppStore, useSideQueueType } from '/@/renderer/store';
|
||||
|
||||
interface RightSidebarProps {
|
||||
isResizing: boolean;
|
||||
startResizing: (direction: 'left' | 'right', mouseEvent?: MouseEvent) => void;
|
||||
startResizing: (direction: 'left' | 'right' | 'top', mouseEvent?: MouseEvent) => void;
|
||||
}
|
||||
|
||||
export const RightSidebar = forwardRef(
|
||||
@@ -56,12 +57,16 @@ export const RightSidebar = forwardRef(
|
||||
) => {
|
||||
const rightExpanded = useAppStore((state) => state.sidebar.rightExpanded);
|
||||
const sideQueueType = useSideQueueType();
|
||||
const sideQueueLayout = useSideQueueLayout();
|
||||
const isVerticalLayout = sideQueueLayout === 'vertical';
|
||||
|
||||
return (
|
||||
<>
|
||||
{rightExpanded && sideQueueType === 'sideQueue' && (
|
||||
<aside
|
||||
className={styles.rightSidebarContainer}
|
||||
className={clsx(styles.rightSidebarContainer, {
|
||||
[styles.verticalLayout]: isVerticalLayout,
|
||||
})}
|
||||
id="sidebar-queue"
|
||||
key="queue-sidebar"
|
||||
>
|
||||
@@ -69,9 +74,9 @@ export const RightSidebar = forwardRef(
|
||||
isResizing={isResizingRight}
|
||||
onMouseDown={(e) => {
|
||||
e.preventDefault();
|
||||
startResizing('right', e.nativeEvent);
|
||||
startResizing(isVerticalLayout ? 'top' : 'right', e.nativeEvent);
|
||||
}}
|
||||
placement="left"
|
||||
placement={isVerticalLayout ? 'top' : 'left'}
|
||||
ref={ref}
|
||||
/>
|
||||
<SidebarPlayQueue />
|
||||
|
||||
Reference in New Issue
Block a user