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