diff --git a/apps/web/src/components/ChatView.tsx b/apps/web/src/components/ChatView.tsx index 185fa7c2ee..48f79da415 100644 --- a/apps/web/src/components/ChatView.tsx +++ b/apps/web/src/components/ChatView.tsx @@ -647,6 +647,8 @@ export default function ChatView({ threadId }: ChatViewProps) { (store) => store.draftThreadsByThreadId[threadId] ?? null, ); const promptRef = useRef(prompt); + const historyIndexRef = useRef(-1); // -1 = live draft + const savedDraftRef = useRef(''); const [showScrollToBottom, setShowScrollToBottom] = useState(false); const [isDragOverComposer, setIsDragOverComposer] = useState(false); const [expandedImage, setExpandedImage] = useState(null); @@ -2389,6 +2391,8 @@ export default function ChatView({ threadId }: ChatViewProps) { setComposerCursor(collapseExpandedComposerCursor(promptRef.current, promptRef.current.length)); setComposerTrigger(detectComposerTrigger(promptRef.current, promptRef.current.length)); dragDepthRef.current = 0; + historyIndexRef.current = -1; + savedDraftRef.current = ''; setIsDragOverComposer(false); setExpandedImage(null); }, [resetLocalDispatch, threadId]); @@ -2871,6 +2875,8 @@ export default function ChatView({ threadId }: ChatViewProps) { planMarkdown: activeProposedPlan.planMarkdown, }); promptRef.current = ""; + historyIndexRef.current = -1; + savedDraftRef.current = ''; clearComposerDraftContent(activeThread.id); setComposerHighlightedItemId(null); setComposerCursor(0); @@ -2888,6 +2894,8 @@ export default function ChatView({ threadId }: ChatViewProps) { if (standaloneSlashCommand) { handleInteractionModeChange(standaloneSlashCommand); promptRef.current = ""; + historyIndexRef.current = -1; + savedDraftRef.current = ''; clearComposerDraftContent(activeThread.id); setComposerHighlightedItemId(null); setComposerCursor(0); @@ -2991,6 +2999,8 @@ export default function ChatView({ threadId }: ChatViewProps) { }); } promptRef.current = ""; + historyIndexRef.current = -1; + savedDraftRef.current = ''; clearComposerDraftContent(threadIdForSend); setComposerHighlightedItemId(null); setComposerCursor(0); @@ -3853,6 +3863,19 @@ export default function ChatView({ threadId }: ChatViewProps) { } } + if (key === "ArrowUp" || (key === "ArrowDown" && historyIndexRef.current !== -1)) { + const userMsgs = activeThread?.messages.filter((m) => m.role === 'user') ?? []; + const nextIndex = historyIndexRef.current + (key === "ArrowUp" ? 1 : -1); + if (key === "ArrowUp" && nextIndex >= userMsgs.length) return false; + if (historyIndexRef.current === -1) savedDraftRef.current = promptRef.current; + historyIndexRef.current = nextIndex; + const next = nextIndex === -1 ? savedDraftRef.current : (userMsgs[userMsgs.length - 1 - nextIndex]?.text ?? ''); + setPrompt(next); + setComposerCursor(next.length); + setComposerTrigger(detectComposerTrigger(next, next.length)); + return true; + } + if (key === "Enter" && !event.shiftKey) { void onSend(); return true;