Skip to content

Commit 130874d

Browse files
committed
feat: add message navigator for improved conversation navigation
- Add MessageNavigator component with search and filter functionality - Support filtering by message type (user, assistant, file edits, commands, errors, etc.) - Add keyboard shortcuts (Ctrl/Cmd+F to open, arrow keys to navigate, Enter to select, Esc to close) - Integrate with ChatView and TaskHeader - Add search button to TaskHeader for easy access - Add localization strings for the new feature Addresses #7721
1 parent e8deedd commit 130874d

File tree

4 files changed

+554
-2
lines changed

4 files changed

+554
-2
lines changed

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

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ import SystemPromptWarning from "./SystemPromptWarning"
5656
import ProfileViolationWarning from "./ProfileViolationWarning"
5757
import { CheckpointWarning } from "./CheckpointWarning"
5858
import { QueuedMessages } from "./QueuedMessages"
59+
import { MessageNavigator } from "./MessageNavigator"
5960

6061
export interface ChatViewProps {
6162
isHidden: boolean
@@ -193,6 +194,7 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
193194
const [showCheckpointWarning, setShowCheckpointWarning] = useState<boolean>(false)
194195
const [isCondensing, setIsCondensing] = useState<boolean>(false)
195196
const [showAnnouncementModal, setShowAnnouncementModal] = useState(false)
197+
const [showMessageNavigator, setShowMessageNavigator] = useState(false)
196198
const everVisibleMessagesTsRef = useRef<LRUCache<number, boolean>>(
197199
new LRUCache({
198200
max: 100,
@@ -1728,8 +1730,13 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
17281730
switchToNextMode()
17291731
}
17301732
}
1733+
// Check for Cmd/Ctrl + F to open message navigator
1734+
if ((event.metaKey || event.ctrlKey) && event.key === "f" && task) {
1735+
event.preventDefault()
1736+
setShowMessageNavigator(true)
1737+
}
17311738
},
1732-
[switchToNextMode, switchToPreviousMode],
1739+
[switchToNextMode, switchToPreviousMode, task],
17331740
)
17341741

17351742
useEffect(() => {
@@ -1759,6 +1766,40 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
17591766
vscode.postMessage({ type: "condenseTaskContextRequest", text: taskId })
17601767
}
17611768

1769+
// Handle navigation to a specific message
1770+
const handleNavigateToMessage = useCallback(
1771+
(messageIndex: number) => {
1772+
// Find the message in visibleMessages
1773+
const targetMessage = visibleMessages[messageIndex]
1774+
if (targetMessage && virtuosoRef.current) {
1775+
// Find the index in groupedMessages
1776+
const groupIndex = groupedMessages.findIndex((item) => {
1777+
if (Array.isArray(item)) {
1778+
return item.some((msg) => msg.ts === targetMessage.ts)
1779+
}
1780+
return item.ts === targetMessage.ts
1781+
})
1782+
1783+
if (groupIndex !== -1) {
1784+
// Scroll to the message
1785+
virtuosoRef.current.scrollToIndex({
1786+
index: groupIndex,
1787+
behavior: "smooth",
1788+
align: "center",
1789+
})
1790+
1791+
// Optionally expand the message if it's collapsible
1792+
if (!Array.isArray(groupedMessages[groupIndex])) {
1793+
const message = groupedMessages[groupIndex] as ClineMessage
1794+
setExpandedRows((prev) => ({ ...prev, [message.ts]: true }))
1795+
}
1796+
}
1797+
}
1798+
setShowMessageNavigator(false)
1799+
},
1800+
[visibleMessages, groupedMessages],
1801+
)
1802+
17621803
const areButtonsVisible = showScrollToBottom || primaryButtonText || secondaryButtonText || isStreaming
17631804

17641805
return (
@@ -1790,6 +1831,7 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
17901831
buttonsDisabled={sendingDisabled}
17911832
handleCondenseContext={handleCondenseContext}
17921833
todos={latestTodos}
1834+
onOpenNavigator={() => setShowMessageNavigator(true)}
17931835
/>
17941836

17951837
{hasSystemPromptOverride && (
@@ -2013,6 +2055,14 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
20132055
)}
20142056

20152057
<div id="roo-portal" />
2058+
2059+
{/* Message Navigator Overlay */}
2060+
<MessageNavigator
2061+
messages={visibleMessages}
2062+
onNavigateToMessage={handleNavigateToMessage}
2063+
isVisible={showMessageNavigator}
2064+
onClose={() => setShowMessageNavigator(false)}
2065+
/>
20162066
</div>
20172067
)
20182068
}

0 commit comments

Comments
 (0)