feat: redesign settings page

This commit is contained in:
butterfly
2024-04-24 15:44:24 +08:00
parent f7074bba8c
commit c99086447e
55 changed files with 2603 additions and 1446 deletions

59
app/hooks/useDrag.ts Normal file
View File

@@ -0,0 +1,59 @@
import { RefObject, useRef } from "react";
export default function useDrag(options: {
customDragMove: (nextWidth: number, start?: number) => void;
customToggle: () => void;
customLimit?: (x: number, start?: number) => number;
customDragEnd?: (nextWidth: number, start?: number) => void;
}) {
const { customDragMove, customToggle, customLimit, customDragEnd } =
options || {};
const limit = customLimit;
const startX = useRef(0);
const lastUpdateTime = useRef(Date.now());
const toggleSideBar = customToggle;
const onDragMove = customDragMove;
const onDragStart = (e: MouseEvent) => {
// Remembers the initial width each time the mouse is pressed
startX.current = e.clientX;
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?.(d, startX.current) ?? d;
onDragMove(nextWidth, startX.current);
};
const handleDragEnd = (e: MouseEvent) => {
// 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();
} else {
const d = e.clientX - startX.current;
const nextWidth = limit?.(d, startX.current) ?? d;
customDragEnd?.(nextWidth, startX.current);
}
};
window.addEventListener("pointermove", handleDragMove);
window.addEventListener("pointerup", handleDragEnd);
};
return {
onDragStart,
};
}

View File

@@ -1,74 +0,0 @@
import {
DEFAULT_SIDEBAR_WIDTH,
MAX_SIDEBAR_WIDTH,
MIN_SIDEBAR_WIDTH,
} from "@/app/constant";
import { useAppConfig } from "@/app/store/config";
import { useRef } from "react";
import { updateGlobalCSSVars } from "@/app/utils/client";
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);
const { menuWidth } = updateGlobalCSSVars(nextWidth);
document.documentElement.style.setProperty(
"--menu-width",
`${menuWidth}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("--menu-width", `${barWidth}px`);
// }, [config.sidebarWidth]);
return {
onDragStart,
};
}

View File

@@ -8,7 +8,6 @@ import {
DEFAULT_SIDEBAR_WIDTH,
MAX_SIDEBAR_WIDTH,
MIN_SIDEBAR_WIDTH,
SIDEBAR_ID,
} from "@/app/constant";
import { useAppConfig } from "@/app/store/config";
import { updateGlobalCSSVars } from "@/app/utils/client";
@@ -49,5 +48,8 @@ export default function useListenWinResize() {
config.update((config) => {
config.sidebarWidth = menuWidth;
});
config.update((config) => {
config.isMobileScreen = size.width <= MOBILE_MAX_WIDTH;
});
});
}

View File

@@ -1,6 +1,5 @@
import { useWindowSize } from "@/app/hooks/useWindowSize";
export const MOBILE_MAX_WIDTH = 768;
import { MOBILE_MAX_WIDTH } from "@/app/hooks/useListenWinResize";
export default function useMobileScreen() {
const { width } = useWindowSize();

View File

@@ -2,7 +2,7 @@ import { RefObject, useState } from "react";
import { useDebouncedCallback } from "use-debounce";
export interface Options {
containerRef: RefObject<HTMLDivElement | null>;
containerRef?: RefObject<HTMLElement | null>;
delay?: number;
offsetDistance?: number;
}
@@ -32,7 +32,7 @@ interface Position {
}
export default function useRelativePosition({
containerRef,
containerRef = { current: window.document.body },
delay = 100,
offsetDistance = 0,
}: Options) {
@@ -49,6 +49,7 @@ export default function useRelativePosition({
width: targetW,
height: targetH,
} = target.getBoundingClientRect();
const {
x: containerX,
y: containerY,

View File

@@ -1,7 +1,7 @@
import { useState } from "react";
import { useDebouncedCallback } from "use-debounce";
import { autoGrowTextArea } from "../utils";
import useMobileScreen from "./useMobileScreen";
import { useAppConfig } from "../store";
export default function useRows({
inputRef,
@@ -9,14 +9,14 @@ export default function useRows({
inputRef: React.RefObject<HTMLTextAreaElement>;
}) {
const [inputRows, setInputRows] = useState(2);
const isMobileScreen = useMobileScreen();
const config = useAppConfig();
const measure = useDebouncedCallback(
() => {
const rows = inputRef.current ? autoGrowTextArea(inputRef.current) : 1;
const inputRows = Math.min(
20,
Math.max(2 + (isMobileScreen ? -1 : 1), rows),
Math.max(2 + (config.isMobileScreen ? -1 : 1), rows),
);
setInputRows(inputRows);
},