@@ -30,6 +30,7 @@ typedef OnCallPermissionRequest = void Function(
3030typedef GetCurrentUserId = String ? Function ();
3131
3232typedef SetActiveCall = Future <void > Function (Call ? );
33+ typedef GetActiveCallCid = StreamCallCid ? Function ();
3334
3435const _idState = 1 ;
3536const _idUserId = 2 ;
@@ -53,6 +54,7 @@ class Call {
5354 required CoordinatorClient coordinatorClient,
5455 required StateEmitter <User ?> currentUser,
5556 required SetActiveCall setActiveCall,
57+ required GetActiveCallCid getActiveCallCid,
5658 RetryPolicy ? retryPolicy,
5759 SdpPolicy ? sdpPolicy,
5860 CallPreferences ? preferences,
@@ -63,6 +65,7 @@ class Call {
6365 coordinatorClient: coordinatorClient,
6466 currentUser: currentUser,
6567 setActiveCall: setActiveCall,
68+ getActiveCallCid: getActiveCallCid,
6669 retryPolicy: retryPolicy,
6770 sdpPolicy: sdpPolicy,
6871 preferences: preferences,
@@ -77,6 +80,7 @@ class Call {
7780 required CoordinatorClient coordinatorClient,
7881 required StateEmitter <User ?> currentUser,
7982 required SetActiveCall setActiveCall,
83+ required GetActiveCallCid getActiveCallCid,
8084 RetryPolicy ? retryPolicy,
8185 SdpPolicy ? sdpPolicy,
8286 CallPreferences ? preferences,
@@ -87,6 +91,7 @@ class Call {
8791 coordinatorClient: coordinatorClient,
8892 currentUser: currentUser,
8993 setActiveCall: setActiveCall,
94+ getActiveCallCid: getActiveCallCid,
9095 retryPolicy: retryPolicy,
9196 sdpPolicy: sdpPolicy,
9297 preferences: preferences,
@@ -101,6 +106,7 @@ class Call {
101106 required CoordinatorClient coordinatorClient,
102107 required StateEmitter <User ?> currentUser,
103108 required SetActiveCall setActiveCall,
109+ required GetActiveCallCid getActiveCallCid,
104110 RetryPolicy ? retryPolicy,
105111 SdpPolicy ? sdpPolicy,
106112 CallPreferences ? preferences,
@@ -111,6 +117,7 @@ class Call {
111117 coordinatorClient: coordinatorClient,
112118 currentUser: currentUser,
113119 setActiveCall: setActiveCall,
120+ getActiveCallCid: getActiveCallCid,
114121 retryPolicy: retryPolicy,
115122 sdpPolicy: sdpPolicy,
116123 preferences: preferences,
@@ -122,6 +129,7 @@ class Call {
122129 required CoordinatorClient coordinatorClient,
123130 required StateEmitter <User ?> currentUser,
124131 required SetActiveCall setActiveCall,
132+ required GetActiveCallCid getActiveCallCid,
125133 RetryPolicy ? retryPolicy,
126134 SdpPolicy ? sdpPolicy,
127135 CallPreferences ? preferences,
@@ -145,6 +153,7 @@ class Call {
145153 coordinatorClient: coordinatorClient,
146154 currentUser: currentUser,
147155 setActiveCall: setActiveCall,
156+ getActiveCallCid: getActiveCallCid,
148157 preferences: finalCallPreferences,
149158 stateManager: stateManager,
150159 credentials: credentials,
@@ -157,6 +166,7 @@ class Call {
157166 Call ._({
158167 required StateEmitter <User ?> currentUser,
159168 required SetActiveCall setActiveCall,
169+ required GetActiveCallCid getActiveCallCid,
160170 required CoordinatorClient coordinatorClient,
161171 required CallPreferences preferences,
162172 required CallStateNotifier stateManager,
@@ -177,6 +187,7 @@ class Call {
177187 .whereNotNull ()
178188 .distinct (),
179189 _setActiveCall = setActiveCall,
190+ _getActiveCallCid = getActiveCallCid,
180191 _coordinatorClient = coordinatorClient,
181192 _preferences = preferences,
182193 _retryPolicy = retryPolicy,
@@ -196,6 +207,7 @@ class Call {
196207 final GetCurrentUserId _getCurrentUserId;
197208 final Stream <String > _currentUserIdUpdates;
198209 final SetActiveCall _setActiveCall;
210+ final GetActiveCallCid _getActiveCallCid;
199211 final CoordinatorClient _coordinatorClient;
200212 final RetryPolicy _retryPolicy;
201213 final CallPreferences _preferences;
@@ -383,29 +395,35 @@ class Call {
383395
384396 @Deprecated ('Lobby view no longer needs joining to coordinator' )
385397 Future <Result <None >> joinLobby () async {
386- _logger.d (() => '[join ] no args' );
398+ _logger.d (() => '[joinLobby ] no args' );
387399 _stateManager.lifecycleCallJoining (const CallJoining ());
388400 final joinedResult = await _joinIfNeeded ();
389401 if (joinedResult is Success <CallCredentials >) {
390- _logger.v (() => '[join ] completed' );
402+ _logger.v (() => '[joinLobby ] completed' );
391403 return const Result .success (none);
392404 } else {
393405 final failedResult = joinedResult as Failure ;
394- _logger.e (() => '[join ] failed: $failedResult ' );
406+ _logger.e (() => '[joinLobby ] failed: $failedResult ' );
395407 final error = failedResult.error;
396408 _stateManager.lifecycleCallConnectFailed (ConnectFailed (error));
397409 return failedResult;
398410 }
399411 }
400412
401413 Future <Result <None >> join () async {
402- _logger.i (() => '[connect ] status: ${_status .value }' );
414+ _logger.i (() => '[join ] status: ${_status .value }' );
403415 if (_status.value == _ConnectionStatus .connected) {
404- _logger.w (() => '[connect ] rejected (connected)' );
416+ _logger.w (() => '[join ] rejected (connected)' );
405417 return const Result .success (none);
406418 }
419+ if (_getActiveCallCid () == callCid) {
420+ _logger.w (
421+ () => '[join] rejected (a call with the same cid is in progress)' ,
422+ );
423+ return Result .error ('a call with the same cid is in progress' );
424+ }
407425 if (_status.value == _ConnectionStatus .connecting) {
408- _logger.v (() => '[connect ] await "connecting" change' );
426+ _logger.v (() => '[join ] await "connecting" change' );
409427 final status = await _status.firstWhere (
410428 (it) => it != _ConnectionStatus .connecting,
411429 timeLimit: _preferences.connectTimeout,
@@ -423,10 +441,10 @@ class Call {
423441 .storeIn (_idConnect, _cancelables)
424442 .valueOrDefault (Result .error ('connect cancelled' ));
425443 if (result.isSuccess) {
426- _logger.v (() => '[connect ] finished: $result ' );
444+ _logger.v (() => '[join ] finished: $result ' );
427445 _status.value = _ConnectionStatus .connected;
428446 } else {
429- _logger.e (() => '[connect ] failed: $result ' );
447+ _logger.e (() => '[join ] failed: $result ' );
430448 await leave ();
431449 }
432450 return result;
@@ -458,26 +476,26 @@ class Call {
458476 }
459477
460478 Future <Result <None >> _connect () async {
461- _logger.d (() => '[connect ] options: $_connectOptions ' );
479+ _logger.d (() => '[join ] options: $_connectOptions ' );
462480 final validation = await _stateManager.validateUserId (_getCurrentUserId);
463481 if (validation.isFailure) {
464- _logger.w (() => '[connect ] rejected (validation): $validation ' );
482+ _logger.w (() => '[join ] rejected (validation): $validation ' );
465483 return validation;
466484 }
467- _logger.v (() => '[connect ] validated' );
485+ _logger.v (() => '[join ] validated' );
468486
469487 final state = this .state.value;
470488 final status = state.status;
471489 if (! status.isConnectable) {
472- _logger.w (() => '[connect ] rejected (not Connectable): $status ' );
490+ _logger.w (() => '[join ] rejected (not Connectable): $status ' );
473491 return Result .error ('invalid status: $status ' );
474492 }
475493 _observeState ();
476494 _observeEvents ();
477495 _observeUserId ();
478496 final result = await _awaitIfNeeded ();
479497 if (result.isFailure) {
480- _logger.e (() => '[connect ] waiting failed: $result ' );
498+ _logger.e (() => '[join ] waiting failed: $result ' );
481499
482500 _stateManager.lifecycleCallTimeout (const CallTimeout ());
483501
@@ -486,28 +504,28 @@ class Call {
486504
487505 _stateManager
488506 .lifecycleCallConnectingAction (CallConnecting (_reconnectAttempt));
489- _logger.v (() => '[connect ] joining to coordinator' );
507+ _logger.v (() => '[join ] joining to coordinator' );
490508 final joinedResult = await _joinIfNeeded ();
491509 if (joinedResult is ! Success <CallCredentials >) {
492- _logger.e (() => '[connect] joining failed: $joinedResult ' );
510+ _logger.e (() => '[join] coordinator joining failed: $joinedResult ' );
493511 final error = (joinedResult as Failure ).error;
494512 _stateManager.lifecycleCallConnectFailed (ConnectFailed (error));
495513 return result;
496514 }
497515
498- _logger.v (() => '[connect ] starting sfu session' );
516+ _logger.v (() => '[join ] starting sfu session' );
499517 final sessionResult = await _startSession (joinedResult.data);
500518 if (sessionResult is ! Success <None >) {
501- _logger.w (() => '[connect ] sfu session start failed: $sessionResult ' );
519+ _logger.w (() => '[join ] sfu session start failed: $sessionResult ' );
502520 final error = (sessionResult as Failure ).error;
503521 _stateManager.lifecycleCallConnectFailed (ConnectFailed (error));
504522 return sessionResult;
505523 }
506- _logger.v (() => '[connect ] started session' );
524+ _logger.v (() => '[join ] started session' );
507525 _stateManager.lifecycleCallConnected (const CallConnected ());
508526 await _applyConnectOptions ();
509527
510- _logger.v (() => '[connect ] completed' );
528+ _logger.v (() => '[join ] completed' );
511529 return const Result .success (none);
512530 }
513531
@@ -662,19 +680,19 @@ class Call {
662680
663681 Future <Result <None >> leave () async {
664682 final state = this .state.value;
665- _logger.i (() => '[disconnect ] ${_status .value }; state: $state ' );
683+ _logger.i (() => '[leave ] ${_status .value }; state: $state ' );
666684 if (state.status.isDisconnected) {
667- _logger.w (() => '[disconnect ] rejected (state.status is disconnected)' );
685+ _logger.w (() => '[leave ] rejected (state.status is disconnected)' );
668686 return const Result .success (none);
669687 }
670688 if (_status.value == _ConnectionStatus .disconnected) {
671- _logger.w (() => '[disconnect ] rejected (status is disconnected)' );
689+ _logger.w (() => '[leave ] rejected (status is disconnected)' );
672690 return const Result .success (none);
673691 }
674692 _status.value = _ConnectionStatus .disconnected;
675- await _clear ('disconnect ' );
693+ await _clear ('leave ' );
676694 _stateManager.lifecycleCallDisconnected (const CallDisconnected ());
677- _logger.v (() => '[disconnect ] finished' );
695+ _logger.v (() => '[leave ] finished' );
678696 return const Result .success (none);
679697 }
680698
0 commit comments