diff --git a/apps/web/src/components/DiffPanel.tsx b/apps/web/src/components/DiffPanel.tsx
index face19f291c743484177b4fd83a34e942aaf7788..6510cea7ee3ca999660b8447c360dde862b7f352 100644
--- a/apps/web/src/components/DiffPanel.tsx
+++ b/apps/web/src/components/DiffPanel.tsx
@@ -3,12 +3,11 @@ import {
FileDiff,
type FileDiffMetadata,
Virtualizer,
- WorkerPoolContextProvider,
} from "@pierre/diffs/react";
import { useQuery } from "@tanstack/react-query";
import { useNavigate, useParams, useSearch } from "@tanstack/react-router";
import { Columns2Icon, Rows3Icon } from "lucide-react";
-import { type ReactNode, useEffect, useMemo, useRef, useState } from "react";
+import { useEffect, useMemo, useRef, useState } from "react";
import { checkpointDiffQueryOptions } from "~/lib/providerReactQuery";
import { cn } from "~/lib/utils";
import { parseDiffRouteSearch } from "../diffRouteSearch";
@@ -77,28 +76,7 @@ interface DiffPanelProps {
mode?: "inline" | "sheet";
}
-export function DiffWorkerPoolProvider({ children }: { children?: ReactNode }) {
- const workerPoolSize = useMemo(() => {
- const cores = typeof navigator === "undefined" ? 4 : Math.max(1, navigator.hardwareConcurrency || 4);
- return Math.max(2, Math.min(6, Math.floor(cores / 2)));
- }, []);
-
- return (
-
- new Worker(new URL("../workers/diffs.worker.ts", import.meta.url), { type: "module" }),
- poolSize: workerPoolSize,
- totalASTLRUCacheSize: 240,
- }}
- highlighterOptions={{
- tokenizeMaxLineLength: 1_000,
- }}
- >
- {children}
-
- );
-}
+export { DiffWorkerPoolProvider } from "./DiffWorkerPoolProvider";
export default function DiffPanel({ mode = "inline" }: DiffPanelProps) {
const api = useNativeApi();
diff --git a/apps/web/src/components/DiffWorkerPoolProvider.tsx b/apps/web/src/components/DiffWorkerPoolProvider.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..53939cf81cfefa1371776945a059c4e6df247ba8
--- /dev/null
+++ b/apps/web/src/components/DiffWorkerPoolProvider.tsx
@@ -0,0 +1,26 @@
+import { WorkerPoolContextProvider } from "@pierre/diffs/react";
+import { useMemo, type ReactNode } from "react";
+
+export function DiffWorkerPoolProvider({ children }: { children?: ReactNode }) {
+ const workerPoolSize = useMemo(() => {
+ const cores = typeof navigator === "undefined" ? 4 : Math.max(1, navigator.hardwareConcurrency || 4);
+ return Math.max(2, Math.min(6, Math.floor(cores / 2)));
+ }, []);
+
+ return (
+
+ new Worker(new URL("../workers/diffs.worker.ts", import.meta.url), { type: "module" }),
+ poolSize: workerPoolSize,
+ totalASTLRUCacheSize: 240,
+ }}
+ highlighterOptions={{
+ tokenizeMaxLineLength: 1_000,
+ }}
+ >
+ {children}
+
+ );
+}
+
diff --git a/apps/web/src/routes/_chat.$threadId.tsx b/apps/web/src/routes/_chat.$threadId.tsx
index 8cca8c2e69d0dde8c85474d0589215cf00883b80..ecf1e2bd53bf39931d872c404a5440387d4a2c38 100644
--- a/apps/web/src/routes/_chat.$threadId.tsx
+++ b/apps/web/src/routes/_chat.$threadId.tsx
@@ -1,15 +1,73 @@
import { createFileRoute, useNavigate } from "@tanstack/react-router";
-import { useEffect } from "react";
+import { Activity, Suspense, lazy, type ReactNode, useCallback, useEffect } from "react";
import ChatView from "../components/ChatView";
import { parseDiffRouteSearch } from "../diffRouteSearch";
+import { useMediaQuery } from "../hooks/useMediaQuery";
import { useStore } from "../store";
+import { Sheet, SheetPopup } from "../components/ui/sheet";
+
+const DiffPanel = lazy(() => import("../components/DiffPanel"));
+const DIFF_INLINE_LAYOUT_MEDIA_QUERY = "(max-width: 1180px)";
+
+const DiffPanelWrapper = (props: {
+ children: ReactNode;
+ sheet: boolean;
+ diffOpen: boolean;
+ onCloseDiff: () => void;
+}) => {
+ if (props.sheet) {
+ return (
+ {
+ if (!open) {
+ props.onCloseDiff();
+ }
+ }}
+ >
+
+ {props.children}
+
+
+ );
+ }
+
+ return (
+
+ );
+};
function ChatThreadRouteView() {
const { state } = useStore();
const navigate = useNavigate();
const { threadId } = Route.useParams();
+ const search = Route.useSearch();
const threadExists = threadId ? state.threads.some((thread) => thread.id === threadId) : false;
+ const diffOpen = search.diff === "1";
+ const shouldUseDiffSheet = useMediaQuery(DIFF_INLINE_LAYOUT_MEDIA_QUERY);
+ const closeDiff = useCallback(() => {
+ void navigate({
+ to: "/$threadId",
+ params: { threadId },
+ search: (previous) => {
+ const {
+ diff: _diff,
+ diffTurnId: _diffTurnId,
+ diffFilePath: _diffFilePath,
+ ...rest
+ } = previous;
+ return rest;
+ },
+ });
+ }, [navigate, threadId]);
useEffect(() => {
if (!threadId) {
@@ -31,10 +89,33 @@ function ChatThreadRouteView() {
return null;
}
- return ;
+ const diffLoadingFallback =
+ !diffOpen || shouldUseDiffSheet ? (
+
+ Loading diff viewer...
+
+ ) : (
+
+ );
+
+ return (
+ <>
+
+
+
+
+
+
+
+
+ >
+ );
}
export const Route = createFileRoute("/_chat/$threadId")({
validateSearch: (search) => parseDiffRouteSearch(search),
component: ChatThreadRouteView,
});
+
diff --git a/apps/web/src/routes/_chat.tsx b/apps/web/src/routes/_chat.tsx
index d225a4e33f353b6fb10d756f4788a35a06301a6d..6f766e44f1db3a5f4d90a09e7f61586c89ebf339 100644
--- a/apps/web/src/routes/_chat.tsx
+++ b/apps/web/src/routes/_chat.tsx
@@ -1,112 +1,15 @@
-import {
- Outlet,
- createFileRoute,
- useNavigate,
- useParams,
- useSearch,
-} from "@tanstack/react-router";
-import { Activity, Suspense, lazy, type ReactNode, useCallback, useMemo } from "react";
+import { Outlet, createFileRoute } from "@tanstack/react-router";
+import { DiffWorkerPoolProvider } from "../components/DiffWorkerPoolProvider";
import Sidebar from "../components/Sidebar";
-import { parseDiffRouteSearch } from "../diffRouteSearch";
-import { useMediaQuery } from "../hooks/useMediaQuery";
-import { Sheet, SheetPopup } from "../components/ui/sheet";
-
-const DiffPanel = lazy(() => import("../components/DiffPanel"));
-const DiffWorkerPoolProvider = lazy(() =>
- import("../components/DiffPanel").then((module) => ({
- default: module.DiffWorkerPoolProvider,
- })),
-);
-const DIFF_INLINE_LAYOUT_MEDIA_QUERY = "(max-width: 1180px)";
-
-const DiffPanelWrapper = (props: {
- children: ReactNode;
- sheet: boolean;
- diffOpen: boolean;
- onCloseDiff: () => void;
-}) => {
- if (props.sheet) {
- return (
- {
- if (!open) {
- props.onCloseDiff();
- }
- }}
- >
-
- {props.children}
-
-
- );
- }
-
- return (
-
- );
-};
function ChatRouteLayout() {
- const navigate = useNavigate();
- const params = useParams({ strict: false });
- const routeThreadId = typeof params.threadId === "string" ? params.threadId : null;
- const rawSearch = useSearch({ strict: false });
- const diffSearch = useMemo(
- () => parseDiffRouteSearch(rawSearch as Record),
- [rawSearch],
- );
- const diffOpen = routeThreadId !== null && diffSearch.diff === "1";
- const shouldUseDiffSheet = useMediaQuery(DIFF_INLINE_LAYOUT_MEDIA_QUERY);
- const closeDiff = useCallback(() => {
- if (!routeThreadId) return;
- void navigate({
- to: "/$threadId",
- params: { threadId: routeThreadId },
- search: (previous) => {
- const {
- diff: _diff,
- diffTurnId: _diffTurnId,
- diffFilePath: _diffFilePath,
- ...rest
- } = previous;
- return rest;
- },
- });
- }, [navigate, routeThreadId]);
-
- const diffLoadingFallback =
- !diffOpen || shouldUseDiffSheet ? (
-
- Loading diff viewer...
-
- ) : (
-
- );
-
return (
-
-
-
-
-
-
-
-
-
-
+
+
+
);
}
@@ -114,3 +17,4 @@ function ChatRouteLayout() {
export const Route = createFileRoute("/_chat")({
component: ChatRouteLayout,
});
+