Skip to content

Commit 0a3965c

Browse files
Brazolkanat
andauthored
fix: fixed accepting ringing during call (#699)
* [PBE-1710] make example app Firebase friendly * [PBE-1710] support reject.reason & show notification * fix ios, improve setup * support pronto-staging * write openapi script + generate new API * fixed accepting incoming call during another call (or outgoing call) * Update packages/stream_video/lib/src/core/client_state.dart --------- Co-authored-by: kanat <[email protected]>
1 parent eb89b63 commit 0a3965c

File tree

6 files changed

+98
-30
lines changed

6 files changed

+98
-30
lines changed

packages/stream_video/lib/src/call/call.dart

Lines changed: 59 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,9 @@ typedef OnCallPermissionRequest = void Function(
4141
typedef GetCurrentUserId = String? Function();
4242

4343
typedef SetActiveCall = Future<void> Function(Call?);
44-
typedef GetActiveCallCid = StreamCallCid? Function();
44+
typedef SetOutgoingCall = Future<void> Function(Call?);
45+
typedef GetActiveCall = Call? Function();
46+
typedef GetOutgoingCall = Call? Function();
4547

4648
const _idState = 1;
4749
const _idUserId = 2;
@@ -68,7 +70,9 @@ class Call {
6870
required CoordinatorClient coordinatorClient,
6971
required StateEmitter<User?> currentUser,
7072
required SetActiveCall setActiveCall,
71-
required GetActiveCallCid getActiveCallCid,
73+
required SetOutgoingCall setOutgoingCall,
74+
required GetActiveCall getActiveCall,
75+
required GetOutgoingCall getOutgoingCall,
7276
RetryPolicy? retryPolicy,
7377
SdpPolicy? sdpPolicy,
7478
CallPreferences? preferences,
@@ -79,7 +83,9 @@ class Call {
7983
coordinatorClient: coordinatorClient,
8084
currentUser: currentUser,
8185
setActiveCall: setActiveCall,
82-
getActiveCallCid: getActiveCallCid,
86+
setOutgoingCall: setOutgoingCall,
87+
getActiveCall: getActiveCall,
88+
getOutgoingCall: getOutgoingCall,
8389
retryPolicy: retryPolicy,
8490
sdpPolicy: sdpPolicy,
8591
preferences: preferences,
@@ -94,7 +100,9 @@ class Call {
94100
required CoordinatorClient coordinatorClient,
95101
required StateEmitter<User?> currentUser,
96102
required SetActiveCall setActiveCall,
97-
required GetActiveCallCid getActiveCallCid,
103+
required SetOutgoingCall setOutgoingCall,
104+
required GetActiveCall getActiveCall,
105+
required GetOutgoingCall getOutgoingCall,
98106
RetryPolicy? retryPolicy,
99107
SdpPolicy? sdpPolicy,
100108
CallPreferences? preferences,
@@ -105,7 +113,9 @@ class Call {
105113
coordinatorClient: coordinatorClient,
106114
currentUser: currentUser,
107115
setActiveCall: setActiveCall,
108-
getActiveCallCid: getActiveCallCid,
116+
setOutgoingCall: setOutgoingCall,
117+
getActiveCall: getActiveCall,
118+
getOutgoingCall: getOutgoingCall,
109119
retryPolicy: retryPolicy,
110120
sdpPolicy: sdpPolicy,
111121
preferences: preferences,
@@ -125,7 +135,9 @@ class Call {
125135
required CoordinatorClient coordinatorClient,
126136
required StateEmitter<User?> currentUser,
127137
required SetActiveCall setActiveCall,
128-
required GetActiveCallCid getActiveCallCid,
138+
required SetOutgoingCall setOutgoingCall,
139+
required GetActiveCall getActiveCall,
140+
required GetOutgoingCall getOutgoingCall,
129141
RetryPolicy? retryPolicy,
130142
SdpPolicy? sdpPolicy,
131143
CallPreferences? preferences,
@@ -136,7 +148,9 @@ class Call {
136148
coordinatorClient: coordinatorClient,
137149
currentUser: currentUser,
138150
setActiveCall: setActiveCall,
139-
getActiveCallCid: getActiveCallCid,
151+
setOutgoingCall: setOutgoingCall,
152+
getActiveCall: getActiveCall,
153+
getOutgoingCall: getOutgoingCall,
140154
retryPolicy: retryPolicy,
141155
sdpPolicy: sdpPolicy,
142156
preferences: preferences,
@@ -148,7 +162,9 @@ class Call {
148162
required CoordinatorClient coordinatorClient,
149163
required StateEmitter<User?> currentUser,
150164
required SetActiveCall setActiveCall,
151-
required GetActiveCallCid getActiveCallCid,
165+
required SetOutgoingCall setOutgoingCall,
166+
required GetActiveCall getActiveCall,
167+
required GetOutgoingCall getOutgoingCall,
152168
RetryPolicy? retryPolicy,
153169
SdpPolicy? sdpPolicy,
154170
CallPreferences? preferences,
@@ -172,7 +188,9 @@ class Call {
172188
coordinatorClient: coordinatorClient,
173189
currentUser: currentUser,
174190
setActiveCall: setActiveCall,
175-
getActiveCallCid: getActiveCallCid,
191+
setOutgoingCall: setOutgoingCall,
192+
getActiveCall: getActiveCall,
193+
getOutgoingCall: getOutgoingCall,
176194
preferences: finalCallPreferences,
177195
stateManager: stateManager,
178196
credentials: credentials,
@@ -185,7 +203,9 @@ class Call {
185203
Call._({
186204
required StateEmitter<User?> currentUser,
187205
required SetActiveCall setActiveCall,
188-
required GetActiveCallCid getActiveCallCid,
206+
required SetOutgoingCall setOutgoingCall,
207+
required GetActiveCall getActiveCall,
208+
required GetOutgoingCall getOutgoingCall,
189209
required CoordinatorClient coordinatorClient,
190210
required CallPreferences preferences,
191211
required CallStateNotifier stateManager,
@@ -206,7 +226,9 @@ class Call {
206226
.whereNotNull()
207227
.distinct(),
208228
_setActiveCall = setActiveCall,
209-
_getActiveCallCid = getActiveCallCid,
229+
_setOutgoingCall = setOutgoingCall,
230+
_getActiveCall = getActiveCall,
231+
_getOutgoingCall = getOutgoingCall,
210232
_coordinatorClient = coordinatorClient,
211233
_preferences = preferences,
212234
_retryPolicy = retryPolicy,
@@ -226,7 +248,9 @@ class Call {
226248
final GetCurrentUserId _getCurrentUserId;
227249
final Stream<String> _currentUserIdUpdates;
228250
final SetActiveCall _setActiveCall;
229-
final GetActiveCallCid _getActiveCallCid;
251+
final SetOutgoingCall _setOutgoingCall;
252+
final GetActiveCall _getActiveCall;
253+
final GetOutgoingCall _getOutgoingCall;
230254
final CoordinatorClient _coordinatorClient;
231255
final RetryPolicy _retryPolicy;
232256
final CallPreferences _preferences;
@@ -241,6 +265,8 @@ class Call {
241265

242266
StreamCallType get type => state.value.callType;
243267

268+
bool get isActiveCall => _getActiveCall()?.callCid == callCid;
269+
244270
String get id => state.value.callId;
245271

246272
StateEmitter<CallState> get state => _stateManager.callStateStream;
@@ -380,6 +406,21 @@ class Call {
380406
_logger.w(() => '[acceptCall] rejected (invalid status): $status');
381407
return Result.error('invalid status: $status');
382408
}
409+
410+
final outgoingCall = _getOutgoingCall();
411+
if (outgoingCall?.callCid != callCid) {
412+
await outgoingCall?.reject(reason: 'cancel');
413+
await outgoingCall?.leave();
414+
await _setOutgoingCall(null);
415+
}
416+
417+
final activeCall = _getActiveCall();
418+
if (activeCall?.callCid != callCid) {
419+
await activeCall?.reject(reason: 'cancel');
420+
await activeCall?.leave();
421+
await _setActiveCall(null);
422+
}
423+
383424
final result = await _coordinatorClient.acceptCall(cid: state.callCid);
384425
if (result is Success<None>) {
385426
_stateManager.lifecycleCallAccepted();
@@ -448,7 +489,7 @@ class Call {
448489
return const Result.success(none);
449490
}
450491

451-
if (_getActiveCallCid() == callCid) {
492+
if (_getActiveCall()?.callCid == callCid) {
452493
_logger.w(
453494
() => '[join] rejected (a call with the same cid is in progress)',
454495
);
@@ -997,6 +1038,7 @@ class Call {
9971038
await _session?.dispose();
9981039
_session = null;
9991040
await _setActiveCall(null);
1041+
await _setOutgoingCall(null);
10001042
_logger.v(() => '[clear] completed');
10011043
}
10021044

@@ -1291,6 +1333,10 @@ class Call {
12911333
return Result.error('[getOrCreate] failed; no user_id found');
12921334
}
12931335

1336+
if (ringing) {
1337+
await _setOutgoingCall(this);
1338+
}
1339+
12941340
final response = await _coordinatorClient.getOrCreateCall(
12951341
callCid: callCid,
12961342
ringing: ringing,

packages/stream_video/lib/src/call/session/call_session.dart

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -766,7 +766,8 @@ class CallSession extends Disposable {
766766
Future<Result<None>> setSubscriptions(
767767
List<SubscriptionChange> subscriptionChanges,
768768
) async {
769-
_logger.d(() => '[setSubscriptions] subscriptionChanges: $subscriptionChanges');
769+
_logger.d(
770+
() => '[setSubscriptions] subscriptionChanges: $subscriptionChanges');
770771

771772
final participants = stateManager.callState.callParticipants;
772773
final exclude = {SfuTrackType.video, SfuTrackType.screenShare};
@@ -792,7 +793,8 @@ class CallSession extends Disposable {
792793
Future<Result<None>> updateSubscription(
793794
SubscriptionChange subscriptionChange,
794795
) async {
795-
_logger.d(() => '[updateSubscription] subscriptionChange: $subscriptionChange');
796+
_logger.d(
797+
() => '[updateSubscription] subscriptionChange: $subscriptionChange');
796798
return _saBuffer.post(subscriptionChange);
797799
}
798800

@@ -885,6 +887,7 @@ class CallSession extends Disposable {
885887
enabled: enabled,
886888
constraints: constraints,
887889
);
890+
888891
return result.map((_) => none);
889892
}
890893

packages/stream_video/lib/src/coordinator/open_api/coordinator_ws.dart

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,6 @@ class CoordinatorWebSocket extends StreamWebSocket
7070

7171
bool _refreshToken = false;
7272

73-
@override
7473
SharedEmitter<CoordinatorEvent> get events => _events;
7574
final _events = MutableSharedEmitterImpl<CoordinatorEvent>();
7675

packages/stream_video/lib/src/core/client_state.dart

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import '../call/call.dart';
2-
import '../models/call_cid.dart';
32
import '../models/user.dart';
43
import '../state_emitter.dart';
54
import 'connection_state.dart';
@@ -21,14 +20,18 @@ abstract class ClientState {
2120
StateEmitter<Call?> get activeCall;
2221

2322
/// Emits when a call was created by another user with ringing set as True.
24-
StateEmitter<Call> get incomingCall;
23+
StateEmitter<Call?> get incomingCall;
24+
25+
/// Emits when a call was created by current user with ringing set as True.
26+
StateEmitter<Call?> get outgoingCall;
2527
}
2628

2729
class MutableClientState implements ClientState {
2830
MutableClientState(User user)
2931
: user = MutableStateEmitterImpl(user),
3032
activeCall = MutableStateEmitterImpl(null),
3133
incomingCall = MutableStateEmitterImpl(null),
34+
outgoingCall = MutableStateEmitterImpl(null),
3235
connection = MutableStateEmitterImpl(
3336
ConnectionState.disconnected(user.id),
3437
);
@@ -40,7 +43,10 @@ class MutableClientState implements ClientState {
4043
final MutableStateEmitter<Call?> activeCall;
4144

4245
@override
43-
final MutableStateEmitter<Call> incomingCall;
46+
final MutableStateEmitter<Call?> incomingCall;
47+
48+
@override
49+
final MutableStateEmitter<Call?> outgoingCall;
4450

4551
@override
4652
final MutableStateEmitter<ConnectionState> connection;
@@ -50,16 +56,23 @@ class MutableClientState implements ClientState {
5056

5157
Future<void> clear() async {
5258
activeCall.value = null;
59+
outgoingCall.value = null;
5360
connection.value = ConnectionState.disconnected(user.value.id);
5461
}
5562

56-
StreamCallCid? getActiveCallCid() => activeCall.valueOrNull?.callCid;
63+
Call? getActiveCall() => activeCall.valueOrNull;
64+
Call? getOutgoingCall() => outgoingCall.valueOrNull;
5765

5866
Future<void> setActiveCall(Call? call) async {
59-
final ongoingCall = activeCall.valueOrNull;
60-
if (ongoingCall != null && call != null) {
61-
await ongoingCall.leave();
67+
final currentlyActiveCall = activeCall.valueOrNull;
68+
if (currentlyActiveCall != null && call != null) {
69+
await currentlyActiveCall.leave();
6270
}
71+
6372
activeCall.value = call;
6473
}
74+
75+
Future<void> setOutgoingCall(Call? call) async {
76+
outgoingCall.value = call;
77+
}
6578
}

packages/stream_video/lib/src/stream_video.dart

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -493,7 +493,9 @@ class StreamVideo extends Disposable {
493493
coordinatorClient: _client,
494494
currentUser: _state.user,
495495
setActiveCall: _state.setActiveCall,
496-
getActiveCallCid: _state.getActiveCallCid,
496+
setOutgoingCall: _state.setOutgoingCall,
497+
getActiveCall: _state.getActiveCall,
498+
getOutgoingCall: _state.getOutgoingCall,
497499
retryPolicy: _options.retryPolicy,
498500
sdpPolicy: _options.sdpPolicy,
499501
preferences: preferences,
@@ -509,7 +511,9 @@ class StreamVideo extends Disposable {
509511
coordinatorClient: _client,
510512
currentUser: _state.user,
511513
setActiveCall: _state.setActiveCall,
512-
getActiveCallCid: _state.getActiveCallCid,
514+
setOutgoingCall: _state.setOutgoingCall,
515+
getActiveCall: _state.getActiveCall,
516+
getOutgoingCall: _state.getOutgoingCall,
513517
retryPolicy: _options.retryPolicy,
514518
sdpPolicy: _options.sdpPolicy,
515519
preferences: preferences,
@@ -721,7 +725,7 @@ class StreamVideo extends Disposable {
721725
}
722726

723727
if (_state.incomingCall.valueOrNull?.callCid.value == cid) {
724-
return Result.success(_state.incomingCall.value);
728+
return Result.success(_state.incomingCall.value!);
725729
}
726730

727731
final callCid = StreamCallCid(cid: cid);

packages/stream_video_flutter/example/lib/screen/home_screen.dart

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,18 @@ class _HomeScreenState extends State<HomeScreen> {
1818
final StreamVideo _streamVideo = StreamVideo.instance;
1919
late final currentUser = _streamVideo.currentUser;
2020

21-
StreamSubscription<Call>? _onIncomingCallSubscription;
21+
StreamSubscription<Call?>? _onIncomingCallSubscription;
2222

2323
@override
2424
void initState() {
2525
super.initState();
2626
_onIncomingCallSubscription?.cancel();
27-
_onIncomingCallSubscription = _streamVideo.state.incomingCall.listen(
28-
_onNavigateToCall,
29-
);
27+
_onIncomingCallSubscription =
28+
_streamVideo.state.incomingCall.listen((call) {
29+
if (call != null) {
30+
_onNavigateToCall(call);
31+
}
32+
});
3033
}
3134

3235
@override

0 commit comments

Comments
 (0)