// // WatchConnectivityClient.swift // FantasyWatch Watch App // // Created by Claude Code // import ComposableArchitecture import Foundation import WatchConnectivity @DependencyClient struct WatchConnectivityClient { var matchupUpdates: @Sendable () -> AsyncStream<(Matchup, RosterStatus, Date)> var requestRefresh: @Sendable () async throws -> Void } extension WatchConnectivityClient: DependencyKey { static let liveValue: WatchConnectivityClient = { let manager = WatchConnectivityManager() return Self( matchupUpdates: { manager.matchupUpdatesStream() }, requestRefresh: { try await manager.requestRefresh() } ) }() static let testValue = Self( matchupUpdates: { AsyncStream { continuation in continuation.yield(( Matchup( week: 1, status: "midevent", userTeam: TeamScore(teamKey: "test.l.123.t.1", teamName: "Test Team", wins: 5, losses: 3, ties: 1), opponentTeam: TeamScore(teamKey: "test.l.123.t.2", teamName: "Opponent", wins: 4, losses: 4, ties: 1), categories: [] ), RosterStatus(activeCount: 10, benchedCount: 5, injuredReserve: 2), Date() )) } }, requestRefresh: {} ) } extension DependencyValues { var watchConnectivityClient: WatchConnectivityClient { get { self[WatchConnectivityClient.self] } set { self[WatchConnectivityClient.self] = newValue } } } // MARK: - Watch Connectivity Manager final class WatchConnectivityManager: NSObject, WCSessionDelegate { private var session: WCSession? private var updatesContinuation: AsyncStream<(Matchup, RosterStatus, Date)>.Continuation? override init() { super.init() guard WCSession.isSupported() else { return } session = WCSession.default session?.delegate = self session?.activate() } func matchupUpdatesStream() -> AsyncStream<(Matchup, RosterStatus, Date)> { AsyncStream { continuation in self.updatesContinuation = continuation if let context = session?.receivedApplicationContext, let data = context["payload"] as? Data, let payload = try? JSONDecoder().decode(WatchPayload.self, from: data) { continuation.yield((payload.matchup, payload.roster, payload.timestamp)) } } } func requestRefresh() async throws { guard let session = session, session.activationState == .activated else { throw NetworkError.networkFailure( NSError(domain: "WatchConnectivity", code: -1, userInfo: [NSLocalizedDescriptionKey: "Watch session not active"]) ) } let message = ["type": WatchMessage.refreshRequest.rawValue] session.sendMessage(message, replyHandler: nil) { error in print("Failed to send refresh request: \(error.localizedDescription)") } } // MARK: - WCSessionDelegate func session(_ session: WCSession, activationDidCompleteWith activationState: WCSessionActivationState, error: Error?) { if let error = error { print("Watch session activation failed: \(error.localizedDescription)") } } func session(_ session: WCSession, didReceiveApplicationContext applicationContext: [String : Any]) { guard let data = applicationContext["payload"] as? Data, let payload = try? JSONDecoder().decode(WatchPayload.self, from: data) else { return } updatesContinuation?.yield((payload.matchup, payload.roster, payload.timestamp)) } }