Skip to content

Commit b750b8c

Browse files
committed
feat(chat): enable jump-to-file in regular chat diff accordions (#997)
1 parent 7af1a8a commit b750b8c

2 files changed

Lines changed: 48 additions & 11 deletions

File tree

webview-ui/src/components/chat/ChatRow.tsx

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -420,12 +420,13 @@ export const ChatRowContent = ({
420420
return (tool.content ?? tool.diff) as string | undefined
421421
}, [tool])
422422

423-
const onJumpToCreatedFile = useMemo(() => {
424-
if (!tool || tool.tool !== "newFileCreated" || !tool.path) {
423+
const onJumpToFile = useMemo(() => {
424+
const path = tool?.path
425+
if (!tool || !path) {
425426
return undefined
426427
}
427428

428-
return () => vscode.postMessage({ type: "openFile", text: "./" + tool.path })
429+
return () => vscode.postMessage({ type: "openFile", text: path.startsWith("./") ? path : "./" + path })
429430
}, [tool])
430431

431432
const followUpData = useMemo(() => {
@@ -497,7 +498,7 @@ export const ChatRowContent = ({
497498
isLoading={message.partial}
498499
isExpanded={isExpanded}
499500
onToggleExpand={handleToggleExpand}
500-
onJumpToFile={onJumpToCreatedFile}
501+
onJumpToFile={onJumpToFile}
501502
diffStats={tool.diffStats}
502503
/>
503504
</div>
@@ -536,6 +537,7 @@ export const ChatRowContent = ({
536537
isLoading={message.partial}
537538
isExpanded={isExpanded}
538539
onToggleExpand={handleToggleExpand}
540+
onJumpToFile={onJumpToFile}
539541
diffStats={tool.diffStats}
540542
/>
541543
</div>

webview-ui/src/components/chat/__tests__/ChatRow.diff-actions.spec.tsx

Lines changed: 42 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -141,30 +141,65 @@ describe("ChatRow - inline diff stats and actions", () => {
141141
expect(screen.getByText("-0")).toBeInTheDocument()
142142
})
143143

144-
it("preserves jump-to-file affordance for newFileCreated", () => {
144+
it.each([
145+
["appliedDiff", "@@ -1,1 +1,1 @@\n-old\n+new\n"],
146+
["editedExistingFile", "@@ -1,1 +1,1 @@\n-old\n+new\n"],
147+
["newFileCreated", "+new file"],
148+
["searchAndReplace", "-a\n-b\n+c\n"],
149+
["search_and_replace", "-a\n-b\n+c\n"],
150+
["search_replace", "-a\n-b\n+c\n"],
151+
["edit", "@@ -1,1 +1,1 @@\n-old\n+new\n"],
152+
["edit_file", "@@ -1,1 +1,1 @@\n-old\n+new\n"],
153+
["apply_patch", "@@ -1,1 +1,1 @@\n-old\n+new\n"],
154+
["apply_diff", "@@ -1,1 +1,1 @@\n-old\n+new\n"],
155+
["insertContent", "@@ -1,1 +1,1 @@\n-old\n+new\n"],
156+
])("shows jump-to-file affordance for %s", (tool, diff) => {
145157
const message = createToolAskMessage({
146-
tool: "newFileCreated",
147-
path: "src/new-file.ts",
148-
content: "+new file",
149-
diffStats: { added: 1, removed: 0 },
158+
tool,
159+
path: "src/file.ts",
160+
diff,
161+
lineNumber: 0,
162+
diffStats: { added: 1, removed: 1 },
150163
})
151164

152165
const { container } = renderChatRow(message)
153166
const openFileIcon = container.querySelector(".codicon-link-external") as HTMLElement | null
154167

155168
expect(openFileIcon).toBeInTheDocument()
156169
if (!openFileIcon) {
157-
throw new Error("Expected external link icon for newFileCreated")
170+
throw new Error(`Expected external link icon for ${tool}`)
158171
}
159172

160173
fireEvent.click(openFileIcon)
161174

162175
expect(mockPostMessage).toHaveBeenCalledWith({
163176
type: "openFile",
164-
text: "./src/new-file.ts",
177+
text: "./src/file.ts",
165178
})
166179
})
167180

181+
it("does not show jump-to-file affordance when path is missing", () => {
182+
const message = createToolAskMessage({
183+
tool: "appliedDiff",
184+
diff: "@@ -1,1 +1,1 @@\n-old\n+new\n",
185+
diffStats: { added: 1, removed: 1 },
186+
})
187+
188+
const { container } = renderChatRow(message)
189+
expect(container.querySelector(".codicon-link-external")).not.toBeInTheDocument()
190+
})
191+
192+
it("does not show jump-to-file affordance for non-file tools", () => {
193+
const message = createToolAskMessage({
194+
tool: "executeCommand",
195+
command: "echo hello",
196+
content: "hello",
197+
})
198+
199+
const { container } = renderChatRow(message)
200+
expect(container.querySelector(".codicon-link-external")).not.toBeInTheDocument()
201+
})
202+
168203
it("preserves protected and outside-workspace messaging in unified branch", () => {
169204
const outsideWorkspaceMessage = createToolAskMessage({
170205
tool: "searchAndReplace",

0 commit comments

Comments
 (0)