@stream-io/video-client 0.6.4 → 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 +7 -0
- package/dist/index.browser.es.js +44 -33
- package/dist/index.browser.es.js.map +1 -1
- package/dist/index.cjs.js +44 -33
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.es.js +44 -33
- 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/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 +1 -1
- package/src/devices/InputMediaDeviceManagerState.ts +5 -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,13 @@
|
|
|
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
|
+
|
|
5
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)
|
|
6
13
|
|
|
7
14
|
|
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
|
}
|
|
@@ -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) => {
|
|
@@ -11430,7 +11441,7 @@ class Call {
|
|
|
11430
11441
|
/**
|
|
11431
11442
|
* Leave the call and stop the media streams that were published by the call.
|
|
11432
11443
|
*/
|
|
11433
|
-
this.leave = async ({ reject = false } = {}) => {
|
|
11444
|
+
this.leave = async ({ reject = false, reason = 'user is leaving the call', } = {}) => {
|
|
11434
11445
|
const callingState = this.state.callingState;
|
|
11435
11446
|
if (callingState === CallingState.LEFT) {
|
|
11436
11447
|
throw new Error('Cannot leave call that has already been left.');
|
|
@@ -11459,7 +11470,7 @@ class Call {
|
|
|
11459
11470
|
this.subscriber = undefined;
|
|
11460
11471
|
this.publisher?.close();
|
|
11461
11472
|
this.publisher = undefined;
|
|
11462
|
-
this.sfuClient?.close();
|
|
11473
|
+
this.sfuClient?.close(StreamSfuClient.NORMAL_CLOSURE, reason);
|
|
11463
11474
|
this.sfuClient = undefined;
|
|
11464
11475
|
this.dispatcher.offAll();
|
|
11465
11476
|
this.state.setCallingState(CallingState.LEFT);
|
|
@@ -11634,7 +11645,7 @@ class Call {
|
|
|
11634
11645
|
/**
|
|
11635
11646
|
* A closure which hides away the re-connection logic.
|
|
11636
11647
|
*/
|
|
11637
|
-
const reconnect = async (strategy
|
|
11648
|
+
const reconnect = async (strategy, reason) => {
|
|
11638
11649
|
const currentState = this.state.callingState;
|
|
11639
11650
|
if (currentState === CallingState.MIGRATING ||
|
|
11640
11651
|
currentState === CallingState.RECONNECTING) {
|
|
@@ -11656,7 +11667,7 @@ class Call {
|
|
|
11656
11667
|
// we'll need it for restoring the previous publishing state later
|
|
11657
11668
|
const localParticipant = this.state.localParticipant;
|
|
11658
11669
|
if (strategy === 'fast') {
|
|
11659
|
-
sfuClient.close(StreamSfuClient.ERROR_CONNECTION_BROKEN,
|
|
11670
|
+
sfuClient.close(StreamSfuClient.ERROR_CONNECTION_BROKEN, `attempting fast reconnect: ${reason}`);
|
|
11660
11671
|
}
|
|
11661
11672
|
else if (strategy === 'full') {
|
|
11662
11673
|
// in migration or recovery scenarios, we don't want to
|
|
@@ -11672,7 +11683,7 @@ class Call {
|
|
|
11672
11683
|
this.sfuStatsReporter?.stop();
|
|
11673
11684
|
this.sfuStatsReporter = undefined;
|
|
11674
11685
|
// clean up current connection
|
|
11675
|
-
sfuClient.close(StreamSfuClient.NORMAL_CLOSURE,
|
|
11686
|
+
sfuClient.close(StreamSfuClient.NORMAL_CLOSURE, `attempting full reconnect: ${reason}`);
|
|
11676
11687
|
}
|
|
11677
11688
|
await this.join({
|
|
11678
11689
|
...data,
|
|
@@ -11680,7 +11691,7 @@ class Call {
|
|
|
11680
11691
|
});
|
|
11681
11692
|
// clean up previous connection
|
|
11682
11693
|
if (strategy === 'migrate') {
|
|
11683
|
-
sfuClient.close(StreamSfuClient.NORMAL_CLOSURE, '
|
|
11694
|
+
sfuClient.close(StreamSfuClient.NORMAL_CLOSURE, 'attempting migration');
|
|
11684
11695
|
}
|
|
11685
11696
|
this.logger('info', `[Rejoin]: Attempt ${this.reconnectAttempts} successful!`);
|
|
11686
11697
|
// we shouldn't be republishing the streams if we're migrating
|
|
@@ -11719,7 +11730,7 @@ class Call {
|
|
|
11719
11730
|
const unregisterGoAway = this.dispatcher.on('goAway', (event) => {
|
|
11720
11731
|
const { reason } = event;
|
|
11721
11732
|
this.logger('info', `[Migration]: Going away from SFU... Reason: ${GoAwayReason[reason]}`);
|
|
11722
|
-
reconnect('migrate').catch((err) => {
|
|
11733
|
+
reconnect('migrate', GoAwayReason[reason]).catch((err) => {
|
|
11723
11734
|
this.logger('warn', `[Migration]: Failed to migrate to another SFU.`, err);
|
|
11724
11735
|
});
|
|
11725
11736
|
});
|
|
@@ -11749,7 +11760,7 @@ class Call {
|
|
|
11749
11760
|
if (this.reconnectAttempts < this.maxReconnectAttempts) {
|
|
11750
11761
|
sfuClient.isFastReconnecting = this.reconnectAttempts === 0;
|
|
11751
11762
|
const strategy = sfuClient.isFastReconnecting ? 'fast' : 'full';
|
|
11752
|
-
reconnect(strategy).catch((err) => {
|
|
11763
|
+
reconnect(strategy, `SFU closed the WS with code: ${e.code}`).catch((err) => {
|
|
11753
11764
|
this.logger('error', `[Rejoin]: ${strategy} rejoin failed for ${this.reconnectAttempts} times. Giving up.`, err);
|
|
11754
11765
|
this.state.setCallingState(CallingState.RECONNECTING_FAILED);
|
|
11755
11766
|
});
|
|
@@ -11777,7 +11788,7 @@ class Call {
|
|
|
11777
11788
|
do {
|
|
11778
11789
|
try {
|
|
11779
11790
|
sfuClient.isFastReconnecting = isFirstReconnectAttempt;
|
|
11780
|
-
await reconnect(isFirstReconnectAttempt ? 'fast' : 'full');
|
|
11791
|
+
await reconnect(isFirstReconnectAttempt ? 'fast' : 'full', 'Network: online');
|
|
11781
11792
|
return; // break the loop if rejoin is successful
|
|
11782
11793
|
}
|
|
11783
11794
|
catch (err) {
|
|
@@ -11886,7 +11897,7 @@ class Call {
|
|
|
11886
11897
|
}
|
|
11887
11898
|
else if (previousSfuClient?.isFastReconnecting) {
|
|
11888
11899
|
// reconnection wasn't possible, so we need to do a full rejoin
|
|
11889
|
-
return await reconnect('full').catch((err) => {
|
|
11900
|
+
return await reconnect('full', 're-attempting').catch((err) => {
|
|
11890
11901
|
this.logger('error', `[Rejoin]: Rejoin failed forced full rejoin.`, err);
|
|
11891
11902
|
});
|
|
11892
11903
|
}
|
|
@@ -11939,7 +11950,7 @@ class Call {
|
|
|
11939
11950
|
// join failed, try to rejoin
|
|
11940
11951
|
if (this.reconnectAttempts < this.maxReconnectAttempts) {
|
|
11941
11952
|
this.logger('error', `[Rejoin]: Rejoin ${this.reconnectAttempts} failed.`, err);
|
|
11942
|
-
await reconnect();
|
|
11953
|
+
await reconnect('full', 'previous attempt failed');
|
|
11943
11954
|
this.logger('info', `[Rejoin]: Rejoin ${this.reconnectAttempts} successful!`);
|
|
11944
11955
|
}
|
|
11945
11956
|
else {
|
|
@@ -12458,7 +12469,7 @@ class Call {
|
|
|
12458
12469
|
return;
|
|
12459
12470
|
clearTimeout(this.dropTimeout);
|
|
12460
12471
|
this.dropTimeout = setTimeout(() => {
|
|
12461
|
-
this.leave().catch((err) => {
|
|
12472
|
+
this.leave({ reason: 'ring: timeout' }).catch((err) => {
|
|
12462
12473
|
this.logger('error', 'Failed to drop call', err);
|
|
12463
12474
|
});
|
|
12464
12475
|
}, timeoutInMs);
|
|
@@ -12677,7 +12688,7 @@ class Call {
|
|
|
12677
12688
|
const currentUserId = this.currentUserId;
|
|
12678
12689
|
if (currentUserId && blockedUserIds.includes(currentUserId)) {
|
|
12679
12690
|
this.logger('info', 'Leaving call because of being blocked');
|
|
12680
|
-
await this.leave();
|
|
12691
|
+
await this.leave({ reason: 'user blocked' });
|
|
12681
12692
|
}
|
|
12682
12693
|
}));
|
|
12683
12694
|
this.leaveCallHooks.add(
|
|
@@ -14358,7 +14369,7 @@ class StreamClient {
|
|
|
14358
14369
|
});
|
|
14359
14370
|
};
|
|
14360
14371
|
this.getUserAgent = () => {
|
|
14361
|
-
const version = "0.6.
|
|
14372
|
+
const version = "0.6.5" ;
|
|
14362
14373
|
return (this.userAgent ||
|
|
14363
14374
|
`stream-video-javascript-client-${this.node ? 'node' : 'browser'}-${version}`);
|
|
14364
14375
|
};
|
|
@@ -14821,7 +14832,7 @@ class StreamVideoClient {
|
|
|
14821
14832
|
// if `call.created` was received before `call.ring`.
|
|
14822
14833
|
// In that case, we cleanup the already tracked call.
|
|
14823
14834
|
const prevCall = this.writeableStateStore.findCall(call.type, call.id);
|
|
14824
|
-
await prevCall?.leave();
|
|
14835
|
+
await prevCall?.leave({ reason: 'cleaning-up in call.ring' });
|
|
14825
14836
|
// we create a new call
|
|
14826
14837
|
const theCall = new Call({
|
|
14827
14838
|
streamClient: this.streamClient,
|