f3961cc72a
- Upgrade package manager to pnpm@11.5.2 and remove patched dependencies from package.json. - Update pnpm-lock.yaml to reflect new dependency versions and remove obsolete entries. - Refactor Vite configuration to improve legacy build handling, including new plugins for legacy CSS management. - Remove unused client/index.html file and adjust paths in Vite config for better project structure. - Enhance DesktopAIShell and EQPage components to support legacy build conditions and improve loading states for raw curves.
135 lines
3.7 KiB
TypeScript
135 lines
3.7 KiB
TypeScript
import PageSuspense from "@/components/PageSuspense";
|
|
import { useAIDrawer } from "@/contexts/AIDrawerContext";
|
|
import { useIsLgUp } from "@/hooks/useIsLgUp";
|
|
import { cn } from "@/lib/utils";
|
|
import { useLocation } from "wouter";
|
|
import {
|
|
useCallback,
|
|
useEffect,
|
|
useRef,
|
|
lazy,
|
|
type ReactNode,
|
|
type RefObject,
|
|
} from "react";
|
|
|
|
const AIPage = lazy(() => import("@/pages/AIPage"));
|
|
|
|
function SplitDivider({
|
|
containerRef,
|
|
onResize,
|
|
}: {
|
|
containerRef: RefObject<HTMLDivElement | null>;
|
|
onResize: (aiPercent: number) => void;
|
|
}) {
|
|
const dragging = useRef(false);
|
|
|
|
const onMove = useCallback(
|
|
(e: MouseEvent) => {
|
|
if (!dragging.current || !containerRef.current) return;
|
|
const r = containerRef.current.getBoundingClientRect();
|
|
const w = r.width;
|
|
if (w <= 0) return;
|
|
const aiPct = ((r.right - e.clientX) / w) * 100;
|
|
onResize(aiPct);
|
|
},
|
|
[containerRef, onResize],
|
|
);
|
|
|
|
useEffect(() => {
|
|
const onUp = () => {
|
|
dragging.current = false;
|
|
};
|
|
window.addEventListener("mouseup", onUp);
|
|
window.addEventListener("mousemove", onMove);
|
|
return () => {
|
|
window.removeEventListener("mouseup", onUp);
|
|
window.removeEventListener("mousemove", onMove);
|
|
};
|
|
}, [onMove]);
|
|
|
|
return (
|
|
<div
|
|
className={cn(
|
|
"group relative z-10 w-2 shrink-0 cursor-col-resize bg-transparent",
|
|
"hover:bg-[#00FFF6]/10",
|
|
)}
|
|
onMouseDown={() => {
|
|
dragging.current = true;
|
|
}}
|
|
role="separator"
|
|
aria-orientation="vertical"
|
|
aria-label="Resize panels"
|
|
>
|
|
<div className="absolute inset-y-0 left-1/2 w-px -translate-x-1/2 bg-white/15 transition-colors group-hover:bg-[#00FFF6]/45" />
|
|
</div>
|
|
);
|
|
}
|
|
|
|
const isLegacyBuild = import.meta.env.VITE_X8_LEGACY === "1";
|
|
|
|
/**
|
|
* lg+: optional side-by-side AI panel with draggable divider. Mobile unchanged (router only).
|
|
*/
|
|
export default function DesktopAIShell({ children }: { children: ReactNode }) {
|
|
const isLgUp = useIsLgUp();
|
|
const [location] = useLocation();
|
|
const { open, setOpen, splitPercent, setSplitPercent } = useAIDrawer();
|
|
const containerRef = useRef<HTMLDivElement>(null);
|
|
|
|
const showSplit = Boolean(isLgUp && open && location !== "/ai");
|
|
|
|
useEffect(() => {
|
|
if (location === "/ai" && isLgUp) setOpen(false);
|
|
}, [location, isLgUp, setOpen]);
|
|
|
|
return (
|
|
<div
|
|
ref={containerRef}
|
|
className={cn(
|
|
"w-full min-w-0",
|
|
showSplit
|
|
? "flex h-dvh max-h-dvh flex-row overflow-hidden"
|
|
: isLegacyBuild
|
|
? "min-h-0"
|
|
: "min-h-dvh",
|
|
)}
|
|
>
|
|
<div
|
|
className={cn(
|
|
"min-w-0",
|
|
showSplit
|
|
? "h-full min-h-0 overflow-y-auto overflow-x-hidden"
|
|
: isLgUp
|
|
? "min-h-dvh overflow-x-hidden"
|
|
: isLegacyBuild
|
|
? "w-full overflow-x-hidden"
|
|
: "min-h-dvh max-h-dvh overflow-x-hidden overflow-y-auto overscroll-y-contain [touch-action:pan-y]",
|
|
)}
|
|
style={
|
|
showSplit
|
|
? { flex: `${100 - splitPercent} 1 0%`, minWidth: 0 }
|
|
: { width: "100%" }
|
|
}
|
|
>
|
|
{children}
|
|
</div>
|
|
{showSplit && (
|
|
<>
|
|
<SplitDivider
|
|
containerRef={containerRef}
|
|
onResize={(aiPct) => setSplitPercent(aiPct)}
|
|
/>
|
|
<div
|
|
className="flex h-full min-h-0 min-w-0 flex-col overflow-hidden border-l border-white/[0.08] bg-[#0d1117]"
|
|
style={{ flex: `${splitPercent} 1 0%` }}
|
|
>
|
|
<PageSuspense>
|
|
<AIPage variant="split" onClose={() => setOpen(false)} />
|
|
</PageSuspense>
|
|
</div>
|
|
</>
|
|
)}
|
|
</div>
|
|
);
|
|
}
|