@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/dist/index.cjs.js CHANGED
@@ -3318,7 +3318,7 @@ const retryable = async (rpc, signal) => {
3318
3318
  return result;
3319
3319
  };
3320
3320
 
3321
- const version = "1.11.12";
3321
+ const version = "1.11.14";
3322
3322
  const [major, minor, patch] = version.split('.');
3323
3323
  let sdkInfo = {
3324
3324
  type: SdkType.PLAIN_JAVASCRIPT,
@@ -6453,6 +6453,151 @@ const promiseWithResolvers = () => {
6453
6453
  };
6454
6454
  };
6455
6455
 
6456
+ const uninitialized = Symbol('uninitialized');
6457
+ /**
6458
+ * Lazily creates a value using a provided factory
6459
+ */
6460
+ function lazy(factory) {
6461
+ let value = uninitialized;
6462
+ return () => {
6463
+ if (value === uninitialized) {
6464
+ value = factory();
6465
+ }
6466
+ return value;
6467
+ };
6468
+ }
6469
+
6470
+ const timerWorker = {
6471
+ src: `var timerIdMapping = new Map();
6472
+ self.addEventListener('message', function (event) {
6473
+ var request = event.data;
6474
+ switch (request.type) {
6475
+ case 'setTimeout':
6476
+ case 'setInterval':
6477
+ timerIdMapping.set(request.id, (request.type === 'setTimeout' ? setTimeout : setInterval)(function () {
6478
+ tick(request.id);
6479
+ if (request.type === 'setTimeout') {
6480
+ timerIdMapping.delete(request.id);
6481
+ }
6482
+ }, request.timeout));
6483
+ break;
6484
+ case 'clearTimeout':
6485
+ case 'clearInterval':
6486
+ (request.type === 'clearTimeout' ? clearTimeout : clearInterval)(timerIdMapping.get(request.id));
6487
+ timerIdMapping.delete(request.id);
6488
+ break;
6489
+ }
6490
+ });
6491
+ function tick(id) {
6492
+ var message = { type: 'tick', id: id };
6493
+ self.postMessage(message);
6494
+ }`,
6495
+ };
6496
+
6497
+ class TimerWorker {
6498
+ constructor() {
6499
+ this.currentTimerId = 1;
6500
+ this.callbacks = new Map();
6501
+ this.fallback = false;
6502
+ }
6503
+ setup({ useTimerWorker = true } = {}) {
6504
+ if (!useTimerWorker) {
6505
+ this.fallback = true;
6506
+ return;
6507
+ }
6508
+ try {
6509
+ const source = timerWorker.src;
6510
+ const blob = new Blob([source], {
6511
+ type: 'application/javascript; charset=utf-8',
6512
+ });
6513
+ const script = URL.createObjectURL(blob);
6514
+ this.worker = new Worker(script, { name: 'str-timer-worker' });
6515
+ this.worker.addEventListener('message', (event) => {
6516
+ const { type, id } = event.data;
6517
+ if (type === 'tick') {
6518
+ this.callbacks.get(id)?.();
6519
+ }
6520
+ });
6521
+ }
6522
+ catch (err) {
6523
+ getLogger(['timer-worker'])('error', err);
6524
+ this.fallback = true;
6525
+ }
6526
+ }
6527
+ destroy() {
6528
+ this.callbacks.clear();
6529
+ this.worker?.terminate();
6530
+ this.worker = undefined;
6531
+ this.fallback = false;
6532
+ }
6533
+ get ready() {
6534
+ return this.fallback || Boolean(this.worker);
6535
+ }
6536
+ setInterval(callback, timeout) {
6537
+ return this.setTimer('setInterval', callback, timeout);
6538
+ }
6539
+ clearInterval(id) {
6540
+ this.clearTimer('clearInterval', id);
6541
+ }
6542
+ setTimeout(callback, timeout) {
6543
+ return this.setTimer('setTimeout', callback, timeout);
6544
+ }
6545
+ clearTimeout(id) {
6546
+ this.clearTimer('clearTimeout', id);
6547
+ }
6548
+ setTimer(type, callback, timeout) {
6549
+ if (!this.ready) {
6550
+ this.setup();
6551
+ }
6552
+ if (this.fallback) {
6553
+ return (type === 'setTimeout' ? setTimeout : setInterval)(callback, timeout);
6554
+ }
6555
+ const id = this.getTimerId();
6556
+ this.callbacks.set(id, () => {
6557
+ callback();
6558
+ // Timeouts are one-off operations, so no need to keep callback reference
6559
+ // after timer has fired
6560
+ if (type === 'setTimeout') {
6561
+ this.callbacks.delete(id);
6562
+ }
6563
+ });
6564
+ this.sendMessage({ type, id, timeout });
6565
+ return id;
6566
+ }
6567
+ clearTimer(type, id) {
6568
+ if (!id) {
6569
+ return;
6570
+ }
6571
+ if (!this.ready) {
6572
+ this.setup();
6573
+ }
6574
+ if (this.fallback) {
6575
+ (type === 'clearTimeout' ? clearTimeout : clearInterval)(id);
6576
+ return;
6577
+ }
6578
+ this.callbacks.delete(id);
6579
+ this.sendMessage({ type, id });
6580
+ }
6581
+ getTimerId() {
6582
+ return this.currentTimerId++;
6583
+ }
6584
+ sendMessage(message) {
6585
+ if (!this.worker) {
6586
+ throw new Error("Cannot use timer worker before it's set up");
6587
+ }
6588
+ this.worker.postMessage(message);
6589
+ }
6590
+ }
6591
+ let timerWorkerEnabled = false;
6592
+ const enableTimerWorker = () => {
6593
+ timerWorkerEnabled = true;
6594
+ };
6595
+ const getTimers = lazy(() => {
6596
+ const instance = new TimerWorker();
6597
+ instance.setup({ useTimerWorker: timerWorkerEnabled });
6598
+ return instance;
6599
+ });
6600
+
6456
6601
  /**
6457
6602
  * The client used for exchanging information with the SFU.
6458
6603
  */
