@@ -332,6 +332,7 @@ const FormattedResultContent = memo(({ text, theme }: { text: string; theme: The
332332const ToolResultItem = memo ( ( { tool, annotation, theme } : ToolResultItemProps ) => {
333333 const [ isExpanded , setIsExpanded ] = useState ( false ) ;
334334 const [ copied , setCopied ] = useState ( false ) ;
335+ const copyTimerRef = useRef < ReturnType < typeof setTimeout > > ( null ) ;
335336 const resultContainerRef = useRef < HTMLDivElement > ( null ) ;
336337 const [ isOverflowing , setIsOverflowing ] = useState ( false ) ;
337338
@@ -367,6 +368,14 @@ const ToolResultItem = memo(({ tool, annotation, theme }: ToolResultItemProps) =
367368 const isLongResult = lineCount > RESULT_LINE_THRESHOLD ;
368369 const isFormattedLong = ( extracted . text ?. split ( '\n' ) . length ?? 0 ) > RESULT_LINE_THRESHOLD ;
369370
371+ useEffect ( ( ) => {
372+ return ( ) => {
373+ if ( copyTimerRef . current ) {
374+ clearTimeout ( copyTimerRef . current ) ;
375+ }
376+ } ;
377+ } , [ ] ) ;
378+
370379 // Detect whether the result container overflows the collapsed max-height
371380 useEffect ( ( ) => {
372381 if ( resultContainerRef . current ) {
@@ -393,7 +402,12 @@ const ToolResultItem = memo(({ tool, annotation, theme }: ToolResultItemProps) =
393402 const textToCopy = viewMode === 'formatted' && extracted . text ? extracted . text : resultStr ;
394403 await navigator . clipboard . writeText ( textToCopy ) ;
395404 setCopied ( true ) ;
396- setTimeout ( ( ) => setCopied ( false ) , 2000 ) ;
405+
406+ if ( copyTimerRef . current ) {
407+ clearTimeout ( copyTimerRef . current ) ;
408+ }
409+
410+ copyTimerRef . current = setTimeout ( ( ) => setCopied ( false ) , 2000 ) ;
397411 } catch {
398412 logger . error ( 'Failed to copy result to clipboard' ) ;
399413 }
0 commit comments