feat(macos): surface canvas debug status
parent
7932e966db
commit
bcd3c13e2c
|
|
@ -38,6 +38,7 @@ final class AppState {
|
||||||
var debugPaneEnabled: Bool {
|
var debugPaneEnabled: Bool {
|
||||||
didSet {
|
didSet {
|
||||||
self.ifNotPreview { UserDefaults.standard.set(self.debugPaneEnabled, forKey: "clawdis.debugPaneEnabled") }
|
self.ifNotPreview { UserDefaults.standard.set(self.debugPaneEnabled, forKey: "clawdis.debugPaneEnabled") }
|
||||||
|
CanvasManager.shared.refreshDebugStatus()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -56,6 +56,7 @@ final class CanvasManager {
|
||||||
}
|
}
|
||||||
controller.presentAnchoredPanel(anchorProvider: anchorProvider)
|
controller.presentAnchoredPanel(anchorProvider: anchorProvider)
|
||||||
controller.applyPreferredPlacement(placement)
|
controller.applyPreferredPlacement(placement)
|
||||||
|
self.refreshDebugStatus()
|
||||||
|
|
||||||
// Existing session: only navigate when an explicit target was provided.
|
// Existing session: only navigate when an explicit target was provided.
|
||||||
if let normalizedTarget {
|
if let normalizedTarget {
|
||||||
|
|
@ -103,6 +104,7 @@ final class CanvasManager {
|
||||||
if normalizedTarget == nil {
|
if normalizedTarget == nil {
|
||||||
self.maybeAutoNavigateToA2UIAsync(controller: controller)
|
self.maybeAutoNavigateToA2UIAsync(controller: controller)
|
||||||
}
|
}
|
||||||
|
self.refreshDebugStatus()
|
||||||
|
|
||||||
return self.makeShowResult(
|
return self.makeShowResult(
|
||||||
directory: controller.directoryPath,
|
directory: controller.directoryPath,
|
||||||
|
|
@ -177,6 +179,14 @@ final class CanvasManager {
|
||||||
return Self.resolveA2UIHostUrl(from: raw)
|
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? {
|
private static func resolveA2UIHostUrl(from raw: String?) -> String? {
|
||||||
let trimmed = raw?.trimmingCharacters(in: .whitespacesAndNewlines) ?? ""
|
let trimmed = raw?.trimmingCharacters(in: .whitespacesAndNewlines) ?? ""
|
||||||
guard !trimmed.isEmpty, let base = URL(string: trimmed) else { return nil }
|
guard !trimmed.isEmpty, let base = URL(string: trimmed) else { return nil }
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,9 @@ final class CanvasWindowController: NSWindowController, WKNavigationDelegate, NS
|
||||||
let presentation: CanvasPresentation
|
let presentation: CanvasPresentation
|
||||||
private var preferredPlacement: CanvasPlacement?
|
private var preferredPlacement: CanvasPlacement?
|
||||||
private(set) var currentTarget: String?
|
private(set) var currentTarget: String?
|
||||||
|
private var debugStatusEnabled = false
|
||||||
|
private var debugStatusTitle: String?
|
||||||
|
private var debugStatusSubtitle: String?
|
||||||
|
|
||||||
var onVisibilityChanged: ((Bool) -> Void)?
|
var onVisibilityChanged: ((Bool) -> Void)?
|
||||||
|
|
||||||
|
|
@ -278,6 +281,35 @@ final class CanvasWindowController: NSWindowController, WKNavigationDelegate, NS
|
||||||
self.webView.load(URLRequest(url: url))
|
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) {
|
private func loadFile(_ url: URL) {
|
||||||
let fileURL = url.isFileURL ? url : URL(fileURLWithPath: url.path)
|
let fileURL = url.isFileURL ? url : URL(fileURLWithPath: url.path)
|
||||||
let accessDir = fileURL.deletingLastPathComponent()
|
let accessDir = fileURL.deletingLastPathComponent()
|
||||||
|
|
@ -551,6 +583,10 @@ final class CanvasWindowController: NSWindowController, WKNavigationDelegate, NS
|
||||||
decisionHandler(.cancel)
|
decisionHandler(.cancel)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func webView(_: WKWebView, didFinish _: WKNavigation?) {
|
||||||
|
self.applyDebugStatusIfNeeded()
|
||||||
|
}
|
||||||
|
|
||||||
// MARK: - NSWindowDelegate
|
// MARK: - NSWindowDelegate
|
||||||
|
|
||||||
func windowWillClose(_: Notification) {
|
func windowWillClose(_: Notification) {
|
||||||
|
|
@ -585,6 +621,11 @@ final class CanvasWindowController: NSWindowController, WKNavigationDelegate, NS
|
||||||
return data.flatMap { String(data: $0, encoding: .utf8) } ?? "\"\""
|
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 {
|
private static func storedFrameDefaultsKey(sessionKey: String) -> String {
|
||||||
"clawdis.canvas.frame.\(self.sanitizeSessionKey(sessionKey))"
|
"clawdis.canvas.frame.\(self.sanitizeSessionKey(sessionKey))"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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 log: String = ""
|
||||||
private(set) var environmentStatus: GatewayEnvironmentStatus = .checking
|
private(set) var environmentStatus: GatewayEnvironmentStatus = .checking
|
||||||
private(set) var existingGatewayDetails: String?
|
private(set) var existingGatewayDetails: String?
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue