11
22'use client' ;
33
4- import { useEffect , useState , Suspense , useCallback , useMemo , startTransition as ReactStartTransition } from 'react' ;
4+ import { useEffect , useState , Suspense , useCallback , useMemo } from 'react' ;
55import { useParams , useRouter } from 'next/navigation' ;
66import Link from 'next/link' ;
77import { useAuth } from '@/hooks/useAuth' ;
@@ -106,18 +106,21 @@ function FileExplorerContent() {
106106
107107 const loadContent = useCallback ( async ( pathToLoad : string ) => {
108108 if ( ! project || ! project . githubRepoName || authLoading || isLoadingProject ) {
109+ console . log ( "loadContent: Aborting, pre-conditions not met." , { projectExists : ! ! project , githubRepoName : project ?. githubRepoName , authLoading, isLoadingProject } ) ;
109110 return ;
110111 }
112+ console . log ( `loadContent: Loading content for path: ${ pathToLoad } ` ) ;
111113 setIsLoadingPathContent ( true ) ;
112114 setError ( null ) ;
113- setFileData ( null ) ;
114- setIsViewingFile ( false ) ;
115+ setFileData ( null ) ; // Reset file data when navigating to a new path
116+ setIsViewingFile ( false ) ; // Reset viewing state
115117
116118 try {
117119 const extension = pathToLoad . includes ( '.' ) ? getFileExtension ( pathToLoad . split ( '/' ) . pop ( ) ! ) : null ;
118- const isFileCandidate = extension && ! pathToLoad . endsWith ( '/' ) ;
120+ const isFileCandidate = ! ! extension && ! pathToLoad . endsWith ( '/' ) ; // More robust check
119121
120122 if ( isFileCandidate ) {
123+ console . log ( `loadContent: Path is a file candidate: ${ pathToLoad } ` ) ;
121124 const fetchedFileData = await getFileContentAction ( projectUuid , pathToLoad ) ;
122125 if ( 'content' in fetchedFileData && fetchedFileData . sha ) {
123126 let fileDisplayType : 'md' | 'image' | 'html' | 'text' | 'other' = 'other' ;
@@ -137,34 +140,43 @@ function FileExplorerContent() {
137140 } ) ;
138141 setEditingContent ( fetchedFileData . content ) ;
139142 setIsViewingFile ( true ) ;
143+ console . log ( `loadContent: Successfully loaded file: ${ pathToLoad } , type: ${ fileDisplayType } ` ) ;
140144 } else {
141145 setError ( fetchedFileData . error || "Failed to load file content." ) ;
142146 setIsViewingFile ( false ) ;
147+ console . error ( `loadContent: Error loading file content for ${ pathToLoad } :` , fetchedFileData . error ) ;
143148 }
144149 } else { // Is a directory or root
150+ console . log ( `loadContent: Path is a directory candidate: ${ pathToLoad } ` ) ;
145151 const dirData = await getRepoContentsAction ( projectUuid , pathToLoad ) ;
146152 if ( Array . isArray ( dirData ) ) {
147153 setContents ( dirData . sort ( ( a , b ) => {
148154 if ( a . type === 'dir' && b . type !== 'dir' ) return - 1 ;
149155 if ( a . type !== 'dir' && b . type === 'dir' ) return 1 ;
150156 return a . name . localeCompare ( b . name ) ;
151157 } ) ) ;
158+ console . log ( `loadContent: Successfully loaded directory contents for ${ pathToLoad } :` , dirData . length , "items" ) ;
152159 } else {
153160 setError ( dirData . error || "Failed to fetch repository contents." ) ;
161+ console . error ( `loadContent: Error loading directory contents for ${ pathToLoad } :` , dirData . error ) ;
154162 }
155163 }
156164 } catch ( e : any ) {
157165 setError ( e . message || 'An unexpected error occurred while loading content.' ) ;
158166 toast ( { variant : 'destructive' , title : 'Error' , description : e . message } ) ;
167+ console . error ( `loadContent: Exception for path ${ pathToLoad } :` , e ) ;
159168 } finally {
160169 setIsLoadingPathContent ( false ) ;
170+ console . log ( `loadContent: Finished loading for path: ${ pathToLoad } ` ) ;
161171 }
162- } , [ project , projectUuid , authLoading , isLoadingProject , toast ] ) ;
172+ } , [ projectUuid , project , authLoading , isLoadingProject , toast ] ) ;
163173
164174
165175 useEffect ( ( ) => {
176+ console . log ( "Project/Auth Effect: Triggered" , { projectUuid, authLoading, user : ! ! user } ) ;
166177 if ( ! projectUuid || authLoading ) return ;
167178 if ( ! user ) {
179+ console . log ( "Project/Auth Effect: No user, redirecting to login." ) ;
168180 router . push ( '/login' ) ;
169181 return ;
170182 }
@@ -174,30 +186,39 @@ function FileExplorerContent() {
174186 if ( ! fetchedProject ) {
175187 setError ( "Project not found or access denied." ) ;
176188 setProject ( null ) ;
189+ console . log ( "Project/Auth Effect: Project not found." ) ;
177190 } else {
178191 setProject ( fetchedProject ) ;
192+ console . log ( "Project/Auth Effect: Project loaded:" , fetchedProject . name ) ;
179193 if ( ! fetchedProject . githubRepoName ) {
180194 setError ( "Project is not linked to a GitHub repository." ) ;
181195 setIsLoadingPathContent ( false ) ;
196+ console . log ( "Project/Auth Effect: Project not linked to GitHub." ) ;
182197 }
183198 }
184199 } )
185200 . catch ( err => {
186- console . error ( "Error fetching project:" , err ) ;
201+ console . error ( "Project/Auth Effect: Error fetching project:" , err ) ;
187202 setError ( "Failed to load project details." ) ;
188203 setProject ( null ) ;
189204 } )
190205 . finally ( ( ) => {
191206 setIsLoadingProject ( false ) ;
207+ console . log ( "Project/Auth Effect: Finished loading project details." ) ;
192208 } ) ;
193209 } , [ projectUuid , user , authLoading , router ] ) ;
194210
195211
196212 useEffect ( ( ) => {
213+ console . log ( "Path/Content Effect: Triggered" , { projectExists : ! ! project , githubLinked : ! ! project ?. githubRepoName , isLoadingProject, currentPath } ) ;
197214 if ( project && project . githubRepoName && ! isLoadingProject ) {
198215 loadContent ( currentPath ) ;
216+ } else if ( project && ! project . githubRepoName && ! isLoadingProject ) {
217+ console . log ( "Path/Content Effect: Project exists but not linked to GitHub. Skipping content load." ) ;
218+ // setError("Project is not linked to a GitHub repository."); // Already set in project load effect
219+ setIsLoadingPathContent ( false ) ;
199220 }
200- } , [ project , isLoadingProject , currentPath , loadContent ] ) ;
221+ } , [ project , isLoadingProject , currentPath , loadContent ] ) ; // loadContent is now stable due to useCallback
201222
202223
203224 const handleSaveFile = async ( ) => {
@@ -257,7 +278,6 @@ function FileExplorerContent() {
257278 if ( isViewingFile && fileData ?. path === contentToDelete . path ) {
258279 const parentPath = currentPath . substring ( 0 , currentPath . lastIndexOf ( '/' ) ) ;
259280 router . push ( `/projects/${ projectUuid } /codespace/files${ parentPath ? '/' + parentPath : '' } ` ) ;
260- // loadContent will be called by useEffect due to currentPath change
261281 } else {
262282 loadContent ( currentPath ) ;
263283 }
@@ -307,7 +327,7 @@ function FileExplorerContent() {
307327 const isLoadingPage = authLoading || isLoadingProject || isLoadingPathContent ;
308328
309329
310- if ( isLoadingPage && ! error && ! project ?. githubRepoName ) { // Initial loading state before project details are known
330+ if ( isLoadingPage && ! error && ! project ?. githubRepoName ) {
311331 return (
312332 < div className = "space-y-6" >
313333 < div className = "flex justify-between items-center" >
@@ -477,9 +497,9 @@ function FileExplorerContent() {
477497 </ AlertDescription >
478498 </ Alert >
479499 ) : isViewingFile && fileData ? (
480- < div >
481- < div className = "flex justify-between items-center mb-4" >
482- < h3 className = "text-xl font-semibold" > { fileData . name } </ h3 >
500+ < div className = "flex flex-col" > { /* Flex column for the entire file view section */ }
501+ < div className = "flex justify-between items-center mb-4 flex-shrink-0" > { /* Header: Title and Buttons. flex-shrink-0 is important here. */ }
502+ < h3 className = "text-xl font-semibold truncate " > { fileData . name } </ h3 >
483503 < div className = "flex items-center gap-2" >
484504 { canEditCurrentFile && (
485505 < Button variant = "outline" size = "sm" onClick = { ( ) => setIsEditModalOpen ( true ) } >
@@ -502,13 +522,17 @@ function FileExplorerContent() {
502522 ) }
503523 </ div >
504524 </ div >
525+
526+ { /* Content area that will scroll if needed */ }
505527 { fileData . type === 'md' && (
506- < div className = "prose dark:prose-invert max-w-none p-4 border rounded-md bg-muted/30" >
507- < ReactMarkdown remarkPlugins = { [ remarkGfm ] } > { fileData . content } </ ReactMarkdown >
528+ < div className = "overflow-x-auto" >
529+ < div className = "prose dark:prose-invert max-w-none p-4 border rounded-md bg-muted/30 min-w-max" >
530+ < ReactMarkdown remarkPlugins = { [ remarkGfm ] } > { fileData . content } </ ReactMarkdown >
531+ </ div >
508532 </ div >
509533 ) }
510534 { fileData . type === 'image' && fileData . encoding === 'base64' && (
511- < div className = "p-4 border rounded-md bg-muted/30 flex justify-center items-center max-h-[70vh] overflow-hidden " >
535+ < div className = "p-4 border rounded-md bg-muted/30 flex justify-center items-center max-h-[70vh] overflow-auto " >
512536 < NextImage
513537 src = { `data:image/${ getFileExtension ( fileData . name ) } ;base64,${ fileData . content } ` }
514538 alt = { fileData . name }
@@ -522,20 +546,22 @@ function FileExplorerContent() {
522546 </ div >
523547 ) }
524548 { fileData . type === 'html' && (
525- < div className = "p-4 border rounded-md bg-muted/30" >
549+ < div className = "p-4 border rounded-md bg-muted/30 overflow-x-auto " >
526550 < h4 className = "text-sm font-semibold mb-2" > HTML Preview:</ h4 >
527551 < iframe
528552 srcDoc = { fileData . content }
529553 title = { `Preview of ${ fileData . name } ` }
530- className = "w-full h-[50vh] border rounded-md bg-white"
554+ className = "w-full h-[50vh] border rounded-md bg-white min-w-[600px] "
531555 sandbox = "allow-scripts"
532556 />
533557 </ div >
534558 ) }
535559 { fileData . type === 'text' && (
536- < pre className = "p-4 border rounded-md bg-muted/30 text-sm overflow-x-auto max-h-[60vh]" >
537- < code > { fileData . content } </ code >
538- </ pre >
560+ < div className = "overflow-x-auto" >
561+ < pre className = "p-4 border rounded-md bg-muted/30 text-sm max-h-[60vh] min-w-max" >
562+ < code > { fileData . content } </ code >
563+ </ pre >
564+ </ div >
539565 ) }
540566 { fileData . type === 'other' && (
541567 < Alert >
@@ -605,7 +631,7 @@ function FileExplorerContent() {
605631 < Trash2 className = "h-4 w-4" />
606632 </ Button >
607633 </ AlertDialogTrigger >
608- { contentToDelete ?. path === item . path && ( // Check path instead of sha for key consistency
634+ { contentToDelete ?. path === item . path && (
609635 < AlertDialogContent >
610636 < AlertDialogHeader >
611637 < AlertDialogTitle > Delete File: "{ contentToDelete . name } "?</ AlertDialogTitle >
@@ -685,5 +711,3 @@ export default function GitHubFilesPage() {
685711 </ Suspense >
686712 )
687713}
688-
689-
0 commit comments