@@ -77,6 +77,7 @@ interface FileViewerProps {
7777 onDirtyChange ?: ( isDirty : boolean ) => void
7878 onSaveStatusChange ?: ( status : 'idle' | 'saving' | 'saved' | 'error' ) => void
7979 saveRef ?: React . MutableRefObject < ( ( ) => Promise < void > ) | null >
80+ streamingContent ?: string
8081}
8182
8283export function FileViewer ( {
@@ -89,6 +90,7 @@ export function FileViewer({
8990 onDirtyChange,
9091 onSaveStatusChange,
9192 saveRef,
93+ streamingContent,
9294} : FileViewerProps ) {
9395 const category = resolveFileCategory ( file . type , file . name )
9496
@@ -97,12 +99,13 @@ export function FileViewer({
9799 < TextEditor
98100 file = { file }
99101 workspaceId = { workspaceId }
100- canEdit = { canEdit }
102+ canEdit = { streamingContent !== undefined ? false : canEdit }
101103 previewMode = { previewMode ?? ( showPreview ? 'preview' : 'editor' ) }
102104 autoFocus = { autoFocus }
103105 onDirtyChange = { onDirtyChange }
104106 onSaveStatusChange = { onSaveStatusChange }
105107 saveRef = { saveRef }
108+ streamingContent = { streamingContent }
106109 />
107110 )
108111 }
@@ -123,6 +126,7 @@ interface TextEditorProps {
123126 onDirtyChange ?: ( isDirty : boolean ) => void
124127 onSaveStatusChange ?: ( status : 'idle' | 'saving' | 'saved' | 'error' ) => void
125128 saveRef ?: React . MutableRefObject < ( ( ) => Promise < void > ) | null >
129+ streamingContent ?: string
126130}
127131
128132function TextEditor ( {
@@ -134,6 +138,7 @@ function TextEditor({
134138 onDirtyChange,
135139 onSaveStatusChange,
136140 saveRef,
141+ streamingContent,
137142} : TextEditorProps ) {
138143 const initializedRef = useRef ( false )
139144 const contentRef = useRef ( '' )
@@ -157,6 +162,13 @@ function TextEditor({
157162 const savedContentRef = useRef ( '' )
158163
159164 useEffect ( ( ) => {
165+ if ( streamingContent !== undefined ) {
166+ setContent ( streamingContent )
167+ contentRef . current = streamingContent
168+ initializedRef . current = true
169+ return
170+ }
171+
160172 if ( fetchedContent === undefined ) return
161173
162174 if ( ! initializedRef . current ) {
@@ -180,7 +192,7 @@ function TextEditor({
180192 savedContentRef . current = fetchedContent
181193 contentRef . current = fetchedContent
182194 }
183- } , [ fetchedContent , dataUpdatedAt , autoFocus ] )
195+ } , [ streamingContent , fetchedContent , dataUpdatedAt , autoFocus ] )
184196
185197 const handleContentChange = useCallback ( ( value : string ) => {
186198 setContent ( value )
@@ -252,23 +264,25 @@ function TextEditor({
252264 }
253265 } , [ isResizing ] )
254266
255- if ( isLoading ) {
256- return (
257- < div className = 'flex flex-1 flex-col gap-[8px] p-[24px]' >
258- < Skeleton className = 'h-[16px] w-[60%]' />
259- < Skeleton className = 'h-[16px] w-[80%]' />
260- < Skeleton className = 'h-[16px] w-[40%]' />
261- < Skeleton className = 'h-[16px] w-[70%]' />
262- </ div >
263- )
264- }
267+ if ( streamingContent === undefined ) {
268+ if ( isLoading ) {
269+ return (
270+ < div className = 'flex flex-1 flex-col gap-[8px] p-[24px]' >
271+ < Skeleton className = 'h-[16px] w-[60%]' />
272+ < Skeleton className = 'h-[16px] w-[80%]' />
273+ < Skeleton className = 'h-[16px] w-[40%]' />
274+ < Skeleton className = 'h-[16px] w-[70%]' />
275+ </ div >
276+ )
277+ }
265278
266- if ( error ) {
267- return (
268- < div className = 'flex flex-1 items-center justify-center' >
269- < p className = 'text-[13px] text-[var(--text-muted)]' > Failed to load file content</ p >
270- </ div >
271- )
279+ if ( error ) {
280+ return (
281+ < div className = 'flex flex-1 items-center justify-center' >
282+ < p className = 'text-[13px] text-[var(--text-muted)]' > Failed to load file content</ p >
283+ </ div >
284+ )
285+ }
272286 }
273287
274288 const showEditor = previewMode !== 'preview'
0 commit comments