authorgravatar for cursoragent@cursor.comCursor Agent <cursoragent@cursor.com> 2026-02-19 23:36:12+00:00
committergravatar for cursoragent@cursor.comCursor Agent <cursoragent@cursor.com> 2026-02-19 23:36:12+00:00
log842e327583f214714abbde82e7e19a6341c3d140
tree805948e35c0526b64bcc6068be77496e1be52b30
parent891eb02d49d4b511cc1b52ed4d675476484f2aa9

Extract stripDiffSearchParams helper to deduplicate diff param stripping logic

Consolidate the repeated pattern of destructuring and removing diff/diffTurnId/diffFilePath search params into a single stripDiffSearchParams() function in diffRouteSearch.ts. Replaces 5 identical destructuring blocks across 3 files with calls to the shared helper. Applied via @cursor push command

4 files changed, 35 insertions(+), 48 deletions(-)

apps/web/src/components/ChatView.tsx+21-19
......@@ -36,7 +36,7 @@ import { projectSearchEntriesQueryOptions } from "~/lib/projectReactQuery";
3636import { serverConfigQueryOptions, serverQueryKeys } from "~/lib/serverReactQuery";
3737
3838import { isElectron } from "../env";
39import { parseDiffRouteSearch } from "../diffRouteSearch";
39import { parseDiffRouteSearch, stripDiffSearchParams } from "../diffRouteSearch";
4040import { buildBootstrapInput } from "../historyBootstrap";
4141import {
4242 type ComposerTriggerKind,
......@@ -1967,12 +1967,7 @@ export default function ChatView({ threadId }: ChatViewProps) {
19671967 to: "/$threadId",
19681968 params: { threadId },
19691969 search: (previous) => {
1970 const {
1971 diff: _diff,
1972 diffTurnId: _diffTurnId,
1973 diffFilePath: _diffFilePath,
1974 ...rest
1975 } = previous;
1970 const rest = stripDiffSearchParams(previous);
19761971 return diffOpen ? rest : { ...rest, diff: "1" };
19771972 },
19781973 });
......@@ -1983,12 +1978,7 @@ export default function ChatView({ threadId }: ChatViewProps) {
19831978 to: "/$threadId",
19841979 params: { threadId },
19851980 search: (previous) => {
1986 const {
1987 diff: _diff,
1988 diffTurnId: _diffTurnId,
1989 diffFilePath: _diffFilePath,
1990 ...rest
1991 } = previous;
1981 const rest = stripDiffSearchParams(previous);
19921982 return filePath
19931983 ? { ...rest, diff: "1", diffTurnId: turnId, diffFilePath: filePath }
19941984 : { ...rest, diff: "1", diffTurnId: turnId };
......@@ -2828,11 +2818,16 @@ const MessagesTimeline = memo(function MessagesTimeline({
28282818 row.message.id,
28292819 );
28302820 if (!turnSummary) return null;
2831 const checkpointFilesState = turnCheckpointFilesByTurnId.get(turnSummary.turnId);
2821 const checkpointFilesState = turnCheckpointFilesByTurnId.get(
2822 turnSummary.turnId,
2823 );
28322824 const checkpointFiles = checkpointFilesState?.files ?? [];
28332825 const summaryStat = checkpointFiles.reduce(
28342826 (acc, file) => {
2835 if (typeof file.additions !== "number" || typeof file.deletions !== "number") {
2827 if (
2828 typeof file.additions !== "number" ||
2829 typeof file.deletions !== "number"
2830 ) {
28362831 return acc;
28372832 }
28382833 return {
......@@ -2843,7 +2838,9 @@ const MessagesTimeline = memo(function MessagesTimeline({
28432838 { additions: 0, deletions: 0 },
28442839 );
28452840 const changedFileCountLabel =
2846 checkpointFilesState?.status === "ready" ? String(checkpointFiles.length) : "...";
2841 checkpointFilesState?.status === "ready"
2842 ? String(checkpointFiles.length)
2843 : "...";
28472844 return (
28482845 <div className="mt-2 rounded-lg border border-border/80 bg-card/45 p-2.5">
28492846 <div className="mb-1.5 flex items-center justify-between gap-2">
......@@ -2854,7 +2851,9 @@ const MessagesTimeline = memo(function MessagesTimeline({
28542851 <span className="mx-1">•</span>
28552852 <span className="text-success">+{summaryStat.additions}</span>
28562853 <span className="mx-0.5 text-muted-foreground/70">/</span>
2857 <span className="text-destructive">-{summaryStat.deletions}</span>
2854 <span className="text-destructive">
2855 -{summaryStat.deletions}
2856 </span>
28582857 </>
28592858 )}
28602859 </p>
......@@ -2862,12 +2861,15 @@ const MessagesTimeline = memo(function MessagesTimeline({
28622861 type="button"
28632862 size="xs"
28642863 variant="outline"
2865 onClick={() => onOpenTurnDiff(turnSummary.turnId, checkpointFiles[0]?.path)}
2864 onClick={() =>
2865 onOpenTurnDiff(turnSummary.turnId, checkpointFiles[0]?.path)
2866 }
28662867 >
28672868 View diff
28682869 </Button>
28692870 </div>
2870 {!checkpointFilesState || checkpointFilesState.status === "pending" ? (
2871 {!checkpointFilesState ||
2872 checkpointFilesState.status === "pending" ? (
28712873 <p className="text-[11px] text-muted-foreground/70">
28722874 Waiting for checkpoint metadata...
28732875 </p>
apps/web/src/components/DiffPanel.tsx+5-19
......@@ -1,16 +1,12 @@
11import { parsePatchFiles } from "@pierre/diffs";
2import {
3 FileDiff,
4 type FileDiffMetadata,
5 Virtualizer,
6} from "@pierre/diffs/react";
2import { FileDiff, type FileDiffMetadata, Virtualizer } from "@pierre/diffs/react";
73import { useQuery } from "@tanstack/react-query";
84import { useNavigate, useParams, useSearch } from "@tanstack/react-router";
95import { Columns2Icon, Rows3Icon } from "lucide-react";
106import { useEffect, useMemo, useRef, useState } from "react";
117import { checkpointDiffQueryOptions } from "~/lib/providerReactQuery";
128import { cn } from "~/lib/utils";
13import { parseDiffRouteSearch } from "../diffRouteSearch";
9import { parseDiffRouteSearch, stripDiffSearchParams } from "../diffRouteSearch";
1410import { isElectron } from "../env";
1511import { useNativeApi } from "../hooks/useNativeApi";
1612import { useTheme } from "../hooks/useTheme";
......@@ -101,7 +97,7 @@ export default function DiffPanel({ mode = "inline" }: DiffPanelProps) {
10197 useTurnDiffSummaries(activeThread);
10298
10399 const selectedTurnId = diffSearch.diffTurnId ?? null;
104 const selectedFilePath = selectedTurnId !== null ? diffSearch.diffFilePath ?? null : null;
100 const selectedFilePath = selectedTurnId !== null ? (diffSearch.diffFilePath ?? null) : null;
105101 const selectedTurn =
106102 selectedTurnId === null
107103 ? undefined
......@@ -205,12 +201,7 @@ export default function DiffPanel({ mode = "inline" }: DiffPanelProps) {
205201 to: "/$threadId",
206202 params: { threadId: activeThread.id },
207203 search: (previous) => {
208 const {
209 diff: _diff,
210 diffTurnId: _diffTurnId,
211 diffFilePath: _diffFilePath,
212 ...rest
213 } = previous;
204 const rest = stripDiffSearchParams(previous);
214205 return { ...rest, diff: "1", diffTurnId: turnId };
215206 },
216207 });
......@@ -221,12 +212,7 @@ export default function DiffPanel({ mode = "inline" }: DiffPanelProps) {
221212 to: "/$threadId",
222213 params: { threadId: activeThread.id },
223214 search: (previous) => {
224 const {
225 diff: _diff,
226 diffTurnId: _diffTurnId,
227 diffFilePath: _diffFilePath,
228 ...rest
229 } = previous;
215 const rest = stripDiffSearchParams(previous);
230216 return { ...rest, diff: "1" };
231217 },
232218 });
apps/web/src/diffRouteSearch.ts+7-1
......@@ -12,6 +12,13 @@ function normalizeSearchString(value: unknown): string | undefined {
1212 return normalized.length > 0 ? normalized : undefined;
1313}
1414
15export function stripDiffSearchParams<T extends Record<string, unknown>>(
16 params: T,
17): Omit<T, "diff" | "diffTurnId" | "diffFilePath"> {
18 const { diff: _diff, diffTurnId: _diffTurnId, diffFilePath: _diffFilePath, ...rest } = params;
19 return rest as Omit<T, "diff" | "diffTurnId" | "diffFilePath">;
20}
21
1522export function parseDiffRouteSearch(search: Record<string, unknown>): DiffRouteSearch {
1623 const diff = search.diff === "1" ? "1" : undefined;
1724 const diffTurnId = diff ? normalizeSearchString(search.diffTurnId) : undefined;
......@@ -23,4 +30,3 @@ export function parseDiffRouteSearch(search: Record<string, unknown>): DiffRoute
2330 ...(diffFilePath ? { diffFilePath } : {}),
2431 };
2532}
26
apps/web/src/routes/_chat.$threadId.tsx+2-9
......@@ -2,7 +2,7 @@ import { createFileRoute, useNavigate } from "@tanstack/react-router";
22import { Activity, Suspense, lazy, type ReactNode, useCallback, useEffect } from "react";
33
44import ChatView from "../components/ChatView";
5import { parseDiffRouteSearch } from "../diffRouteSearch";
5import { parseDiffRouteSearch, stripDiffSearchParams } from "../diffRouteSearch";
66import { useMediaQuery } from "../hooks/useMediaQuery";
77import { useStore } from "../store";
88import { Sheet, SheetPopup } from "../components/ui/sheet";
......@@ -58,13 +58,7 @@ function ChatThreadRouteView() {
5858 to: "/$threadId",
5959 params: { threadId },
6060 search: (previous) => {
61 const {
62 diff: _diff,
63 diffTurnId: _diffTurnId,
64 diffFilePath: _diffFilePath,
65 ...rest
66 } = previous;
67 return rest;
61 return stripDiffSearchParams(previous);
6862 },
6963 });
7064 }, [navigate, threadId]);
......@@ -118,4 +112,3 @@ export const Route = createFileRoute("/_chat/$threadId")({
118112 validateSearch: (search) => parseDiffRouteSearch(search),
119113 component: ChatThreadRouteView,
120114});
121