@@ -71,13 +71,10 @@ function App() {
7171 // Tab State
7272 const [ tabs , setTabs ] = useState < Tab [ ] > ( ( ) => {
7373 const saved = localStorage . getItem ( 'opendb_tabs' ) ;
74- // We use a constant for the title here because it's initial state, but we should potentially localize it dynamically if re-rendered.
75- // However, tabs state is persisted. We might want to store 'type' and resolve title visually if generic.
76- // For now, let's keep it simple.
77- return saved ? JSON . parse ( saved ) : [ { id : 'query-main' , type : 'query' , title : t ( 'app.queryEditor' ) } ] ;
74+ return saved ? JSON . parse ( saved ) : [ ] ;
7875 } ) ;
7976 const [ activeTabId , setActiveTabId ] = useState < string > ( ( ) => {
80- return localStorage . getItem ( 'opendb_active_tab' ) || 'query-main ' ;
77+ return localStorage . getItem ( 'opendb_active_tab' ) || '' ;
8178 } ) ;
8279 // Schema for autocomplete
8380 const [ dbSchema , setDbSchema ] = useState < Record < string , string [ ] > | null > ( null ) ;
@@ -219,6 +216,16 @@ function App() {
219216 } , [ query , executeQueries , tabs , activeTab ] ) ;
220217
221218
219+ const handleNewQueryTab = useCallback ( ( ) => {
220+ const newTab : Tab = {
221+ id : `query-${ Date . now ( ) } ` ,
222+ type : 'query' ,
223+ title : t ( 'app.newQuery' )
224+ } ;
225+ setTabs ( prev => [ ...prev , newTab ] ) ;
226+ setActiveTabId ( newTab . id ) ;
227+ } , [ t ] ) ;
228+
222229 const handleOpenModal = ( config ?: ConnectionConfig , name ?: string ) => {
223230 setModalData ( { config, name } ) ;
224231 setModalOpen ( true ) ;
@@ -315,9 +322,14 @@ function App() {
315322
316323 { connected && (
317324 < div className = "flex items-center h-full gap-1" >
318- { /* Replaced by TabBar in main area */ }
325+ < button
326+ onClick = { handleNewQueryTab }
327+ className = "flex items-center gap-2 px-3 py-1.5 rounded-md bg-primary/10 text-primary hover:bg-primary/20 transition-all font-bold text-[10px] uppercase tracking-wider border border-primary/20"
328+ >
329+ < Code2 size = { 12 } strokeWidth = { 2.5 } />
330+ { t ( 'app.newQuery' ) }
331+ </ button >
319332 </ div >
320-
321333 ) }
322334 </ div >
323335
@@ -391,6 +403,7 @@ function App() {
391403 activeTabId = { activeTabId }
392404 onTabSelect = { setActiveTabId }
393405 onTabClose = { handleTabClose }
406+ onAddTab = { handleNewQueryTab }
394407 />
395408 ) }
396409
@@ -432,8 +445,18 @@ function App() {
432445 } }
433446 />
434447 ) : (
435- < div className = "p-10 flex items-center justify-center h-full text-muted-foreground opacity-50 text-sm font-bold uppercase tracking-widest" >
436- { t ( 'app.noTabSelected' ) }
448+ < div className = "p-10 flex flex-col items-center justify-center h-full text-muted-foreground opacity-50 gap-4" >
449+ < span className = "text-sm font-bold uppercase tracking-widest" > { t ( 'app.noTabSelected' ) } </ span >
450+ < div className = "flex gap-2" >
451+ < button
452+ onClick = { handleNewQueryTab }
453+ className = "flex items-center gap-2 px-4 py-2 rounded-lg bg-primary/10 text-primary hover:bg-primary/20 transition-colors font-bold text-xs uppercase tracking-wider"
454+ >
455+ < Code2 size = { 16 } />
456+ { t ( 'app.newQuery' ) }
457+ </ button >
458+ </ div >
459+ < p className = "text-[10px] font-mono opacity-50" > Press Cmd+K for commands</ p >
437460 </ div >
438461 ) }
439462 </ div >
@@ -461,29 +484,33 @@ function App() {
461484 ) }
462485 </ ResizablePanel >
463486
464- </ ResizablePanelGroup >
465- </ div >
487+ </ ResizablePanelGroup >
488+ </ div >
466489
467490 { /* Premium Modal */ }
468- { modalOpen && (
469- < ConnectionModal
470- title = { modalData . name ? t ( 'app.editConnection' ) : t ( 'app.newConnection' ) }
471- initialConfig = { modalData . config }
472- initialName = { modalData . name }
473- onSave = { handleSaveModal }
474- onClose = { ( ) => setModalOpen ( false ) }
475- onTest = { testConnection }
476- loading = { loading }
477- />
478- ) }
491+ {
492+ modalOpen && (
493+ < ConnectionModal
494+ title = { modalData . name ? t ( 'app.editConnection' ) : t ( 'app.newConnection' ) }
495+ initialConfig = { modalData . config }
496+ initialName = { modalData . name }
497+ onSave = { handleSaveModal }
498+ onClose = { ( ) => setModalOpen ( false ) }
499+ onTest = { testConnection }
500+ loading = { loading }
501+ />
502+ )
503+ }
479504
480505 { /* Update Modal */ }
481- { updateInfo && (
482- < UpdateModal
483- updateInfo = { updateInfo }
484- onClose = { ( ) => setUpdateInfo ( null ) }
485- />
486- ) }
506+ {
507+ updateInfo && (
508+ < UpdateModal
509+ updateInfo = { updateInfo }
510+ onClose = { ( ) => setUpdateInfo ( null ) }
511+ />
512+ )
513+ }
487514
488515 { /* Slim Status Footer */ }
489516 < footer className = "h-8 border-t bg-card/80 flex items-center px-4 justify-between shrink-0 shadow-inner" >
@@ -511,15 +538,7 @@ function App() {
511538 databases = { databases }
512539 currentDb = { currentDb }
513540 connected = { connected }
514- onNewQueryTab = { ( ) => {
515- const newTab : Tab = {
516- id : `query-${ Date . now ( ) } ` ,
517- type : 'query' ,
518- title : t ( 'app.newQuery' )
519- } ;
520- setTabs ( prev => [ ...prev , newTab ] ) ;
521- setActiveTabId ( newTab . id ) ;
522- } }
541+ onNewQueryTab = { handleNewQueryTab }
523542 onSwitchDb = { handleSelectDatabase }
524543 onOpenHistory = { ( ) => {
525544 // Focus query editor and open history popover
@@ -535,7 +554,7 @@ function App() {
535554 } }
536555 onOpenSettings = { ( ) => setModalOpen ( true ) }
537556 />
538- </ div >
557+ </ div >
539558 ) ;
540559}
541560
0 commit comments