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