From 6675c273fdfea01d2113b3d926ceea9e57c1d272 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Tue, 9 Dec 2025 21:41:24 +0100 Subject: [PATCH] mac: panel highlight when webchat open --- apps/macos/Sources/Clawdis/MenuBar.swift | 4 ++++ .../macos/Sources/Clawdis/WebChatWindow.swift | 23 +++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/apps/macos/Sources/Clawdis/MenuBar.swift b/apps/macos/Sources/Clawdis/MenuBar.swift index 90835f730..719a7262d 100644 --- a/apps/macos/Sources/Clawdis/MenuBar.swift +++ b/apps/macos/Sources/Clawdis/MenuBar.swift @@ -59,6 +59,10 @@ struct ClawdisApp: App { guard let button = item.button else { return } if button.subviews.contains(where: { $0 is StatusItemMouseHandlerView }) { return } + WebChatManager.shared.onPanelVisibilityChanged = { [self] visible in + self.statusItem?.button?.highlight(visible) + } + let handler = StatusItemMouseHandlerView() handler.translatesAutoresizingMaskIntoConstraints = false handler.onLeftClick = { [self] in self.toggleWebChatPanel() } diff --git a/apps/macos/Sources/Clawdis/WebChatWindow.swift b/apps/macos/Sources/Clawdis/WebChatWindow.swift index 2e613635b..ba29d56d1 100644 --- a/apps/macos/Sources/Clawdis/WebChatWindow.swift +++ b/apps/macos/Sources/Clawdis/WebChatWindow.swift @@ -26,6 +26,8 @@ final class WebChatWindowController: NSWindowController, WKNavigationDelegate, N private var reachabilityTask: Task? private var tunnelRestartEnabled = false let presentation: WebChatPresentation + var onPanelClosed: (() -> Void)? + private var panelCloseNotified = false init(sessionKey: String, presentation: WebChatPresentation = .window) { webChatLogger.debug("init WebChatWindowController sessionKey=\(sessionKey, privacy: .public)") @@ -217,6 +219,7 @@ final class WebChatWindowController: NSWindowController, WKNavigationDelegate, N func presentAnchoredPanel(anchorProvider: @escaping () -> NSRect?) { guard case .panel = self.presentation, let window else { return } + self.panelCloseNotified = false self.repositionPanel(using: anchorProvider) window.makeKeyAndOrderFront(nil) NSApp.activate(ignoringOtherApps: true) @@ -226,6 +229,7 @@ final class WebChatWindowController: NSWindowController, WKNavigationDelegate, N func closePanel() { guard case .panel = self.presentation else { return } self.window?.orderOut(nil) + self.notifyPanelClosedOnce() } private func repositionPanel(using anchorProvider: () -> NSRect?) { @@ -268,6 +272,13 @@ final class WebChatWindowController: NSWindowController, WKNavigationDelegate, N func windowDidResignKey(_ notification: Notification) { guard case .panel = self.presentation else { return } self.closePanel() + self.notifyPanelClosedOnce() + } + + private func notifyPanelClosedOnce() { + guard !self.panelCloseNotified else { return } + self.panelCloseNotified = true + self.onPanelClosed?() } } @@ -310,11 +321,13 @@ extension WebChatWindowController { final class WebChatManager { static let shared = WebChatManager() private var controller: WebChatWindowController? + var onPanelVisibilityChanged: ((Bool) -> Void)? func show(sessionKey: String) { if self.controller == nil { self.controller = WebChatWindowController(sessionKey: sessionKey) } + self.onPanelVisibilityChanged?(false) self.controller?.showWindow(nil) self.controller?.window?.makeKeyAndOrderFront(nil) NSApp.activate(ignoringOtherApps: true) @@ -334,7 +347,11 @@ final class WebChatManager { let controller = WebChatWindowController(sessionKey: sessionKey, presentation: .panel(anchorProvider: anchorProvider)) self.controller = controller + controller.onPanelClosed = { [weak self] in + self?.panelClosed() + } controller.presentAnchoredPanel(anchorProvider: anchorProvider) + self.onPanelVisibilityChanged?(true) } func closePanel() { @@ -342,6 +359,7 @@ final class WebChatManager { controller.shutdown() controller.closePanel() self.controller = nil + self.onPanelVisibilityChanged?(false) } func preferredSessionKey() -> String { @@ -367,6 +385,11 @@ final class WebChatManager { self.controller?.close() self.controller = nil } + + private func panelClosed() { + self.onPanelVisibilityChanged?(false) + self.controller = nil + } } // MARK: - Port forwarding tunnel