@signalwire/js 4.0.0-dev-20260410161919 → 4.0.0-dev-20260413184400
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/browser.mjs +934 -614
- package/dist/browser.mjs.map +1 -1
- package/dist/browser.umd.js +934 -614
- package/dist/browser.umd.js.map +1 -1
- package/dist/index.cjs +698 -379
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +8 -2
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +8 -2
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +688 -369
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/browser.mjs
CHANGED
|
@@ -3390,7 +3390,7 @@ var require_map = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
3390
3390
|
exports.map = void 0;
|
|
3391
3391
|
var lift_1$64 = require_lift();
|
|
3392
3392
|
var OperatorSubscriber_1$54 = require_OperatorSubscriber();
|
|
3393
|
-
function map$
|
|
3393
|
+
function map$19(project, thisArg) {
|
|
3394
3394
|
return lift_1$64.operate(function(source, subscriber) {
|
|
3395
3395
|
var index = 0;
|
|
3396
3396
|
source.subscribe(OperatorSubscriber_1$54.createOperatorSubscriber(subscriber, function(value) {
|
|
@@ -3398,7 +3398,7 @@ var require_map = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
3398
3398
|
}));
|
|
3399
3399
|
});
|
|
3400
3400
|
}
|
|
3401
|
-
exports.map = map$
|
|
3401
|
+
exports.map = map$19;
|
|
3402
3402
|
}));
|
|
3403
3403
|
|
|
3404
3404
|
//#endregion
|
|
@@ -4140,7 +4140,7 @@ var require_timer = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
4140
4140
|
var async_1$11 = require_async();
|
|
4141
4141
|
var isScheduler_1 = require_isScheduler();
|
|
4142
4142
|
var isDate_1$1 = require_isDate();
|
|
4143
|
-
function timer$
|
|
4143
|
+
function timer$2(dueTime, intervalOrScheduler, scheduler) {
|
|
4144
4144
|
if (dueTime === void 0) dueTime = 0;
|
|
4145
4145
|
if (scheduler === void 0) scheduler = async_1$11.async;
|
|
4146
4146
|
var intervalDuration = -1;
|
|
@@ -4159,7 +4159,7 @@ var require_timer = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
4159
4159
|
}, due);
|
|
4160
4160
|
});
|
|
4161
4161
|
}
|
|
4162
|
-
exports.timer = timer$
|
|
4162
|
+
exports.timer = timer$2;
|
|
4163
4163
|
}));
|
|
4164
4164
|
|
|
4165
4165
|
//#endregion
|
|
@@ -4293,7 +4293,7 @@ var require_filter = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
4293
4293
|
exports.filter = void 0;
|
|
4294
4294
|
var lift_1$62 = require_lift();
|
|
4295
4295
|
var OperatorSubscriber_1$49 = require_OperatorSubscriber();
|
|
4296
|
-
function filter$
|
|
4296
|
+
function filter$16(predicate, thisArg) {
|
|
4297
4297
|
return lift_1$62.operate(function(source, subscriber) {
|
|
4298
4298
|
var index = 0;
|
|
4299
4299
|
source.subscribe(OperatorSubscriber_1$49.createOperatorSubscriber(subscriber, function(value) {
|
|
@@ -4301,7 +4301,7 @@ var require_filter = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
4301
4301
|
}));
|
|
4302
4302
|
});
|
|
4303
4303
|
}
|
|
4304
|
-
exports.filter = filter$
|
|
4304
|
+
exports.filter = filter$16;
|
|
4305
4305
|
}));
|
|
4306
4306
|
|
|
4307
4307
|
//#endregion
|
|
@@ -6934,7 +6934,7 @@ var require_switchMap = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
6934
6934
|
var innerFrom_1$6 = require_innerFrom();
|
|
6935
6935
|
var lift_1$13 = require_lift();
|
|
6936
6936
|
var OperatorSubscriber_1$11 = require_OperatorSubscriber();
|
|
6937
|
-
function switchMap$
|
|
6937
|
+
function switchMap$7(project, resultSelector) {
|
|
6938
6938
|
return lift_1$13.operate(function(source, subscriber) {
|
|
6939
6939
|
var innerSubscriber = null;
|
|
6940
6940
|
var index = 0;
|
|
@@ -6958,7 +6958,7 @@ var require_switchMap = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
6958
6958
|
}));
|
|
6959
6959
|
});
|
|
6960
6960
|
}
|
|
6961
|
-
exports.switchMap = switchMap$
|
|
6961
|
+
exports.switchMap = switchMap$7;
|
|
6962
6962
|
}));
|
|
6963
6963
|
|
|
6964
6964
|
//#endregion
|
|
@@ -7582,7 +7582,7 @@ var require_withLatestFrom = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
7582
7582
|
var identity_1$1 = require_identity();
|
|
7583
7583
|
var noop_1$1 = require_noop();
|
|
7584
7584
|
var args_1 = require_args();
|
|
7585
|
-
function withLatestFrom$
|
|
7585
|
+
function withLatestFrom$2() {
|
|
7586
7586
|
var inputs = [];
|
|
7587
7587
|
for (var _i = 0; _i < arguments.length; _i++) inputs[_i] = arguments[_i];
|
|
7588
7588
|
var project = args_1.popResultSelector(inputs);
|
|
@@ -7611,7 +7611,7 @@ var require_withLatestFrom = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
7611
7611
|
}));
|
|
7612
7612
|
});
|
|
7613
7613
|
}
|
|
7614
|
-
exports.withLatestFrom = withLatestFrom$
|
|
7614
|
+
exports.withLatestFrom = withLatestFrom$2;
|
|
7615
7615
|
}));
|
|
7616
7616
|
|
|
7617
7617
|
//#endregion
|
|
@@ -8933,13 +8933,13 @@ var require_cjs = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
8933
8933
|
|
|
8934
8934
|
//#endregion
|
|
8935
8935
|
//#region src/behaviors/Destroyable.ts
|
|
8936
|
-
var import_cjs$
|
|
8936
|
+
var import_cjs$28 = require_cjs();
|
|
8937
8937
|
var Destroyable = class {
|
|
8938
8938
|
constructor() {
|
|
8939
8939
|
this.subscriptions = [];
|
|
8940
8940
|
this.subjects = [];
|
|
8941
|
-
this._destroyed$ = new import_cjs$
|
|
8942
|
-
this._change$ = new import_cjs$
|
|
8941
|
+
this._destroyed$ = new import_cjs$28.Subject();
|
|
8942
|
+
this._change$ = new import_cjs$28.Subject();
|
|
8943
8943
|
}
|
|
8944
8944
|
destroy() {
|
|
8945
8945
|
this._observableCache?.clear();
|
|
@@ -8976,7 +8976,7 @@ var Destroyable = class {
|
|
|
8976
8976
|
this._observableCache ??= /* @__PURE__ */ new Map();
|
|
8977
8977
|
let cached = this._observableCache.get(publicKey);
|
|
8978
8978
|
if (!cached) {
|
|
8979
|
-
cached = factory().pipe((0, import_cjs$
|
|
8979
|
+
cached = factory().pipe((0, import_cjs$28.observeOn)(import_cjs$28.asapScheduler));
|
|
8980
8980
|
this._observableCache.set(publicKey, cached);
|
|
8981
8981
|
}
|
|
8982
8982
|
return cached;
|
|
@@ -8990,32 +8990,32 @@ var Destroyable = class {
|
|
|
8990
8990
|
* Do NOT use for observables consumed internally by the SDK.
|
|
8991
8991
|
*/
|
|
8992
8992
|
deferEmission(observable) {
|
|
8993
|
-
return observable.pipe((0, import_cjs$
|
|
8993
|
+
return observable.pipe((0, import_cjs$28.observeOn)(import_cjs$28.asapScheduler));
|
|
8994
8994
|
}
|
|
8995
8995
|
subscribeTo(observable, observerOrNext) {
|
|
8996
8996
|
const subscription = observable.subscribe(observerOrNext);
|
|
8997
8997
|
this.subscriptions.push(subscription);
|
|
8998
8998
|
}
|
|
8999
8999
|
createSubject() {
|
|
9000
|
-
const subject = new import_cjs$
|
|
9000
|
+
const subject = new import_cjs$28.Subject();
|
|
9001
9001
|
this.subjects.push(subject);
|
|
9002
|
-
this.subscriptions.push(subject.pipe((0, import_cjs$
|
|
9002
|
+
this.subscriptions.push(subject.pipe((0, import_cjs$28.map)(() => void 0)).subscribe(this._change$));
|
|
9003
9003
|
return subject;
|
|
9004
9004
|
}
|
|
9005
9005
|
createReplaySubject(bufferSize, windowTime$1) {
|
|
9006
|
-
const subject = new import_cjs$
|
|
9006
|
+
const subject = new import_cjs$28.ReplaySubject(bufferSize, windowTime$1);
|
|
9007
9007
|
this.subjects.push(subject);
|
|
9008
|
-
this.subscriptions.push(subject.pipe((0, import_cjs$
|
|
9008
|
+
this.subscriptions.push(subject.pipe((0, import_cjs$28.map)(() => void 0)).subscribe(this._change$));
|
|
9009
9009
|
return subject;
|
|
9010
9010
|
}
|
|
9011
9011
|
createBehaviorSubject(initialValue) {
|
|
9012
|
-
const subject = new import_cjs$
|
|
9012
|
+
const subject = new import_cjs$28.BehaviorSubject(initialValue);
|
|
9013
9013
|
this.subjects.push(subject);
|
|
9014
|
-
this.subscriptions.push(subject.pipe((0, import_cjs$
|
|
9014
|
+
this.subscriptions.push(subject.pipe((0, import_cjs$28.skip)(1), (0, import_cjs$28.map)(() => void 0)).subscribe(this._change$));
|
|
9015
9015
|
return subject;
|
|
9016
9016
|
}
|
|
9017
9017
|
get $() {
|
|
9018
|
-
return this._change$.pipe((0, import_cjs$
|
|
9018
|
+
return this._change$.pipe((0, import_cjs$28.map)(() => this));
|
|
9019
9019
|
}
|
|
9020
9020
|
/**
|
|
9021
9021
|
* Observable that emits when the instance is destroyed
|
|
@@ -9474,9 +9474,9 @@ var require_loglevel = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
9474
9474
|
defaultLogger$1 = new Logger();
|
|
9475
9475
|
defaultLogger$1.getLogger = function getLogger$1(name) {
|
|
9476
9476
|
if (typeof name !== "symbol" && typeof name !== "string" || name === "") throw new TypeError("You must supply a name when creating a logger.");
|
|
9477
|
-
var logger$
|
|
9478
|
-
if (!logger$
|
|
9479
|
-
return logger$
|
|
9477
|
+
var logger$30 = _loggersByName[name];
|
|
9478
|
+
if (!logger$30) logger$30 = _loggersByName[name] = new Logger(name, defaultLogger$1.methodFactory);
|
|
9479
|
+
return logger$30;
|
|
9480
9480
|
};
|
|
9481
9481
|
var _log = typeof window !== undefinedType ? window.log : void 0;
|
|
9482
9482
|
defaultLogger$1.noConflict = function() {
|
|
@@ -9516,15 +9516,15 @@ const shouldStringify = (payload) => {
|
|
|
9516
9516
|
return true;
|
|
9517
9517
|
};
|
|
9518
9518
|
const wsTraffic = ({ type, payload }) => {
|
|
9519
|
-
const logger$
|
|
9519
|
+
const logger$30 = getLoggerInstance();
|
|
9520
9520
|
const { logWsTraffic } = debugOptions ?? {};
|
|
9521
9521
|
if (!logWsTraffic) return;
|
|
9522
9522
|
const msg = shouldStringify(payload) ? JSON.stringify(payload, null, 2) : payload;
|
|
9523
|
-
return logger$
|
|
9523
|
+
return logger$30.debug(`${type.toUpperCase()}: \n`, msg, "\n");
|
|
9524
9524
|
};
|
|
9525
9525
|
const getLogger = () => {
|
|
9526
|
-
const logger$
|
|
9527
|
-
return new Proxy(logger$
|
|
9526
|
+
const logger$30 = getLoggerInstance();
|
|
9527
|
+
return new Proxy(logger$30, { get(target, prop, receiver) {
|
|
9528
9528
|
if (prop === "wsTraffic") return wsTraffic;
|
|
9529
9529
|
return Reflect.get(target, prop, receiver);
|
|
9530
9530
|
} });
|
|
@@ -9573,8 +9573,8 @@ const asyncRetry = async ({ asyncCallable, maxRetries: retries = DEFAULT_MAX_RET
|
|
|
9573
9573
|
|
|
9574
9574
|
//#endregion
|
|
9575
9575
|
//#region src/controllers/HTTPRequestController.ts
|
|
9576
|
-
var import_cjs$
|
|
9577
|
-
const logger$
|
|
9576
|
+
var import_cjs$27 = require_cjs();
|
|
9577
|
+
const logger$29 = getLogger();
|
|
9578
9578
|
const GET_PARAMS = {
|
|
9579
9579
|
method: "GET",
|
|
9580
9580
|
headers: { Accept: "application/json" }
|
|
@@ -9609,9 +9609,9 @@ var HTTPRequestController = class HTTPRequestController {
|
|
|
9609
9609
|
constructor(baseURL, getCredential, options = {}) {
|
|
9610
9610
|
this.baseURL = baseURL;
|
|
9611
9611
|
this.getCredential = getCredential;
|
|
9612
|
-
this._responses$ = new import_cjs$
|
|
9613
|
-
this._errors$ = new import_cjs$
|
|
9614
|
-
this._status$ = new import_cjs$
|
|
9612
|
+
this._responses$ = new import_cjs$27.Subject();
|
|
9613
|
+
this._errors$ = new import_cjs$27.Subject();
|
|
9614
|
+
this._status$ = new import_cjs$27.BehaviorSubject("idle");
|
|
9615
9615
|
this.maxRetries = options.maxRetries ?? HTTPRequestController.defaultMaxRetries;
|
|
9616
9616
|
this.retryDelayMin = options.retryDelayMin ?? HTTPRequestController.defaultRetryDelayMinMs;
|
|
9617
9617
|
this.retryDelayMax = options.retryDelayMax ?? HTTPRequestController.defaultRetryDelayMaxMs;
|
|
@@ -9637,7 +9637,7 @@ var HTTPRequestController = class HTTPRequestController {
|
|
|
9637
9637
|
this._responses$.next(response);
|
|
9638
9638
|
return response;
|
|
9639
9639
|
} catch (error) {
|
|
9640
|
-
logger$
|
|
9640
|
+
logger$29.error("[HTTPRequestController] Request error:", error);
|
|
9641
9641
|
this._status$.next("error");
|
|
9642
9642
|
const err = error instanceof Error ? error : new Error("HTTP request failed", { cause: error });
|
|
9643
9643
|
this._errors$.next(err);
|
|
@@ -9664,7 +9664,7 @@ var HTTPRequestController = class HTTPRequestController {
|
|
|
9664
9664
|
const url = this.buildURL(request.url);
|
|
9665
9665
|
const headers = this.buildHeaders(request.headers);
|
|
9666
9666
|
const timeout$5 = request.timeout ?? this.requestTimeout;
|
|
9667
|
-
logger$
|
|
9667
|
+
logger$29.debug("[HTTPRequestController] Executing request:", {
|
|
9668
9668
|
method: request.method,
|
|
9669
9669
|
url,
|
|
9670
9670
|
headers: Object.keys(headers).reduce((acc, key) => {
|
|
@@ -9684,7 +9684,7 @@ var HTTPRequestController = class HTTPRequestController {
|
|
|
9684
9684
|
});
|
|
9685
9685
|
clearTimeout(timeoutId);
|
|
9686
9686
|
const httpResponse = await this.convertResponse(response);
|
|
9687
|
-
logger$
|
|
9687
|
+
logger$29.debug("[HTTPRequestController] Response received:", {
|
|
9688
9688
|
status: response.status,
|
|
9689
9689
|
statusText: response.statusText,
|
|
9690
9690
|
headers: [...response.headers.entries()],
|
|
@@ -9694,7 +9694,7 @@ var HTTPRequestController = class HTTPRequestController {
|
|
|
9694
9694
|
} catch (error) {
|
|
9695
9695
|
clearTimeout(timeoutId);
|
|
9696
9696
|
if (error instanceof Error && error.name === "AbortError") throw new RequestTimeoutError(`Request timeout after ${timeout$5}ms`, { cause: error });
|
|
9697
|
-
logger$
|
|
9697
|
+
logger$29.error("[HTTPRequestController] Request failed:", error);
|
|
9698
9698
|
throw error;
|
|
9699
9699
|
}
|
|
9700
9700
|
}
|
|
@@ -9708,8 +9708,8 @@ var HTTPRequestController = class HTTPRequestController {
|
|
|
9708
9708
|
const credential = this.getCredential();
|
|
9709
9709
|
if (credential.token) {
|
|
9710
9710
|
headers.Authorization = `Bearer ${credential.token}`;
|
|
9711
|
-
logger$
|
|
9712
|
-
} else logger$
|
|
9711
|
+
logger$29.debug("[HTTPRequestController] Using Bearer token auth, token length:", credential.token.length);
|
|
9712
|
+
} else logger$29.warn("[HTTPRequestController] No credentials available for authentication");
|
|
9713
9713
|
return headers;
|
|
9714
9714
|
}
|
|
9715
9715
|
/**
|
|
@@ -9858,6 +9858,19 @@ const DEFAULT_RECONNECT_DELAY_MAX_MS = 3e3;
|
|
|
9858
9858
|
const DEFAULT_DEVICE_DEBOUNCE_TIME_MS = 1500;
|
|
9859
9859
|
const DEFAULT_DEVICE_POLLING_INTERVAL_MS = 0;
|
|
9860
9860
|
const PREFERENCES_STORAGE_KEY = "sw:preferences";
|
|
9861
|
+
/** Scope value that enables automatic token refresh. */
|
|
9862
|
+
const SAT_REFRESH_SCOPE = "sat:refresh";
|
|
9863
|
+
/** API endpoints for device token operations. */
|
|
9864
|
+
const DEVICE_TOKEN_ENDPOINT = "/api/fabric/subscriber/devices/token";
|
|
9865
|
+
const DEVICE_REFRESH_ENDPOINT = "/api/fabric/subscriber/devices/refresh";
|
|
9866
|
+
/** Default device token TTL in seconds (15 minutes). */
|
|
9867
|
+
const DEVICE_TOKEN_DEFAULT_EXPIRE_IN = 900;
|
|
9868
|
+
/** Buffer time in milliseconds before expiry to trigger refresh. */
|
|
9869
|
+
const DEVICE_TOKEN_REFRESH_BUFFER_MS = 3e4;
|
|
9870
|
+
/** Maximum retry attempts for device token refresh on transient failure. */
|
|
9871
|
+
const DEVICE_TOKEN_REFRESH_MAX_RETRIES = 3;
|
|
9872
|
+
/** Base delay in milliseconds for exponential backoff on refresh retry. */
|
|
9873
|
+
const DEVICE_TOKEN_REFRESH_RETRY_BASE_MS = 1e3;
|
|
9861
9874
|
/** JSON-RPC error code for requester validation failure (corrupted auth state). */
|
|
9862
9875
|
const RPC_ERROR_REQUESTER_VALIDATION_FAILED = -32003;
|
|
9863
9876
|
/** JSON-RPC error code for invalid params (e.g., missing authentication block). */
|
|
@@ -9948,7 +9961,7 @@ function fromMsToSec(milliseconds) {
|
|
|
9948
9961
|
|
|
9949
9962
|
//#endregion
|
|
9950
9963
|
//#region src/containers/PreferencesContainer.ts
|
|
9951
|
-
const logger$
|
|
9964
|
+
const logger$28 = getLogger();
|
|
9952
9965
|
var PreferencesContainer = class PreferencesContainer {
|
|
9953
9966
|
static get instance() {
|
|
9954
9967
|
this._instance ??= new PreferencesContainer();
|
|
@@ -10610,7 +10623,7 @@ var ClientPreferences = class {
|
|
|
10610
10623
|
if (!this._storage) return;
|
|
10611
10624
|
const data = collectStoredPreferences();
|
|
10612
10625
|
this._storage.setItem(PREFERENCES_STORAGE_KEY, data, "local").catch((error) => {
|
|
10613
|
-
logger$
|
|
10626
|
+
logger$28.error(`[ClientPreferences] Failed to save preferences: ${String(error)}`);
|
|
10614
10627
|
});
|
|
10615
10628
|
}
|
|
10616
10629
|
/** Loads preferences from storage and applies them to the container. */
|
|
@@ -10619,15 +10632,15 @@ var ClientPreferences = class {
|
|
|
10619
10632
|
this._storage.getItem(PREFERENCES_STORAGE_KEY, "local").then((stored) => {
|
|
10620
10633
|
if (stored) applyStoredPreferences(stored);
|
|
10621
10634
|
}).catch((error) => {
|
|
10622
|
-
logger$
|
|
10635
|
+
logger$28.error(`[ClientPreferences] Failed to load preferences: ${String(error)}`);
|
|
10623
10636
|
});
|
|
10624
10637
|
}
|
|
10625
10638
|
};
|
|
10626
10639
|
|
|
10627
10640
|
//#endregion
|
|
10628
10641
|
//#region src/controllers/NavigatorDeviceController.ts
|
|
10629
|
-
var import_cjs$
|
|
10630
|
-
const logger$
|
|
10642
|
+
var import_cjs$26 = require_cjs();
|
|
10643
|
+
const logger$27 = getLogger();
|
|
10631
10644
|
/** Maps a device kind to its storage key. */
|
|
10632
10645
|
const DEVICE_STORAGE_KEYS = {
|
|
10633
10646
|
audioinput: DEVICE_STORAGE_KEY_AUDIO_INPUT,
|
|
@@ -10649,7 +10662,7 @@ var NavigatorDeviceController = class extends Destroyable {
|
|
|
10649
10662
|
super();
|
|
10650
10663
|
this.webRTCApiProvider = webRTCApiProvider;
|
|
10651
10664
|
this.deviceChangeHandler = () => {
|
|
10652
|
-
logger$
|
|
10665
|
+
logger$27.debug("[DeviceController] Device change detected");
|
|
10653
10666
|
this.enumerateDevices();
|
|
10654
10667
|
};
|
|
10655
10668
|
this._devicesState$ = this.createBehaviorSubject(initialDevicesState);
|
|
@@ -10686,17 +10699,17 @@ var NavigatorDeviceController = class extends Destroyable {
|
|
|
10686
10699
|
return {};
|
|
10687
10700
|
}
|
|
10688
10701
|
get errors$() {
|
|
10689
|
-
return this.cachedObservable("errors$", () => this._errors$.asObservable().pipe((0, import_cjs$
|
|
10702
|
+
return this.cachedObservable("errors$", () => this._errors$.asObservable().pipe((0, import_cjs$26.takeUntil)(this.destroyed$)));
|
|
10690
10703
|
}
|
|
10691
10704
|
/** Observable that emits when the SDK auto-switches a device. */
|
|
10692
10705
|
get deviceRecovered$() {
|
|
10693
|
-
return this._deviceRecovered$.asObservable().pipe((0, import_cjs$
|
|
10706
|
+
return this._deviceRecovered$.asObservable().pipe((0, import_cjs$26.takeUntil)(this.destroyed$));
|
|
10694
10707
|
}
|
|
10695
10708
|
get videoInputDisabled$() {
|
|
10696
|
-
return this.cachedObservable("videoInputDisabled$", () => this._videoInputDisabled$.asObservable().pipe((0, import_cjs$
|
|
10709
|
+
return this.cachedObservable("videoInputDisabled$", () => this._videoInputDisabled$.asObservable().pipe((0, import_cjs$26.distinctUntilChanged)(), (0, import_cjs$26.takeUntil)(this.destroyed$)));
|
|
10697
10710
|
}
|
|
10698
10711
|
get audioInputDisabled$() {
|
|
10699
|
-
return this.cachedObservable("audioInputDisabled$", () => this._audioInputDisabled$.asObservable().pipe((0, import_cjs$
|
|
10712
|
+
return this.cachedObservable("audioInputDisabled$", () => this._audioInputDisabled$.asObservable().pipe((0, import_cjs$26.distinctUntilChanged)(), (0, import_cjs$26.takeUntil)(this.destroyed$)));
|
|
10700
10713
|
}
|
|
10701
10714
|
get videoInputDisabled() {
|
|
10702
10715
|
return this._videoInputDisabled$.value;
|
|
@@ -10705,22 +10718,22 @@ var NavigatorDeviceController = class extends Destroyable {
|
|
|
10705
10718
|
return this._audioInputDisabled$.value;
|
|
10706
10719
|
}
|
|
10707
10720
|
get audioInputDevices$() {
|
|
10708
|
-
return this.cachedObservable("audioInputDevices$", () => this._devicesState$.pipe((0, import_cjs$
|
|
10721
|
+
return this.cachedObservable("audioInputDevices$", () => this._devicesState$.pipe((0, import_cjs$26.map)((state) => state.audioinput), (0, import_cjs$26.distinctUntilChanged)(), (0, import_cjs$26.takeUntil)(this.destroyed$)));
|
|
10709
10722
|
}
|
|
10710
10723
|
get audioOutputDevices$() {
|
|
10711
|
-
return this.cachedObservable("audioOutputDevices$", () => this._devicesState$.pipe((0, import_cjs$
|
|
10724
|
+
return this.cachedObservable("audioOutputDevices$", () => this._devicesState$.pipe((0, import_cjs$26.map)((state) => state.audiooutput), (0, import_cjs$26.distinctUntilChanged)(), (0, import_cjs$26.takeUntil)(this.destroyed$)));
|
|
10712
10725
|
}
|
|
10713
10726
|
get videoInputDevices$() {
|
|
10714
|
-
return this.cachedObservable("videoInputDevices$", () => this._devicesState$.pipe((0, import_cjs$
|
|
10727
|
+
return this.cachedObservable("videoInputDevices$", () => this._devicesState$.pipe((0, import_cjs$26.map)((state) => state.videoinput), (0, import_cjs$26.distinctUntilChanged)(), (0, import_cjs$26.takeUntil)(this.destroyed$)));
|
|
10715
10728
|
}
|
|
10716
10729
|
get selectedAudioInputDevice$() {
|
|
10717
|
-
return this.cachedObservable("selectedAudioInputDevice$", () => this._selectedDevicesState$.asObservable().pipe((0, import_cjs$
|
|
10730
|
+
return this.cachedObservable("selectedAudioInputDevice$", () => this._selectedDevicesState$.asObservable().pipe((0, import_cjs$26.map)((state) => state.audioinput), (0, import_cjs$26.distinctUntilChanged)(), (0, import_cjs$26.takeUntil)(this.destroyed$), (0, import_cjs$26.tap)((info) => logger$27.debug("[DeviceController] Selected audio input device changed:", info))));
|
|
10718
10731
|
}
|
|
10719
10732
|
get selectedAudioOutputDevice$() {
|
|
10720
|
-
return this.cachedObservable("selectedAudioOutputDevice$", () => this._selectedDevicesState$.asObservable().pipe((0, import_cjs$
|
|
10733
|
+
return this.cachedObservable("selectedAudioOutputDevice$", () => this._selectedDevicesState$.asObservable().pipe((0, import_cjs$26.map)((state) => state.audiooutput), (0, import_cjs$26.distinctUntilChanged)(), (0, import_cjs$26.takeUntil)(this.destroyed$), (0, import_cjs$26.tap)((info) => logger$27.debug("[DeviceController] Selected audio output device changed:", info))));
|
|
10721
10734
|
}
|
|
10722
10735
|
get selectedVideoInputDevice$() {
|
|
10723
|
-
return this.cachedObservable("selectedVideoInputDevice$", () => this._selectedDevicesState$.asObservable().pipe((0, import_cjs$
|
|
10736
|
+
return this.cachedObservable("selectedVideoInputDevice$", () => this._selectedDevicesState$.asObservable().pipe((0, import_cjs$26.map)((state) => state.videoinput), (0, import_cjs$26.distinctUntilChanged)(), (0, import_cjs$26.takeUntil)(this.destroyed$), (0, import_cjs$26.tap)((info) => logger$27.debug("[DeviceController] Selected video input device changed:", info))));
|
|
10724
10737
|
}
|
|
10725
10738
|
get selectedAudioInputDevice() {
|
|
10726
10739
|
if (this._audioInputDisabled$.value) return null;
|
|
@@ -10795,7 +10808,7 @@ var NavigatorDeviceController = class extends Destroyable {
|
|
|
10795
10808
|
if (device) this.persistDeviceSelection("audioinput", device);
|
|
10796
10809
|
}
|
|
10797
10810
|
selectVideoInputDevice(device) {
|
|
10798
|
-
logger$
|
|
10811
|
+
logger$27.debug("[DeviceController] Setting selected video input device:", device);
|
|
10799
10812
|
if (this._videoInputDisabled$.value && device) this._videoInputDisabled$.next(false);
|
|
10800
10813
|
const previous = this._selectedDevicesState$.value.videoinput;
|
|
10801
10814
|
if (previous && previous.deviceId !== device?.deviceId) this._deviceHistory.push("videoinput", previous);
|
|
@@ -10816,7 +10829,7 @@ var NavigatorDeviceController = class extends Destroyable {
|
|
|
10816
10829
|
}
|
|
10817
10830
|
init() {
|
|
10818
10831
|
this.loadPersistedDevices();
|
|
10819
|
-
this.subscribeTo(this._devicesState$.pipe((0, import_cjs$
|
|
10832
|
+
this.subscribeTo(this._devicesState$.pipe((0, import_cjs$26.debounceTime)(PreferencesContainer.instance.deviceDebounceTime)), (devicesState) => {
|
|
10820
10833
|
const currentSelected = this._selectedDevicesState$.value;
|
|
10821
10834
|
const newAudioInput = this._audioInputDisabled$.value ? null : this.resolveDevice("audioinput", devicesState.audioinput, currentSelected.audioinput, PreferencesContainer.instance.preferredAudioInput);
|
|
10822
10835
|
const newAudioOutput = this.resolveDevice("audiooutput", devicesState.audiooutput, currentSelected.audiooutput, PreferencesContainer.instance.preferredAudioOutput);
|
|
@@ -10852,7 +10865,7 @@ var NavigatorDeviceController = class extends Destroyable {
|
|
|
10852
10865
|
}
|
|
10853
10866
|
const fromHistory = this._deviceHistory.findInHistory(kind, devices);
|
|
10854
10867
|
if (fromHistory) {
|
|
10855
|
-
logger$
|
|
10868
|
+
logger$27.debug(`[DeviceController] Device disappeared, falling back to history: ${fromHistory.label}`);
|
|
10856
10869
|
this.emitDeviceRecovered(kind, selected, fromHistory, "device_disconnected");
|
|
10857
10870
|
return fromHistory;
|
|
10858
10871
|
}
|
|
@@ -10905,7 +10918,7 @@ var NavigatorDeviceController = class extends Destroyable {
|
|
|
10905
10918
|
try {
|
|
10906
10919
|
await this._storageManager.setItem(DEVICE_STORAGE_KEYS[kind], stored, "local");
|
|
10907
10920
|
} catch (error) {
|
|
10908
|
-
logger$
|
|
10921
|
+
logger$27.error(`[DeviceController] Failed to persist device selection for ${kind}:`, error);
|
|
10909
10922
|
}
|
|
10910
10923
|
}
|
|
10911
10924
|
async loadPersistedDevices() {
|
|
@@ -10921,7 +10934,7 @@ var NavigatorDeviceController = class extends Destroyable {
|
|
|
10921
10934
|
[kind]: stored
|
|
10922
10935
|
};
|
|
10923
10936
|
} catch (error) {
|
|
10924
|
-
logger$
|
|
10937
|
+
logger$27.error(`[DeviceController] Failed to load persisted device for ${kind}:`, error);
|
|
10925
10938
|
}
|
|
10926
10939
|
}
|
|
10927
10940
|
/** Clears device history, persisted selections, and re-enumerates devices. */
|
|
@@ -10938,8 +10951,8 @@ var NavigatorDeviceController = class extends Destroyable {
|
|
|
10938
10951
|
enableDeviceMonitoring() {
|
|
10939
10952
|
this.disableDeviceMonitoring();
|
|
10940
10953
|
this.webRTCApiProvider.mediaDevices.addEventListener("devicechange", this.deviceChangeHandler);
|
|
10941
|
-
if (PreferencesContainer.instance.devicePollingInterval > 0) this._devicesPoolingSubscription = (0, import_cjs$
|
|
10942
|
-
logger$
|
|
10954
|
+
if (PreferencesContainer.instance.devicePollingInterval > 0) this._devicesPoolingSubscription = (0, import_cjs$26.interval)(PreferencesContainer.instance.devicePollingInterval).subscribe(() => {
|
|
10955
|
+
logger$27.debug("[DeviceController] Polling devices due to interval");
|
|
10943
10956
|
this.enumerateDevices();
|
|
10944
10957
|
});
|
|
10945
10958
|
this.enumerateDevices();
|
|
@@ -10965,13 +10978,13 @@ var NavigatorDeviceController = class extends Destroyable {
|
|
|
10965
10978
|
videoinput: []
|
|
10966
10979
|
});
|
|
10967
10980
|
this._devicesState$.next(devicesByKind);
|
|
10968
|
-
logger$
|
|
10981
|
+
logger$27.debug("[DeviceController] Devices enumerated:", {
|
|
10969
10982
|
audioInputs: devicesByKind.audioinput.length,
|
|
10970
10983
|
audioOutputs: devicesByKind.audiooutput.length,
|
|
10971
10984
|
videoInputs: devicesByKind.videoinput.length
|
|
10972
10985
|
});
|
|
10973
10986
|
} catch (error) {
|
|
10974
|
-
logger$
|
|
10987
|
+
logger$27.error("[DeviceController] Failed to enumerate devices:", error);
|
|
10975
10988
|
this._errors$.next(error);
|
|
10976
10989
|
}
|
|
10977
10990
|
}
|
|
@@ -10987,7 +11000,7 @@ var NavigatorDeviceController = class extends Destroyable {
|
|
|
10987
11000
|
stream.getTracks().forEach((t) => t.stop());
|
|
10988
11001
|
return capabilities;
|
|
10989
11002
|
} catch (error) {
|
|
10990
|
-
logger$
|
|
11003
|
+
logger$27.error("[DeviceController] Failed to get device capabilities:", error);
|
|
10991
11004
|
this._errors$.next(error);
|
|
10992
11005
|
throw error;
|
|
10993
11006
|
}
|
|
@@ -11238,7 +11251,7 @@ var DependencyContainer = class {
|
|
|
11238
11251
|
|
|
11239
11252
|
//#endregion
|
|
11240
11253
|
//#region src/controllers/CryptoController.ts
|
|
11241
|
-
const logger$
|
|
11254
|
+
const logger$26 = getLogger();
|
|
11242
11255
|
const DPOP_DB_NAME = "sw-dpop";
|
|
11243
11256
|
const DPOP_DB_VERSION = 1;
|
|
11244
11257
|
const DPOP_STORE_NAME = "keys";
|
|
@@ -11297,7 +11310,7 @@ async function loadKeyPairFromDB() {
|
|
|
11297
11310
|
tx.oncomplete = () => db.close();
|
|
11298
11311
|
});
|
|
11299
11312
|
} catch (error) {
|
|
11300
|
-
logger$
|
|
11313
|
+
logger$26.warn("[DPoP] Failed to load key pair from IndexedDB:", error);
|
|
11301
11314
|
return null;
|
|
11302
11315
|
}
|
|
11303
11316
|
}
|
|
@@ -11317,7 +11330,7 @@ async function saveKeyPairToDB(keyPair) {
|
|
|
11317
11330
|
};
|
|
11318
11331
|
});
|
|
11319
11332
|
} catch (error) {
|
|
11320
|
-
logger$
|
|
11333
|
+
logger$26.warn("[DPoP] Failed to save key pair to IndexedDB:", error);
|
|
11321
11334
|
}
|
|
11322
11335
|
}
|
|
11323
11336
|
async function deleteKeyPairFromDB() {
|
|
@@ -11336,7 +11349,7 @@ async function deleteKeyPairFromDB() {
|
|
|
11336
11349
|
};
|
|
11337
11350
|
});
|
|
11338
11351
|
} catch (error) {
|
|
11339
|
-
logger$
|
|
11352
|
+
logger$26.warn("[DPoP] Failed to delete key pair from IndexedDB:", error);
|
|
11340
11353
|
}
|
|
11341
11354
|
}
|
|
11342
11355
|
/**
|
|
@@ -11396,13 +11409,13 @@ var CryptoController = class {
|
|
|
11396
11409
|
this._publicJwk = await crypto.subtle.exportKey("jwk", stored.publicKey);
|
|
11397
11410
|
this._fingerprint = await computeJwkThumbprint(this._publicJwk);
|
|
11398
11411
|
this._initialized = true;
|
|
11399
|
-
logger$
|
|
11412
|
+
logger$26.debug("[DPoP] Key pair restored from IndexedDB, fingerprint:", this._fingerprint);
|
|
11400
11413
|
return this._fingerprint;
|
|
11401
11414
|
} catch (error) {
|
|
11402
|
-
logger$
|
|
11415
|
+
logger$26.warn("[DPoP] Stored key pair unusable, generating new one:", error);
|
|
11403
11416
|
await deleteKeyPairFromDB();
|
|
11404
11417
|
}
|
|
11405
|
-
logger$
|
|
11418
|
+
logger$26.debug("[DPoP] Generating RSA key pair");
|
|
11406
11419
|
this._keyPair = await crypto.subtle.generateKey({
|
|
11407
11420
|
name: "RSASSA-PKCS1-v1_5",
|
|
11408
11421
|
modulusLength: 2048,
|
|
@@ -11417,7 +11430,7 @@ var CryptoController = class {
|
|
|
11417
11430
|
this._fingerprint = await computeJwkThumbprint(this._publicJwk);
|
|
11418
11431
|
this._initialized = true;
|
|
11419
11432
|
await saveKeyPairToDB(this._keyPair);
|
|
11420
|
-
logger$
|
|
11433
|
+
logger$26.debug("[DPoP] Key pair generated and persisted, fingerprint:", this._fingerprint);
|
|
11421
11434
|
return this._fingerprint;
|
|
11422
11435
|
}
|
|
11423
11436
|
/**
|
|
@@ -11483,7 +11496,7 @@ var CryptoController = class {
|
|
|
11483
11496
|
this._fingerprint = null;
|
|
11484
11497
|
this._initialized = false;
|
|
11485
11498
|
deleteKeyPairFromDB();
|
|
11486
|
-
logger$
|
|
11499
|
+
logger$26.debug("[DPoP] Controller destroyed");
|
|
11487
11500
|
}
|
|
11488
11501
|
get publicJwk() {
|
|
11489
11502
|
if (!this._publicJwk) throw new DPoPInitError("CryptoController not initialized. Call init() first.");
|
|
@@ -11506,8 +11519,8 @@ var CryptoController = class {
|
|
|
11506
11519
|
|
|
11507
11520
|
//#endregion
|
|
11508
11521
|
//#region src/controllers/NetworkMonitor.ts
|
|
11509
|
-
var import_cjs$
|
|
11510
|
-
const logger$
|
|
11522
|
+
var import_cjs$25 = require_cjs();
|
|
11523
|
+
const logger$25 = getLogger();
|
|
11511
11524
|
/**
|
|
11512
11525
|
* Safely check whether we are running in a browser environment
|
|
11513
11526
|
* with `window` and the relevant event targets.
|
|
@@ -11550,13 +11563,13 @@ var NetworkMonitor = class extends Destroyable {
|
|
|
11550
11563
|
this.attachListeners();
|
|
11551
11564
|
}
|
|
11552
11565
|
get isOnline$() {
|
|
11553
|
-
return this._isOnline$.asObservable().pipe((0, import_cjs$
|
|
11566
|
+
return this._isOnline$.asObservable().pipe((0, import_cjs$25.takeUntil)(this._destroyed$));
|
|
11554
11567
|
}
|
|
11555
11568
|
get isOnline() {
|
|
11556
11569
|
return this._isOnline$.value;
|
|
11557
11570
|
}
|
|
11558
11571
|
get networkChange$() {
|
|
11559
|
-
return this._networkChange$.asObservable().pipe((0, import_cjs$
|
|
11572
|
+
return this._networkChange$.asObservable().pipe((0, import_cjs$25.takeUntil)(this._destroyed$));
|
|
11560
11573
|
}
|
|
11561
11574
|
destroy() {
|
|
11562
11575
|
this.removeListeners();
|
|
@@ -11564,7 +11577,7 @@ var NetworkMonitor = class extends Destroyable {
|
|
|
11564
11577
|
}
|
|
11565
11578
|
attachListeners() {
|
|
11566
11579
|
if (!hasBrowserNetworkEvents()) {
|
|
11567
|
-
logger$
|
|
11580
|
+
logger$25.debug("NetworkMonitor: no browser environment detected, skipping event listeners");
|
|
11568
11581
|
return;
|
|
11569
11582
|
}
|
|
11570
11583
|
window.addEventListener("online", this._onOnline);
|
|
@@ -11572,7 +11585,7 @@ var NetworkMonitor = class extends Destroyable {
|
|
|
11572
11585
|
const connection = getNetworkConnection();
|
|
11573
11586
|
if (connection) connection.addEventListener("change", this._onConnectionChange);
|
|
11574
11587
|
this._listenersAttached = true;
|
|
11575
|
-
logger$
|
|
11588
|
+
logger$25.debug("NetworkMonitor: event listeners attached");
|
|
11576
11589
|
}
|
|
11577
11590
|
removeListeners() {
|
|
11578
11591
|
if (!this._listenersAttached) return;
|
|
@@ -11583,10 +11596,10 @@ var NetworkMonitor = class extends Destroyable {
|
|
|
11583
11596
|
if (connection) connection.removeEventListener("change", this._onConnectionChange);
|
|
11584
11597
|
}
|
|
11585
11598
|
this._listenersAttached = false;
|
|
11586
|
-
logger$
|
|
11599
|
+
logger$25.debug("NetworkMonitor: event listeners removed");
|
|
11587
11600
|
}
|
|
11588
11601
|
handleOnline() {
|
|
11589
|
-
logger$
|
|
11602
|
+
logger$25.info("NetworkMonitor: browser went online");
|
|
11590
11603
|
this._isOnline$.next(true);
|
|
11591
11604
|
this._networkChange$.next({
|
|
11592
11605
|
type: "online",
|
|
@@ -11595,7 +11608,7 @@ var NetworkMonitor = class extends Destroyable {
|
|
|
11595
11608
|
});
|
|
11596
11609
|
}
|
|
11597
11610
|
handleOffline() {
|
|
11598
|
-
logger$
|
|
11611
|
+
logger$25.info("NetworkMonitor: browser went offline");
|
|
11599
11612
|
this._isOnline$.next(false);
|
|
11600
11613
|
this._networkChange$.next({
|
|
11601
11614
|
type: "offline",
|
|
@@ -11604,7 +11617,7 @@ var NetworkMonitor = class extends Destroyable {
|
|
|
11604
11617
|
}
|
|
11605
11618
|
handleConnectionChange() {
|
|
11606
11619
|
const networkType = getNetworkType();
|
|
11607
|
-
logger$
|
|
11620
|
+
logger$25.info(`NetworkMonitor: connection changed — effectiveType=${networkType ?? "unknown"}`);
|
|
11608
11621
|
this._networkChange$.next({
|
|
11609
11622
|
type: "connection_change",
|
|
11610
11623
|
timestamp: Date.now(),
|
|
@@ -11719,8 +11732,8 @@ function getNavigatorMediaDevices() {
|
|
|
11719
11732
|
|
|
11720
11733
|
//#endregion
|
|
11721
11734
|
//#region src/controllers/PreflightRunner.ts
|
|
11722
|
-
var import_cjs$
|
|
11723
|
-
const logger$
|
|
11735
|
+
var import_cjs$24 = require_cjs();
|
|
11736
|
+
const logger$24 = getLogger();
|
|
11724
11737
|
const DEFAULT_MEDIA_TEST_DURATION_S = 10;
|
|
11725
11738
|
const ICE_GATHERING_TIMEOUT_MS = 1e4;
|
|
11726
11739
|
const SIGNALING_RTT_TIMEOUT_MS = 5e3;
|
|
@@ -11769,7 +11782,7 @@ var PreflightRunner = class extends Destroyable {
|
|
|
11769
11782
|
if (!this._options.skipMediaTest) try {
|
|
11770
11783
|
bandwidth = await this.testMediaBandwidth(destination);
|
|
11771
11784
|
} catch (error) {
|
|
11772
|
-
logger$
|
|
11785
|
+
logger$24.warn("[PreflightRunner] Media bandwidth test failed:", error);
|
|
11773
11786
|
warnings.push("Media bandwidth test failed");
|
|
11774
11787
|
}
|
|
11775
11788
|
return {
|
|
@@ -11781,7 +11794,7 @@ var PreflightRunner = class extends Destroyable {
|
|
|
11781
11794
|
warnings
|
|
11782
11795
|
};
|
|
11783
11796
|
} catch (error) {
|
|
11784
|
-
logger$
|
|
11797
|
+
logger$24.error("[PreflightRunner] Preflight test failed:", error);
|
|
11785
11798
|
throw new PreflightError("preflight", error instanceof Error ? error : new Error(String(error)));
|
|
11786
11799
|
} finally {
|
|
11787
11800
|
this.destroy();
|
|
@@ -11812,7 +11825,7 @@ var PreflightRunner = class extends Destroyable {
|
|
|
11812
11825
|
if (track.kind === "video" && track.readyState === "live") videoWorking = true;
|
|
11813
11826
|
}
|
|
11814
11827
|
} catch (error) {
|
|
11815
|
-
logger$
|
|
11828
|
+
logger$24.warn("[PreflightRunner] Device test failed:", error);
|
|
11816
11829
|
} finally {
|
|
11817
11830
|
if (audioStream) audioStream.getTracks().forEach((t) => t.stop());
|
|
11818
11831
|
}
|
|
@@ -11835,18 +11848,19 @@ var PreflightRunner = class extends Destroyable {
|
|
|
11835
11848
|
let pc;
|
|
11836
11849
|
try {
|
|
11837
11850
|
pc = new RTCPeerConnection({ iceServers: this.iceServers });
|
|
11851
|
+
const peerConnection = pc;
|
|
11838
11852
|
const candidateTypes = /* @__PURE__ */ new Set();
|
|
11839
11853
|
const startTime = Date.now();
|
|
11840
11854
|
const gatheringComplete = new Promise((resolve) => {
|
|
11841
|
-
const timer$
|
|
11842
|
-
|
|
11855
|
+
const timer$3 = setTimeout(resolve, ICE_GATHERING_TIMEOUT_MS);
|
|
11856
|
+
peerConnection.onicecandidate = (event) => {
|
|
11843
11857
|
if (event.candidate) {
|
|
11844
11858
|
const candidateStr = event.candidate.candidate;
|
|
11845
11859
|
if (candidateStr.includes("typ host")) candidateTypes.add("host");
|
|
11846
11860
|
if (candidateStr.includes("typ srflx")) candidateTypes.add("srflx");
|
|
11847
11861
|
if (candidateStr.includes("typ relay")) candidateTypes.add("relay");
|
|
11848
11862
|
} else {
|
|
11849
|
-
clearTimeout(timer$
|
|
11863
|
+
clearTimeout(timer$3);
|
|
11850
11864
|
resolve();
|
|
11851
11865
|
}
|
|
11852
11866
|
};
|
|
@@ -11869,7 +11883,7 @@ var PreflightRunner = class extends Destroyable {
|
|
|
11869
11883
|
rttMs
|
|
11870
11884
|
};
|
|
11871
11885
|
} catch (error) {
|
|
11872
|
-
logger$
|
|
11886
|
+
logger$24.warn("[PreflightRunner] ICE connectivity test failed:", error);
|
|
11873
11887
|
return {
|
|
11874
11888
|
type: "failed",
|
|
11875
11889
|
turnReachable: false,
|
|
@@ -11887,7 +11901,7 @@ var PreflightRunner = class extends Destroyable {
|
|
|
11887
11901
|
audio: true,
|
|
11888
11902
|
video: false
|
|
11889
11903
|
});
|
|
11890
|
-
await (0, import_cjs$
|
|
11904
|
+
await (0, import_cjs$24.firstValueFrom)(call.status$.pipe((0, import_cjs$24.filter)((s) => s === "connected"), (0, import_cjs$24.take)(1), (0, import_cjs$24.timeout)(SIGNALING_RTT_TIMEOUT_MS)));
|
|
11891
11905
|
const durationMs = this._options.duration * 1e3;
|
|
11892
11906
|
await new Promise((resolve) => setTimeout(resolve, durationMs));
|
|
11893
11907
|
const metrics = call.networkMetrics;
|
|
@@ -11916,8 +11930,8 @@ var PreflightRunner = class extends Destroyable {
|
|
|
11916
11930
|
|
|
11917
11931
|
//#endregion
|
|
11918
11932
|
//#region src/controllers/VisibilityController.ts
|
|
11919
|
-
var import_cjs$
|
|
11920
|
-
const logger$
|
|
11933
|
+
var import_cjs$23 = require_cjs();
|
|
11934
|
+
const logger$23 = getLogger();
|
|
11921
11935
|
/**
|
|
11922
11936
|
* Checks whether the document visibility API is available.
|
|
11923
11937
|
*/
|
|
@@ -11954,15 +11968,15 @@ var VisibilityController = class extends Destroyable {
|
|
|
11954
11968
|
this._boundHandler = this._handleVisibilityChange.bind(this);
|
|
11955
11969
|
if (this._hasVisibilityApi) {
|
|
11956
11970
|
document.addEventListener("visibilitychange", this._boundHandler);
|
|
11957
|
-
logger$
|
|
11958
|
-
} else logger$
|
|
11971
|
+
logger$23.debug("VisibilityController: listening for visibilitychange events");
|
|
11972
|
+
} else logger$23.debug("VisibilityController: document visibility API not available, defaulting to visible");
|
|
11959
11973
|
}
|
|
11960
11974
|
/**
|
|
11961
11975
|
* Observable of the current visibility state.
|
|
11962
11976
|
* Emits 'visible' or 'hidden'. Always starts with the current state.
|
|
11963
11977
|
*/
|
|
11964
11978
|
get visibility$() {
|
|
11965
|
-
return this._visibility$.pipe((0, import_cjs$
|
|
11979
|
+
return this._visibility$.pipe((0, import_cjs$23.takeUntil)(this._destroyed$));
|
|
11966
11980
|
}
|
|
11967
11981
|
/**
|
|
11968
11982
|
* The current visibility state value.
|
|
@@ -11975,12 +11989,12 @@ var VisibilityController = class extends Destroyable {
|
|
|
11975
11989
|
* Each event includes the previous state, new state, and timestamp.
|
|
11976
11990
|
*/
|
|
11977
11991
|
get visibilityChange$() {
|
|
11978
|
-
return this._visibilityChange$.pipe((0, import_cjs$
|
|
11992
|
+
return this._visibilityChange$.pipe((0, import_cjs$23.takeUntil)(this._destroyed$));
|
|
11979
11993
|
}
|
|
11980
11994
|
destroy() {
|
|
11981
11995
|
if (this._hasVisibilityApi) {
|
|
11982
11996
|
document.removeEventListener("visibilitychange", this._boundHandler);
|
|
11983
|
-
logger$
|
|
11997
|
+
logger$23.debug("VisibilityController: removed visibilitychange listener");
|
|
11984
11998
|
}
|
|
11985
11999
|
super.destroy();
|
|
11986
12000
|
}
|
|
@@ -11998,7 +12012,7 @@ var VisibilityController = class extends Destroyable {
|
|
|
11998
12012
|
timestamp: Date.now()
|
|
11999
12013
|
};
|
|
12000
12014
|
this._visibilityChange$.next(changeEvent);
|
|
12001
|
-
logger$
|
|
12015
|
+
logger$23.debug("VisibilityController: visibility changed", {
|
|
12002
12016
|
from: previousState,
|
|
12003
12017
|
to: newState
|
|
12004
12018
|
});
|
|
@@ -12007,13 +12021,13 @@ var VisibilityController = class extends Destroyable {
|
|
|
12007
12021
|
|
|
12008
12022
|
//#endregion
|
|
12009
12023
|
//#region src/behaviors/Fetchable.ts
|
|
12010
|
-
var import_cjs$
|
|
12024
|
+
var import_cjs$22 = require_cjs();
|
|
12011
12025
|
var Fetchable = class extends Destroyable {
|
|
12012
12026
|
constructor(fromPath, http) {
|
|
12013
12027
|
super();
|
|
12014
12028
|
this.fromPath = fromPath;
|
|
12015
12029
|
this.http = http;
|
|
12016
|
-
this.fetched$ = (0, import_cjs$
|
|
12030
|
+
this.fetched$ = (0, import_cjs$22.defer)(() => (0, import_cjs$22.from)(this.fetch())).pipe((0, import_cjs$22.shareReplay)(1), (0, import_cjs$22.takeUntil)(this.destroyed$));
|
|
12017
12031
|
}
|
|
12018
12032
|
async fetch() {
|
|
12019
12033
|
const response = await this.http.request({
|
|
@@ -12248,7 +12262,7 @@ const RPCEventAckResponse = (id) => makeRPCResponse({
|
|
|
12248
12262
|
|
|
12249
12263
|
//#endregion
|
|
12250
12264
|
//#region src/managers/AttachManager.ts
|
|
12251
|
-
const logger$
|
|
12265
|
+
const logger$22 = getLogger();
|
|
12252
12266
|
var AttachManager = class {
|
|
12253
12267
|
constructor(storage, deviceController, reconnectCallsTimeout, attachKey) {
|
|
12254
12268
|
this.storage = storage;
|
|
@@ -12260,6 +12274,7 @@ var AttachManager = class {
|
|
|
12260
12274
|
const attached = await this.readAttached();
|
|
12261
12275
|
for (const callId of Object.keys(attached)) await this.detach({
|
|
12262
12276
|
id: callId,
|
|
12277
|
+
nodeId: attached[callId].nodeId,
|
|
12263
12278
|
mediaDirections: attached[callId].mediaDirections
|
|
12264
12279
|
});
|
|
12265
12280
|
}
|
|
@@ -12270,7 +12285,7 @@ var AttachManager = class {
|
|
|
12270
12285
|
try {
|
|
12271
12286
|
return await this.storage.getItem(this.attachKey) ?? {};
|
|
12272
12287
|
} catch (error) {
|
|
12273
|
-
logger$
|
|
12288
|
+
logger$22.warn("[AttachManager] Failed to retrieve attached calls from storage", error);
|
|
12274
12289
|
return {};
|
|
12275
12290
|
}
|
|
12276
12291
|
}
|
|
@@ -12278,20 +12293,20 @@ var AttachManager = class {
|
|
|
12278
12293
|
try {
|
|
12279
12294
|
await this.storage.setItem(this.attachKey, attached);
|
|
12280
12295
|
} catch (error) {
|
|
12281
|
-
logger$
|
|
12296
|
+
logger$22.warn("[AttachManager] Failed to write attached calls to storage", error);
|
|
12282
12297
|
}
|
|
12283
12298
|
}
|
|
12284
12299
|
async attach(call) {
|
|
12285
12300
|
if (!call.to) {
|
|
12286
|
-
logger$
|
|
12301
|
+
logger$22.warn("[AttachManager] Skip attach for calls with no destination");
|
|
12287
12302
|
return;
|
|
12288
12303
|
}
|
|
12289
12304
|
const attachment = {
|
|
12305
|
+
nodeId: call.nodeId,
|
|
12290
12306
|
destination: call.to,
|
|
12291
12307
|
mediaDirections: call.mediaDirections,
|
|
12292
12308
|
audioInputDevice: call.mediaDirections.audio !== "inactive" ? this.deviceController.selectedAudioInputDevice : null,
|
|
12293
12309
|
videoInputDevice: call.mediaDirections.video !== "inactive" ? this.deviceController.selectedVideoInputDevice : null,
|
|
12294
|
-
nodeId: call.nodeId,
|
|
12295
12310
|
attachedAt: Date.now()
|
|
12296
12311
|
};
|
|
12297
12312
|
const updated = {
|
|
@@ -12334,15 +12349,15 @@ var AttachManager = class {
|
|
|
12334
12349
|
callId,
|
|
12335
12350
|
...options
|
|
12336
12351
|
});
|
|
12337
|
-
logger$
|
|
12352
|
+
logger$22.info(`[AttachManager] Reattached call ${callId} (attempt ${attempt})`);
|
|
12338
12353
|
succeeded = true;
|
|
12339
12354
|
break;
|
|
12340
12355
|
} catch (error) {
|
|
12341
|
-
logger$
|
|
12356
|
+
logger$22.warn(`[AttachManager] Reattach attempt ${attempt}/3 failed for call ${callId}:`, error);
|
|
12342
12357
|
if (attempt < 3) await new Promise((r) => setTimeout(r, (attempt + 1) * 1e3));
|
|
12343
12358
|
}
|
|
12344
12359
|
if (!succeeded) {
|
|
12345
|
-
logger$
|
|
12360
|
+
logger$22.warn(`[AttachManager] Reattach failed after 3 attempts for call ${callId}, removing reference`);
|
|
12346
12361
|
await this.detach({
|
|
12347
12362
|
id: callId,
|
|
12348
12363
|
mediaDirections: attachment.mediaDirections
|
|
@@ -12356,12 +12371,13 @@ var AttachManager = class {
|
|
|
12356
12371
|
*/
|
|
12357
12372
|
buildCallOptions(attachment) {
|
|
12358
12373
|
const { audio: audioDirection, video: videoDirection } = attachment.mediaDirections;
|
|
12359
|
-
const { audioInputDevice, videoInputDevice } = attachment;
|
|
12374
|
+
const { audioInputDevice, videoInputDevice, nodeId } = attachment;
|
|
12360
12375
|
const receiveAudio = audioDirection.includes("recv");
|
|
12361
12376
|
const receiveVideo = videoDirection.includes("recv");
|
|
12362
12377
|
const sendAudio = audioDirection.includes("send");
|
|
12363
12378
|
const sendVideo = videoDirection.includes("send");
|
|
12364
12379
|
return {
|
|
12380
|
+
nodeId,
|
|
12365
12381
|
receiveAudio,
|
|
12366
12382
|
receiveVideo,
|
|
12367
12383
|
inputAudioDeviceConstraints: sendAudio ? {
|
|
@@ -12372,7 +12388,6 @@ var AttachManager = class {
|
|
|
12372
12388
|
video: true,
|
|
12373
12389
|
...this.deviceController.deviceInfoToConstraints(videoInputDevice)
|
|
12374
12390
|
} : void 0,
|
|
12375
|
-
nodeId: attachment.nodeId ?? void 0,
|
|
12376
12391
|
reattach: true
|
|
12377
12392
|
};
|
|
12378
12393
|
}
|
|
@@ -13248,7 +13263,7 @@ var require_operators = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
13248
13263
|
//#endregion
|
|
13249
13264
|
//#region src/operators/filterNull.ts
|
|
13250
13265
|
var import_operators$1 = require_operators();
|
|
13251
|
-
var import_cjs$
|
|
13266
|
+
var import_cjs$21 = require_cjs();
|
|
13252
13267
|
/**
|
|
13253
13268
|
* RxJS operator that filters out `null` and `undefined` values with type narrowing.
|
|
13254
13269
|
*
|
|
@@ -13260,7 +13275,7 @@ var import_cjs$20 = require_cjs();
|
|
|
13260
13275
|
* ```
|
|
13261
13276
|
*/
|
|
13262
13277
|
function filterNull() {
|
|
13263
|
-
return (0, import_cjs$
|
|
13278
|
+
return (0, import_cjs$21.filter)((value) => value != null);
|
|
13264
13279
|
}
|
|
13265
13280
|
|
|
13266
13281
|
//#endregion
|
|
@@ -13388,7 +13403,7 @@ function computeCapabilities(capabilities) {
|
|
|
13388
13403
|
|
|
13389
13404
|
//#endregion
|
|
13390
13405
|
//#region src/core/capabilities/SelfCapabilities.ts
|
|
13391
|
-
var import_cjs$
|
|
13406
|
+
var import_cjs$20 = require_cjs();
|
|
13392
13407
|
/**
|
|
13393
13408
|
* SelfCapabilities manages the capability state for the self participant.
|
|
13394
13409
|
*
|
|
@@ -13424,7 +13439,7 @@ var SelfCapabilities = class extends Destroyable {
|
|
|
13424
13439
|
}
|
|
13425
13440
|
/** Observable for self member capabilities */
|
|
13426
13441
|
get self$() {
|
|
13427
|
-
return this.cachedObservable("self$", () => this._state$.pipe((0, import_cjs$
|
|
13442
|
+
return this.cachedObservable("self$", () => this._state$.pipe((0, import_cjs$20.map)((state) => state.self), (0, import_cjs$20.distinctUntilChanged)()));
|
|
13428
13443
|
}
|
|
13429
13444
|
/** Current self member capabilities */
|
|
13430
13445
|
get self() {
|
|
@@ -13432,7 +13447,7 @@ var SelfCapabilities = class extends Destroyable {
|
|
|
13432
13447
|
}
|
|
13433
13448
|
/** Observable for other member capabilities */
|
|
13434
13449
|
get member$() {
|
|
13435
|
-
return this.cachedObservable("member$", () => this._state$.pipe((0, import_cjs$
|
|
13450
|
+
return this.cachedObservable("member$", () => this._state$.pipe((0, import_cjs$20.map)((state) => state.member), (0, import_cjs$20.distinctUntilChanged)()));
|
|
13436
13451
|
}
|
|
13437
13452
|
/** Current other member capabilities */
|
|
13438
13453
|
get member() {
|
|
@@ -13440,7 +13455,7 @@ var SelfCapabilities = class extends Destroyable {
|
|
|
13440
13455
|
}
|
|
13441
13456
|
/** Observable for end call capability */
|
|
13442
13457
|
get end$() {
|
|
13443
|
-
return this.cachedObservable("end$", () => this._state$.pipe((0, import_cjs$
|
|
13458
|
+
return this.cachedObservable("end$", () => this._state$.pipe((0, import_cjs$20.map)((state) => state.end), (0, import_cjs$20.distinctUntilChanged)()));
|
|
13444
13459
|
}
|
|
13445
13460
|
/** Current end call capability */
|
|
13446
13461
|
get end() {
|
|
@@ -13448,7 +13463,7 @@ var SelfCapabilities = class extends Destroyable {
|
|
|
13448
13463
|
}
|
|
13449
13464
|
/** Observable for set layout capability */
|
|
13450
13465
|
get setLayout$() {
|
|
13451
|
-
return this.cachedObservable("setLayout$", () => this._state$.pipe((0, import_cjs$
|
|
13466
|
+
return this.cachedObservable("setLayout$", () => this._state$.pipe((0, import_cjs$20.map)((state) => state.setLayout), (0, import_cjs$20.distinctUntilChanged)()));
|
|
13452
13467
|
}
|
|
13453
13468
|
/** Current set layout capability */
|
|
13454
13469
|
get setLayout() {
|
|
@@ -13456,7 +13471,7 @@ var SelfCapabilities = class extends Destroyable {
|
|
|
13456
13471
|
}
|
|
13457
13472
|
/** Observable for send digit capability */
|
|
13458
13473
|
get sendDigit$() {
|
|
13459
|
-
return this.cachedObservable("sendDigit$", () => this._state$.pipe((0, import_cjs$
|
|
13474
|
+
return this.cachedObservable("sendDigit$", () => this._state$.pipe((0, import_cjs$20.map)((state) => state.sendDigit), (0, import_cjs$20.distinctUntilChanged)()));
|
|
13460
13475
|
}
|
|
13461
13476
|
/** Current send digit capability */
|
|
13462
13477
|
get sendDigit() {
|
|
@@ -13464,7 +13479,7 @@ var SelfCapabilities = class extends Destroyable {
|
|
|
13464
13479
|
}
|
|
13465
13480
|
/** Observable for vmuted hide capability */
|
|
13466
13481
|
get vmutedHide$() {
|
|
13467
|
-
return this.cachedObservable("vmutedHide$", () => this._state$.pipe((0, import_cjs$
|
|
13482
|
+
return this.cachedObservable("vmutedHide$", () => this._state$.pipe((0, import_cjs$20.map)((state) => state.vmutedHide), (0, import_cjs$20.distinctUntilChanged)()));
|
|
13468
13483
|
}
|
|
13469
13484
|
/** Current vmuted hide capability */
|
|
13470
13485
|
get vmutedHide() {
|
|
@@ -13472,7 +13487,7 @@ var SelfCapabilities = class extends Destroyable {
|
|
|
13472
13487
|
}
|
|
13473
13488
|
/** Observable for lock capability */
|
|
13474
13489
|
get lock$() {
|
|
13475
|
-
return this.cachedObservable("lock$", () => this._state$.pipe((0, import_cjs$
|
|
13490
|
+
return this.cachedObservable("lock$", () => this._state$.pipe((0, import_cjs$20.map)((state) => state.lock), (0, import_cjs$20.distinctUntilChanged)()));
|
|
13476
13491
|
}
|
|
13477
13492
|
/** Current lock capability */
|
|
13478
13493
|
get lock() {
|
|
@@ -13480,7 +13495,7 @@ var SelfCapabilities = class extends Destroyable {
|
|
|
13480
13495
|
}
|
|
13481
13496
|
/** Observable for device capability */
|
|
13482
13497
|
get device$() {
|
|
13483
|
-
return this.cachedObservable("device$", () => this._state$.pipe((0, import_cjs$
|
|
13498
|
+
return this.cachedObservable("device$", () => this._state$.pipe((0, import_cjs$20.map)((state) => state.device), (0, import_cjs$20.distinctUntilChanged)()));
|
|
13484
13499
|
}
|
|
13485
13500
|
/** Current device capability */
|
|
13486
13501
|
get device() {
|
|
@@ -13488,7 +13503,7 @@ var SelfCapabilities = class extends Destroyable {
|
|
|
13488
13503
|
}
|
|
13489
13504
|
/** Observable for screenshare capability */
|
|
13490
13505
|
get screenshare$() {
|
|
13491
|
-
return this.cachedObservable("screenshare$", () => this._state$.pipe((0, import_cjs$
|
|
13506
|
+
return this.cachedObservable("screenshare$", () => this._state$.pipe((0, import_cjs$20.map)((state) => state.screenshare), (0, import_cjs$20.distinctUntilChanged)()));
|
|
13492
13507
|
}
|
|
13493
13508
|
/** Current screenshare capability */
|
|
13494
13509
|
get screenshare() {
|
|
@@ -13515,7 +13530,7 @@ function toggleHandraiseMethod(is) {
|
|
|
13515
13530
|
|
|
13516
13531
|
//#endregion
|
|
13517
13532
|
//#region src/core/entities/Participant.ts
|
|
13518
|
-
const logger$
|
|
13533
|
+
const logger$21 = getLogger();
|
|
13519
13534
|
const initialState = {};
|
|
13520
13535
|
/**
|
|
13521
13536
|
* Represents a participant in a call.
|
|
@@ -13893,7 +13908,7 @@ var SelfParticipant = class extends Participant {
|
|
|
13893
13908
|
try {
|
|
13894
13909
|
await this.vertoManager.addScreenMedia();
|
|
13895
13910
|
} catch (error) {
|
|
13896
|
-
logger$
|
|
13911
|
+
logger$21.error("[Participant.startScreenShare] Screen share error:", error);
|
|
13897
13912
|
}
|
|
13898
13913
|
}
|
|
13899
13914
|
/** Observable of the current screen share status. */
|
|
@@ -13913,7 +13928,7 @@ var SelfParticipant = class extends Participant {
|
|
|
13913
13928
|
try {
|
|
13914
13929
|
await this.vertoManager.addInputDevice(options);
|
|
13915
13930
|
} catch (error) {
|
|
13916
|
-
logger$
|
|
13931
|
+
logger$21.error("[Participant.startScreenShare] Screen share error:", error);
|
|
13917
13932
|
}
|
|
13918
13933
|
}
|
|
13919
13934
|
/** Removes an additional media input device by ID. */
|
|
@@ -13975,7 +13990,7 @@ var SelfParticipant = class extends Participant {
|
|
|
13975
13990
|
*/
|
|
13976
13991
|
exitStudioModeIfActive() {
|
|
13977
13992
|
if (this._studioAudio$.value) {
|
|
13978
|
-
logger$
|
|
13993
|
+
logger$21.debug("[SelfParticipant] Exiting studio audio mode due to individual flag toggle");
|
|
13979
13994
|
this._studioAudio$.next(false);
|
|
13980
13995
|
}
|
|
13981
13996
|
}
|
|
@@ -13999,7 +14014,7 @@ var SelfParticipant = class extends Participant {
|
|
|
13999
14014
|
try {
|
|
14000
14015
|
await super.mute();
|
|
14001
14016
|
} catch (error) {
|
|
14002
|
-
logger$
|
|
14017
|
+
logger$21.warn("[Participant.toggleAudioInput] Server Error while muting audio input, proceeding with local toggle anyway", error);
|
|
14003
14018
|
} finally {
|
|
14004
14019
|
this.vertoManager.muteMainAudioInputDevice();
|
|
14005
14020
|
}
|
|
@@ -14009,7 +14024,7 @@ var SelfParticipant = class extends Participant {
|
|
|
14009
14024
|
try {
|
|
14010
14025
|
await super.unmute();
|
|
14011
14026
|
} catch (error) {
|
|
14012
|
-
logger$
|
|
14027
|
+
logger$21.warn("[Participant.toggleAudioInput] Server Error while unmuting audio input, proceeding with local toggle anyway", error);
|
|
14013
14028
|
} finally {
|
|
14014
14029
|
await this.vertoManager.unmuteMainAudioInputDevice();
|
|
14015
14030
|
}
|
|
@@ -14019,7 +14034,7 @@ var SelfParticipant = class extends Participant {
|
|
|
14019
14034
|
try {
|
|
14020
14035
|
await super.muteVideo();
|
|
14021
14036
|
} catch (error) {
|
|
14022
|
-
logger$
|
|
14037
|
+
logger$21.warn("[Participant.toggleVideoInput] Server Error while muting video input, proceeding with local toggle anyway", error);
|
|
14023
14038
|
} finally {
|
|
14024
14039
|
this.vertoManager.muteMainVideoInputDevice();
|
|
14025
14040
|
}
|
|
@@ -14029,7 +14044,7 @@ var SelfParticipant = class extends Participant {
|
|
|
14029
14044
|
try {
|
|
14030
14045
|
await super.unmuteVideo();
|
|
14031
14046
|
} catch (error) {
|
|
14032
|
-
logger$
|
|
14047
|
+
logger$21.warn("[Participant.toggleVideoInput] Server Error while unmuting video input, proceeding with local toggle anyway", error);
|
|
14033
14048
|
} finally {
|
|
14034
14049
|
await this.vertoManager.unmuteMainVideoInputDevice();
|
|
14035
14050
|
}
|
|
@@ -14133,7 +14148,7 @@ const getValueFrom = (obj, path, defaultValue) => {
|
|
|
14133
14148
|
|
|
14134
14149
|
//#endregion
|
|
14135
14150
|
//#region src/operators/filterEventAs.ts
|
|
14136
|
-
var import_cjs$
|
|
14151
|
+
var import_cjs$19 = require_cjs();
|
|
14137
14152
|
var import_operators = require_operators();
|
|
14138
14153
|
/**
|
|
14139
14154
|
* RxJS operator that filters events based on a predicate and maps matching events.
|
|
@@ -14167,7 +14182,7 @@ var import_operators = require_operators();
|
|
|
14167
14182
|
* ```
|
|
14168
14183
|
*/
|
|
14169
14184
|
function ifIsMap(predicate, mapFn) {
|
|
14170
|
-
return (0, import_cjs$
|
|
14185
|
+
return (0, import_cjs$19.pipe)((0, import_operators.filter)(predicate), (0, import_operators.map)(mapFn));
|
|
14171
14186
|
}
|
|
14172
14187
|
/**
|
|
14173
14188
|
* Generic RxJS operator that filters events using a type guard and extracts a property.
|
|
@@ -14209,38 +14224,38 @@ function ifIsMap(predicate, mapFn) {
|
|
|
14209
14224
|
* ```
|
|
14210
14225
|
*/
|
|
14211
14226
|
function filterAs(predicate, resultPath) {
|
|
14212
|
-
return (0, import_cjs$
|
|
14227
|
+
return (0, import_cjs$19.pipe)(ifIsMap(predicate, (event) => {
|
|
14213
14228
|
return getValueFrom(event, resultPath);
|
|
14214
14229
|
}), (0, import_operators.filter)((value) => value !== void 0));
|
|
14215
14230
|
}
|
|
14216
14231
|
|
|
14217
14232
|
//#endregion
|
|
14218
14233
|
//#region src/operators/throwOnRPCError.ts
|
|
14219
|
-
var import_cjs$
|
|
14220
|
-
const logger$
|
|
14234
|
+
var import_cjs$18 = require_cjs();
|
|
14235
|
+
const logger$20 = getLogger();
|
|
14221
14236
|
/**
|
|
14222
14237
|
* RxJS operator that throws a {@link JSONRPCError} when the RPC response contains an error.
|
|
14223
14238
|
* Passes successful responses through unchanged.
|
|
14224
14239
|
*/
|
|
14225
14240
|
function throwOnRPCError() {
|
|
14226
|
-
return (0, import_cjs$
|
|
14241
|
+
return (0, import_cjs$18.map)((response) => {
|
|
14227
14242
|
if (response.error) {
|
|
14228
|
-
logger$
|
|
14243
|
+
logger$20.error("[throwOnRPCError] RPC error response:", {
|
|
14229
14244
|
code: response.error.code,
|
|
14230
14245
|
message: response.error.message,
|
|
14231
14246
|
data: response.error.data
|
|
14232
14247
|
});
|
|
14233
14248
|
throw new JSONRPCError(response.error.code, response.error.message, response.error.data);
|
|
14234
14249
|
}
|
|
14235
|
-
logger$
|
|
14250
|
+
logger$20.debug("[throwOnRPCError] RPC successful response:", response);
|
|
14236
14251
|
return response;
|
|
14237
14252
|
});
|
|
14238
14253
|
}
|
|
14239
14254
|
|
|
14240
14255
|
//#endregion
|
|
14241
14256
|
//#region src/managers/CallEventsManager.ts
|
|
14242
|
-
var import_cjs$
|
|
14243
|
-
const logger$
|
|
14257
|
+
var import_cjs$17 = require_cjs();
|
|
14258
|
+
const logger$19 = getLogger();
|
|
14244
14259
|
const initialSessionState = {};
|
|
14245
14260
|
/** @internal */
|
|
14246
14261
|
var CallEventsManager = class extends Destroyable {
|
|
@@ -14256,7 +14271,7 @@ var CallEventsManager = class extends Destroyable {
|
|
|
14256
14271
|
this.initSubscriptions();
|
|
14257
14272
|
}
|
|
14258
14273
|
get participants$() {
|
|
14259
|
-
return this.cachedObservable("participants$", () => this._participants$.asObservable().pipe((0, import_cjs$
|
|
14274
|
+
return this.cachedObservable("participants$", () => this._participants$.asObservable().pipe((0, import_cjs$17.map)((participantsRecord) => Object.values(participantsRecord))));
|
|
14260
14275
|
}
|
|
14261
14276
|
get participants() {
|
|
14262
14277
|
return Object.values(this._participants$.value);
|
|
@@ -14274,40 +14289,40 @@ var CallEventsManager = class extends Destroyable {
|
|
|
14274
14289
|
return this.callIds.has(callId);
|
|
14275
14290
|
}
|
|
14276
14291
|
get recording$() {
|
|
14277
|
-
return this.cachedObservable("recording$", () => this._sessionState$.pipe((0, import_cjs$
|
|
14292
|
+
return this.cachedObservable("recording$", () => this._sessionState$.pipe((0, import_cjs$17.map)((state) => state.recording), (0, import_cjs$17.distinctUntilChanged)(), filterNull()));
|
|
14278
14293
|
}
|
|
14279
14294
|
get recordings$() {
|
|
14280
|
-
return this.cachedObservable("recordings$", () => this._sessionState$.pipe((0, import_cjs$
|
|
14295
|
+
return this.cachedObservable("recordings$", () => this._sessionState$.pipe((0, import_cjs$17.map)((state) => state.recordings), (0, import_cjs$17.distinctUntilChanged)(), filterNull()));
|
|
14281
14296
|
}
|
|
14282
14297
|
get streaming$() {
|
|
14283
|
-
return this.cachedObservable("streaming$", () => this._sessionState$.pipe((0, import_cjs$
|
|
14298
|
+
return this.cachedObservable("streaming$", () => this._sessionState$.pipe((0, import_cjs$17.map)((state) => state.streaming), (0, import_cjs$17.distinctUntilChanged)(), filterNull()));
|
|
14284
14299
|
}
|
|
14285
14300
|
get streams$() {
|
|
14286
|
-
return this.cachedObservable("streams$", () => this._sessionState$.pipe((0, import_cjs$
|
|
14301
|
+
return this.cachedObservable("streams$", () => this._sessionState$.pipe((0, import_cjs$17.map)((state) => state.streams), (0, import_cjs$17.distinctUntilChanged)(), filterNull()));
|
|
14287
14302
|
}
|
|
14288
14303
|
get playbacks$() {
|
|
14289
|
-
return this.cachedObservable("playbacks$", () => this._sessionState$.pipe((0, import_cjs$
|
|
14304
|
+
return this.cachedObservable("playbacks$", () => this._sessionState$.pipe((0, import_cjs$17.map)((state) => state.playbacks), (0, import_cjs$17.distinctUntilChanged)(), filterNull()));
|
|
14290
14305
|
}
|
|
14291
14306
|
get raiseHandPriority$() {
|
|
14292
|
-
return this.cachedObservable("raiseHandPriority$", () => this._sessionState$.pipe((0, import_cjs$
|
|
14307
|
+
return this.cachedObservable("raiseHandPriority$", () => this._sessionState$.pipe((0, import_cjs$17.map)((state) => state.prioritize_handraise), (0, import_cjs$17.distinctUntilChanged)(), filterNull()));
|
|
14293
14308
|
}
|
|
14294
14309
|
get locked$() {
|
|
14295
|
-
return this.cachedObservable("locked$", () => this._sessionState$.pipe((0, import_cjs$
|
|
14310
|
+
return this.cachedObservable("locked$", () => this._sessionState$.pipe((0, import_cjs$17.map)((state) => state.locked), (0, import_cjs$17.distinctUntilChanged)(), filterNull()));
|
|
14296
14311
|
}
|
|
14297
14312
|
get meta$() {
|
|
14298
|
-
return this.cachedObservable("meta$", () => this._sessionState$.pipe((0, import_cjs$
|
|
14313
|
+
return this.cachedObservable("meta$", () => this._sessionState$.pipe((0, import_cjs$17.map)((state) => state.meta), (0, import_cjs$17.distinctUntilChanged)(), filterNull()));
|
|
14299
14314
|
}
|
|
14300
14315
|
get capabilities$() {
|
|
14301
|
-
return this.cachedObservable("capabilities$", () => this._sessionState$.pipe((0, import_cjs$
|
|
14316
|
+
return this.cachedObservable("capabilities$", () => this._sessionState$.pipe((0, import_cjs$17.map)((state) => state.capabilities), (0, import_cjs$17.distinctUntilChanged)(), filterNull()));
|
|
14302
14317
|
}
|
|
14303
14318
|
get layout$() {
|
|
14304
|
-
return this.cachedObservable("layout$", () => this._sessionState$.pipe((0, import_cjs$
|
|
14319
|
+
return this.cachedObservable("layout$", () => this._sessionState$.pipe((0, import_cjs$17.map)((state) => state.layout_name), (0, import_cjs$17.distinctUntilChanged)(), filterNull()));
|
|
14305
14320
|
}
|
|
14306
14321
|
get layouts$() {
|
|
14307
|
-
return this.cachedObservable("layouts$", () => this._sessionState$.pipe((0, import_cjs$
|
|
14322
|
+
return this.cachedObservable("layouts$", () => this._sessionState$.pipe((0, import_cjs$17.map)((state) => state.layouts), (0, import_cjs$17.distinctUntilChanged)(), filterNull()));
|
|
14308
14323
|
}
|
|
14309
14324
|
get layoutLayers$() {
|
|
14310
|
-
return this.cachedObservable("layoutLayers$", () => this._sessionState$.pipe((0, import_cjs$
|
|
14325
|
+
return this.cachedObservable("layoutLayers$", () => this._sessionState$.pipe((0, import_cjs$17.map)((state) => state.layout_layers), (0, import_cjs$17.distinctUntilChanged)(), filterNull()));
|
|
14311
14326
|
}
|
|
14312
14327
|
get self() {
|
|
14313
14328
|
return this._self$.value;
|
|
@@ -14344,7 +14359,7 @@ var CallEventsManager = class extends Destroyable {
|
|
|
14344
14359
|
}
|
|
14345
14360
|
initSubscriptions() {
|
|
14346
14361
|
this.subscribeTo(this.callJoinedEvent$, (callJoinedEvent) => {
|
|
14347
|
-
logger$
|
|
14362
|
+
logger$19.debug("[CallEventsManager] Handling call.joined event for call/session IDs:", {
|
|
14348
14363
|
callId: callJoinedEvent.call_id,
|
|
14349
14364
|
roomSessionId: callJoinedEvent.room_session_id
|
|
14350
14365
|
});
|
|
@@ -14371,19 +14386,19 @@ var CallEventsManager = class extends Destroyable {
|
|
|
14371
14386
|
if (this._self$.value?.capabilities.setLayout) this.updateLayouts();
|
|
14372
14387
|
});
|
|
14373
14388
|
this.subscribeTo(this.memberUpdates$, (member) => {
|
|
14374
|
-
logger$
|
|
14389
|
+
logger$19.debug("[CallEventsManager] Handling member update event for member ID:", member);
|
|
14375
14390
|
this.upsertParticipant(member);
|
|
14376
14391
|
});
|
|
14377
14392
|
this.subscribeTo(this.webRtcCallSession.memberLeft$, (memberLeftEvent) => {
|
|
14378
|
-
logger$
|
|
14393
|
+
logger$19.debug("[CallEventsManager] Handling member.left event for member ID:", memberLeftEvent.member.member_id);
|
|
14379
14394
|
const participants = { ...this._participants$.value };
|
|
14380
14395
|
if (memberLeftEvent.member.member_id in participants) {
|
|
14381
14396
|
delete participants[memberLeftEvent.member.member_id];
|
|
14382
14397
|
this._participants$.next(participants);
|
|
14383
|
-
} else logger$
|
|
14398
|
+
} else logger$19.warn(`[CallEventsManager] Received member.left event for unknown member ID: ${memberLeftEvent.member.member_id}`);
|
|
14384
14399
|
});
|
|
14385
14400
|
this.subscribeTo(this.webRtcCallSession.callUpdated$, (callUpdatedEvent) => {
|
|
14386
|
-
logger$
|
|
14401
|
+
logger$19.debug("[CallEventsManager] Handling call.updated event:", callUpdatedEvent);
|
|
14387
14402
|
const roomSession = callUpdatedEvent.room_session;
|
|
14388
14403
|
this._sessionState$.next({
|
|
14389
14404
|
...this._sessionState$.value,
|
|
@@ -14398,7 +14413,7 @@ var CallEventsManager = class extends Destroyable {
|
|
|
14398
14413
|
});
|
|
14399
14414
|
});
|
|
14400
14415
|
this.subscribeTo(this.layoutChangedEvent$, (layoutChangedEvent) => {
|
|
14401
|
-
logger$
|
|
14416
|
+
logger$19.debug("[CallEventsManager] Handling layout.changed event:", layoutChangedEvent);
|
|
14402
14417
|
this._sessionState$.next({
|
|
14403
14418
|
...this._sessionState$.value,
|
|
14404
14419
|
layout_name: layoutChangedEvent.id,
|
|
@@ -14408,10 +14423,10 @@ var CallEventsManager = class extends Destroyable {
|
|
|
14408
14423
|
});
|
|
14409
14424
|
}
|
|
14410
14425
|
updateParticipantPositions(layoutChangedEvent) {
|
|
14411
|
-
if (Object.keys(this._participants$.value).length > 0 && !layoutChangedEvent.layers.some((layer) => !!layer.member_id)) logger$
|
|
14412
|
-
layoutChangedEvent.layers.filter((layer) =>
|
|
14413
|
-
if (!
|
|
14414
|
-
logger$
|
|
14426
|
+
if (Object.keys(this._participants$.value).length > 0 && !layoutChangedEvent.layers.some((layer) => !!layer.member_id)) logger$19.warn("[CallEventsManager] No layers with member_id found in layout.changed event. Nothing to update.");
|
|
14427
|
+
layoutChangedEvent.layers.filter((layer) => !!layer.member_id).filter((layer) => {
|
|
14428
|
+
if (!(layer.member_id in this._participants$.value)) {
|
|
14429
|
+
logger$19.warn(`[CallEventsManager] Skipping layout layer for unknown member_id: ${layer.member_id}`);
|
|
14415
14430
|
return false;
|
|
14416
14431
|
}
|
|
14417
14432
|
return true;
|
|
@@ -14434,7 +14449,7 @@ var CallEventsManager = class extends Destroyable {
|
|
|
14434
14449
|
layouts: response.result.layouts
|
|
14435
14450
|
});
|
|
14436
14451
|
}).catch((error) => {
|
|
14437
|
-
logger$
|
|
14452
|
+
logger$19.error("[CallEventsManager] Error fetching layouts:", error);
|
|
14438
14453
|
});
|
|
14439
14454
|
}
|
|
14440
14455
|
updateParticipants(members) {
|
|
@@ -14450,7 +14465,7 @@ var CallEventsManager = class extends Destroyable {
|
|
|
14450
14465
|
}
|
|
14451
14466
|
const participant = this._participants$.value[member.member_id];
|
|
14452
14467
|
const oldValue = participant.value;
|
|
14453
|
-
logger$
|
|
14468
|
+
logger$19.debug("[CallEventsManager] Updating participant:", member.member_id, {
|
|
14454
14469
|
oldValue,
|
|
14455
14470
|
newValue: member
|
|
14456
14471
|
});
|
|
@@ -14462,18 +14477,18 @@ var CallEventsManager = class extends Destroyable {
|
|
|
14462
14477
|
this._participants$.next(this._participants$.value);
|
|
14463
14478
|
}
|
|
14464
14479
|
get callJoinedEvent$() {
|
|
14465
|
-
return this.cachedObservable("callJoinedEvent$", () => this.webRtcCallSession.callEvent$.pipe((0, import_cjs$
|
|
14466
|
-
logger$
|
|
14480
|
+
return this.cachedObservable("callJoinedEvent$", () => this.webRtcCallSession.callEvent$.pipe((0, import_cjs$17.filter)(isCallJoinedPayload), (0, import_cjs$17.tap)((event) => {
|
|
14481
|
+
logger$19.debug("[CallEventsManager] Call joined event:", event);
|
|
14467
14482
|
})));
|
|
14468
14483
|
}
|
|
14469
14484
|
get layoutChangedEvent$() {
|
|
14470
|
-
return this.cachedObservable("layoutChangedEvent$", () => this.webRtcCallSession.callEvent$.pipe(filterAs(isLayoutChangedPayload, "layout"), (0, import_cjs$
|
|
14471
|
-
logger$
|
|
14485
|
+
return this.cachedObservable("layoutChangedEvent$", () => this.webRtcCallSession.callEvent$.pipe(filterAs(isLayoutChangedPayload, "layout"), (0, import_cjs$17.tap)((event) => {
|
|
14486
|
+
logger$19.debug("[CallEventsManager] Layout changed event:", event);
|
|
14472
14487
|
})));
|
|
14473
14488
|
}
|
|
14474
14489
|
get memberUpdates$() {
|
|
14475
|
-
return this.cachedObservable("memberUpdates$", () => (0, import_cjs$
|
|
14476
|
-
logger$
|
|
14490
|
+
return this.cachedObservable("memberUpdates$", () => (0, import_cjs$17.merge)(this.webRtcCallSession.memberJoined$, this.webRtcCallSession.memberUpdated$, this.webRtcCallSession.memberTalking$).pipe((0, import_cjs$17.map)((event) => event.member), (0, import_cjs$17.tap)((event) => {
|
|
14491
|
+
logger$19.debug("[CallEventsManager] Member update event:", event);
|
|
14477
14492
|
})));
|
|
14478
14493
|
}
|
|
14479
14494
|
destroy() {
|
|
@@ -14729,8 +14744,8 @@ function appendStereoParams(fmtpLine, maxBitrate) {
|
|
|
14729
14744
|
|
|
14730
14745
|
//#endregion
|
|
14731
14746
|
//#region src/controllers/ICEGatheringController.ts
|
|
14732
|
-
var import_cjs$
|
|
14733
|
-
const logger$
|
|
14747
|
+
var import_cjs$16 = require_cjs();
|
|
14748
|
+
const logger$18 = getLogger();
|
|
14734
14749
|
var ICEGatheringController = class extends Destroyable {
|
|
14735
14750
|
constructor(peerConnection, peerConnectionControllerNegotiating$, options = {}) {
|
|
14736
14751
|
super();
|
|
@@ -14738,23 +14753,23 @@ var ICEGatheringController = class extends Destroyable {
|
|
|
14738
14753
|
this.peerConnectionControllerNegotiating$ = peerConnectionControllerNegotiating$;
|
|
14739
14754
|
this.onicegatheringstatechangeHandler = () => {
|
|
14740
14755
|
const { iceGatheringState } = this.peerConnection;
|
|
14741
|
-
logger$
|
|
14756
|
+
logger$18.debug(`[ICEGatheringController] ICE gathering state changed to: ${iceGatheringState}`);
|
|
14742
14757
|
if (iceGatheringState === "gathering") this._iceCandidatesState.next({
|
|
14743
14758
|
state: "gathering",
|
|
14744
14759
|
validSDP: false
|
|
14745
14760
|
});
|
|
14746
14761
|
};
|
|
14747
14762
|
this.onicecandidateHandler = (event) => {
|
|
14748
|
-
logger$
|
|
14763
|
+
logger$18.debug("[ICEGatheringController] ICE candidate event received:", event.candidate);
|
|
14749
14764
|
this.removeTimer("iceCandidateTimer");
|
|
14750
14765
|
if (event.candidate) this.iceCandidateTimer = setTimeout(() => {
|
|
14751
14766
|
if (this.peerConnection.iceGatheringState !== "complete") {
|
|
14752
|
-
logger$
|
|
14767
|
+
logger$18.warn("[ICEGatheringController] ICE candidate timeout, using current SDP");
|
|
14753
14768
|
this.handleICECandidateTimeout();
|
|
14754
14769
|
}
|
|
14755
14770
|
}, this.iceCandidateTimeout);
|
|
14756
14771
|
else {
|
|
14757
|
-
logger$
|
|
14772
|
+
logger$18.debug("[ICEGatheringController] ICE gathering completed: null candidate received");
|
|
14758
14773
|
this.removeTimer("iceGatheringTimer");
|
|
14759
14774
|
this.handleICEGatheringComplete();
|
|
14760
14775
|
}
|
|
@@ -14767,12 +14782,12 @@ var ICEGatheringController = class extends Destroyable {
|
|
|
14767
14782
|
this.iceGatheringTimeout = options.iceGatheringTimeout ?? DEFAULT_ICE_GATHERING_TIMEOUT_MS;
|
|
14768
14783
|
this.relayOnly = options.relayOnly ?? false;
|
|
14769
14784
|
this.setupEventListeners();
|
|
14770
|
-
this.subscribeTo(this.peerConnectionControllerNegotiating$.pipe((0, import_cjs$
|
|
14785
|
+
this.subscribeTo(this.peerConnectionControllerNegotiating$.pipe((0, import_cjs$16.filter)((isNegotiating) => isNegotiating)), (isNegotiating) => {
|
|
14771
14786
|
if (isNegotiating) {
|
|
14772
14787
|
this.setupEventListeners();
|
|
14773
14788
|
this.iceGatheringTimer = setTimeout(() => {
|
|
14774
14789
|
if (this.peerConnection.iceGatheringState !== "complete") {
|
|
14775
|
-
logger$
|
|
14790
|
+
logger$18.warn("[ICEGatheringController] ICE gathering timeout, using current SDP");
|
|
14776
14791
|
this.handleICEGatheringTimeout();
|
|
14777
14792
|
}
|
|
14778
14793
|
}, this.iceGatheringTimeout);
|
|
@@ -14786,7 +14801,7 @@ var ICEGatheringController = class extends Destroyable {
|
|
|
14786
14801
|
this.peerConnection.addEventListener("icegatheringstatechange", this.onicegatheringstatechangeHandler);
|
|
14787
14802
|
}
|
|
14788
14803
|
get iceCandidatesState$() {
|
|
14789
|
-
return this._iceCandidatesState.pipe((0, import_cjs$
|
|
14804
|
+
return this._iceCandidatesState.pipe((0, import_cjs$16.withLatestFrom)(this.peerConnectionControllerNegotiating$), (0, import_cjs$16.filter)(([_, isNegotiating]) => isNegotiating), (0, import_cjs$16.map)(([state, _]) => state.state));
|
|
14790
14805
|
}
|
|
14791
14806
|
get hasValidLocalDescriptionSDP() {
|
|
14792
14807
|
const sdp = this.peerConnection.localDescription?.sdp;
|
|
@@ -14799,9 +14814,9 @@ var ICEGatheringController = class extends Destroyable {
|
|
|
14799
14814
|
this.relayOnly = value;
|
|
14800
14815
|
}
|
|
14801
14816
|
handleICEGatheringComplete() {
|
|
14802
|
-
logger$
|
|
14803
|
-
logger$
|
|
14804
|
-
logger$
|
|
14817
|
+
logger$18.debug("[ICEGatheringController] Handling ICE gathering complete");
|
|
14818
|
+
logger$18.debug(`[ICEGatheringController] Checking ICE gathering state: ${this.peerConnection.iceGatheringState}`);
|
|
14819
|
+
logger$18.debug("[ICEGatheringController] ICE gathering complete");
|
|
14805
14820
|
this._iceCandidatesState.next({
|
|
14806
14821
|
state: "complete",
|
|
14807
14822
|
validSDP: this.hasValidLocalDescriptionSDP
|
|
@@ -14817,21 +14832,21 @@ var ICEGatheringController = class extends Destroyable {
|
|
|
14817
14832
|
this.removeTimer("iceGatheringTimer");
|
|
14818
14833
|
const validSDP = this.hasValidLocalDescriptionSDP;
|
|
14819
14834
|
if (validSDP) {
|
|
14820
|
-
logger$
|
|
14835
|
+
logger$18.debug("[ICEGatheringController] Local SDP is valid");
|
|
14821
14836
|
this._iceCandidatesState.next({
|
|
14822
14837
|
state: "timeout",
|
|
14823
14838
|
validSDP
|
|
14824
14839
|
});
|
|
14825
14840
|
this.stopGathering();
|
|
14826
|
-
} else logger$
|
|
14841
|
+
} else logger$18.debug("### ICE gathering timeout\n", this.peerConnection.localDescription?.sdp);
|
|
14827
14842
|
}
|
|
14828
14843
|
handleICECandidateTimeout() {
|
|
14829
14844
|
if (this.iceCandidateTimer) this.removeTimer("iceCandidateTimer");
|
|
14830
|
-
logger$
|
|
14845
|
+
logger$18.warn("[ICEGatheringController] ICE candidate timeout");
|
|
14831
14846
|
const validSDP = this.hasValidLocalDescriptionSDP;
|
|
14832
14847
|
if (!validSDP && !this.relayOnly) this.restartICEGatheringWithRelayOnly();
|
|
14833
14848
|
else {
|
|
14834
|
-
logger$
|
|
14849
|
+
logger$18.debug("[ICEGatheringController] Using current SDP due to ICE candidate timeout");
|
|
14835
14850
|
this._iceCandidatesState.next({
|
|
14836
14851
|
state: "timeout",
|
|
14837
14852
|
validSDP
|
|
@@ -14840,7 +14855,7 @@ var ICEGatheringController = class extends Destroyable {
|
|
|
14840
14855
|
}
|
|
14841
14856
|
}
|
|
14842
14857
|
restartICEGatheringWithRelayOnly() {
|
|
14843
|
-
logger$
|
|
14858
|
+
logger$18.debug("[ICEGatheringController] Restarting ICE gathering with relay-only candidates");
|
|
14844
14859
|
this.relayOnly = true;
|
|
14845
14860
|
this.peerConnection.setConfiguration({
|
|
14846
14861
|
...this.peerConnection.getConfiguration(),
|
|
@@ -14848,14 +14863,14 @@ var ICEGatheringController = class extends Destroyable {
|
|
|
14848
14863
|
});
|
|
14849
14864
|
if (!(this.peerConnection.connectionState === "connected")) this.peerConnection.restartIce();
|
|
14850
14865
|
}
|
|
14851
|
-
removeTimer(timer$
|
|
14852
|
-
if (this[timer$
|
|
14853
|
-
clearTimeout(this[timer$
|
|
14854
|
-
this[timer$
|
|
14866
|
+
removeTimer(timer$3) {
|
|
14867
|
+
if (this[timer$3]) {
|
|
14868
|
+
clearTimeout(this[timer$3]);
|
|
14869
|
+
this[timer$3] = void 0;
|
|
14855
14870
|
}
|
|
14856
14871
|
}
|
|
14857
14872
|
clearAllTimers() {
|
|
14858
|
-
logger$
|
|
14873
|
+
logger$18.debug("[ICEGatheringController] Clearing all timers");
|
|
14859
14874
|
this.removeTimer("iceGatheringTimer");
|
|
14860
14875
|
this.removeTimer("iceCandidateTimer");
|
|
14861
14876
|
}
|
|
@@ -14864,7 +14879,7 @@ var ICEGatheringController = class extends Destroyable {
|
|
|
14864
14879
|
this.peerConnection.removeEventListener("icecandidate", this.onicecandidateHandler);
|
|
14865
14880
|
}
|
|
14866
14881
|
destroy() {
|
|
14867
|
-
logger$
|
|
14882
|
+
logger$18.debug("[ICEGatheringController] Destroying ICEGatheringController");
|
|
14868
14883
|
this.clearAllTimers();
|
|
14869
14884
|
this.removeEventListeners();
|
|
14870
14885
|
super.destroy();
|
|
@@ -14873,8 +14888,8 @@ var ICEGatheringController = class extends Destroyable {
|
|
|
14873
14888
|
|
|
14874
14889
|
//#endregion
|
|
14875
14890
|
//#region src/controllers/LocalStreamController.ts
|
|
14876
|
-
var import_cjs$
|
|
14877
|
-
const logger$
|
|
14891
|
+
var import_cjs$15 = require_cjs();
|
|
14892
|
+
const logger$17 = getLogger();
|
|
14878
14893
|
var LocalStreamController = class extends Destroyable {
|
|
14879
14894
|
constructor(options) {
|
|
14880
14895
|
super();
|
|
@@ -14888,16 +14903,16 @@ var LocalStreamController = class extends Destroyable {
|
|
|
14888
14903
|
this._mediaTrackEnded$ = this.createSubject();
|
|
14889
14904
|
}
|
|
14890
14905
|
get localStream$() {
|
|
14891
|
-
return this._localStream$.asObservable().pipe((0, import_cjs$
|
|
14906
|
+
return this._localStream$.asObservable().pipe((0, import_cjs$15.takeUntil)(this.destroyed$));
|
|
14892
14907
|
}
|
|
14893
14908
|
get localAudioTracks$() {
|
|
14894
|
-
return this._localAudioTracks$.asObservable().pipe((0, import_cjs$
|
|
14909
|
+
return this._localAudioTracks$.asObservable().pipe((0, import_cjs$15.takeUntil)(this.destroyed$));
|
|
14895
14910
|
}
|
|
14896
14911
|
get localVideoTracks$() {
|
|
14897
|
-
return this._localVideoTracks$.asObservable().pipe((0, import_cjs$
|
|
14912
|
+
return this._localVideoTracks$.asObservable().pipe((0, import_cjs$15.takeUntil)(this.destroyed$));
|
|
14898
14913
|
}
|
|
14899
14914
|
get mediaTrackEnded$() {
|
|
14900
|
-
return this._mediaTrackEnded$.asObservable().pipe((0, import_cjs$
|
|
14915
|
+
return this._mediaTrackEnded$.asObservable().pipe((0, import_cjs$15.takeUntil)(this.destroyed$));
|
|
14901
14916
|
}
|
|
14902
14917
|
get localStream() {
|
|
14903
14918
|
return this._localStream$.value;
|
|
@@ -14912,26 +14927,26 @@ var LocalStreamController = class extends Destroyable {
|
|
|
14912
14927
|
* Build the local media stream based on the provided options.
|
|
14913
14928
|
*/
|
|
14914
14929
|
async buildLocalStream() {
|
|
14915
|
-
logger$
|
|
14930
|
+
logger$17.debug("[LocalStreamController] Building local media stream.");
|
|
14916
14931
|
let stream;
|
|
14917
14932
|
if (this.options.inputAudioStream ?? this.options.inputVideoStream) {
|
|
14918
14933
|
const tracks = [...this.options.inputAudioStream?.getTracks() ?? [], ...this.options.inputVideoStream?.getTracks() ?? []];
|
|
14919
14934
|
stream = new MediaStream(tracks);
|
|
14920
14935
|
} else if (this.options.propose === "screenshare") {
|
|
14921
|
-
logger$
|
|
14936
|
+
logger$17.debug("[LocalStreamController] Requesting display media for screen sharing with audio:", Boolean(this.options.inputAudioDeviceConstraints));
|
|
14922
14937
|
stream = await this.options.getDisplayMedia({
|
|
14923
14938
|
video: true,
|
|
14924
14939
|
audio: Boolean(this.options.inputAudioDeviceConstraints)
|
|
14925
14940
|
});
|
|
14926
|
-
logger$
|
|
14941
|
+
logger$17.debug("[LocalStreamController] Screen share media obtained:", stream);
|
|
14927
14942
|
} else {
|
|
14928
14943
|
const constraints = {
|
|
14929
14944
|
audio: this.options.inputAudioDeviceConstraints,
|
|
14930
14945
|
video: this.options.inputVideoDeviceConstraints
|
|
14931
14946
|
};
|
|
14932
|
-
logger$
|
|
14947
|
+
logger$17.debug("[LocalStreamController] Requesting user media with constraints:", constraints);
|
|
14933
14948
|
stream = await this.options.getUserMedia(constraints);
|
|
14934
|
-
logger$
|
|
14949
|
+
logger$17.debug("[LocalStreamController] User media obtained:", stream);
|
|
14935
14950
|
}
|
|
14936
14951
|
this._localStream$.next(stream);
|
|
14937
14952
|
return stream;
|
|
@@ -14948,7 +14963,7 @@ var LocalStreamController = class extends Destroyable {
|
|
|
14948
14963
|
this._localStream$.next(localStream);
|
|
14949
14964
|
if (track.kind === "video") this._localVideoTracks$.next(localStream.getVideoTracks());
|
|
14950
14965
|
else this._localAudioTracks$.next(localStream.getAudioTracks());
|
|
14951
|
-
logger$
|
|
14966
|
+
logger$17.debug(`[LocalStreamController] ${track.kind} track added:`, track.id);
|
|
14952
14967
|
return localStream;
|
|
14953
14968
|
}
|
|
14954
14969
|
/**
|
|
@@ -14960,7 +14975,7 @@ var LocalStreamController = class extends Destroyable {
|
|
|
14960
14975
|
const stream = this._localStream$.value;
|
|
14961
14976
|
const track = stream?.getTracks().find((t) => t.id === trackId);
|
|
14962
14977
|
if (!track) {
|
|
14963
|
-
logger$
|
|
14978
|
+
logger$17.debug(`[LocalStreamController] track not found: ${trackId}`);
|
|
14964
14979
|
return;
|
|
14965
14980
|
}
|
|
14966
14981
|
track.removeEventListener("ended", this.mediaTrackEndedHandler);
|
|
@@ -14969,7 +14984,7 @@ var LocalStreamController = class extends Destroyable {
|
|
|
14969
14984
|
this._localStream$.next(stream);
|
|
14970
14985
|
if (track.kind === "video") this._localVideoTracks$.next(stream?.getVideoTracks() ?? []);
|
|
14971
14986
|
else this._localAudioTracks$.next(stream?.getAudioTracks() ?? []);
|
|
14972
|
-
logger$
|
|
14987
|
+
logger$17.debug(`[LocalStreamController] ${track.kind} track removed:`, trackId);
|
|
14973
14988
|
return track;
|
|
14974
14989
|
}
|
|
14975
14990
|
/**
|
|
@@ -15004,7 +15019,7 @@ var LocalStreamController = class extends Destroyable {
|
|
|
15004
15019
|
*/
|
|
15005
15020
|
stopAllTracks() {
|
|
15006
15021
|
this._localStream$.value?.getTracks().forEach((track) => {
|
|
15007
|
-
logger$
|
|
15022
|
+
logger$17.debug(`[LocalStreamController] Stopping local track: ${track.kind}`);
|
|
15008
15023
|
track.removeEventListener("ended", this.mediaTrackEndedHandler);
|
|
15009
15024
|
track.stop();
|
|
15010
15025
|
});
|
|
@@ -15020,7 +15035,7 @@ var LocalStreamController = class extends Destroyable {
|
|
|
15020
15035
|
|
|
15021
15036
|
//#endregion
|
|
15022
15037
|
//#region src/controllers/TransceiverController.ts
|
|
15023
|
-
const logger$
|
|
15038
|
+
const logger$16 = getLogger();
|
|
15024
15039
|
const getDirection = (send, recv) => {
|
|
15025
15040
|
if (send && recv) return "sendrecv";
|
|
15026
15041
|
else if (send && !recv) return "sendonly";
|
|
@@ -15122,7 +15137,7 @@ var TransceiverController = class extends Destroyable {
|
|
|
15122
15137
|
sendEncodings: isAudio ? void 0 : this.sendEncodings,
|
|
15123
15138
|
streams: direction === "recvonly" ? void 0 : [localStream]
|
|
15124
15139
|
};
|
|
15125
|
-
logger$
|
|
15140
|
+
logger$16.debug(`[TransceiverController] Setting up transceiver sender for local ${track.kind} track:`, {
|
|
15126
15141
|
transceiver,
|
|
15127
15142
|
transceiverParams
|
|
15128
15143
|
});
|
|
@@ -15130,11 +15145,11 @@ var TransceiverController = class extends Destroyable {
|
|
|
15130
15145
|
await transceiver.sender.replaceTrack(track);
|
|
15131
15146
|
transceiver.direction = transceiverParams.direction;
|
|
15132
15147
|
if (transceiverParams.streams?.some((stream) => Boolean(stream))) {
|
|
15133
|
-
logger$
|
|
15148
|
+
logger$16.debug(`[TransceiverController] Setting streams for transceiver sender for local ${track.kind} track:`, transceiverParams.streams);
|
|
15134
15149
|
transceiver.sender.setStreams(...transceiverParams.streams);
|
|
15135
15150
|
}
|
|
15136
15151
|
} else {
|
|
15137
|
-
logger$
|
|
15152
|
+
logger$16.debug(`[TransceiverController] Adding new transceiver for local ${track.kind} track:`, track.id);
|
|
15138
15153
|
this.peerConnection.addTransceiver(track, transceiverParams);
|
|
15139
15154
|
}
|
|
15140
15155
|
}
|
|
@@ -15148,13 +15163,13 @@ var TransceiverController = class extends Destroyable {
|
|
|
15148
15163
|
if (options.updateTransceiverDirection) transceiver.direction = "inactive";
|
|
15149
15164
|
}
|
|
15150
15165
|
} catch (error) {
|
|
15151
|
-
logger$
|
|
15166
|
+
logger$16.error("[TransceiverController] stopTrackSender error", kind, error);
|
|
15152
15167
|
this.options.onError?.(new MediaTrackError("stopTrackSender", kind, error));
|
|
15153
15168
|
}
|
|
15154
15169
|
}
|
|
15155
15170
|
async restoreTrackSender(kind) {
|
|
15156
15171
|
try {
|
|
15157
|
-
logger$
|
|
15172
|
+
logger$16.debug("[TransceiverController] restoreTrackSender called", kind);
|
|
15158
15173
|
const constraints = {};
|
|
15159
15174
|
const transceivers = this.transceiverByKind(kind);
|
|
15160
15175
|
for (const transceiver of transceivers) {
|
|
@@ -15164,23 +15179,23 @@ var TransceiverController = class extends Destroyable {
|
|
|
15164
15179
|
if (trackKind === "audio" || trackKind === "video") constraints[trackKind] = this.getConstraintsFor(trackKind);
|
|
15165
15180
|
}
|
|
15166
15181
|
}
|
|
15167
|
-
logger$
|
|
15182
|
+
logger$16.debug("[TransceiverController] restoreTrackSender constraints:", constraints);
|
|
15168
15183
|
if (Object.keys(constraints).length === 0) {
|
|
15169
|
-
logger$
|
|
15184
|
+
logger$16.warn("[TransceiverController] restoreTrackSender: no tracks need restoration", kind);
|
|
15170
15185
|
return;
|
|
15171
15186
|
}
|
|
15172
15187
|
const newTracks = (await this.options.getUserMedia(constraints)).getTracks();
|
|
15173
|
-
logger$
|
|
15188
|
+
logger$16.debug("[TransceiverController] restoreTrackSender new tracks:", newTracks);
|
|
15174
15189
|
for (const newTrack of newTracks) {
|
|
15175
15190
|
this.options.localStreamController.addTrack(newTrack);
|
|
15176
15191
|
const trackKind = newTrack.kind;
|
|
15177
15192
|
const transceiverOfKind = this.transceiverByKind(trackKind)[0];
|
|
15178
15193
|
transceiverOfKind.direction = trackKind === "audio" ? this.audioDirection : this.videoDirection;
|
|
15179
|
-
logger$
|
|
15194
|
+
logger$16.debug("[TransceiverController] restoreTrackSender setting direction for", trackKind, transceiverOfKind.direction);
|
|
15180
15195
|
await transceiverOfKind.sender.replaceTrack(newTrack);
|
|
15181
15196
|
}
|
|
15182
15197
|
} catch (error) {
|
|
15183
|
-
logger$
|
|
15198
|
+
logger$16.error("[TransceiverController] restoreTrackSender error", kind, error);
|
|
15184
15199
|
this.options.onError?.(new MediaTrackError("restoreTrackSender", kind, error));
|
|
15185
15200
|
}
|
|
15186
15201
|
}
|
|
@@ -15221,14 +15236,14 @@ var TransceiverController = class extends Destroyable {
|
|
|
15221
15236
|
};
|
|
15222
15237
|
try {
|
|
15223
15238
|
await track.applyConstraints(constraintsToApply);
|
|
15224
|
-
logger$
|
|
15225
|
-
logger$
|
|
15239
|
+
logger$16.debug(`[TransceiverController] Updated ${kind} sender constraints:`, constraintsToApply);
|
|
15240
|
+
logger$16.debug(`[TransceiverController] Updated ${kind} sender constraints:`, track.getConstraints());
|
|
15226
15241
|
} catch (error) {
|
|
15227
|
-
logger$
|
|
15242
|
+
logger$16.warn(`[TransceiverController] applyConstraints failed for ${kind} track ${track.id}, attempting track replacement fallback:`, error);
|
|
15228
15243
|
try {
|
|
15229
15244
|
await this.replaceTrackFallback(sender, track, kind, constraintsToApply);
|
|
15230
15245
|
} catch (fallbackError) {
|
|
15231
|
-
logger$
|
|
15246
|
+
logger$16.warn(`[TransceiverController] Track replacement fallback also failed for ${kind} track:`, fallbackError);
|
|
15232
15247
|
this.options.onError?.(new MediaTrackError("updateSendersConstraints", kind, fallbackError));
|
|
15233
15248
|
}
|
|
15234
15249
|
}
|
|
@@ -15256,7 +15271,7 @@ var TransceiverController = class extends Destroyable {
|
|
|
15256
15271
|
if (!newTrack) throw new MediaTrackError("replaceTrackFallback", kind, /* @__PURE__ */ new Error("getUserMedia returned no track of the requested kind"));
|
|
15257
15272
|
await sender.replaceTrack(newTrack);
|
|
15258
15273
|
this.options.localStreamController.addTrack(newTrack);
|
|
15259
|
-
logger$
|
|
15274
|
+
logger$16.debug(`[TransceiverController] Track replacement fallback succeeded for ${kind}. New track: ${newTrack.id}`);
|
|
15260
15275
|
}
|
|
15261
15276
|
getMediaDirections() {
|
|
15262
15277
|
if (this.peerConnection.connectionState === "connected") return this.peerConnection.getTransceivers().reduce((acc, transceiver) => {
|
|
@@ -15286,60 +15301,60 @@ var TransceiverController = class extends Destroyable {
|
|
|
15286
15301
|
|
|
15287
15302
|
//#endregion
|
|
15288
15303
|
//#region src/controllers/RTCPeerConnectionController.ts
|
|
15289
|
-
var import_cjs$
|
|
15290
|
-
const logger$
|
|
15304
|
+
var import_cjs$14 = require_cjs();
|
|
15305
|
+
const logger$15 = getLogger();
|
|
15291
15306
|
var RTCPeerConnectionController = class extends Destroyable {
|
|
15292
15307
|
constructor(options = {}, remoteSessionDescription, deviceController) {
|
|
15293
15308
|
super();
|
|
15294
15309
|
this.options = options;
|
|
15295
15310
|
this.firstSDPExchangeCompleted = false;
|
|
15296
15311
|
this.negotiationNeeded$ = this.createSubject();
|
|
15297
|
-
this.localDescription$ = (0, import_cjs$
|
|
15312
|
+
this.localDescription$ = (0, import_cjs$14.defer)(() => (0, import_cjs$14.from)(this.init())).pipe((0, import_cjs$14.switchMap)(() => this.iceGatheringController.iceCandidatesState$.pipe((0, import_cjs$14.filter)((iceCandidateState) => !["new", "gathering"].includes(iceCandidateState)), (0, import_cjs$14.tap)(() => {
|
|
15298
15313
|
this.negotiationEnded();
|
|
15299
|
-
}), (0, import_cjs$
|
|
15314
|
+
}), (0, import_cjs$14.filter)(() => this.shouldEmitLocalDescription), (0, import_cjs$14.map)(() => this.peerConnection?.localDescription), filterNull(), (0, import_cjs$14.tap)((desc) => {
|
|
15300
15315
|
if (desc.type === "answer") this._type = "offer";
|
|
15301
|
-
}))), (0, import_cjs$
|
|
15316
|
+
}))), (0, import_cjs$14.shareReplay)(1), (0, import_cjs$14.takeUntil)(this.destroyed$));
|
|
15302
15317
|
this.connectionTimeout = 3e3;
|
|
15303
15318
|
this.oniceconnectionstatechangeHandler = () => {
|
|
15304
15319
|
if (this.peerConnection) {
|
|
15305
15320
|
const { iceConnectionState } = this.peerConnection;
|
|
15306
|
-
logger$
|
|
15321
|
+
logger$15.debug(`[RTCPeerConnectionController] ICE connection state changed to: ${iceConnectionState}`);
|
|
15307
15322
|
this._iceConnectionState$.next(this.peerConnection.iceConnectionState);
|
|
15308
15323
|
}
|
|
15309
15324
|
};
|
|
15310
15325
|
this.onconnectionstatechangeHandler = () => {
|
|
15311
15326
|
if (this.peerConnection) {
|
|
15312
15327
|
const { connectionState } = this.peerConnection;
|
|
15313
|
-
logger$
|
|
15328
|
+
logger$15.debug(`[RTCPeerConnectionController] Connection state changed to: ${connectionState}`);
|
|
15314
15329
|
if (connectionState === "connected") this.removeConnectionTimer();
|
|
15315
15330
|
this._connectionState$.next(this.peerConnection.connectionState);
|
|
15316
15331
|
}
|
|
15317
15332
|
};
|
|
15318
15333
|
this.onsignalingstatechangeHandler = () => {
|
|
15319
|
-
logger$
|
|
15334
|
+
logger$15.debug(`[RTCPeerConnectionController] Signaling state changed to: ${this.peerConnection?.signalingState}`);
|
|
15320
15335
|
};
|
|
15321
15336
|
this.onicegatheringstatechangeHandler = () => {
|
|
15322
15337
|
if (this.peerConnection) this._iceGatheringState$.next(this.peerConnection.iceGatheringState);
|
|
15323
15338
|
};
|
|
15324
15339
|
this.onnegotiationneededHandler = (event) => {
|
|
15325
|
-
logger$
|
|
15340
|
+
logger$15.debug("[RTCPeerConnectionController] Negotiation needed event received.", event);
|
|
15326
15341
|
this.negotiationNeeded$.next();
|
|
15327
15342
|
};
|
|
15328
15343
|
this.updateSelectedInputDevice = async (kind, deviceInfo) => {
|
|
15329
15344
|
try {
|
|
15330
15345
|
const { localStream } = this;
|
|
15331
15346
|
if (!localStream) {
|
|
15332
|
-
logger$
|
|
15347
|
+
logger$15.warn("[RTCPeerConnectionController] No local stream available to update input device.");
|
|
15333
15348
|
return;
|
|
15334
15349
|
}
|
|
15335
|
-
logger$
|
|
15350
|
+
logger$15.debug(`[RTCPeerConnectionController] Updating selected ${kind} input device:`, localStream.getTracks());
|
|
15336
15351
|
const track = localStream.getTracks().find((track$1) => track$1.kind === kind);
|
|
15337
15352
|
if (track) {
|
|
15338
15353
|
this.transceiverController?.stopTrackSender(kind);
|
|
15339
15354
|
this.localStream?.removeTrack(track);
|
|
15340
|
-
logger$
|
|
15355
|
+
logger$15.debug(`[RTCPeerConnectionController] Stopped existing ${kind} track: ${track.id}`, localStream.getTracks());
|
|
15341
15356
|
if (!deviceInfo) {
|
|
15342
|
-
logger$
|
|
15357
|
+
logger$15.debug(`[RTCPeerConnectionController] ${kind} input device selected: none`);
|
|
15343
15358
|
return;
|
|
15344
15359
|
}
|
|
15345
15360
|
const streamTrack = (await this.getUserMedia({ [kind]: {
|
|
@@ -15347,15 +15362,15 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
15347
15362
|
...this.deviceController.deviceInfoToConstraints(deviceInfo)
|
|
15348
15363
|
} })).getTracks().find((t) => t.kind === kind);
|
|
15349
15364
|
if (streamTrack) {
|
|
15350
|
-
logger$
|
|
15365
|
+
logger$15.debug(`[RTCPeerConnectionController] Adding new ${kind} track: ${streamTrack.id}`);
|
|
15351
15366
|
this.localStream?.addTrack(streamTrack);
|
|
15352
15367
|
await this.transceiverController?.replaceSenderTrack(kind, streamTrack);
|
|
15353
|
-
logger$
|
|
15368
|
+
logger$15.debug(`[RTCPeerConnectionController] Added new ${kind} track: ${streamTrack.id}`, this.localStream?.getTracks());
|
|
15354
15369
|
}
|
|
15355
15370
|
}
|
|
15356
|
-
logger$
|
|
15371
|
+
logger$15.debug(`[RTCPeerConnectionController] ${kind} input device selected:`, deviceInfo?.label);
|
|
15357
15372
|
} catch (error) {
|
|
15358
|
-
logger$
|
|
15373
|
+
logger$15.error(`[RTCPeerConnectionController] Failed to select ${kind} input device:`, error);
|
|
15359
15374
|
this._errors$.next(error);
|
|
15360
15375
|
throw error;
|
|
15361
15376
|
}
|
|
@@ -15441,43 +15456,43 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
15441
15456
|
};
|
|
15442
15457
|
}
|
|
15443
15458
|
get iceGatheringState$() {
|
|
15444
|
-
return this.cachedObservable("iceGatheringState$", () => this._iceGatheringState$.asObservable().pipe((0, import_cjs$
|
|
15459
|
+
return this.cachedObservable("iceGatheringState$", () => this._iceGatheringState$.asObservable().pipe((0, import_cjs$14.takeUntil)(this.destroyed$)));
|
|
15445
15460
|
}
|
|
15446
15461
|
get mediaTrackEnded$() {
|
|
15447
|
-
return this.cachedObservable("mediaTrackEnded$", () => this.localStreamController.mediaTrackEnded$.pipe((0, import_cjs$
|
|
15462
|
+
return this.cachedObservable("mediaTrackEnded$", () => this.localStreamController.mediaTrackEnded$.pipe((0, import_cjs$14.takeUntil)(this.destroyed$)));
|
|
15448
15463
|
}
|
|
15449
15464
|
get errors$() {
|
|
15450
|
-
return this.cachedObservable("errors$", () => this._errors$.asObservable().pipe((0, import_cjs$
|
|
15465
|
+
return this.cachedObservable("errors$", () => this._errors$.asObservable().pipe((0, import_cjs$14.takeUntil)(this.destroyed$)));
|
|
15451
15466
|
}
|
|
15452
15467
|
get iceCandidates$() {
|
|
15453
|
-
return this.cachedObservable("iceCandidates$", () => this._iceCandidates$.asObservable().pipe((0, import_cjs$
|
|
15468
|
+
return this.cachedObservable("iceCandidates$", () => this._iceCandidates$.asObservable().pipe((0, import_cjs$14.takeUntil)(this.destroyed$)));
|
|
15454
15469
|
}
|
|
15455
15470
|
get initialized$() {
|
|
15456
|
-
return this.cachedObservable("initialized$", () => this._initialized$.asObservable().pipe((0, import_cjs$
|
|
15471
|
+
return this.cachedObservable("initialized$", () => this._initialized$.asObservable().pipe((0, import_cjs$14.filter)((initialized) => initialized), (0, import_cjs$14.takeUntil)(this.destroyed$)));
|
|
15457
15472
|
}
|
|
15458
15473
|
get remoteDescription$() {
|
|
15459
|
-
return this.cachedObservable("remoteDescription$", () => this._remoteDescription$.asObservable().pipe((0, import_cjs$
|
|
15474
|
+
return this.cachedObservable("remoteDescription$", () => this._remoteDescription$.asObservable().pipe((0, import_cjs$14.takeUntil)(this.destroyed$)));
|
|
15460
15475
|
}
|
|
15461
15476
|
get localStream$() {
|
|
15462
|
-
return this.cachedObservable("localStream$", () => this.localStreamController.localStream$.pipe((0, import_cjs$
|
|
15477
|
+
return this.cachedObservable("localStream$", () => this.localStreamController.localStream$.pipe((0, import_cjs$14.takeUntil)(this.destroyed$)));
|
|
15463
15478
|
}
|
|
15464
15479
|
get remoteStream$() {
|
|
15465
|
-
return this.cachedObservable("remoteStream$", () => this._remoteStream$.asObservable().pipe((0, import_cjs$
|
|
15480
|
+
return this.cachedObservable("remoteStream$", () => this._remoteStream$.asObservable().pipe((0, import_cjs$14.takeUntil)(this.destroyed$)));
|
|
15466
15481
|
}
|
|
15467
15482
|
get localAudioTracks$() {
|
|
15468
|
-
return this.cachedObservable("localAudioTracks$", () => this.localStreamController.localAudioTracks$.pipe((0, import_cjs$
|
|
15483
|
+
return this.cachedObservable("localAudioTracks$", () => this.localStreamController.localAudioTracks$.pipe((0, import_cjs$14.takeUntil)(this.destroyed$)));
|
|
15469
15484
|
}
|
|
15470
15485
|
get localVideoTracks$() {
|
|
15471
|
-
return this.cachedObservable("localVideoTracks$", () => this.localStreamController.localVideoTracks$.pipe((0, import_cjs$
|
|
15486
|
+
return this.cachedObservable("localVideoTracks$", () => this.localStreamController.localVideoTracks$.pipe((0, import_cjs$14.takeUntil)(this.destroyed$)));
|
|
15472
15487
|
}
|
|
15473
15488
|
get iceConnectionState$() {
|
|
15474
|
-
return this.cachedObservable("iceConnectionState$", () => this._iceConnectionState$.asObservable().pipe((0, import_cjs$
|
|
15489
|
+
return this.cachedObservable("iceConnectionState$", () => this._iceConnectionState$.asObservable().pipe((0, import_cjs$14.takeUntil)(this.destroyed$)));
|
|
15475
15490
|
}
|
|
15476
15491
|
get connectionState$() {
|
|
15477
|
-
return this.cachedObservable("connectionState$", () => this._connectionState$.asObservable().pipe((0, import_cjs$
|
|
15492
|
+
return this.cachedObservable("connectionState$", () => this._connectionState$.asObservable().pipe((0, import_cjs$14.takeUntil)(this.destroyed$)));
|
|
15478
15493
|
}
|
|
15479
15494
|
get signalingState$() {
|
|
15480
|
-
return this.cachedObservable("signalingState$", () => this._signalingState$.asObservable().pipe((0, import_cjs$
|
|
15495
|
+
return this.cachedObservable("signalingState$", () => this._signalingState$.asObservable().pipe((0, import_cjs$14.takeUntil)(this.destroyed$)));
|
|
15481
15496
|
}
|
|
15482
15497
|
get type() {
|
|
15483
15498
|
return this._type;
|
|
@@ -15590,17 +15605,17 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
15590
15605
|
async doInit() {
|
|
15591
15606
|
try {
|
|
15592
15607
|
this.setupPeerConnection();
|
|
15593
|
-
this.subscribeTo(this.negotiationNeeded$.pipe((0, import_cjs$
|
|
15608
|
+
this.subscribeTo(this.negotiationNeeded$.pipe((0, import_cjs$14.auditTime)(0), (0, import_cjs$14.exhaustMap)(async () => this.startNegotiation())), {
|
|
15594
15609
|
next: () => {
|
|
15595
|
-
logger$
|
|
15610
|
+
logger$15.debug("[RTCPeerConnectionController] Start Negotiation completed successfully");
|
|
15596
15611
|
},
|
|
15597
15612
|
error: (error) => {
|
|
15598
|
-
logger$
|
|
15613
|
+
logger$15.error("[RTCPeerConnectionController] Start Negotiation error:", error);
|
|
15599
15614
|
this._errors$.next(error);
|
|
15600
15615
|
}
|
|
15601
15616
|
});
|
|
15602
|
-
this.subscribeTo((0, import_cjs$
|
|
15603
|
-
logger$
|
|
15617
|
+
this.subscribeTo((0, import_cjs$14.merge)(this.deviceController.selectedAudioInputDevice$.pipe((0, import_cjs$14.map)((deviceInfo) => ["audio", deviceInfo])), this.deviceController.selectedVideoInputDevice$.pipe((0, import_cjs$14.map)((deviceInfo) => ["video", deviceInfo]))).pipe((0, import_cjs$14.skipWhile)(() => !this.localStreamController.localStream)), async ([kind, deviceInfo]) => {
|
|
15618
|
+
logger$15.debug(`[RTCPeerConnectionController] Selected input device changed for:`, {
|
|
15604
15619
|
kind,
|
|
15605
15620
|
deviceInfo
|
|
15606
15621
|
});
|
|
@@ -15617,7 +15632,7 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
15617
15632
|
this._initialized$.next(true);
|
|
15618
15633
|
}
|
|
15619
15634
|
} catch (error) {
|
|
15620
|
-
logger$
|
|
15635
|
+
logger$15.error("[RTCPeerConnectionController] Initialization error:", error);
|
|
15621
15636
|
this._errors$.next(error);
|
|
15622
15637
|
this.destroy();
|
|
15623
15638
|
}
|
|
@@ -15649,22 +15664,22 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
15649
15664
|
}
|
|
15650
15665
|
async startNegotiation() {
|
|
15651
15666
|
if (this.isNegotiating) {
|
|
15652
|
-
logger$
|
|
15667
|
+
logger$15.debug("[RTCPeerConnectionController] Negotiation already in progress, skipping.");
|
|
15653
15668
|
return;
|
|
15654
15669
|
}
|
|
15655
15670
|
this.setupEventListeners();
|
|
15656
15671
|
if (this.type === "answer") {
|
|
15657
|
-
logger$
|
|
15672
|
+
logger$15.debug("[RTCPeerConnectionController] This is an answer type still, skipping offer creation.");
|
|
15658
15673
|
return;
|
|
15659
15674
|
}
|
|
15660
15675
|
this._isNegotiating$.next(true);
|
|
15661
|
-
logger$
|
|
15676
|
+
logger$15.debug("[RTCPeerConnectionController] Starting negotiation.");
|
|
15662
15677
|
try {
|
|
15663
15678
|
const { offerOptions } = this;
|
|
15664
|
-
logger$
|
|
15679
|
+
logger$15.debug("[RTCPeerConnectionController] Creating offer with options:", offerOptions);
|
|
15665
15680
|
await this.createOffer(offerOptions);
|
|
15666
15681
|
} catch (error) {
|
|
15667
|
-
logger$
|
|
15682
|
+
logger$15.error("[RTCPeerConnectionController] Error during negotiation:", error);
|
|
15668
15683
|
this._errors$.next(error);
|
|
15669
15684
|
}
|
|
15670
15685
|
}
|
|
@@ -15680,14 +15695,14 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
15680
15695
|
let readyToConnect = status !== "failed";
|
|
15681
15696
|
try {
|
|
15682
15697
|
if (status === "received" && sdp) {
|
|
15683
|
-
logger$
|
|
15698
|
+
logger$15.debug("[RTCPeerConnectionController] Received answer SDP:", sdp);
|
|
15684
15699
|
await this._setRemoteDescription({
|
|
15685
15700
|
type: "answer",
|
|
15686
15701
|
sdp
|
|
15687
15702
|
});
|
|
15688
15703
|
}
|
|
15689
15704
|
} catch (error) {
|
|
15690
|
-
logger$
|
|
15705
|
+
logger$15.error("[RTCPeerConnectionController] Error updating answer status:", error);
|
|
15691
15706
|
this._errors$.next(error);
|
|
15692
15707
|
readyToConnect = false;
|
|
15693
15708
|
} finally {
|
|
@@ -15706,7 +15721,7 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
15706
15721
|
await this.handleOfferReceived();
|
|
15707
15722
|
break;
|
|
15708
15723
|
case "failed":
|
|
15709
|
-
logger$
|
|
15724
|
+
logger$15.error("[RTCPeerConnectionController] Offer failed to be processed by remote.");
|
|
15710
15725
|
break;
|
|
15711
15726
|
case "sent":
|
|
15712
15727
|
default:
|
|
@@ -15738,7 +15753,7 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
15738
15753
|
}
|
|
15739
15754
|
await this.setupLocalTracks();
|
|
15740
15755
|
const { answerOptions } = this;
|
|
15741
|
-
logger$
|
|
15756
|
+
logger$15.debug("[RTCPeerConnectionController] Creating inbound answer with options:", answerOptions);
|
|
15742
15757
|
await this.createAnswer(answerOptions);
|
|
15743
15758
|
}
|
|
15744
15759
|
async handleOfferReceived() {
|
|
@@ -15746,7 +15761,7 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
15746
15761
|
this._isNegotiating$.next(true);
|
|
15747
15762
|
await this._setRemoteDescription(this.sdpInit);
|
|
15748
15763
|
const { answerOptions } = this;
|
|
15749
|
-
logger$
|
|
15764
|
+
logger$15.debug("[RTCPeerConnectionController] Creating answer with options:", answerOptions);
|
|
15750
15765
|
await this.createAnswer(answerOptions);
|
|
15751
15766
|
}
|
|
15752
15767
|
readyToConnect() {
|
|
@@ -15754,7 +15769,7 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
15754
15769
|
this.connectionTimer = setTimeout(() => {
|
|
15755
15770
|
this.removeConnectionTimer();
|
|
15756
15771
|
if (this.peerConnection?.connectionState !== "connected") {
|
|
15757
|
-
logger$
|
|
15772
|
+
logger$15.debug("[RTCPeerConnectionController] Connection timeout, restarting ICE gathering with relay only.");
|
|
15758
15773
|
this.iceGatheringController.restartICEGatheringWithRelayOnly();
|
|
15759
15774
|
}
|
|
15760
15775
|
}, this.connectionTimeout);
|
|
@@ -15776,14 +15791,14 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
15776
15791
|
const stereo = this.options.stereo ?? PreferencesContainer.instance.stereoAudio;
|
|
15777
15792
|
if (preferredAudioCodecs.length > 0 || preferredVideoCodecs.length > 0) {
|
|
15778
15793
|
result = setCodecPreferences(result, preferredAudioCodecs, preferredVideoCodecs);
|
|
15779
|
-
logger$
|
|
15794
|
+
logger$15.debug("[RTCPeerConnectionController] Applied codec preferences to SDP", {
|
|
15780
15795
|
preferredAudioCodecs,
|
|
15781
15796
|
preferredVideoCodecs
|
|
15782
15797
|
});
|
|
15783
15798
|
}
|
|
15784
15799
|
if (stereo) {
|
|
15785
15800
|
result = enableStereoOpus(result);
|
|
15786
|
-
logger$
|
|
15801
|
+
logger$15.debug("[RTCPeerConnectionController] Applied stereo Opus to SDP");
|
|
15787
15802
|
}
|
|
15788
15803
|
return Promise.resolve(result);
|
|
15789
15804
|
}
|
|
@@ -15842,18 +15857,18 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
15842
15857
|
...this.peerConnection.getConfiguration(),
|
|
15843
15858
|
iceTransportPolicy: "relay"
|
|
15844
15859
|
});
|
|
15845
|
-
logger$
|
|
15860
|
+
logger$15.debug("[RTCPeerConnectionController] ICE transport policy set to relay-only");
|
|
15846
15861
|
} catch (error) {
|
|
15847
|
-
logger$
|
|
15862
|
+
logger$15.warn("[RTCPeerConnectionController] Failed to set relay-only policy:", error);
|
|
15848
15863
|
}
|
|
15849
15864
|
this.setupEventListeners();
|
|
15850
15865
|
this._isNegotiating$.next(true);
|
|
15851
|
-
logger$
|
|
15866
|
+
logger$15.debug(`[RTCPeerConnectionController] Triggering ICE restart${relayOnly ? " (relay-only)" : ""}.`);
|
|
15852
15867
|
try {
|
|
15853
15868
|
const offer = await this.peerConnection.createOffer({ iceRestart: true });
|
|
15854
15869
|
await this.setLocalDescription(offer);
|
|
15855
15870
|
} catch (error) {
|
|
15856
|
-
logger$
|
|
15871
|
+
logger$15.error("[RTCPeerConnectionController] ICE restart offer failed:", error);
|
|
15857
15872
|
this._errors$.next(error);
|
|
15858
15873
|
this.negotiationEnded();
|
|
15859
15874
|
if (policyChanged) this.restoreIceTransportPolicy();
|
|
@@ -15867,9 +15882,9 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
15867
15882
|
...this.peerConnection.getConfiguration(),
|
|
15868
15883
|
iceTransportPolicy: this.options.relayOnly ? "relay" : "all"
|
|
15869
15884
|
});
|
|
15870
|
-
logger$
|
|
15885
|
+
logger$15.debug("[RTCPeerConnectionController] ICE transport policy restored");
|
|
15871
15886
|
} catch (error) {
|
|
15872
|
-
logger$
|
|
15887
|
+
logger$15.warn("[RTCPeerConnectionController] Failed to restore ICE transport policy:", error);
|
|
15873
15888
|
}
|
|
15874
15889
|
}
|
|
15875
15890
|
/**
|
|
@@ -15881,13 +15896,13 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
15881
15896
|
await this.setupRemoteTracks();
|
|
15882
15897
|
}
|
|
15883
15898
|
async setupLocalTracks() {
|
|
15884
|
-
logger$
|
|
15899
|
+
logger$15.debug("[RTCPeerConnectionController] Setting up local tracks/transceivers.");
|
|
15885
15900
|
const localStream = this.localStream ?? await this.localStreamController.buildLocalStream();
|
|
15886
15901
|
if (this.transceiverController?.useAddStream ?? false) {
|
|
15887
|
-
logger$
|
|
15902
|
+
logger$15.warn("[RTCPeerConnectionController] Using deprecated addStream API to add local stream.");
|
|
15888
15903
|
this.peerConnection?.addStream(localStream);
|
|
15889
15904
|
if (!this.isNegotiating) {
|
|
15890
|
-
logger$
|
|
15905
|
+
logger$15.debug("[RTCPeerConnectionController] Forcing negotiationneeded after local tracks setup.");
|
|
15891
15906
|
this.negotiationNeeded$.next();
|
|
15892
15907
|
}
|
|
15893
15908
|
return;
|
|
@@ -15903,7 +15918,7 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
15903
15918
|
const transceivers = (kind === "audio" ? this.transceiverController?.audioTransceivers : this.transceiverController?.videoTransceivers) ?? [];
|
|
15904
15919
|
await this.transceiverController?.setupTransceiverSender(track, localStream, transceivers[index]);
|
|
15905
15920
|
} else {
|
|
15906
|
-
logger$
|
|
15921
|
+
logger$15.debug(`[RTCPeerConnectionController] Using addTrack for local ${kind} track:`, track.id);
|
|
15907
15922
|
this.peerConnection?.addTrack(track, localStream);
|
|
15908
15923
|
}
|
|
15909
15924
|
}
|
|
@@ -15920,7 +15935,7 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
15920
15935
|
async setupRemoteTracks() {
|
|
15921
15936
|
if (!this.peerConnection) throw new DependencyError("RTCPeerConnection is not initialized");
|
|
15922
15937
|
this.peerConnection.ontrack = (event) => {
|
|
15923
|
-
logger$
|
|
15938
|
+
logger$15.debug("[RTCPeerConnectionController] Remote track received:", event.track.kind);
|
|
15924
15939
|
if (event.streams[0]) this._remoteStream$.next(event.streams[0]);
|
|
15925
15940
|
else {
|
|
15926
15941
|
const existingTracks = this._remoteStream$.value?.getTracks() ?? [];
|
|
@@ -15946,9 +15961,9 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
15946
15961
|
try {
|
|
15947
15962
|
const localStream = this.localStreamController.addTrack(track);
|
|
15948
15963
|
this.peerConnection.addTrack(track, localStream);
|
|
15949
|
-
logger$
|
|
15964
|
+
logger$15.debug(`[RTCPeerConnectionController] ${track.kind} track added:`, track.id);
|
|
15950
15965
|
} catch (error) {
|
|
15951
|
-
logger$
|
|
15966
|
+
logger$15.error(`[RTCPeerConnectionController] Failed to add ${track.kind} track:`, error);
|
|
15952
15967
|
this._errors$.next(error);
|
|
15953
15968
|
throw error;
|
|
15954
15969
|
}
|
|
@@ -15965,15 +15980,15 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
15965
15980
|
}
|
|
15966
15981
|
const sender = this.peerConnection.getSenders().find((sender$1) => sender$1.track?.id === trackId);
|
|
15967
15982
|
if (!sender) {
|
|
15968
|
-
logger$
|
|
15983
|
+
logger$15.debug(`[RTCPeerConnectionController] track not found: ${trackId}`);
|
|
15969
15984
|
return;
|
|
15970
15985
|
}
|
|
15971
15986
|
try {
|
|
15972
15987
|
this.peerConnection.removeTrack(sender);
|
|
15973
15988
|
this.localStreamController.removeTrack(trackId);
|
|
15974
|
-
logger$
|
|
15989
|
+
logger$15.debug(`[RTCPeerConnectionController] ${sender.track?.kind} track removed:`, trackId);
|
|
15975
15990
|
} catch (error) {
|
|
15976
|
-
logger$
|
|
15991
|
+
logger$15.error(`[RTCPeerConnectionController] Failed to remove ${sender.track?.kind} track:`, error);
|
|
15977
15992
|
this._errors$.next(error);
|
|
15978
15993
|
throw error;
|
|
15979
15994
|
}
|
|
@@ -16000,7 +16015,7 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
16000
16015
|
async replaceAudioTrackWithConstraints(constraints) {
|
|
16001
16016
|
const senders = this.peerConnection?.getSenders().filter((s) => s.track?.kind === "audio" && s.track.readyState === "live");
|
|
16002
16017
|
if (!senders || senders.length === 0) {
|
|
16003
|
-
logger$
|
|
16018
|
+
logger$15.warn("[RTCPeerConnectionController] No live audio sender to replace");
|
|
16004
16019
|
return;
|
|
16005
16020
|
}
|
|
16006
16021
|
for (const sender of senders) {
|
|
@@ -16018,7 +16033,7 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
16018
16033
|
const newTrack = (await this.getUserMedia({ audio: mergedConstraints })).getAudioTracks()[0];
|
|
16019
16034
|
await sender.replaceTrack(newTrack);
|
|
16020
16035
|
this.localStreamController.addTrack(newTrack);
|
|
16021
|
-
logger$
|
|
16036
|
+
logger$15.debug(`[RTCPeerConnectionController] Audio track replaced for server-pushed params. New track: ${newTrack.id}`);
|
|
16022
16037
|
}
|
|
16023
16038
|
}
|
|
16024
16039
|
/**
|
|
@@ -16026,7 +16041,7 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
16026
16041
|
* Completes all observables to prevent memory leaks.
|
|
16027
16042
|
*/
|
|
16028
16043
|
destroy() {
|
|
16029
|
-
logger$
|
|
16044
|
+
logger$15.debug(`[RTCPeerConnectionController] Destroying RTCPeerConnectionController. ${this.propose}`);
|
|
16030
16045
|
this.removeConnectionTimer();
|
|
16031
16046
|
this._iceGatheringController?.destroy();
|
|
16032
16047
|
this.localStreamController.destroy();
|
|
@@ -16050,7 +16065,7 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
16050
16065
|
}
|
|
16051
16066
|
stopRemoteTracks() {
|
|
16052
16067
|
this._remoteStream$.value?.getTracks().forEach((track) => {
|
|
16053
|
-
logger$
|
|
16068
|
+
logger$15.debug(`[RTCPeerConnectionController] Stopping remote track: ${track.kind}`);
|
|
16054
16069
|
track.stop();
|
|
16055
16070
|
});
|
|
16056
16071
|
}
|
|
@@ -16067,7 +16082,7 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
16067
16082
|
...params,
|
|
16068
16083
|
sdp: finalRemote
|
|
16069
16084
|
};
|
|
16070
|
-
logger$
|
|
16085
|
+
logger$15.debug("[RTCPeerConnectionController] Setting remote description:", answer);
|
|
16071
16086
|
return this.peerConnection.setRemoteDescription(answer);
|
|
16072
16087
|
}
|
|
16073
16088
|
};
|
|
@@ -16105,8 +16120,8 @@ function isVertoPingInnerParams(value) {
|
|
|
16105
16120
|
|
|
16106
16121
|
//#endregion
|
|
16107
16122
|
//#region src/managers/VertoManager.ts
|
|
16108
|
-
var import_cjs$
|
|
16109
|
-
const logger$
|
|
16123
|
+
var import_cjs$13 = require_cjs();
|
|
16124
|
+
const logger$14 = getLogger();
|
|
16110
16125
|
var VertoManager = class extends Destroyable {
|
|
16111
16126
|
constructor(callSession) {
|
|
16112
16127
|
super();
|
|
@@ -16132,6 +16147,7 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16132
16147
|
this._screenShareTimeoutMs = 5e4;
|
|
16133
16148
|
this._nodeId$ = this.createBehaviorSubject(options.nodeId ?? null);
|
|
16134
16149
|
this.onError = options.onError;
|
|
16150
|
+
this.onModifyFailed = options.onModifyFailed;
|
|
16135
16151
|
this.initSubscriptions();
|
|
16136
16152
|
this.initMainPeerConnection();
|
|
16137
16153
|
}
|
|
@@ -16144,7 +16160,7 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16144
16160
|
try {
|
|
16145
16161
|
await this.executeVerto(vertoModifyMessage);
|
|
16146
16162
|
} catch (error) {
|
|
16147
|
-
logger$
|
|
16163
|
+
logger$14.warn("[WebRTCManager] Call might already be disconnected, error sending Verto hold:", error);
|
|
16148
16164
|
throw error;
|
|
16149
16165
|
}
|
|
16150
16166
|
}
|
|
@@ -16157,7 +16173,7 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16157
16173
|
try {
|
|
16158
16174
|
await this.executeVerto(vertoModifyMessage);
|
|
16159
16175
|
} catch (error) {
|
|
16160
|
-
logger$
|
|
16176
|
+
logger$14.warn("[WebRTCManager] Call might already be disconnected, error sending Verto unhold:", error);
|
|
16161
16177
|
throw error;
|
|
16162
16178
|
}
|
|
16163
16179
|
}
|
|
@@ -16197,7 +16213,7 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16197
16213
|
return rtcPeerConnection;
|
|
16198
16214
|
}
|
|
16199
16215
|
get signalingStatus$() {
|
|
16200
|
-
return this.cachedObservable("signalingStatus$", () => (0, import_cjs$
|
|
16216
|
+
return this.cachedObservable("signalingStatus$", () => (0, import_cjs$13.merge)(this._signalingStatus$.pipe(filterNull()), this.mainPeerConnection.connectionState$.pipe((0, import_cjs$13.filter)((connectionState) => [
|
|
16201
16217
|
"connected",
|
|
16202
16218
|
"disconnected",
|
|
16203
16219
|
"failed"
|
|
@@ -16210,7 +16226,7 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16210
16226
|
if (event.member_id) this.setSelfIdIfNull(event.member_id);
|
|
16211
16227
|
});
|
|
16212
16228
|
this.subscribeTo(this.vertoMedia$, (event) => {
|
|
16213
|
-
logger$
|
|
16229
|
+
logger$14.debug("[WebRTCManager] Received Verto media event (early media SDP):", event);
|
|
16214
16230
|
this._signalingStatus$.next("ringing");
|
|
16215
16231
|
const { sdp, callID } = event;
|
|
16216
16232
|
this._rtcPeerConnectionsMap.get(callID)?.updateAnswerStatus({
|
|
@@ -16219,7 +16235,7 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16219
16235
|
});
|
|
16220
16236
|
});
|
|
16221
16237
|
this.subscribeTo(this.vertoAnswer$, (event) => {
|
|
16222
|
-
logger$
|
|
16238
|
+
logger$14.debug("[WebRTCManager] Received Verto answer event:", event);
|
|
16223
16239
|
this._signalingStatus$.next("connecting");
|
|
16224
16240
|
const { sdp, callID } = event;
|
|
16225
16241
|
this._rtcPeerConnectionsMap.get(callID)?.updateAnswerStatus({
|
|
@@ -16228,7 +16244,7 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16228
16244
|
});
|
|
16229
16245
|
});
|
|
16230
16246
|
this.subscribeTo(this.vertoMediaParams$, (event) => {
|
|
16231
|
-
logger$
|
|
16247
|
+
logger$14.debug("[WebRTCManager] Received Verto mediaParams event:", event);
|
|
16232
16248
|
const { mediaParams, callID } = event;
|
|
16233
16249
|
const rtcPeerConnController = this._rtcPeerConnectionsMap.get(callID);
|
|
16234
16250
|
const { audio, video } = mediaParams;
|
|
@@ -16242,13 +16258,13 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16242
16258
|
timestamp: Date.now()
|
|
16243
16259
|
});
|
|
16244
16260
|
} catch (error) {
|
|
16245
|
-
logger$
|
|
16261
|
+
logger$14.warn("[WebRTCManager] Error applying server-pushed media params:", error);
|
|
16246
16262
|
this.onError?.(error instanceof Error ? error : new Error(String(error), { cause: error }));
|
|
16247
16263
|
}
|
|
16248
16264
|
})();
|
|
16249
16265
|
});
|
|
16250
16266
|
this.subscribeTo(this.vertoPing$, (vertoPing) => {
|
|
16251
|
-
this.attachManager.attach(this.
|
|
16267
|
+
this.attachManager.attach(this.buildAttachableCall());
|
|
16252
16268
|
this.sendVertoPong(vertoPing);
|
|
16253
16269
|
});
|
|
16254
16270
|
}
|
|
@@ -16264,13 +16280,13 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16264
16280
|
*/
|
|
16265
16281
|
setNodeIdIfNull(nodeId) {
|
|
16266
16282
|
if (!this._nodeId$.value && nodeId) {
|
|
16267
|
-
logger$
|
|
16283
|
+
logger$14.debug(`[WebRTCManager] Early node_id set: ${nodeId}`);
|
|
16268
16284
|
this._nodeId$.next(nodeId);
|
|
16269
16285
|
}
|
|
16270
16286
|
}
|
|
16271
16287
|
setSelfIdIfNull(selfId) {
|
|
16272
16288
|
if (!this._selfId$.value && selfId) {
|
|
16273
|
-
logger$
|
|
16289
|
+
logger$14.debug(`[WebRTCManager] Early selfId set: ${selfId}`);
|
|
16274
16290
|
this._selfId$.next(selfId);
|
|
16275
16291
|
}
|
|
16276
16292
|
}
|
|
@@ -16279,7 +16295,7 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16279
16295
|
const vertoPongMessage = VertoPong({ ...vertoPing });
|
|
16280
16296
|
await this.executeVerto(vertoPongMessage);
|
|
16281
16297
|
} catch (error) {
|
|
16282
|
-
logger$
|
|
16298
|
+
logger$14.warn("[WebRTCManager] Call might disconnect, error sending Verto pong:", error);
|
|
16283
16299
|
this.onError?.(new VertoPongError(error));
|
|
16284
16300
|
}
|
|
16285
16301
|
}
|
|
@@ -16289,7 +16305,7 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16289
16305
|
if (audio) await this.mainPeerConnection.updateSendersConstraints("audio", audio);
|
|
16290
16306
|
if (video) await this.mainPeerConnection.updateSendersConstraints("video", video);
|
|
16291
16307
|
} catch (error) {
|
|
16292
|
-
logger$
|
|
16308
|
+
logger$14.warn("[WebRTCManager] Error updating media constraints:", error);
|
|
16293
16309
|
this.onError?.(error instanceof Error ? error : new Error(String(error), { cause: error }));
|
|
16294
16310
|
throw error;
|
|
16295
16311
|
}
|
|
@@ -16297,6 +16313,15 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16297
16313
|
get selfId() {
|
|
16298
16314
|
return this._selfId$.value;
|
|
16299
16315
|
}
|
|
16316
|
+
/** Build an AttachableCall from the current call state. */
|
|
16317
|
+
buildAttachableCall(idOverride) {
|
|
16318
|
+
return {
|
|
16319
|
+
nodeId: this.nodeId ?? void 0,
|
|
16320
|
+
id: idOverride ?? this.webRtcCallSession.id,
|
|
16321
|
+
to: this.webRtcCallSession.to,
|
|
16322
|
+
mediaDirections: this.webRtcCallSession.mediaDirections
|
|
16323
|
+
};
|
|
16324
|
+
}
|
|
16300
16325
|
/**
|
|
16301
16326
|
* Request a video keyframe via RTCP PLI/FIR.
|
|
16302
16327
|
*
|
|
@@ -16310,20 +16335,20 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16310
16335
|
try {
|
|
16311
16336
|
const pc = this.mainPeerConnection.peerConnection;
|
|
16312
16337
|
if (!pc) {
|
|
16313
|
-
logger$
|
|
16338
|
+
logger$14.warn("[WebRTCManager] No peer connection for keyframe request");
|
|
16314
16339
|
return;
|
|
16315
16340
|
}
|
|
16316
16341
|
const videoReceiver = pc.getReceivers().find((r) => r.track.kind === "video");
|
|
16317
16342
|
if (!videoReceiver) {
|
|
16318
|
-
logger$
|
|
16343
|
+
logger$14.warn("[WebRTCManager] No video receiver for keyframe request");
|
|
16319
16344
|
return;
|
|
16320
16345
|
}
|
|
16321
16346
|
if (typeof videoReceiver.requestKeyFrame === "function") {
|
|
16322
16347
|
videoReceiver.requestKeyFrame();
|
|
16323
|
-
logger$
|
|
16324
|
-
} else logger$
|
|
16348
|
+
logger$14.debug("[WebRTCManager] Keyframe requested via RTCRtpReceiver.requestKeyFrame()");
|
|
16349
|
+
} else logger$14.debug("[WebRTCManager] requestKeyFrame() not supported, skipping");
|
|
16325
16350
|
} catch (error) {
|
|
16326
|
-
logger$
|
|
16351
|
+
logger$14.warn("[WebRTCManager] Keyframe request failed (non-fatal):", error);
|
|
16327
16352
|
}
|
|
16328
16353
|
}
|
|
16329
16354
|
/**
|
|
@@ -16341,13 +16366,13 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16341
16366
|
try {
|
|
16342
16367
|
const controller = this.mainPeerConnection;
|
|
16343
16368
|
if (!controller.peerConnection) {
|
|
16344
|
-
logger$
|
|
16369
|
+
logger$14.warn("[WebRTCManager] No peer connection for ICE restart");
|
|
16345
16370
|
return;
|
|
16346
16371
|
}
|
|
16347
16372
|
await controller.triggerIceRestart(relayOnly);
|
|
16348
|
-
logger$
|
|
16373
|
+
logger$14.info(`[WebRTCManager] ICE restart initiated${relayOnly ? " (relay-only)" : ""}`);
|
|
16349
16374
|
} catch (error) {
|
|
16350
|
-
logger$
|
|
16375
|
+
logger$14.error("[WebRTCManager] ICE restart failed:", error);
|
|
16351
16376
|
throw error;
|
|
16352
16377
|
}
|
|
16353
16378
|
}
|
|
@@ -16365,13 +16390,13 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16365
16390
|
const entries = Array.from(this._rtcPeerConnectionsMap.entries());
|
|
16366
16391
|
for (const [id, controller] of entries) try {
|
|
16367
16392
|
if (!controller.peerConnection) {
|
|
16368
|
-
logger$
|
|
16393
|
+
logger$14.debug(`[WebRTCManager] No peer connection for leg ${id}, skipping ICE restart`);
|
|
16369
16394
|
continue;
|
|
16370
16395
|
}
|
|
16371
16396
|
await controller.triggerIceRestart(relayOnly);
|
|
16372
|
-
logger$
|
|
16397
|
+
logger$14.info(`[WebRTCManager] ICE restart initiated for leg ${id}${relayOnly ? " (relay-only)" : ""}`);
|
|
16373
16398
|
} catch (error) {
|
|
16374
|
-
logger$
|
|
16399
|
+
logger$14.warn(`[WebRTCManager] ICE restart failed for leg ${id}:`, error);
|
|
16375
16400
|
}
|
|
16376
16401
|
}
|
|
16377
16402
|
/**
|
|
@@ -16383,7 +16408,7 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16383
16408
|
requestKeyframeAll() {
|
|
16384
16409
|
for (const [id, controller] of this._rtcPeerConnectionsMap) {
|
|
16385
16410
|
if (controller.isScreenShare) {
|
|
16386
|
-
logger$
|
|
16411
|
+
logger$14.debug(`[WebRTCManager] Skipping keyframe for send-only screen share leg ${id}`);
|
|
16387
16412
|
continue;
|
|
16388
16413
|
}
|
|
16389
16414
|
try {
|
|
@@ -16393,33 +16418,33 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16393
16418
|
if (!videoReceiver) continue;
|
|
16394
16419
|
if (typeof videoReceiver.requestKeyFrame === "function") {
|
|
16395
16420
|
videoReceiver.requestKeyFrame();
|
|
16396
|
-
logger$
|
|
16421
|
+
logger$14.debug(`[WebRTCManager] Keyframe requested for leg ${id}`);
|
|
16397
16422
|
}
|
|
16398
16423
|
} catch (error) {
|
|
16399
|
-
logger$
|
|
16424
|
+
logger$14.warn(`[WebRTCManager] Keyframe request failed for leg ${id} (non-fatal):`, error);
|
|
16400
16425
|
}
|
|
16401
16426
|
}
|
|
16402
16427
|
}
|
|
16403
16428
|
get callJoinedEvent$() {
|
|
16404
|
-
return this.webRtcCallSession.callEvent$.pipe((0, import_cjs$
|
|
16429
|
+
return this.webRtcCallSession.callEvent$.pipe((0, import_cjs$13.filter)(isCallJoinedPayload), (0, import_cjs$13.takeUntil)(this.destroyed$));
|
|
16405
16430
|
}
|
|
16406
16431
|
get vertoMedia$() {
|
|
16407
|
-
return this.webRtcCallSession.webrtcMessages$.pipe(filterAs(isVertoMediaInnerParams, "params"), (0, import_cjs$
|
|
16432
|
+
return this.webRtcCallSession.webrtcMessages$.pipe(filterAs(isVertoMediaInnerParams, "params"), (0, import_cjs$13.takeUntil)(this.destroyed$));
|
|
16408
16433
|
}
|
|
16409
16434
|
get vertoAnswer$() {
|
|
16410
|
-
return this.cachedObservable("vertoAnswer$", () => this.webRtcCallSession.webrtcMessages$.pipe(filterAs(isVertoAnswerInnerParams, "params"), (0, import_cjs$
|
|
16435
|
+
return this.cachedObservable("vertoAnswer$", () => this.webRtcCallSession.webrtcMessages$.pipe(filterAs(isVertoAnswerInnerParams, "params"), (0, import_cjs$13.takeUntil)(this.destroyed$)));
|
|
16411
16436
|
}
|
|
16412
16437
|
get vertoMediaParams$() {
|
|
16413
|
-
return this.cachedObservable("vertoMediaParams$", () => this.webRtcCallSession.webrtcMessages$.pipe(filterAs(isVertoMediaParamsInnerParams, "params"), (0, import_cjs$
|
|
16438
|
+
return this.cachedObservable("vertoMediaParams$", () => this.webRtcCallSession.webrtcMessages$.pipe(filterAs(isVertoMediaParamsInnerParams, "params"), (0, import_cjs$13.takeUntil)(this.destroyed$)));
|
|
16414
16439
|
}
|
|
16415
16440
|
get vertoBye$() {
|
|
16416
|
-
return this.cachedObservable("vertoBye$", () => this.webRtcCallSession.webrtcMessages$.pipe(filterAs(isVertoByeMessage, "params"), (0, import_cjs$
|
|
16441
|
+
return this.cachedObservable("vertoBye$", () => this.webRtcCallSession.webrtcMessages$.pipe(filterAs(isVertoByeMessage, "params"), (0, import_cjs$13.takeUntil)(this.destroyed$)));
|
|
16417
16442
|
}
|
|
16418
16443
|
get vertoAttach$() {
|
|
16419
|
-
return this.cachedObservable("vertoAttach$", () => this.webRtcCallSession.webrtcMessages$.pipe(filterAs(isVertoAttachMessage, "params"), (0, import_cjs$
|
|
16444
|
+
return this.cachedObservable("vertoAttach$", () => this.webRtcCallSession.webrtcMessages$.pipe(filterAs(isVertoAttachMessage, "params"), (0, import_cjs$13.takeUntil)(this.destroyed$)));
|
|
16420
16445
|
}
|
|
16421
16446
|
get vertoPing$() {
|
|
16422
|
-
return this.cachedObservable("vertoPing$", () => this.webRtcCallSession.webrtcMessages$.pipe(filterAs(isVertoPingInnerParams, "params"), (0, import_cjs$
|
|
16447
|
+
return this.cachedObservable("vertoPing$", () => this.webRtcCallSession.webrtcMessages$.pipe(filterAs(isVertoPingInnerParams, "params"), (0, import_cjs$13.takeUntil)(this.destroyed$)));
|
|
16423
16448
|
}
|
|
16424
16449
|
async executeVerto(message, optionals = {}) {
|
|
16425
16450
|
const webrtcVertoMessage = WebrtcVerto({
|
|
@@ -16444,7 +16469,7 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16444
16469
|
}
|
|
16445
16470
|
async sendLocalDescription(message, rtcPeerConnController) {
|
|
16446
16471
|
const vertoMethod = message.method;
|
|
16447
|
-
const optionalsParams = this.getSendLocalSDPOptionalParams(rtcPeerConnController,
|
|
16472
|
+
const optionalsParams = this.getSendLocalSDPOptionalParams(rtcPeerConnController, message);
|
|
16448
16473
|
try {
|
|
16449
16474
|
const response = await this.executeVerto(message, optionalsParams);
|
|
16450
16475
|
switch (vertoMethod) {
|
|
@@ -16457,8 +16482,9 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16457
16482
|
default:
|
|
16458
16483
|
}
|
|
16459
16484
|
} catch (error) {
|
|
16460
|
-
logger$
|
|
16485
|
+
logger$14.error(`[WebRTCManager] Error sending Verto ${vertoMethod}:`, error);
|
|
16461
16486
|
this.onError?.(error instanceof Error ? error : new Error(String(error), { cause: error }));
|
|
16487
|
+
if (vertoMethod === "verto.modify") this.onModifyFailed?.();
|
|
16462
16488
|
}
|
|
16463
16489
|
}
|
|
16464
16490
|
async processModifyResponse(response, rtcPeerConnController) {
|
|
@@ -16471,7 +16497,7 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16471
16497
|
sdp
|
|
16472
16498
|
});
|
|
16473
16499
|
} catch (error) {
|
|
16474
|
-
logger$
|
|
16500
|
+
logger$14.warn("[WebRTCManager] Error processing modify response:", error);
|
|
16475
16501
|
const modifyError = error instanceof Error ? error : new Error(String(error), { cause: error });
|
|
16476
16502
|
this.onError?.(modifyError);
|
|
16477
16503
|
}
|
|
@@ -16483,19 +16509,24 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16483
16509
|
this._nodeId$.next(getValueFrom(response, "result.node_id") ?? null);
|
|
16484
16510
|
const memberId = getValueFrom(response, "result.result.result.memberID") ?? null;
|
|
16485
16511
|
const callId = getValueFrom(response, "result.result.result.callID") ?? null;
|
|
16486
|
-
logger$
|
|
16512
|
+
logger$14.debug("[WebRTCManager] Verto invite response:", {
|
|
16487
16513
|
callId,
|
|
16488
16514
|
memberId,
|
|
16489
16515
|
response
|
|
16490
16516
|
});
|
|
16491
16517
|
this._selfId$.next(memberId);
|
|
16492
16518
|
rtcPeerConnController.setMemberId(memberId);
|
|
16493
|
-
if (callId)
|
|
16494
|
-
|
|
16495
|
-
|
|
16496
|
-
logger$
|
|
16519
|
+
if (callId) {
|
|
16520
|
+
this.webRtcCallSession.addCallId(callId);
|
|
16521
|
+
this.attachManager.attach(this.buildAttachableCall(callId));
|
|
16522
|
+
} else logger$14.warn("[WebRTCManager] Cannot attach call, missing callId:", {
|
|
16523
|
+
nodeId: this.nodeId,
|
|
16524
|
+
callId
|
|
16525
|
+
});
|
|
16526
|
+
logger$14.info("[WebRTCManager] Verto invite successful");
|
|
16527
|
+
logger$14.debug(`[WebRTCManager] nodeid: ${this._nodeId$.value}, selfId: ${this._selfId$.value}`);
|
|
16497
16528
|
} else {
|
|
16498
|
-
logger$
|
|
16529
|
+
logger$14.error("[WebRTCManager] Verto invite failed:", response);
|
|
16499
16530
|
const inviteError = response.error ? new JSONRPCError(response.error.code, response.error.message, response.error.data) : /* @__PURE__ */ new Error("Verto invite failed: unexpected response");
|
|
16500
16531
|
this.onError?.(inviteError);
|
|
16501
16532
|
}
|
|
@@ -16540,17 +16571,17 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16540
16571
|
if (options.initOffer) this.handleInboundAnswer(rtcPeerConnController);
|
|
16541
16572
|
}
|
|
16542
16573
|
async handleInboundAnswer(rtcPeerConnController) {
|
|
16543
|
-
logger$
|
|
16544
|
-
const vertoByeOrAccepted = await (0, import_cjs$
|
|
16574
|
+
logger$14.debug("[WebRTCManager] Waiting for inbound call to be accepted or rejected");
|
|
16575
|
+
const vertoByeOrAccepted = await (0, import_cjs$13.firstValueFrom)((0, import_cjs$13.race)(this.vertoBye$, this.webRtcCallSession.answered$).pipe((0, import_cjs$13.takeUntil)(this.destroyed$))).catch(() => null);
|
|
16545
16576
|
if (vertoByeOrAccepted === null) {
|
|
16546
|
-
logger$
|
|
16577
|
+
logger$14.debug("[WebRTCManager] Inbound answer handler aborted (destroyed).");
|
|
16547
16578
|
return;
|
|
16548
16579
|
}
|
|
16549
16580
|
if (isVertoByeMessage(vertoByeOrAccepted)) {
|
|
16550
|
-
logger$
|
|
16581
|
+
logger$14.info("[WebRTCManager] Inbound call ended by remote before answer.");
|
|
16551
16582
|
this.callSession?.destroy();
|
|
16552
16583
|
} else if (!vertoByeOrAccepted) {
|
|
16553
|
-
logger$
|
|
16584
|
+
logger$14.info("[WebRTCManager] Inbound call rejected by user.");
|
|
16554
16585
|
try {
|
|
16555
16586
|
await this.bye("USER_BUSY");
|
|
16556
16587
|
} finally {
|
|
@@ -16558,21 +16589,22 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16558
16589
|
this.callSession?.destroy();
|
|
16559
16590
|
}
|
|
16560
16591
|
} else {
|
|
16561
|
-
logger$
|
|
16592
|
+
logger$14.debug("[WebRTCManager] Inbound call accepted, creating SDP answer");
|
|
16562
16593
|
const answerOptions = this.webRtcCallSession.answerMediaOptions;
|
|
16563
16594
|
try {
|
|
16564
16595
|
await rtcPeerConnController.acceptInbound(answerOptions);
|
|
16565
16596
|
} catch (error) {
|
|
16566
|
-
logger$
|
|
16597
|
+
logger$14.error("[WebRTCManager] Error creating inbound answer:", error);
|
|
16567
16598
|
this.onError?.(error instanceof Error ? error : new Error(String(error), { cause: error }));
|
|
16568
16599
|
}
|
|
16569
16600
|
}
|
|
16570
16601
|
}
|
|
16571
16602
|
setupVertoAttachHandler() {
|
|
16572
16603
|
this.subscribeTo(this.vertoAttach$, async (vertoAttach) => {
|
|
16573
|
-
logger$
|
|
16604
|
+
logger$14.debug("[WebRTCManager] Received Verto attach event for existing call:", vertoAttach);
|
|
16574
16605
|
const { callID } = vertoAttach;
|
|
16575
16606
|
await this.attachManager.attach({
|
|
16607
|
+
nodeId: this.nodeId ?? void 0,
|
|
16576
16608
|
id: callID,
|
|
16577
16609
|
to: vertoAttach.callee_id_number,
|
|
16578
16610
|
mediaDirections: {
|
|
@@ -16583,12 +16615,12 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16583
16615
|
});
|
|
16584
16616
|
}
|
|
16585
16617
|
initObservables(rtcPeerConnController) {
|
|
16586
|
-
this.mediaDirections$ = rtcPeerConnController.connectionState$.pipe((0, import_cjs$
|
|
16587
|
-
this.localStream$ = rtcPeerConnController.localStream$.pipe(filterNull(), (0, import_cjs$
|
|
16588
|
-
this.remoteStream$ = rtcPeerConnController.remoteStream$.pipe(filterNull(), (0, import_cjs$
|
|
16618
|
+
this.mediaDirections$ = rtcPeerConnController.connectionState$.pipe((0, import_cjs$13.filter)((state) => state === "connected"), (0, import_cjs$13.map)(() => rtcPeerConnController.mediaDirections), (0, import_cjs$13.startWith)(rtcPeerConnController.mediaDirections), (0, import_cjs$13.takeUntil)(this.destroyed$));
|
|
16619
|
+
this.localStream$ = rtcPeerConnController.localStream$.pipe(filterNull(), (0, import_cjs$13.takeUntil)(this.destroyed$));
|
|
16620
|
+
this.remoteStream$ = rtcPeerConnController.remoteStream$.pipe(filterNull(), (0, import_cjs$13.takeUntil)(this.destroyed$));
|
|
16589
16621
|
}
|
|
16590
16622
|
setupLocalDescriptionHandler(rtcPeerConnController) {
|
|
16591
|
-
this.subscribeTo(rtcPeerConnController.localDescription$.pipe((0, import_cjs$
|
|
16623
|
+
this.subscribeTo(rtcPeerConnController.localDescription$.pipe((0, import_cjs$13.filter)((description) => description !== null), (0, import_cjs$13.takeUntil)(this.destroyed$)), (description) => {
|
|
16592
16624
|
const { type, sdp } = description;
|
|
16593
16625
|
const dialogParams = this.dialogParams(rtcPeerConnController);
|
|
16594
16626
|
const initial = !rtcPeerConnController.firstSDPExchangeCompleted;
|
|
@@ -16617,11 +16649,11 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16617
16649
|
setupVertoByeHandler() {
|
|
16618
16650
|
this.subscribeTo(this.vertoBye$, () => {
|
|
16619
16651
|
this._signalingStatus$.next("disconnected");
|
|
16620
|
-
this.attachManager.detach(this.
|
|
16652
|
+
this.attachManager.detach(this.buildAttachableCall());
|
|
16621
16653
|
this.callSession?.destroy();
|
|
16622
16654
|
});
|
|
16623
16655
|
}
|
|
16624
|
-
getSendLocalSDPOptionalParams(rtcPeerConnController,
|
|
16656
|
+
getSendLocalSDPOptionalParams(rtcPeerConnController, vertoMessage) {
|
|
16625
16657
|
let subscribe = void 0;
|
|
16626
16658
|
if (!rtcPeerConnController.firstSDPExchangeCompleted) {
|
|
16627
16659
|
subscribe = [];
|
|
@@ -16629,7 +16661,7 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16629
16661
|
else if (rtcPeerConnController.isAdditionalDevice) subscribe.push(...PreferencesContainer.instance.inviteSubscribeAdditionalDevice);
|
|
16630
16662
|
else if (rtcPeerConnController.isScreenShare) subscribe.push(...PreferencesContainer.instance.inviteSubscribeScreenshare);
|
|
16631
16663
|
}
|
|
16632
|
-
const isInvite =
|
|
16664
|
+
const isInvite = isVertoInviteMessage(vertoMessage);
|
|
16633
16665
|
const isReattach = isInvite && this.webRtcCallSession.options.reattach;
|
|
16634
16666
|
return {
|
|
16635
16667
|
callID: rtcPeerConnController.id,
|
|
@@ -16638,13 +16670,13 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16638
16670
|
};
|
|
16639
16671
|
}
|
|
16640
16672
|
async sendLocalDescriptionOnceAccepted(vertoMessageRequest, rtcPeerConnectionController) {
|
|
16641
|
-
logger$
|
|
16642
|
-
const vertoByeOrAccepted = await (0, import_cjs$
|
|
16673
|
+
logger$14.debug("[WebRTCManager] Waiting for call to be accepted or ended before sending answer");
|
|
16674
|
+
const vertoByeOrAccepted = await (0, import_cjs$13.firstValueFrom)((0, import_cjs$13.race)(this.vertoBye$, this.webRtcCallSession.answered$));
|
|
16643
16675
|
if (isVertoByeMessage(vertoByeOrAccepted)) {
|
|
16644
|
-
logger$
|
|
16676
|
+
logger$14.info("[WebRTCManager] Call ended before answer was sent.");
|
|
16645
16677
|
this.callSession?.destroy();
|
|
16646
16678
|
} else if (!vertoByeOrAccepted) {
|
|
16647
|
-
logger$
|
|
16679
|
+
logger$14.info("[WebRTCManager] Call was not accepted, sending verto.bye.");
|
|
16648
16680
|
try {
|
|
16649
16681
|
await this.bye("USER_BUSY");
|
|
16650
16682
|
} finally {
|
|
@@ -16652,14 +16684,14 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16652
16684
|
this.callSession?.destroy();
|
|
16653
16685
|
}
|
|
16654
16686
|
} else {
|
|
16655
|
-
logger$
|
|
16687
|
+
logger$14.debug("[WebRTCManager] Call accepted, sending answer");
|
|
16656
16688
|
try {
|
|
16657
16689
|
this._signalingStatus$.next("connecting");
|
|
16658
16690
|
await this.sendLocalDescription(vertoMessageRequest, rtcPeerConnectionController);
|
|
16659
16691
|
await rtcPeerConnectionController.updateAnswerStatus({ status: "sent" });
|
|
16660
|
-
await this.attachManager.attach(this.
|
|
16692
|
+
await this.attachManager.attach(this.buildAttachableCall());
|
|
16661
16693
|
} catch (error) {
|
|
16662
|
-
logger$
|
|
16694
|
+
logger$14.error("[WebRTCManager] Error sending Verto answer:", error);
|
|
16663
16695
|
this.onError?.(error instanceof Error ? error : new Error(String(error), { cause: error }));
|
|
16664
16696
|
await rtcPeerConnectionController.updateAnswerStatus({ status: "failed" });
|
|
16665
16697
|
}
|
|
@@ -16748,12 +16780,12 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16748
16780
|
this.subscribeTo(rtcPeerConnController.errors$, (error) => {
|
|
16749
16781
|
this.onError?.(error);
|
|
16750
16782
|
});
|
|
16751
|
-
await (0, import_cjs$
|
|
16783
|
+
await (0, import_cjs$13.firstValueFrom)(rtcPeerConnController.connectionState$.pipe((0, import_cjs$13.filter)((state) => state === "connected"), (0, import_cjs$13.take)(1), (0, import_cjs$13.timeout)(this._screenShareTimeoutMs)));
|
|
16752
16784
|
this._screenShareStatus$.next("started");
|
|
16753
|
-
logger$
|
|
16785
|
+
logger$14.info("[WebRTCManager] Screen share started successfully.");
|
|
16754
16786
|
return rtcPeerConnController.id;
|
|
16755
16787
|
} catch (error) {
|
|
16756
|
-
logger$
|
|
16788
|
+
logger$14.warn("[WebRTCManager] Error initializing additional peer connection:", error);
|
|
16757
16789
|
this.onError?.(error instanceof Error ? error : new Error(String(error), { cause: error }));
|
|
16758
16790
|
if (rtcPeerConnController) rtcPeerConnController.destroy();
|
|
16759
16791
|
this._screenShareStatus$.next("none");
|
|
@@ -16772,9 +16804,9 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16772
16804
|
if (removeTrack) return this.mainPeerConnection.stopTrackSender(removeTrack, { updateTransceiverDirection: true });
|
|
16773
16805
|
}
|
|
16774
16806
|
async removeScreenMedia() {
|
|
16775
|
-
if (!["starting", "started"].includes(this._screenShareStatus$.value)) logger$
|
|
16807
|
+
if (!["starting", "started"].includes(this._screenShareStatus$.value)) logger$14.warn("[WebRTCManager] No active screen share to stop.");
|
|
16776
16808
|
if (!this._screenShareId) {
|
|
16777
|
-
logger$
|
|
16809
|
+
logger$14.debug("[WebRTCManager] No screen share peer connection found.");
|
|
16778
16810
|
return;
|
|
16779
16811
|
}
|
|
16780
16812
|
this._screenShareStatus$.next("stopping");
|
|
@@ -16803,12 +16835,12 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16803
16835
|
dialogParams: this.dialogParams(rtcPeerConnController)
|
|
16804
16836
|
}));
|
|
16805
16837
|
} catch (error) {
|
|
16806
|
-
logger$
|
|
16838
|
+
logger$14.warn("[WebRTCManager] Call might already be disconnected, error sending Verto bye:", error);
|
|
16807
16839
|
throw error;
|
|
16808
16840
|
}
|
|
16809
16841
|
}
|
|
16810
16842
|
async bye(cause) {
|
|
16811
|
-
this.attachManager.detach(this.
|
|
16843
|
+
this.attachManager.detach(this.buildAttachableCall());
|
|
16812
16844
|
const rtcPeerConnController = this._rtcPeerConnectionsMap.get(this.webRtcCallSession.id);
|
|
16813
16845
|
if (rtcPeerConnController) await this.executeVertoBye(rtcPeerConnController, cause);
|
|
16814
16846
|
}
|
|
@@ -16821,7 +16853,7 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16821
16853
|
try {
|
|
16822
16854
|
await this.executeVerto(vertoInfoMessage);
|
|
16823
16855
|
} catch (error) {
|
|
16824
|
-
logger$
|
|
16856
|
+
logger$14.warn("[WebRTCManager] Error sending DTMF digits:", error);
|
|
16825
16857
|
throw error;
|
|
16826
16858
|
}
|
|
16827
16859
|
}
|
|
@@ -16832,10 +16864,10 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16832
16864
|
action: "transfer"
|
|
16833
16865
|
});
|
|
16834
16866
|
try {
|
|
16835
|
-
logger$
|
|
16867
|
+
logger$14.debug("[WebRTCManager] Transferring call with options:", options);
|
|
16836
16868
|
await this.executeVerto(message);
|
|
16837
16869
|
} catch (error) {
|
|
16838
|
-
logger$
|
|
16870
|
+
logger$14.error("[WebRTCManager] Error transferring call:", error);
|
|
16839
16871
|
throw error;
|
|
16840
16872
|
}
|
|
16841
16873
|
}
|
|
@@ -16851,8 +16883,8 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16851
16883
|
|
|
16852
16884
|
//#endregion
|
|
16853
16885
|
//#region src/controllers/RTCStatsMonitor.ts
|
|
16854
|
-
var import_cjs$
|
|
16855
|
-
const logger$
|
|
16886
|
+
var import_cjs$12 = require_cjs();
|
|
16887
|
+
const logger$13 = getLogger();
|
|
16856
16888
|
const DEFAULT_POLLING_INTERVAL_MS = 1e3;
|
|
16857
16889
|
const DEFAULT_BASELINE_SAMPLES = 10;
|
|
16858
16890
|
const DEFAULT_NO_AUDIO_PACKET_THRESHOLD_MS = 2e3;
|
|
@@ -16868,6 +16900,12 @@ function computePacketLossPercent(lost, received) {
|
|
|
16868
16900
|
if (total === 0) return 0;
|
|
16869
16901
|
return lost / total * 100;
|
|
16870
16902
|
}
|
|
16903
|
+
function isInboundRtpStat(stat) {
|
|
16904
|
+
return typeof stat === "object" && stat !== null && "type" in stat && stat.type === "inbound-rtp";
|
|
16905
|
+
}
|
|
16906
|
+
function isCandidatePairStat(stat) {
|
|
16907
|
+
return typeof stat === "object" && stat !== null && "type" in stat && stat.type === "candidate-pair";
|
|
16908
|
+
}
|
|
16871
16909
|
var RTCStatsMonitor = class extends Destroyable {
|
|
16872
16910
|
constructor(peerConnection, config = {}) {
|
|
16873
16911
|
super();
|
|
@@ -16908,7 +16946,7 @@ var RTCStatsMonitor = class extends Destroyable {
|
|
|
16908
16946
|
}
|
|
16909
16947
|
/** Simple boolean health indicator. */
|
|
16910
16948
|
get isNetworkHealthy$() {
|
|
16911
|
-
return this.cachedObservable("isNetworkHealthy$", () => this._networkIssues$.pipe((0, import_cjs$
|
|
16949
|
+
return this.cachedObservable("isNetworkHealthy$", () => this._networkIssues$.pipe((0, import_cjs$12.map)((issues) => issues.length === 0), (0, import_cjs$12.distinctUntilChanged)(), (0, import_cjs$12.takeUntil)(this.destroyed$)));
|
|
16912
16950
|
}
|
|
16913
16951
|
/** Whether the network is currently healthy. */
|
|
16914
16952
|
get isNetworkHealthy() {
|
|
@@ -16924,7 +16962,7 @@ var RTCStatsMonitor = class extends Destroyable {
|
|
|
16924
16962
|
}
|
|
16925
16963
|
/** Emits individual critical issues for the recovery pipeline. */
|
|
16926
16964
|
get criticalIssue$() {
|
|
16927
|
-
return this.cachedObservable("criticalIssue$", () => this._networkIssues$.pipe((0, import_cjs$
|
|
16965
|
+
return this.cachedObservable("criticalIssue$", () => this._networkIssues$.pipe((0, import_cjs$12.mergeMap)((issues) => (0, import_cjs$12.from)(issues.filter((i) => i.severity === "critical"))), (0, import_cjs$12.takeUntil)(this.destroyed$)));
|
|
16928
16966
|
}
|
|
16929
16967
|
/** Emits each raw stats sample extracted from the peer connection. */
|
|
16930
16968
|
get sample$() {
|
|
@@ -16936,32 +16974,32 @@ var RTCStatsMonitor = class extends Destroyable {
|
|
|
16936
16974
|
const now = Date.now();
|
|
16937
16975
|
this.lastAudioPacketChangeTime = now;
|
|
16938
16976
|
this.lastVideoPacketChangeTime = now;
|
|
16939
|
-
logger$
|
|
16940
|
-
this.subscribeTo((0, import_cjs$
|
|
16941
|
-
logger$
|
|
16942
|
-
return import_cjs$
|
|
16943
|
-
}))), (0, import_cjs$
|
|
16944
|
-
this.subscribeTo(this._sample$.pipe((0, import_cjs$
|
|
16977
|
+
logger$13.debug("[RTCStatsMonitor] Starting stats monitoring");
|
|
16978
|
+
this.subscribeTo((0, import_cjs$12.interval)(this.pollingIntervalMs).pipe((0, import_cjs$12.filter)(() => this.running), (0, import_cjs$12.switchMap)(() => (0, import_cjs$12.from)(this.peerConnection.getStats()).pipe((0, import_cjs$12.catchError)((err) => {
|
|
16979
|
+
logger$13.warn("[RTCStatsMonitor] Failed to get stats:", err);
|
|
16980
|
+
return import_cjs$12.EMPTY;
|
|
16981
|
+
}))), (0, import_cjs$12.filter)(() => this.running), (0, import_cjs$12.map)((report) => this.extractSample(report))), (sample$1) => this._sample$.next(sample$1));
|
|
16982
|
+
this.subscribeTo(this._sample$.pipe((0, import_cjs$12.take)(this.baselineSampleCount), (0, import_cjs$12.toArray)(), (0, import_cjs$12.map)((samples) => ({
|
|
16945
16983
|
rtt: samples.reduce((s, b) => s + b.roundTripTime, 0) / samples.length,
|
|
16946
16984
|
jitter: samples.reduce((s, b) => s + b.audioJitter, 0) / samples.length,
|
|
16947
16985
|
ready: true
|
|
16948
16986
|
}))), (baseline) => {
|
|
16949
|
-
logger$
|
|
16987
|
+
logger$13.debug(`[RTCStatsMonitor] Baseline established: rtt=${baseline.rtt.toFixed(1)}ms, jitter=${baseline.jitter.toFixed(1)}ms`);
|
|
16950
16988
|
this._baseline$.next(baseline);
|
|
16951
16989
|
});
|
|
16952
|
-
this.subscribeTo(this._sample$.pipe((0, import_cjs$
|
|
16990
|
+
this.subscribeTo(this._sample$.pipe((0, import_cjs$12.scan)((acc, sample$1) => ({
|
|
16953
16991
|
prev: acc.current,
|
|
16954
16992
|
current: sample$1
|
|
16955
16993
|
}), {
|
|
16956
16994
|
prev: null,
|
|
16957
16995
|
current: null
|
|
16958
|
-
}), (0, import_cjs$
|
|
16996
|
+
}), (0, import_cjs$12.filter)((pair) => pair.current !== null)), ({ prev, current }) => {
|
|
16959
16997
|
const now$1 = current.timestamp;
|
|
16960
16998
|
this.updatePacketTracking(current, now$1);
|
|
16961
16999
|
const issues = this.detectIssues(current, prev, now$1);
|
|
16962
17000
|
this._networkIssues$.next(issues);
|
|
16963
17001
|
});
|
|
16964
|
-
this.subscribeTo(this._sample$.pipe((0, import_cjs$
|
|
17002
|
+
this.subscribeTo(this._sample$.pipe((0, import_cjs$12.scan)((history, sample$1) => {
|
|
16965
17003
|
const cutoff = sample$1.timestamp - this.historyWindowSeconds * 1e3;
|
|
16966
17004
|
const metrics = {
|
|
16967
17005
|
timestamp: sample$1.timestamp,
|
|
@@ -16983,10 +17021,10 @@ var RTCStatsMonitor = class extends Destroyable {
|
|
|
16983
17021
|
stop() {
|
|
16984
17022
|
if (!this.running) return;
|
|
16985
17023
|
this.running = false;
|
|
16986
|
-
logger$
|
|
17024
|
+
logger$13.debug("[RTCStatsMonitor] Stopping stats monitoring");
|
|
16987
17025
|
}
|
|
16988
17026
|
destroy() {
|
|
16989
|
-
logger$
|
|
17027
|
+
logger$13.debug("[RTCStatsMonitor] Destroying RTCStatsMonitor");
|
|
16990
17028
|
this.stop();
|
|
16991
17029
|
super.destroy();
|
|
16992
17030
|
}
|
|
@@ -16999,17 +17037,15 @@ var RTCStatsMonitor = class extends Destroyable {
|
|
|
16999
17037
|
let roundTripTime = 0;
|
|
17000
17038
|
let availableOutgoingBitrate;
|
|
17001
17039
|
report.forEach((stat) => {
|
|
17002
|
-
if (stat.
|
|
17003
|
-
|
|
17004
|
-
|
|
17005
|
-
|
|
17006
|
-
|
|
17007
|
-
|
|
17008
|
-
|
|
17009
|
-
videoPacketsLost += stat.packetsLost ?? 0;
|
|
17010
|
-
}
|
|
17040
|
+
if (isInboundRtpStat(stat)) if (stat.kind === "audio") {
|
|
17041
|
+
audioPacketsReceived += stat.packetsReceived ?? this.lastAudioPacketsReceived;
|
|
17042
|
+
audioPacketsLost += stat.packetsLost ?? 0;
|
|
17043
|
+
audioJitter = Math.max(audioJitter, (stat.jitter ?? 0) * 1e3);
|
|
17044
|
+
} else {
|
|
17045
|
+
videoPacketsReceived += stat.packetsReceived ?? this.lastVideoPacketsReceived;
|
|
17046
|
+
videoPacketsLost += stat.packetsLost ?? 0;
|
|
17011
17047
|
}
|
|
17012
|
-
if (stat
|
|
17048
|
+
if (isCandidatePairStat(stat) && stat.state === "succeeded" && stat.nominated) {
|
|
17013
17049
|
roundTripTime = stat.currentRoundTripTime ? stat.currentRoundTripTime * 1e3 : this.lastRoundTripTime;
|
|
17014
17050
|
availableOutgoingBitrate = stat.availableOutgoingBitrate ?? this.lastAvailableOutgoingBitrate;
|
|
17015
17051
|
}
|
|
@@ -17116,8 +17152,8 @@ var RTCStatsMonitor = class extends Destroyable {
|
|
|
17116
17152
|
|
|
17117
17153
|
//#endregion
|
|
17118
17154
|
//#region src/managers/CallRecoveryManager.ts
|
|
17119
|
-
var import_cjs$
|
|
17120
|
-
const logger$
|
|
17155
|
+
var import_cjs$11 = require_cjs();
|
|
17156
|
+
const logger$12 = getLogger();
|
|
17121
17157
|
const DEFAULT_DEBOUNCE_TIME_MS = 2e3;
|
|
17122
17158
|
const DEFAULT_COOLDOWN_MS = 1e4;
|
|
17123
17159
|
const DEFAULT_ICE_GRACE_PERIOD_MS = 3e3;
|
|
@@ -17153,7 +17189,7 @@ const DEGRADATION_ONLY_ISSUES = new Set([
|
|
|
17153
17189
|
* A state machine tracks the pipeline: IDLE -> DEBOUNCING -> RECOVERING -> COOLDOWN.
|
|
17154
17190
|
*/
|
|
17155
17191
|
var CallRecoveryManager = class extends Destroyable {
|
|
17156
|
-
constructor(callbacks, config = {}) {
|
|
17192
|
+
constructor(callbacks, inputs, config = {}) {
|
|
17157
17193
|
super();
|
|
17158
17194
|
this._recoveryState$ = this.createBehaviorSubject("idle");
|
|
17159
17195
|
this._recoveryEvent$ = this.createSubject();
|
|
@@ -17167,6 +17203,7 @@ var CallRecoveryManager = class extends Destroyable {
|
|
|
17167
17203
|
this._cooldownUntil = 0;
|
|
17168
17204
|
this._pipelineStop$ = this.createSubject();
|
|
17169
17205
|
this._callbacks = callbacks;
|
|
17206
|
+
this._inputs = inputs;
|
|
17170
17207
|
this._config = {
|
|
17171
17208
|
debounceTimeMs: config.debounceTimeMs ?? DEFAULT_DEBOUNCE_TIME_MS,
|
|
17172
17209
|
cooldownMs: config.cooldownMs ?? DEFAULT_COOLDOWN_MS,
|
|
@@ -17186,16 +17223,16 @@ var CallRecoveryManager = class extends Destroyable {
|
|
|
17186
17223
|
this.initDegradationRecoveryPipeline();
|
|
17187
17224
|
}
|
|
17188
17225
|
get recoveryState$() {
|
|
17189
|
-
return this._recoveryState$.asObservable().pipe((0, import_cjs$
|
|
17226
|
+
return this._recoveryState$.asObservable().pipe((0, import_cjs$11.takeUntil)(this._destroyed$));
|
|
17190
17227
|
}
|
|
17191
17228
|
get recoveryState() {
|
|
17192
17229
|
return this._recoveryState$.value;
|
|
17193
17230
|
}
|
|
17194
17231
|
get recoveryEvent$() {
|
|
17195
|
-
return this._recoveryEvent$.asObservable().pipe((0, import_cjs$
|
|
17232
|
+
return this._recoveryEvent$.asObservable().pipe((0, import_cjs$11.takeUntil)(this._destroyed$));
|
|
17196
17233
|
}
|
|
17197
17234
|
get bandwidthConstrained$() {
|
|
17198
|
-
return this._bandwidthConstrained$.asObservable().pipe((0, import_cjs$
|
|
17235
|
+
return this._bandwidthConstrained$.asObservable().pipe((0, import_cjs$11.takeUntil)(this._destroyed$));
|
|
17199
17236
|
}
|
|
17200
17237
|
get bandwidthConstrained() {
|
|
17201
17238
|
return this._bandwidthConstrained$.value;
|
|
@@ -17213,10 +17250,10 @@ var CallRecoveryManager = class extends Destroyable {
|
|
|
17213
17250
|
*/
|
|
17214
17251
|
async requestIceRestart() {
|
|
17215
17252
|
if (this._recoveryState$.value === "recovering") {
|
|
17216
|
-
logger$
|
|
17253
|
+
logger$12.info("CallRecoveryManager: manual ICE restart skipped — recovery already in progress");
|
|
17217
17254
|
return;
|
|
17218
17255
|
}
|
|
17219
|
-
logger$
|
|
17256
|
+
logger$12.info("CallRecoveryManager: manual ICE restart requested");
|
|
17220
17257
|
this.transitionTo("recovering");
|
|
17221
17258
|
await this.executeIceRestart(false);
|
|
17222
17259
|
this.startCooldown();
|
|
@@ -17232,7 +17269,7 @@ var CallRecoveryManager = class extends Destroyable {
|
|
|
17232
17269
|
* WebSocket reconnect or call state recovers to 'connected'.
|
|
17233
17270
|
*/
|
|
17234
17271
|
reset() {
|
|
17235
|
-
logger$
|
|
17272
|
+
logger$12.info("CallRecoveryManager: resetting counters");
|
|
17236
17273
|
this._attemptCount = 0;
|
|
17237
17274
|
this._keyframeBurstCount = 0;
|
|
17238
17275
|
this._keyframeBurstStart = 0;
|
|
@@ -17241,6 +17278,22 @@ var CallRecoveryManager = class extends Destroyable {
|
|
|
17241
17278
|
this.transitionTo("idle");
|
|
17242
17279
|
}
|
|
17243
17280
|
/**
|
|
17281
|
+
* Notify the recovery manager that a verto.modify (ICE restart SDP exchange)
|
|
17282
|
+
* failed at the signaling layer. Resets cooldown and pushes a new trigger
|
|
17283
|
+
* so recovery can re-attempt.
|
|
17284
|
+
*/
|
|
17285
|
+
notifyModifyFailed() {
|
|
17286
|
+
if (this._recoveryState$.value === "cooldown" || this._recoveryState$.value === "idle") {
|
|
17287
|
+
logger$12.info("CallRecoveryManager: verto.modify failed — re-entering recovery");
|
|
17288
|
+
this._cooldownUntil = 0;
|
|
17289
|
+
this.transitionTo("idle");
|
|
17290
|
+
this.pushTrigger({
|
|
17291
|
+
source: "network",
|
|
17292
|
+
detail: "modify_failed_during_recovery"
|
|
17293
|
+
});
|
|
17294
|
+
}
|
|
17295
|
+
}
|
|
17296
|
+
/**
|
|
17244
17297
|
* Feed bandwidth information for graceful degradation (Section 22).
|
|
17245
17298
|
* Call this from the stats monitor with current available outgoing bitrate.
|
|
17246
17299
|
*/
|
|
@@ -17255,7 +17308,7 @@ var CallRecoveryManager = class extends Destroyable {
|
|
|
17255
17308
|
reason: `bandwidth ${bitrateKbps}kbps below threshold ${this._config.degradationBitrateThreshold}kbps`,
|
|
17256
17309
|
timestamp: Date.now()
|
|
17257
17310
|
});
|
|
17258
|
-
logger$
|
|
17311
|
+
logger$12.warn(`CallRecoveryManager: disabling video — bandwidth ${bitrateKbps}kbps < ${this._config.degradationBitrateThreshold}kbps`);
|
|
17259
17312
|
} else if (wasConstrained && bitrateKbps >= this._config.degradationRecoveryThreshold) {
|
|
17260
17313
|
this._bandwidthConstrained$.next(false);
|
|
17261
17314
|
this._callbacks.enableVideo();
|
|
@@ -17264,7 +17317,7 @@ var CallRecoveryManager = class extends Destroyable {
|
|
|
17264
17317
|
reason: `bandwidth ${bitrateKbps}kbps recovered above ${this._config.degradationRecoveryThreshold}kbps`,
|
|
17265
17318
|
timestamp: Date.now()
|
|
17266
17319
|
});
|
|
17267
|
-
logger$
|
|
17320
|
+
logger$12.info(`CallRecoveryManager: restoring video — bandwidth ${bitrateKbps}kbps >= ${this._config.degradationRecoveryThreshold}kbps`);
|
|
17268
17321
|
}
|
|
17269
17322
|
}
|
|
17270
17323
|
/**
|
|
@@ -17283,14 +17336,14 @@ var CallRecoveryManager = class extends Destroyable {
|
|
|
17283
17336
|
handleWebSocketReconnect() {
|
|
17284
17337
|
const pcState = this._callbacks.getPeerConnectionState();
|
|
17285
17338
|
if (pcState === "connected" || pcState === "completed") {
|
|
17286
|
-
logger$
|
|
17339
|
+
logger$12.info("CallRecoveryManager: signal-only reconnect — peer connection still alive");
|
|
17287
17340
|
this.emitEvent({
|
|
17288
17341
|
action: "signal_reconnect",
|
|
17289
17342
|
reason: "WebSocket reconnected, peer connection still connected",
|
|
17290
17343
|
timestamp: Date.now()
|
|
17291
17344
|
});
|
|
17292
17345
|
} else {
|
|
17293
|
-
logger$
|
|
17346
|
+
logger$12.info("CallRecoveryManager: full reconnect — peer connection also down");
|
|
17294
17347
|
this.emitEvent({
|
|
17295
17348
|
action: "full_reconnect",
|
|
17296
17349
|
reason: "WebSocket reconnected, peer connection not connected — ICE restart needed",
|
|
@@ -17309,12 +17362,12 @@ var CallRecoveryManager = class extends Destroyable {
|
|
|
17309
17362
|
super.destroy();
|
|
17310
17363
|
}
|
|
17311
17364
|
initPipeline() {
|
|
17312
|
-
this.subscribeTo(this._trigger$.pipe((0, import_cjs$
|
|
17365
|
+
this.subscribeTo(this._trigger$.pipe((0, import_cjs$11.tap)(() => {
|
|
17313
17366
|
if (this._recoveryState$.value === "idle") this.transitionTo("debouncing");
|
|
17314
|
-
}), (0, import_cjs$
|
|
17367
|
+
}), (0, import_cjs$11.debounceTime)(this._config.debounceTimeMs), (0, import_cjs$11.withLatestFrom)(this._inputs.signalingReady$), (0, import_cjs$11.filter)(([, signalingReady]) => this.passGateChecks(signalingReady)), (0, import_cjs$11.map)(([trigger]) => trigger), (0, import_cjs$11.exhaustMap)((trigger) => this.executeTieredRecovery(trigger)), (0, import_cjs$11.takeUntil)((0, import_cjs$11.merge)(this._destroyed$, this._pipelineStop$))), {
|
|
17315
17368
|
next: () => {},
|
|
17316
17369
|
error: (err) => {
|
|
17317
|
-
logger$
|
|
17370
|
+
logger$12.error("CallRecoveryManager: pipeline error", err);
|
|
17318
17371
|
this.transitionTo("idle");
|
|
17319
17372
|
}
|
|
17320
17373
|
});
|
|
@@ -17330,10 +17383,10 @@ var CallRecoveryManager = class extends Destroyable {
|
|
|
17330
17383
|
initDegradationRecoveryPipeline() {
|
|
17331
17384
|
if (!this._config.enableAutoDegradation) return;
|
|
17332
17385
|
const delayMs = this._config.packetLossRecoveryDelaySec * 1e3;
|
|
17333
|
-
this.subscribeTo((0, import_cjs$
|
|
17334
|
-
if (constrained && !hasPacketLoss) return (0, import_cjs$
|
|
17335
|
-
return import_cjs$
|
|
17336
|
-
}), (0, import_cjs$
|
|
17386
|
+
this.subscribeTo((0, import_cjs$11.combineLatest)([this._bandwidthConstrained$, this._hasPacketLoss$]).pipe((0, import_cjs$11.switchMap)(([constrained, hasPacketLoss]) => {
|
|
17387
|
+
if (constrained && !hasPacketLoss) return (0, import_cjs$11.timer)(delayMs);
|
|
17388
|
+
return import_cjs$11.EMPTY;
|
|
17389
|
+
}), (0, import_cjs$11.takeUntil)(this._destroyed$)), () => {
|
|
17337
17390
|
this._bandwidthConstrained$.next(false);
|
|
17338
17391
|
this._callbacks.enableVideo();
|
|
17339
17392
|
this.emitEvent({
|
|
@@ -17341,27 +17394,27 @@ var CallRecoveryManager = class extends Destroyable {
|
|
|
17341
17394
|
reason: `no packet loss for ${this._config.packetLossRecoveryDelaySec}s — restoring video`,
|
|
17342
17395
|
timestamp: Date.now()
|
|
17343
17396
|
});
|
|
17344
|
-
logger$
|
|
17397
|
+
logger$12.info(`CallRecoveryManager: restoring video — no packet loss for ${this._config.packetLossRecoveryDelaySec}s`);
|
|
17345
17398
|
});
|
|
17346
17399
|
}
|
|
17347
|
-
passGateChecks() {
|
|
17400
|
+
passGateChecks(signalingReady) {
|
|
17348
17401
|
if (this._callbacks.isNegotiating()) {
|
|
17349
|
-
logger$
|
|
17402
|
+
logger$12.debug("CallRecoveryManager: gate blocked — negotiation in progress");
|
|
17350
17403
|
this.transitionTo("idle");
|
|
17351
17404
|
return false;
|
|
17352
17405
|
}
|
|
17353
|
-
if (!
|
|
17354
|
-
logger$
|
|
17406
|
+
if (!signalingReady) {
|
|
17407
|
+
logger$12.debug("CallRecoveryManager: gate blocked — signaling not ready");
|
|
17355
17408
|
this.transitionTo("idle");
|
|
17356
17409
|
return false;
|
|
17357
17410
|
}
|
|
17358
17411
|
if (!this._callbacks.isCallConnected()) {
|
|
17359
|
-
logger$
|
|
17412
|
+
logger$12.debug("CallRecoveryManager: gate blocked — call not connected");
|
|
17360
17413
|
this.transitionTo("idle");
|
|
17361
17414
|
return false;
|
|
17362
17415
|
}
|
|
17363
17416
|
if (this.isCooldownActive()) {
|
|
17364
|
-
logger$
|
|
17417
|
+
logger$12.debug("CallRecoveryManager: gate blocked — cooldown active");
|
|
17365
17418
|
this.transitionTo("cooldown");
|
|
17366
17419
|
return false;
|
|
17367
17420
|
}
|
|
@@ -17372,17 +17425,17 @@ var CallRecoveryManager = class extends Destroyable {
|
|
|
17372
17425
|
}
|
|
17373
17426
|
executeTieredRecovery(trigger) {
|
|
17374
17427
|
this.transitionTo("recovering");
|
|
17375
|
-
logger$
|
|
17376
|
-
return (0, import_cjs$
|
|
17377
|
-
logger$
|
|
17428
|
+
logger$12.info(`CallRecoveryManager: starting tiered recovery — source=${trigger.source} detail=${trigger.detail}`);
|
|
17429
|
+
return (0, import_cjs$11.from)(this.runTiers(trigger)).pipe((0, import_cjs$11.tap)(() => this.startCooldown()), (0, import_cjs$11.catchError)((err) => {
|
|
17430
|
+
logger$12.error("CallRecoveryManager: tiered recovery failed", err);
|
|
17378
17431
|
this.startCooldown();
|
|
17379
|
-
return import_cjs$
|
|
17432
|
+
return import_cjs$11.EMPTY;
|
|
17380
17433
|
}));
|
|
17381
17434
|
}
|
|
17382
17435
|
async runTiers(trigger) {
|
|
17383
17436
|
this.executeKeyframe(trigger.detail);
|
|
17384
17437
|
if (trigger.issueType && DEGRADATION_ONLY_ISSUES.has(trigger.issueType)) {
|
|
17385
|
-
logger$
|
|
17438
|
+
logger$12.debug(`CallRecoveryManager: degradation-only issue (${trigger.issueType}) — Tier 1 only, skipping ICE restart`);
|
|
17386
17439
|
return;
|
|
17387
17440
|
}
|
|
17388
17441
|
if (this._attemptCount < this._config.maxAttempts) {
|
|
@@ -17399,13 +17452,13 @@ var CallRecoveryManager = class extends Destroyable {
|
|
|
17399
17452
|
maxAttempts: this._config.maxAttempts,
|
|
17400
17453
|
timestamp: Date.now()
|
|
17401
17454
|
});
|
|
17402
|
-
logger$
|
|
17455
|
+
logger$12.warn("CallRecoveryManager: max recovery attempts reached");
|
|
17403
17456
|
}
|
|
17404
17457
|
}
|
|
17405
17458
|
executeKeyframe(reason) {
|
|
17406
17459
|
const now = Date.now();
|
|
17407
17460
|
if (now < this._keyframeCooldownUntil) {
|
|
17408
|
-
logger$
|
|
17461
|
+
logger$12.debug("CallRecoveryManager: keyframe request skipped — cooldown active");
|
|
17409
17462
|
return;
|
|
17410
17463
|
}
|
|
17411
17464
|
if (now - this._keyframeBurstStart > this._config.keyframeBurstWindowMs) {
|
|
@@ -17414,7 +17467,7 @@ var CallRecoveryManager = class extends Destroyable {
|
|
|
17414
17467
|
}
|
|
17415
17468
|
if (this._keyframeBurstCount >= this._config.keyframeMaxBurst) {
|
|
17416
17469
|
this._keyframeCooldownUntil = now + this._config.keyframeCooldownMs;
|
|
17417
|
-
logger$
|
|
17470
|
+
logger$12.debug(`CallRecoveryManager: keyframe burst limit reached (${this._config.keyframeMaxBurst}), cooldown until ${this._keyframeCooldownUntil}`);
|
|
17418
17471
|
return;
|
|
17419
17472
|
}
|
|
17420
17473
|
this._keyframeBurstCount += 1;
|
|
@@ -17424,12 +17477,12 @@ var CallRecoveryManager = class extends Destroyable {
|
|
|
17424
17477
|
reason,
|
|
17425
17478
|
timestamp: now
|
|
17426
17479
|
});
|
|
17427
|
-
logger$
|
|
17480
|
+
logger$12.debug(`CallRecoveryManager: keyframe requested (burst ${this._keyframeBurstCount}/${this._config.keyframeMaxBurst})`);
|
|
17428
17481
|
}
|
|
17429
17482
|
async executeIceRestart(relayOnly) {
|
|
17430
17483
|
this._attemptCount += 1;
|
|
17431
17484
|
const tier = relayOnly ? "Tier 3 (relay-only)" : "Tier 2 (standard)";
|
|
17432
|
-
logger$
|
|
17485
|
+
logger$12.info(`CallRecoveryManager: ${tier} ICE restart — attempt ${this._attemptCount}/${this._config.maxAttempts}`);
|
|
17433
17486
|
this.emitEvent({
|
|
17434
17487
|
action: "reinvite_started",
|
|
17435
17488
|
reason: `${tier} ICE restart`,
|
|
@@ -17446,7 +17499,7 @@ var CallRecoveryManager = class extends Destroyable {
|
|
|
17446
17499
|
maxAttempts: this._config.maxAttempts,
|
|
17447
17500
|
timestamp: Date.now()
|
|
17448
17501
|
});
|
|
17449
|
-
logger$
|
|
17502
|
+
logger$12.info(`CallRecoveryManager: ${tier} ICE restart succeeded`);
|
|
17450
17503
|
this._attemptCount = 0;
|
|
17451
17504
|
return true;
|
|
17452
17505
|
}
|
|
@@ -17457,7 +17510,7 @@ var CallRecoveryManager = class extends Destroyable {
|
|
|
17457
17510
|
maxAttempts: this._config.maxAttempts,
|
|
17458
17511
|
timestamp: Date.now()
|
|
17459
17512
|
});
|
|
17460
|
-
logger$
|
|
17513
|
+
logger$12.warn(`CallRecoveryManager: ${tier} ICE restart failed`);
|
|
17461
17514
|
return false;
|
|
17462
17515
|
} catch {
|
|
17463
17516
|
this.emitEvent({
|
|
@@ -17467,7 +17520,7 @@ var CallRecoveryManager = class extends Destroyable {
|
|
|
17467
17520
|
maxAttempts: this._config.maxAttempts,
|
|
17468
17521
|
timestamp: Date.now()
|
|
17469
17522
|
});
|
|
17470
|
-
logger$
|
|
17523
|
+
logger$12.warn(`CallRecoveryManager: ${tier} ICE restart timed out`);
|
|
17471
17524
|
return false;
|
|
17472
17525
|
}
|
|
17473
17526
|
}
|
|
@@ -17488,7 +17541,7 @@ var CallRecoveryManager = class extends Destroyable {
|
|
|
17488
17541
|
transitionTo(state) {
|
|
17489
17542
|
const prev = this._recoveryState$.value;
|
|
17490
17543
|
if (prev !== state) {
|
|
17491
|
-
logger$
|
|
17544
|
+
logger$12.debug(`CallRecoveryManager: state ${prev} -> ${state}`);
|
|
17492
17545
|
this._recoveryState$.next(state);
|
|
17493
17546
|
}
|
|
17494
17547
|
}
|
|
@@ -17496,7 +17549,7 @@ var CallRecoveryManager = class extends Destroyable {
|
|
|
17496
17549
|
this._cooldownUntil = Date.now() + this._config.cooldownMs;
|
|
17497
17550
|
this.transitionTo("cooldown");
|
|
17498
17551
|
if (this._cooldownSubscription) this._cooldownSubscription.unsubscribe();
|
|
17499
|
-
this._cooldownSubscription = (0, import_cjs$
|
|
17552
|
+
this._cooldownSubscription = (0, import_cjs$11.timer)(this._config.cooldownMs).pipe((0, import_cjs$11.take)(1), (0, import_cjs$11.takeUntil)(this._destroyed$), (0, import_cjs$11.filter)(() => this._recoveryState$.value === "cooldown")).subscribe(() => this.transitionTo("idle"));
|
|
17500
17553
|
}
|
|
17501
17554
|
emitEvent(event) {
|
|
17502
17555
|
this._recoveryEvent$.next(event);
|
|
@@ -17590,8 +17643,8 @@ function mosToQualityLevel(mos) {
|
|
|
17590
17643
|
|
|
17591
17644
|
//#endregion
|
|
17592
17645
|
//#region src/core/entities/Call.ts
|
|
17593
|
-
var import_cjs$
|
|
17594
|
-
const logger$
|
|
17646
|
+
var import_cjs$10 = require_cjs();
|
|
17647
|
+
const logger$11 = getLogger();
|
|
17595
17648
|
/**
|
|
17596
17649
|
* Ratio between the critical and warning RTT spike multipliers.
|
|
17597
17650
|
* Warning threshold = baseline * warningMultiplier (default 3x)
|
|
@@ -17609,7 +17662,7 @@ const fromDestinationParams = (destination) => {
|
|
|
17609
17662
|
});
|
|
17610
17663
|
return params;
|
|
17611
17664
|
} catch (error) {
|
|
17612
|
-
logger$
|
|
17665
|
+
logger$11.warn(`Failed to parse destination URI: ${destination}`, error);
|
|
17613
17666
|
return {};
|
|
17614
17667
|
}
|
|
17615
17668
|
};
|
|
@@ -17665,10 +17718,13 @@ var WebRTCCall = class extends Destroyable {
|
|
|
17665
17718
|
const { deviceController, networkChange$ } = initialization;
|
|
17666
17719
|
this._networkChange$ = networkChange$;
|
|
17667
17720
|
this.participantFactory = new ParticipantFactory(this.executeMethod.bind(this), this.vertoManager, deviceController);
|
|
17668
|
-
this.subscribeTo((0, import_cjs$
|
|
17721
|
+
this.subscribeTo((0, import_cjs$10.merge)(this._status$.asObservable(), this.vertoManager.signalingStatus$).pipe((0, import_cjs$10.distinctUntilChanged)(), (0, import_cjs$10.takeUntil)(this._destroyed$)), (status) => {
|
|
17669
17722
|
this._lastMergedStatus = status;
|
|
17670
17723
|
if (status === "connected" && !this._statsMonitor) this.initResilienceSubsystems();
|
|
17671
|
-
else if (status === "disconnected"
|
|
17724
|
+
else if (status === "disconnected") {
|
|
17725
|
+
this._statsMonitor?.destroy();
|
|
17726
|
+
this._statsMonitor = void 0;
|
|
17727
|
+
} else if (status === "destroyed" || status === "failed") this.stopResilienceSubsystems();
|
|
17672
17728
|
});
|
|
17673
17729
|
}
|
|
17674
17730
|
/** Observable stream of errors from media, signaling, and peer connection layers. */
|
|
@@ -17687,13 +17743,17 @@ var WebRTCCall = class extends Destroyable {
|
|
|
17687
17743
|
this.destroy();
|
|
17688
17744
|
}
|
|
17689
17745
|
}
|
|
17746
|
+
/** Notify the recovery manager that a verto.modify signaling exchange failed. */
|
|
17747
|
+
notifyModifyFailed() {
|
|
17748
|
+
this._recoveryManager?.notifyModifyFailed();
|
|
17749
|
+
}
|
|
17690
17750
|
/** Whether this call is `'inbound'` or `'outbound'`. */
|
|
17691
17751
|
get direction() {
|
|
17692
17752
|
return this.options.initOffer ? "inbound" : "outbound";
|
|
17693
17753
|
}
|
|
17694
17754
|
/** Observable of the address associated with this call. */
|
|
17695
17755
|
get address$() {
|
|
17696
|
-
return this.deferEmission((0, import_cjs$
|
|
17756
|
+
return this.deferEmission((0, import_cjs$10.from)([this.address])).pipe((0, import_cjs$10.takeUntil)(this._destroyed$));
|
|
17697
17757
|
}
|
|
17698
17758
|
/** Display name of the caller. */
|
|
17699
17759
|
get fromName() {
|
|
@@ -17772,7 +17832,7 @@ var WebRTCCall = class extends Destroyable {
|
|
|
17772
17832
|
}
|
|
17773
17833
|
/** Observable of layout layer positions for all participants. */
|
|
17774
17834
|
get layoutLayers$() {
|
|
17775
|
-
return this.deferEmission(this.callEventsManager.layoutLayers$).pipe((0, import_cjs$
|
|
17835
|
+
return this.deferEmission(this.callEventsManager.layoutLayers$).pipe((0, import_cjs$10.takeUntil)(this._destroyed$));
|
|
17776
17836
|
}
|
|
17777
17837
|
/** Current snapshot of layout layers. */
|
|
17778
17838
|
get layoutLayers() {
|
|
@@ -17800,7 +17860,7 @@ var WebRTCCall = class extends Destroyable {
|
|
|
17800
17860
|
if (isJSONRPCErrorResponse(response)) throw new JSONRPCError(parseInt(response.result?.code ?? "0"), `Error response from method ${method}: ${response.result?.code} ${response.result?.message}`, void 0, void 0, request.id);
|
|
17801
17861
|
return response;
|
|
17802
17862
|
} catch (error) {
|
|
17803
|
-
logger$
|
|
17863
|
+
logger$11.error(`[Call] Error executing method ${method} with params`, params, error);
|
|
17804
17864
|
throw error;
|
|
17805
17865
|
}
|
|
17806
17866
|
}
|
|
@@ -17827,45 +17887,45 @@ var WebRTCCall = class extends Destroyable {
|
|
|
17827
17887
|
}
|
|
17828
17888
|
/** Observable of the current call status (e.g. `'ringing'`, `'connected'`). */
|
|
17829
17889
|
get status$() {
|
|
17830
|
-
return this.publicCachedObservable("status$", () => (0, import_cjs$
|
|
17890
|
+
return this.publicCachedObservable("status$", () => (0, import_cjs$10.merge)(this._status$.asObservable(), this.vertoManager.signalingStatus$).pipe((0, import_cjs$10.distinctUntilChanged)(), (0, import_cjs$10.tap)((status) => {
|
|
17831
17891
|
this._lastMergedStatus = status;
|
|
17832
17892
|
})));
|
|
17833
17893
|
}
|
|
17834
17894
|
/** Observable of the participants list, emits on join/leave/update. */
|
|
17835
17895
|
get participants$() {
|
|
17836
|
-
return this.deferEmission(this.callEventsManager.participants$).pipe((0, import_cjs$
|
|
17896
|
+
return this.deferEmission(this.callEventsManager.participants$).pipe((0, import_cjs$10.takeUntil)(this._destroyed$));
|
|
17837
17897
|
}
|
|
17838
17898
|
/** Observable of the local (self) participant. */
|
|
17839
17899
|
get self$() {
|
|
17840
|
-
return this.deferEmission(this.callEventsManager.self$).pipe((0, import_cjs$
|
|
17900
|
+
return this.deferEmission(this.callEventsManager.self$).pipe((0, import_cjs$10.takeUntil)(this._destroyed$));
|
|
17841
17901
|
}
|
|
17842
17902
|
/** Observable indicating whether the call is being recorded. */
|
|
17843
17903
|
get recording$() {
|
|
17844
|
-
return this.deferEmission(this.callEventsManager.recording$).pipe((0, import_cjs$
|
|
17904
|
+
return this.deferEmission(this.callEventsManager.recording$).pipe((0, import_cjs$10.takeUntil)(this._destroyed$));
|
|
17845
17905
|
}
|
|
17846
17906
|
/** Observable indicating whether the call is being streamed. */
|
|
17847
17907
|
get streaming$() {
|
|
17848
|
-
return this.deferEmission(this.callEventsManager.streaming$).pipe((0, import_cjs$
|
|
17908
|
+
return this.deferEmission(this.callEventsManager.streaming$).pipe((0, import_cjs$10.takeUntil)(this._destroyed$));
|
|
17849
17909
|
}
|
|
17850
17910
|
/** Observable indicating whether raise-hand priority is active. */
|
|
17851
17911
|
get raiseHandPriority$() {
|
|
17852
|
-
return this.deferEmission(this.callEventsManager.raiseHandPriority$).pipe((0, import_cjs$
|
|
17912
|
+
return this.deferEmission(this.callEventsManager.raiseHandPriority$).pipe((0, import_cjs$10.takeUntil)(this._destroyed$));
|
|
17853
17913
|
}
|
|
17854
17914
|
/** Observable indicating whether the call room is locked. */
|
|
17855
17915
|
get locked$() {
|
|
17856
|
-
return this.deferEmission(this.callEventsManager.locked$).pipe((0, import_cjs$
|
|
17916
|
+
return this.deferEmission(this.callEventsManager.locked$).pipe((0, import_cjs$10.takeUntil)(this._destroyed$));
|
|
17857
17917
|
}
|
|
17858
17918
|
/** Observable of custom metadata associated with the call. */
|
|
17859
17919
|
get meta$() {
|
|
17860
|
-
return this.deferEmission(this.callEventsManager.meta$).pipe((0, import_cjs$
|
|
17920
|
+
return this.deferEmission(this.callEventsManager.meta$).pipe((0, import_cjs$10.takeUntil)(this._destroyed$));
|
|
17861
17921
|
}
|
|
17862
17922
|
/** Observable of the call's capability flags. */
|
|
17863
17923
|
get capabilities$() {
|
|
17864
|
-
return this.deferEmission(this.callEventsManager.capabilities$).pipe((0, import_cjs$
|
|
17924
|
+
return this.deferEmission(this.callEventsManager.capabilities$).pipe((0, import_cjs$10.takeUntil)(this._destroyed$));
|
|
17865
17925
|
}
|
|
17866
17926
|
/** Observable of the current layout name. */
|
|
17867
17927
|
get layout$() {
|
|
17868
|
-
return this.deferEmission(this.callEventsManager.layout$).pipe((0, import_cjs$
|
|
17928
|
+
return this.deferEmission(this.callEventsManager.layout$).pipe((0, import_cjs$10.takeUntil)(this._destroyed$));
|
|
17869
17929
|
}
|
|
17870
17930
|
/** Current call status. */
|
|
17871
17931
|
get status() {
|
|
@@ -17897,7 +17957,7 @@ var WebRTCCall = class extends Destroyable {
|
|
|
17897
17957
|
}
|
|
17898
17958
|
/** Observable of available layout names. */
|
|
17899
17959
|
get layouts$() {
|
|
17900
|
-
return this.deferEmission(this.callEventsManager.layouts$).pipe((0, import_cjs$
|
|
17960
|
+
return this.deferEmission(this.callEventsManager.layouts$).pipe((0, import_cjs$10.takeUntil)(this._destroyed$));
|
|
17901
17961
|
}
|
|
17902
17962
|
/** Current snapshot of available layout names. */
|
|
17903
17963
|
get layouts() {
|
|
@@ -17905,7 +17965,7 @@ var WebRTCCall = class extends Destroyable {
|
|
|
17905
17965
|
}
|
|
17906
17966
|
/** Observable of the local media stream (camera/microphone). */
|
|
17907
17967
|
get localStream$() {
|
|
17908
|
-
return this.deferEmission(this.vertoManager.localStream$).pipe((0, import_cjs$
|
|
17968
|
+
return this.deferEmission(this.vertoManager.localStream$).pipe((0, import_cjs$10.takeUntil)(this._destroyed$));
|
|
17909
17969
|
}
|
|
17910
17970
|
/** Current local media stream, or `null` if not available. */
|
|
17911
17971
|
get localStream() {
|
|
@@ -17913,7 +17973,7 @@ var WebRTCCall = class extends Destroyable {
|
|
|
17913
17973
|
}
|
|
17914
17974
|
/** Observable of the remote media stream from the far end. */
|
|
17915
17975
|
get remoteStream$() {
|
|
17916
|
-
return this.deferEmission(this.vertoManager.remoteStream$).pipe((0, import_cjs$
|
|
17976
|
+
return this.deferEmission(this.vertoManager.remoteStream$).pipe((0, import_cjs$10.takeUntil)(this._destroyed$));
|
|
17917
17977
|
}
|
|
17918
17978
|
/** Current remote media stream, or `null` if not available. */
|
|
17919
17979
|
get remoteStream() {
|
|
@@ -18003,9 +18063,9 @@ var WebRTCCall = class extends Destroyable {
|
|
|
18003
18063
|
*/
|
|
18004
18064
|
initResilienceSubsystems() {
|
|
18005
18065
|
const pc = this.rtcPeerConnection;
|
|
18006
|
-
logger$
|
|
18066
|
+
logger$11.debug(`[Call] initResilienceSubsystems: pc=${pc ? "exists" : "undefined"}, connectionState=${pc?.connectionState}`);
|
|
18007
18067
|
if (!pc) {
|
|
18008
|
-
logger$
|
|
18068
|
+
logger$11.warn("[Call] No peer connection available, skipping resilience init");
|
|
18009
18069
|
return;
|
|
18010
18070
|
}
|
|
18011
18071
|
try {
|
|
@@ -18040,21 +18100,20 @@ var WebRTCCall = class extends Destroyable {
|
|
|
18040
18100
|
disableVideo: () => {
|
|
18041
18101
|
try {
|
|
18042
18102
|
this.vertoManager.muteMainVideoInputDevice();
|
|
18043
|
-
logger$
|
|
18103
|
+
logger$11.debug("[Call] Recovery manager disabled video");
|
|
18044
18104
|
} catch {
|
|
18045
|
-
logger$
|
|
18105
|
+
logger$11.debug("[Call] Recovery manager failed to disable video");
|
|
18046
18106
|
}
|
|
18047
18107
|
},
|
|
18048
18108
|
enableVideo: () => {
|
|
18049
18109
|
this.vertoManager.unmuteMainVideoInputDevice().catch(() => {
|
|
18050
|
-
logger$
|
|
18110
|
+
logger$11.debug("[Call] Recovery manager failed to enable video");
|
|
18051
18111
|
});
|
|
18052
18112
|
},
|
|
18053
18113
|
isNegotiating: () => this.vertoManager.mainPeerConnection.isNegotiating,
|
|
18054
|
-
isWebSocketConnected: () => this._lastMergedStatus !== "disconnected",
|
|
18055
18114
|
isCallConnected: () => this._lastMergedStatus === "connected",
|
|
18056
18115
|
getPeerConnectionState: () => pc.connectionState
|
|
18057
|
-
}, {
|
|
18116
|
+
}, { signalingReady$: this.clientSession.authenticated$ }, {
|
|
18058
18117
|
debounceTimeMs: prefs.recoveryDebounceTime,
|
|
18059
18118
|
cooldownMs: prefs.recoveryCooldown,
|
|
18060
18119
|
iceGracePeriodMs: prefs.iceDisconnectedGracePeriod,
|
|
@@ -18097,6 +18156,15 @@ var WebRTCCall = class extends Destroyable {
|
|
|
18097
18156
|
});
|
|
18098
18157
|
this.subscribeTo(this._recoveryManager.recoveryEvent$, (event) => {
|
|
18099
18158
|
this._recoveryEvent$.next(event);
|
|
18159
|
+
if (event.action === "max_attempts_reached") {
|
|
18160
|
+
logger$11.warn("[Call] All recovery attempts exhausted, terminating call");
|
|
18161
|
+
this.emitError({
|
|
18162
|
+
kind: "network",
|
|
18163
|
+
fatal: true,
|
|
18164
|
+
error: /* @__PURE__ */ new Error("Call recovery failed: all attempts exhausted"),
|
|
18165
|
+
callId: this.id
|
|
18166
|
+
});
|
|
18167
|
+
}
|
|
18100
18168
|
});
|
|
18101
18169
|
this.subscribeTo(this._recoveryManager.bandwidthConstrained$, (constrained) => {
|
|
18102
18170
|
this._bandwidthConstrained$.next(constrained);
|
|
@@ -18108,14 +18176,14 @@ var WebRTCCall = class extends Destroyable {
|
|
|
18108
18176
|
});
|
|
18109
18177
|
else if (event.type === "online") this._recoveryManager?.handleWebSocketReconnect();
|
|
18110
18178
|
});
|
|
18111
|
-
this.subscribeTo(this.clientSession.authenticated$.pipe((0, import_cjs$
|
|
18112
|
-
logger$
|
|
18179
|
+
this.subscribeTo(this.clientSession.authenticated$.pipe((0, import_cjs$10.skip)(1), (0, import_cjs$10.filter)(Boolean)), () => {
|
|
18180
|
+
logger$11.debug("[Call] WebSocket reconnected — notifying recovery manager");
|
|
18113
18181
|
this._recoveryManager?.handleWebSocketReconnect();
|
|
18114
18182
|
});
|
|
18115
18183
|
this._statsMonitor.start();
|
|
18116
|
-
logger$
|
|
18184
|
+
logger$11.debug("[Call] Resilience subsystems initialized for call", this.id);
|
|
18117
18185
|
} catch (error) {
|
|
18118
|
-
logger$
|
|
18186
|
+
logger$11.warn("[Call] Failed to initialize resilience subsystems:", error);
|
|
18119
18187
|
}
|
|
18120
18188
|
}
|
|
18121
18189
|
/**
|
|
@@ -18137,14 +18205,14 @@ var WebRTCCall = class extends Destroyable {
|
|
|
18137
18205
|
}
|
|
18138
18206
|
/** Observable of the current audio/video send/receive directions. */
|
|
18139
18207
|
get mediaDirections$() {
|
|
18140
|
-
return this.deferEmission(this.vertoManager.mediaDirections$).pipe((0, import_cjs$
|
|
18208
|
+
return this.deferEmission(this.vertoManager.mediaDirections$).pipe((0, import_cjs$10.takeUntil)(this._destroyed$));
|
|
18141
18209
|
}
|
|
18142
18210
|
/** Current audio/video send/receive directions. */
|
|
18143
18211
|
get mediaDirections() {
|
|
18144
18212
|
return this.vertoManager.mediaDirections;
|
|
18145
18213
|
}
|
|
18146
18214
|
get participantsId$() {
|
|
18147
|
-
return this.cachedObservable("participantsId$", () => this.participants$.pipe((0, import_cjs$
|
|
18215
|
+
return this.cachedObservable("participantsId$", () => this.participants$.pipe((0, import_cjs$10.map)((participants) => participants.map((participant) => participant.id))));
|
|
18148
18216
|
}
|
|
18149
18217
|
/**
|
|
18150
18218
|
* Executes a raw JSON-RPC request on the client session.
|
|
@@ -18177,48 +18245,48 @@ var WebRTCCall = class extends Destroyable {
|
|
|
18177
18245
|
}
|
|
18178
18246
|
isCallSessionEvent(event) {
|
|
18179
18247
|
try {
|
|
18180
|
-
logger$
|
|
18248
|
+
logger$11.debug("[Call] Checking if event is for this call session:", event);
|
|
18181
18249
|
const callId = getValueFrom(event, "params.params.callID") ?? getValueFrom(event, "params.call_id");
|
|
18182
18250
|
const roomSessionId = getValueFrom(event, "params.room_session_id");
|
|
18183
|
-
logger$
|
|
18251
|
+
logger$11.debug(`[Call] Extracted session identifiers callID: ${callId} and roomSessionID: ${roomSessionId} from event:`);
|
|
18184
18252
|
return callId === this.id || !!callId && this.callEventsManager.isCallIdValid(callId) || !!roomSessionId && this.callEventsManager.isRoomSessionIdValid(roomSessionId);
|
|
18185
18253
|
} catch (error) {
|
|
18186
|
-
logger$
|
|
18254
|
+
logger$11.error("[Call] Error checking if event is for this call session:", error);
|
|
18187
18255
|
return false;
|
|
18188
18256
|
}
|
|
18189
18257
|
}
|
|
18190
18258
|
get callSessionEvents$() {
|
|
18191
|
-
return this.cachedObservable("callSessionEvents$", () => this.clientSession.signalingEvent$.pipe((0, import_cjs$
|
|
18192
|
-
logger$
|
|
18193
|
-
}), (0, import_cjs$
|
|
18259
|
+
return this.cachedObservable("callSessionEvents$", () => this.clientSession.signalingEvent$.pipe((0, import_cjs$10.filter)((event) => this.isCallSessionEvent(event)), (0, import_cjs$10.tap)((event) => {
|
|
18260
|
+
logger$11.debug("[Call] Received call session event:", event);
|
|
18261
|
+
}), (0, import_cjs$10.takeUntil)(this.destroyed$), (0, import_cjs$10.share)()));
|
|
18194
18262
|
}
|
|
18195
18263
|
/** Observable of call-updated events. */
|
|
18196
18264
|
get callUpdated$() {
|
|
18197
|
-
return this.publicCachedObservable("callUpdated$", () => this.callSessionEvents$.pipe(filterAs(isCallUpdatedMetadata, "params"), (0, import_cjs$
|
|
18265
|
+
return this.publicCachedObservable("callUpdated$", () => this.callSessionEvents$.pipe(filterAs(isCallUpdatedMetadata, "params"), (0, import_cjs$10.takeUntil)(this.destroyed$)));
|
|
18198
18266
|
}
|
|
18199
18267
|
/** Observable of member-joined events, emitted when a remote participant joins the call. */
|
|
18200
18268
|
get memberJoined$() {
|
|
18201
|
-
return this.publicCachedObservable("memberJoined$", () => this.callSessionEvents$.pipe(filterAs(isMemberJoinedMetadata, "params"), (0, import_cjs$
|
|
18269
|
+
return this.publicCachedObservable("memberJoined$", () => this.callSessionEvents$.pipe(filterAs(isMemberJoinedMetadata, "params"), (0, import_cjs$10.takeUntil)(this.destroyed$)));
|
|
18202
18270
|
}
|
|
18203
18271
|
/** Observable of member-left events, emitted when a participant leaves the call. */
|
|
18204
18272
|
get memberLeft$() {
|
|
18205
|
-
return this.publicCachedObservable("memberLeft$", () => this.callSessionEvents$.pipe(filterAs(isMemberLeftMetadata, "params"), (0, import_cjs$
|
|
18273
|
+
return this.publicCachedObservable("memberLeft$", () => this.callSessionEvents$.pipe(filterAs(isMemberLeftMetadata, "params"), (0, import_cjs$10.takeUntil)(this.destroyed$)));
|
|
18206
18274
|
}
|
|
18207
18275
|
/** Observable of member-updated events (mute, volume, etc.). */
|
|
18208
18276
|
get memberUpdated$() {
|
|
18209
|
-
return this.publicCachedObservable("memberUpdated$", () => this.callSessionEvents$.pipe(filterAs(isMemberUpdatedMetadata, "params"), (0, import_cjs$
|
|
18277
|
+
return this.publicCachedObservable("memberUpdated$", () => this.callSessionEvents$.pipe(filterAs(isMemberUpdatedMetadata, "params"), (0, import_cjs$10.takeUntil)(this.destroyed$)));
|
|
18210
18278
|
}
|
|
18211
18279
|
/** Observable of member-talking events (speech start/stop). */
|
|
18212
18280
|
get memberTalking$() {
|
|
18213
|
-
return this.publicCachedObservable("memberTalking$", () => this.callSessionEvents$.pipe(filterAs(isMemberTalkingMetadata, "params"), (0, import_cjs$
|
|
18281
|
+
return this.publicCachedObservable("memberTalking$", () => this.callSessionEvents$.pipe(filterAs(isMemberTalkingMetadata, "params"), (0, import_cjs$10.takeUntil)(this.destroyed$)));
|
|
18214
18282
|
}
|
|
18215
18283
|
/** Observable of call state-change events. */
|
|
18216
18284
|
get callStates$() {
|
|
18217
|
-
return this.publicCachedObservable("callStates$", () => this.callSessionEvents$.pipe(filterAs(isCallStateMetadata, "params"), (0, import_cjs$
|
|
18285
|
+
return this.publicCachedObservable("callStates$", () => this.callSessionEvents$.pipe(filterAs(isCallStateMetadata, "params"), (0, import_cjs$10.takeUntil)(this.destroyed$)));
|
|
18218
18286
|
}
|
|
18219
18287
|
/** Observable of layout-changed events. */
|
|
18220
18288
|
get layoutUpdates$() {
|
|
18221
|
-
return this.publicCachedObservable("layoutUpdates$", () => this.callSessionEvents$.pipe(filterAs(isLayoutChangedMetadata, "params"), (0, import_cjs$
|
|
18289
|
+
return this.publicCachedObservable("layoutUpdates$", () => this.callSessionEvents$.pipe(filterAs(isLayoutChangedMetadata, "params"), (0, import_cjs$10.takeUntil)(this.destroyed$)));
|
|
18222
18290
|
}
|
|
18223
18291
|
/** Underlying `RTCPeerConnection`, for advanced use cases. */
|
|
18224
18292
|
get rtcPeerConnection() {
|
|
@@ -18226,7 +18294,7 @@ var WebRTCCall = class extends Destroyable {
|
|
|
18226
18294
|
}
|
|
18227
18295
|
/** Observable of raw signaling events as plain objects. */
|
|
18228
18296
|
get signalingEvent$() {
|
|
18229
|
-
return this.publicCachedObservable("signalingEvent$", () => this.callEvent$.pipe((0, import_cjs$
|
|
18297
|
+
return this.publicCachedObservable("signalingEvent$", () => this.callEvent$.pipe((0, import_cjs$10.map)((event) => JSON.parse(JSON.stringify(event)))));
|
|
18230
18298
|
}
|
|
18231
18299
|
/**
|
|
18232
18300
|
* Subscribe to a custom signaling event type on this call.
|
|
@@ -18254,16 +18322,16 @@ var WebRTCCall = class extends Destroyable {
|
|
|
18254
18322
|
subscribe(eventType) {
|
|
18255
18323
|
const cached = this._customSubscriptions.get(eventType);
|
|
18256
18324
|
if (cached) return cached;
|
|
18257
|
-
const filtered$ = this.callSessionEvents$.pipe((0, import_cjs$
|
|
18325
|
+
const filtered$ = this.callSessionEvents$.pipe((0, import_cjs$10.filter)((event) => event.event_type === eventType), (0, import_cjs$10.map)((event) => JSON.parse(JSON.stringify(event))), (0, import_cjs$10.takeUntil)(this._destroyed$));
|
|
18258
18326
|
this._customSubscriptions.set(eventType, filtered$);
|
|
18259
18327
|
this._sendVertoSubscribe(eventType);
|
|
18260
18328
|
return filtered$;
|
|
18261
18329
|
}
|
|
18262
18330
|
get webrtcMessages$() {
|
|
18263
|
-
return this.cachedObservable("webrtcMessages$", () => this.callSessionEvents$.pipe(filterAs(isWebrtcMessageMetadata, "params"), (0, import_cjs$
|
|
18331
|
+
return this.cachedObservable("webrtcMessages$", () => this.callSessionEvents$.pipe(filterAs(isWebrtcMessageMetadata, "params"), (0, import_cjs$10.tap)((event) => logger$11.debug("[Call] Event is a WebRTC message event:", event)), (0, import_cjs$10.takeUntil)(this.destroyed$), (0, import_cjs$10.share)()));
|
|
18264
18332
|
}
|
|
18265
18333
|
get callEvent$() {
|
|
18266
|
-
return this.cachedObservable("callEvent$", () => this.callSessionEvents$.pipe(filterAs(isSignalwireCallMetadata, "params"), (0, import_cjs$
|
|
18334
|
+
return this.cachedObservable("callEvent$", () => this.callSessionEvents$.pipe(filterAs(isSignalwireCallMetadata, "params"), (0, import_cjs$10.tap)((event) => logger$11.debug("[Call] Event is a call event:", event)), (0, import_cjs$10.takeUntil)(this.destroyed$), (0, import_cjs$10.share)()));
|
|
18267
18335
|
}
|
|
18268
18336
|
get layoutEvent$() {
|
|
18269
18337
|
return this.cachedObservable("layoutEvent$", () => this.callEvent$.pipe(filterAs(isLayoutChangedMetadata, "params")));
|
|
@@ -18356,7 +18424,7 @@ var WebRTCCall = class extends Destroyable {
|
|
|
18356
18424
|
*/
|
|
18357
18425
|
async setLayout(layout, positions) {
|
|
18358
18426
|
if (!this.layouts.includes(layout)) throw new InvalidParams(`Layout ${layout} is not available in the current call layouts: ${this.layouts.join(", ")}`);
|
|
18359
|
-
const selfId = await (0, import_cjs$
|
|
18427
|
+
const selfId = await (0, import_cjs$10.firstValueFrom)(this.selfId$.pipe((0, import_cjs$10.filter)((id) => id !== null)));
|
|
18360
18428
|
await this.executeMethod(selfId, "call.layout.set", {
|
|
18361
18429
|
layout,
|
|
18362
18430
|
positions
|
|
@@ -18397,10 +18465,10 @@ var WebRTCCall = class extends Destroyable {
|
|
|
18397
18465
|
message
|
|
18398
18466
|
};
|
|
18399
18467
|
this.clientSession.execute(WebrtcVerto(params)).catch((error) => {
|
|
18400
|
-
logger$
|
|
18468
|
+
logger$11.warn(`[Call] verto.subscribe for '${eventType}' failed (non-fatal):`, error);
|
|
18401
18469
|
});
|
|
18402
18470
|
} catch (error) {
|
|
18403
|
-
logger$
|
|
18471
|
+
logger$11.warn(`[Call] Failed to send verto.subscribe for '${eventType}':`, error);
|
|
18404
18472
|
}
|
|
18405
18473
|
}
|
|
18406
18474
|
};
|
|
@@ -18422,6 +18490,7 @@ function inferCallErrorKind(error) {
|
|
|
18422
18490
|
function isFatalError(error) {
|
|
18423
18491
|
if (error instanceof VertoPongError) return false;
|
|
18424
18492
|
if (error instanceof MediaTrackError) return false;
|
|
18493
|
+
if (error instanceof RPCTimeoutError) return false;
|
|
18425
18494
|
return true;
|
|
18426
18495
|
}
|
|
18427
18496
|
/**
|
|
@@ -18453,6 +18522,9 @@ var CallFactory = class {
|
|
|
18453
18522
|
callId: callInstance.id
|
|
18454
18523
|
};
|
|
18455
18524
|
callInstance.emitError(callError);
|
|
18525
|
+
},
|
|
18526
|
+
onModifyFailed: () => {
|
|
18527
|
+
callInstance.notifyModifyFailed();
|
|
18456
18528
|
}
|
|
18457
18529
|
}),
|
|
18458
18530
|
callEventsManager: new CallEventsManager(callInstance)
|
|
@@ -18466,8 +18538,8 @@ var CallFactory = class {
|
|
|
18466
18538
|
|
|
18467
18539
|
//#endregion
|
|
18468
18540
|
//#region src/behaviors/Collection.ts
|
|
18469
|
-
var import_cjs$
|
|
18470
|
-
const logger$
|
|
18541
|
+
var import_cjs$9 = require_cjs();
|
|
18542
|
+
const logger$10 = getLogger();
|
|
18471
18543
|
var Fetcher = class {
|
|
18472
18544
|
constructor(endpoint, params, http) {
|
|
18473
18545
|
this.endpoint = endpoint;
|
|
@@ -18491,7 +18563,7 @@ var Fetcher = class {
|
|
|
18491
18563
|
this.hasMore = !!this.nextUrl;
|
|
18492
18564
|
return result.data.filter(this.filter).map(this.mapper);
|
|
18493
18565
|
}
|
|
18494
|
-
logger$
|
|
18566
|
+
logger$10.error("Failed to fetch entity");
|
|
18495
18567
|
return [];
|
|
18496
18568
|
}
|
|
18497
18569
|
async id(v) {
|
|
@@ -18532,10 +18604,10 @@ var EntityCollection = class extends Destroyable {
|
|
|
18532
18604
|
this.values$.next(Array.from(this.collectionData.values()));
|
|
18533
18605
|
};
|
|
18534
18606
|
this._hasMore$ = this.createBehaviorSubject(true);
|
|
18535
|
-
this._destroy$ = new import_cjs$
|
|
18607
|
+
this._destroy$ = new import_cjs$9.Subject();
|
|
18536
18608
|
this.updateSubscription = this.update$.subscribe(this.upsertData);
|
|
18537
18609
|
this.loading$.next(false);
|
|
18538
|
-
this.hasMore$ = (0, import_cjs$
|
|
18610
|
+
this.hasMore$ = (0, import_cjs$9.defer)(() => (0, import_cjs$9.from)(this.init())).pipe((0, import_cjs$9.switchMap)(() => this._hasMore$), (0, import_cjs$9.distinctUntilChanged)(), (0, import_cjs$9.shareReplay)(1), (0, import_cjs$9.takeUntil)(this._destroy$));
|
|
18539
18611
|
}
|
|
18540
18612
|
get loading() {
|
|
18541
18613
|
return this.loading$.value;
|
|
@@ -18544,7 +18616,7 @@ var EntityCollection = class extends Destroyable {
|
|
|
18544
18616
|
return this.fetchController.hasMore ?? true;
|
|
18545
18617
|
}
|
|
18546
18618
|
get updated$() {
|
|
18547
|
-
return this.cachedObservable("updated$", () => this.loading$.pipe((0, import_cjs$
|
|
18619
|
+
return this.cachedObservable("updated$", () => this.loading$.pipe((0, import_cjs$9.distinctUntilChanged)(), (0, import_cjs$9.skip)(1), (0, import_cjs$9.filter)((loading) => !loading), (0, import_cjs$9.map)(() => void 0), (0, import_cjs$9.takeUntil)(this._destroy$)));
|
|
18548
18620
|
}
|
|
18549
18621
|
get values() {
|
|
18550
18622
|
return Array.from(this.collectionData.values());
|
|
@@ -18563,7 +18635,7 @@ var EntityCollection = class extends Destroyable {
|
|
|
18563
18635
|
this._hasMore$.next(this.fetchController.hasMore ?? false);
|
|
18564
18636
|
this.loading$.next(false);
|
|
18565
18637
|
} catch (error) {
|
|
18566
|
-
logger$
|
|
18638
|
+
logger$10.error(`Failed to fetch initial collection data`, error);
|
|
18567
18639
|
this._hasMore$.next(this.fetchController.hasMore ?? false);
|
|
18568
18640
|
this.loading$.next(false);
|
|
18569
18641
|
this.onError?.(new CollectionFetchError("fetchMore", error));
|
|
@@ -18577,14 +18649,14 @@ var EntityCollection = class extends Destroyable {
|
|
|
18577
18649
|
if (data) this.upsertData(data);
|
|
18578
18650
|
return data;
|
|
18579
18651
|
} catch (error) {
|
|
18580
|
-
logger$
|
|
18652
|
+
logger$10.error(`Failed to fetch data for (${String(key)}:${String(value)}) :`, error);
|
|
18581
18653
|
this.loading$.next(false);
|
|
18582
18654
|
this.onError?.(new CollectionFetchError(`tryFetch(${String(key)})`, error));
|
|
18583
18655
|
}
|
|
18584
18656
|
}
|
|
18585
18657
|
get$(id) {
|
|
18586
18658
|
if (!this.observablesRegistry.has(id)) {
|
|
18587
|
-
this.observablesRegistry.set(id, new import_cjs$
|
|
18659
|
+
this.observablesRegistry.set(id, new import_cjs$9.ReplaySubject(1));
|
|
18588
18660
|
const data = this.collectionData.get(id);
|
|
18589
18661
|
if (data) this.observablesRegistry.get(id)?.next(data);
|
|
18590
18662
|
else this.tryFetch("id", id);
|
|
@@ -18608,9 +18680,9 @@ var EntityCollection = class extends Destroyable {
|
|
|
18608
18680
|
}
|
|
18609
18681
|
};
|
|
18610
18682
|
var EntityCollectionTransformed = class {
|
|
18611
|
-
constructor(originalCollection, filter$
|
|
18683
|
+
constructor(originalCollection, filter$17 = (i) => !!i, mapper = (item) => item) {
|
|
18612
18684
|
this.originalCollection = originalCollection;
|
|
18613
|
-
this.filter = filter$
|
|
18685
|
+
this.filter = filter$17;
|
|
18614
18686
|
this.mapper = mapper;
|
|
18615
18687
|
}
|
|
18616
18688
|
get loading$() {
|
|
@@ -18629,15 +18701,15 @@ var EntityCollectionTransformed = class {
|
|
|
18629
18701
|
return this.originalCollection.values.filter(this.filter).map(this.mapper);
|
|
18630
18702
|
}
|
|
18631
18703
|
get values$() {
|
|
18632
|
-
return this._values$ ??= this.originalCollection.values$.pipe((0, import_cjs$
|
|
18704
|
+
return this._values$ ??= this.originalCollection.values$.pipe((0, import_cjs$9.map)((values) => values.filter(this.filter).map(this.mapper)));
|
|
18633
18705
|
}
|
|
18634
18706
|
get$(id) {
|
|
18635
18707
|
const original$ = this.originalCollection.get$(id);
|
|
18636
|
-
return !original$ ? original$ : original$.pipe((0, import_cjs$
|
|
18708
|
+
return !original$ ? original$ : original$.pipe((0, import_cjs$9.pipe)((0, import_cjs$9.filter)(this.filter), (0, import_cjs$9.map)(this.mapper)));
|
|
18637
18709
|
}
|
|
18638
18710
|
async find$(key, value) {
|
|
18639
18711
|
const original$ = await this.originalCollection.find$(key, value);
|
|
18640
|
-
return !original$ ? original$ : original$.pipe((0, import_cjs$
|
|
18712
|
+
return !original$ ? original$ : original$.pipe((0, import_cjs$9.pipe)((0, import_cjs$9.filter)(this.filter), (0, import_cjs$9.map)(this.mapper)));
|
|
18641
18713
|
}
|
|
18642
18714
|
loadMore() {
|
|
18643
18715
|
this.originalCollection.loadMore();
|
|
@@ -18649,7 +18721,7 @@ var EntityCollectionTransformed = class {
|
|
|
18649
18721
|
|
|
18650
18722
|
//#endregion
|
|
18651
18723
|
//#region src/core/entities/Address.ts
|
|
18652
|
-
var import_cjs$
|
|
18724
|
+
var import_cjs$8 = require_cjs();
|
|
18653
18725
|
/**
|
|
18654
18726
|
* Represents a contact or room in the directory.
|
|
18655
18727
|
*
|
|
@@ -18667,8 +18739,8 @@ var Address = class extends Destroyable {
|
|
|
18667
18739
|
if (this._conversationMessages.hasMore) this._conversationMessages.loadMore();
|
|
18668
18740
|
return this._conversationMessages;
|
|
18669
18741
|
};
|
|
18670
|
-
this.textMessages$ = (0, import_cjs$
|
|
18671
|
-
this.history$ = (0, import_cjs$
|
|
18742
|
+
this.textMessages$ = (0, import_cjs$8.defer)(this.initConversationMessages).pipe((0, import_cjs$8.map)(() => this.textMessage), (0, import_cjs$8.shareReplay)(1), (0, import_cjs$8.takeUntil)(this.destroyed$));
|
|
18743
|
+
this.history$ = (0, import_cjs$8.defer)(this.initConversationMessages).pipe((0, import_cjs$8.map)(() => this.history), (0, import_cjs$8.shareReplay)(1), (0, import_cjs$8.takeUntil)(this.destroyed$));
|
|
18672
18744
|
this._state$ = this.createBehaviorSubject(null);
|
|
18673
18745
|
}
|
|
18674
18746
|
/** @internal */
|
|
@@ -18703,7 +18775,7 @@ var Address = class extends Destroyable {
|
|
|
18703
18775
|
}
|
|
18704
18776
|
/** Observable of the human-readable display name. */
|
|
18705
18777
|
get displayName$() {
|
|
18706
|
-
return this.cachedObservable("displayName$", () => this._state$.pipe(filterNull(), (0, import_cjs$
|
|
18778
|
+
return this.cachedObservable("displayName$", () => this._state$.pipe(filterNull(), (0, import_cjs$8.map)((state) => state.display_name), (0, import_cjs$8.takeUntil)(this.destroyed$)));
|
|
18707
18779
|
}
|
|
18708
18780
|
/** Human-readable display name. */
|
|
18709
18781
|
get displayName() {
|
|
@@ -18712,7 +18784,7 @@ var Address = class extends Destroyable {
|
|
|
18712
18784
|
}
|
|
18713
18785
|
/** Observable of the preview image URL. */
|
|
18714
18786
|
get previewUrl$() {
|
|
18715
|
-
return this.cachedObservable("previewUrl$", () => this._state$.pipe(filterNull(), (0, import_cjs$
|
|
18787
|
+
return this.cachedObservable("previewUrl$", () => this._state$.pipe(filterNull(), (0, import_cjs$8.map)((state) => state.preview_url), (0, import_cjs$8.takeUntil)(this.destroyed$)));
|
|
18716
18788
|
}
|
|
18717
18789
|
/** Preview image URL. */
|
|
18718
18790
|
get previewUrl() {
|
|
@@ -18721,7 +18793,7 @@ var Address = class extends Destroyable {
|
|
|
18721
18793
|
}
|
|
18722
18794
|
/** Observable of the cover image URL. */
|
|
18723
18795
|
get coverUrl$() {
|
|
18724
|
-
return this.cachedObservable("coverUrl$", () => this._state$.pipe(filterNull(), (0, import_cjs$
|
|
18796
|
+
return this.cachedObservable("coverUrl$", () => this._state$.pipe(filterNull(), (0, import_cjs$8.shareReplay)(1), (0, import_cjs$8.map)((state) => state.cover_url), (0, import_cjs$8.takeUntil)(this.destroyed$)));
|
|
18725
18797
|
}
|
|
18726
18798
|
/** Cover image URL. */
|
|
18727
18799
|
get coverUrl() {
|
|
@@ -18730,7 +18802,7 @@ var Address = class extends Destroyable {
|
|
|
18730
18802
|
}
|
|
18731
18803
|
/** Observable of the underlying resource ID. */
|
|
18732
18804
|
get resourceId$() {
|
|
18733
|
-
return this.cachedObservable("resourceId$", () => this._state$.pipe(filterNull(), (0, import_cjs$
|
|
18805
|
+
return this.cachedObservable("resourceId$", () => this._state$.pipe(filterNull(), (0, import_cjs$8.shareReplay)(1), (0, import_cjs$8.map)((state) => state.resource_id), (0, import_cjs$8.takeUntil)(this.destroyed$)));
|
|
18734
18806
|
}
|
|
18735
18807
|
/** Underlying resource ID. */
|
|
18736
18808
|
get resourceId() {
|
|
@@ -18739,7 +18811,7 @@ var Address = class extends Destroyable {
|
|
|
18739
18811
|
}
|
|
18740
18812
|
/** Observable of the resource type (e.g. `'room'`, `'subscriber'`). */
|
|
18741
18813
|
get type$() {
|
|
18742
|
-
return this.cachedObservable("type$", () => this._state$.pipe(filterNull(), (0, import_cjs$
|
|
18814
|
+
return this.cachedObservable("type$", () => this._state$.pipe(filterNull(), (0, import_cjs$8.shareReplay)(1), (0, import_cjs$8.map)((state) => state.type), (0, import_cjs$8.takeUntil)(this.destroyed$)));
|
|
18743
18815
|
}
|
|
18744
18816
|
/** Resource type (e.g. `'room'`, `'subscriber'`). */
|
|
18745
18817
|
get type() {
|
|
@@ -18748,7 +18820,7 @@ var Address = class extends Destroyable {
|
|
|
18748
18820
|
}
|
|
18749
18821
|
/** Observable of available communication channels (audio, video, messaging). */
|
|
18750
18822
|
get channels$() {
|
|
18751
|
-
return this.cachedObservable("channels$", () => this._state$.pipe(filterNull(), (0, import_cjs$
|
|
18823
|
+
return this.cachedObservable("channels$", () => this._state$.pipe(filterNull(), (0, import_cjs$8.shareReplay)(1), (0, import_cjs$8.map)((state) => state.channels), (0, import_cjs$8.takeUntil)(this.destroyed$)));
|
|
18752
18824
|
}
|
|
18753
18825
|
/** Available communication channels. */
|
|
18754
18826
|
get channels() {
|
|
@@ -18762,7 +18834,7 @@ var Address = class extends Destroyable {
|
|
|
18762
18834
|
}
|
|
18763
18835
|
/** Observable indicating whether the address (room) is locked. */
|
|
18764
18836
|
get locked$() {
|
|
18765
|
-
return this.cachedObservable("locked$", () => this._state$.pipe(filterNull(), (0, import_cjs$
|
|
18837
|
+
return this.cachedObservable("locked$", () => this._state$.pipe(filterNull(), (0, import_cjs$8.shareReplay)(1), (0, import_cjs$8.map)((state) => state.locked), (0, import_cjs$8.takeUntil)(this.destroyed$)));
|
|
18766
18838
|
}
|
|
18767
18839
|
/**
|
|
18768
18840
|
* Sends a text message to this address.
|
|
@@ -18828,14 +18900,14 @@ var Address = class extends Destroyable {
|
|
|
18828
18900
|
|
|
18829
18901
|
//#endregion
|
|
18830
18902
|
//#region src/core/utils.ts
|
|
18831
|
-
var import_cjs$
|
|
18832
|
-
const logger$
|
|
18903
|
+
var import_cjs$7 = require_cjs();
|
|
18904
|
+
const logger$9 = getLogger();
|
|
18833
18905
|
const isRPCConnectResult = (e) => {
|
|
18834
|
-
logger$
|
|
18906
|
+
logger$9.debug("isRPCConnectResult check:", e);
|
|
18835
18907
|
if (!e || typeof e !== "object") return false;
|
|
18836
18908
|
const result = e;
|
|
18837
18909
|
const is = typeof result.identity === "string" && typeof result.protocol === "string" && typeof result.authorization === "object" && typeof result.authorization.jti === "string" && typeof result.authorization.project_id === "string" && typeof result.authorization.fabric_subscriber === "object";
|
|
18838
|
-
logger$
|
|
18910
|
+
logger$9.debug("isRPCConnectResult check result:", is);
|
|
18839
18911
|
return is;
|
|
18840
18912
|
};
|
|
18841
18913
|
var PendingRPC = class PendingRPC {
|
|
@@ -18844,7 +18916,7 @@ var PendingRPC = class PendingRPC {
|
|
|
18844
18916
|
}
|
|
18845
18917
|
constructor(request, responses$, options) {
|
|
18846
18918
|
this.id = v4_default();
|
|
18847
|
-
logger$
|
|
18919
|
+
logger$9.debug(`[PendingRPC(${this.id}) request:${request.id}: method:${request.method}] Creating PendingRPC`);
|
|
18848
18920
|
this.request = request;
|
|
18849
18921
|
const timeoutMs = options?.timeoutMs ?? PendingRPC.defaultTimeoutMs;
|
|
18850
18922
|
const signal = options?.signal;
|
|
@@ -18854,38 +18926,38 @@ var PendingRPC = class PendingRPC {
|
|
|
18854
18926
|
return;
|
|
18855
18927
|
}
|
|
18856
18928
|
let isSettled = false;
|
|
18857
|
-
const subscription = (0, import_cjs$
|
|
18858
|
-
const timer$
|
|
18929
|
+
const subscription = (0, import_cjs$7.race)(responses$.pipe((0, import_cjs$7.filter)((result) => result.id === request.id), (0, import_cjs$7.take)(1)), new import_cjs$7.Observable((subscriber) => {
|
|
18930
|
+
const timer$3 = setTimeout(() => {
|
|
18859
18931
|
subscriber.error(new RPCTimeoutError(request.id, timeoutMs));
|
|
18860
18932
|
}, timeoutMs);
|
|
18861
|
-
return () => clearTimeout(timer$
|
|
18862
|
-
}), signal ? new import_cjs$
|
|
18933
|
+
return () => clearTimeout(timer$3);
|
|
18934
|
+
}), signal ? new import_cjs$7.Observable((subscriber) => {
|
|
18863
18935
|
const abortHandler = () => {
|
|
18864
18936
|
subscriber.error(new DOMException("The operation was aborted", "AbortError"));
|
|
18865
18937
|
};
|
|
18866
18938
|
signal.addEventListener("abort", abortHandler);
|
|
18867
18939
|
return () => signal.removeEventListener("abort", abortHandler);
|
|
18868
|
-
}) : import_cjs$
|
|
18940
|
+
}) : import_cjs$7.NEVER).subscribe({
|
|
18869
18941
|
next: (response) => {
|
|
18870
18942
|
isSettled = true;
|
|
18871
18943
|
if (response.error) {
|
|
18872
18944
|
const rpcError = new JSONRPCError(response.error.code, response.error.message, response.error.data, void 0, request.id);
|
|
18873
|
-
logger$
|
|
18945
|
+
logger$9.debug(`[PendingRPC(${this.id}) request:${request.id}] Rejecting promise with RPC error:`, rpcError);
|
|
18874
18946
|
reject(rpcError);
|
|
18875
18947
|
} else {
|
|
18876
|
-
logger$
|
|
18948
|
+
logger$9.debug(`[PendingRPC(${this.id}) request:${request.id}] Resolving promise with response:`, response);
|
|
18877
18949
|
resolve(response);
|
|
18878
18950
|
}
|
|
18879
18951
|
subscription.unsubscribe();
|
|
18880
18952
|
},
|
|
18881
18953
|
error: (error) => {
|
|
18882
|
-
logger$
|
|
18954
|
+
logger$9.debug(`[PendingRPC(${this.id}) request:${request.id}] Rejecting promise with error:`, error);
|
|
18883
18955
|
isSettled = true;
|
|
18884
18956
|
reject(error);
|
|
18885
18957
|
subscription.unsubscribe();
|
|
18886
18958
|
},
|
|
18887
18959
|
complete: () => {
|
|
18888
|
-
logger$
|
|
18960
|
+
logger$9.debug(`[PendingRPC(${this.id}) request:${request.id}] Observable completed`);
|
|
18889
18961
|
if (!isSettled) reject(new RPCTimeoutError(request.id, timeoutMs));
|
|
18890
18962
|
subscription.unsubscribe();
|
|
18891
18963
|
}
|
|
@@ -18905,8 +18977,8 @@ var PendingRPC = class PendingRPC {
|
|
|
18905
18977
|
|
|
18906
18978
|
//#endregion
|
|
18907
18979
|
//#region src/managers/ClientSessionManager.ts
|
|
18908
|
-
var import_cjs$
|
|
18909
|
-
const logger$
|
|
18980
|
+
var import_cjs$6 = require_cjs();
|
|
18981
|
+
const logger$8 = getLogger();
|
|
18910
18982
|
const getAddressSearchURI = (options) => {
|
|
18911
18983
|
const to = options.to?.split("?")[0];
|
|
18912
18984
|
const from$9 = options.from?.startsWith("subscriber://") ? options.from.replace("subscriber://", "") : options.from;
|
|
@@ -18941,10 +19013,10 @@ var ClientSessionManager = class extends Destroyable {
|
|
|
18941
19013
|
this._iceServers$ = this.createBehaviorSubject([]);
|
|
18942
19014
|
attachManager.setSession(this);
|
|
18943
19015
|
this.callFactory = new CallFactory(this, deviceController, attachManager, webRTCApiProvider, networkChange$);
|
|
18944
|
-
this.initialized$ = (0, import_cjs$
|
|
19016
|
+
this.initialized$ = (0, import_cjs$6.defer)(() => (0, import_cjs$6.from)(this.init())).pipe((0, import_cjs$6.shareReplay)(1), (0, import_cjs$6.takeUntil)(this.destroyed$));
|
|
18945
19017
|
}
|
|
18946
19018
|
get incomingCalls$() {
|
|
18947
|
-
return this.cachedObservable("incomingCalls$", () => this.calls$.pipe((0, import_cjs$
|
|
19019
|
+
return this.cachedObservable("incomingCalls$", () => this.calls$.pipe((0, import_cjs$6.map)((calls) => calls.filter((call) => call.direction === "inbound"))));
|
|
18948
19020
|
}
|
|
18949
19021
|
get incomingCalls() {
|
|
18950
19022
|
return Object.values(this._calls$.value).filter((call) => call.direction === "inbound");
|
|
@@ -18956,7 +19028,7 @@ var ClientSessionManager = class extends Destroyable {
|
|
|
18956
19028
|
return this._subscriberInfo$.value;
|
|
18957
19029
|
}
|
|
18958
19030
|
get calls$() {
|
|
18959
|
-
return this.cachedObservable("calls$", () => this._calls$.pipe((0, import_cjs$
|
|
19031
|
+
return this.cachedObservable("calls$", () => this._calls$.pipe((0, import_cjs$6.map)((calls) => Object.values(calls))));
|
|
18960
19032
|
}
|
|
18961
19033
|
get calls() {
|
|
18962
19034
|
return Object.values(this._calls$.value);
|
|
@@ -19000,7 +19072,7 @@ var ClientSessionManager = class extends Destroyable {
|
|
|
19000
19072
|
try {
|
|
19001
19073
|
return await this.transport.execute(request, options);
|
|
19002
19074
|
} catch (error) {
|
|
19003
|
-
logger$
|
|
19075
|
+
logger$8.debug("[Session] Execute Error", error);
|
|
19004
19076
|
this._errors$.next(error instanceof Error ? error : new Error(String(error), { cause: error }));
|
|
19005
19077
|
throw error;
|
|
19006
19078
|
}
|
|
@@ -19014,40 +19086,40 @@ var ClientSessionManager = class extends Destroyable {
|
|
|
19014
19086
|
return true;
|
|
19015
19087
|
}
|
|
19016
19088
|
setupMessageHandlers() {
|
|
19017
|
-
logger$
|
|
19089
|
+
logger$8.debug("[Session] Setting up message handlers");
|
|
19018
19090
|
this.subscribeTo(this.authStateEvent$, async (authStateEvent) => {
|
|
19019
|
-
logger$
|
|
19091
|
+
logger$8.debug("[Session] Authorization state event received:", authStateEvent);
|
|
19020
19092
|
try {
|
|
19021
19093
|
await this.updateAuthorizationStateInStorage(authStateEvent.authorization_state);
|
|
19022
19094
|
} catch (error) {
|
|
19023
|
-
logger$
|
|
19095
|
+
logger$8.error("[Session] Failed to handle authorization state update:", error);
|
|
19024
19096
|
this._errors$.next(new AuthStateHandlerError(error));
|
|
19025
19097
|
}
|
|
19026
19098
|
});
|
|
19027
|
-
this.subscribeTo(this.transport.connectionStatus$.pipe((0, import_cjs$
|
|
19028
|
-
logger$
|
|
19029
|
-
return (0, import_cjs$
|
|
19099
|
+
this.subscribeTo(this.transport.connectionStatus$.pipe((0, import_cjs$6.filter)((status) => status === "connected"), (0, import_cjs$6.exhaustMap)(() => {
|
|
19100
|
+
logger$8.debug("[Session] Connection established, initiating authentication");
|
|
19101
|
+
return (0, import_cjs$6.from)(this.authenticate()).pipe((0, import_cjs$6.catchError)((error) => {
|
|
19030
19102
|
this.handleAuthenticationError(error).catch((err) => {
|
|
19031
|
-
logger$
|
|
19103
|
+
logger$8.error("[Session] Error handling authentication failure:", err);
|
|
19032
19104
|
});
|
|
19033
|
-
return import_cjs$
|
|
19105
|
+
return import_cjs$6.EMPTY;
|
|
19034
19106
|
}));
|
|
19035
19107
|
})), void 0);
|
|
19036
19108
|
this.subscribeTo(this.vertoInvite$, async (invite) => {
|
|
19037
|
-
logger$
|
|
19109
|
+
logger$8.debug("[Session] Verto invite received:", invite);
|
|
19038
19110
|
try {
|
|
19039
19111
|
await this.createInboundCall(invite);
|
|
19040
19112
|
} catch (error) {
|
|
19041
|
-
logger$
|
|
19113
|
+
logger$8.error("[Session] Error handling Verto invite:", error);
|
|
19042
19114
|
this._errors$.next(new VertoInviteHandlerError(error));
|
|
19043
19115
|
}
|
|
19044
19116
|
});
|
|
19045
19117
|
this.subscribeTo(this.vertoAttach$, async (attach) => {
|
|
19046
|
-
logger$
|
|
19118
|
+
logger$8.debug("[Session] Verto attach received:", attach);
|
|
19047
19119
|
try {
|
|
19048
19120
|
await this.handleVertoAttach(attach);
|
|
19049
19121
|
} catch (error) {
|
|
19050
|
-
logger$
|
|
19122
|
+
logger$8.error("[Session] Error handling Verto attach:", error);
|
|
19051
19123
|
this._errors$.next(new VertoAttachHandlerError(error));
|
|
19052
19124
|
}
|
|
19053
19125
|
});
|
|
@@ -19057,49 +19129,49 @@ var ClientSessionManager = class extends Destroyable {
|
|
|
19057
19129
|
const storedState = await this.storage.getItem(this.authorizationStateKey);
|
|
19058
19130
|
this.authorizationState$.next(storedState ?? void 0);
|
|
19059
19131
|
} catch (error) {
|
|
19060
|
-
logger$
|
|
19132
|
+
logger$8.error("Failed to retrieve authorization state from storage:", error);
|
|
19061
19133
|
this.authorizationState$.next(void 0);
|
|
19062
19134
|
}
|
|
19063
19135
|
}
|
|
19064
19136
|
async updateAuthorizationStateInStorage(authorizationState) {
|
|
19065
19137
|
if (!authorizationState) {
|
|
19066
|
-
logger$
|
|
19138
|
+
logger$8.debug("[Session] Removing authorization state from storage");
|
|
19067
19139
|
try {
|
|
19068
19140
|
await this.storage.removeItem(this.authorizationStateKey);
|
|
19069
19141
|
this.authorizationState$.next(void 0);
|
|
19070
19142
|
} catch (error) {
|
|
19071
|
-
logger$
|
|
19143
|
+
logger$8.error("Failed to remove authorization state from storage:", error);
|
|
19072
19144
|
throw error;
|
|
19073
19145
|
}
|
|
19074
19146
|
return;
|
|
19075
19147
|
}
|
|
19076
19148
|
try {
|
|
19077
|
-
logger$
|
|
19149
|
+
logger$8.debug("[Session] Updating authorization state in storage");
|
|
19078
19150
|
await this.storage.setItem(this.authorizationStateKey, authorizationState);
|
|
19079
19151
|
this.authorizationState$.next(authorizationState);
|
|
19080
19152
|
} catch (error) {
|
|
19081
|
-
logger$
|
|
19153
|
+
logger$8.error("Failed to retrieve authorization state from storage:", error);
|
|
19082
19154
|
throw error;
|
|
19083
19155
|
}
|
|
19084
19156
|
}
|
|
19085
19157
|
get authStateEvent$() {
|
|
19086
|
-
return this.cachedObservable("authStateEvent$", () => this.signalingEvent$.pipe((0, import_cjs$
|
|
19087
|
-
logger$
|
|
19088
|
-
}), filterAs(isSignalwireAuthorizationStateMetadata, "params"), (0, import_cjs$
|
|
19089
|
-
logger$
|
|
19158
|
+
return this.cachedObservable("authStateEvent$", () => this.signalingEvent$.pipe((0, import_cjs$6.tap)((msg) => {
|
|
19159
|
+
logger$8.debug("[Session] Received incoming message:", msg);
|
|
19160
|
+
}), filterAs(isSignalwireAuthorizationStateMetadata, "params"), (0, import_cjs$6.tap)((event) => {
|
|
19161
|
+
logger$8.debug("[Session] Authorization state event received:", event.authorization_state);
|
|
19090
19162
|
})));
|
|
19091
19163
|
}
|
|
19092
19164
|
get signalingEvent$() {
|
|
19093
|
-
return this.cachedObservable("signalingEvent$", () => this.transport.incomingEvent$.pipe(filterAs(isSignalwireRequest, "params"), (0, import_cjs$
|
|
19165
|
+
return this.cachedObservable("signalingEvent$", () => this.transport.incomingEvent$.pipe(filterAs(isSignalwireRequest, "params"), (0, import_cjs$6.share)()));
|
|
19094
19166
|
}
|
|
19095
19167
|
get vertoInvite$() {
|
|
19096
|
-
return this.cachedObservable("vertoInvite$", () => this.signalingEvent$.pipe((0, import_cjs$
|
|
19168
|
+
return this.cachedObservable("vertoInvite$", () => this.signalingEvent$.pipe((0, import_cjs$6.filter)(isWebrtcMessageMetadata), (0, import_cjs$6.filter)((event) => isVertoInviteMessage(event.params)), (0, import_cjs$6.map)((event) => ({
|
|
19097
19169
|
node_id: event.node_id,
|
|
19098
19170
|
...event.params.params
|
|
19099
19171
|
}))));
|
|
19100
19172
|
}
|
|
19101
19173
|
get vertoAttach$() {
|
|
19102
|
-
return this.cachedObservable("vertoAttach$", () => this.signalingEvent$.pipe((0, import_cjs$
|
|
19174
|
+
return this.cachedObservable("vertoAttach$", () => this.signalingEvent$.pipe((0, import_cjs$6.filter)(isWebrtcMessageMetadata), (0, import_cjs$6.filter)((event) => isVertoAttachMessage(event.params)), (0, import_cjs$6.map)((event) => ({
|
|
19103
19175
|
node_id: event.node_id,
|
|
19104
19176
|
...event.params.params
|
|
19105
19177
|
}))));
|
|
@@ -19119,20 +19191,20 @@ var ClientSessionManager = class extends Destroyable {
|
|
|
19119
19191
|
return { jwt_token: credential.token };
|
|
19120
19192
|
}
|
|
19121
19193
|
async connect() {
|
|
19122
|
-
await (0, import_cjs$
|
|
19194
|
+
await (0, import_cjs$6.firstValueFrom)(this.initialized$);
|
|
19123
19195
|
await this.transport.connect();
|
|
19124
|
-
await (0, import_cjs$
|
|
19196
|
+
await (0, import_cjs$6.firstValueFrom)(this.authenticated$.pipe((0, import_cjs$6.takeUntil)(this.destroyed$), (0, import_cjs$6.filter)(Boolean), (0, import_cjs$6.take)(1), (0, import_cjs$6.timeout)({ first: 15e3 })));
|
|
19125
19197
|
}
|
|
19126
19198
|
async handleAuthenticationError(error) {
|
|
19127
|
-
logger$
|
|
19199
|
+
logger$8.error("Authentication error:", error);
|
|
19128
19200
|
const isRecoverableAuthError = error instanceof JSONRPCError && (error.code === RPC_ERROR_REQUESTER_VALIDATION_FAILED || error.code === RPC_ERROR_INVALID_PARAMS || error.code === RPC_ERROR_AUTHENTICATION_FAILED);
|
|
19129
|
-
const hasStoredState = await (0, import_cjs$
|
|
19201
|
+
const hasStoredState = await (0, import_cjs$6.firstValueFrom)(this.authorizationState$.pipe((0, import_cjs$6.take)(1))) !== void 0;
|
|
19130
19202
|
if (isRecoverableAuthError && hasStoredState) {
|
|
19131
|
-
logger$
|
|
19203
|
+
logger$8.debug("[Session] Recoverable auth error — cleaning up stored state and reconnecting fresh");
|
|
19132
19204
|
try {
|
|
19133
19205
|
await this.cleanupStoredConnectionParams();
|
|
19134
19206
|
} catch (cleanupError) {
|
|
19135
|
-
logger$
|
|
19207
|
+
logger$8.error("Failed to cleanup stored connection params:", cleanupError);
|
|
19136
19208
|
} finally {
|
|
19137
19209
|
this.transport.reconnect();
|
|
19138
19210
|
}
|
|
@@ -19147,44 +19219,44 @@ var ClientSessionManager = class extends Destroyable {
|
|
|
19147
19219
|
try {
|
|
19148
19220
|
await this.storage.setItem(this.authorizationStateKey, authorization_state);
|
|
19149
19221
|
} catch (error) {
|
|
19150
|
-
logger$
|
|
19222
|
+
logger$8.error("Failed to update authorization state in storage:", error);
|
|
19151
19223
|
this._errors$.next(new AuthStateHandlerError(error));
|
|
19152
19224
|
}
|
|
19153
19225
|
}
|
|
19154
19226
|
async reauthenticate(token, dpopToken, options) {
|
|
19155
|
-
logger$
|
|
19227
|
+
logger$8.debug("[Session] Re-authenticating session");
|
|
19156
19228
|
try {
|
|
19157
19229
|
let resolvedDpopToken = dpopToken;
|
|
19158
19230
|
if (!resolvedDpopToken && this.dpopManager?.initialized) try {
|
|
19159
19231
|
resolvedDpopToken = await this.dpopManager.createRpcProof({ method: "signalwire.reauthenticate" });
|
|
19160
19232
|
} catch (error) {
|
|
19161
19233
|
if (this._clientBound) throw error;
|
|
19162
|
-
logger$
|
|
19234
|
+
logger$8.warn("[Session] Failed to create DPoP proof for reauthenticate:", error);
|
|
19163
19235
|
}
|
|
19164
19236
|
const request = RPCReauthenticate({
|
|
19165
19237
|
project: this._authorization$.value?.project_id ?? "",
|
|
19166
19238
|
jwt_token: token,
|
|
19167
19239
|
...resolvedDpopToken ? { dpop_token: resolvedDpopToken } : {}
|
|
19168
19240
|
});
|
|
19169
|
-
await (0, import_cjs$
|
|
19170
|
-
logger$
|
|
19241
|
+
await (0, import_cjs$6.lastValueFrom)((0, import_cjs$6.from)(this.transport.execute(request)).pipe(throwOnRPCError(), (0, import_cjs$6.take)(1), (0, import_cjs$6.catchError)((err) => {
|
|
19242
|
+
logger$8.error("[Session] Re-authentication RPC failed:", err);
|
|
19171
19243
|
throw err;
|
|
19172
19244
|
})));
|
|
19173
19245
|
if (options?.clientBound) this._clientBound = true;
|
|
19174
|
-
logger$
|
|
19246
|
+
logger$8.debug("[Session] Re-authentication successful, updating stored auth state");
|
|
19175
19247
|
} catch (error) {
|
|
19176
|
-
logger$
|
|
19248
|
+
logger$8.error("[Session] Re-authentication failed:", error);
|
|
19177
19249
|
this._errors$.next(new AuthStateHandlerError(error));
|
|
19178
19250
|
throw error;
|
|
19179
19251
|
}
|
|
19180
19252
|
}
|
|
19181
19253
|
async authenticate() {
|
|
19182
|
-
logger$
|
|
19183
|
-
const persistedParams = await (0, import_cjs$
|
|
19254
|
+
logger$8.debug("[Session] Starting authentication process");
|
|
19255
|
+
const persistedParams = await (0, import_cjs$6.firstValueFrom)((0, import_cjs$6.combineLatest)({
|
|
19184
19256
|
protocol: this.transport.protocol$,
|
|
19185
19257
|
authorization_state: this.authorizationState$
|
|
19186
|
-
}).pipe((0, import_cjs$
|
|
19187
|
-
logger$
|
|
19258
|
+
}).pipe((0, import_cjs$6.take)(1)));
|
|
19259
|
+
logger$8.debug("[Session] Persisted params:\n", {
|
|
19188
19260
|
protocol: persistedParams.protocol,
|
|
19189
19261
|
authStateLength: persistedParams.authorization_state?.length
|
|
19190
19262
|
});
|
|
@@ -19192,16 +19264,16 @@ var ClientSessionManager = class extends Destroyable {
|
|
|
19192
19264
|
const storedToken = this.getCredential().token;
|
|
19193
19265
|
const isReconnect = hasReconnectState && storedToken;
|
|
19194
19266
|
let dpopToken;
|
|
19195
|
-
if (isReconnect) logger$
|
|
19267
|
+
if (isReconnect) logger$8.debug("[Session] Reconnecting with stored jwt_token + authorization_state");
|
|
19196
19268
|
else if (this.onBeforeReconnect && this._clientBound) {
|
|
19197
|
-
logger$
|
|
19269
|
+
logger$8.debug("[Session] Refreshing credentials before fresh connect");
|
|
19198
19270
|
await this.onBeforeReconnect();
|
|
19199
19271
|
}
|
|
19200
19272
|
if ((!isReconnect || this._clientBound) && this.dpopManager?.initialized) try {
|
|
19201
19273
|
dpopToken = await this.dpopManager.createRpcProof({ method: "signalwire.connect" });
|
|
19202
19274
|
} catch (error) {
|
|
19203
19275
|
if (this._clientBound) throw error;
|
|
19204
|
-
logger$
|
|
19276
|
+
logger$8.warn("[Session] Failed to create DPoP proof for connect, proceeding without:", error);
|
|
19205
19277
|
}
|
|
19206
19278
|
const rpcConnectRequest = RPCConnect({
|
|
19207
19279
|
authentication: isReconnect ? { jwt_token: storedToken } : this.authentication,
|
|
@@ -19217,13 +19289,13 @@ var ClientSessionManager = class extends Destroyable {
|
|
|
19217
19289
|
protocol: persistedParams.protocol
|
|
19218
19290
|
} : {}
|
|
19219
19291
|
});
|
|
19220
|
-
const response = await (0, import_cjs$
|
|
19221
|
-
logger$
|
|
19222
|
-
}), (0, import_cjs$
|
|
19223
|
-
logger$
|
|
19292
|
+
const response = await (0, import_cjs$6.lastValueFrom)((0, import_cjs$6.from)(this.transport.execute(rpcConnectRequest)).pipe(throwOnRPCError(), (0, import_cjs$6.map)((res) => res.result), (0, import_cjs$6.filter)(isRPCConnectResult), (0, import_cjs$6.tap)(() => {
|
|
19293
|
+
logger$8.debug("[Session] Response passed filter, processing authentication result");
|
|
19294
|
+
}), (0, import_cjs$6.take)(1), (0, import_cjs$6.catchError)((err) => {
|
|
19295
|
+
logger$8.error("[Session] Authentication RPC failed:", err);
|
|
19224
19296
|
throw err;
|
|
19225
19297
|
})));
|
|
19226
|
-
logger$
|
|
19298
|
+
logger$8.debug("[Session] Processing authentication result:", {
|
|
19227
19299
|
hasProtocol: !!response.protocol,
|
|
19228
19300
|
hasAuthorization: !!response.authorization,
|
|
19229
19301
|
hasIceServers: !!response.ice_servers
|
|
@@ -19232,7 +19304,7 @@ var ClientSessionManager = class extends Destroyable {
|
|
|
19232
19304
|
this._authorization$.next(response.authorization);
|
|
19233
19305
|
this._iceServers$.next(response.ice_servers ?? []);
|
|
19234
19306
|
this._authenticated$.next(true);
|
|
19235
|
-
logger$
|
|
19307
|
+
logger$8.debug("[Session] Authentication completed successfully");
|
|
19236
19308
|
}
|
|
19237
19309
|
async disconnect() {
|
|
19238
19310
|
this.transport.disconnect();
|
|
@@ -19251,7 +19323,7 @@ var ClientSessionManager = class extends Destroyable {
|
|
|
19251
19323
|
displayDirection: invite.display_direction,
|
|
19252
19324
|
userVariables: invite.userVariables
|
|
19253
19325
|
});
|
|
19254
|
-
await (0, import_cjs$
|
|
19326
|
+
await (0, import_cjs$6.firstValueFrom)(callSession.status$);
|
|
19255
19327
|
this._calls$.next({
|
|
19256
19328
|
[`${callSession.id}`]: callSession,
|
|
19257
19329
|
...this._calls$.value
|
|
@@ -19269,11 +19341,11 @@ var ClientSessionManager = class extends Destroyable {
|
|
|
19269
19341
|
async handleVertoAttach(attach) {
|
|
19270
19342
|
const { callID } = attach;
|
|
19271
19343
|
if (callID in this._calls$.value) {
|
|
19272
|
-
logger$
|
|
19344
|
+
logger$8.debug(`[Session] Verto attach for existing call ${callID}, deferring to per-call handler`);
|
|
19273
19345
|
return;
|
|
19274
19346
|
}
|
|
19275
19347
|
const storedOptions = this.attachManager.consumePendingAttachment(callID);
|
|
19276
|
-
logger$
|
|
19348
|
+
logger$8.debug(`[Session] Creating reattached call for callID: ${callID}`);
|
|
19277
19349
|
const callSession = await this.createCall({
|
|
19278
19350
|
nodeId: attach.node_id,
|
|
19279
19351
|
callId: callID,
|
|
@@ -19284,7 +19356,7 @@ var ClientSessionManager = class extends Destroyable {
|
|
|
19284
19356
|
reattach: true,
|
|
19285
19357
|
...storedOptions
|
|
19286
19358
|
});
|
|
19287
|
-
await (0, import_cjs$
|
|
19359
|
+
await (0, import_cjs$6.firstValueFrom)(callSession.status$);
|
|
19288
19360
|
this._calls$.next({
|
|
19289
19361
|
[`${callSession.id}`]: callSession,
|
|
19290
19362
|
...this._calls$.value
|
|
@@ -19298,16 +19370,16 @@ var ClientSessionManager = class extends Destroyable {
|
|
|
19298
19370
|
to: destinationURI,
|
|
19299
19371
|
...options
|
|
19300
19372
|
});
|
|
19301
|
-
await (0, import_cjs$
|
|
19373
|
+
await (0, import_cjs$6.firstValueFrom)((0, import_cjs$6.race)(callSession.selfId$.pipe((0, import_cjs$6.filter)((id) => Boolean(id)), (0, import_cjs$6.take)(1), (0, import_cjs$6.timeout)(this.callCreateTimeout)), callSession.errors$.pipe((0, import_cjs$6.take)(1), (0, import_cjs$6.switchMap)((callError) => (0, import_cjs$6.throwError)(() => callError.error)))));
|
|
19302
19374
|
this._calls$.next({
|
|
19303
19375
|
[`${callSession.id}`]: callSession,
|
|
19304
19376
|
...this._calls$.value
|
|
19305
19377
|
});
|
|
19306
19378
|
return callSession;
|
|
19307
19379
|
} catch (error) {
|
|
19308
|
-
logger$
|
|
19380
|
+
logger$8.error("[Session] Error creating outbound call:", error);
|
|
19309
19381
|
callSession?.destroy();
|
|
19310
|
-
const callError = new CallCreateError(error instanceof import_cjs$
|
|
19382
|
+
const callError = new CallCreateError(error instanceof import_cjs$6.TimeoutError ? "Call create timeout" : "Call creation failed", error, "outbound");
|
|
19311
19383
|
this._errors$.next(callError);
|
|
19312
19384
|
throw callError;
|
|
19313
19385
|
}
|
|
@@ -19323,16 +19395,16 @@ var ClientSessionManager = class extends Destroyable {
|
|
|
19323
19395
|
address = this._directory.get(addressId);
|
|
19324
19396
|
if (!address) throw new DependencyError(`Address ID: ${addressId} not found`);
|
|
19325
19397
|
} catch {
|
|
19326
|
-
logger$
|
|
19398
|
+
logger$8.warn(`[Session] Directory lookup failed for ${addressURI}, proceeding with raw URI`);
|
|
19327
19399
|
}
|
|
19328
19400
|
const callSession = this.callFactory.createCall(address, { ...options });
|
|
19329
|
-
this.subscribeTo(callSession.status$.pipe((0, import_cjs$
|
|
19401
|
+
this.subscribeTo(callSession.status$.pipe((0, import_cjs$6.filter)((status) => status === "destroyed"), (0, import_cjs$6.take)(1)), () => {
|
|
19330
19402
|
const { [`${callSession.id}`]: _, ...remainingCalls } = this._calls$.value;
|
|
19331
19403
|
this._calls$.next(remainingCalls);
|
|
19332
19404
|
});
|
|
19333
19405
|
return callSession;
|
|
19334
19406
|
} catch (error) {
|
|
19335
|
-
logger$
|
|
19407
|
+
logger$8.error("[Session] Error creating call session:", error);
|
|
19336
19408
|
throw new CallCreateError("Call create error", error, options.initOffer ? "inbound" : "outbound");
|
|
19337
19409
|
}
|
|
19338
19410
|
}
|
|
@@ -19380,8 +19452,8 @@ const isString = (obj) => typeof obj === "string";
|
|
|
19380
19452
|
|
|
19381
19453
|
//#endregion
|
|
19382
19454
|
//#region src/managers/ConversationsManager.ts
|
|
19383
|
-
var import_cjs$
|
|
19384
|
-
const logger$
|
|
19455
|
+
var import_cjs$5 = require_cjs();
|
|
19456
|
+
const logger$7 = getLogger();
|
|
19385
19457
|
var ConversationMessagesFetcher = class extends Fetcher {
|
|
19386
19458
|
constructor(groupId, http) {
|
|
19387
19459
|
super(`/api/fabric/conversations/${groupId}/messages`, "page_size=100", http);
|
|
@@ -19421,13 +19493,13 @@ var ConversationsManager = class {
|
|
|
19421
19493
|
}
|
|
19422
19494
|
throw new ConversationError("Join Failed - Unexpected response");
|
|
19423
19495
|
} catch (error) {
|
|
19424
|
-
logger$
|
|
19496
|
+
logger$7.error("[ConversationsManager] Failed to join conversation:", error);
|
|
19425
19497
|
throw error;
|
|
19426
19498
|
}
|
|
19427
19499
|
}
|
|
19428
19500
|
async getConversationMessageCollection(addressId) {
|
|
19429
19501
|
const groupId = this.groupIds.get(addressId) ?? await this.join(addressId);
|
|
19430
|
-
return Promise.resolve(new ConversationMessageCollection(groupId, this.clientSession.signalingEvent$.pipe(filterAs(isConversationMessageMetadata, "params"), (0, import_cjs$
|
|
19502
|
+
return Promise.resolve(new ConversationMessageCollection(groupId, this.clientSession.signalingEvent$.pipe(filterAs(isConversationMessageMetadata, "params"), (0, import_cjs$5.tap)((event) => logger$7.debug("[ConversationsManager ] Conversation Event:", event)), (0, import_cjs$5.map)((params) => ({ ...params }))), this.http, this.onError));
|
|
19431
19503
|
}
|
|
19432
19504
|
async sendText(text, destinationAddressId) {
|
|
19433
19505
|
const groupId = this.groupIds.get(destinationAddressId) ?? await this.join(destinationAddressId);
|
|
@@ -19444,12 +19516,222 @@ var ConversationsManager = class {
|
|
|
19444
19516
|
})).ok) return;
|
|
19445
19517
|
throw new ConversationError("Send Text Failed - Unexpected response");
|
|
19446
19518
|
} catch (error) {
|
|
19447
|
-
logger$
|
|
19519
|
+
logger$7.error("[ConversationsManager] Failed to send text message:", error);
|
|
19448
19520
|
throw error;
|
|
19449
19521
|
}
|
|
19450
19522
|
}
|
|
19451
19523
|
};
|
|
19452
19524
|
|
|
19525
|
+
//#endregion
|
|
19526
|
+
//#region src/managers/DeviceTokenManager.ts
|
|
19527
|
+
var import_cjs$4 = require_cjs();
|
|
19528
|
+
const logger$6 = getLogger();
|
|
19529
|
+
/**
|
|
19530
|
+
* Resolves the token expiry timestamp (epoch seconds) using a 3-tier priority chain:
|
|
19531
|
+
* 1. `data.expires_at` — server-provided absolute timestamp
|
|
19532
|
+
* 2. `data.expires_in` — server-provided relative lifetime
|
|
19533
|
+
* 3. Fallback to `DEVICE_TOKEN_DEFAULT_EXPIRE_IN` with a warning
|
|
19534
|
+
*/
|
|
19535
|
+
function resolveExpiresAt(data) {
|
|
19536
|
+
if (data.expires_at) return data.expires_at;
|
|
19537
|
+
if (data.expires_in) return Math.floor(Date.now() / 1e3) + data.expires_in;
|
|
19538
|
+
logger$6.warn("[DeviceToken] Could not determine token expiry, using default");
|
|
19539
|
+
return Math.floor(Date.now() / 1e3) + DEVICE_TOKEN_DEFAULT_EXPIRE_IN;
|
|
19540
|
+
}
|
|
19541
|
+
/**
|
|
19542
|
+
* Resolves the token TTL in seconds from a fresh response.
|
|
19543
|
+
* Called at token receive time so `expires_at - now` reflects the original lifetime.
|
|
19544
|
+
*
|
|
19545
|
+
* 1. `data.expires_in` — server-provided TTL directly
|
|
19546
|
+
* 2. `data.expires_at - now` — derive TTL from absolute timestamp
|
|
19547
|
+
* 3. Fallback to `DEVICE_TOKEN_DEFAULT_EXPIRE_IN`
|
|
19548
|
+
*/
|
|
19549
|
+
function resolveExpireIn(data) {
|
|
19550
|
+
if (data.expires_in) return data.expires_in;
|
|
19551
|
+
if (data.expires_at) return Math.max(data.expires_at - Math.floor(Date.now() / 1e3), 1);
|
|
19552
|
+
return DEVICE_TOKEN_DEFAULT_EXPIRE_IN;
|
|
19553
|
+
}
|
|
19554
|
+
/**
|
|
19555
|
+
* Manages the Client Bound SAT lifecycle: activation, token exchange,
|
|
19556
|
+
* reauthentication, and automatic refresh scheduling.
|
|
19557
|
+
*
|
|
19558
|
+
* Extends {@link Destroyable} for automatic RxJS subscription and subject cleanup.
|
|
19559
|
+
* Uses a reactive pipeline (`BehaviorSubject` + `switchMap(timer())`) instead of
|
|
19560
|
+
* raw `setTimeout` for refresh scheduling.
|
|
19561
|
+
*/
|
|
19562
|
+
var DeviceTokenManager = class extends Destroyable {
|
|
19563
|
+
constructor(dpopManager, http, errorHandler, getCredential) {
|
|
19564
|
+
super();
|
|
19565
|
+
this.dpopManager = dpopManager;
|
|
19566
|
+
this.http = http;
|
|
19567
|
+
this.errorHandler = errorHandler;
|
|
19568
|
+
this.getCredential = getCredential;
|
|
19569
|
+
this._currentToken$ = this.createBehaviorSubject(null);
|
|
19570
|
+
this._refreshInProgress = false;
|
|
19571
|
+
this._effectiveExpireIn = DEVICE_TOKEN_DEFAULT_EXPIRE_IN;
|
|
19572
|
+
this.subscribeTo(this._currentToken$.pipe((0, import_cjs$4.filter)(Boolean), (0, import_cjs$4.switchMap)((tokenData) => {
|
|
19573
|
+
const expiresAt = resolveExpiresAt(tokenData);
|
|
19574
|
+
const refreshIn = Math.max(expiresAt * 1e3 - Date.now() - DEVICE_TOKEN_REFRESH_BUFFER_MS, 1e3);
|
|
19575
|
+
logger$6.debug(`[DeviceToken] Scheduling Client Bound SAT refresh in ${refreshIn}ms`);
|
|
19576
|
+
return (0, import_cjs$4.timer)(refreshIn);
|
|
19577
|
+
})), () => {
|
|
19578
|
+
this.executeRefresh();
|
|
19579
|
+
});
|
|
19580
|
+
}
|
|
19581
|
+
/** Current token TTL in milliseconds. Used to extend cached credential expiry on refresh. */
|
|
19582
|
+
get effectiveExpireIn() {
|
|
19583
|
+
return this._effectiveExpireIn;
|
|
19584
|
+
}
|
|
19585
|
+
/**
|
|
19586
|
+
* Activates the Client Bound SAT flow when the subscriber's token has
|
|
19587
|
+
* `sat:refresh` scope.
|
|
19588
|
+
*
|
|
19589
|
+
* Steps:
|
|
19590
|
+
* 1. Check subscriber's `sat_claims` for `sat:refresh` scope
|
|
19591
|
+
* 2. Call `/api/fabric/subscriber/devices/token` with a DPoP proof
|
|
19592
|
+
* 3. Reauthenticate the session with the Client Bound SAT + DPoP proof
|
|
19593
|
+
* 4. Emit token to trigger the reactive refresh pipeline
|
|
19594
|
+
*/
|
|
19595
|
+
async activate(subscriber, session, updateCredential) {
|
|
19596
|
+
const { satClaims } = subscriber;
|
|
19597
|
+
if (!satClaims?.scope?.includes(SAT_REFRESH_SCOPE)) {
|
|
19598
|
+
logger$6.debug("[DeviceToken] No sat:refresh scope, skipping Client Bound SAT activation");
|
|
19599
|
+
return;
|
|
19600
|
+
}
|
|
19601
|
+
this._session = session;
|
|
19602
|
+
this._updateCredential = updateCredential;
|
|
19603
|
+
try {
|
|
19604
|
+
const tokenData = await this.obtainToken();
|
|
19605
|
+
if (!tokenData.expires_at && !tokenData.expires_in && satClaims.expires_at) tokenData.expires_at = satClaims.expires_at;
|
|
19606
|
+
this._effectiveExpireIn = resolveExpireIn(tokenData);
|
|
19607
|
+
const rpcProof = await this.dpopManager.createRpcProof({ method: "signalwire.reauthenticate" });
|
|
19608
|
+
await session.reauthenticate(tokenData.token, rpcProof, { clientBound: true });
|
|
19609
|
+
updateCredential({ token: tokenData.token });
|
|
19610
|
+
logger$6.info("[DeviceToken] Client Bound SAT activated successfully");
|
|
19611
|
+
this._currentToken$.next(tokenData);
|
|
19612
|
+
} catch (error) {
|
|
19613
|
+
logger$6.error("[DeviceToken] Failed to activate Client Bound SAT:", error);
|
|
19614
|
+
this.errorHandler(new DPoPInitError(error, "Failed to activate Client Bound SAT"));
|
|
19615
|
+
const credential = this.getCredential();
|
|
19616
|
+
const expiresAt = satClaims.expires_at ?? (credential.expiry_at ? credential.expiry_at / 1e3 : Date.now() / 1e3 + DEVICE_TOKEN_DEFAULT_EXPIRE_IN / 1e3);
|
|
19617
|
+
this._currentToken$.next({
|
|
19618
|
+
token: credential.token ?? "",
|
|
19619
|
+
expires_at: expiresAt
|
|
19620
|
+
});
|
|
19621
|
+
}
|
|
19622
|
+
}
|
|
19623
|
+
/**
|
|
19624
|
+
* Obtains a Client Bound SAT from `/api/fabric/subscriber/devices/token`.
|
|
19625
|
+
* Returns the full {@link DeviceTokenResponse} including expiry metadata.
|
|
19626
|
+
*/
|
|
19627
|
+
async obtainToken() {
|
|
19628
|
+
const dpopProof = await this.dpopManager.createHttpProof({
|
|
19629
|
+
method: "POST",
|
|
19630
|
+
uri: DEVICE_TOKEN_ENDPOINT
|
|
19631
|
+
});
|
|
19632
|
+
const response = await this.http.request({
|
|
19633
|
+
url: DEVICE_TOKEN_ENDPOINT,
|
|
19634
|
+
...POST_PARAMS,
|
|
19635
|
+
body: JSON.stringify({
|
|
19636
|
+
dpop_token: dpopProof,
|
|
19637
|
+
expire_in: DEVICE_TOKEN_DEFAULT_EXPIRE_IN
|
|
19638
|
+
})
|
|
19639
|
+
});
|
|
19640
|
+
if (!response.ok || !response.body) throw new DeviceTokenError(`Failed to obtain device token: ${response.status} ${response.statusText}`);
|
|
19641
|
+
const data = JSON.parse(response.body);
|
|
19642
|
+
if (!data.token) throw new DeviceTokenError("Device token response missing token field");
|
|
19643
|
+
return data;
|
|
19644
|
+
}
|
|
19645
|
+
/**
|
|
19646
|
+
* Refreshes the Client Bound SAT via `/api/fabric/subscriber/devices/refresh`.
|
|
19647
|
+
*
|
|
19648
|
+
* Creates a fresh DPoP proof, calls the refresh endpoint, reauthenticates
|
|
19649
|
+
* the WebSocket session, and returns the new token data (scheduling is
|
|
19650
|
+
* handled by the reactive pipeline).
|
|
19651
|
+
*/
|
|
19652
|
+
async refreshToken(session, currentToken, updateCredential) {
|
|
19653
|
+
logger$6.debug("[DeviceToken] Refreshing Client Bound SAT");
|
|
19654
|
+
const dpopProof = await this.dpopManager.createHttpProof({
|
|
19655
|
+
method: "POST",
|
|
19656
|
+
uri: DEVICE_REFRESH_ENDPOINT,
|
|
19657
|
+
accessToken: currentToken
|
|
19658
|
+
});
|
|
19659
|
+
const response = await this.http.request({
|
|
19660
|
+
url: DEVICE_REFRESH_ENDPOINT,
|
|
19661
|
+
...POST_PARAMS,
|
|
19662
|
+
body: JSON.stringify({
|
|
19663
|
+
dpop_token: dpopProof,
|
|
19664
|
+
expire_in: this._effectiveExpireIn
|
|
19665
|
+
})
|
|
19666
|
+
});
|
|
19667
|
+
if (!response.ok || !response.body) throw new TokenRefreshError(`Failed to refresh device token: ${response.status} ${response.statusText}`);
|
|
19668
|
+
const data = JSON.parse(response.body);
|
|
19669
|
+
if (!data.token) throw new TokenRefreshError("Device token refresh response missing token field");
|
|
19670
|
+
if (!data.expires_at && !data.expires_in) data.expires_in = this._effectiveExpireIn;
|
|
19671
|
+
this._effectiveExpireIn = resolveExpireIn(data);
|
|
19672
|
+
const rpcProof = await this.dpopManager.createRpcProof({ method: "signalwire.reauthenticate" });
|
|
19673
|
+
await session.reauthenticate(data.token, rpcProof);
|
|
19674
|
+
updateCredential({ token: data.token });
|
|
19675
|
+
logger$6.info("[DeviceToken] Client Bound SAT refreshed successfully");
|
|
19676
|
+
return data;
|
|
19677
|
+
}
|
|
19678
|
+
/**
|
|
19679
|
+
* Executes a refresh with retry and exponential backoff.
|
|
19680
|
+
* On success, emits to `_currentToken$` to schedule the next refresh.
|
|
19681
|
+
* On all retries exhausted, emits to `errorHandler`.
|
|
19682
|
+
*/
|
|
19683
|
+
async executeRefresh() {
|
|
19684
|
+
if (this._refreshInProgress) {
|
|
19685
|
+
logger$6.debug("[DeviceToken] Refresh already in progress, skipping");
|
|
19686
|
+
return;
|
|
19687
|
+
}
|
|
19688
|
+
const session = this._session;
|
|
19689
|
+
const updateCredential = this._updateCredential;
|
|
19690
|
+
if (!session || !updateCredential) {
|
|
19691
|
+
logger$6.warn("[DeviceToken] Cannot refresh: session or updateCredential not set");
|
|
19692
|
+
return;
|
|
19693
|
+
}
|
|
19694
|
+
if (!session.authenticated) {
|
|
19695
|
+
logger$6.debug("[DeviceToken] Session not authenticated, deferring refresh");
|
|
19696
|
+
return;
|
|
19697
|
+
}
|
|
19698
|
+
this._refreshInProgress = true;
|
|
19699
|
+
try {
|
|
19700
|
+
const currentToken = this.getCredential().token;
|
|
19701
|
+
if (!currentToken) throw new TokenRefreshError("No current token available for refresh");
|
|
19702
|
+
const newTokenData = await this.retryRefresh(session, currentToken, updateCredential);
|
|
19703
|
+
this._currentToken$.next(newTokenData);
|
|
19704
|
+
} catch (error) {
|
|
19705
|
+
logger$6.error("[DeviceToken] Automatic Client Bound SAT refresh failed:", error);
|
|
19706
|
+
this.errorHandler(error instanceof TokenRefreshError ? error : new TokenRefreshError("Automatic token refresh failed", error));
|
|
19707
|
+
} finally {
|
|
19708
|
+
this._refreshInProgress = false;
|
|
19709
|
+
}
|
|
19710
|
+
}
|
|
19711
|
+
/**
|
|
19712
|
+
* Retries `refreshToken()` up to `DEVICE_TOKEN_REFRESH_MAX_RETRIES` times
|
|
19713
|
+
* with exponential backoff (1s, 2s, 4s).
|
|
19714
|
+
*/
|
|
19715
|
+
async retryRefresh(session, currentToken, updateCredential) {
|
|
19716
|
+
let lastError;
|
|
19717
|
+
for (let attempt = 0; attempt < DEVICE_TOKEN_REFRESH_MAX_RETRIES; attempt++) try {
|
|
19718
|
+
return await this.refreshToken(session, currentToken, updateCredential);
|
|
19719
|
+
} catch (error) {
|
|
19720
|
+
lastError = error;
|
|
19721
|
+
if (attempt < DEVICE_TOKEN_REFRESH_MAX_RETRIES - 1) {
|
|
19722
|
+
const delay$1 = DEVICE_TOKEN_REFRESH_RETRY_BASE_MS * Math.pow(2, attempt);
|
|
19723
|
+
logger$6.warn(`[DeviceToken] Refresh attempt ${attempt + 1} failed, retrying in ${delay$1}ms`);
|
|
19724
|
+
await new Promise((resolve) => setTimeout(resolve, delay$1));
|
|
19725
|
+
}
|
|
19726
|
+
}
|
|
19727
|
+
throw lastError instanceof Error ? lastError : new TokenRefreshError("All refresh retries exhausted", lastError);
|
|
19728
|
+
}
|
|
19729
|
+
/** Cleans up the manager, cancelling the reactive pipeline and all subscriptions. */
|
|
19730
|
+
destroy() {
|
|
19731
|
+
super.destroy();
|
|
19732
|
+
}
|
|
19733
|
+
};
|
|
19734
|
+
|
|
19453
19735
|
//#endregion
|
|
19454
19736
|
//#region src/managers/DiagnosticsCollector.ts
|
|
19455
19737
|
const logger$5 = getLogger();
|
|
@@ -20383,13 +20665,43 @@ var SignalWire = class extends Destroyable {
|
|
|
20383
20665
|
this._errors$.next(error);
|
|
20384
20666
|
});
|
|
20385
20667
|
await this._clientSession.connect();
|
|
20386
|
-
|
|
20387
|
-
|
|
20388
|
-
|
|
20668
|
+
if (this._dpopManager?.initialized) {
|
|
20669
|
+
if (this._refreshTimerId) {
|
|
20670
|
+
clearTimeout(this._refreshTimerId);
|
|
20671
|
+
this._refreshTimerId = void 0;
|
|
20672
|
+
logger$1.debug("[SignalWire] Developer refresh disabled — Client Bound SAT activation starting");
|
|
20673
|
+
}
|
|
20674
|
+
this._deviceTokenManager = new DeviceTokenManager(this._dpopManager, this._deps.http, (error) => this._errors$.next(error), () => this._deps.credential);
|
|
20675
|
+
await this._deviceTokenManager.activate(this._deps.subscriber, this._clientSession, (cred) => {
|
|
20676
|
+
this._deps.credential = {
|
|
20677
|
+
...this._deps.credential,
|
|
20678
|
+
...cred
|
|
20679
|
+
};
|
|
20680
|
+
});
|
|
20681
|
+
}
|
|
20682
|
+
this.subscribeTo(this._clientSession.authenticated$.pipe((0, import_cjs.skip)(1), (0, import_cjs.filter)(Boolean)), async () => {
|
|
20683
|
+
try {
|
|
20684
|
+
if (this._deviceTokenManager) {
|
|
20685
|
+
await this._deviceTokenManager.activate(this._deps.subscriber, this._clientSession, (cred) => {
|
|
20686
|
+
this._deps.credential = {
|
|
20687
|
+
...this._deps.credential,
|
|
20688
|
+
...cred
|
|
20689
|
+
};
|
|
20690
|
+
});
|
|
20691
|
+
logger$1.debug("[SignalWire] Client Bound SAT re-activated after reconnect");
|
|
20692
|
+
}
|
|
20693
|
+
} catch (error) {
|
|
20694
|
+
logger$1.error("[SignalWire] Client Bound SAT re-activation failed (non-fatal):", error);
|
|
20695
|
+
this._errors$.next(error instanceof Error ? error : new Error(String(error), { cause: error }));
|
|
20696
|
+
}
|
|
20697
|
+
try {
|
|
20698
|
+
logger$1.debug("[SignalWire] Re-registering subscriber after reconnect");
|
|
20699
|
+
await this.register();
|
|
20389
20700
|
logger$1.debug("[SignalWire] Subscriber re-registered successfully after reconnect");
|
|
20390
|
-
}
|
|
20701
|
+
} catch (error) {
|
|
20391
20702
|
logger$1.error("[SignalWire] Re-registration failed after reconnect:", error);
|
|
20392
|
-
|
|
20703
|
+
this._errors$.next(error instanceof Error ? error : new Error(String(error), { cause: error }));
|
|
20704
|
+
}
|
|
20393
20705
|
});
|
|
20394
20706
|
const conversationManager = new ConversationsManager(this._clientSession, this._deps.http, () => this._deps.getSubscriberFromAddressId(), errorHandler);
|
|
20395
20707
|
const directory = new DirectoryManager(this._deps.http, this._clientSession, conversationManager, errorHandler);
|
|
@@ -20812,6 +21124,8 @@ var SignalWire = class extends Destroyable {
|
|
|
20812
21124
|
* Triggers the browser's media permission dialog and captures the user's device selections.
|
|
20813
21125
|
*
|
|
20814
21126
|
* @param options - Which permissions to request.
|
|
21127
|
+
* @param options.audio - Whether to request audio permission.
|
|
21128
|
+
* @param options.video - Whether to request video permission.
|
|
20815
21129
|
* @returns The permission result with selected devices.
|
|
20816
21130
|
*/
|
|
20817
21131
|
async requestMediaPermissions(options = {
|
|
@@ -20843,8 +21157,14 @@ var SignalWire = class extends Destroyable {
|
|
|
20843
21157
|
logger$1.warn("[SignalWire] Media permission request failed:", error);
|
|
20844
21158
|
}
|
|
20845
21159
|
await this._deviceController.enumerateDevices();
|
|
20846
|
-
if (audioGranted && selectedAudioDevice)
|
|
20847
|
-
|
|
21160
|
+
if (audioGranted && selectedAudioDevice) {
|
|
21161
|
+
const audioDeviceId = selectedAudioDevice.deviceId;
|
|
21162
|
+
selectedAudioDevice = this.audioInputDevices.find((d) => d.deviceId === audioDeviceId) ?? selectedAudioDevice;
|
|
21163
|
+
}
|
|
21164
|
+
if (videoGranted && selectedVideoDevice) {
|
|
21165
|
+
const videoDeviceId = selectedVideoDevice.deviceId;
|
|
21166
|
+
selectedVideoDevice = this.videoInputDevices.find((d) => d.deviceId === videoDeviceId) ?? selectedVideoDevice;
|
|
21167
|
+
}
|
|
20848
21168
|
if (audioGranted && selectedAudioDevice && !this.selectedAudioInputDevice) this.selectAudioInputDevice(selectedAudioDevice);
|
|
20849
21169
|
if (videoGranted && selectedVideoDevice && !this.selectedVideoInputDevice) this.selectVideoInputDevice(selectedVideoDevice);
|
|
20850
21170
|
return {
|