@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.browser.es.js +76 -49
- package/dist/index.browser.es.js.map +1 -1
- package/dist/index.cjs.js +76 -49
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.es.js +76 -49
- package/dist/index.es.js.map +1 -1
- package/dist/src/Call.d.ts +1 -1
- package/dist/src/types.d.ts +36 -5
- package/package.json +1 -1
- package/src/Call.ts +83 -62
- package/src/devices/SpeakerManager.ts +1 -0
- package/src/events/call.ts +3 -0
- package/src/types.ts +47 -5
package/dist/index.cjs.js
CHANGED
|
@@ -6251,7 +6251,7 @@ const getSdkVersion = (sdk) => {
|
|
|
6251
6251
|
return sdk ? `${sdk.major}.${sdk.minor}.${sdk.patch}` : '0.0.0-development';
|
|
6252
6252
|
};
|
|
6253
6253
|
|
|
6254
|
-
const version = "1.44.1-beta.
|
|
6254
|
+
const version = "1.44.1-beta.2";
|
|
6255
6255
|
const [major, minor, patch] = version.split('.');
|
|
6256
6256
|
let sdkInfo = {
|
|
6257
6257
|
type: SdkType.PLAIN_JAVASCRIPT,
|
|
@@ -8944,6 +8944,7 @@ const watchCallRejected = (call) => {
|
|
|
8944
8944
|
else {
|
|
8945
8945
|
if (rejectedBy[eventCall.created_by.id]) {
|
|
8946
8946
|
call.logger.info('call creator rejected, leaving call');
|
|
8947
|
+
globalThis.streamRNVideoSDK?.callingX?.endCall(call, 'remote');
|
|
8947
8948
|
await call.leave({ message: 'ring: creator rejected' });
|
|
8948
8949
|
}
|
|
8949
8950
|
}
|
|
@@ -8957,6 +8958,7 @@ const watchCallEnded = (call) => {
|
|
|
8957
8958
|
const { callingState } = call.state;
|
|
8958
8959
|
if (callingState !== exports.CallingState.IDLE &&
|
|
8959
8960
|
callingState !== exports.CallingState.LEFT) {
|
|
8961
|
+
globalThis.streamRNVideoSDK?.callingX?.endCall(call, 'remote');
|
|
8960
8962
|
call
|
|
8961
8963
|
.leave({ message: 'call.ended event received', reject: false })
|
|
8962
8964
|
.catch((err) => {
|
|
@@ -8985,6 +8987,7 @@ const watchSfuCallEnded = (call) => {
|
|
|
8985
8987
|
// update the call state to reflect the call has ended.
|
|
8986
8988
|
call.state.setEndedAt(new Date());
|
|
8987
8989
|
const reason = CallEndedReason[e.reason];
|
|
8990
|
+
globalThis.streamRNVideoSDK?.callingX?.endCall(call, 'remote');
|
|
8988
8991
|
await call.leave({ message: `callEnded received: ${reason}` });
|
|
8989
8992
|
}
|
|
8990
8993
|
catch (err) {
|
|
@@ -12499,6 +12502,7 @@ class SpeakerManager {
|
|
|
12499
12502
|
this.defaultDevice = defaultDevice;
|
|
12500
12503
|
globalThis.streamRNVideoSDK?.callManager.setup({
|
|
12501
12504
|
defaultDevice,
|
|
12505
|
+
isRingingTypeCall: this.call.ringing,
|
|
12502
12506
|
});
|
|
12503
12507
|
}
|
|
12504
12508
|
}
|
|
@@ -12698,6 +12702,7 @@ class Call {
|
|
|
12698
12702
|
const currentUserId = this.currentUserId;
|
|
12699
12703
|
if (currentUserId && blockedUserIds.includes(currentUserId)) {
|
|
12700
12704
|
this.logger.info('Leaving call because of being blocked');
|
|
12705
|
+
globalThis.streamRNVideoSDK?.callingX?.endCall(this, 'restricted');
|
|
12701
12706
|
await this.leave({ message: 'user blocked' }).catch((err) => {
|
|
12702
12707
|
this.logger.error('Error leaving call after being blocked', err);
|
|
12703
12708
|
});
|
|
@@ -12734,6 +12739,7 @@ class Call {
|
|
|
12734
12739
|
const isAcceptedElsewhere = isAcceptedByMe && this.state.callingState === exports.CallingState.RINGING;
|
|
12735
12740
|
if ((isAcceptedElsewhere || isRejectedByMe) &&
|
|
12736
12741
|
!hasPending(this.joinLeaveConcurrencyTag)) {
|
|
12742
|
+
globalThis.streamRNVideoSDK?.callingX?.endCall(this, isAcceptedElsewhere ? 'answeredElsewhere' : 'rejected');
|
|
12737
12743
|
this.leave().catch(() => {
|
|
12738
12744
|
this.logger.error('Could not leave a call that was accepted or rejected elsewhere');
|
|
12739
12745
|
});
|
|
@@ -12883,17 +12889,28 @@ class Call {
|
|
|
12883
12889
|
}
|
|
12884
12890
|
if (callingState === exports.CallingState.RINGING && reject !== false) {
|
|
12885
12891
|
if (reject) {
|
|
12886
|
-
|
|
12892
|
+
const reasonToEndCallReason = {
|
|
12893
|
+
timeout: 'missed',
|
|
12894
|
+
cancel: 'canceled',
|
|
12895
|
+
busy: 'busy',
|
|
12896
|
+
decline: 'rejected',
|
|
12897
|
+
};
|
|
12898
|
+
const rejectReason = reason ?? 'decline';
|
|
12899
|
+
const endCallReason = reasonToEndCallReason[rejectReason] ?? 'rejected';
|
|
12900
|
+
globalThis.streamRNVideoSDK?.callingX?.endCall(this, endCallReason);
|
|
12901
|
+
await this.reject(rejectReason);
|
|
12887
12902
|
}
|
|
12888
12903
|
else {
|
|
12889
12904
|
// if reject was undefined, we still have to cancel the call automatically
|
|
12890
12905
|
// when I am the creator and everyone else left the call
|
|
12891
12906
|
const hasOtherParticipants = this.state.remoteParticipants.length > 0;
|
|
12892
12907
|
if (this.isCreatedByMe && !hasOtherParticipants) {
|
|
12908
|
+
globalThis.streamRNVideoSDK?.callingX?.endCall(this, 'canceled');
|
|
12893
12909
|
await this.reject('cancel');
|
|
12894
12910
|
}
|
|
12895
12911
|
}
|
|
12896
12912
|
}
|
|
12913
|
+
globalThis.streamRNVideoSDK?.callingX?.endCall(this);
|
|
12897
12914
|
this.statsReporter?.stop();
|
|
12898
12915
|
this.statsReporter = undefined;
|
|
12899
12916
|
const leaveReason = message ?? reason ?? 'user is leaving the call';
|
|
@@ -12920,7 +12937,9 @@ class Call {
|
|
|
12920
12937
|
this.ringingSubject.next(false);
|
|
12921
12938
|
this.cancelAutoDrop();
|
|
12922
12939
|
this.clientStore.unregisterCall(this);
|
|
12923
|
-
globalThis.streamRNVideoSDK?.callManager.stop(
|
|
12940
|
+
globalThis.streamRNVideoSDK?.callManager.stop({
|
|
12941
|
+
isRingingTypeCall: this.ringing,
|
|
12942
|
+
});
|
|
12924
12943
|
this.camera.dispose();
|
|
12925
12944
|
this.microphone.dispose();
|
|
12926
12945
|
this.screenShare.dispose();
|
|
@@ -12964,8 +12983,7 @@ class Call {
|
|
|
12964
12983
|
// const calls = useCalls().filter((c) => c.ringing);
|
|
12965
12984
|
const calls = this.clientStore.calls.filter((c) => c.cid !== this.cid);
|
|
12966
12985
|
this.clientStore.setCalls([this, ...calls]);
|
|
12967
|
-
|
|
12968
|
-
await this.applyDeviceConfig(settings, false, skipSpeakerApply);
|
|
12986
|
+
await this.applyDeviceConfig(settings, false);
|
|
12969
12987
|
};
|
|
12970
12988
|
/**
|
|
12971
12989
|
* Loads the information about the call.
|
|
@@ -12988,10 +13006,7 @@ class Call {
|
|
|
12988
13006
|
this.watching = true;
|
|
12989
13007
|
this.clientStore.registerOrUpdateCall(this);
|
|
12990
13008
|
}
|
|
12991
|
-
|
|
12992
|
-
? (params?.ring ?? this.ringing)
|
|
12993
|
-
: false;
|
|
12994
|
-
await this.applyDeviceConfig(response.call.settings, false, skipSpeakerApply);
|
|
13009
|
+
await this.applyDeviceConfig(response.call.settings, false);
|
|
12995
13010
|
return response;
|
|
12996
13011
|
};
|
|
12997
13012
|
/**
|
|
@@ -13012,10 +13027,7 @@ class Call {
|
|
|
13012
13027
|
this.watching = true;
|
|
13013
13028
|
this.clientStore.registerOrUpdateCall(this);
|
|
13014
13029
|
}
|
|
13015
|
-
|
|
13016
|
-
? (data?.ring ?? this.ringing)
|
|
13017
|
-
: false;
|
|
13018
|
-
await this.applyDeviceConfig(response.call.settings, false, skipSpeakerApply);
|
|
13030
|
+
await this.applyDeviceConfig(response.call.settings, false);
|
|
13019
13031
|
return response;
|
|
13020
13032
|
};
|
|
13021
13033
|
/**
|
|
@@ -13080,11 +13092,19 @@ class Call {
|
|
|
13080
13092
|
* @returns a promise which resolves once the call join-flow has finished.
|
|
13081
13093
|
*/
|
|
13082
13094
|
this.join = async ({ maxJoinRetries = 3, joinResponseTimeout, rpcRequestTimeout, ...data } = {}) => {
|
|
13083
|
-
await this.setup();
|
|
13084
13095
|
const callingState = this.state.callingState;
|
|
13085
13096
|
if ([exports.CallingState.JOINED, exports.CallingState.JOINING].includes(callingState)) {
|
|
13086
13097
|
throw new Error(`Illegal State: call.join() shall be called only once`);
|
|
13087
13098
|
}
|
|
13099
|
+
if (data?.ring) {
|
|
13100
|
+
this.ringingSubject.next(true);
|
|
13101
|
+
}
|
|
13102
|
+
const callingX = globalThis.streamRNVideoSDK?.callingX;
|
|
13103
|
+
if (callingX) {
|
|
13104
|
+
// for Android/iOS, we need to start the call in the callingx library as soon as possible
|
|
13105
|
+
await callingX.startCall(this, this.clientStore.calls);
|
|
13106
|
+
}
|
|
13107
|
+
await this.setup();
|
|
13088
13108
|
this.joinResponseTimeout = joinResponseTimeout;
|
|
13089
13109
|
this.rpcRequestTimeout = rpcRequestTimeout;
|
|
13090
13110
|
// we will count the number of join failures per SFU.
|
|
@@ -13093,38 +13113,44 @@ class Call {
|
|
|
13093
13113
|
const sfuJoinFailures = new Map();
|
|
13094
13114
|
const joinData = data;
|
|
13095
13115
|
maxJoinRetries = Math.max(maxJoinRetries, 1);
|
|
13096
|
-
|
|
13097
|
-
|
|
13098
|
-
|
|
13099
|
-
|
|
13100
|
-
|
|
13101
|
-
|
|
13102
|
-
|
|
13103
|
-
|
|
13104
|
-
catch (err) {
|
|
13105
|
-
this.logger.warn(`Failed to join call (${attempt})`, this.cid);
|
|
13106
|
-
if ((err instanceof ErrorFromResponse && err.unrecoverable) ||
|
|
13107
|
-
(err instanceof SfuJoinError && err.unrecoverable)) {
|
|
13108
|
-
// if the error is unrecoverable, we should not retry as that signals
|
|
13109
|
-
// that connectivity is good, but the coordinator doesn't allow the user
|
|
13110
|
-
// to join the call due to some reason (e.g., ended call, expired token...)
|
|
13111
|
-
throw err;
|
|
13112
|
-
}
|
|
13113
|
-
// immediately switch to a different SFU in case of recoverable join error
|
|
13114
|
-
const switchSfu = err instanceof SfuJoinError &&
|
|
13115
|
-
SfuJoinError.isJoinErrorCode(err.errorEvent);
|
|
13116
|
-
const sfuId = this.credentials?.server.edge_name || '';
|
|
13117
|
-
const failures = (sfuJoinFailures.get(sfuId) || 0) + 1;
|
|
13118
|
-
sfuJoinFailures.set(sfuId, failures);
|
|
13119
|
-
if (switchSfu || failures >= 2) {
|
|
13120
|
-
joinData.migrating_from = sfuId;
|
|
13121
|
-
joinData.migrating_from_list = Array.from(sfuJoinFailures.keys());
|
|
13116
|
+
try {
|
|
13117
|
+
for (let attempt = 0; attempt < maxJoinRetries; attempt++) {
|
|
13118
|
+
try {
|
|
13119
|
+
this.logger.trace(`Joining call (${attempt})`, this.cid);
|
|
13120
|
+
await this.doJoin(data);
|
|
13121
|
+
delete joinData.migrating_from;
|
|
13122
|
+
delete joinData.migrating_from_list;
|
|
13123
|
+
break;
|
|
13122
13124
|
}
|
|
13123
|
-
|
|
13124
|
-
|
|
13125
|
+
catch (err) {
|
|
13126
|
+
this.logger.warn(`Failed to join call (${attempt})`, this.cid);
|
|
13127
|
+
if ((err instanceof ErrorFromResponse && err.unrecoverable) ||
|
|
13128
|
+
(err instanceof SfuJoinError && err.unrecoverable)) {
|
|
13129
|
+
// if the error is unrecoverable, we should not retry as that signals
|
|
13130
|
+
// that connectivity is good, but the coordinator doesn't allow the user
|
|
13131
|
+
// to join the call due to some reason (e.g., ended call, expired token...)
|
|
13132
|
+
throw err;
|
|
13133
|
+
}
|
|
13134
|
+
// immediately switch to a different SFU in case of recoverable join error
|
|
13135
|
+
const switchSfu = err instanceof SfuJoinError &&
|
|
13136
|
+
SfuJoinError.isJoinErrorCode(err.errorEvent);
|
|
13137
|
+
const sfuId = this.credentials?.server.edge_name || '';
|
|
13138
|
+
const failures = (sfuJoinFailures.get(sfuId) || 0) + 1;
|
|
13139
|
+
sfuJoinFailures.set(sfuId, failures);
|
|
13140
|
+
if (switchSfu || failures >= 2) {
|
|
13141
|
+
joinData.migrating_from = sfuId;
|
|
13142
|
+
joinData.migrating_from_list = Array.from(sfuJoinFailures.keys());
|
|
13143
|
+
}
|
|
13144
|
+
if (attempt === maxJoinRetries - 1) {
|
|
13145
|
+
throw err;
|
|
13146
|
+
}
|
|
13125
13147
|
}
|
|
13148
|
+
await sleep(retryInterval(attempt));
|
|
13126
13149
|
}
|
|
13127
|
-
|
|
13150
|
+
}
|
|
13151
|
+
catch (error) {
|
|
13152
|
+
callingX?.endCall(this, 'error');
|
|
13153
|
+
throw error;
|
|
13128
13154
|
}
|
|
13129
13155
|
};
|
|
13130
13156
|
/**
|
|
@@ -13271,7 +13297,9 @@ class Call {
|
|
|
13271
13297
|
// re-apply them on later reconnections or server-side data fetches
|
|
13272
13298
|
if (!this.deviceSettingsAppliedOnce && this.state.settings) {
|
|
13273
13299
|
await this.applyDeviceConfig(this.state.settings, true);
|
|
13274
|
-
globalThis.streamRNVideoSDK?.callManager.start(
|
|
13300
|
+
globalThis.streamRNVideoSDK?.callManager.start({
|
|
13301
|
+
isRingingTypeCall: this.ringing,
|
|
13302
|
+
});
|
|
13275
13303
|
this.deviceSettingsAppliedOnce = true;
|
|
13276
13304
|
}
|
|
13277
13305
|
// We shouldn't persist the `ring` and `notify` state after joining the call
|
|
@@ -13699,6 +13727,7 @@ class Call {
|
|
|
13699
13727
|
if (strategy === WebsocketReconnectStrategy.UNSPECIFIED)
|
|
13700
13728
|
return;
|
|
13701
13729
|
if (strategy === WebsocketReconnectStrategy.DISCONNECT) {
|
|
13730
|
+
globalThis.streamRNVideoSDK?.callingX?.endCall(this, 'error');
|
|
13702
13731
|
this.leave({ message: 'SFU instructed to disconnect' }).catch((err) => {
|
|
13703
13732
|
this.logger.warn(`Can't leave call after disconnect request`, err);
|
|
13704
13733
|
});
|
|
@@ -14528,10 +14557,8 @@ class Call {
|
|
|
14528
14557
|
*
|
|
14529
14558
|
* @internal
|
|
14530
14559
|
*/
|
|
14531
|
-
this.applyDeviceConfig = async (settings, publish
|
|
14532
|
-
|
|
14533
|
-
this.speaker.apply(settings);
|
|
14534
|
-
}
|
|
14560
|
+
this.applyDeviceConfig = async (settings, publish) => {
|
|
14561
|
+
this.speaker.apply(settings);
|
|
14535
14562
|
await this.camera.apply(settings.video, publish).catch((err) => {
|
|
14536
14563
|
this.logger.warn('Camera init failed', err);
|
|
14537
14564
|
});
|
|
@@ -15844,7 +15871,7 @@ class StreamClient {
|
|
|
15844
15871
|
this.getUserAgent = () => {
|
|
15845
15872
|
if (!this.cachedUserAgent) {
|
|
15846
15873
|
const { clientAppIdentifier = {} } = this.options;
|
|
15847
|
-
const { sdkName = 'js', sdkVersion = "1.44.1-beta.
|
|
15874
|
+
const { sdkName = 'js', sdkVersion = "1.44.1-beta.2", ...extras } = clientAppIdentifier;
|
|
15848
15875
|
this.cachedUserAgent = [
|
|
15849
15876
|
`stream-video-${sdkName}-v${sdkVersion}`,
|
|
15850
15877
|
...Object.entries(extras).map(([key, value]) => `${key}=${value}`),
|