@@ -45,7 +45,7 @@ struct MainContentView: View {
4545 @State private var justRestoredTab = false // Prevent lazy load duplicate execution after restore
4646
4747 // MARK: - Constants
48-
48+
4949 private static let tabSaveDebounceDelay : UInt64 = 500_000_000 // 500ms in nanoseconds
5050 private static let connectionCheckDelay : UInt64 = 100_000_000 // 100ms in nanoseconds
5151 private static let maxConnectionRetries = 50 // Max retries for connection check (5 seconds total)
@@ -369,10 +369,65 @@ struct MainContentView: View {
369369 /// First part of notifications - reduces type-checker complexity
370370 @ViewBuilder
371371 private var bodyContentPart1 : some View {
372+ bodyContentPart2
373+ . onReceive ( NotificationCenter . default. publisher ( for: . deleteSelectedRows) ) { _ in
374+ // Delete rows or mark table for deletion
375+ Task { @MainActor in
376+ // First check if we have row selection in data grid
377+ if !selectedRowIndices. isEmpty {
378+ deleteSelectedRows ( )
379+ }
380+ // Otherwise check if tables are selected in sidebar
381+ else if !selectedTables. isEmpty {
382+ // Batch update to avoid stale copy issues with @Binding
383+ var updatedDeletes = pendingDeletes
384+ var updatedTruncates = pendingTruncates
385+
386+ for table in selectedTables {
387+ updatedTruncates. remove ( table. name)
388+ if updatedDeletes. contains ( table. name) {
389+ updatedDeletes. remove ( table. name)
390+ } else {
391+ updatedDeletes. insert ( table. name)
392+ }
393+ }
394+
395+ pendingTruncates = updatedTruncates
396+ pendingDeletes = updatedDeletes
397+ }
398+ }
399+ }
400+ . onReceive ( NotificationCenter . default. publisher ( for: . databaseDidConnect) ) { _ in
401+ // Load schema and update toolbar when connection is established (fixes race condition)
402+ Task { @MainActor in
403+ await loadSchema ( )
404+ // Update version after connection is fully established
405+ if let driver = DatabaseManager . shared. activeDriver {
406+ toolbarState. databaseVersion = driver. serverVersion
407+ }
408+ }
409+ }
410+ . onReceive ( NotificationCenter . default. publisher ( for: . showAllTables) ) { _ in
411+ // Show all tables metadata when user clicks "Tables" heading in sidebar
412+ Task { @MainActor in
413+ showAllTablesMetadata ( )
414+ }
415+ }
416+ . onReceive ( NotificationCenter . default. publisher ( for: . addNewRow) ) { _ in
417+ // Add row menu item (Cmd+I)
418+ Task { @MainActor in
419+ addNewRow ( )
420+ }
421+ }
422+ }
423+
424+ /// Second part of notifications - further reduces type-checker complexity
425+ @ViewBuilder
426+ private var bodyContentPart2 : some View {
372427 viewWithToolbar
373428 . task {
374429 await initializeView ( )
375-
430+
376431 // Restore tabs from disk first (persists across app restarts)
377432 // Fallback to session tabs (persists during app session only)
378433 var didRestoreTabs = false
@@ -381,7 +436,7 @@ struct MainContentView: View {
381436 // Restore from disk
382437 isRestoringTabs = true
383438 defer { isRestoringTabs = false }
384-
439+
385440 let restoredTabs = savedState. tabs. map { QueryTab ( from: $0) }
386441 tabManager. tabs = restoredTabs
387442 tabManager. selectedTabId = savedState. selectedTabId
@@ -392,7 +447,7 @@ struct MainContentView: View {
392447 // Fallback: Restore from session (for backward compatibility)
393448 isRestoringTabs = true
394449 defer { isRestoringTabs = false }
395-
450+
396451 tabManager. tabs = session. tabs
397452 tabManager. selectedTabId = session. selectedTabId
398453 didRestoreTabs = true
@@ -402,13 +457,13 @@ struct MainContentView: View {
402457 if let selectedTab = tabManager. selectedTab,
403458 selectedTab. tabType == . table,
404459 !selectedTab. query. trimmingCharacters ( in: . whitespacesAndNewlines) . isEmpty {
405-
460+
406461 // Wait for connection to be established
407462 var retryCount = 0
408463 while retryCount < Self . maxConnectionRetries {
409464 // Stop waiting if view is being dismissed
410465 guard !isDismissing else { break }
411-
466+
412467 if let session = DatabaseManager . shared. currentSession,
413468 session. isConnected {
414469 // Small delay to ensure everything is initialized
@@ -419,13 +474,13 @@ struct MainContentView: View {
419474 }
420475 break
421476 }
422-
477+
423478 // Wait 100ms and retry
424479 try ? await Task . sleep ( nanoseconds: 100_000_000 )
425480 retryCount += 1
426481 }
427-
428- if retryCount >= 50 {
482+
483+ if retryCount >= Self . maxConnectionRetries {
429484 print ( " [MainContentView] ⚠️ Connection timeout, query not executed " )
430485 }
431486 }
@@ -462,7 +517,7 @@ struct MainContentView: View {
462517 // Load query from history/bookmark panel into current tab
463518 Task { @MainActor in
464519 guard let query = notification. object as? String else { return }
465-
520+
466521 // Load into the current tab (which was just created by .newTab)
467522 if let tabIndex = tabManager. selectedTabIndex,
468523 tabIndex < tabManager. tabs. count {
@@ -493,67 +548,18 @@ struct MainContentView: View {
493548 } else {
494549 // Cancel any running query to prevent race conditions
495550 currentQueryTask? . cancel ( )
496-
551+
497552 // Rebuild query for table tabs to ensure fresh data
498553 if let tabIndex = tabManager. selectedTabIndex,
499554 tabManager. tabs [ tabIndex] . tabType == . table {
500555 rebuildTableQuery ( at: tabIndex)
501556 }
502-
557+
503558 // Fetch fresh data from database
504559 runQuery ( )
505560 }
506561 }
507562 }
508- . onReceive ( NotificationCenter . default. publisher ( for: . deleteSelectedRows) ) { _ in
509- // Delete rows or mark table for deletion
510- Task { @MainActor in
511- // First check if we have row selection in data grid
512- if !selectedRowIndices. isEmpty {
513- deleteSelectedRows ( )
514- }
515- // Otherwise check if tables are selected in sidebar
516- else if !selectedTables. isEmpty {
517- // Batch update to avoid stale copy issues with @Binding
518- var updatedDeletes = pendingDeletes
519- var updatedTruncates = pendingTruncates
520-
521- for table in selectedTables {
522- updatedTruncates. remove ( table. name)
523- if updatedDeletes. contains ( table. name) {
524- updatedDeletes. remove ( table. name)
525- } else {
526- updatedDeletes. insert ( table. name)
527- }
528- }
529-
530- pendingTruncates = updatedTruncates
531- pendingDeletes = updatedDeletes
532- }
533- }
534- }
535- . onReceive ( NotificationCenter . default. publisher ( for: . databaseDidConnect) ) { _ in
536- // Load schema and update toolbar when connection is established (fixes race condition)
537- Task { @MainActor in
538- await loadSchema ( )
539- // Update version after connection is fully established
540- if let driver = DatabaseManager . shared. activeDriver {
541- toolbarState. databaseVersion = driver. serverVersion
542- }
543- }
544- }
545- . onReceive ( NotificationCenter . default. publisher ( for: . showAllTables) ) { _ in
546- // Show all tables metadata when user clicks "Tables" heading in sidebar
547- Task { @MainActor in
548- showAllTablesMetadata ( )
549- }
550- }
551- . onReceive ( NotificationCenter . default. publisher ( for: . addNewRow) ) { _ in
552- // Add row menu item (Cmd+I)
553- Task { @MainActor in
554- addNewRow ( )
555- }
556- }
557563 }
558564
559565 // MARK: - Query Tab Content
@@ -590,7 +596,7 @@ struct MainContentView: View {
590596
591597 // Create new debounce task
592598 saveDebounceTask = Task { @MainActor in
593- try ? await Task . sleep ( nanoseconds: 500_000_000 ) // 0.5s
599+ try ? await Task . sleep ( nanoseconds: Self . tabSaveDebounceDelay )
594600
595601 // Only save if not cancelled and view not being dismissed
596602 guard !Task. isCancelled && !isDismissing else { return }
0 commit comments