@@ -10,7 +10,15 @@ import { appendImages } from "@src/utils/imageUtils"
1010import { getCostBreakdownIfNeeded } from "@src/utils/costFormatting"
1111import { batchConsecutive } from "@src/utils/batchConsecutive"
1212
13- import type { ClineAsk , ClineSayTool , ClineMessage , ExtensionMessage , AudioType } from "@roo-code/types"
13+ import type {
14+ ClineAsk ,
15+ ClineSayTool ,
16+ ClineMessage ,
17+ ExtensionMessage ,
18+ AudioType ,
19+ TodoItem ,
20+ QueuedMessage ,
21+ } from "@roo-code/types"
1422import { isRetiredProvider } from "@roo-code/types"
1523
1624import { findLast } from "@roo/array"
@@ -62,6 +70,12 @@ interface DraftConversation {
6270 title : string
6371}
6472
73+ const EMPTY_MESSAGES : ClineMessage [ ] = [ ]
74+ const EMPTY_TODOS : TodoItem [ ] = [ ]
75+ const EMPTY_MESSAGE_QUEUE : QueuedMessage [ ] = [ ]
76+ const RECENT_CONVERSATIONS_HIDDEN_STORAGE_KEY = "crc.recentConversationsHidden"
77+ const RECENT_CONVERSATIONS_TOGGLE_SHORTCUT = "Ctrl+Shift+H"
78+
6579const ChatViewComponent : React . ForwardRefRenderFunction < ChatViewRef , ChatViewProps > = ( { isHidden } , ref ) => {
6680 const [ audioBaseUri ] = useState ( ( ) => {
6781 return ( window as unknown as { AUDIO_BASE_URI ?: string } ) . AUDIO_BASE_URI || ""
@@ -71,10 +85,10 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
7185 const modeShortcutText = `${ isMac ? "⌘" : "Ctrl" } + . ${ t ( "chat:forNextMode" ) } , ${ isMac ? "⌘" : "Ctrl" } + Shift + . ${ t ( "chat:forPreviousMode" ) } `
7286
7387 const {
74- clineMessages : messages ,
75- currentTaskId,
76- currentTaskItem,
77- currentTaskTodos,
88+ clineMessages : contextMessages ,
89+ currentTaskId : contextCurrentTaskId ,
90+ currentTaskItem : contextCurrentTaskItem ,
91+ currentTaskTodos : contextCurrentTaskTodos ,
7892 activeConversations = [ ] ,
7993 taskHistory,
8094 apiConfiguration,
@@ -85,12 +99,34 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
8599 customModes,
86100 soundEnabled,
87101 soundVolume,
88- messageQueue = [ ] ,
102+ messageQueue : contextMessageQueue = EMPTY_MESSAGE_QUEUE ,
89103 showWorktreesInHomeScreen,
90104 currentAskDecision,
91105 } = useExtensionState ( )
92106 const [ draftConversations , setDraftConversations ] = useState < DraftConversation [ ] > ( [ ] )
93107 const [ selectedDraftId , setSelectedDraftId ] = useState < string | undefined > ( undefined )
108+ const [ areRecentConversationsHidden , setAreRecentConversationsHidden ] = useState ( ( ) => {
109+ try {
110+ return window . localStorage . getItem ( RECENT_CONVERSATIONS_HIDDEN_STORAGE_KEY ) === "true"
111+ } catch {
112+ return false
113+ }
114+ } )
115+ const isDraftSelected = selectedDraftId !== undefined
116+ const messages = useMemo (
117+ ( ) => ( isDraftSelected ? EMPTY_MESSAGES : contextMessages ) ,
118+ [ contextMessages , isDraftSelected ] ,
119+ )
120+ const currentTaskId = isDraftSelected ? undefined : contextCurrentTaskId
121+ const currentTaskItem = isDraftSelected ? undefined : contextCurrentTaskItem
122+ const currentTaskTodos = useMemo (
123+ ( ) => ( isDraftSelected ? EMPTY_TODOS : contextCurrentTaskTodos ) ,
124+ [ contextCurrentTaskTodos , isDraftSelected ] ,
125+ )
126+ const messageQueue = useMemo (
127+ ( ) => ( isDraftSelected ? EMPTY_MESSAGE_QUEUE : contextMessageQueue ) ,
128+ [ contextMessageQueue , isDraftSelected ] ,
129+ )
94130
95131 const visibleConversationIds = useMemo (
96132 ( ) =>
@@ -112,6 +148,17 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
112148 } , [ selectedDraftId , visibleConversationIds ] )
113149
114150 const selectedConversationId = selectedDraftId ?? currentTaskId
151+ const toggleRecentConversationsVisibility = useCallback ( ( ) => {
152+ setAreRecentConversationsHidden ( ( prev ) => {
153+ const next = ! prev
154+ try {
155+ window . localStorage . setItem ( RECENT_CONVERSATIONS_HIDDEN_STORAGE_KEY , String ( next ) )
156+ } catch {
157+ // Ignore storage failures; the in-memory display toggle still works.
158+ }
159+ return next
160+ } )
161+ } , [ ] )
115162
116163 const conversations = useMemo < ConversationListItem [ ] > ( ( ) => {
117164 const draftItems = draftConversations
@@ -785,7 +832,7 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
785832 // Mark that user has responded - this prevents any pending auto-approvals.
786833 userRespondedRef . current = true
787834
788- if ( messagesRef . current . length === 0 ) {
835+ if ( selectedDraftId || messagesRef . current . length === 0 ) {
789836 vscode . postMessage ( { type : "newTask" , taskId : selectedDraftId , text, images } )
790837 } else if ( clineAskRef . current ) {
791838 if ( clineAskRef . current === "followup" ) {
@@ -885,20 +932,41 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
885932 } ,
886933 [ inputValue , selectedImages ] ,
887934 )
888-
889- const startNewTask = useCallback ( ( ) => {
890- const draftId = `draft-${ typeof crypto !== "undefined" && typeof crypto . randomUUID === "function" ? crypto . randomUUID ( ) : Date . now ( ) . toString ( 36 ) } `
935+ const resetDraftSelectionState = useCallback ( ( ) => {
891936 setShowRetiredProviderWarning ( false )
892937 setInputValue ( "" )
893938 setSelectedImages ( [ ] )
939+ setSendingDisabled ( false )
940+ setClineAsk ( undefined )
941+ setEnableButtons ( false )
942+ setPrimaryButtonText ( undefined )
943+ setSecondaryButtonText ( undefined )
944+ setDidClickCancel ( false )
945+ setExpandedRows ( { } )
946+ setCurrentFollowUpTs ( null )
947+ setCheckpointWarning ( undefined )
948+ everVisibleMessagesTsRef . current . clear ( )
949+
950+ if ( autoApproveTimeoutRef . current ) {
951+ clearTimeout ( autoApproveTimeoutRef . current )
952+ autoApproveTimeoutRef . current = null
953+ }
954+
955+ userRespondedRef . current = false
956+ } , [ ] )
957+
958+ const startNewTask = useCallback ( ( ) => {
959+ const draftId = `draft-${ typeof crypto !== "undefined" && typeof crypto . randomUUID === "function" ? crypto . randomUUID ( ) : Date . now ( ) . toString ( 36 ) } `
960+ resetDraftSelectionState ( )
894961 setSelectedDraftId ( draftId )
895962 setDraftConversations ( ( prev ) => [ { id : draftId , ts : Date . now ( ) , title : "New conversation" } , ...prev ] )
896963 vscode . postMessage ( { type : "clearTask" } )
897- } , [ ] )
964+ } , [ resetDraftSelectionState ] )
898965
899966 const handleSelectConversation = useCallback (
900967 ( conversation : ConversationListItem ) => {
901968 if ( conversation . kind === "draft" ) {
969+ resetDraftSelectionState ( )
902970 setSelectedDraftId ( conversation . activeTaskId )
903971 if ( currentTaskId ) {
904972 vscode . postMessage ( { type : "clearTask" } )
@@ -909,7 +977,7 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
909977 setSelectedDraftId ( undefined )
910978 vscode . postMessage ( { type : "showTaskWithId" , text : conversation . activeTaskId } )
911979 } ,
912- [ currentTaskId ] ,
980+ [ currentTaskId , resetDraftSelectionState ] ,
913981 )
914982
915983 const handleDeleteConversation = useCallback ( ( conversation : ConversationListItem ) => {
@@ -983,6 +1051,7 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
9831051 )
9841052 if ( isCompletedSubtaskForClick ) {
9851053 startNewTask ( )
1054+ return
9861055 } else {
9871056 // Only send text/images if they exist
9881057 if ( trimmedInput || ( images && images . length > 0 ) ) {
@@ -1009,7 +1078,7 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
10091078 case "resume_completed_task" :
10101079 // Waiting for feedback, but we can just present a new task button
10111080 startNewTask ( )
1012- break
1081+ return
10131082 case "command_output" :
10141083 vscode . postMessage ( {
10151084 type : "terminalOperation" ,
@@ -1046,7 +1115,7 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
10461115 case "mistake_limit_reached" :
10471116 case "resume_task" :
10481117 startNewTask ( )
1049- break
1118+ return
10501119 case "command" :
10511120 case "tool" :
10521121 case "use_mcp_server" :
@@ -1762,6 +1831,11 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
17621831 // (PageUp, Home, ArrowUp) is handled by useScrollLifecycle.
17631832 const handleKeyDown = useCallback (
17641833 ( event : KeyboardEvent ) => {
1834+ if ( event . ctrlKey && event . shiftKey && ! event . altKey && ! event . metaKey && event . key . toLowerCase ( ) === "h" ) {
1835+ event . preventDefault ( )
1836+ toggleRecentConversationsVisibility ( )
1837+ return
1838+ }
17651839 if ( ( event . metaKey || event . ctrlKey ) && event . key === "." ) {
17661840 event . preventDefault ( )
17671841 if ( event . shiftKey ) {
@@ -1771,7 +1845,7 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
17711845 }
17721846 }
17731847 } ,
1774- [ switchToNextMode , switchToPreviousMode ] ,
1848+ [ switchToNextMode , switchToPreviousMode , toggleRecentConversationsVisibility ] ,
17751849 )
17761850
17771851 useEffect ( ( ) => {
@@ -1877,7 +1951,40 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
18771951 { /* Show RooTips when authenticated or when user is new */ }
18781952 { taskHistory . length < 6 && < RooTips /> }
18791953 { /* Everyone should see their task history if any */ }
1880- { taskHistory . length > 0 && < HistoryPreview /> }
1954+ { taskHistory . length > 0 && (
1955+ < div className = "flex flex-col gap-2" >
1956+ < div className = "flex justify-end" >
1957+ < Button
1958+ variant = "secondary"
1959+ size = "sm"
1960+ className = "h-7 px-2 text-xs"
1961+ onClick = { toggleRecentConversationsVisibility }
1962+ aria-label = {
1963+ areRecentConversationsHidden
1964+ ? `Show recent conversations (${ RECENT_CONVERSATIONS_TOGGLE_SHORTCUT } )`
1965+ : `Hide recent conversations (${ RECENT_CONVERSATIONS_TOGGLE_SHORTCUT } )`
1966+ } >
1967+ { areRecentConversationsHidden
1968+ ? "Show recent conversations"
1969+ : "Hide recent conversations" }
1970+ < span className = "ml-2 text-[10px] opacity-70" >
1971+ { RECENT_CONVERSATIONS_TOGGLE_SHORTCUT }
1972+ </ span >
1973+ </ Button >
1974+ </ div >
1975+ { areRecentConversationsHidden ? (
1976+ < div
1977+ className = "rounded-md border border-vscode-editorGroup-border bg-vscode-editor-background/60 px-3 py-2 text-sm text-vscode-descriptionForeground"
1978+ data-testid = "recent-conversations-hidden" >
1979+ Recent conversations are hidden for privacy. Your history is still
1980+ saved; use the button or { RECENT_CONVERSATIONS_TOGGLE_SHORTCUT } to
1981+ show it again.
1982+ </ div >
1983+ ) : (
1984+ < HistoryPreview />
1985+ ) }
1986+ </ div >
1987+ ) }
18811988 </ div >
18821989 </ div >
18831990 </ div >
0 commit comments