@stream-io/video-client 1.44.1-beta.1 → 1.44.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/CHANGELOG.md +12 -0
- package/dist/index.browser.es.js +86 -27
- package/dist/index.browser.es.js.map +1 -1
- package/dist/index.cjs.js +86 -27
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.es.js +86 -27
- package/dist/index.es.js.map +1 -1
- package/dist/src/Call.d.ts +1 -1
- package/dist/src/rtc/BasePeerConnection.d.ts +2 -2
- package/dist/src/rtc/Dispatcher.d.ts +25 -5
- package/package.json +1 -1
- package/src/Call.ts +11 -5
- package/src/StreamVideoClient.ts +2 -1
- package/src/rtc/BasePeerConnection.ts +6 -3
- package/src/rtc/Dispatcher.ts +82 -20
- package/src/rtc/__tests__/Dispatcher.test.ts +54 -0
- package/src/rtc/__tests__/Subscriber.test.ts +39 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
This file was generated using [@jscutlery/semver](https://github.com/jscutlery/semver).
|
|
4
4
|
|
|
5
|
+
## [1.44.2](https://github.com/GetStream/stream-video-js/compare/@stream-io/video-client-1.44.1...@stream-io/video-client-1.44.2) (2026-03-06)
|
|
6
|
+
|
|
7
|
+
### Bug Fixes
|
|
8
|
+
|
|
9
|
+
- do not setup speaker early for ringing type calls ([#2154](https://github.com/GetStream/stream-video-js/issues/2154)) ([57adb90](https://github.com/GetStream/stream-video-js/commit/57adb90f03cfaceb4e6d3c050feaea239b80b1d9))
|
|
10
|
+
|
|
11
|
+
## [1.44.1](https://github.com/GetStream/stream-video-js/compare/@stream-io/video-client-1.44.0...@stream-io/video-client-1.44.1) (2026-03-04)
|
|
12
|
+
|
|
13
|
+
### Bug Fixes
|
|
14
|
+
|
|
15
|
+
- **client:** handle SFU tag changes during reconnect ([#2149](https://github.com/GetStream/stream-video-js/issues/2149)) ([5aa89d3](https://github.com/GetStream/stream-video-js/commit/5aa89d378a73d33d8e46a6eb40e688bd0f50cca9)), closes [#2121](https://github.com/GetStream/stream-video-js/issues/2121)
|
|
16
|
+
|
|
5
17
|
## [1.44.0](https://github.com/GetStream/stream-video-js/compare/@stream-io/video-client-1.43.0...@stream-io/video-client-1.44.0) (2026-02-27)
|
|
6
18
|
|
|
7
19
|
- update agent instructions [skip ci] ([9cec4c6](https://github.com/GetStream/stream-video-js/commit/9cec4c6431ff51549fcfc870a0df935b0b8aa850))
|
package/dist/index.browser.es.js
CHANGED
|
@@ -4283,7 +4283,7 @@ const isSfuEvent = (eventName) => {
|
|
|
4283
4283
|
class Dispatcher {
|
|
4284
4284
|
constructor() {
|
|
4285
4285
|
this.logger = videoLoggerSystem.getLogger('Dispatcher');
|
|
4286
|
-
this.subscribers =
|
|
4286
|
+
this.subscribers = new Map();
|
|
4287
4287
|
/**
|
|
4288
4288
|
* Dispatch an event to all subscribers.
|
|
4289
4289
|
*
|
|
@@ -4296,12 +4296,14 @@ class Dispatcher {
|
|
|
4296
4296
|
return;
|
|
4297
4297
|
const payload = message.eventPayload[eventKind];
|
|
4298
4298
|
this.logger.debug(`Dispatching ${eventKind}, tag=${tag}`, payload);
|
|
4299
|
-
const handlers = this.subscribers
|
|
4299
|
+
const handlers = this.subscribers.get(eventKind);
|
|
4300
4300
|
if (!handlers)
|
|
4301
4301
|
return;
|
|
4302
|
-
|
|
4302
|
+
const { byTag, dynamic } = handlers;
|
|
4303
|
+
this.emit(payload, byTag.get(tag));
|
|
4303
4304
|
if (tag !== '*')
|
|
4304
|
-
this.emit(payload,
|
|
4305
|
+
this.emit(payload, byTag.get('*'));
|
|
4306
|
+
this.emitDynamic(payload, tag, dynamic);
|
|
4305
4307
|
};
|
|
4306
4308
|
/**
|
|
4307
4309
|
* Emit an event to a list of listeners.
|
|
@@ -4311,26 +4313,54 @@ class Dispatcher {
|
|
|
4311
4313
|
*/
|
|
4312
4314
|
this.emit = (payload, listeners = []) => {
|
|
4313
4315
|
for (const listener of listeners) {
|
|
4314
|
-
|
|
4315
|
-
|
|
4316
|
-
|
|
4317
|
-
|
|
4318
|
-
|
|
4316
|
+
this.emitOne(payload, listener);
|
|
4317
|
+
}
|
|
4318
|
+
};
|
|
4319
|
+
/**
|
|
4320
|
+
* Emit an event to a list of listeners.
|
|
4321
|
+
*
|
|
4322
|
+
*/
|
|
4323
|
+
this.emitDynamic = (payload, tag, dynamic) => {
|
|
4324
|
+
for (const { tagSelector, listener } of dynamic) {
|
|
4325
|
+
const dynamicTag = tagSelector();
|
|
4326
|
+
if (dynamicTag === tag || (tag !== '*' && dynamicTag === '*')) {
|
|
4327
|
+
this.emitOne(payload, listener);
|
|
4319
4328
|
}
|
|
4320
4329
|
}
|
|
4321
4330
|
};
|
|
4331
|
+
/**
|
|
4332
|
+
* Emit an event to a single listener.
|
|
4333
|
+
* @param payload the event payload to emit.
|
|
4334
|
+
* @param listener the listener to emit the event to.
|
|
4335
|
+
*/
|
|
4336
|
+
this.emitOne = (payload, listener) => {
|
|
4337
|
+
try {
|
|
4338
|
+
listener(payload);
|
|
4339
|
+
}
|
|
4340
|
+
catch (e) {
|
|
4341
|
+
this.logger.warn('Listener failed with error', e);
|
|
4342
|
+
}
|
|
4343
|
+
};
|
|
4322
4344
|
/**
|
|
4323
4345
|
* Subscribe to an event.
|
|
4324
4346
|
*
|
|
4325
4347
|
* @param eventName the name of the event to subscribe to.
|
|
4326
|
-
* @param tag for scoping events to a specific tag.
|
|
4348
|
+
* @param tag for scoping events to a specific tag. Can be a static tag
|
|
4349
|
+
* string or a function that resolves the tag dynamically.
|
|
4327
4350
|
* @param fn the callback function to invoke when the event is emitted.
|
|
4328
4351
|
* @returns a function that can be called to unsubscribe from the event.
|
|
4329
4352
|
*/
|
|
4330
4353
|
this.on = (eventName, tag, fn) => {
|
|
4331
|
-
|
|
4332
|
-
const
|
|
4333
|
-
(
|
|
4354
|
+
const { byTag, dynamic } = this.getHandlers(eventName);
|
|
4355
|
+
const listener = fn;
|
|
4356
|
+
if (typeof tag === 'string') {
|
|
4357
|
+
const listeners = byTag.get(tag) ?? [];
|
|
4358
|
+
listeners.push(listener);
|
|
4359
|
+
byTag.set(tag, listeners);
|
|
4360
|
+
}
|
|
4361
|
+
else {
|
|
4362
|
+
dynamic.push({ tagSelector: tag, listener });
|
|
4363
|
+
}
|
|
4334
4364
|
return () => {
|
|
4335
4365
|
this.off(eventName, tag, fn);
|
|
4336
4366
|
};
|
|
@@ -4339,15 +4369,35 @@ class Dispatcher {
|
|
|
4339
4369
|
* Unsubscribe from an event.
|
|
4340
4370
|
*
|
|
4341
4371
|
* @param eventName the name of the event to unsubscribe from.
|
|
4342
|
-
* @param tag
|
|
4372
|
+
* @param tag the original static/dynamic tag selector used during subscription.
|
|
4343
4373
|
* @param fn the callback function to remove from the event listeners.
|
|
4344
4374
|
*/
|
|
4345
4375
|
this.off = (eventName, tag, fn) => {
|
|
4346
|
-
const bucket = this.subscribers
|
|
4347
|
-
|
|
4348
|
-
if (!listeners)
|
|
4376
|
+
const bucket = this.subscribers.get(eventName);
|
|
4377
|
+
if (!bucket)
|
|
4349
4378
|
return;
|
|
4350
|
-
|
|
4379
|
+
const { byTag, dynamic } = bucket;
|
|
4380
|
+
if (typeof tag === 'string') {
|
|
4381
|
+
const listeners = byTag.get(tag) || [];
|
|
4382
|
+
const idx = listeners.indexOf(fn);
|
|
4383
|
+
if (idx >= 0)
|
|
4384
|
+
listeners.splice(idx, 1);
|
|
4385
|
+
}
|
|
4386
|
+
else {
|
|
4387
|
+
const idx = dynamic.findIndex(({ tagSelector, listener }) => {
|
|
4388
|
+
return tagSelector === tag && listener === fn;
|
|
4389
|
+
});
|
|
4390
|
+
if (idx >= 0)
|
|
4391
|
+
dynamic.splice(idx, 1);
|
|
4392
|
+
}
|
|
4393
|
+
};
|
|
4394
|
+
this.getHandlers = (eventName) => {
|
|
4395
|
+
const existing = this.subscribers.get(eventName);
|
|
4396
|
+
if (existing)
|
|
4397
|
+
return existing;
|
|
4398
|
+
const next = { byTag: new Map(), dynamic: [] };
|
|
4399
|
+
this.subscribers.set(eventName, next);
|
|
4400
|
+
return next;
|
|
4351
4401
|
};
|
|
4352
4402
|
}
|
|
4353
4403
|
}
|
|
@@ -6231,7 +6281,7 @@ const getSdkVersion = (sdk) => {
|
|
|
6231
6281
|
return sdk ? `${sdk.major}.${sdk.minor}.${sdk.patch}` : '0.0.0-development';
|
|
6232
6282
|
};
|
|
6233
6283
|
|
|
6234
|
-
const version = "1.44.
|
|
6284
|
+
const version = "1.44.2";
|
|
6235
6285
|
const [major, minor, patch] = version.split('.');
|
|
6236
6286
|
let sdkInfo = {
|
|
6237
6287
|
type: SdkType.PLAIN_JAVASCRIPT,
|
|
@@ -7298,7 +7348,8 @@ class BasePeerConnection {
|
|
|
7298
7348
|
* Consecutive events are queued and executed one after the other.
|
|
7299
7349
|
*/
|
|
7300
7350
|
this.on = (event, fn) => {
|
|
7301
|
-
|
|
7351
|
+
const getTag = () => this.tag;
|
|
7352
|
+
this.subscriptions.push(this.dispatcher.on(event, getTag, (e) => {
|
|
7302
7353
|
const lockKey = `pc.${this.lock}.${event}`;
|
|
7303
7354
|
withoutConcurrency(lockKey, async () => fn(e)).catch((err) => {
|
|
7304
7355
|
if (this.isDisposed)
|
|
@@ -7331,6 +7382,7 @@ class BasePeerConnection {
|
|
|
7331
7382
|
*/
|
|
7332
7383
|
this.setSfuClient = (sfuClient) => {
|
|
7333
7384
|
this.sfuClient = sfuClient;
|
|
7385
|
+
this.tag = sfuClient.tag;
|
|
7334
7386
|
};
|
|
7335
7387
|
/**
|
|
7336
7388
|
* Returns the result of the `RTCPeerConnection.getStats()` method
|
|
@@ -7521,6 +7573,7 @@ class BasePeerConnection {
|
|
|
7521
7573
|
pc.removeEventListener('icegatheringstatechange', this.onIceGatherChange);
|
|
7522
7574
|
this.unsubscribeIceTrickle?.();
|
|
7523
7575
|
this.subscriptions.forEach((unsubscribe) => unsubscribe());
|
|
7576
|
+
this.subscriptions = [];
|
|
7524
7577
|
}
|
|
7525
7578
|
}
|
|
7526
7579
|
|
|
@@ -12944,7 +12997,7 @@ class Call {
|
|
|
12944
12997
|
// const calls = useCalls().filter((c) => c.ringing);
|
|
12945
12998
|
const calls = this.clientStore.calls.filter((c) => c.cid !== this.cid);
|
|
12946
12999
|
this.clientStore.setCalls([this, ...calls]);
|
|
12947
|
-
const skipSpeakerApply = isReactNative()
|
|
13000
|
+
const skipSpeakerApply = isReactNative();
|
|
12948
13001
|
await this.applyDeviceConfig(settings, false, skipSpeakerApply);
|
|
12949
13002
|
};
|
|
12950
13003
|
/**
|
|
@@ -12968,8 +13021,11 @@ class Call {
|
|
|
12968
13021
|
this.watching = true;
|
|
12969
13022
|
this.clientStore.registerOrUpdateCall(this);
|
|
12970
13023
|
}
|
|
13024
|
+
// Skip speaker setup on RN if ringing was requested or the call is already ringing
|
|
12971
13025
|
const skipSpeakerApply = isReactNative()
|
|
12972
|
-
?
|
|
13026
|
+
? params?.ring === true
|
|
13027
|
+
? true
|
|
13028
|
+
: this.ringing
|
|
12973
13029
|
: false;
|
|
12974
13030
|
await this.applyDeviceConfig(response.call.settings, false, skipSpeakerApply);
|
|
12975
13031
|
return response;
|
|
@@ -12992,8 +13048,11 @@ class Call {
|
|
|
12992
13048
|
this.watching = true;
|
|
12993
13049
|
this.clientStore.registerOrUpdateCall(this);
|
|
12994
13050
|
}
|
|
13051
|
+
// Skip speaker setup on RN if ringing was requested or the call is already ringing
|
|
12995
13052
|
const skipSpeakerApply = isReactNative()
|
|
12996
|
-
?
|
|
13053
|
+
? data?.ring === true
|
|
13054
|
+
? true
|
|
13055
|
+
: this.ringing
|
|
12997
13056
|
: false;
|
|
12998
13057
|
await this.applyDeviceConfig(response.call.settings, false, skipSpeakerApply);
|
|
12999
13058
|
return response;
|
|
@@ -13250,7 +13309,7 @@ class Call {
|
|
|
13250
13309
|
// device settings should be applied only once, we don't have to
|
|
13251
13310
|
// re-apply them on later reconnections or server-side data fetches
|
|
13252
13311
|
if (!this.deviceSettingsAppliedOnce && this.state.settings) {
|
|
13253
|
-
await this.applyDeviceConfig(this.state.settings, true);
|
|
13312
|
+
await this.applyDeviceConfig(this.state.settings, true, false);
|
|
13254
13313
|
globalThis.streamRNVideoSDK?.callManager.start();
|
|
13255
13314
|
this.deviceSettingsAppliedOnce = true;
|
|
13256
13315
|
}
|
|
@@ -14508,7 +14567,7 @@ class Call {
|
|
|
14508
14567
|
*
|
|
14509
14568
|
* @internal
|
|
14510
14569
|
*/
|
|
14511
|
-
this.applyDeviceConfig = async (settings, publish, skipSpeakerApply
|
|
14570
|
+
this.applyDeviceConfig = async (settings, publish, skipSpeakerApply) => {
|
|
14512
14571
|
if (!skipSpeakerApply) {
|
|
14513
14572
|
this.speaker.apply(settings);
|
|
14514
14573
|
}
|
|
@@ -15826,7 +15885,7 @@ class StreamClient {
|
|
|
15826
15885
|
this.getUserAgent = () => {
|
|
15827
15886
|
if (!this.cachedUserAgent) {
|
|
15828
15887
|
const { clientAppIdentifier = {} } = this.options;
|
|
15829
|
-
const { sdkName = 'js', sdkVersion = "1.44.
|
|
15888
|
+
const { sdkName = 'js', sdkVersion = "1.44.2", ...extras } = clientAppIdentifier;
|
|
15830
15889
|
this.cachedUserAgent = [
|
|
15831
15890
|
`stream-video-${sdkName}-v${sdkVersion}`,
|
|
15832
15891
|
...Object.entries(extras).map(([key, value]) => `${key}=${value}`),
|
|
@@ -16261,7 +16320,7 @@ class StreamVideoClient {
|
|
|
16261
16320
|
clientStore: this.writeableStateStore,
|
|
16262
16321
|
});
|
|
16263
16322
|
call.state.updateFromCallResponse(c.call);
|
|
16264
|
-
await call.applyDeviceConfig(c.call.settings, false);
|
|
16323
|
+
await call.applyDeviceConfig(c.call.settings, false, isReactNative());
|
|
16265
16324
|
if (data.watch) {
|
|
16266
16325
|
await call.setup();
|
|
16267
16326
|
this.writeableStateStore.registerCall(call);
|