@stream-io/video-client 1.31.0 → 1.32.0
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 +11 -0
- package/dist/index.browser.es.js +45 -11
- package/dist/index.browser.es.js.map +1 -1
- package/dist/index.cjs.js +45 -11
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.es.js +45 -11
- package/dist/index.es.js.map +1 -1
- package/dist/src/StreamVideoClient.d.ts +2 -0
- package/dist/src/coordinator/connection/types.d.ts +4 -0
- package/dist/src/gen/video/sfu/event/events.d.ts +8 -0
- package/package.json +1 -1
- package/src/Call.ts +6 -6
- package/src/StreamVideoClient.ts +42 -3
- package/src/coordinator/connection/types.ts +5 -0
- package/src/gen/video/sfu/event/events.ts +14 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,17 @@
|
|
|
2
2
|
|
|
3
3
|
This file was generated using [@jscutlery/semver](https://github.com/jscutlery/semver).
|
|
4
4
|
|
|
5
|
+
## [1.32.0](https://github.com/GetStream/stream-video-js/compare/@stream-io/video-client-1.31.0...@stream-io/video-client-1.32.0) (2025-09-29)
|
|
6
|
+
|
|
7
|
+
### Features
|
|
8
|
+
|
|
9
|
+
- **react-native:** reject call when busy ([#1856](https://github.com/GetStream/stream-video-js/issues/1856)) ([b60bc7c](https://github.com/GetStream/stream-video-js/commit/b60bc7cd2dc2e09d52496d7b5cb593cac4b89485))
|
|
10
|
+
|
|
11
|
+
### Bug Fixes
|
|
12
|
+
|
|
13
|
+
- restore calling state after unrecoverable join fail ([#1935](https://github.com/GetStream/stream-video-js/issues/1935)) ([8ab0168](https://github.com/GetStream/stream-video-js/commit/8ab01680d01cc47f9cf48078634358507f0c109d))
|
|
14
|
+
- send unifiedSessionId in the initial join request ([#1934](https://github.com/GetStream/stream-video-js/issues/1934)) ([e6a533d](https://github.com/GetStream/stream-video-js/commit/e6a533d7e926086ac5930ebfb4648dade449d15a))
|
|
15
|
+
|
|
5
16
|
## [1.31.0](https://github.com/GetStream/stream-video-js/compare/@stream-io/video-client-1.30.1...@stream-io/video-client-1.31.0) (2025-09-17)
|
|
6
17
|
|
|
7
18
|
### Features
|
package/dist/index.browser.es.js
CHANGED
|
@@ -2949,6 +2949,12 @@ class JoinRequest$Type extends MessageType {
|
|
|
2949
2949
|
super('stream.video.sfu.event.JoinRequest', [
|
|
2950
2950
|
{ no: 1, name: 'token', kind: 'scalar', T: 9 /*ScalarType.STRING*/ },
|
|
2951
2951
|
{ no: 2, name: 'session_id', kind: 'scalar', T: 9 /*ScalarType.STRING*/ },
|
|
2952
|
+
{
|
|
2953
|
+
no: 13,
|
|
2954
|
+
name: 'unified_session_id',
|
|
2955
|
+
kind: 'scalar',
|
|
2956
|
+
T: 9 /*ScalarType.STRING*/,
|
|
2957
|
+
},
|
|
2952
2958
|
{
|
|
2953
2959
|
no: 3,
|
|
2954
2960
|
name: 'subscriber_sdp',
|
|
@@ -5758,7 +5764,7 @@ const getSdkVersion = (sdk) => {
|
|
|
5758
5764
|
return sdk ? `${sdk.major}.${sdk.minor}.${sdk.patch}` : '0.0.0-development';
|
|
5759
5765
|
};
|
|
5760
5766
|
|
|
5761
|
-
const version = "1.
|
|
5767
|
+
const version = "1.32.0";
|
|
5762
5768
|
const [major, minor, patch] = version.split('.');
|
|
5763
5769
|
let sdkInfo = {
|
|
5764
5770
|
type: SdkType.PLAIN_JAVASCRIPT,
|
|
@@ -11869,7 +11875,6 @@ class Call {
|
|
|
11869
11875
|
if ([CallingState.JOINED, CallingState.JOINING].includes(callingState)) {
|
|
11870
11876
|
throw new Error(`Illegal State: call.join() shall be called only once`);
|
|
11871
11877
|
}
|
|
11872
|
-
this.state.setCallingState(CallingState.JOINING);
|
|
11873
11878
|
// we will count the number of join failures per SFU.
|
|
11874
11879
|
// once the number of failures reaches 2, we will piggyback on the `migrating_from`
|
|
11875
11880
|
// field to force the coordinator to provide us another SFU
|
|
@@ -11898,8 +11903,6 @@ class Call {
|
|
|
11898
11903
|
joinData.migrating_from = sfuId;
|
|
11899
11904
|
}
|
|
11900
11905
|
if (attempt === maxJoinRetries - 1) {
|
|
11901
|
-
// restore the previous call state if the join-flow fails
|
|
11902
|
-
this.state.setCallingState(callingState);
|
|
11903
11906
|
throw err;
|
|
11904
11907
|
}
|
|
11905
11908
|
}
|
|
@@ -11959,6 +11962,7 @@ class Call {
|
|
|
11959
11962
|
})
|
|
11960
11963
|
: previousSfuClient;
|
|
11961
11964
|
this.sfuClient = sfuClient;
|
|
11965
|
+
this.unifiedSessionId ?? (this.unifiedSessionId = sfuClient.sessionId);
|
|
11962
11966
|
this.dynascaleManager.setSfuClient(sfuClient);
|
|
11963
11967
|
const clientDetails = await getClientDetails();
|
|
11964
11968
|
// we don't need to send JoinRequest if we are re-using an existing healthy SFU client
|
|
@@ -11982,6 +11986,7 @@ class Call {
|
|
|
11982
11986
|
: [];
|
|
11983
11987
|
try {
|
|
11984
11988
|
const { callState, fastReconnectDeadlineSeconds, publishOptions } = await sfuClient.join({
|
|
11989
|
+
unifiedSessionId: this.unifiedSessionId,
|
|
11985
11990
|
subscriberSdp,
|
|
11986
11991
|
publisherSdp,
|
|
11987
11992
|
clientDetails,
|
|
@@ -12027,6 +12032,7 @@ class Call {
|
|
|
12027
12032
|
statsOptions,
|
|
12028
12033
|
publishOptions: this.currentPublishOptions || [],
|
|
12029
12034
|
closePreviousInstances: !performingMigration,
|
|
12035
|
+
unifiedSessionId: this.unifiedSessionId,
|
|
12030
12036
|
});
|
|
12031
12037
|
}
|
|
12032
12038
|
// make sure we only track connection timing if we are not calling this method as part of a reconnection flow
|
|
@@ -12153,7 +12159,7 @@ class Call {
|
|
|
12153
12159
|
* @internal
|
|
12154
12160
|
*/
|
|
12155
12161
|
this.initPublisherAndSubscriber = (opts) => {
|
|
12156
|
-
const { sfuClient, connectionConfig, clientDetails, statsOptions, publishOptions, closePreviousInstances, } = opts;
|
|
12162
|
+
const { sfuClient, connectionConfig, clientDetails, statsOptions, publishOptions, closePreviousInstances, unifiedSessionId, } = opts;
|
|
12157
12163
|
const { enable_rtc_stats: enableTracing } = statsOptions;
|
|
12158
12164
|
if (closePreviousInstances && this.subscriber) {
|
|
12159
12165
|
this.subscriber.dispose();
|
|
@@ -12208,7 +12214,6 @@ class Call {
|
|
|
12208
12214
|
this.tracer.setEnabled(enableTracing);
|
|
12209
12215
|
this.sfuStatsReporter?.stop();
|
|
12210
12216
|
if (statsOptions?.reporting_interval_ms > 0) {
|
|
12211
|
-
this.unifiedSessionId ?? (this.unifiedSessionId = sfuClient.sessionId);
|
|
12212
12217
|
this.sfuStatsReporter = new SfuStatsReporter(sfuClient, {
|
|
12213
12218
|
clientDetails,
|
|
12214
12219
|
options: statsOptions,
|
|
@@ -12218,7 +12223,7 @@ class Call {
|
|
|
12218
12223
|
camera: this.camera,
|
|
12219
12224
|
state: this.state,
|
|
12220
12225
|
tracer: this.tracer,
|
|
12221
|
-
unifiedSessionId
|
|
12226
|
+
unifiedSessionId,
|
|
12222
12227
|
});
|
|
12223
12228
|
this.sfuStatsReporter.start();
|
|
12224
12229
|
}
|
|
@@ -14540,7 +14545,7 @@ class StreamClient {
|
|
|
14540
14545
|
this.getUserAgent = () => {
|
|
14541
14546
|
if (!this.cachedUserAgent) {
|
|
14542
14547
|
const { clientAppIdentifier = {} } = this.options;
|
|
14543
|
-
const { sdkName = 'js', sdkVersion = "1.
|
|
14548
|
+
const { sdkName = 'js', sdkVersion = "1.32.0", ...extras } = clientAppIdentifier;
|
|
14544
14549
|
this.cachedUserAgent = [
|
|
14545
14550
|
`stream-video-${sdkName}-v${sdkVersion}`,
|
|
14546
14551
|
...Object.entries(extras).map(([key, value]) => `${key}=${value}`),
|
|
@@ -14729,6 +14734,7 @@ class StreamVideoClient {
|
|
|
14729
14734
|
this.effectsRegistered = false;
|
|
14730
14735
|
this.eventHandlersToUnregister = [];
|
|
14731
14736
|
this.connectionConcurrencyTag = Symbol('connectionConcurrencyTag');
|
|
14737
|
+
this.rejectCallWhenBusy = false;
|
|
14732
14738
|
this.registerClientInstance = (apiKey, user) => {
|
|
14733
14739
|
const instanceKey = getInstanceKey(apiKey, user);
|
|
14734
14740
|
if (StreamVideoClient._instances.has(instanceKey)) {
|
|
@@ -14774,7 +14780,16 @@ class StreamVideoClient {
|
|
|
14774
14780
|
let call = this.writeableStateStore.findCall(e.call.type, e.call.id);
|
|
14775
14781
|
if (call) {
|
|
14776
14782
|
if (ringing) {
|
|
14777
|
-
|
|
14783
|
+
if (this.shouldRejectCall(call.cid)) {
|
|
14784
|
+
this.logger('info', `Leaving call with busy reject reason ${call.cid} because user is busy`);
|
|
14785
|
+
// remove the instance from the state store
|
|
14786
|
+
await call.leave();
|
|
14787
|
+
// explicitly reject the call with busy reason as calling state was not ringing before and leave would not call it therefore
|
|
14788
|
+
await call.reject('busy');
|
|
14789
|
+
}
|
|
14790
|
+
else {
|
|
14791
|
+
await call.updateFromRingingEvent(e);
|
|
14792
|
+
}
|
|
14778
14793
|
}
|
|
14779
14794
|
else {
|
|
14780
14795
|
call.state.updateFromCallResponse(e.call);
|
|
@@ -14789,11 +14804,19 @@ class StreamVideoClient {
|
|
|
14789
14804
|
clientStore: this.writeableStateStore,
|
|
14790
14805
|
ringing,
|
|
14791
14806
|
});
|
|
14792
|
-
call.state.updateFromCallResponse(e.call);
|
|
14793
14807
|
if (ringing) {
|
|
14794
|
-
|
|
14808
|
+
if (this.shouldRejectCall(call.cid)) {
|
|
14809
|
+
this.logger('info', `Rejecting call ${call.cid} because user is busy`);
|
|
14810
|
+
// call is not in the state store yet, so just reject api is enough
|
|
14811
|
+
await call.reject('busy');
|
|
14812
|
+
}
|
|
14813
|
+
else {
|
|
14814
|
+
await call.updateFromRingingEvent(e);
|
|
14815
|
+
await call.get();
|
|
14816
|
+
}
|
|
14795
14817
|
}
|
|
14796
14818
|
else {
|
|
14819
|
+
call.state.updateFromCallResponse(e.call);
|
|
14797
14820
|
this.writeableStateStore.registerCall(call);
|
|
14798
14821
|
this.logger('info', `New call created and registered: ${call.cid}`);
|
|
14799
14822
|
}
|
|
@@ -15060,6 +15083,16 @@ class StreamVideoClient {
|
|
|
15060
15083
|
this.connectAnonymousUser = async (user, tokenOrProvider) => {
|
|
15061
15084
|
return withoutConcurrency(this.connectionConcurrencyTag, () => this.streamClient.connectAnonymousUser(user, tokenOrProvider));
|
|
15062
15085
|
};
|
|
15086
|
+
this.shouldRejectCall = (currentCallId) => {
|
|
15087
|
+
if (!this.rejectCallWhenBusy)
|
|
15088
|
+
return false;
|
|
15089
|
+
const hasOngoingRingingCall = this.state.calls.some((c) => c.cid !== currentCallId &&
|
|
15090
|
+
c.ringing &&
|
|
15091
|
+
c.state.callingState !== CallingState.IDLE &&
|
|
15092
|
+
c.state.callingState !== CallingState.LEFT &&
|
|
15093
|
+
c.state.callingState !== CallingState.RECONNECTING_FAILED);
|
|
15094
|
+
return hasOngoingRingingCall;
|
|
15095
|
+
};
|
|
15063
15096
|
const apiKey = typeof apiKeyOrArgs === 'string' ? apiKeyOrArgs : apiKeyOrArgs.apiKey;
|
|
15064
15097
|
const clientOptions = typeof apiKeyOrArgs === 'string' ? opts : apiKeyOrArgs.options;
|
|
15065
15098
|
if (clientOptions?.enableTimerWorker)
|
|
@@ -15067,6 +15100,7 @@ class StreamVideoClient {
|
|
|
15067
15100
|
const rootLogger = clientOptions?.logger || logToConsole;
|
|
15068
15101
|
setLogger(rootLogger, clientOptions?.logLevel || 'warn');
|
|
15069
15102
|
this.logger = getLogger(['client']);
|
|
15103
|
+
this.rejectCallWhenBusy = clientOptions?.rejectCallWhenBusy ?? false;
|
|
15070
15104
|
this.streamClient = createCoordinatorClient(apiKey, clientOptions);
|
|
15071
15105
|
this.writeableStateStore = new StreamVideoWriteableStateStore();
|
|
15072
15106
|
this.readOnlyStateStore = new StreamVideoReadOnlyStateStore(this.writeableStateStore);
|