@@ -6511,7 +6656,7 @@ class StreamSfuClient {
6511
6656
  };
6512
6657
  this.handleWebSocketClose = () => {
6513
6658
  this.signalWs.removeEventListener('close', this.handleWebSocketClose);
6514
- clearInterval(this.keepAliveInterval);
6659
+ getTimers().clearInterval(this.keepAliveInterval);
6515
6660
  clearTimeout(this.connectionCheckTimeout);
6516
6661
  this.onSignalClose?.();
6517
6662
  };
@@ -6667,8 +6812,9 @@ class StreamSfuClient {
6667
6812
  this.signalWs.send(SfuRequest.toBinary(message));
6668
6813
  };
6669
6814
  this.keepAlive = () => {
6670
- clearInterval(this.keepAliveInterval);
6671
- this.keepAliveInterval = setInterval(() => {
6815
+ const timers = getTimers();
6816
+ timers.clearInterval(this.keepAliveInterval);
6817
+ this.keepAliveInterval = timers.setInterval(() => {
6672
6818
  this.ping().catch((e) => {
6673
6819
  this.logger('error', 'Error sending healthCheckRequest to SFU', e);
6674
6820
  });
@@ -8187,7 +8333,7 @@ class BrowserPermission {
8187
8333
  return this.state;
8188
8334
  }
8189
8335
  async prompt({ forcePrompt = false, throwOnNotAllowed = false, } = {}) {
8190
- await withoutConcurrency(`permission-prompt-${this.permission.queryName}`, async () => {
8336
+ return await withoutConcurrency(`permission-prompt-${this.permission.queryName}`, async () => {
8191
8337
  if ((await this.getState()) !== 'prompt' ||
8192
8338
  (this.wasPrompted && !forcePrompt)) {
8193
8339
  const isGranted = this.state === 'granted';
@@ -8249,20 +8395,6 @@ function canQueryPermissions() {
8249
8395
  !!navigator.permissions?.query);
8250
8396
  }
8251
8397
 
8252
- const uninitialized = Symbol('uninitialized');
8253
- /**
8254
- * Lazily creates a value using a provided factory
8255
- */
8256
- function lazy(factory) {
8257
- let value = uninitialized;
8258
- return () => {
8259
- if (value === uninitialized) {
8260
- value = factory();
8261
- }
8262
- return value;
8263
- };
8264
- }
8265
-
8266
8398
  /**
8267
8399
  * Returns an Observable that emits the list of available devices
8268
8400
  * that meet the given constraints.
@@ -8276,8 +8408,7 @@ const getDevices = (permission, kind) => {
8276
8408
  // for privacy reasons, most browsers don't give you device labels
8277
8409
  // unless you have a corresponding camera or microphone permission
8278
8410
  const shouldPromptForBrowserPermission = devices.some((device) => device.kind === kind && device.label === '');
8279
- if (shouldPromptForBrowserPermission) {
8280
- await permission.prompt({ throwOnNotAllowed: true });
8411
+ if (shouldPromptForBrowserPermission && (await permission.prompt())) {
8281
8412
  devices = await navigator.mediaDevices.enumerateDevices();
8282
8413
  }
8283
8414
  return devices.filter((device) => device.kind === kind &&
@@ -11809,9 +11940,12 @@ class StableWSConnection {
11809
11940
  * Schedules a next health check ping for websocket.
11810
11941
  */
11811
11942
  this.scheduleNextPing = () => {
11943
+ const timers = getTimers();
11944
+ if (this.healthCheckTimeoutRef) {
11945
+ timers.clearTimeout(this.healthCheckTimeoutRef);
11946
+ }
11812
11947
  // 30 seconds is the recommended interval (messenger uses this)
11813
- clearTimeout(this.healthCheckTimeoutRef);
11814
- this.healthCheckTimeoutRef = setTimeout(() => {
11948
+ this.healthCheckTimeoutRef = timers.setTimeout(() => {
11815
11949
  // send the healthcheck..., server replies with a health check event
11816
11950
  const data = [{ type: 'health.check', client_id: this.client.clientID }];
11817
11951
  // try to send on the connection
@@ -11954,8 +12088,12 @@ class StableWSConnection {
11954
12088
  this.isConnecting = false;
11955
12089
  this.isDisconnected = true;
11956
12090
  // start by removing all the listeners
11957
- clearInterval(this.healthCheckTimeoutRef);
11958
- clearInterval(this.connectionCheckTimeoutRef);
12091
+ if (this.healthCheckTimeoutRef) {
12092
+ getTimers().clearInterval(this.healthCheckTimeoutRef);
12093
+ }
12094
+ if (this.connectionCheckTimeoutRef) {
12095
+ clearInterval(this.connectionCheckTimeoutRef);
12096
+ }
11959
12097
  removeConnectionEventListeners(this.onlineStatusChanged);
11960
12098
  this.isHealthy = false;
11961
12099
  let isClosedPromise;
@@ -12655,7 +12793,7 @@ class StreamClient {
12655
12793
  return await this.wsConnection.connect(this.defaultWSTimeout);
12656
12794
  };
12657
12795
  this.getUserAgent = () => {
12658
- const version = "1.11.12";
12796
+ const version = "1.11.14";
12659
12797
  return (this.userAgent ||
12660
12798
  `stream-video-javascript-client-${this.node ? 'node' : 'browser'}-${version}`);
12661
12799
  };
@@ -13066,10 +13204,14 @@ class StreamVideoClient {
13066
13204
  if (typeof apiKeyOrArgs === 'string') {
13067
13205
  logLevel = opts?.logLevel || logLevel;
13068
13206
  logger = opts?.logger || logger;
13207
+ if (opts?.expertimental_enableTimerWorker)
13208
+ enableTimerWorker();
13069
13209
  }
13070
13210
  else {
13071
13211
  logLevel = apiKeyOrArgs.options?.logLevel || logLevel;
13072
13212
  logger = apiKeyOrArgs.options?.logger || logger;
13213
+ if (apiKeyOrArgs.options?.expertimental_enableTimerWorker)
13214
+ enableTimerWorker();
13073
13215
  }
13074
13216
  setLogger(logger, logLevel);
13075
13217
  this.logger = getLogger(['client']);