@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/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.leave().catch((err) => {
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 = StreamSfuClient.NORMAL_CLOSURE, reason = 'js-client: requested signal connection close') => {
8631
- this.logger('debug', 'Closing SFU WS connection', code, reason);
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 = () => subscriber.next(
10625
- // In Safari, the `change` event doesn't reliably emit and hence,
10626
- // permissionState stays in 'prompt' state forever.
10627
- // Instead of checking if a permission is granted, we check if it isn't denied
10628
- isSafari()
10629
- ? permissionState.state !== 'denied'
10630
- : permissionState.state === 'granted');
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 = 'full') => {
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, 'js-client: attempting fast reconnect');
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, 'js-client: attempting full reconnect');
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, 'js-client: attempting migration');
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.4" ;
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,