@@ -8,6 +8,8 @@ import { VSCodeButton } from "@vscode/webview-ui-toolkit/react"
88import useSound from "use-sound"
99import { LRUCache } from "lru-cache"
1010
11+ import { useDebounceEffect } from "@src/utils/useDebounceEffect"
12+
1113import type { ClineAsk , ClineMessage } from "@roo-code/types"
1214
1315import { ClineSayBrowserAction , ClineSayTool , ExtensionMessage } from "@roo/ExtensionMessage"
@@ -154,6 +156,7 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
154156 ttl : 1000 * 60 * 15 , // 15 minutes TTL for long-running tasks
155157 } ) ,
156158 )
159+ const autoApproveTimeoutRef = useRef < NodeJS . Timeout | null > ( null )
157160
158161 const clineAskRef = useRef ( clineAsk )
159162 useEffect ( ( ) => {
@@ -408,6 +411,12 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
408411 everVisibleMessagesTsRef . current . clear ( ) // Clear for new task
409412 } , [ task ?. ts ] )
410413
414+ useEffect ( ( ) => {
415+ if ( isHidden ) {
416+ everVisibleMessagesTsRef . current . clear ( )
417+ }
418+ } , [ isHidden ] )
419+
411420 useEffect ( ( ) => ( ) => everVisibleMessagesTsRef . current . clear ( ) , [ ] )
412421
413422 useEffect ( ( ) => {
@@ -714,17 +723,15 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
714723 // NOTE: the VSCode window needs to be focused for this to work.
715724 useMount ( ( ) => textAreaRef . current ?. focus ( ) )
716725
717- useEffect ( ( ) => {
718- const timer = setTimeout ( ( ) => {
726+ useDebounceEffect (
727+ ( ) => {
719728 if ( ! isHidden && ! sendingDisabled && ! enableButtons ) {
720729 textAreaRef . current ?. focus ( )
721730 }
722- } , 50 )
723-
724- return ( ) => {
725- clearTimeout ( timer )
726- }
727- } , [ isHidden , sendingDisabled , enableButtons ] )
731+ } ,
732+ 50 ,
733+ [ isHidden , sendingDisabled , enableButtons ]
734+ )
728735
729736 const visibleMessages = useMemo ( ( ) => {
730737 const newVisibleMessages = modifiedMessages . filter ( ( message ) => {
@@ -1086,6 +1093,14 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
10861093 [ ] ,
10871094 )
10881095
1096+ useEffect ( ( ) => {
1097+ return ( ) => {
1098+ if ( scrollToBottomSmooth && typeof ( scrollToBottomSmooth as any ) . cancel === 'function' ) {
1099+ ( scrollToBottomSmooth as any ) . cancel ( )
1100+ }
1101+ }
1102+ } , [ scrollToBottomSmooth ] )
1103+
10891104 const scrollToBottomAuto = useCallback ( ( ) => {
10901105 virtuosoRef . current ?. scrollTo ( {
10911106 top : Number . MAX_SAFE_INTEGER ,
@@ -1124,13 +1139,13 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
11241139 )
11251140
11261141 useEffect ( ( ) => {
1127- let timerId : NodeJS . Timeout | undefined
1142+ let timer : NodeJS . Timeout | undefined
11281143 if ( ! disableAutoScrollRef . current ) {
1129- timerId = setTimeout ( ( ) => scrollToBottomSmooth ( ) , 50 )
1144+ timer = setTimeout ( ( ) => scrollToBottomSmooth ( ) , 50 )
11301145 }
11311146 return ( ) => {
1132- if ( timerId ) {
1133- clearTimeout ( timerId )
1147+ if ( timer ) {
1148+ clearTimeout ( timer )
11341149 }
11351150 }
11361151 } , [ groupedMessages . length , scrollToBottomSmooth ] )
@@ -1151,21 +1166,23 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
11511166 // Effect to handle showing the checkpoint warning after a delay
11521167 useEffect ( ( ) => {
11531168 // Only show the warning when there's a task but no visible messages yet
1154- if ( task && modifiedMessages . length === 0 && ! isStreaming ) {
1169+ if ( task && modifiedMessages . length === 0 && ! isStreaming && ! isHidden ) {
11551170 const timer = setTimeout ( ( ) => {
11561171 setShowCheckpointWarning ( true )
11571172 } , 5000 ) // 5 seconds
11581173
11591174 return ( ) => clearTimeout ( timer )
1175+ } else {
1176+ setShowCheckpointWarning ( false )
11601177 }
1161- } , [ task , modifiedMessages . length , isStreaming ] )
1178+ } , [ task , modifiedMessages . length , isStreaming , isHidden ] )
11621179
11631180 // Effect to hide the checkpoint warning when messages appear
11641181 useEffect ( ( ) => {
1165- if ( modifiedMessages . length > 0 || isStreaming ) {
1182+ if ( modifiedMessages . length > 0 || isStreaming || isHidden ) {
11661183 setShowCheckpointWarning ( false )
11671184 }
1168- } , [ modifiedMessages . length , isStreaming ] )
1185+ } , [ modifiedMessages . length , isStreaming , isHidden ] )
11691186
11701187 const placeholderText = task ? t ( "chat:typeMessage" ) : t ( "chat:typeTask" )
11711188
@@ -1239,38 +1256,40 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
12391256 )
12401257
12411258 useEffect ( ( ) => {
1242- // Only proceed if we have an ask and buttons are enabled.
1259+ if ( autoApproveTimeoutRef . current ) {
1260+ clearTimeout ( autoApproveTimeoutRef . current )
1261+ autoApproveTimeoutRef . current = null
1262+ }
1263+
12431264 if ( ! clineAsk || ! enableButtons ) {
12441265 return
12451266 }
12461267
12471268 const autoApprove = async ( ) => {
12481269 if ( lastMessage ?. ask && isAutoApproved ( lastMessage ) ) {
1249- // Note that `isAutoApproved` can only return true if
1250- // lastMessage is an ask of type "browser_action_launch",
1251- // "use_mcp_server", "command", or "tool".
1252-
1253- // Add delay for write operations.
12541270 if ( lastMessage . ask === "tool" && isWriteToolAction ( lastMessage ) ) {
1255- await new Promise ( ( resolve ) => setTimeout ( resolve , writeDelayMs ) )
1256- if ( ! isMountedRef . current ) {
1257- return
1258- }
1271+ await new Promise < void > ( ( resolve ) => {
1272+ autoApproveTimeoutRef . current = setTimeout ( resolve , writeDelayMs )
1273+ } )
12591274 }
12601275
1261- vscode . postMessage ( { type : "askResponse" , askResponse : "yesButtonClicked" } )
1276+ if ( autoApproveTimeoutRef . current === null || autoApproveTimeoutRef . current ) {
1277+ vscode . postMessage ( { type : "askResponse" , askResponse : "yesButtonClicked" } )
12621278
1263- // This is copied from `handlePrimaryButtonClick`, which we used
1264- // to call from `autoApprove`. I'm not sure how many of these
1265- // things are actually needed.
1266- if ( isMountedRef . current ) {
12671279 setSendingDisabled ( true )
12681280 setClineAsk ( undefined )
12691281 setEnableButtons ( false )
12701282 }
12711283 }
12721284 }
12731285 autoApprove ( )
1286+
1287+ return ( ) => {
1288+ if ( autoApproveTimeoutRef . current ) {
1289+ clearTimeout ( autoApproveTimeoutRef . current )
1290+ autoApproveTimeoutRef . current = null
1291+ }
1292+ }
12741293 } , [
12751294 clineAsk ,
12761295 enableButtons ,
0 commit comments