ChatGPT-Next-Web/app/hooks/useDragSideBar.ts

72 lines
2.1 KiB
TypeScript

import {
DEFAULT_SIDEBAR_WIDTH,
MAX_SIDEBAR_WIDTH,
MIN_SIDEBAR_WIDTH,
} from "@/app/constant";
import { useAppConfig } from "../store/config";
import { useRef } from "react";
export default function useDragSideBar() {
const limit = (x: number) =>
Math.max(MIN_SIDEBAR_WIDTH, Math.min(MAX_SIDEBAR_WIDTH, x));
const config = useAppConfig();
const startX = useRef(0);
const startDragWidth = useRef(config.sidebarWidth ?? DEFAULT_SIDEBAR_WIDTH);
const lastUpdateTime = useRef(Date.now());
const toggleSideBar = () => {
config.update((config) => {
config.sidebarWidth = DEFAULT_SIDEBAR_WIDTH;
});
};
const onDragStart = (e: MouseEvent) => {
// Remembers the initial width each time the mouse is pressed
startX.current = e.clientX;
startDragWidth.current = config.sidebarWidth;
const dragStartTime = Date.now();
const handleDragMove = (e: MouseEvent) => {
if (Date.now() < lastUpdateTime.current + 20) {
return;
}
lastUpdateTime.current = Date.now();
const d = e.clientX - startX.current;
const nextWidth = limit(startDragWidth.current + d);
document.documentElement.style.setProperty(
"--sidebar-width",
`${nextWidth}px`,
);
config.update((config) => {
config.sidebarWidth = nextWidth;
});
};
const handleDragEnd = () => {
// In useRef the data is non-responsive, so `config.sidebarWidth` can't get the dynamic sidebarWidth
window.removeEventListener("pointermove", handleDragMove);
window.removeEventListener("pointerup", handleDragEnd);
// if user click the drag icon, should toggle the sidebar
const shouldFireClick = Date.now() - dragStartTime < 300;
if (shouldFireClick) {
toggleSideBar();
}
};
window.addEventListener("pointermove", handleDragMove);
window.addEventListener("pointerup", handleDragEnd);
};
// useLayoutEffect(() => {
// const barWidth = limit(config.sidebarWidth ?? DEFAULT_SIDEBAR_WIDTH);
// document.documentElement.style.setProperty("--sidebar-width", `${barWidth}px`);
// }, [config.sidebarWidth]);
return {
onDragStart,
};
}