Skip to content
24 changes: 24 additions & 0 deletions GhosttyTabs.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@
A5FF0007 /* SettingDefinition.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5FF0017 /* SettingDefinition.swift */; };
A5001002 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5001012 /* ContentView.swift */; };
A5FF0005 /* ContentView+CommandPalette.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5FF0015 /* ContentView+CommandPalette.swift */; };
NRCV00000000000000000005 /* TabItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = NRCV00000000000000000006 /* TabItemView.swift */; };
NRCV00000000000000000003 /* FileDropOverlayView.swift in Sources */ = {isa = PBXBuildFile; fileRef = NRCV00000000000000000004 /* FileDropOverlayView.swift */; };
NRCV00000000000000000001 /* CommandPaletteSearchEngine.swift in Sources */ = {isa = PBXBuildFile; fileRef = NRCV00000000000000000002 /* CommandPaletteSearchEngine.swift */; };
NRCV00000000000000000007 /* SidebarDragDrop.swift in Sources */ = {isa = PBXBuildFile; fileRef = NRCV00000000000000000008 /* SidebarDragDrop.swift */; };
NRCV00000000000000000009 /* SidebarVisuals.swift in Sources */ = {isa = PBXBuildFile; fileRef = NRCV00000000000000000010 /* SidebarVisuals.swift */; };
NRCV00000000000000000011 /* CommandPaletteController.swift in Sources */ = {isa = PBXBuildFile; fileRef = NRCV00000000000000000012 /* CommandPaletteController.swift */; };
E62155868BB29FEB5DAAAF25 /* SidebarSelectionState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9AD52285508B1D6A9875E7B3 /* SidebarSelectionState.swift */; };
B9000018A1B2C3D4E5F60719 /* WindowDragHandleView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9000017A1B2C3D4E5F60719 /* WindowDragHandleView.swift */; };
A5001003 /* TabManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5001013 /* TabManager.swift */; };
Expand Down Expand Up @@ -243,6 +249,12 @@
A5FF0017 /* SettingDefinition.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingDefinition.swift; sourceTree = "<group>"; };
A5001012 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
A5FF0015 /* ContentView+CommandPalette.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ContentView+CommandPalette.swift"; sourceTree = "<group>"; };
NRCV00000000000000000006 /* TabItemView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabItemView.swift; sourceTree = "<group>"; };
NRCV00000000000000000004 /* FileDropOverlayView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileDropOverlayView.swift; sourceTree = "<group>"; };
NRCV00000000000000000002 /* CommandPaletteSearchEngine.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommandPaletteSearchEngine.swift; sourceTree = "<group>"; };
NRCV00000000000000000008 /* SidebarDragDrop.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SidebarDragDrop.swift; sourceTree = "<group>"; };
NRCV00000000000000000010 /* SidebarVisuals.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SidebarVisuals.swift; sourceTree = "<group>"; };
NRCV00000000000000000012 /* CommandPaletteController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommandPaletteController.swift; sourceTree = "<group>"; };
9AD52285508B1D6A9875E7B3 /* SidebarSelectionState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SidebarSelectionState.swift; sourceTree = "<group>"; };
B9000017A1B2C3D4E5F60719 /* WindowDragHandleView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WindowDragHandleView.swift; sourceTree = "<group>"; };
A5001013 /* TabManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabManager.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -520,6 +532,12 @@
A5FF0017 /* SettingDefinition.swift */,
A5001012 /* ContentView.swift */,
A5FF0015 /* ContentView+CommandPalette.swift */,
NRCV00000000000000000006 /* TabItemView.swift */,
NRCV00000000000000000004 /* FileDropOverlayView.swift */,
NRCV00000000000000000002 /* CommandPaletteSearchEngine.swift */,
NRCV00000000000000000008 /* SidebarDragDrop.swift */,
NRCV00000000000000000010 /* SidebarVisuals.swift */,
NRCV00000000000000000012 /* CommandPaletteController.swift */,
9AD52285508B1D6A9875E7B3 /* SidebarSelectionState.swift */,
B9000017A1B2C3D4E5F60719 /* WindowDragHandleView.swift */,
A50012F0 /* Backport.swift */,
Expand Down Expand Up @@ -858,6 +876,12 @@
A5FF0007 /* SettingDefinition.swift in Sources */,
A5001002 /* ContentView.swift in Sources */,
A5FF0005 /* ContentView+CommandPalette.swift in Sources */,
NRCV00000000000000000005 /* TabItemView.swift in Sources */,
NRCV00000000000000000003 /* FileDropOverlayView.swift in Sources */,
NRCV00000000000000000001 /* CommandPaletteSearchEngine.swift in Sources */,
NRCV00000000000000000007 /* SidebarDragDrop.swift in Sources */,
NRCV00000000000000000009 /* SidebarVisuals.swift in Sources */,
NRCV00000000000000000011 /* CommandPaletteController.swift in Sources */,
E62155868BB29FEB5DAAAF25 /* SidebarSelectionState.swift in Sources */,
B9000018A1B2C3D4E5F60719 /* WindowDragHandleView.swift in Sources */,
A50012F1 /* Backport.swift in Sources */,
Expand Down
73 changes: 73 additions & 0 deletions Sources/CommandPaletteController.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
// Command-palette state ownership, extracted from ContentView.swift (nuclear-review #88).
//
// CommandPaletteController owns every @State property that used to live on
// ContentView and is exclusively used by the command palette (query, mode,
// search corpus/results, rename/workspace-description drafts, focus-restore
// targets, usage history, etc.). ContentView holds a single
// `@StateObject private var commandPaletteController` and exposes each
// property back to its existing (unqualified) call sites in its body via
// thin computed proxies — this keeps the ~4000 lines of palette orchestration
// code that reads/writes these properties unchanged while genuinely moving
// storage ownership onto the controller (no more @State duplicated per-view).
//
// The two @FocusState properties (isCommandPaletteSearchFocused,
// isCommandPaletteRenameFocused) stay on ContentView: @FocusState is a
// SwiftUI View-only property wrapper and cannot be hosted on an
// ObservableObject.
//
// Access-level widening: CommandPaletteMode, CommandPaletteRestoreFocusTarget,
// CommandPaletteTextSelectionBehavior, and CommandPaletteMultilineTextEditorRepresentable
// were `private` nested types inside ContentView; widened to internal (dropped
// the `private` modifier) so this controller (a different file) can reference
// them. No other behavior change. CommandPaletteCommand, CommandPaletteSearchResult,
// CommandPaletteListScope, CommandPalettePendingActivation, and
// CommandPaletteUsageEntry were already internal nested types; referenced here
// via `ContentView.` qualification since nested-type name lookup requires it
// from outside the enclosing type's lexical scope.

