iOS: centralize canvas commands and capabilities
parent
c976799f8c
commit
33bf5cf42a
|
|
@ -155,17 +155,17 @@ final class BridgeConnectionController {
|
||||||
}
|
}
|
||||||
|
|
||||||
private func currentCaps() -> [String] {
|
private func currentCaps() -> [String] {
|
||||||
var caps = ["canvas"]
|
var caps = [ClawdisCapability.canvas.rawValue]
|
||||||
|
|
||||||
// Default-on: if the key doesn't exist yet, treat it as enabled.
|
// Default-on: if the key doesn't exist yet, treat it as enabled.
|
||||||
let cameraEnabled =
|
let cameraEnabled =
|
||||||
UserDefaults.standard.object(forKey: "camera.enabled") == nil
|
UserDefaults.standard.object(forKey: "camera.enabled") == nil
|
||||||
? true
|
? true
|
||||||
: UserDefaults.standard.bool(forKey: "camera.enabled")
|
: UserDefaults.standard.bool(forKey: "camera.enabled")
|
||||||
if cameraEnabled { caps.append("camera") }
|
if cameraEnabled { caps.append(ClawdisCapability.camera.rawValue) }
|
||||||
|
|
||||||
let voiceWakeEnabled = UserDefaults.standard.bool(forKey: VoiceWakePreferences.enabledKey)
|
let voiceWakeEnabled = UserDefaults.standard.bool(forKey: VoiceWakePreferences.enabledKey)
|
||||||
if voiceWakeEnabled { caps.append("voiceWake") }
|
if voiceWakeEnabled { caps.append(ClawdisCapability.voiceWake.rawValue) }
|
||||||
|
|
||||||
return caps
|
return caps
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -266,12 +266,7 @@ final class NodeAppModel {
|
||||||
|
|
||||||
private func handleInvoke(_ req: BridgeInvokeRequest) async -> BridgeInvokeResponse {
|
private func handleInvoke(_ req: BridgeInvokeRequest) async -> BridgeInvokeResponse {
|
||||||
// Alias for "canvas" capability: accept canvas.* commands and map them to screen.*.
|
// Alias for "canvas" capability: accept canvas.* commands and map them to screen.*.
|
||||||
let command =
|
let command = ClawdisInvokeCommandAliases.canonicalizeCanvasToScreen(req.command)
|
||||||
if req.command.hasPrefix("canvas.") {
|
|
||||||
"screen." + req.command.dropFirst("canvas.".count)
|
|
||||||
} else {
|
|
||||||
req.command
|
|
||||||
}
|
|
||||||
|
|
||||||
if command.hasPrefix("screen.") || command.hasPrefix("camera."), self.isBackgrounded {
|
if command.hasPrefix("screen.") || command.hasPrefix("camera."), self.isBackgrounded {
|
||||||
return BridgeInvokeResponse(
|
return BridgeInvokeResponse(
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,38 @@
|
||||||
|
import ClawdisKit
|
||||||
|
import Testing
|
||||||
|
|
||||||
|
@Suite struct CanvasCommandAliasTests {
|
||||||
|
@Test func mapsKnownCanvasCommandsToScreen() {
|
||||||
|
let mappings: [(ClawdisCanvasCommand, ClawdisScreenCommand)] = [
|
||||||
|
(.show, .show),
|
||||||
|
(.hide, .hide),
|
||||||
|
(.setMode, .setMode),
|
||||||
|
(.navigate, .navigate),
|
||||||
|
(.evalJS, .evalJS),
|
||||||
|
(.snapshot, .snapshot),
|
||||||
|
]
|
||||||
|
|
||||||
|
for (canvas, screen) in mappings {
|
||||||
|
#expect(
|
||||||
|
ClawdisInvokeCommandAliases.canonicalizeCanvasToScreen(canvas.rawValue) ==
|
||||||
|
screen.rawValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test func mapsUnknownCanvasNamespaceToScreen() {
|
||||||
|
#expect(ClawdisInvokeCommandAliases.canonicalizeCanvasToScreen("canvas.foo") == "screen.foo")
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test func leavesNonCanvasCommandsUnchanged() {
|
||||||
|
#expect(
|
||||||
|
ClawdisInvokeCommandAliases.canonicalizeCanvasToScreen(ClawdisCameraCommand.snap.rawValue) ==
|
||||||
|
ClawdisCameraCommand.snap.rawValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test func capabilitiesUseStableStrings() {
|
||||||
|
#expect(ClawdisCapability.canvas.rawValue == "canvas")
|
||||||
|
#expect(ClawdisCapability.camera.rawValue == "camera")
|
||||||
|
#expect(ClawdisCapability.voiceWake.rawValue == "voiceWake")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
public enum ClawdisCanvasCommand: String, Codable, Sendable {
|
||||||
|
case show = "canvas.show"
|
||||||
|
case hide = "canvas.hide"
|
||||||
|
case setMode = "canvas.setMode"
|
||||||
|
case navigate = "canvas.navigate"
|
||||||
|
case evalJS = "canvas.eval"
|
||||||
|
case snapshot = "canvas.snapshot"
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum ClawdisInvokeCommandAliases {
|
||||||
|
public static func canonicalizeCanvasToScreen(_ command: String) -> String {
|
||||||
|
if command.hasPrefix(ClawdisCanvasCommand.namespacePrefix) {
|
||||||
|
return ClawdisScreenCommand.namespacePrefix +
|
||||||
|
command.dropFirst(ClawdisCanvasCommand.namespacePrefix.count)
|
||||||
|
}
|
||||||
|
return command
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension ClawdisCanvasCommand {
|
||||||
|
public static var namespacePrefix: String { "canvas." }
|
||||||
|
}
|
||||||
|
|
||||||
|
extension ClawdisScreenCommand {
|
||||||
|
public static var namespacePrefix: String { "screen." }
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
public enum ClawdisCapability: String, Codable, Sendable {
|
||||||
|
case canvas
|
||||||
|
case camera
|
||||||
|
case voiceWake
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue