@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/dist/index.cjs.js
CHANGED
|
@@ -6607,6 +6607,14 @@ exports.CallingState = void 0;
|
|
|
6607
6607
|
*/
|
|
6608
6608
|
CallingState["OFFLINE"] = "offline";
|
|
6609
6609
|
})(exports.CallingState || (exports.CallingState = {}));
|
|
6610
|
+
/**
|
|
6611
|
+
* Returns the default egress object - when no egress data is available.
|
|
6612
|
+
*/
|
|
6613
|
+
const defaultEgress = {
|
|
6614
|
+
broadcasting: false,
|
|
6615
|
+
hls: { playlist_url: '' },
|
|
6616
|
+
rtmps: [],
|
|
6617
|
+
};
|
|
6610
6618
|
/**
|
|
6611
6619
|
* Holds the state of the current call.
|
|
6612
6620
|
* @react You don't have to use this class directly, as we are exposing the state through Hooks.
|
|
@@ -6921,19 +6929,19 @@ class CallState {
|
|
|
6921
6929
|
]);
|
|
6922
6930
|
};
|
|
6923
6931
|
this.updateFromHLSBroadcastStopped = () => {
|
|
6924
|
-
this.setCurrentValue(this.egressSubject, (egress) => ({
|
|
6932
|
+
this.setCurrentValue(this.egressSubject, (egress = defaultEgress) => ({
|
|
6925
6933
|
...egress,
|
|
6926
6934
|
broadcasting: false,
|
|
6927
6935
|
}));
|
|
6928
6936
|
};
|
|
6929
6937
|
this.updateFromHLSBroadcastingFailed = () => {
|
|
6930
|
-
this.setCurrentValue(this.egressSubject, (egress) => ({
|
|
6938
|
+
this.setCurrentValue(this.egressSubject, (egress = defaultEgress) => ({
|
|
6931
6939
|
...egress,
|
|
6932
6940
|
broadcasting: false,
|
|
6933
6941
|
}));
|
|
6934
6942
|
};
|
|
6935
6943
|
this.updateFromHLSBroadcastStarted = (event) => {
|
|
6936
|
-
this.setCurrentValue(this.egressSubject, (egress) => ({
|
|
6944
|
+
this.setCurrentValue(this.egressSubject, (egress = defaultEgress) => ({
|
|
6937
6945
|
...egress,
|
|
6938
6946
|
broadcasting: true,
|
|
6939
6947
|
hls: {
|
|
@@ -7375,7 +7383,9 @@ class StreamVideoWriteableStateStore {
|
|
|
7375
7383
|
if (call.state.callingState === exports.CallingState.LEFT)
|
|
7376
7384
|
continue;
|
|
7377
7385
|
logger('info', `User disconnected, leaving call: ${call.cid}`);
|
|
7378
|
-
await call
|
|
7386
|
+
await call
|
|
7387
|
+
.leave({ reason: 'client.disconnectUser() called' })
|
|
7388
|
+
.catch((err) => {
|
|
7379
7389
|
logger('error', `Error leaving call: ${call.cid}`, err);
|
|
7380
7390
|
});
|
|
7381
7391
|
}
|
|
@@ -8627,10 +8637,10 @@ class StreamSfuClient {
|
|
|
8627
8637
|
this.isFastReconnecting = false;
|
|
8628
8638
|
this.pingIntervalInMs = 10 * 1000;
|
|
8629
8639
|
this.unhealthyTimeoutInMs = this.pingIntervalInMs + 5 * 1000;
|
|
8630
|
-
this.close = (code
|
|
8631
|
-
this.logger('debug',
|
|
8640
|
+
this.close = (code, reason) => {
|
|
8641
|
+
this.logger('debug', `Closing SFU WS connection: ${code} - ${reason}`);
|
|
8632
8642
|
if (this.signalWs.readyState !== this.signalWs.CLOSED) {
|
|
8633
|
-
this.signalWs.close(code, reason);
|
|
8643
|
+
this.signalWs.close(code, `js-client: ${reason}`);
|
|
8634
8644
|
}
|
|
8635
8645
|
this.unsubscribeIceTrickle();
|
|
8636
8646
|
clearInterval(this.keepAliveInterval);
|
|
@@ -8879,13 +8889,13 @@ const watchCallRejected = (call) => {
|
|
|
8879
8889
|
.every((m) => rejectedBy[m.user_id]);
|
|
8880
8890
|
if (everyoneElseRejected) {
|
|
8881
8891
|
call.logger('info', 'everyone rejected, leaving the call');
|
|
8882
|
-
await call.leave();
|
|
8892
|
+
await call.leave({ reason: 'ring: everyone rejected' });
|
|
8883
8893
|
}
|
|
8884
8894
|
}
|
|
8885
8895
|
else {
|
|
8886
8896
|
if (rejectedBy[eventCall.created_by.id]) {
|
|
8887
8897
|
call.logger('info', 'call creator rejected, leaving call');
|
|
8888
|
-
await call.leave();
|
|
8898
|
+
await call.leave({ reason: 'ring: creator rejected' });
|
|
8889
8899
|
}
|
|
8890
8900
|
}
|
|
8891
8901
|
};
|
|
@@ -8899,7 +8909,7 @@ const watchCallEnded = (call) => {
|
|
|
8899
8909
|
if (callingState === exports.CallingState.RINGING ||
|
|
8900
8910
|
callingState === exports.CallingState.JOINED ||
|
|
8901
8911
|
callingState === exports.CallingState.JOINING) {
|
|
8902
|
-
await call.leave();
|
|
8912
|
+
await call.leave({ reason: 'call.ended event received' });
|
|
8903
8913
|
}
|
|
8904
8914
|
};
|
|
8905
8915
|
};
|
|
@@ -8975,7 +8985,7 @@ const watchLiveEnded = (dispatcher, call) => {
|
|
|
8975
8985
|
if (e.error && e.error.code !== ErrorCode.LIVE_ENDED)
|
|
8976
8986
|
return;
|
|
8977
8987
|
if (!call.permissionsContext.hasPermission(OwnCapability.JOIN_BACKSTAGE)) {
|
|
8978
|
-
call.leave().catch((err) => {
|
|
8988
|
+
call.leave({ reason: 'live ended' }).catch((err) => {
|
|
8979
8989
|
logger$1('error', 'Failed to leave call after live ended', err);
|
|
8980
8990
|
});
|
|
8981
8991
|
}
|
|
@@ -10621,13 +10631,14 @@ class InputMediaDeviceManagerState {
|
|
|
10621
10631
|
return notifyGranted();
|
|
10622
10632
|
}
|
|
10623
10633
|
let permissionState;
|
|
10624
|
-
const notify = () =>
|
|
10625
|
-
|
|
10626
|
-
|
|
10627
|
-
|
|
10628
|
-
|
|
10629
|
-
|
|
10630
|
-
|
|
10634
|
+
const notify = () => {
|
|
10635
|
+
subscriber.next(
|
|
10636
|
+
// In some browsers, the 'change' event doesn't reliably emit and hence,
|
|
10637
|
+
// permissionState stays in 'prompt' state forever.
|
|
10638
|
+
// Typically, this happens when a user grants one-time permission.
|
|
10639
|
+
// Instead of checking if a permission is granted, we check if it isn't denied
|
|
10640
|
+
permissionState.state !== 'denied');
|
|
10641
|
+
};
|
|
10631
10642
|
navigator.permissions
|
|
10632
10643
|
.query({ name: this.permissionName })
|
|
10633
10644
|
.then((permissionStatus) => {
|
|
@@ -11453,7 +11464,7 @@ class Call {
|
|
|
11453
11464
|
/**
|
|
11454
11465
|
* Leave the call and stop the media streams that were published by the call.
|
|
11455
11466
|
*/
|
|
11456
|
-
this.leave = async ({ reject = false } = {}) => {
|
|
11467
|
+
this.leave = async ({ reject = false, reason = 'user is leaving the call', } = {}) => {
|
|
11457
11468
|
const callingState = this.state.callingState;
|
|
11458
11469
|
if (callingState === exports.CallingState.LEFT) {
|
|
11459
11470
|
throw new Error('Cannot leave call that has already been left.');
|
|
@@ -11482,7 +11493,7 @@ class Call {
|
|
|
11482
11493
|
this.subscriber = undefined;
|
|
11483
11494
|
this.publisher?.close();
|
|
11484
11495
|
this.publisher = undefined;
|
|
11485
|
-
this.sfuClient?.close();
|
|
11496
|
+
this.sfuClient?.close(StreamSfuClient.NORMAL_CLOSURE, reason);
|
|
11486
11497
|
this.sfuClient = undefined;
|
|
11487
11498
|
this.dispatcher.offAll();
|
|
11488
11499
|
this.state.setCallingState(exports.CallingState.LEFT);
|
|
@@ -11657,7 +11668,7 @@ class Call {
|
|
|
11657
11668
|
/**
|
|
11658
11669
|
* A closure which hides away the re-connection logic.
|
|
11659
11670
|
*/
|
|
11660
|
-
const reconnect = async (strategy
|
|
11671
|
+
const reconnect = async (strategy, reason) => {
|
|
11661
11672
|
const currentState = this.state.callingState;
|
|
11662
11673
|
if (currentState === exports.CallingState.MIGRATING ||
|
|
11663
11674
|
currentState === exports.CallingState.RECONNECTING) {
|
|
@@ -11679,7 +11690,7 @@ class Call {
|
|
|
11679
11690
|
// we'll need it for restoring the previous publishing state later
|
|
11680
11691
|
const localParticipant = this.state.localParticipant;
|
|
11681
11692
|
if (strategy === 'fast') {
|
|
11682
|
-
sfuClient.close(StreamSfuClient.ERROR_CONNECTION_BROKEN,
|
|
11693
|
+
sfuClient.close(StreamSfuClient.ERROR_CONNECTION_BROKEN, `attempting fast reconnect: ${reason}`);
|
|
11683
11694
|
}
|
|
11684
11695
|
else if (strategy === 'full') {
|
|
11685
11696
|
// in migration or recovery scenarios, we don't want to
|
|
@@ -11695,7 +11706,7 @@ class Call {
|
|
|
11695
11706
|
this.sfuStatsReporter?.stop();
|
|
11696
11707
|
this.sfuStatsReporter = undefined;
|
|
11697
11708
|
// clean up current connection
|
|
11698
|
-
sfuClient.close(StreamSfuClient.NORMAL_CLOSURE,
|
|
11709
|
+
sfuClient.close(StreamSfuClient.NORMAL_CLOSURE, `attempting full reconnect: ${reason}`);
|
|
11699
11710
|
}
|
|
11700
11711
|
await this.join({
|
|
11701
11712
|
...data,
|
|
@@ -11703,7 +11714,7 @@ class Call {
|
|
|
11703
11714
|
});
|
|
11704
11715
|
// clean up previous connection
|
|
11705
11716
|
if (strategy === 'migrate') {
|
|
11706
|
-
sfuClient.close(StreamSfuClient.NORMAL_CLOSURE, '
|
|
11717
|
+
sfuClient.close(StreamSfuClient.NORMAL_CLOSURE, 'attempting migration');
|
|
11707
11718
|
}
|
|
11708
11719
|
this.logger('info', `[Rejoin]: Attempt ${this.reconnectAttempts} successful!`);
|
|
11709
11720
|
// we shouldn't be republishing the streams if we're migrating
|
|
@@ -11742,7 +11753,7 @@ class Call {
|
|
|
11742
11753
|
const unregisterGoAway = this.dispatcher.on('goAway', (event) => {
|
|
11743
11754
|
const { reason } = event;
|
|
11744
11755
|
this.logger('info', `[Migration]: Going away from SFU... Reason: ${GoAwayReason[reason]}`);
|
|
11745
|
-
reconnect('migrate').catch((err) => {
|
|
11756
|
+
reconnect('migrate', GoAwayReason[reason]).catch((err) => {
|
|
11746
11757
|
this.logger('warn', `[Migration]: Failed to migrate to another SFU.`, err);
|
|
11747
11758
|
});
|
|
11748
11759
|
});
|
|
@@ -11772,7 +11783,7 @@ class Call {
|
|
|
11772
11783
|
if (this.reconnectAttempts < this.maxReconnectAttempts) {
|
|
11773
11784
|
sfuClient.isFastReconnecting = this.reconnectAttempts === 0;
|
|
11774
11785
|
const strategy = sfuClient.isFastReconnecting ? 'fast' : 'full';
|
|
11775
|
-
reconnect(strategy).catch((err) => {
|
|
11786
|
+
reconnect(strategy, `SFU closed the WS with code: ${e.code}`).catch((err) => {
|
|
11776
11787
|
this.logger('error', `[Rejoin]: ${strategy} rejoin failed for ${this.reconnectAttempts} times. Giving up.`, err);
|
|
11777
11788
|
this.state.setCallingState(exports.CallingState.RECONNECTING_FAILED);
|
|
11778
11789
|
});
|
|
@@ -11800,7 +11811,7 @@ class Call {
|
|
|
11800
11811
|
do {
|
|
11801
11812
|
try {
|
|
11802
11813
|
sfuClient.isFastReconnecting = isFirstReconnectAttempt;
|
|
11803
|
-
await reconnect(isFirstReconnectAttempt ? 'fast' : 'full');
|
|
11814
|
+
await reconnect(isFirstReconnectAttempt ? 'fast' : 'full', 'Network: online');
|
|
11804
11815
|
return; // break the loop if rejoin is successful
|
|
11805
11816
|
}
|
|
11806
11817
|
catch (err) {
|
|
@@ -11909,7 +11920,7 @@ class Call {
|
|
|
11909
11920
|
}
|
|
11910
11921
|
else if (previousSfuClient?.isFastReconnecting) {
|
|
11911
11922
|
// reconnection wasn't possible, so we need to do a full rejoin
|
|
11912
|
-
return await reconnect('full').catch((err) => {
|
|
11923
|
+
return await reconnect('full', 're-attempting').catch((err) => {
|
|
11913
11924
|
this.logger('error', `[Rejoin]: Rejoin failed forced full rejoin.`, err);
|
|
11914
11925
|
});
|
|
11915
11926
|
}
|
|
@@ -11962,7 +11973,7 @@ class Call {
|
|
|
11962
11973
|
// join failed, try to rejoin
|
|
11963
11974
|
if (this.reconnectAttempts < this.maxReconnectAttempts) {
|
|
11964
11975
|
this.logger('error', `[Rejoin]: Rejoin ${this.reconnectAttempts} failed.`, err);
|
|
11965
|
-
await reconnect();
|
|
11976
|
+
await reconnect('full', 'previous attempt failed');
|
|
11966
11977
|
this.logger('info', `[Rejoin]: Rejoin ${this.reconnectAttempts} successful!`);
|
|
11967
11978
|
}
|
|
11968
11979
|
else {
|
|
@@ -12481,7 +12492,7 @@ class Call {
|
|
|
12481
12492
|
return;
|
|
12482
12493
|
clearTimeout(this.dropTimeout);
|
|
12483
12494
|
this.dropTimeout = setTimeout(() => {
|
|
12484
|
-
this.leave().catch((err) => {
|
|
12495
|
+
this.leave({ reason: 'ring: timeout' }).catch((err) => {
|
|
12485
12496
|
this.logger('error', 'Failed to drop call', err);
|
|
12486
12497
|
});
|
|
12487
12498
|
}, timeoutInMs);
|
|
@@ -12700,7 +12711,7 @@ class Call {
|
|
|
12700
12711
|
const currentUserId = this.currentUserId;
|
|
12701
12712
|
if (currentUserId && blockedUserIds.includes(currentUserId)) {
|
|
12702
12713
|
this.logger('info', 'Leaving call because of being blocked');
|
|
12703
|
-
await this.leave();
|
|
12714
|
+
await this.leave({ reason: 'user blocked' });
|
|
12704
12715
|
}
|
|
12705
12716
|
}));
|
|
12706
12717
|
this.leaveCallHooks.add(
|
|
@@ -14382,7 +14393,7 @@ class StreamClient {
|
|
|
14382
14393
|
});
|
|
14383
14394
|
};
|
|
14384
14395
|
this.getUserAgent = () => {
|
|
14385
|
-
const version = "0.6.
|
|
14396
|
+
const version = "0.6.5" ;
|
|
14386
14397
|
return (this.userAgent ||
|
|
14387
14398
|
`stream-video-javascript-client-${this.node ? 'node' : 'browser'}-${version}`);
|
|
14388
14399
|
};
|
|
@@ -14845,7 +14856,7 @@ class StreamVideoClient {
|
|
|
14845
14856
|
// if `call.created` was received before `call.ring`.
|
|
14846
14857
|
// In that case, we cleanup the already tracked call.
|
|
14847
14858
|
const prevCall = this.writeableStateStore.findCall(call.type, call.id);
|
|
14848
|
-
await prevCall?.leave();
|
|
14859
|
+
await prevCall?.leave({ reason: 'cleaning-up in call.ring' });
|
|
14849
14860
|
// we create a new call
|
|
14850
14861
|
const theCall = new Call({
|
|
14851
14862
|
streamClient: this.streamClient,
|