feishin/src/renderer/layouts/default-layout/main-content.tsx

126 lines
4.6 KiB
TypeScript
Raw Normal View History

import clsx from 'clsx';
import throttle from 'lodash/throttle';
import { motion } from 'motion/react';
import {
CSSProperties,
lazy,
Suspense,
useCallback,
useEffect,
useMemo,
useRef,
useState,
} from 'react';
2023-03-28 23:59:51 -07:00
import { Outlet, useLocation } from 'react-router';
import styles from './main-content.module.css';
import { FullScreenOverlay } from '/@/renderer/layouts/default-layout/full-screen-overlay';
import { LeftSidebar } from '/@/renderer/layouts/default-layout/left-sidebar';
import { RightSidebar } from '/@/renderer/layouts/default-layout/right-sidebar';
2023-03-28 23:59:51 -07:00
import { AppRoute } from '/@/renderer/router/routes';
2023-05-31 01:13:54 -07:00
import { useAppStoreActions, useSidebarStore } from '/@/renderer/store';
import { useGeneralSettings } from '/@/renderer/store/settings.store';
import { constrainRightSidebarWidth, constrainSidebarWidth } from '/@/renderer/utils';
import { Spinner } from '/@/shared/components/spinner/spinner';
2023-05-31 01:13:54 -07:00
const SideDrawerQueue = lazy(() =>
2023-07-01 19:10:05 -07:00
import('/@/renderer/layouts/default-layout/side-drawer-queue').then((module) => ({
default: module.SideDrawerQueue,
})),
2023-05-31 01:13:54 -07:00
);
2023-03-28 23:59:51 -07:00
const MINIMUM_SIDEBAR_WIDTH = 260;
2023-03-28 23:59:51 -07:00
export const MainContent = ({ shell }: { shell?: boolean }) => {
2023-07-01 19:10:05 -07:00
const location = useLocation();
const { collapsed, leftWidth, rightExpanded, rightWidth } = useSidebarStore();
2023-07-01 19:10:05 -07:00
const { setSideBar } = useAppStoreActions();
const { showQueueDrawerButton, sideQueueType } = useGeneralSettings();
2023-07-01 19:10:05 -07:00
const [isResizing, setIsResizing] = useState(false);
const [isResizingRight, setIsResizingRight] = useState(false);
2023-03-28 23:59:51 -07:00
2023-07-01 19:10:05 -07:00
const showSideQueue = rightExpanded && location.pathname !== AppRoute.NOW_PLAYING;
const rightSidebarRef = useRef<HTMLDivElement | null>(null);
2023-03-28 23:59:51 -07:00
2023-07-01 19:10:05 -07:00
const startResizing = useCallback((position: 'left' | 'right') => {
if (position === 'left') return setIsResizing(true);
return setIsResizingRight(true);
}, []);
2023-03-28 23:59:51 -07:00
2023-07-01 19:10:05 -07:00
const stopResizing = useCallback(() => {
setIsResizing(false);
setIsResizingRight(false);
}, []);
2023-03-28 23:59:51 -07:00
2023-07-01 19:10:05 -07:00
const resize = useCallback(
(mouseMoveEvent: any) => {
if (isResizing) {
const width = mouseMoveEvent.clientX;
const constrainedWidth = `${constrainSidebarWidth(width)}px`;
2023-07-01 19:10:05 -07:00
if (width < MINIMUM_SIDEBAR_WIDTH - 100) {
setSideBar({ collapsed: true });
} else {
setSideBar({ collapsed: false, leftWidth: constrainedWidth });
}
} else if (isResizingRight) {
const start = Number(rightWidth.split('px')[0]);
const { left } = rightSidebarRef!.current!.getBoundingClientRect();
const width = `${constrainRightSidebarWidth(
start + left - mouseMoveEvent.clientX,
)}px`;
setSideBar({ rightWidth: width });
}
},
[isResizing, isResizingRight, setSideBar, rightWidth],
);
2023-03-28 23:59:51 -07:00
2023-07-01 19:10:05 -07:00
const throttledResize = useMemo(() => throttle(resize, 50), [resize]);
2023-03-28 23:59:51 -07:00
2023-07-01 19:10:05 -07:00
useEffect(() => {
window.addEventListener('mousemove', throttledResize);
window.addEventListener('mouseup', stopResizing);
return () => {
window.removeEventListener('mousemove', throttledResize);
window.removeEventListener('mouseup', stopResizing);
};
}, [throttledResize, stopResizing]);
2023-03-28 23:59:51 -07:00
2023-07-01 19:10:05 -07:00
return (
<motion.div
className={clsx(styles.mainContentContainer, {
[styles.rightExpanded]: showSideQueue && sideQueueType === 'sideQueue',
[styles.shell]: shell,
[styles.sidebarCollapsed]: collapsed,
[styles.sidebarExpanded]: !collapsed,
})}
2023-07-01 19:10:05 -07:00
id="main-content"
style={
{
'--right-sidebar-width': rightWidth,
'--sidebar-width': leftWidth,
} as CSSProperties
}
2023-07-01 19:10:05 -07:00
>
{!shell && (
<>
<Suspense fallback={<></>}>
{showQueueDrawerButton && <SideDrawerQueue />}
</Suspense>
<FullScreenOverlay />
2025-07-12 11:17:54 -07:00
<LeftSidebar isResizing={isResizing} startResizing={startResizing} />
2023-07-01 19:10:05 -07:00
<RightSidebar
isResizing={isResizingRight}
ref={rightSidebarRef}
2023-07-01 19:10:05 -07:00
startResizing={startResizing}
/>
</>
)}
<Suspense fallback={<Spinner container />}>
<Outlet />
</Suspense>
</motion.div>
2023-07-01 19:10:05 -07:00
);
2023-03-28 23:59:51 -07:00
};