Skip to content

Commit bd975f3

Browse files
committed
fix: preserve original input when navigating history after typing
- Modified resetOnInputChange to not clear tempInput when user types - Updated handleHistoryNavigation to allow navigating back to history even after typing - Added test case to verify the new behavior prevents input loss - Fixed linting warning about missing dependency in useCallback Fixes #6249
1 parent 6216075 commit bd975f3

File tree

2 files changed

+56
-10
lines changed

2 files changed

+56
-10
lines changed

webview-ui/src/components/chat/__tests__/ChatTextArea.spec.tsx

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -602,6 +602,39 @@ describe("ChatTextArea", () => {
602602
expect(setInputValue).toHaveBeenCalledWith("New input")
603603
})
604604

605+
it("should allow navigating back to original input after typing in history mode", () => {
606+
const setInputValue = vi.fn()
607+
const { container } = render(
608+
<ChatTextArea {...defaultProps} setInputValue={setInputValue} inputValue="My original input" />,
609+
)
610+
611+
const textarea = container.querySelector("textarea")!
612+
// Ensure cursor is at the beginning
613+
textarea.setSelectionRange(0, 0)
614+
615+
// Navigate to history (saves "My original input" as tempInput)
616+
fireEvent.keyDown(textarea, { key: "ArrowUp" })
617+
expect(setInputValue).toHaveBeenCalledWith("Third prompt")
618+
setInputValue.mockClear()
619+
620+
// Type something to modify the historical prompt
621+
fireEvent.change(textarea, { target: { value: "Modified third prompt", selectionStart: 21 } })
622+
expect(setInputValue).toHaveBeenCalledWith("Modified third prompt")
623+
setInputValue.mockClear()
624+
625+
// Now press down arrow - should go back to the first history item
626+
textarea.setSelectionRange(0, 0) // Cursor at beginning
627+
fireEvent.keyDown(textarea, { key: "ArrowDown" })
628+
629+
// After typing, pressing down goes back to the first history item
630+
expect(setInputValue).toHaveBeenCalledWith("Third prompt")
631+
setInputValue.mockClear()
632+
633+
// Navigate down to return to original input
634+
fireEvent.keyDown(textarea, { key: "ArrowDown" })
635+
expect(setInputValue).toHaveBeenCalledWith("My original input")
636+
})
637+
605638
it("should reset history navigation when sending message", () => {
606639
const onSend = vi.fn()
607640
const setInputValue = vi.fn()

webview-ui/src/components/chat/hooks/usePromptHistory.ts

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -74,14 +74,16 @@ export const usePromptHistory = ({
7474
setPromptHistory(filteredPromptHistory)
7575
// Reset navigation state when switching between history sources
7676
setHistoryIndex(-1)
77+
// Clear tempInput when history source changes (e.g., switching tasks)
7778
setTempInput("")
7879
}, [filteredPromptHistory])
7980

8081
// Reset history navigation when user types (but not when we're setting it programmatically)
8182
const resetOnInputChange = useCallback(() => {
8283
if (historyIndex !== -1) {
84+
// Don't clear tempInput - preserve it so user can navigate back to their original input
8385
setHistoryIndex(-1)
84-
setTempInput("")
86+
// Keep tempInput as is, don't clear it
8587
}
8688
}, [historyIndex])
8789

@@ -151,27 +153,38 @@ export const usePromptHistory = ({
151153
return navigateToHistory(historyIndex + 1, textarea, "start")
152154
}
153155

154-
// Handle DOWN arrow - only in history navigation mode
155-
if (event.key === "ArrowDown" && historyIndex >= 0 && (isAtBeginning || isAtEnd)) {
156+
// Handle DOWN arrow - allow navigation back even after typing
157+
if (event.key === "ArrowDown" && (isAtBeginning || isAtEnd)) {
156158
event.preventDefault()
157159

158-
if (historyIndex > 0) {
159-
// Keep cursor position consistent with where we started
160-
return navigateToHistory(historyIndex - 1, textarea, isAtBeginning ? "start" : "end")
161-
} else if (historyIndex === 0) {
162-
returnToCurrentInput(textarea, isAtBeginning ? "start" : "end")
163-
return true
160+
// If we're not in history mode but have tempInput, it means user typed after navigating
161+
// Allow them to go back to history
162+
if (historyIndex === -1 && tempInput !== "") {
163+
// User typed something after navigating history, but wants to go back
164+
// Save their current edits
165+
setTempInput(inputValue)
166+
// Go to the first history item
167+
return navigateToHistory(0, textarea, isAtBeginning ? "start" : "end")
168+
} else if (historyIndex >= 0) {
169+
if (historyIndex > 0) {
170+
// Keep cursor position consistent with where we started
171+
return navigateToHistory(historyIndex - 1, textarea, isAtBeginning ? "start" : "end")
172+
} else if (historyIndex === 0) {
173+
returnToCurrentInput(textarea, isAtBeginning ? "start" : "end")
174+
return true
175+
}
164176
}
165177
}
166178
}
167179
}
168180
return false
169181
},
170-
[promptHistory, historyIndex, inputValue, navigateToHistory, returnToCurrentInput],
182+
[promptHistory, historyIndex, inputValue, tempInput, navigateToHistory, returnToCurrentInput],
171183
)
172184

173185
const resetHistoryNavigation = useCallback(() => {
174186
setHistoryIndex(-1)
187+
// Clear tempInput when explicitly resetting (e.g., when sending a message)
175188
setTempInput("")
176189
}, [])
177190

0 commit comments

Comments
 (0)