Integrate live phone and watch remote prototype with guarded motion control
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import Foundation
|
||||
import CoreFoundation
|
||||
import RemoteCore
|
||||
|
||||
private func relayNSNumberIsBoolean(_ value: NSNumber) -> Bool {
|
||||
@@ -88,22 +89,24 @@ public struct RelayApplicationContext: Sendable, Equatable {
|
||||
public let schemaVersion: Int
|
||||
public let selectedTelevisionID: UUID?
|
||||
public let displayName: String?
|
||||
public let isConnectionReady: Bool
|
||||
|
||||
public init(selectedTelevisionID: UUID?, displayName: String?) {
|
||||
public init(selectedTelevisionID: UUID?, displayName: String?, isConnectionReady: Bool = false) {
|
||||
self.schemaVersion = RelayWire.schemaVersion
|
||||
self.selectedTelevisionID = selectedTelevisionID
|
||||
self.displayName = displayName
|
||||
self.isConnectionReady = isConnectionReady && selectedTelevisionID != nil
|
||||
}
|
||||
|
||||
public func dictionary() throws -> [String: Any] {
|
||||
var result: [String: Any] = ["schemaVersion": schemaVersion]
|
||||
var result: [String: Any] = ["schemaVersion": schemaVersion, "isConnectionReady": isConnectionReady]
|
||||
if let selectedTelevisionID { result["selectedTelevisionID"] = selectedTelevisionID.uuidString }
|
||||
if let displayName { result["displayName"] = String(displayName.prefix(128)) }
|
||||
return result
|
||||
}
|
||||
|
||||
public init(dictionary: [String: Any]) throws {
|
||||
let allowed: Set<String> = ["schemaVersion", "selectedTelevisionID", "displayName"]
|
||||
let allowed: Set<String> = ["schemaVersion", "selectedTelevisionID", "displayName", "isConnectionReady"]
|
||||
guard Set(dictionary.keys).isSubset(of: allowed) else { throw RelayContainerError.extraKeys }
|
||||
guard let version = dictionary["schemaVersion"] as? NSNumber,
|
||||
relayNSNumberIsInteger(version),
|
||||
@@ -127,6 +130,12 @@ public struct RelayApplicationContext: Sendable, Equatable {
|
||||
} else {
|
||||
self.displayName = nil
|
||||
}
|
||||
if let raw = dictionary["isConnectionReady"] {
|
||||
guard let number = raw as? NSNumber, CFGetTypeID(number) == CFBooleanGetTypeID() else {
|
||||
throw RelayContainerError.invalidPayload
|
||||
}
|
||||
self.isConnectionReady = number.boolValue && selectedTelevisionID != nil
|
||||
} else { self.isConnectionReady = false }
|
||||
self.schemaVersion = version.intValue
|
||||
}
|
||||
}
|
||||
@@ -168,12 +177,13 @@ public final class RelayReplyOnce: @unchecked Sendable {
|
||||
/// a delegate context. This explicit boundary lets the native delegate hop to
|
||||
/// the main actor without pretending the dictionary itself is Sendable.
|
||||
public final class RelayInboundMessage: @unchecked Sendable {
|
||||
public let message: [String: Any]
|
||||
private let container: RelayContainer?
|
||||
public var message: [String: Any] { container?.dictionary() ?? [:] }
|
||||
public let reply: RelayReplyOnce
|
||||
|
||||
public init(message: [String: Any],
|
||||
replyHandler: @escaping ([String: Any]) -> Void) {
|
||||
self.message = message
|
||||
self.container = try? RelayContainer(dictionary: message)
|
||||
self.reply = RelayReplyOnce(replyHandler)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user