@@ -450,25 +450,34 @@ public class StreamVideo: ObservableObject, @unchecked Sendable {
450450 } else {
451451 throw ClientError . Unknown ( )
452452 }
453- var connected = false
454- var timeout = false
455- let control = DefaultTimer . schedule ( timeInterval: 30 , queue: . sdk) {
456- timeout = true
457- }
458- log. debug ( " Listening for WS connection " )
459- webSocketClient? . onConnected = {
460- control. cancel ( )
461- connected = true
462- log. debug ( " WS connected " )
463- }
464453
465- while ( !connected && !timeout) {
466- try await Task . sleep ( nanoseconds: 100_000 )
467- }
468-
469- if timeout {
470- log. debug ( " Timeout while waiting for WS connection opening " )
471- throw ClientError . NetworkError ( )
454+ log. debug ( " Listening for WS connection " )
455+ var continuationHandler : ( ( ) -> Void ) ? = nil
456+ try await withThrowingTaskGroup ( of: Void . self) { group in
457+ group. addTask {
458+ try await Task . sleep ( nanoseconds: 30 * 1_000_000_000 )
459+ log. debug ( " Timeout while waiting for WS connection opening " )
460+ continuationHandler = nil
461+ throw ClientError . NetworkError ( )
462+ }
463+ group. addTask {
464+ try await withCheckedThrowingContinuation { ( continuation: CheckedContinuation < Void , Error > ) in
465+ continuationHandler = {
466+ continuation. resume ( returning: ( ) )
467+ }
468+ webSocketClient? . onConnected = { [ weak self] in
469+ self ? . log. debug ( " WS connected " )
470+ // Only resume if the handler still exists
471+ if let continuationHandler {
472+ continuationHandler ( )
473+ continuationHandler = nil
474+ }
475+ }
476+ }
477+ }
478+ // race between “onConnected” and 30s timeout: whichever finishes first “wins”
479+ try await group. next ( )
480+ group. cancelAll ( )
472481 }
473482 }
474483
0 commit comments