mirror of
https://github.com/jeffvli/feishin.git
synced 2026-05-09 20:29:36 +02:00
optimize sidebar resizing for performance
This commit is contained in:
@@ -9,7 +9,7 @@ import { useSidebarStore } from '/@/renderer/store';
|
|||||||
|
|
||||||
interface LeftSidebarProps {
|
interface LeftSidebarProps {
|
||||||
isResizing: boolean;
|
isResizing: boolean;
|
||||||
startResizing: (direction: 'left' | 'right') => void;
|
startResizing: (direction: 'left' | 'right', mouseEvent?: MouseEvent) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const LeftSidebar = ({ isResizing, startResizing }: LeftSidebarProps) => {
|
export const LeftSidebar = ({ isResizing, startResizing }: LeftSidebarProps) => {
|
||||||
|
|||||||
@@ -1,16 +1,7 @@
|
|||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
import throttle from 'lodash/throttle';
|
import throttle from 'lodash/throttle';
|
||||||
import { motion } from 'motion/react';
|
import { motion } from 'motion/react';
|
||||||
import {
|
import { lazy, Suspense, useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||||
CSSProperties,
|
|
||||||
lazy,
|
|
||||||
Suspense,
|
|
||||||
useCallback,
|
|
||||||
useEffect,
|
|
||||||
useMemo,
|
|
||||||
useRef,
|
|
||||||
useState,
|
|
||||||
} from 'react';
|
|
||||||
import { Outlet, useLocation } from 'react-router';
|
import { Outlet, useLocation } from 'react-router';
|
||||||
|
|
||||||
import styles from './main-content.module.css';
|
import styles from './main-content.module.css';
|
||||||
@@ -42,19 +33,62 @@ export const MainContent = ({ shell }: { shell?: boolean }) => {
|
|||||||
|
|
||||||
const showSideQueue = rightExpanded && location.pathname !== AppRoute.NOW_PLAYING;
|
const showSideQueue = rightExpanded && location.pathname !== AppRoute.NOW_PLAYING;
|
||||||
const rightSidebarRef = useRef<HTMLDivElement | null>(null);
|
const rightSidebarRef = useRef<HTMLDivElement | null>(null);
|
||||||
|
const mainContentRef = useRef<HTMLDivElement | null>(null);
|
||||||
|
const initialRightWidthRef = useRef<string>(rightWidth);
|
||||||
|
const initialMouseXRef = useRef<number>(0);
|
||||||
|
|
||||||
const startResizing = useCallback((position: 'left' | 'right') => {
|
useEffect(() => {
|
||||||
if (position === 'left') return setIsResizing(true);
|
if (mainContentRef.current && !isResizing && !isResizingRight) {
|
||||||
return setIsResizingRight(true);
|
mainContentRef.current.style.setProperty('--sidebar-width', leftWidth);
|
||||||
}, []);
|
mainContentRef.current.style.setProperty('--right-sidebar-width', rightWidth);
|
||||||
|
initialRightWidthRef.current = rightWidth;
|
||||||
|
}
|
||||||
|
}, [leftWidth, rightWidth, isResizing, isResizingRight]);
|
||||||
|
|
||||||
|
const startResizing = useCallback(
|
||||||
|
(position: 'left' | 'right', mouseEvent?: MouseEvent) => {
|
||||||
|
if (position === 'left') {
|
||||||
|
setIsResizing(true);
|
||||||
|
} else {
|
||||||
|
setIsResizingRight(true);
|
||||||
|
if (mainContentRef.current && rightSidebarRef.current && mouseEvent) {
|
||||||
|
const currentWidth =
|
||||||
|
mainContentRef.current.style.getPropertyValue('--right-sidebar-width');
|
||||||
|
if (currentWidth) {
|
||||||
|
initialRightWidthRef.current = currentWidth;
|
||||||
|
} else {
|
||||||
|
initialRightWidthRef.current = rightWidth;
|
||||||
|
}
|
||||||
|
initialMouseXRef.current = mouseEvent.clientX;
|
||||||
|
} else {
|
||||||
|
initialRightWidthRef.current = rightWidth;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[rightWidth],
|
||||||
|
);
|
||||||
|
|
||||||
const stopResizing = useCallback(() => {
|
const stopResizing = useCallback(() => {
|
||||||
setIsResizing(false);
|
if (isResizing && mainContentRef.current) {
|
||||||
setIsResizingRight(false);
|
const finalWidth = mainContentRef.current.style.getPropertyValue('--sidebar-width');
|
||||||
}, []);
|
if (finalWidth) {
|
||||||
|
setSideBar({ collapsed: false, leftWidth: finalWidth });
|
||||||
|
}
|
||||||
|
setIsResizing(false);
|
||||||
|
} else if (isResizingRight && mainContentRef.current) {
|
||||||
|
const finalWidth =
|
||||||
|
mainContentRef.current.style.getPropertyValue('--right-sidebar-width');
|
||||||
|
if (finalWidth) {
|
||||||
|
setSideBar({ rightWidth: finalWidth });
|
||||||
|
}
|
||||||
|
setIsResizingRight(false);
|
||||||
|
}
|
||||||
|
}, [isResizing, isResizingRight, setSideBar]);
|
||||||
|
|
||||||
const resize = useCallback(
|
const resize = useCallback(
|
||||||
(mouseMoveEvent: any) => {
|
(mouseMoveEvent: any) => {
|
||||||
|
if (!mainContentRef.current) return;
|
||||||
|
|
||||||
if (isResizing) {
|
if (isResizing) {
|
||||||
const width = mouseMoveEvent.clientX;
|
const width = mouseMoveEvent.clientX;
|
||||||
const constrainedWidth = `${constrainSidebarWidth(width)}px`;
|
const constrainedWidth = `${constrainSidebarWidth(width)}px`;
|
||||||
@@ -62,21 +96,21 @@ export const MainContent = ({ shell }: { shell?: boolean }) => {
|
|||||||
if (width < MINIMUM_SIDEBAR_WIDTH - 100) {
|
if (width < MINIMUM_SIDEBAR_WIDTH - 100) {
|
||||||
setSideBar({ collapsed: true });
|
setSideBar({ collapsed: true });
|
||||||
} else {
|
} else {
|
||||||
setSideBar({ collapsed: false, leftWidth: constrainedWidth });
|
mainContentRef.current.style.setProperty('--sidebar-width', constrainedWidth);
|
||||||
}
|
}
|
||||||
} else if (isResizingRight) {
|
} else if (isResizingRight) {
|
||||||
const start = Number(rightWidth.split('px')[0]);
|
const initialWidth = Number(initialRightWidthRef.current.split('px')[0]);
|
||||||
const { left } = rightSidebarRef!.current!.getBoundingClientRect();
|
const initialMouseX = initialMouseXRef.current;
|
||||||
const width = `${constrainRightSidebarWidth(
|
const deltaX = mouseMoveEvent.clientX - initialMouseX;
|
||||||
start + left - mouseMoveEvent.clientX,
|
const newWidth = initialWidth - deltaX;
|
||||||
)}px`;
|
const width = `${constrainRightSidebarWidth(newWidth)}px`;
|
||||||
setSideBar({ rightWidth: width });
|
mainContentRef.current.style.setProperty('--right-sidebar-width', width);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[isResizing, isResizingRight, setSideBar, rightWidth],
|
[isResizing, isResizingRight, setSideBar],
|
||||||
);
|
);
|
||||||
|
|
||||||
const throttledResize = useMemo(() => throttle(resize, 50), [resize]);
|
const throttledResize = useMemo(() => throttle(resize, 10), [resize]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
window.addEventListener('mousemove', throttledResize);
|
window.addEventListener('mousemove', throttledResize);
|
||||||
@@ -96,12 +130,7 @@ export const MainContent = ({ shell }: { shell?: boolean }) => {
|
|||||||
[styles.sidebarExpanded]: !collapsed,
|
[styles.sidebarExpanded]: !collapsed,
|
||||||
})}
|
})}
|
||||||
id="main-content"
|
id="main-content"
|
||||||
style={
|
ref={mainContentRef}
|
||||||
{
|
|
||||||
'--right-sidebar-width': rightWidth,
|
|
||||||
'--sidebar-width': leftWidth,
|
|
||||||
} as CSSProperties
|
|
||||||
}
|
|
||||||
>
|
>
|
||||||
{!shell && (
|
{!shell && (
|
||||||
<>
|
<>
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ const queueDrawerVariants: Variants = {
|
|||||||
|
|
||||||
interface RightSidebarProps {
|
interface RightSidebarProps {
|
||||||
isResizing: boolean;
|
isResizing: boolean;
|
||||||
startResizing: (direction: 'left' | 'right') => void;
|
startResizing: (direction: 'left' | 'right', mouseEvent?: MouseEvent) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const RightSidebar = forwardRef(
|
export const RightSidebar = forwardRef(
|
||||||
@@ -102,7 +102,7 @@ export const RightSidebar = forwardRef(
|
|||||||
isResizing={isResizingRight}
|
isResizing={isResizingRight}
|
||||||
onMouseDown={(e) => {
|
onMouseDown={(e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
startResizing('right');
|
startResizing('right', e.nativeEvent);
|
||||||
}}
|
}}
|
||||||
placement="left"
|
placement="left"
|
||||||
ref={ref}
|
ref={ref}
|
||||||
|
|||||||
Reference in New Issue
Block a user