Implement WatchConnectivity relay bridge
This commit is contained in:
@@ -0,0 +1,87 @@
|
||||
#if os(iOS)
|
||||
import Foundation
|
||||
import RemoteCore
|
||||
import WatchBridgeCommon
|
||||
import WatchConnectivity
|
||||
|
||||
@MainActor
|
||||
private final class PhoneWCSessionSending: RelaySessionSending {
|
||||
private let session: WCSession
|
||||
|
||||
init(session: WCSession) { self.session = session }
|
||||
|
||||
var activationState: RelayActivationState {
|
||||
switch session.activationState {
|
||||
case .notActivated: return .notActivated
|
||||
case .inactive: return .inactive
|
||||
case .activated: return .activated
|
||||
@unknown default: return .inactive
|
||||
}
|
||||
}
|
||||
|
||||
var isReachable: Bool { session.isReachable }
|
||||
func activate() { session.activate() }
|
||||
func sendMessage(_ message: [String: Any],
|
||||
replyHandler: @escaping ([String: Any]) -> Void,
|
||||
errorHandler: @escaping (Error) -> Void) {
|
||||
session.sendMessage(message, replyHandler: replyHandler, errorHandler: errorHandler)
|
||||
}
|
||||
func updateApplicationContext(_ context: [String: Any]) throws {
|
||||
try session.updateApplicationContext(context)
|
||||
}
|
||||
}
|
||||
|
||||
/// iPhone-side WCSession delegate. All UI-facing state changes are hopped to
|
||||
/// the main actor; semantic command admission remains in the injected actor.
|
||||
@MainActor
|
||||
public final class PhoneWCSessionDelegate: NSObject, WCSessionDelegate {
|
||||
public let bridge: PhoneRelayBridge
|
||||
private let session: WCSession
|
||||
|
||||
public init(coordinator: any PhoneCommandCoordinating,
|
||||
session: WCSession = .default) {
|
||||
self.session = session
|
||||
self.bridge = PhoneRelayBridge(session: PhoneWCSessionSending(session: session),
|
||||
dependency: PhoneRelayDependency(coordinator: coordinator))
|
||||
super.init()
|
||||
session.delegate = self
|
||||
bridge.activate()
|
||||
}
|
||||
|
||||
nonisolated public func session(_ session: WCSession,
|
||||
activationDidCompleteWith activationState: WCSessionActivationState,
|
||||
error: Error?) {
|
||||
Task { @MainActor [weak self] in self?.bridge.activationDidComplete(error: error) }
|
||||
}
|
||||
|
||||
nonisolated public func sessionDidBecomeInactive(_ session: WCSession) {
|
||||
Task { @MainActor [weak self] in self?.bridge.didBecomeInactive() }
|
||||
}
|
||||
|
||||
nonisolated public func sessionDidDeactivate(_ session: WCSession) {
|
||||
Task { @MainActor [weak self] in
|
||||
guard let self else { return }
|
||||
self.bridge.didDeactivate()
|
||||
self.session.activate()
|
||||
}
|
||||
}
|
||||
|
||||
nonisolated public func sessionReachabilityDidChange(_ session: WCSession) {
|
||||
Task { @MainActor [weak self] in self?.bridge.reachabilityDidChange() }
|
||||
}
|
||||
|
||||
nonisolated public func session(_ session: WCSession,
|
||||
didReceiveMessage message: [String: Any],
|
||||
replyHandler: @escaping ([String: Any]) -> Void) {
|
||||
let inbound = RelayInboundMessage(message: message, replyHandler: replyHandler)
|
||||
Task { @MainActor [weak self, inbound] in
|
||||
guard let self else {
|
||||
inbound.reply.reply(relayErrorReply(RelayFailure(code: .unavailable)))
|
||||
return
|
||||
}
|
||||
self.bridge.receive(message: inbound.message,
|
||||
replyHandler: inbound.reply.reply)
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
Reference in New Issue
Block a user