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

136 lines
4.5 KiB
TypeScript
Raw Normal View History

2023-05-31 01:13:54 -07:00
import { lazy, Suspense, useCallback, useEffect, useMemo, useRef, useState } from 'react';
2023-03-28 23:59:51 -07:00
import { throttle } from 'lodash';
import { Outlet, useLocation } from 'react-router';
import styled from 'styled-components';
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';
2023-03-28 23:59:51 -07:00
import { constrainSidebarWidth, constrainRightSidebarWidth } from '/@/renderer/utils';
2023-05-31 01:13:54 -07:00
import { LeftSidebar } from '/@/renderer/layouts/default-layout/left-sidebar';
import { FullScreenOverlay } from '/@/renderer/layouts/default-layout/full-screen-overlay';
import { RightSidebar } from '/@/renderer/layouts/default-layout/right-sidebar';
2023-06-01 20:08:43 -07:00
import { Center } from '@mantine/core';
import { Spinner } from '/@/renderer/components';
2023-05-31 01:13:54 -07:00
const SideDrawerQueue = lazy(() =>
import('/@/renderer/layouts/default-layout/side-drawer-queue').then((module) => ({
default: module.SideDrawerQueue,
})),
);
2023-03-28 23:59:51 -07:00
const MINIMUM_SIDEBAR_WIDTH = 260;
2023-03-28 23:59:51 -07:00
const MainContentContainer = styled.div<{
leftSidebarWidth: string;
rightExpanded?: boolean;
rightSidebarWidth?: string;
shell?: boolean;
sidebarCollapsed?: boolean;
2023-03-28 23:59:51 -07:00
}>`
position: relative;
display: ${(props) => (props.shell ? 'flex' : 'grid')};
grid-area: main-content;
grid-template-areas: 'sidebar . right-sidebar';
grid-template-rows: 1fr;
grid-template-columns: ${(props) => (props.sidebarCollapsed ? '80px' : props.leftSidebarWidth)} 1fr ${(
props,
) => props.rightExpanded && props.rightSidebarWidth};
2023-03-28 23:59:51 -07:00
gap: 0;
background: var(--main-bg);
`;
export const MainContent = ({ shell }: { shell?: boolean }) => {
const location = useLocation();
2023-05-31 01:13:54 -07:00
const { collapsed, leftWidth, rightWidth, rightExpanded } = useSidebarStore();
const { setSideBar } = useAppStoreActions();
const { sideQueueType } = useGeneralSettings();
2023-03-28 23:59:51 -07:00
const [isResizing, setIsResizing] = useState(false);
const [isResizingRight, setIsResizingRight] = useState(false);
2023-05-31 01:13:54 -07:00
const { showQueueDrawerButton } = useGeneralSettings();
2023-03-28 23:59:51 -07:00
2023-05-31 01:13:54 -07:00
const showSideQueue = rightExpanded && location.pathname !== AppRoute.NOW_PLAYING;
const rightSidebarRef = useRef<HTMLDivElement | null>(null);
2023-03-28 23:59:51 -07:00
const startResizing = useCallback((position: 'left' | 'right') => {
if (position === 'left') return setIsResizing(true);
return setIsResizingRight(true);
}, []);
const stopResizing = useCallback(() => {
setIsResizing(false);
setIsResizingRight(false);
}, []);
const resize = useCallback(
(mouseMoveEvent: any) => {
if (isResizing) {
const width = mouseMoveEvent.clientX;
const constrainedWidth = `${constrainSidebarWidth(width)}px`;
if (width < MINIMUM_SIDEBAR_WIDTH - 100) {
setSideBar({ collapsed: true });
} else {
setSideBar({ collapsed: false, leftWidth: constrainedWidth });
}
} else if (isResizingRight) {
2023-05-31 01:13:54 -07:00
const start = Number(rightWidth.split('px')[0]);
2023-03-28 23:59:51 -07:00
const { left } = rightSidebarRef!.current!.getBoundingClientRect();
const width = `${constrainRightSidebarWidth(start + left - mouseMoveEvent.clientX)}px`;
setSideBar({ rightWidth: width });
}
},
2023-05-31 01:13:54 -07:00
[isResizing, isResizingRight, setSideBar, rightWidth],
2023-03-28 23:59:51 -07:00
);
const throttledResize = useMemo(() => throttle(resize, 50), [resize]);
useEffect(() => {
window.addEventListener('mousemove', throttledResize);
window.addEventListener('mouseup', stopResizing);
return () => {
window.removeEventListener('mousemove', throttledResize);
window.removeEventListener('mouseup', stopResizing);
};
}, [throttledResize, stopResizing]);
return (
<MainContentContainer
id="main-content"
2023-05-31 01:13:54 -07:00
leftSidebarWidth={leftWidth}
2023-03-28 23:59:51 -07:00
rightExpanded={showSideQueue && sideQueueType === 'sideQueue'}
2023-05-31 01:13:54 -07:00
rightSidebarWidth={rightWidth}
2023-03-28 23:59:51 -07:00
shell={shell}
2023-05-31 01:13:54 -07:00
sidebarCollapsed={collapsed}
2023-03-28 23:59:51 -07:00
>
{!shell && (
2023-06-01 20:08:43 -07:00
<>
<Suspense fallback={<></>}>{showQueueDrawerButton && <SideDrawerQueue />}</Suspense>
2023-05-31 01:13:54 -07:00
<FullScreenOverlay />
<LeftSidebar
isResizing={isResizing}
startResizing={startResizing}
/>
<RightSidebar
ref={rightSidebarRef}
isResizing={isResizingRight}
startResizing={startResizing}
/>
2023-06-01 20:08:43 -07:00
</>
2023-03-28 23:59:51 -07:00
)}
2023-06-01 20:08:43 -07:00
<Suspense
fallback={
<Center
h="100%"
w="100%"
>
<Spinner />
</Center>
}
>
2023-03-28 23:59:51 -07:00
<Outlet />
</Suspense>
</MainContentContainer>
);
};