1- import { HTMLAttributes , useCallback , useEffect , useMemo , useState } from "react"
1+ import { useCallback , useEffect , useState , memo } from "react"
22import { useEvent } from "react-use"
3- import { Virtuoso } from "react-virtuoso"
43import { ChevronDown , Skull } from "lucide-react"
54
65import { CommandExecutionStatus , commandExecutionStatusSchema } from "@roo/schemas"
@@ -30,11 +29,6 @@ export const CommandExecution = ({ executionId, text }: CommandExecutionProps) =
3029 const [ output , setOutput ] = useState ( "" )
3130 const [ command , setCommand ] = useState ( text )
3231
33- const lines = useMemo (
34- ( ) => [ `$ ${ command } ` , ...output . split ( "\n" ) . filter ( ( line ) => line . trim ( ) !== "" ) ] ,
35- [ output , command ] ,
36- )
37-
3832 const onMessage = useCallback (
3933 ( event : MessageEvent ) => {
4034 const message : ExtensionMessage = event . data
@@ -55,7 +49,7 @@ export const CommandExecution = ({ executionId, text }: CommandExecutionProps) =
5549 setStatus ( data )
5650 break
5751 case "output" :
58- setOutput ( ( output ) => output + data . output )
52+ setOutput ( data . output )
5953 break
6054 case "fallback" :
6155 setIsExpanded ( true )
@@ -116,7 +110,7 @@ export const CommandExecution = ({ executionId, text }: CommandExecutionProps) =
116110 < div className = "whitespace-nowrap" > Exited ({ status . exitCode } )</ div >
117111 </ div >
118112 ) }
119- { lines . length > 0 && (
113+ { output . length > 0 && (
120114 < Button variant = "ghost" size = "icon" onClick = { ( ) => setIsExpanded ( ! isExpanded ) } >
121115 < ChevronDown
122116 className = { cn ( "size-4 transition-transform duration-300" , {
@@ -127,31 +121,21 @@ export const CommandExecution = ({ executionId, text }: CommandExecutionProps) =
127121 ) }
128122 </ div >
129123 </ div >
130- < div
131- className = { cn ( "mt-1 pt-1 border-t border-border/25" , { hidden : ! isExpanded } ) }
132- style = { { height : Math . min ( ( lines . length + 1 ) * 16 , 200 ) } } >
133- { lines . length > 0 && (
134- < Virtuoso
135- className = "h-full"
136- totalCount = { lines . length }
137- itemContent = { ( i ) => < Line className = "text-sm" > { lines [ i ] } </ Line > }
138- followOutput = "auto"
139- />
140- ) }
141- </ div >
124+ < MemoizedOutputContainer isExpanded = { isExpanded } output = { output } />
142125 </ div >
143126 )
144127}
145128
146- type LineProps = HTMLAttributes < HTMLDivElement >
147-
148- const Line = ( { className, ...props } : LineProps ) => {
149- return (
150- < div
151- className = { cn ( "font-mono text-vscode-editor-foreground whitespace-pre-wrap break-words" , className ) }
152- { ...props }
153- />
154- )
155- }
156-
157129CommandExecution . displayName = "CommandExecution"
130+
131+ const OutputContainer = ( { isExpanded, output } : { isExpanded : boolean ; output : string } ) => (
132+ < div
133+ className = { cn ( "mt-1 pt-1 border-t border-border/25 overflow-hidden transition-[max-height] duration-300" , {
134+ "max-h-0" : ! isExpanded ,
135+ "max-h-[100%]" : isExpanded ,
136+ } ) } >
137+ { output . length > 0 && < CodeBlock source = { output } language = "log" /> }
138+ </ div >
139+ )
140+
141+ const MemoizedOutputContainer = memo ( OutputContainer )
0 commit comments