#if os(watchOS) import Foundation import RemoteCore import WatchBridgeCommon import WatchConnectivity @MainActor private final class WatchWCSessionSending: 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) } } /// Separate watchOS delegate. The app remains foreground/active for gesture /// use; this delegate does not add a background mode or deferred command queue. @MainActor public final class WatchWCSessionDelegate: NSObject, WCSessionDelegate { public let bridge: WatchRelayBridge public init(session: WCSession = .default) { bridge = WatchRelayBridge(session: WatchWCSessionSending(session: session)) super.init() session.delegate = self bridge.activate() } nonisolated public func session(_ session: WCSession, activationDidCompleteWith activationState: WCSessionActivationState, error: Error?) { Task { @MainActor [weak self] in guard let self else { return } if case .inactive = self.bridge.state { } else { self.bridge.didDeactivate() } self.bridge.activationDidComplete(error: error) } } 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) { // The watch is the request sender in v1; never execute a phone reply // as a request. Complete unexpected inbound traffic exactly once. RelayReplyOnce(replyHandler).reply( relayErrorReply(RelayFailure(code: .malformedRequest))) } } #endif