2022-05-04 04:07:09 +00:00
|
|
|
|
import { useCallback, useEffect, useRef, useState } from 'react';
|
2022-03-12 02:31:03 +00:00
|
|
|
|
import useSWR from 'swr';
|
2022-03-27 07:43:06 +00:00
|
|
|
|
import { useWindowSize } from 'hooks/use-window-size';
|
2022-03-12 02:31:03 +00:00
|
|
|
|
import { setStorage, getStorage } from 'helpers/storage';
|
2022-05-04 04:07:09 +00:00
|
|
|
|
import { clamp } from 'helpers/clamp';
|
2022-02-20 11:51:55 +00:00
|
|
|
|
|
2022-03-12 02:31:03 +00:00
|
|
|
|
const key = 'dragable-menu-width';
|
2022-02-20 11:51:55 +00:00
|
|
|
|
|
2022-05-04 04:07:09 +00:00
|
|
|
|
const DEFAULT_PC_MIN_WIDTH = 240;
|
|
|
|
|
const DEFAULT_PC_MAX_WIDTH = 600;
|
|
|
|
|
|
|
|
|
|
const DEFAULT_MOBILE_MIN_WIDTH = 24;
|
|
|
|
|
const DEFAULT_MOBILE_MAX_WIDTH = 240;
|
|
|
|
|
|
|
|
|
|
// 收起宽度:24
|
2022-02-20 11:51:55 +00:00
|
|
|
|
const COLLAPSED_WIDTH = 24;
|
|
|
|
|
|
2022-05-04 04:07:09 +00:00
|
|
|
|
const PC_MOBILE_CRITICAL_WIDTH = 765;
|
|
|
|
|
|
2022-02-20 11:51:55 +00:00
|
|
|
|
export const useDragableWidth = () => {
|
2022-05-04 04:07:09 +00:00
|
|
|
|
const { width: windowWidth } = useWindowSize();
|
|
|
|
|
const [minWidth, setMinWidth] = useState(DEFAULT_MOBILE_MIN_WIDTH);
|
|
|
|
|
const [maxWidth, setMaxWidth] = useState(DEFAULT_MOBILE_MAX_WIDTH);
|
|
|
|
|
const { data: currentWidth, mutate } = useSWR<number>(key, () => {
|
|
|
|
|
const nextWidth = getStorage(key, minWidth);
|
2022-02-20 11:51:55 +00:00
|
|
|
|
|
2022-05-04 04:07:09 +00:00
|
|
|
|
if (nextWidth <= COLLAPSED_WIDTH) {
|
|
|
|
|
return COLLAPSED_WIDTH;
|
|
|
|
|
}
|
2022-02-20 11:51:55 +00:00
|
|
|
|
|
2022-05-04 04:07:09 +00:00
|
|
|
|
return clamp(nextWidth, minWidth, maxWidth);
|
|
|
|
|
});
|
|
|
|
|
const prevWidthRef = useRef<number>(maxWidth);
|
|
|
|
|
|
|
|
|
|
const updateWidth = useCallback(
|
|
|
|
|
(size) => {
|
|
|
|
|
const isMobile = windowWidth <= PC_MOBILE_CRITICAL_WIDTH;
|
|
|
|
|
|
|
|
|
|
if (isMobile && size < maxWidth) {
|
|
|
|
|
size = minWidth;
|
|
|
|
|
}
|
|
|
|
|
setStorage(key, size);
|
|
|
|
|
prevWidthRef.current = size;
|
2022-05-01 14:07:22 +00:00
|
|
|
|
mutate();
|
|
|
|
|
},
|
2022-05-04 04:07:09 +00:00
|
|
|
|
[mutate, windowWidth, minWidth, maxWidth]
|
2022-05-01 14:07:22 +00:00
|
|
|
|
);
|
2022-02-20 11:51:55 +00:00
|
|
|
|
|
2022-05-04 04:07:09 +00:00
|
|
|
|
const toggleCollapsed = useCallback(() => {
|
|
|
|
|
const isCollapsed = currentWidth <= COLLAPSED_WIDTH;
|
2022-02-20 11:51:55 +00:00
|
|
|
|
|
2022-05-04 04:07:09 +00:00
|
|
|
|
if (!isCollapsed) {
|
|
|
|
|
prevWidthRef.current = currentWidth;
|
|
|
|
|
setStorage(key, COLLAPSED_WIDTH);
|
|
|
|
|
} else {
|
|
|
|
|
let nextWidth = prevWidthRef.current;
|
2022-02-20 11:51:55 +00:00
|
|
|
|
|
2022-05-04 04:07:09 +00:00
|
|
|
|
if (nextWidth >= maxWidth) {
|
|
|
|
|
nextWidth = maxWidth;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (nextWidth <= minWidth) {
|
|
|
|
|
nextWidth = minWidth;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
setStorage(key, nextWidth);
|
2022-03-30 05:57:29 +00:00
|
|
|
|
}
|
2022-05-04 04:07:09 +00:00
|
|
|
|
mutate();
|
2022-05-04 06:50:58 +00:00
|
|
|
|
}, [mutate, currentWidth, minWidth, maxWidth]);
|
2022-05-04 04:07:09 +00:00
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
const min = windowWidth <= PC_MOBILE_CRITICAL_WIDTH ? DEFAULT_MOBILE_MIN_WIDTH : DEFAULT_PC_MIN_WIDTH;
|
|
|
|
|
const max = windowWidth <= PC_MOBILE_CRITICAL_WIDTH ? DEFAULT_MOBILE_MAX_WIDTH : DEFAULT_PC_MAX_WIDTH;
|
|
|
|
|
setMinWidth(min);
|
|
|
|
|
setMaxWidth(max);
|
|
|
|
|
}, [windowWidth, mutate, currentWidth]);
|
2022-02-20 11:51:55 +00:00
|
|
|
|
|
|
|
|
|
return {
|
2022-05-04 04:07:09 +00:00
|
|
|
|
minWidth,
|
|
|
|
|
maxWidth,
|
|
|
|
|
width: currentWidth,
|
|
|
|
|
isCollapsed: currentWidth <= COLLAPSED_WIDTH,
|
2022-02-20 11:51:55 +00:00
|
|
|
|
toggleCollapsed,
|
|
|
|
|
updateWidth,
|
|
|
|
|
};
|
|
|
|
|
};
|