@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/CHANGELOG.md +7 -0
- package/dist/index.browser.es.js +79 -47
- package/dist/index.browser.es.js.map +1 -1
- package/dist/index.cjs.js +79 -47
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.es.js +79 -47
- package/dist/index.es.js.map +1 -1
- package/dist/src/devices/InputMediaDeviceManager.d.ts +4 -5
- package/dist/src/devices/InputMediaDeviceManagerState.d.ts +14 -0
- package/package.json +1 -1
- package/src/Call.ts +2 -12
- package/src/devices/CameraManager.ts +2 -2
- package/src/devices/InputMediaDeviceManager.ts +58 -36
- package/src/devices/InputMediaDeviceManagerState.ts +25 -0
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.
|
|
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.
|
|
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.
|
|
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.
|
|
11128
|
-
await this.
|
|
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.
|
|
11162
|
-
await this.
|
|
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.
|
|
11478
|
+
if (this.statusChangePromise && this.state.optimisticStatus === 'enabled') {
|
|
11437
11479
|
try {
|
|
11438
|
-
await this.
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
15199
|
+
const version = "1.0.2" ;
|
|
15168
15200
|
return (this.userAgent ||
|
|
15169
15201
|
`stream-video-javascript-client-${this.node ? 'node' : 'browser'}-${version}`);
|
|
15170
15202
|
};
|