@stream-io/video-client 0.6.3 → 0.6.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -0
- package/dist/index.browser.es.js +57 -42
- package/dist/index.browser.es.js.map +1 -1
- package/dist/index.cjs.js +57 -42
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.es.js +57 -42
- package/dist/index.es.js.map +1 -1
- package/dist/src/Call.d.ts +1 -1
- package/dist/src/StreamSfuClient.d.ts +1 -1
- package/dist/src/StreamVideoClient.d.ts +1 -1
- package/dist/src/devices/InputMediaDeviceManager.d.ts +1 -1
- package/dist/src/devices/SpeakerManager.d.ts +4 -3
- package/dist/src/types.d.ts +5 -0
- package/package.json +1 -1
- package/src/Call.ts +29 -23
- package/src/StreamSfuClient.ts +3 -6
- package/src/StreamVideoClient.ts +2 -2
- package/src/devices/InputMediaDeviceManager.ts +4 -2
- package/src/devices/InputMediaDeviceManagerState.ts +5 -6
- package/src/devices/SpeakerManager.ts +18 -6
- package/src/devices/__tests__/InputMediaDeviceManagerState.test.ts +1 -25
- package/src/events/call.ts +3 -3
- package/src/events/internal.ts +1 -1
- package/src/store/CallState.ts +16 -7
- package/src/store/stateStore.ts +5 -3
- package/src/types.ts +6 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,20 @@
|
|
|
2
2
|
|
|
3
3
|
This file was generated using [@jscutlery/semver](https://github.com/jscutlery/semver).
|
|
4
4
|
|
|
5
|
+
### [0.6.5](https://github.com/GetStream/stream-video-js/compare/@stream-io/video-client-0.6.4...@stream-io/video-client-0.6.5) (2024-03-29)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
### Bug Fixes
|
|
9
|
+
|
|
10
|
+
* various bug fixes and improvements ([#1300](https://github.com/GetStream/stream-video-js/issues/1300)) ([a6186e2](https://github.com/GetStream/stream-video-js/commit/a6186e2406fd0b3e0aaa51a4222fa2e24e9dfac3))
|
|
11
|
+
|
|
12
|
+
### [0.6.4](https://github.com/GetStream/stream-video-js/compare/@stream-io/video-client-0.6.3...@stream-io/video-client-0.6.4) (2024-03-28)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
### Bug Fixes
|
|
16
|
+
|
|
17
|
+
* **react-native:** improve error logging for speaker manager hook and improve usage of incall manager in SDK ([#1299](https://github.com/GetStream/stream-video-js/issues/1299)) ([9527c41](https://github.com/GetStream/stream-video-js/commit/9527c4176d4e46224ddec18e3fddfb404e0aaae5))
|
|
18
|
+
|
|
5
19
|
### [0.6.3](https://github.com/GetStream/stream-video-js/compare/@stream-io/video-client-0.6.2...@stream-io/video-client-0.6.3) (2024-03-25)
|
|
6
20
|
|
|
7
21
|
|
package/dist/index.browser.es.js
CHANGED
|
@@ -6584,6 +6584,14 @@ var CallingState;
|
|
|
6584
6584
|
*/
|
|
6585
6585
|
CallingState["OFFLINE"] = "offline";
|
|
6586
6586
|
})(CallingState || (CallingState = {}));
|
|
6587
|
+
/**
|
|
6588
|
+
* Returns the default egress object - when no egress data is available.
|
|
6589
|
+
*/
|
|
6590
|
+
const defaultEgress = {
|
|
6591
|
+
broadcasting: false,
|
|
6592
|
+
hls: { playlist_url: '' },
|
|
6593
|
+
rtmps: [],
|
|
6594
|
+
};
|
|
6587
6595
|
/**
|
|
6588
6596
|
* Holds the state of the current call.
|
|
6589
6597
|
* @react You don't have to use this class directly, as we are exposing the state through Hooks.
|
|
@@ -6898,19 +6906,19 @@ class CallState {
|
|
|
6898
6906
|
]);
|
|
6899
6907
|
};
|
|
6900
6908
|
this.updateFromHLSBroadcastStopped = () => {
|
|
6901
|
-
this.setCurrentValue(this.egressSubject, (egress) => ({
|
|
6909
|
+
this.setCurrentValue(this.egressSubject, (egress = defaultEgress) => ({
|
|
6902
6910
|
...egress,
|
|
6903
6911
|
broadcasting: false,
|
|
6904
6912
|
}));
|
|
6905
6913
|
};
|
|
6906
6914
|
this.updateFromHLSBroadcastingFailed = () => {
|
|
6907
|
-
this.setCurrentValue(this.egressSubject, (egress) => ({
|
|
6915
|
+
this.setCurrentValue(this.egressSubject, (egress = defaultEgress) => ({
|
|
6908
6916
|
...egress,
|
|
6909
6917
|
broadcasting: false,
|
|
6910
6918
|
}));
|
|
6911
6919
|
};
|
|
6912
6920
|
this.updateFromHLSBroadcastStarted = (event) => {
|
|
6913
|
-
this.setCurrentValue(this.egressSubject, (egress) => ({
|
|
6921
|
+
this.setCurrentValue(this.egressSubject, (egress = defaultEgress) => ({
|
|
6914
6922
|
...egress,
|
|
6915
6923
|
broadcasting: true,
|
|
6916
6924
|
hls: {
|
|
@@ -7352,7 +7360,9 @@ class StreamVideoWriteableStateStore {
|
|
|
7352
7360
|
if (call.state.callingState === CallingState.LEFT)
|
|
7353
7361
|
continue;
|
|
7354
7362
|
logger('info', `User disconnected, leaving call: ${call.cid}`);
|
|
7355
|
-
await call
|
|
7363
|
+
await call
|
|
7364
|
+
.leave({ reason: 'client.disconnectUser() called' })
|
|
7365
|
+
.catch((err) => {
|
|
7356
7366
|
logger('error', `Error leaving call: ${call.cid}`, err);
|
|
7357
7367
|
});
|
|
7358
7368
|
}
|
|
@@ -8604,10 +8614,10 @@ class StreamSfuClient {
|
|
|
8604
8614
|
this.isFastReconnecting = false;
|
|
8605
8615
|
this.pingIntervalInMs = 10 * 1000;
|
|
8606
8616
|
this.unhealthyTimeoutInMs = this.pingIntervalInMs + 5 * 1000;
|
|
8607
|
-
this.close = (code
|
|
8608
|
-
this.logger('debug',
|
|
8617
|
+
this.close = (code, reason) => {
|
|
8618
|
+
this.logger('debug', `Closing SFU WS connection: ${code} - ${reason}`);
|
|
8609
8619
|
if (this.signalWs.readyState !== this.signalWs.CLOSED) {
|
|
8610
|
-
this.signalWs.close(code, reason);
|
|
8620
|
+
this.signalWs.close(code, `js-client: ${reason}`);
|
|
8611
8621
|
}
|
|
8612
8622
|
this.unsubscribeIceTrickle();
|
|
8613
8623
|
clearInterval(this.keepAliveInterval);
|
|
@@ -8856,13 +8866,13 @@ const watchCallRejected = (call) => {
|
|
|
8856
8866
|
.every((m) => rejectedBy[m.user_id]);
|
|
8857
8867
|
if (everyoneElseRejected) {
|
|
8858
8868
|
call.logger('info', 'everyone rejected, leaving the call');
|
|
8859
|
-
await call.leave();
|
|
8869
|
+
await call.leave({ reason: 'ring: everyone rejected' });
|
|
8860
8870
|
}
|
|
8861
8871
|
}
|
|
8862
8872
|
else {
|
|
8863
8873
|
if (rejectedBy[eventCall.created_by.id]) {
|
|
8864
8874
|
call.logger('info', 'call creator rejected, leaving call');
|
|
8865
|
-
await call.leave();
|
|
8875
|
+
await call.leave({ reason: 'ring: creator rejected' });
|
|
8866
8876
|
}
|
|
8867
8877
|
}
|
|
8868
8878
|
};
|
|
@@ -8876,7 +8886,7 @@ const watchCallEnded = (call) => {
|
|
|
8876
8886
|
if (callingState === CallingState.RINGING ||
|
|
8877
8887
|
callingState === CallingState.JOINED ||
|
|
8878
8888
|
callingState === CallingState.JOINING) {
|
|
8879
|
-
await call.leave();
|
|
8889
|
+
await call.leave({ reason: 'call.ended event received' });
|
|
8880
8890
|
}
|
|
8881
8891
|
};
|
|
8882
8892
|
};
|
|
@@ -8952,7 +8962,7 @@ const watchLiveEnded = (dispatcher, call) => {
|
|
|
8952
8962
|
if (e.error && e.error.code !== ErrorCode.LIVE_ENDED)
|
|
8953
8963
|
return;
|
|
8954
8964
|
if (!call.permissionsContext.hasPermission(OwnCapability.JOIN_BACKSTAGE)) {
|
|
8955
|
-
call.leave().catch((err) => {
|
|
8965
|
+
call.leave({ reason: 'live ended' }).catch((err) => {
|
|
8956
8966
|
logger$1('error', 'Failed to leave call after live ended', err);
|
|
8957
8967
|
});
|
|
8958
8968
|
}
|
|
@@ -10385,12 +10395,12 @@ class InputMediaDeviceManager {
|
|
|
10385
10395
|
/**
|
|
10386
10396
|
* Selects a device.
|
|
10387
10397
|
*
|
|
10388
|
-
* Note:
|
|
10398
|
+
* Note: This method is not supported in React Native
|
|
10389
10399
|
* @param deviceId the device id to select.
|
|
10390
10400
|
*/
|
|
10391
10401
|
async select(deviceId) {
|
|
10392
10402
|
if (isReactNative()) {
|
|
10393
|
-
throw new Error('This method is not supported in React Native');
|
|
10403
|
+
throw new Error('This method is not supported in React Native. Please visit https://getstream.io/video/docs/reactnative/core/camera-and-microphone/#speaker-management for reference.');
|
|
10394
10404
|
}
|
|
10395
10405
|
if (deviceId === this.state.selectedDevice) {
|
|
10396
10406
|
return;
|
|
@@ -10598,13 +10608,14 @@ class InputMediaDeviceManagerState {
|
|
|
10598
10608
|
return notifyGranted();
|
|
10599
10609
|
}
|
|
10600
10610
|
let permissionState;
|
|
10601
|
-
const notify = () =>
|
|
10602
|
-
|
|
10603
|
-
|
|
10604
|
-
|
|
10605
|
-
|
|
10606
|
-
|
|
10607
|
-
|
|
10611
|
+
const notify = () => {
|
|
10612
|
+
subscriber.next(
|
|
10613
|
+
// In some browsers, the 'change' event doesn't reliably emit and hence,
|
|
10614
|
+
// permissionState stays in 'prompt' state forever.
|
|
10615
|
+
// Typically, this happens when a user grants one-time permission.
|
|
10616
|
+
// Instead of checking if a permission is granted, we check if it isn't denied
|
|
10617
|
+
permissionState.state !== 'denied');
|
|
10618
|
+
};
|
|
10608
10619
|
navigator.permissions
|
|
10609
10620
|
.query({ name: this.permissionName })
|
|
10610
10621
|
.then((permissionStatus) => {
|
|
@@ -11291,22 +11302,26 @@ class SpeakerManager {
|
|
|
11291
11302
|
* Lists the available audio output devices
|
|
11292
11303
|
*
|
|
11293
11304
|
* Note: It prompts the user for a permission to use devices (if not already granted)
|
|
11305
|
+
* Note: This method is not supported in React Native
|
|
11294
11306
|
*
|
|
11295
11307
|
* @returns an Observable that will be updated if a device is connected or disconnected
|
|
11296
11308
|
*/
|
|
11297
11309
|
listDevices() {
|
|
11310
|
+
if (isReactNative()) {
|
|
11311
|
+
throw new Error('This feature is not supported in React Native. Please visit https://getstream.io/video/docs/reactnative/core/camera-and-microphone/#speaker-management for more details');
|
|
11312
|
+
}
|
|
11298
11313
|
return getAudioOutputDevices();
|
|
11299
11314
|
}
|
|
11300
11315
|
/**
|
|
11301
11316
|
* Select a device.
|
|
11302
11317
|
*
|
|
11303
|
-
* Note:
|
|
11318
|
+
* Note: This method is not supported in React Native
|
|
11304
11319
|
*
|
|
11305
11320
|
* @param deviceId empty string means the system default
|
|
11306
11321
|
*/
|
|
11307
11322
|
select(deviceId) {
|
|
11308
11323
|
if (isReactNative()) {
|
|
11309
|
-
throw new Error('This feature is not supported in React Native');
|
|
11324
|
+
throw new Error('This feature is not supported in React Native. Please visit https://getstream.io/video/docs/reactnative/core/camera-and-microphone/#speaker-management for more details');
|
|
11310
11325
|
}
|
|
11311
11326
|
this.state.setDevice(deviceId);
|
|
11312
11327
|
}
|
|
@@ -11314,11 +11329,11 @@ class SpeakerManager {
|
|
|
11314
11329
|
* Set the volume of the audio elements
|
|
11315
11330
|
* @param volume a number between 0 and 1.
|
|
11316
11331
|
*
|
|
11317
|
-
* Note:
|
|
11332
|
+
* Note: This method is not supported in React Native
|
|
11318
11333
|
*/
|
|
11319
11334
|
setVolume(volume) {
|
|
11320
11335
|
if (isReactNative()) {
|
|
11321
|
-
throw new Error('This feature is not supported in React Native');
|
|
11336
|
+
throw new Error('This feature is not supported in React Native. Please visit https://getstream.io/video/docs/reactnative/core/camera-and-microphone/#speaker-management for more details');
|
|
11322
11337
|
}
|
|
11323
11338
|
if (volume && (volume < 0 || volume > 1)) {
|
|
11324
11339
|
throw new Error('Volume must be between 0 and 1');
|
|
@@ -11328,14 +11343,14 @@ class SpeakerManager {
|
|
|
11328
11343
|
/**
|
|
11329
11344
|
* Set the volume of a participant.
|
|
11330
11345
|
*
|
|
11331
|
-
* Note:
|
|
11346
|
+
* Note: This method is not supported in React Native.
|
|
11332
11347
|
*
|
|
11333
11348
|
* @param sessionId the participant's session id.
|
|
11334
11349
|
* @param volume a number between 0 and 1. Set it to `undefined` to use the default volume.
|
|
11335
11350
|
*/
|
|
11336
11351
|
setParticipantVolume(sessionId, volume) {
|
|
11337
11352
|
if (isReactNative()) {
|
|
11338
|
-
throw new Error('This feature is not supported in React Native');
|
|
11353
|
+
throw new Error('This feature is not supported in React Native. Please visit https://getstream.io/video/docs/reactnative/core/camera-and-microphone/#speaker-management for more details');
|
|
11339
11354
|
}
|
|
11340
11355
|
if (volume && (volume < 0 || volume > 1)) {
|
|
11341
11356
|
throw new Error('Volume must be between 0 and 1, or undefined');
|
|
@@ -11426,7 +11441,7 @@ class Call {
|
|
|
11426
11441
|
/**
|
|
11427
11442
|
* Leave the call and stop the media streams that were published by the call.
|
|
11428
11443
|
*/
|
|
11429
|
-
this.leave = async ({ reject = false } = {}) => {
|
|
11444
|
+
this.leave = async ({ reject = false, reason = 'user is leaving the call', } = {}) => {
|
|
11430
11445
|
const callingState = this.state.callingState;
|
|
11431
11446
|
if (callingState === CallingState.LEFT) {
|
|
11432
11447
|
throw new Error('Cannot leave call that has already been left.');
|
|
@@ -11455,7 +11470,7 @@ class Call {
|
|
|
11455
11470
|
this.subscriber = undefined;
|
|
11456
11471
|
this.publisher?.close();
|
|
11457
11472
|
this.publisher = undefined;
|
|
11458
|
-
this.sfuClient?.close();
|
|
11473
|
+
this.sfuClient?.close(StreamSfuClient.NORMAL_CLOSURE, reason);
|
|
11459
11474
|
this.sfuClient = undefined;
|
|
11460
11475
|
this.dispatcher.offAll();
|
|
11461
11476
|
this.state.setCallingState(CallingState.LEFT);
|
|
@@ -11630,7 +11645,7 @@ class Call {
|
|
|
11630
11645
|
/**
|
|
11631
11646
|
* A closure which hides away the re-connection logic.
|
|
11632
11647
|
*/
|
|
11633
|
-
const reconnect = async (strategy
|
|
11648
|
+
const reconnect = async (strategy, reason) => {
|
|
11634
11649
|
const currentState = this.state.callingState;
|
|
11635
11650
|
if (currentState === CallingState.MIGRATING ||
|
|
11636
11651
|
currentState === CallingState.RECONNECTING) {
|
|
@@ -11652,7 +11667,7 @@ class Call {
|
|
|
11652
11667
|
// we'll need it for restoring the previous publishing state later
|
|
11653
11668
|
const localParticipant = this.state.localParticipant;
|
|
11654
11669
|
if (strategy === 'fast') {
|
|
11655
|
-
sfuClient.close(StreamSfuClient.ERROR_CONNECTION_BROKEN,
|
|
11670
|
+
sfuClient.close(StreamSfuClient.ERROR_CONNECTION_BROKEN, `attempting fast reconnect: ${reason}`);
|
|
11656
11671
|
}
|
|
11657
11672
|
else if (strategy === 'full') {
|
|
11658
11673
|
// in migration or recovery scenarios, we don't want to
|
|
@@ -11668,7 +11683,7 @@ class Call {
|
|
|
11668
11683
|
this.sfuStatsReporter?.stop();
|
|
11669
11684
|
this.sfuStatsReporter = undefined;
|
|
11670
11685
|
// clean up current connection
|
|
11671
|
-
sfuClient.close(StreamSfuClient.NORMAL_CLOSURE,
|
|
11686
|
+
sfuClient.close(StreamSfuClient.NORMAL_CLOSURE, `attempting full reconnect: ${reason}`);
|
|
11672
11687
|
}
|
|
11673
11688
|
await this.join({
|
|
11674
11689
|
...data,
|
|
@@ -11676,7 +11691,7 @@ class Call {
|
|
|
11676
11691
|
});
|
|
11677
11692
|
// clean up previous connection
|
|
11678
11693
|
if (strategy === 'migrate') {
|
|
11679
|
-
sfuClient.close(StreamSfuClient.NORMAL_CLOSURE, '
|
|
11694
|
+
sfuClient.close(StreamSfuClient.NORMAL_CLOSURE, 'attempting migration');
|
|
11680
11695
|
}
|
|
11681
11696
|
this.logger('info', `[Rejoin]: Attempt ${this.reconnectAttempts} successful!`);
|
|
11682
11697
|
// we shouldn't be republishing the streams if we're migrating
|
|
@@ -11715,7 +11730,7 @@ class Call {
|
|
|
11715
11730
|
const unregisterGoAway = this.dispatcher.on('goAway', (event) => {
|
|
11716
11731
|
const { reason } = event;
|
|
11717
11732
|
this.logger('info', `[Migration]: Going away from SFU... Reason: ${GoAwayReason[reason]}`);
|
|
11718
|
-
reconnect('migrate').catch((err) => {
|
|
11733
|
+
reconnect('migrate', GoAwayReason[reason]).catch((err) => {
|
|
11719
11734
|
this.logger('warn', `[Migration]: Failed to migrate to another SFU.`, err);
|
|
11720
11735
|
});
|
|
11721
11736
|
});
|
|
@@ -11745,7 +11760,7 @@ class Call {
|
|
|
11745
11760
|
if (this.reconnectAttempts < this.maxReconnectAttempts) {
|
|
11746
11761
|
sfuClient.isFastReconnecting = this.reconnectAttempts === 0;
|
|
11747
11762
|
const strategy = sfuClient.isFastReconnecting ? 'fast' : 'full';
|
|
11748
|
-
reconnect(strategy).catch((err) => {
|
|
11763
|
+
reconnect(strategy, `SFU closed the WS with code: ${e.code}`).catch((err) => {
|
|
11749
11764
|
this.logger('error', `[Rejoin]: ${strategy} rejoin failed for ${this.reconnectAttempts} times. Giving up.`, err);
|
|
11750
11765
|
this.state.setCallingState(CallingState.RECONNECTING_FAILED);
|
|
11751
11766
|
});
|
|
@@ -11773,7 +11788,7 @@ class Call {
|
|
|
11773
11788
|
do {
|
|
11774
11789
|
try {
|
|
11775
11790
|
sfuClient.isFastReconnecting = isFirstReconnectAttempt;
|
|
11776
|
-
await reconnect(isFirstReconnectAttempt ? 'fast' : 'full');
|
|
11791
|
+
await reconnect(isFirstReconnectAttempt ? 'fast' : 'full', 'Network: online');
|
|
11777
11792
|
return; // break the loop if rejoin is successful
|
|
11778
11793
|
}
|
|
11779
11794
|
catch (err) {
|
|
@@ -11882,7 +11897,7 @@ class Call {
|
|
|
11882
11897
|
}
|
|
11883
11898
|
else if (previousSfuClient?.isFastReconnecting) {
|
|
11884
11899
|
// reconnection wasn't possible, so we need to do a full rejoin
|
|
11885
|
-
return await reconnect('full').catch((err) => {
|
|
11900
|
+
return await reconnect('full', 're-attempting').catch((err) => {
|
|
11886
11901
|
this.logger('error', `[Rejoin]: Rejoin failed forced full rejoin.`, err);
|
|
11887
11902
|
});
|
|
11888
11903
|
}
|
|
@@ -11935,7 +11950,7 @@ class Call {
|
|
|
11935
11950
|
// join failed, try to rejoin
|
|
11936
11951
|
if (this.reconnectAttempts < this.maxReconnectAttempts) {
|
|
11937
11952
|
this.logger('error', `[Rejoin]: Rejoin ${this.reconnectAttempts} failed.`, err);
|
|
11938
|
-
await reconnect();
|
|
11953
|
+
await reconnect('full', 'previous attempt failed');
|
|
11939
11954
|
this.logger('info', `[Rejoin]: Rejoin ${this.reconnectAttempts} successful!`);
|
|
11940
11955
|
}
|
|
11941
11956
|
else {
|
|
@@ -12454,7 +12469,7 @@ class Call {
|
|
|
12454
12469
|
return;
|
|
12455
12470
|
clearTimeout(this.dropTimeout);
|
|
12456
12471
|
this.dropTimeout = setTimeout(() => {
|
|
12457
|
-
this.leave().catch((err) => {
|
|
12472
|
+
this.leave({ reason: 'ring: timeout' }).catch((err) => {
|
|
12458
12473
|
this.logger('error', 'Failed to drop call', err);
|
|
12459
12474
|
});
|
|
12460
12475
|
}, timeoutInMs);
|
|
@@ -12673,7 +12688,7 @@ class Call {
|
|
|
12673
12688
|
const currentUserId = this.currentUserId;
|
|
12674
12689
|
if (currentUserId && blockedUserIds.includes(currentUserId)) {
|
|
12675
12690
|
this.logger('info', 'Leaving call because of being blocked');
|
|
12676
|
-
await this.leave();
|
|
12691
|
+
await this.leave({ reason: 'user blocked' });
|
|
12677
12692
|
}
|
|
12678
12693
|
}));
|
|
12679
12694
|
this.leaveCallHooks.add(
|
|
@@ -14354,7 +14369,7 @@ class StreamClient {
|
|
|
14354
14369
|
});
|
|
14355
14370
|
};
|
|
14356
14371
|
this.getUserAgent = () => {
|
|
14357
|
-
const version = "0.6.
|
|
14372
|
+
const version = "0.6.5" ;
|
|
14358
14373
|
return (this.userAgent ||
|
|
14359
14374
|
`stream-video-javascript-client-${this.node ? 'node' : 'browser'}-${version}`);
|
|
14360
14375
|
};
|
|
@@ -14565,7 +14580,7 @@ class StreamVideoClient {
|
|
|
14565
14580
|
* Creates a new call.
|
|
14566
14581
|
*
|
|
14567
14582
|
* @param type the type of the call.
|
|
14568
|
-
* @param id the id of the call
|
|
14583
|
+
* @param id the id of the call.
|
|
14569
14584
|
*/
|
|
14570
14585
|
this.call = (type, id) => {
|
|
14571
14586
|
return new Call({
|
|
@@ -14817,7 +14832,7 @@ class StreamVideoClient {
|
|
|
14817
14832
|
// if `call.created` was received before `call.ring`.
|
|
14818
14833
|
// In that case, we cleanup the already tracked call.
|
|
14819
14834
|
const prevCall = this.writeableStateStore.findCall(call.type, call.id);
|
|
14820
|
-
await prevCall?.leave();
|
|
14835
|
+
await prevCall?.leave({ reason: 'cleaning-up in call.ring' });
|
|
14821
14836
|
// we create a new call
|
|
14822
14837
|
const theCall = new Call({
|
|
14823
14838
|
streamClient: this.streamClient,
|