import AppKit
import Combine
import SwiftUI

final class CommandPaletteController: ObservableObject {
@Published var isCommandPalettePresented = false
@Published var commandPaletteQuery: String = ""
@Published var commandPaletteMode: ContentView.CommandPaletteMode = .commands
@Published var commandPaletteRenameDraft: String = ""
@Published var commandPaletteWorkspaceDescriptionDraft: String = ""
@Published var commandPaletteWorkspaceDescriptionHeight: CGFloat = ContentView.CommandPaletteMultilineTextEditorRepresentable.defaultMinimumHeight
@Published var commandPaletteSelectedResultIndex: Int = 0
@Published var commandPaletteSelectionAnchorCommandID: String?
@Published var commandPaletteHoveredResultIndex: Int?
@Published var commandPaletteScrollTargetIndex: Int?
@Published var commandPaletteScrollTargetAnchor: UnitPoint?
@Published var commandPaletteRestoreFocusTarget: ContentView.CommandPaletteRestoreFocusTarget?
@Published var commandPaletteSearchCorpus: [CommandPaletteSearchCorpusEntry<String>] = []
@Published var commandPaletteSearchCorpusByID: [String: CommandPaletteSearchCorpusEntry<String>] = [:]
@Published var commandPaletteSearchCommandsByID: [String: ContentView.CommandPaletteCommand] = [:]
@Published var cachedCommandPaletteResults: [ContentView.CommandPaletteSearchResult] = []
@Published var commandPaletteVisibleResults: [ContentView.CommandPaletteSearchResult] = []
@Published var commandPaletteVisibleResultsScope: ContentView.CommandPaletteListScope?
@Published var commandPaletteVisibleResultsFingerprint: Int?
@Published var cachedCommandPaletteScope: ContentView.CommandPaletteListScope?
@Published var cachedCommandPaletteFingerprint: Int?
@Published var commandPalettePendingDismissFocusTarget: ContentView.CommandPaletteRestoreFocusTarget?
@Published var commandPaletteRestoreTimeoutWorkItem: DispatchWorkItem?
@Published var commandPalettePendingTextSelectionBehavior: ContentView.CommandPaletteTextSelectionBehavior?
@Published var commandPaletteSearchTask: Task<Void, Never>?
@Published var commandPaletteSearchRequestID: UInt64 = 0
@Published var commandPaletteResolvedSearchRequestID: UInt64 = 0
@Published var commandPaletteResolvedSearchScope: ContentView.CommandPaletteListScope?
@Published var commandPaletteResolvedSearchFingerprint: Int?
@Published var commandPaletteResolvedMatchingQuery = ""
@Published var commandPaletteTerminalOpenTargetAvailability: Set<TerminalDirectoryOpenTarget> = []
@Published var isCommandPaletteSearchPending = false
@Published var commandPalettePendingActivation: ContentView.CommandPalettePendingActivation?
@Published var commandPaletteResultsRevision: UInt64 = 0
@Published var commandPaletteUsageHistoryByCommandId: [String: ContentView.CommandPaletteUsageEntry] = [:]
@AppStorage(CommandPaletteRenameSelectionSettings.selectAllOnFocusKey)
var commandPaletteRenameSelectAllOnFocus = CommandPaletteRenameSelectionSettings.defaultSelectAllOnFocus
@AppStorage(CommandPaletteSwitcherSearchSettings.searchAllSurfacesKey)
var commandPaletteSearchAllSurfaces = CommandPaletteSwitcherSearchSettings.defaultSearchAllSurfaces
@Published var commandPaletteShouldFocusWorkspaceDescriptionEditor = false
}
Loading
Loading