@stream-io/video-client 1.0.1 → 1.0.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/dist/index.cjs.js CHANGED
@@ -10890,18 +10890,27 @@ class InputMediaDeviceManager {
10890
10890
  * Starts stream.
10891
10891
  */
10892
10892
  async enable() {
10893
- if (this.state.status === 'enabled')
10893
+ if (this.state.optimisticStatus === 'enabled') {
10894
+ await this.statusChangePromise;
10894
10895
  return;
10895
- this.enablePromise = this.unmuteStream();
10896
- try {
10897
- await this.enablePromise;
10898
- this.state.setStatus('enabled');
10899
- this.enablePromise = undefined;
10900
- }
10901
- catch (error) {
10902
- this.enablePromise = undefined;
10903
- throw error;
10904
10896
  }
10897
+ const signal = this.nextAbortableStatusChangeRequest('enabled');
10898
+ const doEnable = async () => {
10899
+ if (signal.aborted)
10900
+ return;
10901
+ try {
10902
+ await this.unmuteStream();
10903
+ this.state.setStatus('enabled');
10904
+ }
10905
+ finally {
10906
+ if (!signal.aborted)
10907
+ this.resetStatusChangeRequest();
10908
+ }
10909
+ };
10910
+ this.statusChangePromise = this.statusChangePromise
10911
+ ? this.statusChangePromise.then(doEnable)
10912
+ : doEnable();
10913
+ await this.statusChangePromise;
10905
10914
  }
10906
10915
  /**
10907
10916
  * Stops or pauses the stream based on state.disableMode
@@ -10909,19 +10918,28 @@ class InputMediaDeviceManager {
10909
10918
  */
10910
10919
  async disable(forceStop = false) {
10911
10920
  this.state.prevStatus = this.state.status;
10912
- if (!forceStop && this.state.status === 'disabled')
10921
+ if (!forceStop && this.state.optimisticStatus === 'disabled') {
10922
+ await this.statusChangePromise;
10913
10923
  return;
10914
- const stopTracks = forceStop || this.state.disableMode === 'stop-tracks';
10915
- this.disablePromise = this.muteStream(stopTracks);
10916
- try {
10917
- await this.disablePromise;
10918
- this.state.setStatus('disabled');
10919
- this.disablePromise = undefined;
10920
- }
10921
- catch (error) {
10922
- this.disablePromise = undefined;
10923
- throw error;
10924
10924
  }
10925
+ const stopTracks = forceStop || this.state.disableMode === 'stop-tracks';
10926
+ const signal = this.nextAbortableStatusChangeRequest('disabled');
10927
+ const doDisable = async () => {
10928
+ if (signal.aborted)
10929
+ return;
10930
+ try {
10931
+ await this.muteStream(stopTracks);
10932
+ this.state.setStatus('disabled');
10933
+ }
10934
+ finally {
10935
+ if (!signal.aborted)
10936
+ this.resetStatusChangeRequest();
10937
+ }
10938
+ };
10939
+ this.statusChangePromise = this.statusChangePromise
10940
+ ? this.statusChangePromise.then(doDisable)
10941
+ : doDisable();
10942
+ await this.statusChangePromise;
10925
10943
  }
10926
10944
  /**
10927
10945
  * If status was previously enabled, it will re-enable the device.
@@ -10937,7 +10955,7 @@ class InputMediaDeviceManager {
10937
10955
  * else it will disable it.
10938
10956
  */
10939
10957
  async toggle() {
10940
- if (this.state.status === 'enabled') {
10958
+ if (this.state.optimisticStatus === 'enabled') {
10941
10959
  return this.disable();
10942
10960
  }
10943
10961
  else {
@@ -11124,11 +11142,8 @@ class InputMediaDeviceManager {
11124
11142
  this.state.setMediaStream(stream, await rootStream);
11125
11143
  this.getTracks().forEach((track) => {
11126
11144
  track.addEventListener('ended', async () => {
11127
- if (this.enablePromise) {
11128
- await this.enablePromise;
11129
- }
11130
- if (this.disablePromise) {
11131
- await this.disablePromise;
11145
+ if (this.statusChangePromise) {
11146
+ await this.statusChangePromise;
11132
11147
  }
11133
11148
  if (this.state.status === 'enabled') {
11134
11149
  this.isTrackStoppedDueToTrackEnd = true;
@@ -11158,11 +11173,8 @@ class InputMediaDeviceManager {
11158
11173
  if (!deviceId) {
11159
11174
  return;
11160
11175
  }
11161
- if (this.enablePromise) {
11162
- await this.enablePromise;
11163
- }
11164
- if (this.disablePromise) {
11165
- await this.disablePromise;
11176
+ if (this.statusChangePromise) {
11177
+ await this.statusChangePromise;
11166
11178
  }
11167
11179
  let isDeviceDisconnected = false;
11168
11180
  let isDeviceReplaced = false;
@@ -11196,6 +11208,16 @@ class InputMediaDeviceManager {
11196
11208
  findDeviceInList(devices, deviceId) {
11197
11209
  return devices.find((d) => d.deviceId === deviceId && d.kind === this.mediaDeviceKind);
11198
11210
  }
11211
+ nextAbortableStatusChangeRequest(status) {
11212
+ this.statusChangeAbortController?.abort();
11213
+ this.statusChangeAbortController = new AbortController();
11214
+ this.state.setPendingStatus(status);
11215
+ return this.statusChangeAbortController.signal;
11216
+ }
11217
+ resetStatusChangeRequest() {
11218
+ this.statusChangePromise = undefined;
11219
+ this.statusChangeAbortController = undefined;
11220
+ }
11199
11221
  }
11200
11222
 
11201
11223
  class InputMediaDeviceManagerState {
@@ -11210,6 +11232,7 @@ class InputMediaDeviceManagerState {
11210
11232
  this.disableMode = disableMode;
11211
11233
  this.permissionName = permissionName;
11212
11234
  this.statusSubject = new rxjs.BehaviorSubject(undefined);
11235
+ this.optimisticStatusSubject = new rxjs.BehaviorSubject(undefined);
11213
11236
  this.mediaStreamSubject = new rxjs.BehaviorSubject(undefined);
11214
11237
  this.selectedDeviceSubject = new rxjs.BehaviorSubject(undefined);
11215
11238
  this.defaultConstraintsSubject = new rxjs.BehaviorSubject(undefined);
@@ -11228,6 +11251,12 @@ class InputMediaDeviceManagerState {
11228
11251
  * An Observable that emits the device status
11229
11252
  */
11230
11253
  this.status$ = this.statusSubject.asObservable().pipe(rxjs.distinctUntilChanged());
11254
+ /**
11255
+ * An Observable the reflects the requested device status. Useful for optimistic UIs
11256
+ */
11257
+ this.optimisticStatus$ = this.optimisticStatusSubject
11258
+ .asObservable()
11259
+ .pipe(rxjs.distinctUntilChanged());
11231
11260
  /**
11232
11261
  * The default constraints for the device.
11233
11262
  */
@@ -11295,6 +11324,12 @@ class InputMediaDeviceManagerState {
11295
11324
  get status() {
11296
11325
  return this.getCurrentValue(this.status$);
11297
11326
  }
11327
+ /**
11328
+ * The requested device status. Useful for optimistic UIs
11329
+ */
11330
+ get optimisticStatus() {
11331
+ return this.getCurrentValue(this.optimisticStatus$);
11332
+ }
11298
11333
  /**
11299
11334
  * The currently selected device
11300
11335
  */
@@ -11314,6 +11349,13 @@ class InputMediaDeviceManagerState {
11314
11349
  setStatus(status) {
11315
11350
  this.setCurrentValue(this.statusSubject, status);
11316
11351
  }
11352
+ /**
11353
+ * @internal
11354
+ * @param pendingStatus
11355
+ */
11356
+ setPendingStatus(pendingStatus) {
11357
+ this.setCurrentValue(this.optimisticStatusSubject, pendingStatus);
11358
+ }
11317
11359
  /**
11318
11360
  * Updates the `mediaStream` state variable.
11319
11361
  *
@@ -11433,9 +11475,9 @@ class CameraManager extends InputMediaDeviceManager {
11433
11475
  async selectTargetResolution(resolution) {
11434
11476
  this.targetResolution.height = resolution.height;
11435
11477
  this.targetResolution.width = resolution.width;
11436
- if (this.enablePromise) {
11478
+ if (this.statusChangePromise && this.state.optimisticStatus === 'enabled') {
11437
11479
  try {
11438
- await this.enablePromise;
11480
+ await this.statusChangePromise;
11439
11481
  }
11440
11482
  catch (error) {
11441
11483
  // couldn't enable device, target resolution will be applied the next time user attempts to start the device
@@ -13576,12 +13618,7 @@ class Call {
13576
13618
  }
13577
13619
  async initCamera(options) {
13578
13620
  // Wait for any in progress camera operation
13579
- if (this.camera.enablePromise) {
13580
- await this.camera.enablePromise;
13581
- }
13582
- if (this.camera.disablePromise) {
13583
- await this.camera.disablePromise;
13584
- }
13621
+ await this.camera.statusChangePromise;
13585
13622
  if (this.state.localParticipant?.videoStream ||
13586
13623
  !this.permissionsContext.hasPermission('send-video')) {
13587
13624
  return;
@@ -13618,12 +13655,7 @@ class Call {
13618
13655
  }
13619
13656
  async initMic(options) {
13620
13657
  // Wait for any in progress mic operation
13621
- if (this.microphone.enablePromise) {
13622
- await this.microphone.enablePromise;
13623
- }
13624
- if (this.microphone.disablePromise) {
13625
- await this.microphone.disablePromise;
13626
- }
13658
+ await this.microphone.statusChangePromise;
13627
13659
  if (this.state.localParticipant?.audioStream ||
13628
13660
  !this.permissionsContext.hasPermission('send-audio')) {
13629
13661
  return;
@@ -15164,7 +15196,7 @@ class StreamClient {
15164
15196
  });
15165
15197
  };
15166
15198
  this.getUserAgent = () => {
15167
- const version = "1.0.1" ;
15199
+ const version = "1.0.2" ;
15168
15200
  return (this.userAgent ||
15169
15201
  `stream-video-javascript-client-${this.node ? 'node' : 'browser'}-${version}`);
15170
15202
  };