Files
wristivo/Adapters/WatchBridge/Sources/iPhone/PhoneWCSessionDelegate.swift
T

88 lines
3.3 KiB
Swift

#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