Skip to content

refactor: migrate menu commands from AppState.shared to @FocusedValue#610

Merged
datlechin merged 7 commits intomainfrom
refactor/appstate-to-focused-value
Apr 7, 2026
Merged

refactor: migrate menu commands from AppState.shared to @FocusedValue#610
datlechin merged 7 commits intomainfrom
refactor/appstate-to-focused-value

Conversation

@datlechin
Copy link
Copy Markdown
Member

Summary

Migrates menu command state from the global AppState.shared singleton to per-window @FocusedValue(\.commandActions). This fixes multi-window state corruption where menu items reflected the last-active window instead of the currently-focused one.

What changed:

  • MainContentCommandActions — 13 computed properties added deriving state from the per-window coordinator, connection, and bindings
  • AppMenuCommands — All appState.xxx reads replaced with actions?.xxx ?? default
  • PasteboardCommands — Same migration

What stays:

  • AppState.shared class and singleton preserved as a thin bridge for 6 remaining non-menu consumers (SidebarView, MainContentView)
  • .environment(AppState.shared) still injected into WindowGroup
  • Coordinator writes to AppState still exist (will be removed in a follow-up when remaining consumers are migrated)

Multi-window fix: When two windows are open, switching focus now correctly updates all menu enabled/disabled states for the active window. Previously, menus reflected whichever window last wrote to AppState.shared.

Test plan

  • Single window: all menu items enable/disable correctly
  • Two windows open: switch between them → menus reflect active window
  • Welcome window focused → all connection menus disabled
  • Edit cell in window A → switch to window B → Save menu reflects B's state
  • Close all windows → menus reset to disabled

Phase 1+2 of AppState migration:

- Add 13 computed properties to MainContentCommandActions (per-window state)
- Replace all appState.xxx reads in AppMenuCommands and PasteboardCommands
  with actions?.xxx reads from @focusedvalue
- Remove appState parameter from AppMenuCommands and PasteboardCommands
- Menu items now correctly reflect the active window's state in multi-window

AppState.shared is kept as a thin bridge for non-menu consumers
(SidebarView, MainContentView) that will be migrated separately.
- SidebarView: safeModeLevel read from coordinator instead of AppState.shared
- SidebarContextMenu: currentDatabaseType read from coordinator.connection
…ToolbarState

Migrated sidebar reads from AppState.shared to per-window coordinator.
Added two properties to ConnectionToolbarState for future write migration.
AppState.shared writes remain temporarily — removing them requires careful
per-file editing to avoid breaking multi-line expressions.
- TableProApp: replace all 38 appState.xxx reads with actions?.xxx
- Remove appState parameter from AppMenuCommands and PasteboardCommands
- MainContentCommandActions: hasStructureChanges reads from toolbarState
- MainContentCommandActions: toggleHistoryPanel writes to toolbarState
- MainEditorContentView: isHistoryPanelVisible reads from toolbarState
- MainContentView: hasStructureChanges reads from toolbarState
…nges

- MainContentView: hasStructureChanges reads from toolbarState
- MainEditorContentView: hasQueryText writes to toolbarState
- QueryEditorView: hasQueryText derived from queryText binding directly
- ConnectionToolbarState: add hasQueryText property
- Zero appState.xxx reads remain in the codebase
- Remove 4 unused @Environment(AppState.self) declarations
- Remove .environment(AppState.shared) injection from WindowGroup
- Add hasQueryText to ConnectionToolbarState
- QueryEditorView derives hasQueryText from queryText binding directly
- Zero appState reads remain; 53 dead writes remain (harmless, for cleanup)
@datlechin datlechin merged commit 330a37a into main Apr 7, 2026
2 checks passed
@datlechin datlechin deleted the refactor/appstate-to-focused-value branch April 7, 2026 06:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant