feat(macos): surface canvas debug status

This commit is contained in:
Peter Steinberger
2025-12-21 14:20:33 +01:00
parent 7932e966db
commit bcd3c13e2c
4 changed files with 55 additions and 1 deletions

View File

@@ -38,6 +38,7 @@ final class AppState {
var debugPaneEnabled: Bool {
didSet {
self.ifNotPreview { UserDefaults.standard.set(self.debugPaneEnabled, forKey: "clawdis.debugPaneEnabled") }
CanvasManager.shared.refreshDebugStatus()
}
}

View File

@@ -56,6 +56,7 @@ final class CanvasManager {
}
controller.presentAnchoredPanel(anchorProvider: anchorProvider)
controller.applyPreferredPlacement(placement)
self.refreshDebugStatus()
// Existing session: only navigate when an explicit target was provided.
if let normalizedTarget {
@@ -103,6 +104,7 @@ final class CanvasManager {
if normalizedTarget == nil {
self.maybeAutoNavigateToA2UIAsync(controller: controller)
}
self.refreshDebugStatus()
return self.makeShowResult(
directory: controller.directoryPath,
@@ -177,6 +179,14 @@ final class CanvasManager {
return Self.resolveA2UIHostUrl(from: raw)
}
func refreshDebugStatus() {
guard let controller = self.panelController else { return }
let enabled = AppStateStore.shared.debugPaneEnabled
let title = GatewayProcessManager.shared.status.label
let subtitle = AppStateStore.shared.connectionMode.rawValue
controller.updateDebugStatus(enabled: enabled, title: title, subtitle: subtitle)
}
private static func resolveA2UIHostUrl(from raw: String?) -> String? {
let trimmed = raw?.trimmingCharacters(in: .whitespacesAndNewlines) ?? ""
guard !trimmed.isEmpty, let base = URL(string: trimmed) else { return nil }

View File

@@ -44,6 +44,9 @@ final class CanvasWindowController: NSWindowController, WKNavigationDelegate, NS
let presentation: CanvasPresentation
private var preferredPlacement: CanvasPlacement?
private(set) var currentTarget: String?
private var debugStatusEnabled = false
private var debugStatusTitle: String?
private var debugStatusSubtitle: String?
var onVisibilityChanged: ((Bool) -> Void)?
@@ -278,6 +281,35 @@ final class CanvasWindowController: NSWindowController, WKNavigationDelegate, NS
self.webView.load(URLRequest(url: url))
}
func updateDebugStatus(enabled: Bool, title: String?, subtitle: String?) {
self.debugStatusEnabled = enabled
self.debugStatusTitle = title
self.debugStatusSubtitle = subtitle
self.applyDebugStatusIfNeeded()
}
private func applyDebugStatusIfNeeded() {
let enabled = self.debugStatusEnabled
let title = Self.jsOptionalStringLiteral(self.debugStatusTitle)
let subtitle = Self.jsOptionalStringLiteral(self.debugStatusSubtitle)
let js = """
(() => {
try {
const api = globalThis.__clawdis;
if (!api) return;
if (typeof api.setDebugStatusEnabled === 'function') {
api.setDebugStatusEnabled(\(enabled ? "true" : "false"));
}
if (!\(enabled ? "true" : "false")) return;
if (typeof api.setStatus === 'function') {
api.setStatus(\(title), \(subtitle));
}
} catch (_) {}
})();
"""
self.webView.evaluateJavaScript(js) { _, _ in }
}
private func loadFile(_ url: URL) {
let fileURL = url.isFileURL ? url : URL(fileURLWithPath: url.path)
let accessDir = fileURL.deletingLastPathComponent()
@@ -551,6 +583,10 @@ final class CanvasWindowController: NSWindowController, WKNavigationDelegate, NS
decisionHandler(.cancel)
}
func webView(_: WKWebView, didFinish _: WKNavigation?) {
self.applyDebugStatusIfNeeded()
}
// MARK: - NSWindowDelegate
func windowWillClose(_: Notification) {
@@ -585,6 +621,11 @@ final class CanvasWindowController: NSWindowController, WKNavigationDelegate, NS
return data.flatMap { String(data: $0, encoding: .utf8) } ?? "\"\""
}
private static func jsOptionalStringLiteral(_ value: String?) -> String {
guard let value else { return "null" }
return Self.jsStringLiteral(value)
}
private static func storedFrameDefaultsKey(sessionKey: String) -> String {
"clawdis.canvas.frame.\(self.sanitizeSessionKey(sessionKey))"
}

View File

@@ -30,7 +30,9 @@ final class GatewayProcessManager {
}
}
private(set) var status: Status = .stopped
private(set) var status: Status = .stopped {
didSet { CanvasManager.shared.refreshDebugStatus() }
}
private(set) var log: String = ""
private(set) var environmentStatus: GatewayEnvironmentStatus = .checking
private(set) var existingGatewayDetails: String?