fix(frontend): harden activity split responsiveness
This commit is contained in:
@@ -71,11 +71,17 @@ export function resizeWidthFromKey(
|
||||
return null;
|
||||
}
|
||||
|
||||
type DragState = { pointerId: number; startX: number; startWidth: number };
|
||||
type DragState = {
|
||||
pointerId: number;
|
||||
startX: number;
|
||||
startWidth: number;
|
||||
target: HTMLDivElement;
|
||||
};
|
||||
|
||||
export function useActivityPanelResize(): {
|
||||
containerRef: RefObject<HTMLDivElement>;
|
||||
panelWidth: number;
|
||||
desktopSplit: boolean;
|
||||
resizing: boolean;
|
||||
separatorProps: {
|
||||
role: "separator";
|
||||
@@ -103,6 +109,7 @@ export function useActivityPanelResize(): {
|
||||
const dragRef = useRef<DragState | null>(null);
|
||||
const [panelWidth, setPanelWidth] = useState(initialWidthRef.current);
|
||||
const [bounds, setBounds] = useState(boundsRef.current);
|
||||
const [desktopSplit, setDesktopSplit] = useState(false);
|
||||
const [resizing, setResizing] = useState(false);
|
||||
|
||||
const applyWidth = useCallback((rawWidth: number, persist: boolean) => {
|
||||
@@ -116,20 +123,42 @@ export function useActivityPanelResize(): {
|
||||
useLayoutEffect(() => {
|
||||
const container = containerRef.current;
|
||||
if (!container) return;
|
||||
const syncBounds = () => {
|
||||
if (container.clientWidth < ACTIVITY_PANEL_MIN_WIDTH + ACTIVITY_CENTRAL_MIN_WIDTH) return;
|
||||
const cancelDrag = () => {
|
||||
const drag = dragRef.current;
|
||||
if (drag?.target.hasPointerCapture?.(drag.pointerId)) {
|
||||
drag.target.releasePointerCapture?.(drag.pointerId);
|
||||
}
|
||||
dragRef.current = null;
|
||||
setResizing(false);
|
||||
};
|
||||
const syncLayout = () => {
|
||||
const viewportIsDesktop = window.matchMedia?.("(min-width: 1024px)").matches
|
||||
?? window.innerWidth >= 1024;
|
||||
const hasUsableContainer = container.clientWidth >= ACTIVITY_PANEL_MIN_WIDTH + ACTIVITY_CENTRAL_MIN_WIDTH;
|
||||
const nextDesktopSplit = viewportIsDesktop && hasUsableContainer;
|
||||
setDesktopSplit(nextDesktopSplit);
|
||||
if (!nextDesktopSplit) {
|
||||
cancelDrag();
|
||||
const savedWidth = loadActivityPanelWidth(storageRef.current);
|
||||
widthRef.current = savedWidth;
|
||||
setPanelWidth(savedWidth);
|
||||
return;
|
||||
}
|
||||
const nextBounds = getActivityPanelBounds(container.clientWidth);
|
||||
boundsRef.current = nextBounds;
|
||||
setBounds(nextBounds);
|
||||
applyWidth(widthRef.current, true);
|
||||
};
|
||||
syncBounds();
|
||||
const observer = typeof ResizeObserver === "undefined" ? null : new ResizeObserver(syncBounds);
|
||||
syncLayout();
|
||||
const observer = typeof ResizeObserver === "undefined" ? null : new ResizeObserver(syncLayout);
|
||||
observer?.observe(container);
|
||||
window.addEventListener("resize", syncBounds);
|
||||
const media = window.matchMedia?.("(min-width: 1024px)");
|
||||
media?.addEventListener?.("change", syncLayout);
|
||||
window.addEventListener("resize", syncLayout);
|
||||
return () => {
|
||||
observer?.disconnect();
|
||||
window.removeEventListener("resize", syncBounds);
|
||||
media?.removeEventListener?.("change", syncLayout);
|
||||
window.removeEventListener("resize", syncLayout);
|
||||
};
|
||||
}, [applyWidth]);
|
||||
|
||||
@@ -138,6 +167,7 @@ export function useActivityPanelResize(): {
|
||||
pointerId: event.pointerId,
|
||||
startX: event.clientX,
|
||||
startWidth: widthRef.current,
|
||||
target: event.currentTarget,
|
||||
};
|
||||
event.currentTarget.setPointerCapture?.(event.pointerId);
|
||||
setResizing(true);
|
||||
@@ -174,6 +204,7 @@ export function useActivityPanelResize(): {
|
||||
return {
|
||||
containerRef,
|
||||
panelWidth,
|
||||
desktopSplit,
|
||||
resizing,
|
||||
separatorProps: {
|
||||
role: "separator",
|
||||
|
||||
Reference in New Issue
Block a user