diff --git a/apps/macos/Sources/Clawdis/AppState.swift b/apps/macos/Sources/Clawdis/AppState.swift index 315e59568..2528406fc 100644 --- a/apps/macos/Sources/Clawdis/AppState.swift +++ b/apps/macos/Sources/Clawdis/AppState.swift @@ -160,6 +160,9 @@ final class AppState { didSet { self.ifNotPreview { UserDefaults.standard.set(self.canvasEnabled, forKey: canvasEnabledKey) } } } + /// Tracks whether the Canvas panel is currently visible (not persisted). + var canvasPanelVisible: Bool = false + var peekabooBridgeEnabled: Bool { didSet { self.ifNotPreview { diff --git a/apps/macos/Sources/Clawdis/CanvasManager.swift b/apps/macos/Sources/Clawdis/CanvasManager.swift index 60d68829e..57c614280 100644 --- a/apps/macos/Sources/Clawdis/CanvasManager.swift +++ b/apps/macos/Sources/Clawdis/CanvasManager.swift @@ -9,6 +9,8 @@ final class CanvasManager { private var panelController: CanvasWindowController? private var panelSessionKey: String? + var onPanelVisibilityChanged: ((Bool) -> Void)? + /// Optional anchor provider (e.g. menu bar status item). If nil, Canvas anchors to the mouse cursor. var defaultAnchorProvider: (() -> NSRect?)? @@ -29,6 +31,9 @@ final class CanvasManager { .nonEmpty if let controller = self.panelController, self.panelSessionKey == session { + controller.onVisibilityChanged = { [weak self] visible in + self?.onPanelVisibilityChanged?(visible) + } controller.presentAnchoredPanel(anchorProvider: anchorProvider) controller.applyPreferredPlacement(placement) @@ -58,6 +63,9 @@ final class CanvasManager { sessionKey: session, root: Self.canvasRoot, presentation: .panel(anchorProvider: anchorProvider)) + controller.onVisibilityChanged = { [weak self] visible in + self?.onPanelVisibilityChanged?(visible) + } self.panelController = controller self.panelSessionKey = session controller.applyPreferredPlacement(placement) diff --git a/apps/macos/Sources/Clawdis/MenuBar.swift b/apps/macos/Sources/Clawdis/MenuBar.swift index 4ee817a7e..106d651e3 100644 --- a/apps/macos/Sources/Clawdis/MenuBar.swift +++ b/apps/macos/Sources/Clawdis/MenuBar.swift @@ -81,6 +81,9 @@ struct ClawdisApp: App { self.isPanelVisible = visible self.updateStatusHighlight() } + CanvasManager.shared.onPanelVisibilityChanged = { [self] visible in + self.state.canvasPanelVisible = visible + } CanvasManager.shared.defaultAnchorProvider = { [self] in self.statusButtonScreenFrame() } let handler = StatusItemMouseHandlerView() diff --git a/apps/macos/Sources/Clawdis/MenuContentView.swift b/apps/macos/Sources/Clawdis/MenuContentView.swift index 556c2b693..c85f9bd7c 100644 --- a/apps/macos/Sources/Clawdis/MenuContentView.swift +++ b/apps/macos/Sources/Clawdis/MenuContentView.swift @@ -63,6 +63,15 @@ struct MenuContent: View { CanvasManager.shared.hideAll() } } + if self.state.canvasEnabled { + Button(self.state.canvasPanelVisible ? "Close Canvas" : "Open Canvas") { + if self.state.canvasPanelVisible { + CanvasManager.shared.hideAll() + } else { + _ = try? CanvasManager.shared.show(sessionKey: "main", path: "/") + } + } + } Divider() Button("Settings…") { self.open(tab: .general) } .keyboardShortcut(",", modifiers: [.command])