@stream-io/video-client 1.44.1-beta.1 → 1.44.1-beta.2

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.es.js CHANGED
@@ -6232,7 +6232,7 @@ const getSdkVersion = (sdk) => {
6232
6232
  return sdk ? `${sdk.major}.${sdk.minor}.${sdk.patch}` : '0.0.0-development';
6233
6233
  };
6234
6234
 
6235
- const version = "1.44.1-beta.1";
6235
+ const version = "1.44.1-beta.2";
6236
6236
  const [major, minor, patch] = version.split('.');
6237
6237
  let sdkInfo = {
6238
6238
  type: SdkType.PLAIN_JAVASCRIPT,
@@ -8925,6 +8925,7 @@ const watchCallRejected = (call) => {
8925
8925
  else {
8926
8926
  if (rejectedBy[eventCall.created_by.id]) {
8927
8927
  call.logger.info('call creator rejected, leaving call');
8928
+ globalThis.streamRNVideoSDK?.callingX?.endCall(call, 'remote');
8928
8929
  await call.leave({ message: 'ring: creator rejected' });
8929
8930
  }
8930
8931
  }
@@ -8938,6 +8939,7 @@ const watchCallEnded = (call) => {
8938
8939
  const { callingState } = call.state;
8939
8940
  if (callingState !== CallingState.IDLE &&
8940
8941
  callingState !== CallingState.LEFT) {
8942
+ globalThis.streamRNVideoSDK?.callingX?.endCall(call, 'remote');
8941
8943
  call
8942
8944
  .leave({ message: 'call.ended event received', reject: false })
8943
8945
  .catch((err) => {
@@ -8966,6 +8968,7 @@ const watchSfuCallEnded = (call) => {
8966
8968
  // update the call state to reflect the call has ended.
8967
8969
  call.state.setEndedAt(new Date());
8968
8970
  const reason = CallEndedReason[e.reason];
8971
+ globalThis.streamRNVideoSDK?.callingX?.endCall(call, 'remote');
8969
8972
  await call.leave({ message: `callEnded received: ${reason}` });
8970
8973
  }
8971
8974
  catch (err) {
@@ -12480,6 +12483,7 @@ class SpeakerManager {
12480
12483
  this.defaultDevice = defaultDevice;
12481
12484
  globalThis.streamRNVideoSDK?.callManager.setup({
12482
12485
  defaultDevice,
12486
+ isRingingTypeCall: this.call.ringing,
12483
12487
  });
12484
12488
  }
12485
12489
  }
@@ -12679,6 +12683,7 @@ class Call {
12679
12683
  const currentUserId = this.currentUserId;
12680
12684
  if (currentUserId && blockedUserIds.includes(currentUserId)) {
12681
12685
  this.logger.info('Leaving call because of being blocked');
12686
+ globalThis.streamRNVideoSDK?.callingX?.endCall(this, 'restricted');
12682
12687
  await this.leave({ message: 'user blocked' }).catch((err) => {
12683
12688
  this.logger.error('Error leaving call after being blocked', err);
12684
12689
  });
@@ -12715,6 +12720,7 @@ class Call {
12715
12720
  const isAcceptedElsewhere = isAcceptedByMe && this.state.callingState === CallingState.RINGING;
12716
12721
  if ((isAcceptedElsewhere || isRejectedByMe) &&
12717
12722
  !hasPending(this.joinLeaveConcurrencyTag)) {
12723
+ globalThis.streamRNVideoSDK?.callingX?.endCall(this, isAcceptedElsewhere ? 'answeredElsewhere' : 'rejected');
12718
12724
  this.leave().catch(() => {
12719
12725
  this.logger.error('Could not leave a call that was accepted or rejected elsewhere');
12720
12726
  });
@@ -12864,17 +12870,28 @@ class Call {
12864
12870
  }
12865
12871
  if (callingState === CallingState.RINGING && reject !== false) {
12866
12872
  if (reject) {
12867
- await this.reject(reason ?? 'decline');
12873
+ const reasonToEndCallReason = {
12874
+ timeout: 'missed',
12875
+ cancel: 'canceled',
12876
+ busy: 'busy',
12877
+ decline: 'rejected',
12878
+ };
12879
+ const rejectReason = reason ?? 'decline';
12880
+ const endCallReason = reasonToEndCallReason[rejectReason] ?? 'rejected';
12881
+ globalThis.streamRNVideoSDK?.callingX?.endCall(this, endCallReason);
12882
+ await this.reject(rejectReason);
12868
12883
  }
12869
12884
  else {
12870
12885
  // if reject was undefined, we still have to cancel the call automatically
12871
12886
  // when I am the creator and everyone else left the call
12872
12887
  const hasOtherParticipants = this.state.remoteParticipants.length > 0;
12873
12888
  if (this.isCreatedByMe && !hasOtherParticipants) {
12889
+ globalThis.streamRNVideoSDK?.callingX?.endCall(this, 'canceled');
12874
12890
  await this.reject('cancel');
12875
12891
  }
12876
12892
  }
12877
12893
  }
12894
+ globalThis.streamRNVideoSDK?.callingX?.endCall(this);
12878
12895
  this.statsReporter?.stop();
12879
12896
  this.statsReporter = undefined;
12880
12897
  const leaveReason = message ?? reason ?? 'user is leaving the call';
@@ -12901,7 +12918,9 @@ class Call {
12901
12918
  this.ringingSubject.next(false);
12902
12919
  this.cancelAutoDrop();
12903
12920
  this.clientStore.unregisterCall(this);
12904
- globalThis.streamRNVideoSDK?.callManager.stop();
12921
+ globalThis.streamRNVideoSDK?.callManager.stop({
12922
+ isRingingTypeCall: this.ringing,
12923
+ });
12905
12924
  this.camera.dispose();
12906
12925
  this.microphone.dispose();
12907
12926
  this.screenShare.dispose();
@@ -12945,8 +12964,7 @@ class Call {
12945
12964
  // const calls = useCalls().filter((c) => c.ringing);
12946
12965
  const calls = this.clientStore.calls.filter((c) => c.cid !== this.cid);
12947
12966
  this.clientStore.setCalls([this, ...calls]);
12948
- const skipSpeakerApply = isReactNative() && true;
12949
- await this.applyDeviceConfig(settings, false, skipSpeakerApply);
12967
+ await this.applyDeviceConfig(settings, false);
12950
12968
  };
12951
12969
  /**
12952
12970
  * Loads the information about the call.
@@ -12969,10 +12987,7 @@ class Call {
12969
12987
  this.watching = true;
12970
12988
  this.clientStore.registerOrUpdateCall(this);
12971
12989
  }
12972
- const skipSpeakerApply = isReactNative()
12973
- ? (params?.ring ?? this.ringing)
12974
- : false;
12975
- await this.applyDeviceConfig(response.call.settings, false, skipSpeakerApply);
12990
+ await this.applyDeviceConfig(response.call.settings, false);
12976
12991
  return response;
12977
12992
  };
12978
12993
  /**
@@ -12993,10 +13008,7 @@ class Call {
12993
13008
  this.watching = true;
12994
13009
  this.clientStore.registerOrUpdateCall(this);
12995
13010
  }
12996
- const skipSpeakerApply = isReactNative()
12997
- ? (data?.ring ?? this.ringing)
12998
- : false;
12999
- await this.applyDeviceConfig(response.call.settings, false, skipSpeakerApply);
13011
+ await this.applyDeviceConfig(response.call.settings, false);
13000
13012
  return response;
13001
13013
  };
13002
13014
  /**
@@ -13061,11 +13073,19 @@ class Call {
13061
13073
  * @returns a promise which resolves once the call join-flow has finished.
13062
13074
  */
13063
13075
  this.join = async ({ maxJoinRetries = 3, joinResponseTimeout, rpcRequestTimeout, ...data } = {}) => {
13064
- await this.setup();
13065
13076
  const callingState = this.state.callingState;
13066
13077
  if ([CallingState.JOINED, CallingState.JOINING].includes(callingState)) {
13067
13078
  throw new Error(`Illegal State: call.join() shall be called only once`);
13068
13079
  }
13080
+ if (data?.ring) {
13081
+ this.ringingSubject.next(true);
13082
+ }
13083
+ const callingX = globalThis.streamRNVideoSDK?.callingX;
13084
+ if (callingX) {
13085
+ // for Android/iOS, we need to start the call in the callingx library as soon as possible
13086
+ await callingX.startCall(this, this.clientStore.calls);
13087
+ }
13088
+ await this.setup();
13069
13089
  this.joinResponseTimeout = joinResponseTimeout;
13070
13090
  this.rpcRequestTimeout = rpcRequestTimeout;
13071
13091
  // we will count the number of join failures per SFU.
@@ -13074,38 +13094,44 @@ class Call {
13074
13094
  const sfuJoinFailures = new Map();
13075
13095
  const joinData = data;
13076
13096
  maxJoinRetries = Math.max(maxJoinRetries, 1);
13077
- for (let attempt = 0; attempt < maxJoinRetries; attempt++) {
13078
- try {
13079
- this.logger.trace(`Joining call (${attempt})`, this.cid);
13080
- await this.doJoin(data);
13081
- delete joinData.migrating_from;
13082
- delete joinData.migrating_from_list;
13083
- break;
13084
- }
13085
- catch (err) {
13086
- this.logger.warn(`Failed to join call (${attempt})`, this.cid);
13087
- if ((err instanceof ErrorFromResponse && err.unrecoverable) ||
13088
- (err instanceof SfuJoinError && err.unrecoverable)) {
13089
- // if the error is unrecoverable, we should not retry as that signals
13090
- // that connectivity is good, but the coordinator doesn't allow the user
13091
- // to join the call due to some reason (e.g., ended call, expired token...)
13092
- throw err;
13093
- }
13094
- // immediately switch to a different SFU in case of recoverable join error
13095
- const switchSfu = err instanceof SfuJoinError &&
13096
- SfuJoinError.isJoinErrorCode(err.errorEvent);
13097
- const sfuId = this.credentials?.server.edge_name || '';
13098
- const failures = (sfuJoinFailures.get(sfuId) || 0) + 1;
13099
- sfuJoinFailures.set(sfuId, failures);
13100
- if (switchSfu || failures >= 2) {
13101
- joinData.migrating_from = sfuId;
13102
- joinData.migrating_from_list = Array.from(sfuJoinFailures.keys());
13097
+ try {
13098
+ for (let attempt = 0; attempt < maxJoinRetries; attempt++) {
13099
+ try {
13100
+ this.logger.trace(`Joining call (${attempt})`, this.cid);
13101
+ await this.doJoin(data);
13102
+ delete joinData.migrating_from;
13103
+ delete joinData.migrating_from_list;
13104
+ break;
13103
13105
  }
13104
- if (attempt === maxJoinRetries - 1) {
13105
- throw err;
13106
+ catch (err) {
13107
+ this.logger.warn(`Failed to join call (${attempt})`, this.cid);
13108
+ if ((err instanceof ErrorFromResponse && err.unrecoverable) ||
13109
+ (err instanceof SfuJoinError && err.unrecoverable)) {
13110
+ // if the error is unrecoverable, we should not retry as that signals
13111
+ // that connectivity is good, but the coordinator doesn't allow the user
13112
+ // to join the call due to some reason (e.g., ended call, expired token...)
13113
+ throw err;
13114
+ }
13115
+ // immediately switch to a different SFU in case of recoverable join error
13116
+ const switchSfu = err instanceof SfuJoinError &&
13117
+ SfuJoinError.isJoinErrorCode(err.errorEvent);
13118
+ const sfuId = this.credentials?.server.edge_name || '';
13119
+ const failures = (sfuJoinFailures.get(sfuId) || 0) + 1;
13120
+ sfuJoinFailures.set(sfuId, failures);
13121
+ if (switchSfu || failures >= 2) {
13122
+ joinData.migrating_from = sfuId;
13123
+ joinData.migrating_from_list = Array.from(sfuJoinFailures.keys());
13124
+ }
13125
+ if (attempt === maxJoinRetries - 1) {
13126
+ throw err;
13127
+ }
13106
13128
  }
13129
+ await sleep(retryInterval(attempt));
13107
13130
  }
13108
- await sleep(retryInterval(attempt));
13131
+ }
13132
+ catch (error) {
13133
+ callingX?.endCall(this, 'error');
13134
+ throw error;
13109
13135
  }
13110
13136
  };
13111
13137
  /**
@@ -13252,7 +13278,9 @@ class Call {
13252
13278
  // re-apply them on later reconnections or server-side data fetches
13253
13279
  if (!this.deviceSettingsAppliedOnce && this.state.settings) {
13254
13280
  await this.applyDeviceConfig(this.state.settings, true);
13255
- globalThis.streamRNVideoSDK?.callManager.start();
13281
+ globalThis.streamRNVideoSDK?.callManager.start({
13282
+ isRingingTypeCall: this.ringing,
13283
+ });
13256
13284
  this.deviceSettingsAppliedOnce = true;
13257
13285
  }
13258
13286
  // We shouldn't persist the `ring` and `notify` state after joining the call
@@ -13680,6 +13708,7 @@ class Call {
13680
13708
  if (strategy === WebsocketReconnectStrategy.UNSPECIFIED)
13681
13709
  return;
13682
13710
  if (strategy === WebsocketReconnectStrategy.DISCONNECT) {
13711
+ globalThis.streamRNVideoSDK?.callingX?.endCall(this, 'error');
13683
13712
  this.leave({ message: 'SFU instructed to disconnect' }).catch((err) => {
13684
13713
  this.logger.warn(`Can't leave call after disconnect request`, err);
13685
13714
  });
@@ -14509,10 +14538,8 @@ class Call {
14509
14538
  *
14510
14539
  * @internal
14511
14540
  */
14512
- this.applyDeviceConfig = async (settings, publish, skipSpeakerApply = false) => {
14513
- if (!skipSpeakerApply) {
14514
- this.speaker.apply(settings);
14515
- }
14541
+ this.applyDeviceConfig = async (settings, publish) => {
14542
+ this.speaker.apply(settings);
14516
14543
  await this.camera.apply(settings.video, publish).catch((err) => {
14517
14544
  this.logger.warn('Camera init failed', err);
14518
14545
  });
@@ -15825,7 +15852,7 @@ class StreamClient {
15825
15852
  this.getUserAgent = () => {
15826
15853
  if (!this.cachedUserAgent) {
15827
15854
  const { clientAppIdentifier = {} } = this.options;
15828
- const { sdkName = 'js', sdkVersion = "1.44.1-beta.1", ...extras } = clientAppIdentifier;
15855
+ const { sdkName = 'js', sdkVersion = "1.44.1-beta.2", ...extras } = clientAppIdentifier;
15829
15856
  this.cachedUserAgent = [
15830
15857
  `stream-video-${sdkName}-v${sdkVersion}`,
15831
15858
  ...Object.entries(extras).map(([key, value]) => `${key}=${value}`),