#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