@@ -5,6 +5,7 @@ import { Sidebar } from "./Sidebar";
55import { StatusBar } from "./StatusBar" ;
66import { PrefixProvider , useTUIContext } from "./FocusContext" ;
77import { SearchOverlay } from "./SearchOverlay" ;
8+ import { LocalFileViewer } from "./LocalFileViewer" ;
89import type { CategoryInfo } from "../types" ;
910
1011const SIDEBAR_WIDTH = 30 ;
@@ -30,9 +31,11 @@ interface SidebarNavigationItem {
3031const buildAllNavigationItems = (
3132 categories : ReadonlyArray < CategoryInfo > ,
3233) : readonly SidebarNavigationItem [ ] =>
33- categories
34- . filter ( ( c ) => c . type !== "files" )
35- . flatMap ( ( c ) => c . tabs . map ( ( tab ) => ( { categoryName : c . name , tabId : tab . id } ) ) ) ;
34+ categories . flatMap ( ( c ) =>
35+ c . type === "files"
36+ ? ( c . openFiles ?? [ ] ) . map ( ( file ) => ( { categoryName : c . name , tabId : `file::${ file . path } ` } ) )
37+ : c . tabs . map ( ( tab ) => ( { categoryName : c . name , tabId : tab . id } ) ) ,
38+ ) ;
3639
3740const navigateItem = (
3841 items : readonly SidebarNavigationItem [ ] ,
@@ -105,12 +108,24 @@ export const WmuxApp = (props: {
105108 return map ;
106109 } , [ children ] ) ;
107110
111+ const selectFirstInCategory = useCallback ( ( cat : CategoryInfo ) => {
112+ if ( cat . type === "files" ) {
113+ const firstOpen = ( cat . openFiles ?? [ ] ) [ 0 ] ;
114+ if ( firstOpen ) { selectTab ( `file::${ firstOpen . path } ` ) ; return ; }
115+ const firstFile = ( cat . fileEntries ?? [ ] ) . find ( ( e ) => ! e . isDir ) ;
116+ if ( firstFile ) { selectTab ( `file::${ firstFile . path } ` ) ; openFile ( firstFile . path ) ; }
117+ return ;
118+ }
119+ if ( cat . tabs . length > 0 ) selectTab ( cat . tabs [ 0 ] ! . id ) ;
120+ } , [ selectTab , openFile ] ) ;
121+
108122 const handleNavigate = useCallback ( ( delta : number ) => {
109123 const target = navigateItem ( allNavItems , activeTabId , delta ) ;
110124 if ( ! target ) return ;
111125 if ( target . categoryName !== activeCategory ) selectCategory ( target . categoryName ) ;
112126 selectTab ( target . tabId ) ;
113- } , [ allNavItems , activeTabId , activeCategory , selectCategory , selectTab ] ) ;
127+ if ( target . tabId . startsWith ( "file::" ) ) openFile ( target . tabId . slice ( 6 ) ) ;
128+ } , [ allNavItems , activeTabId , activeCategory , selectCategory , selectTab , openFile ] ) ;
114129
115130 useKeyboard ( ( key ) => {
116131 // ── Search overlay handles its own keys ──────────────
@@ -147,9 +162,7 @@ export const WmuxApp = (props: {
147162 if ( idx < categories . length ) {
148163 const cat = categories [ idx ] ! ;
149164 selectCategory ( cat . name ) ;
150- if ( cat . type !== "files" && cat . tabs . length > 0 ) {
151- selectTab ( cat . tabs [ 0 ] ! . id ) ;
152- }
165+ selectFirstInCategory ( cat ) ;
153166 }
154167 return ;
155168 }
@@ -160,19 +173,15 @@ export const WmuxApp = (props: {
160173 const nextIdx = ( catIdx + 1 ) % categories . length ;
161174 const nextCat = categories [ nextIdx ] ! ;
162175 selectCategory ( nextCat . name ) ;
163- if ( nextCat . type !== "files" && nextCat . tabs . length > 0 ) {
164- selectTab ( nextCat . tabs [ 0 ] ! . id ) ;
165- }
176+ selectFirstInCategory ( nextCat ) ;
166177 return ;
167178 }
168179 if ( key . name === "[" ) {
169180 const catIdx = categories . findIndex ( ( c ) => c . name === activeCategory ) ;
170181 const prevIdx = ( catIdx - 1 + categories . length ) % categories . length ;
171182 const prevCat = categories [ prevIdx ] ! ;
172183 selectCategory ( prevCat . name ) ;
173- if ( prevCat . type !== "files" && prevCat . tabs . length > 0 ) {
174- selectTab ( prevCat . tabs [ 0 ] ! . id ) ;
175- }
184+ selectFirstInCategory ( prevCat ) ;
176185 return ;
177186 }
178187
@@ -274,12 +283,14 @@ export const WmuxApp = (props: {
274283 onOpenFile = { openFile }
275284 onClose = { handleSearchClose }
276285 />
286+ ) : activeChild ? (
287+ activeChild
288+ ) : activeTabId . startsWith ( "file::" ) ? (
289+ < LocalFileViewer filePath = { activeTabId . slice ( 6 ) } />
277290 ) : (
278- activeChild ?? (
279- < box flexGrow = { 1 } justifyContent = "center" alignItems = "center" >
280- < text fg = "#636366" > No active tab</ text >
281- </ box >
282- )
291+ < box flexGrow = { 1 } justifyContent = "center" alignItems = "center" >
292+ < text fg = "#636366" > No active tab</ text >
293+ </ box >
283294 ) }
284295 </ box >
285296 </ box >
0 commit comments