@stream-io/video-client 1.11.12 → 1.11.14
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 +14 -0
- package/dist/index.browser.es.js +168 -26
- package/dist/index.browser.es.js.map +1 -1
- package/dist/index.cjs.js +168 -26
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.es.js +168 -26
- package/dist/index.es.js.map +1 -1
- package/dist/src/coordinator/connection/connection.d.ts +1 -1
- package/dist/src/coordinator/connection/types.d.ts +5 -0
- package/dist/src/devices/BrowserPermission.d.ts +1 -1
- package/dist/src/timers/index.d.ts +22 -0
- package/dist/src/timers/types.d.ts +12 -0
- package/dist/src/timers/worker.build.d.ts +3 -0
- package/dist/src/timers/worker.d.ts +1 -0
- package/package.json +4 -3
- package/src/StreamSfuClient.ts +6 -4
- package/src/StreamVideoClient.ts +4 -0
- package/src/coordinator/connection/connection.ts +14 -5
- package/src/coordinator/connection/types.ts +6 -0
- package/src/devices/BrowserPermission.ts +1 -1
- package/src/devices/devices.ts +1 -2
- package/src/timers/index.ts +137 -0
- package/src/timers/types.ts +15 -0
- package/src/timers/worker.build.ts +26 -0
- package/src/timers/worker.ts +40 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,20 @@
|
|
|
2
2
|
|
|
3
3
|
This file was generated using [@jscutlery/semver](https://github.com/jscutlery/semver).
|
|
4
4
|
|
|
5
|
+
## [1.11.14](https://github.com/GetStream/stream-video-js/compare/@stream-io/video-client-1.11.13...@stream-io/video-client-1.11.14) (2024-12-04)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
### Bug Fixes
|
|
9
|
+
|
|
10
|
+
* prevent device list observable from erroring ([#1608](https://github.com/GetStream/stream-video-js/issues/1608)) ([06af3e7](https://github.com/GetStream/stream-video-js/commit/06af3e7e03b63551c781512c797ac10c0486d0c7))
|
|
11
|
+
|
|
12
|
+
## [1.11.13](https://github.com/GetStream/stream-video-js/compare/@stream-io/video-client-1.11.12...@stream-io/video-client-1.11.13) (2024-12-03)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
### Bug Fixes
|
|
16
|
+
|
|
17
|
+
* use worker to prevent timer throttling ([#1557](https://github.com/GetStream/stream-video-js/issues/1557)) ([c11c3ca](https://github.com/GetStream/stream-video-js/commit/c11c3caf455787fe531c83601bad71e7a0a0e9b9))
|
|
18
|
+
|
|
5
19
|
## [1.11.12](https://github.com/GetStream/stream-video-js/compare/@stream-io/video-client-1.11.11...@stream-io/video-client-1.11.12) (2024-12-03)
|
|
6
20
|
|
|
7
21
|
|
package/dist/index.browser.es.js
CHANGED
|
@@ -3297,7 +3297,7 @@ const retryable = async (rpc, signal) => {
|
|
|
3297
3297
|
return result;
|
|
3298
3298
|
};
|
|
3299
3299
|
|
|
3300
|
-
const version = "1.11.
|
|
3300
|
+
const version = "1.11.14";
|
|
3301
3301
|
const [major, minor, patch] = version.split('.');
|
|
3302
3302
|
let sdkInfo = {
|
|
3303
3303
|
type: SdkType.PLAIN_JAVASCRIPT,
|
|
@@ -6432,6 +6432,151 @@ const promiseWithResolvers = () => {
|
|
|
6432
6432
|
};
|
|
6433
6433
|
};
|
|
6434
6434
|
|
|
6435
|
+
const uninitialized = Symbol('uninitialized');
|
|
6436
|
+
/**
|
|
6437
|
+
* Lazily creates a value using a provided factory
|
|
6438
|
+
*/
|
|
6439
|
+
function lazy(factory) {
|
|
6440
|
+
let value = uninitialized;
|
|
6441
|
+
return () => {
|
|
6442
|
+
if (value === uninitialized) {
|
|
6443
|
+
value = factory();
|
|
6444
|
+
}
|
|
6445
|
+
return value;
|
|
6446
|
+
};
|
|
6447
|
+
}
|
|
6448
|
+
|
|
6449
|
+
const timerWorker = {
|
|
6450
|
+
src: `var timerIdMapping = new Map();
|
|
6451
|
+
self.addEventListener('message', function (event) {
|
|
6452
|
+
var request = event.data;
|
|
6453
|
+
switch (request.type) {
|
|
6454
|
+
case 'setTimeout':
|
|
6455
|
+
case 'setInterval':
|
|
6456
|
+
timerIdMapping.set(request.id, (request.type === 'setTimeout' ? setTimeout : setInterval)(function () {
|
|
6457
|
+
tick(request.id);
|
|
6458
|
+
if (request.type === 'setTimeout') {
|
|
6459
|
+
timerIdMapping.delete(request.id);
|
|
6460
|
+
}
|
|
6461
|
+
}, request.timeout));
|
|
6462
|
+
break;
|
|
6463
|
+
case 'clearTimeout':
|
|
6464
|
+
case 'clearInterval':
|
|
6465
|
+
(request.type === 'clearTimeout' ? clearTimeout : clearInterval)(timerIdMapping.get(request.id));
|
|
6466
|
+
timerIdMapping.delete(request.id);
|
|
6467
|
+
break;
|
|
6468
|
+
}
|
|
6469
|
+
});
|
|
6470
|
+
function tick(id) {
|
|
6471
|
+
var message = { type: 'tick', id: id };
|
|
6472
|
+
self.postMessage(message);
|
|
6473
|
+
}`,
|
|
6474
|
+
};
|
|
6475
|
+
|
|
6476
|
+
class TimerWorker {
|
|
6477
|
+
constructor() {
|
|
6478
|
+
this.currentTimerId = 1;
|
|
6479
|
+
this.callbacks = new Map();
|
|
6480
|
+
this.fallback = false;
|
|
6481
|
+
}
|
|
6482
|
+
setup({ useTimerWorker = true } = {}) {
|
|
6483
|
+
if (!useTimerWorker) {
|
|
6484
|
+
this.fallback = true;
|
|
6485
|
+
return;
|
|
6486
|
+
}
|
|
6487
|
+
try {
|
|
6488
|
+
const source = timerWorker.src;
|
|
6489
|
+
const blob = new Blob([source], {
|
|
6490
|
+
type: 'application/javascript; charset=utf-8',
|
|
6491
|
+
});
|
|
6492
|
+
const script = URL.createObjectURL(blob);
|
|
6493
|
+
this.worker = new Worker(script, { name: 'str-timer-worker' });
|
|
6494
|
+
this.worker.addEventListener('message', (event) => {
|
|
6495
|
+
const { type, id } = event.data;
|
|
6496
|
+
if (type === 'tick') {
|
|
6497
|
+
this.callbacks.get(id)?.();
|
|
6498
|
+
}
|
|
6499
|
+
});
|
|
6500
|
+
}
|
|
6501
|
+
catch (err) {
|
|
6502
|
+
getLogger(['timer-worker'])('error', err);
|
|
6503
|
+
this.fallback = true;
|
|
6504
|
+
}
|
|
6505
|
+
}
|
|
6506
|
+
destroy() {
|
|
6507
|
+
this.callbacks.clear();
|
|
6508
|
+
this.worker?.terminate();
|
|
6509
|
+
this.worker = undefined;
|
|
6510
|
+
this.fallback = false;
|
|
6511
|
+
}
|
|
6512
|
+
get ready() {
|
|
6513
|
+
return this.fallback || Boolean(this.worker);
|
|
6514
|
+
}
|
|
6515
|
+
setInterval(callback, timeout) {
|
|
6516
|
+
return this.setTimer('setInterval', callback, timeout);
|
|
6517
|
+
}
|
|
6518
|
+
clearInterval(id) {
|
|
6519
|
+
this.clearTimer('clearInterval', id);
|
|
6520
|
+
}
|
|
6521
|
+
setTimeout(callback, timeout) {
|
|
6522
|
+
return this.setTimer('setTimeout', callback, timeout);
|
|
6523
|
+
}
|
|
6524
|
+
clearTimeout(id) {
|
|
6525
|
+
this.clearTimer('clearTimeout', id);
|
|
6526
|
+
}
|
|
6527
|
+
setTimer(type, callback, timeout) {
|
|
6528
|
+
if (!this.ready) {
|
|
6529
|
+
this.setup();
|
|
6530
|
+
}
|
|
6531
|
+
if (this.fallback) {
|
|
6532
|
+
return (type === 'setTimeout' ? setTimeout : setInterval)(callback, timeout);
|
|
6533
|
+
}
|
|
6534
|
+
const id = this.getTimerId();
|
|
6535
|
+
this.callbacks.set(id, () => {
|
|
6536
|
+
callback();
|
|
6537
|
+
// Timeouts are one-off operations, so no need to keep callback reference
|
|
6538
|
+
// after timer has fired
|
|
6539
|
+
if (type === 'setTimeout') {
|
|
6540
|
+
this.callbacks.delete(id);
|
|
6541
|
+
}
|
|
6542
|
+
});
|
|
6543
|
+
this.sendMessage({ type, id, timeout });
|
|
6544
|
+
return id;
|
|
6545
|
+
}
|
|
6546
|
+
clearTimer(type, id) {
|
|
6547
|
+
if (!id) {
|
|
6548
|
+
return;
|
|
6549
|
+
}
|
|
6550
|
+
if (!this.ready) {
|
|
6551
|
+
this.setup();
|
|
6552
|
+
}
|
|
6553
|
+
if (this.fallback) {
|
|
6554
|
+
(type === 'clearTimeout' ? clearTimeout : clearInterval)(id);
|
|
6555
|
+
return;
|
|
6556
|
+
}
|
|
6557
|
+
this.callbacks.delete(id);
|
|
6558
|
+
this.sendMessage({ type, id });
|
|
6559
|
+
}
|
|
6560
|
+
getTimerId() {
|
|
6561
|
+
return this.currentTimerId++;
|
|
6562
|
+
}
|
|
6563
|
+
sendMessage(message) {
|
|
6564
|
+
if (!this.worker) {
|
|
6565
|
+
throw new Error("Cannot use timer worker before it's set up");
|
|
6566
|
+
}
|
|
6567
|
+
this.worker.postMessage(message);
|
|
6568
|
+
}
|
|
6569
|
+
}
|
|
6570
|
+
let timerWorkerEnabled = false;
|
|
6571
|
+
const enableTimerWorker = () => {
|
|
6572
|
+
timerWorkerEnabled = true;
|
|
6573
|
+
};
|
|
6574
|
+
const getTimers = lazy(() => {
|
|
6575
|
+
const instance = new TimerWorker();
|
|
6576
|
+
instance.setup({ useTimerWorker: timerWorkerEnabled });
|
|
6577
|
+
return instance;
|
|
6578
|
+
});
|
|
6579
|
+
|
|
6435
6580
|
/**
|
|
6436
6581
|
* The client used for exchanging information with the SFU.
|
|
6437
6582
|
*/
|
|
@@ -6490,7 +6635,7 @@ class StreamSfuClient {
|
|
|
6490
6635
|
};
|
|
6491
6636
|
this.handleWebSocketClose = () => {
|
|
6492
6637
|
this.signalWs.removeEventListener('close', this.handleWebSocketClose);
|
|
6493
|
-
clearInterval(this.keepAliveInterval);
|
|
6638
|
+
getTimers().clearInterval(this.keepAliveInterval);
|
|
6494
6639
|
clearTimeout(this.connectionCheckTimeout);
|
|
6495
6640
|
this.onSignalClose?.();
|
|
6496
6641
|
};
|
|
@@ -6646,8 +6791,9 @@ class StreamSfuClient {
|
|
|
6646
6791
|
this.signalWs.send(SfuRequest.toBinary(message));
|
|
6647
6792
|
};
|
|
6648
6793
|
this.keepAlive = () => {
|
|
6649
|
-
|
|
6650
|
-
this.keepAliveInterval
|
|
6794
|
+
const timers = getTimers();
|
|
6795
|
+
timers.clearInterval(this.keepAliveInterval);
|
|
6796
|
+
this.keepAliveInterval = timers.setInterval(() => {
|
|
6651
6797
|
this.ping().catch((e) => {
|
|
6652
6798
|
this.logger('error', 'Error sending healthCheckRequest to SFU', e);
|
|
6653
6799
|
});
|
|
@@ -8166,7 +8312,7 @@ class BrowserPermission {
|
|
|
8166
8312
|
return this.state;
|
|
8167
8313
|
}
|
|
8168
8314
|
async prompt({ forcePrompt = false, throwOnNotAllowed = false, } = {}) {
|
|
8169
|
-
await withoutConcurrency(`permission-prompt-${this.permission.queryName}`, async () => {
|
|
8315
|
+
return await withoutConcurrency(`permission-prompt-${this.permission.queryName}`, async () => {
|
|
8170
8316
|
if ((await this.getState()) !== 'prompt' ||
|
|
8171
8317
|
(this.wasPrompted && !forcePrompt)) {
|
|
8172
8318
|
const isGranted = this.state === 'granted';
|
|
@@ -8228,20 +8374,6 @@ function canQueryPermissions() {
|
|
|
8228
8374
|
!!navigator.permissions?.query);
|
|
8229
8375
|
}
|
|
8230
8376
|
|
|
8231
|
-
const uninitialized = Symbol('uninitialized');
|
|
8232
|
-
/**
|
|
8233
|
-
* Lazily creates a value using a provided factory
|
|
8234
|
-
*/
|
|
8235
|
-
function lazy(factory) {
|
|
8236
|
-
let value = uninitialized;
|
|
8237
|
-
return () => {
|
|
8238
|
-
if (value === uninitialized) {
|
|
8239
|
-
value = factory();
|
|
8240
|
-
}
|
|
8241
|
-
return value;
|
|
8242
|
-
};
|
|
8243
|
-
}
|
|
8244
|
-
|
|
8245
8377
|
/**
|
|
8246
8378
|
* Returns an Observable that emits the list of available devices
|
|
8247
8379
|
* that meet the given constraints.
|
|
@@ -8255,8 +8387,7 @@ const getDevices = (permission, kind) => {
|
|
|
8255
8387
|
// for privacy reasons, most browsers don't give you device labels
|
|
8256
8388
|
// unless you have a corresponding camera or microphone permission
|
|
8257
8389
|
const shouldPromptForBrowserPermission = devices.some((device) => device.kind === kind && device.label === '');
|
|
8258
|
-
if (shouldPromptForBrowserPermission) {
|
|
8259
|
-
await permission.prompt({ throwOnNotAllowed: true });
|
|
8390
|
+
if (shouldPromptForBrowserPermission && (await permission.prompt())) {
|
|
8260
8391
|
devices = await navigator.mediaDevices.enumerateDevices();
|
|
8261
8392
|
}
|
|
8262
8393
|
return devices.filter((device) => device.kind === kind &&
|
|
@@ -11790,9 +11921,12 @@ class StableWSConnection {
|
|
|
11790
11921
|
* Schedules a next health check ping for websocket.
|
|
11791
11922
|
*/
|
|
11792
11923
|
this.scheduleNextPing = () => {
|
|
11924
|
+
const timers = getTimers();
|
|
11925
|
+
if (this.healthCheckTimeoutRef) {
|
|
11926
|
+
timers.clearTimeout(this.healthCheckTimeoutRef);
|
|
11927
|
+
}
|
|
11793
11928
|
// 30 seconds is the recommended interval (messenger uses this)
|
|
11794
|
-
|
|
11795
|
-
this.healthCheckTimeoutRef = setTimeout(() => {
|
|
11929
|
+
this.healthCheckTimeoutRef = timers.setTimeout(() => {
|
|
11796
11930
|
// send the healthcheck..., server replies with a health check event
|
|
11797
11931
|
const data = [{ type: 'health.check', client_id: this.client.clientID }];
|
|
11798
11932
|
// try to send on the connection
|
|
@@ -11935,8 +12069,12 @@ class StableWSConnection {
|
|
|
11935
12069
|
this.isConnecting = false;
|
|
11936
12070
|
this.isDisconnected = true;
|
|
11937
12071
|
// start by removing all the listeners
|
|
11938
|
-
|
|
11939
|
-
|
|
12072
|
+
if (this.healthCheckTimeoutRef) {
|
|
12073
|
+
getTimers().clearInterval(this.healthCheckTimeoutRef);
|
|
12074
|
+
}
|
|
12075
|
+
if (this.connectionCheckTimeoutRef) {
|
|
12076
|
+
clearInterval(this.connectionCheckTimeoutRef);
|
|
12077
|
+
}
|
|
11940
12078
|
removeConnectionEventListeners(this.onlineStatusChanged);
|
|
11941
12079
|
this.isHealthy = false;
|
|
11942
12080
|
let isClosedPromise;
|
|
@@ -12636,7 +12774,7 @@ class StreamClient {
|
|
|
12636
12774
|
return await this.wsConnection.connect(this.defaultWSTimeout);
|
|
12637
12775
|
};
|
|
12638
12776
|
this.getUserAgent = () => {
|
|
12639
|
-
const version = "1.11.
|
|
12777
|
+
const version = "1.11.14";
|
|
12640
12778
|
return (this.userAgent ||
|
|
12641
12779
|
`stream-video-javascript-client-${this.node ? 'node' : 'browser'}-${version}`);
|
|
12642
12780
|
};
|
|
@@ -13047,10 +13185,14 @@ class StreamVideoClient {
|
|
|
13047
13185
|
if (typeof apiKeyOrArgs === 'string') {
|
|
13048
13186
|
logLevel = opts?.logLevel || logLevel;
|
|
13049
13187
|
logger = opts?.logger || logger;
|
|
13188
|
+
if (opts?.expertimental_enableTimerWorker)
|
|
13189
|
+
enableTimerWorker();
|
|
13050
13190
|
}
|
|
13051
13191
|
else {
|
|
13052
13192
|
logLevel = apiKeyOrArgs.options?.logLevel || logLevel;
|
|
13053
13193
|
logger = apiKeyOrArgs.options?.logger || logger;
|
|
13194
|
+
if (apiKeyOrArgs.options?.expertimental_enableTimerWorker)
|
|
13195
|
+
enableTimerWorker();
|
|
13054
13196
|
}
|
|
13055
13197
|
setLogger(logger, logLevel);
|
|
13056
13198
|
this.logger = getLogger(['client']);
|