// // MainWindowView.swift // Zyquo Agent // // Author: Simon-Pierre Boucher // Mail: contact@spboucher.ai // // The command-center root: translucent 260pt sidebar (NavigationSplitView's // native sidebar material) + the task detail. With no task selected, the // "What should I do on your Mac?" hero creates one. Hosts the ⌘K command // palette overlay and the template browser sheet; the root re-identifies on // accent change so every ZyquoColor.accent token redraws immediately. // import SwiftUI struct MainWindowView: View { @EnvironmentObject private var store: TaskStore @EnvironmentObject private var catalog: ModelCatalog @EnvironmentObject private var appearance: AppearanceStore @EnvironmentObject private var settings: AgentSettingsStore @EnvironmentObject private var templates: TemplateStore @EnvironmentObject private var personas: PersonaStore @EnvironmentObject private var uiState: AppUIState var body: some View { ZStack(alignment: .top) { NavigationSplitView { SidebarView() .navigationSplitViewColumnWidth( min: ZyquoMetrics.sidebarWidth, ideal: ZyquoMetrics.sidebarWidth, max: 360 ) } detail: { if let id = store.selectedID, store.task(id: id) != nil { TaskDetailView(taskID: id) } else { AgentEmptyStateView( model: defaultModel, safetyMode: settings.settings.defaultSafetyMode, personaName: nil, onSelectModel: { model in store.newTask(model: model, safetyMode: settings.settings.defaultSafetyMode) }, onSelectSafetyMode: { mode in store.newTask(model: defaultModel, safetyMode: mode) }, onSelectPersona: { persona in newTask(with: persona) }, onBrowseTemplates: { uiState.showTemplateBrowser = true }, onSuggestion: { prompt in store.pendingDraft = prompt store.newTask(model: defaultModel, safetyMode: settings.settings.defaultSafetyMode) } ) } } if uiState.showCommandPalette { paletteOverlay } } .frame( minWidth: ZyquoMetrics.windowMinWidth, minHeight: ZyquoMetrics.windowMinHeight ) .sheet(isPresented: $uiState.showTemplateBrowser) { TemplateBrowserView { prompt, safetyMode in store.pendingDraft = prompt store.newTask(model: defaultModel, safetyMode: safetyMode) } } .preferredColorScheme(appearance.themeMode.colorScheme) .tint(appearance.accentColor) .id(appearance.accent) } /// New tasks start with the persisted default agent model. private var defaultModel: AIModel? { settings.defaultAgentModel(in: catalog) } private func newTask(with persona: Persona?) { let model: AIModel? if let persona, let id = persona.modelID, let provider = persona.provider, let preferred = catalog.model(id: id, provider: provider) { model = preferred } else { model = defaultModel } store.newTask( model: model, safetyMode: persona?.safetyMode ?? settings.settings.defaultSafetyMode, personaID: persona?.id ) } // MARK: - ⌘K palette private var paletteOverlay: some View { ZStack(alignment: .top) { // Click-away scrim (transparent, keeps the window visible). Color.black.opacity(0.001) .onTapGesture { uiState.showCommandPalette = false } CommandPaletteView(items: paletteItems) { uiState.showCommandPalette = false } .padding(.top, ZyquoSpacing.xxl * 2) } .ignoresSafeArea() .transition(.opacity) } private var paletteItems: [PaletteItem] { var items: [PaletteItem] = [ PaletteItem(id: "action-new-task", kind: .action, title: "New Task", subtitle: "⌘N", symbolName: "plus.circle") { store.newTask(model: defaultModel, safetyMode: settings.settings.defaultSafetyMode) }, PaletteItem(id: "action-settings", kind: .action, title: "Open Settings", subtitle: "⌘,", symbolName: "gearshape") { SettingsOpener.open() }, PaletteItem(id: "action-templates", kind: .action, title: "Browse Templates", subtitle: nil, symbolName: "square.grid.2x2") { uiState.showTemplateBrowser = true }, PaletteItem(id: "action-audit", kind: .action, title: "Open Audit Log", subtitle: "⌘⇧A", symbolName: "list.bullet.rectangle") { uiState.requestAuditLog() }, PaletteItem(id: "action-drawer", kind: .action, title: "Toggle Activity Drawer", subtitle: nil, symbolName: "terminal") { uiState.requestDrawerToggle() }, PaletteItem(id: "action-plan", kind: .action, title: "Toggle Plan Panel", subtitle: nil, symbolName: "sidebar.right") { uiState.requestPlanToggle() }, ] for template in templates.all { items.append(PaletteItem( id: "template-\(template.id.uuidString)", kind: .template, title: template.title, subtitle: template.category.displayName, symbolName: template.displaySymbol ) { if template.variables.isEmpty { store.pendingDraft = template.prompt store.newTask(model: defaultModel, safetyMode: template.suggestedSafetyMode) } else { uiState.showTemplateBrowser = true } }) } for task in store.tasks.prefix(60) { items.append(PaletteItem( id: "task-\(task.id.uuidString)", kind: .task, title: task.title, subtitle: task.status.displayName, symbolName: "checklist" ) { store.selectedID = task.id }) } return items } }