@stream-io/video-client 0.0.1-alpha.83 → 0.0.1-alpha.85
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.browser.es.js +200 -147
- package/dist/index.browser.es.js.map +1 -1
- package/dist/index.cjs.js +200 -147
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.es.js +200 -147
- package/dist/index.es.js.map +1 -1
- package/dist/src/StreamSfuClient.d.ts +14 -6
- package/dist/src/rpc/createClient.d.ts +1 -1
- package/dist/src/rtc/Call.d.ts +7 -0
- package/package.json +7 -9
- package/src/StreamSfuClient.ts +100 -23
- package/src/rpc/createClient.ts +2 -1
- package/src/rtc/Call.ts +42 -13
package/dist/index.browser.es.js
CHANGED
|
@@ -2,7 +2,6 @@ import 'webrtc-adapter';
|
|
|
2
2
|
import { MessageType, isJsonObject, typeofJsonValue, reflectionMergePartial, UnknownFieldHandler, WireType, MESSAGE_TYPE, PbLong } from '@protobuf-ts/runtime';
|
|
3
3
|
import { TwirpFetchTransport } from '@protobuf-ts/twirp-transport';
|
|
4
4
|
import { ServiceType, stackIntercept } from '@protobuf-ts/runtime-rpc';
|
|
5
|
-
import { v4 } from 'uuid';
|
|
6
5
|
import { ReplaySubject, BehaviorSubject, Subject, takeWhile, debounceTime, startWith, pairwise, Observable, concatMap, from, shareReplay, merge, map as map$2, combineLatest, filter, firstValueFrom } from 'rxjs';
|
|
7
6
|
import { take, combineLatestWith, map as map$1, distinctUntilChanged } from 'rxjs/operators';
|
|
8
7
|
import axios, { AxiosHeaders } from 'axios';
|
|
@@ -3798,6 +3797,7 @@ class SignalServerClient {
|
|
|
3798
3797
|
const defaultOptions = {
|
|
3799
3798
|
baseUrl: '',
|
|
3800
3799
|
sendJson: true,
|
|
3800
|
+
timeout: 5 * 1000,
|
|
3801
3801
|
jsonOptions: {
|
|
3802
3802
|
ignoreUnknownFields: true,
|
|
3803
3803
|
},
|
|
@@ -3866,6 +3866,129 @@ class IceTrickleBuffer {
|
|
|
3866
3866
|
}
|
|
3867
3867
|
}
|
|
3868
3868
|
|
|
3869
|
+
const sleep = (m) => new Promise((r) => setTimeout(r, m));
|
|
3870
|
+
function isFunction(value) {
|
|
3871
|
+
return (value &&
|
|
3872
|
+
(Object.prototype.toString.call(value) === '[object Function]' ||
|
|
3873
|
+
'function' === typeof value ||
|
|
3874
|
+
value instanceof Function));
|
|
3875
|
+
}
|
|
3876
|
+
// todo: rename so that it does not contain word "chat"
|
|
3877
|
+
const chatCodes = {
|
|
3878
|
+
TOKEN_EXPIRED: 40,
|
|
3879
|
+
WS_CLOSED_SUCCESS: 1000,
|
|
3880
|
+
};
|
|
3881
|
+
/**
|
|
3882
|
+
* retryInterval - A retry interval which increases acc to number of failures
|
|
3883
|
+
*
|
|
3884
|
+
* @return {number} Duration to wait in milliseconds
|
|
3885
|
+
*/
|
|
3886
|
+
function retryInterval(numberOfFailures) {
|
|
3887
|
+
// try to reconnect in 0.25-5 seconds (random to spread out the load from failures)
|
|
3888
|
+
const max = Math.min(500 + numberOfFailures * 2000, 5000);
|
|
3889
|
+
const min = Math.min(Math.max(250, (numberOfFailures - 1) * 2000), 5000);
|
|
3890
|
+
return Math.floor(Math.random() * (max - min) + min);
|
|
3891
|
+
}
|
|
3892
|
+
function randomId() {
|
|
3893
|
+
return generateUUIDv4();
|
|
3894
|
+
}
|
|
3895
|
+
function hex(bytes) {
|
|
3896
|
+
let s = '';
|
|
3897
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
3898
|
+
s += bytes[i].toString(16).padStart(2, '0');
|
|
3899
|
+
}
|
|
3900
|
+
return s;
|
|
3901
|
+
}
|
|
3902
|
+
// https://tools.ietf.org/html/rfc4122
|
|
3903
|
+
function generateUUIDv4() {
|
|
3904
|
+
const bytes = getRandomBytes(16);
|
|
3905
|
+
bytes[6] = (bytes[6] & 0x0f) | 0x40; // version
|
|
3906
|
+
bytes[8] = (bytes[8] & 0xbf) | 0x80; // variant
|
|
3907
|
+
return (hex(bytes.subarray(0, 4)) +
|
|
3908
|
+
'-' +
|
|
3909
|
+
hex(bytes.subarray(4, 6)) +
|
|
3910
|
+
'-' +
|
|
3911
|
+
hex(bytes.subarray(6, 8)) +
|
|
3912
|
+
'-' +
|
|
3913
|
+
hex(bytes.subarray(8, 10)) +
|
|
3914
|
+
'-' +
|
|
3915
|
+
hex(bytes.subarray(10, 16)));
|
|
3916
|
+
}
|
|
3917
|
+
function getRandomValuesWithMathRandom(bytes) {
|
|
3918
|
+
const max = Math.pow(2, (8 * bytes.byteLength) / bytes.length);
|
|
3919
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
3920
|
+
bytes[i] = Math.random() * max;
|
|
3921
|
+
}
|
|
3922
|
+
}
|
|
3923
|
+
const getRandomValues = (() => {
|
|
3924
|
+
if (typeof crypto !== 'undefined' &&
|
|
3925
|
+
typeof (crypto === null || crypto === void 0 ? void 0 : crypto.getRandomValues) !== 'undefined') {
|
|
3926
|
+
return crypto.getRandomValues.bind(crypto);
|
|
3927
|
+
}
|
|
3928
|
+
else if (typeof msCrypto !== 'undefined') {
|
|
3929
|
+
return msCrypto.getRandomValues.bind(msCrypto);
|
|
3930
|
+
}
|
|
3931
|
+
else {
|
|
3932
|
+
return getRandomValuesWithMathRandom;
|
|
3933
|
+
}
|
|
3934
|
+
})();
|
|
3935
|
+
function getRandomBytes(length) {
|
|
3936
|
+
const bytes = new Uint8Array(length);
|
|
3937
|
+
getRandomValues(bytes);
|
|
3938
|
+
return bytes;
|
|
3939
|
+
}
|
|
3940
|
+
function convertErrorToJson(err) {
|
|
3941
|
+
const jsonObj = {};
|
|
3942
|
+
if (!err)
|
|
3943
|
+
return jsonObj;
|
|
3944
|
+
try {
|
|
3945
|
+
Object.getOwnPropertyNames(err).forEach((key) => {
|
|
3946
|
+
jsonObj[key] = Object.getOwnPropertyDescriptor(err, key);
|
|
3947
|
+
});
|
|
3948
|
+
}
|
|
3949
|
+
catch (_) {
|
|
3950
|
+
return {
|
|
3951
|
+
error: 'failed to serialize the error',
|
|
3952
|
+
};
|
|
3953
|
+
}
|
|
3954
|
+
return jsonObj;
|
|
3955
|
+
}
|
|
3956
|
+
/**
|
|
3957
|
+
* isOnline safely return the navigator.online value for browser env
|
|
3958
|
+
* if navigator is not in global object, it always return true
|
|
3959
|
+
*/
|
|
3960
|
+
function isOnline() {
|
|
3961
|
+
const nav = typeof navigator !== 'undefined'
|
|
3962
|
+
? navigator
|
|
3963
|
+
: typeof window !== 'undefined' && window.navigator
|
|
3964
|
+
? window.navigator
|
|
3965
|
+
: undefined;
|
|
3966
|
+
if (!nav) {
|
|
3967
|
+
console.warn('isOnline failed to access window.navigator and assume browser is online');
|
|
3968
|
+
return true;
|
|
3969
|
+
}
|
|
3970
|
+
// RN navigator has undefined for onLine
|
|
3971
|
+
if (typeof nav.onLine !== 'boolean') {
|
|
3972
|
+
return true;
|
|
3973
|
+
}
|
|
3974
|
+
return nav.onLine;
|
|
3975
|
+
}
|
|
3976
|
+
/**
|
|
3977
|
+
* listenForConnectionChanges - Adds an event listener fired on browser going online or offline
|
|
3978
|
+
*/
|
|
3979
|
+
function addConnectionEventListeners(cb) {
|
|
3980
|
+
if (typeof window !== 'undefined' && window.addEventListener) {
|
|
3981
|
+
window.addEventListener('offline', cb);
|
|
3982
|
+
window.addEventListener('online', cb);
|
|
3983
|
+
}
|
|
3984
|
+
}
|
|
3985
|
+
function removeConnectionEventListeners(cb) {
|
|
3986
|
+
if (typeof window !== 'undefined' && window.removeEventListener) {
|
|
3987
|
+
window.removeEventListener('offline', cb);
|
|
3988
|
+
window.removeEventListener('online', cb);
|
|
3989
|
+
}
|
|
3990
|
+
}
|
|
3991
|
+
|
|
3869
3992
|
const hostnameFromUrl = (url) => {
|
|
3870
3993
|
try {
|
|
3871
3994
|
const u = new URL(url);
|
|
@@ -3894,6 +4017,13 @@ const toURL = (url) => {
|
|
|
3894
4017
|
* The client used for exchanging information with the SFU.
|
|
3895
4018
|
*/
|
|
3896
4019
|
class StreamSfuClient {
|
|
4020
|
+
/**
|
|
4021
|
+
* Constructs a new SFU client.
|
|
4022
|
+
*
|
|
4023
|
+
* @param dispatcher the event dispatcher to use.
|
|
4024
|
+
* @param url the URL of the SFU.
|
|
4025
|
+
* @param token the JWT token to use for authentication.
|
|
4026
|
+
*/
|
|
3897
4027
|
constructor(dispatcher, url, token) {
|
|
3898
4028
|
/**
|
|
3899
4029
|
* A buffer for ICE Candidates that are received before
|
|
@@ -3909,19 +4039,19 @@ class StreamSfuClient {
|
|
|
3909
4039
|
clearTimeout(this.connectionCheckTimeout);
|
|
3910
4040
|
};
|
|
3911
4041
|
this.updateSubscriptions = (subscriptions) => __awaiter(this, void 0, void 0, function* () {
|
|
3912
|
-
return this.rpc.updateSubscriptions({
|
|
4042
|
+
return retryable(() => this.rpc.updateSubscriptions({
|
|
3913
4043
|
sessionId: this.sessionId,
|
|
3914
4044
|
tracks: subscriptions,
|
|
3915
|
-
});
|
|
4045
|
+
}));
|
|
3916
4046
|
});
|
|
3917
4047
|
this.setPublisher = (data) => __awaiter(this, void 0, void 0, function* () {
|
|
3918
|
-
return this.rpc.setPublisher(Object.assign(Object.assign({}, data), { sessionId: this.sessionId }));
|
|
4048
|
+
return retryable(() => this.rpc.setPublisher(Object.assign(Object.assign({}, data), { sessionId: this.sessionId })));
|
|
3919
4049
|
});
|
|
3920
4050
|
this.sendAnswer = (data) => __awaiter(this, void 0, void 0, function* () {
|
|
3921
|
-
return this.rpc.sendAnswer(Object.assign(Object.assign({}, data), { sessionId: this.sessionId }));
|
|
4051
|
+
return retryable(() => this.rpc.sendAnswer(Object.assign(Object.assign({}, data), { sessionId: this.sessionId })));
|
|
3922
4052
|
});
|
|
3923
4053
|
this.iceTrickle = (data) => __awaiter(this, void 0, void 0, function* () {
|
|
3924
|
-
return this.rpc.iceTrickle(Object.assign(Object.assign({}, data), { sessionId: this.sessionId }));
|
|
4054
|
+
return retryable(() => this.rpc.iceTrickle(Object.assign(Object.assign({}, data), { sessionId: this.sessionId })));
|
|
3925
4055
|
});
|
|
3926
4056
|
this.updateMuteState = (trackType, muted) => __awaiter(this, void 0, void 0, function* () {
|
|
3927
4057
|
return this.updateMuteStates({
|
|
@@ -3934,7 +4064,7 @@ class StreamSfuClient {
|
|
|
3934
4064
|
});
|
|
3935
4065
|
});
|
|
3936
4066
|
this.updateMuteStates = (data) => __awaiter(this, void 0, void 0, function* () {
|
|
3937
|
-
return this.rpc.updateMuteStates(Object.assign(Object.assign({}, data), { sessionId: this.sessionId }));
|
|
4067
|
+
return retryable(() => this.rpc.updateMuteStates(Object.assign(Object.assign({}, data), { sessionId: this.sessionId })));
|
|
3938
4068
|
});
|
|
3939
4069
|
this.join = (data) => __awaiter(this, void 0, void 0, function* () {
|
|
3940
4070
|
const joinRequest = JoinRequest.create(Object.assign(Object.assign({}, data), { sessionId: this.sessionId, token: this.token }));
|
|
@@ -3979,7 +4109,7 @@ class StreamSfuClient {
|
|
|
3979
4109
|
}
|
|
3980
4110
|
}, this.unhealthyTimeoutInMs);
|
|
3981
4111
|
};
|
|
3982
|
-
this.sessionId =
|
|
4112
|
+
this.sessionId = generateUUIDv4();
|
|
3983
4113
|
this.token = token;
|
|
3984
4114
|
this.rpc = createSignalClient({
|
|
3985
4115
|
baseUrl: url,
|
|
@@ -4027,6 +4157,37 @@ class StreamSfuClient {
|
|
|
4027
4157
|
});
|
|
4028
4158
|
}
|
|
4029
4159
|
}
|
|
4160
|
+
const MAX_RETRIES = 5;
|
|
4161
|
+
/**
|
|
4162
|
+
* Creates a closure which wraps the given RPC call and retries invoking
|
|
4163
|
+
* the RPC until it succeeds or the maximum number of retries is reached.
|
|
4164
|
+
*
|
|
4165
|
+
* Between each retry, there would be a random delay in order to avoid
|
|
4166
|
+
* request bursts towards the SFU.
|
|
4167
|
+
*
|
|
4168
|
+
* @param rpc the closure around the RPC call to execute.
|
|
4169
|
+
* @param <I> the type of the request object.
|
|
4170
|
+
* @param <O> the type of the response object.
|
|
4171
|
+
*/
|
|
4172
|
+
const retryable = (rpc) => __awaiter(void 0, void 0, void 0, function* () {
|
|
4173
|
+
var _a;
|
|
4174
|
+
let retryAttempt = 0;
|
|
4175
|
+
let rpcCallResult;
|
|
4176
|
+
do {
|
|
4177
|
+
// don't delay the first invocation
|
|
4178
|
+
if (retryAttempt > 0) {
|
|
4179
|
+
yield sleep(retryInterval(retryAttempt));
|
|
4180
|
+
}
|
|
4181
|
+
rpcCallResult = yield rpc();
|
|
4182
|
+
// if the RPC call failed, log the error and retry
|
|
4183
|
+
if (rpcCallResult.response.error) {
|
|
4184
|
+
console.error('SFU Error:', rpcCallResult.response.error);
|
|
4185
|
+
}
|
|
4186
|
+
retryAttempt++;
|
|
4187
|
+
} while (((_a = rpcCallResult.response.error) === null || _a === void 0 ? void 0 : _a.shouldRetry) &&
|
|
4188
|
+
retryAttempt < MAX_RETRIES);
|
|
4189
|
+
return rpcCallResult;
|
|
4190
|
+
});
|
|
4030
4191
|
|
|
4031
4192
|
function getIceCandidate(candidate) {
|
|
4032
4193
|
if (!candidate.usernameFragment) {
|
|
@@ -5727,129 +5888,6 @@ const CallTypes = new CallTypesRegistry([
|
|
|
5727
5888
|
}),
|
|
5728
5889
|
]);
|
|
5729
5890
|
|
|
5730
|
-
const sleep = (m) => new Promise((r) => setTimeout(r, m));
|
|
5731
|
-
function isFunction(value) {
|
|
5732
|
-
return (value &&
|
|
5733
|
-
(Object.prototype.toString.call(value) === '[object Function]' ||
|
|
5734
|
-
'function' === typeof value ||
|
|
5735
|
-
value instanceof Function));
|
|
5736
|
-
}
|
|
5737
|
-
// todo: rename so that it does not contain word "chat"
|
|
5738
|
-
const chatCodes = {
|
|
5739
|
-
TOKEN_EXPIRED: 40,
|
|
5740
|
-
WS_CLOSED_SUCCESS: 1000,
|
|
5741
|
-
};
|
|
5742
|
-
/**
|
|
5743
|
-
* retryInterval - A retry interval which increases acc to number of failures
|
|
5744
|
-
*
|
|
5745
|
-
* @return {number} Duration to wait in milliseconds
|
|
5746
|
-
*/
|
|
5747
|
-
function retryInterval(numberOfFailures) {
|
|
5748
|
-
// try to reconnect in 0.25-5 seconds (random to spread out the load from failures)
|
|
5749
|
-
const max = Math.min(500 + numberOfFailures * 2000, 5000);
|
|
5750
|
-
const min = Math.min(Math.max(250, (numberOfFailures - 1) * 2000), 5000);
|
|
5751
|
-
return Math.floor(Math.random() * (max - min) + min);
|
|
5752
|
-
}
|
|
5753
|
-
function randomId() {
|
|
5754
|
-
return generateUUIDv4();
|
|
5755
|
-
}
|
|
5756
|
-
function hex(bytes) {
|
|
5757
|
-
let s = '';
|
|
5758
|
-
for (let i = 0; i < bytes.length; i++) {
|
|
5759
|
-
s += bytes[i].toString(16).padStart(2, '0');
|
|
5760
|
-
}
|
|
5761
|
-
return s;
|
|
5762
|
-
}
|
|
5763
|
-
// https://tools.ietf.org/html/rfc4122
|
|
5764
|
-
function generateUUIDv4() {
|
|
5765
|
-
const bytes = getRandomBytes(16);
|
|
5766
|
-
bytes[6] = (bytes[6] & 0x0f) | 0x40; // version
|
|
5767
|
-
bytes[8] = (bytes[8] & 0xbf) | 0x80; // variant
|
|
5768
|
-
return (hex(bytes.subarray(0, 4)) +
|
|
5769
|
-
'-' +
|
|
5770
|
-
hex(bytes.subarray(4, 6)) +
|
|
5771
|
-
'-' +
|
|
5772
|
-
hex(bytes.subarray(6, 8)) +
|
|
5773
|
-
'-' +
|
|
5774
|
-
hex(bytes.subarray(8, 10)) +
|
|
5775
|
-
'-' +
|
|
5776
|
-
hex(bytes.subarray(10, 16)));
|
|
5777
|
-
}
|
|
5778
|
-
function getRandomValuesWithMathRandom(bytes) {
|
|
5779
|
-
const max = Math.pow(2, (8 * bytes.byteLength) / bytes.length);
|
|
5780
|
-
for (let i = 0; i < bytes.length; i++) {
|
|
5781
|
-
bytes[i] = Math.random() * max;
|
|
5782
|
-
}
|
|
5783
|
-
}
|
|
5784
|
-
const getRandomValues = (() => {
|
|
5785
|
-
if (typeof crypto !== 'undefined' &&
|
|
5786
|
-
typeof (crypto === null || crypto === void 0 ? void 0 : crypto.getRandomValues) !== 'undefined') {
|
|
5787
|
-
return crypto.getRandomValues.bind(crypto);
|
|
5788
|
-
}
|
|
5789
|
-
else if (typeof msCrypto !== 'undefined') {
|
|
5790
|
-
return msCrypto.getRandomValues.bind(msCrypto);
|
|
5791
|
-
}
|
|
5792
|
-
else {
|
|
5793
|
-
return getRandomValuesWithMathRandom;
|
|
5794
|
-
}
|
|
5795
|
-
})();
|
|
5796
|
-
function getRandomBytes(length) {
|
|
5797
|
-
const bytes = new Uint8Array(length);
|
|
5798
|
-
getRandomValues(bytes);
|
|
5799
|
-
return bytes;
|
|
5800
|
-
}
|
|
5801
|
-
function convertErrorToJson(err) {
|
|
5802
|
-
const jsonObj = {};
|
|
5803
|
-
if (!err)
|
|
5804
|
-
return jsonObj;
|
|
5805
|
-
try {
|
|
5806
|
-
Object.getOwnPropertyNames(err).forEach((key) => {
|
|
5807
|
-
jsonObj[key] = Object.getOwnPropertyDescriptor(err, key);
|
|
5808
|
-
});
|
|
5809
|
-
}
|
|
5810
|
-
catch (_) {
|
|
5811
|
-
return {
|
|
5812
|
-
error: 'failed to serialize the error',
|
|
5813
|
-
};
|
|
5814
|
-
}
|
|
5815
|
-
return jsonObj;
|
|
5816
|
-
}
|
|
5817
|
-
/**
|
|
5818
|
-
* isOnline safely return the navigator.online value for browser env
|
|
5819
|
-
* if navigator is not in global object, it always return true
|
|
5820
|
-
*/
|
|
5821
|
-
function isOnline() {
|
|
5822
|
-
const nav = typeof navigator !== 'undefined'
|
|
5823
|
-
? navigator
|
|
5824
|
-
: typeof window !== 'undefined' && window.navigator
|
|
5825
|
-
? window.navigator
|
|
5826
|
-
: undefined;
|
|
5827
|
-
if (!nav) {
|
|
5828
|
-
console.warn('isOnline failed to access window.navigator and assume browser is online');
|
|
5829
|
-
return true;
|
|
5830
|
-
}
|
|
5831
|
-
// RN navigator has undefined for onLine
|
|
5832
|
-
if (typeof nav.onLine !== 'boolean') {
|
|
5833
|
-
return true;
|
|
5834
|
-
}
|
|
5835
|
-
return nav.onLine;
|
|
5836
|
-
}
|
|
5837
|
-
/**
|
|
5838
|
-
* listenForConnectionChanges - Adds an event listener fired on browser going online or offline
|
|
5839
|
-
*/
|
|
5840
|
-
function addConnectionEventListeners(cb) {
|
|
5841
|
-
if (typeof window !== 'undefined' && window.addEventListener) {
|
|
5842
|
-
window.addEventListener('offline', cb);
|
|
5843
|
-
window.addEventListener('online', cb);
|
|
5844
|
-
}
|
|
5845
|
-
}
|
|
5846
|
-
function removeConnectionEventListeners(cb) {
|
|
5847
|
-
if (typeof window !== 'undefined' && window.removeEventListener) {
|
|
5848
|
-
window.removeEventListener('offline', cb);
|
|
5849
|
-
window.removeEventListener('online', cb);
|
|
5850
|
-
}
|
|
5851
|
-
}
|
|
5852
|
-
|
|
5853
5891
|
const UPDATE_SUBSCRIPTIONS_DEBOUNCE_DURATION = 600;
|
|
5854
5892
|
/**
|
|
5855
5893
|
* A `Call` object represents the active call the user is part of.
|
|
@@ -5887,6 +5925,13 @@ class Call {
|
|
|
5887
5925
|
this.dispatcher = new Dispatcher();
|
|
5888
5926
|
this.trackSubscriptionsSubject = new Subject();
|
|
5889
5927
|
this.reconnectAttempts = 0;
|
|
5928
|
+
this.maxReconnectAttempts = 10;
|
|
5929
|
+
/**
|
|
5930
|
+
* A list hooks/functions to invoke when the call is left.
|
|
5931
|
+
* A typical use case is to clean up some global event handlers.
|
|
5932
|
+
* @private
|
|
5933
|
+
*/
|
|
5934
|
+
this.leaveCallHooks = [];
|
|
5890
5935
|
/**
|
|
5891
5936
|
* Remove subscription for WebSocket events that were created by the `on` method.
|
|
5892
5937
|
* @param eventName
|
|
@@ -5913,6 +5958,8 @@ class Call {
|
|
|
5913
5958
|
(_d = this.sfuClient) === null || _d === void 0 ? void 0 : _d.close();
|
|
5914
5959
|
this.sfuClient = undefined;
|
|
5915
5960
|
this.dispatcher.offAll();
|
|
5961
|
+
// Call all leave call hooks, e.g. to clean up global event handlers
|
|
5962
|
+
this.leaveCallHooks.forEach((hook) => hook());
|
|
5916
5963
|
this.clientStore.setCurrentValue(this.clientStore.activeCallSubject, undefined);
|
|
5917
5964
|
this.state.setCurrentValue(this.state.callingStateSubject, CallingState.LEFT);
|
|
5918
5965
|
};
|
|
@@ -6004,12 +6051,15 @@ class Call {
|
|
|
6004
6051
|
// do nothing if the connection was closed on purpose
|
|
6005
6052
|
if (e.code === 1000)
|
|
6006
6053
|
return;
|
|
6007
|
-
if (this.reconnectAttempts
|
|
6008
|
-
|
|
6009
|
-
|
|
6054
|
+
if (this.reconnectAttempts < this.maxReconnectAttempts) {
|
|
6055
|
+
rejoin().catch(() => {
|
|
6056
|
+
console.log(`Rejoin failed for ${this.reconnectAttempts} times. Giving up.`);
|
|
6057
|
+
this.state.setCurrentValue(this.state.callingStateSubject, CallingState.RECONNECTING_FAILED);
|
|
6058
|
+
});
|
|
6010
6059
|
}
|
|
6011
6060
|
else {
|
|
6012
|
-
|
|
6061
|
+
console.log('Reconnect attempts exceeded. Giving up...');
|
|
6062
|
+
this.state.setCurrentValue(this.state.callingStateSubject, CallingState.RECONNECTING_FAILED);
|
|
6013
6063
|
}
|
|
6014
6064
|
});
|
|
6015
6065
|
});
|
|
@@ -6026,11 +6076,16 @@ class Call {
|
|
|
6026
6076
|
if (this.state.getCurrentValue(this.state.callingState$) ===
|
|
6027
6077
|
CallingState.OFFLINE) {
|
|
6028
6078
|
console.log('Join: Going online...');
|
|
6029
|
-
rejoin()
|
|
6079
|
+
rejoin().catch(() => {
|
|
6080
|
+
console.log(`Rejoin failed for ${this.reconnectAttempts} times. Giving up.`);
|
|
6081
|
+
this.state.setCurrentValue(this.state.callingStateSubject, CallingState.RECONNECTING_FAILED);
|
|
6082
|
+
});
|
|
6030
6083
|
}
|
|
6031
6084
|
};
|
|
6032
6085
|
window.addEventListener('offline', handleOnOffline);
|
|
6033
6086
|
window.addEventListener('online', handleOnOnline);
|
|
6087
|
+
// register cleanup hooks
|
|
6088
|
+
this.leaveCallHooks.push(() => window.removeEventListener('offline', handleOnOffline), () => window.removeEventListener('online', handleOnOnline));
|
|
6034
6089
|
}
|
|
6035
6090
|
this.subscriber = createSubscriber({
|
|
6036
6091
|
rpcClient: sfuClient,
|
|
@@ -6088,7 +6143,7 @@ class Call {
|
|
|
6088
6143
|
}
|
|
6089
6144
|
catch (err) {
|
|
6090
6145
|
// join failed, try to rejoin
|
|
6091
|
-
if (this.reconnectAttempts <
|
|
6146
|
+
if (this.reconnectAttempts < this.maxReconnectAttempts) {
|
|
6092
6147
|
yield rejoin();
|
|
6093
6148
|
console.log(`Rejoin ${this.reconnectAttempts} successful!`);
|
|
6094
6149
|
}
|
|
@@ -6234,12 +6289,10 @@ class Call {
|
|
|
6234
6289
|
* @param trackType the track type to stop publishing.
|
|
6235
6290
|
*/
|
|
6236
6291
|
this.stopPublish = (trackType) => __awaiter(this, void 0, void 0, function* () {
|
|
6237
|
-
|
|
6238
|
-
throw new Error(`Call not joined yet.`);
|
|
6239
|
-
}
|
|
6292
|
+
var _f;
|
|
6240
6293
|
console.log(`stopPublish`, TrackType[trackType]);
|
|
6241
|
-
const wasPublishing = this.publisher.unpublishStream(trackType);
|
|
6242
|
-
if (wasPublishing) {
|
|
6294
|
+
const wasPublishing = (_f = this.publisher) === null || _f === void 0 ? void 0 : _f.unpublishStream(trackType);
|
|
6295
|
+
if (wasPublishing && this.sfuClient) {
|
|
6243
6296
|
yield this.sfuClient.updateMuteState(trackType, true);
|
|
6244
6297
|
const audioOrVideoOrScreenShareStream = trackTypeToParticipantStreamKey(trackType);
|
|
6245
6298
|
if (audioOrVideoOrScreenShareStream) {
|
|
@@ -6316,8 +6369,8 @@ class Call {
|
|
|
6316
6369
|
* @returns
|
|
6317
6370
|
*/
|
|
6318
6371
|
this.getStats = (kind, selector) => __awaiter(this, void 0, void 0, function* () {
|
|
6319
|
-
var
|
|
6320
|
-
return (
|
|
6372
|
+
var _g;
|
|
6373
|
+
return (_g = this.statsReporter) === null || _g === void 0 ? void 0 : _g.getRawStatsForTrack(kind, selector);
|
|
6321
6374
|
});
|
|
6322
6375
|
/**
|
|
6323
6376
|
* Will enhance the reported stats with additional participant-specific information (`callStatsReport$` state [store variable](./StreamVideoClient.md/#readonlystatestore)).
|
|
@@ -6405,8 +6458,8 @@ class Call {
|
|
|
6405
6458
|
* @returns
|
|
6406
6459
|
*/
|
|
6407
6460
|
this.updatePublishQuality = (enabledRids) => __awaiter(this, void 0, void 0, function* () {
|
|
6408
|
-
var
|
|
6409
|
-
return (
|
|
6461
|
+
var _h;
|
|
6462
|
+
return (_h = this.publisher) === null || _h === void 0 ? void 0 : _h.updateVideoPublishQuality(enabledRids);
|
|
6410
6463
|
});
|
|
6411
6464
|
this.handleOnTrack = (e) => {
|
|
6412
6465
|
const [primaryStream] = e.streams;
|
|
@@ -8728,7 +8781,7 @@ class StreamClient {
|
|
|
8728
8781
|
}
|
|
8729
8782
|
getUserAgent() {
|
|
8730
8783
|
return (this.userAgent ||
|
|
8731
|
-
`stream-video-javascript-client-${this.node ? 'node' : 'browser'}-${"0.0.1-alpha.
|
|
8784
|
+
`stream-video-javascript-client-${this.node ? 'node' : 'browser'}-${"0.0.1-alpha.84"}`);
|
|
8732
8785
|
}
|
|
8733
8786
|
setUserAgent(userAgent) {
|
|
8734
8787
|
this.userAgent = userAgent;
|