fix: improve canvas debug status in remote mode

This commit is contained in:
Peter Steinberger
2026-01-01 20:41:13 +00:00
parent dce3bf01fd
commit 952c8c2d64
3 changed files with 63 additions and 6 deletions

View File

@@ -86,6 +86,7 @@
- macOS menu: device list now shows connected nodes only.
- macOS menu: device rows now pack platform/version on the first line, and command lists wrap in submenus.
- macOS menu: split device platform/version across first and second rows for better fit.
- macOS Canvas: show remote control status in the debug overlay and log A2UI auto-nav decisions.
- iOS node: fix ReplayKit screen recording crash caused by queue isolation assertions during capture.
- iOS Talk Mode: avoid audio tap queue assertions when starting recognition.
- macOS: use $HOME/Library/pnpm for SSH PATH exports (thanks @mbelinky).

View File

@@ -151,8 +151,22 @@ final class CanvasManager {
private func handleGatewayPush(_ push: GatewayPush) {
guard case let .snapshot(snapshot) = push else { return }
let a2uiUrl = Self.resolveA2UIHostUrl(from: snapshot.canvashosturl)
guard let controller = self.panelController else { return }
let raw = snapshot.canvashosturl?.trimmingCharacters(in: .whitespacesAndNewlines) ?? ""
if raw.isEmpty {
Self.logger.debug("canvas host url missing in gateway snapshot")
} else {
Self.logger.debug("canvas host url snapshot=\(raw, privacy: .public)")
}
let a2uiUrl = Self.resolveA2UIHostUrl(from: raw)
if a2uiUrl == nil, !raw.isEmpty {
Self.logger.debug("canvas host url invalid; cannot resolve A2UI")
}
guard let controller = self.panelController else {
if a2uiUrl != nil {
Self.logger.debug("canvas panel not visible; skipping auto-nav")
}
return
}
self.maybeAutoNavigateToA2UI(controller: controller, a2uiUrl: a2uiUrl)
}
@@ -169,7 +183,12 @@ final class CanvasManager {
private func maybeAutoNavigateToA2UI(controller: CanvasWindowController, a2uiUrl: String?) {
guard let a2uiUrl else { return }
guard controller.shouldAutoNavigateToA2UI(lastAutoTarget: self.lastAutoA2UIUrl) else { return }
let shouldNavigate = controller.shouldAutoNavigateToA2UI(lastAutoTarget: self.lastAutoA2UIUrl)
guard shouldNavigate else {
Self.logger.debug("canvas auto-nav skipped; target unchanged")
return
}
Self.logger.debug("canvas auto-nav -> \(a2uiUrl, privacy: .public)")
controller.load(target: a2uiUrl)
self.lastAutoA2UIUrl = a2uiUrl
}
@@ -182,8 +201,29 @@ final class CanvasManager {
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
let mode = AppStateStore.shared.connectionMode
let title: String?
let subtitle: String?
switch mode {
case .remote:
title = "Remote control"
switch ControlChannel.shared.state {
case .connected:
subtitle = "Connected"
case .connecting:
subtitle = "Connecting…"
case .disconnected:
subtitle = "Disconnected"
case let .degraded(message):
subtitle = message.isEmpty ? "Degraded" : message
}
case .local:
title = GatewayProcessManager.shared.status.label
subtitle = mode.rawValue
case .unconfigured:
title = "Unconfigured"
subtitle = mode.rawValue
}
controller.updateDebugStatus(enabled: enabled, title: title, subtitle: subtitle)
}

View File

@@ -52,7 +52,23 @@ final class ControlChannel {
case degraded(String)
}
private(set) var state: ConnectionState = .disconnected
private(set) var state: ConnectionState = .disconnected {
didSet {
CanvasManager.shared.refreshDebugStatus()
guard oldValue != state else { return }
switch state {
case .connected:
self.logger.info("control channel state -> connected")
case .connecting:
self.logger.info("control channel state -> connecting")
case .disconnected:
self.logger.info("control channel state -> disconnected")
case let .degraded(message):
let detail = message.isEmpty ? "degraded" : "degraded: \(message)"
self.logger.info("control channel state -> \(detail, privacy: .public)")
}
}
}
private(set) var lastPingMs: Double?
private let logger = Logger(subsystem: "com.steipete.clawdis", category: "control")