@signalwire/js 4.0.0-beta.0 → 4.0.0-beta.10
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/base-CQPEW1lJ.d.mts +31 -0
- package/dist/base-CQPEW1lJ.d.mts.map +1 -0
- package/dist/base-Cif20s3C.d.cts +31 -0
- package/dist/base-Cif20s3C.d.cts.map +1 -0
- package/dist/browser.mjs +815 -334
- package/dist/browser.mjs.map +1 -1
- package/dist/browser.umd.js +817 -333
- package/dist/browser.umd.js.map +1 -1
- package/dist/index.cjs +798 -316
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +437 -154
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +437 -154
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +797 -318
- package/dist/index.mjs.map +1 -1
- package/dist/operators/index.cjs +1 -1
- package/dist/operators/index.d.cts +1 -1
- package/dist/operators/index.d.mts +1 -1
- package/dist/operators/index.mjs +1 -1
- package/dist/{operators-DT4UB24-.cjs → operators-mm21prWr.cjs} +5 -3
- package/dist/operators-mm21prWr.cjs.map +1 -0
- package/dist/{operators-BHQMSEzq.mjs → operators-uT_fb8ba.mjs} +5 -3
- package/dist/operators-uT_fb8ba.mjs.map +1 -0
- package/package.json +1 -1
- package/dist/base-A5AZTrAd.d.cts +0 -23
- package/dist/base-A5AZTrAd.d.cts.map +0 -1
- package/dist/base-aVtoG8Wk.d.mts +0 -23
- package/dist/base-aVtoG8Wk.d.mts.map +0 -1
- package/dist/operators-BHQMSEzq.mjs.map +0 -1
- package/dist/operators-DT4UB24-.cjs.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const require_operators = require('./operators-
|
|
1
|
+
const require_operators = require('./operators-mm21prWr.cjs');
|
|
2
2
|
let jwt_decode = require("jwt-decode");
|
|
3
3
|
let rxjs = require("rxjs");
|
|
4
4
|
let uuid = require("uuid");
|
|
@@ -12,11 +12,55 @@ var Destroyable = class {
|
|
|
12
12
|
this._destroyed$ = new rxjs.Subject();
|
|
13
13
|
}
|
|
14
14
|
destroy() {
|
|
15
|
+
this._observableCache?.clear();
|
|
15
16
|
this.subscriptions.forEach((sub) => sub.unsubscribe());
|
|
16
17
|
this.subjects.forEach((subject) => subject.complete());
|
|
17
18
|
this._destroyed$.next();
|
|
18
19
|
this._destroyed$.complete();
|
|
19
20
|
}
|
|
21
|
+
cachedObservable(key, factory) {
|
|
22
|
+
this._observableCache ??= /* @__PURE__ */ new Map();
|
|
23
|
+
let cached = this._observableCache.get(key);
|
|
24
|
+
if (!cached) {
|
|
25
|
+
cached = factory();
|
|
26
|
+
this._observableCache.set(key, cached);
|
|
27
|
+
}
|
|
28
|
+
return cached;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Like `cachedObservable`, but defers emissions to the microtask queue
|
|
32
|
+
* via `observeOn(asapScheduler)`.
|
|
33
|
+
*
|
|
34
|
+
* Use ONLY for public-facing observable getters that external consumers
|
|
35
|
+
* subscribe to. Prevents a class of bugs where `BehaviorSubject` or
|
|
36
|
+
* `ReplaySubject` replays synchronously during `subscribe()`, before
|
|
37
|
+
* the subscription variable is assigned in the caller's scope.
|
|
38
|
+
*
|
|
39
|
+
* Do NOT use for observables consumed internally by the SDK — internal
|
|
40
|
+
* code using `subscribeTo()`, `firstValueFrom()`, or `withLatestFrom()`
|
|
41
|
+
* depends on synchronous emission delivery.
|
|
42
|
+
*/
|
|
43
|
+
publicCachedObservable(key, factory) {
|
|
44
|
+
const publicKey = `public:${key}`;
|
|
45
|
+
this._observableCache ??= /* @__PURE__ */ new Map();
|
|
46
|
+
let cached = this._observableCache.get(publicKey);
|
|
47
|
+
if (!cached) {
|
|
48
|
+
cached = factory().pipe((0, rxjs.observeOn)(rxjs.asapScheduler));
|
|
49
|
+
this._observableCache.set(publicKey, cached);
|
|
50
|
+
}
|
|
51
|
+
return cached;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Wraps an observable so emissions are deferred to the microtask queue.
|
|
55
|
+
*
|
|
56
|
+
* Use ONLY for public-facing getters that expose a subject via
|
|
57
|
+
* `.asObservable()` without going through `cachedObservable`.
|
|
58
|
+
*
|
|
59
|
+
* Do NOT use for observables consumed internally by the SDK.
|
|
60
|
+
*/
|
|
61
|
+
deferEmission(observable) {
|
|
62
|
+
return observable.pipe((0, rxjs.observeOn)(rxjs.asapScheduler));
|
|
63
|
+
}
|
|
20
64
|
subscribeTo(observable, observerOrNext) {
|
|
21
65
|
const subscription = observable.subscribe(observerOrNext);
|
|
22
66
|
this.subscriptions.push(subscription);
|
|
@@ -37,7 +81,7 @@ var Destroyable = class {
|
|
|
37
81
|
return subject;
|
|
38
82
|
}
|
|
39
83
|
get $() {
|
|
40
|
-
return (0, rxjs.merge)(...this.subjects.map((s) => s instanceof rxjs.BehaviorSubject ? s.pipe((0, rxjs.skip)(1)) : s)).pipe((0, rxjs.map)((_) => this));
|
|
84
|
+
return this.cachedObservable("$", () => (0, rxjs.merge)(...this.subjects.map((s) => s instanceof rxjs.BehaviorSubject ? s.pipe((0, rxjs.skip)(1)) : s)).pipe((0, rxjs.map)((_) => this)));
|
|
41
85
|
}
|
|
42
86
|
/**
|
|
43
87
|
* Observable that emits when the instance is destroyed
|
|
@@ -285,7 +329,7 @@ var PreferencesContainer = class PreferencesContainer {
|
|
|
285
329
|
skipDeviceMonitoring: false,
|
|
286
330
|
savePreferences: false
|
|
287
331
|
};
|
|
288
|
-
this.receiveVideo =
|
|
332
|
+
this.receiveVideo = false;
|
|
289
333
|
this.receiveAudio = true;
|
|
290
334
|
this.preferredAudioInput = null;
|
|
291
335
|
this.preferredAudioOutput = null;
|
|
@@ -588,15 +632,16 @@ const selectDevice = (devices = [], selected, preferred) => {
|
|
|
588
632
|
return selected;
|
|
589
633
|
};
|
|
590
634
|
var NavigatorDeviceController = class extends Destroyable {
|
|
591
|
-
constructor() {
|
|
635
|
+
constructor(webRTCApiProvider) {
|
|
592
636
|
super();
|
|
637
|
+
this.webRTCApiProvider = webRTCApiProvider;
|
|
593
638
|
this.deviceChangeHandler = () => {
|
|
594
639
|
logger$18.debug("[DeviceController] Device change detected");
|
|
595
640
|
this.enumerateDevices();
|
|
596
641
|
};
|
|
597
642
|
this._devicesState$ = this.createBehaviorSubject(initialDevicesState);
|
|
598
643
|
this._selectedDevicesState$ = this.createBehaviorSubject(initialSelectedDevicesState);
|
|
599
|
-
this._errors$ = this.
|
|
644
|
+
this._errors$ = this.createReplaySubject(1);
|
|
600
645
|
this.init();
|
|
601
646
|
}
|
|
602
647
|
get selectedAudioInputDeviceConstraints() {
|
|
@@ -613,25 +658,25 @@ var NavigatorDeviceController = class extends Destroyable {
|
|
|
613
658
|
return {};
|
|
614
659
|
}
|
|
615
660
|
get errors$() {
|
|
616
|
-
return this._errors$.asObservable().pipe((0, rxjs.takeUntil)(this.destroyed$));
|
|
661
|
+
return this.cachedObservable("errors$", () => this._errors$.asObservable().pipe((0, rxjs.takeUntil)(this.destroyed$)));
|
|
617
662
|
}
|
|
618
663
|
get audioInputDevices$() {
|
|
619
|
-
return this._devicesState$.pipe((0, rxjs.map)((state) => state.audioinput), (0, rxjs.distinctUntilChanged)(), (0, rxjs.takeUntil)(this.destroyed$));
|
|
664
|
+
return this.cachedObservable("audioInputDevices$", () => this._devicesState$.pipe((0, rxjs.map)((state) => state.audioinput), (0, rxjs.distinctUntilChanged)(), (0, rxjs.takeUntil)(this.destroyed$)));
|
|
620
665
|
}
|
|
621
666
|
get audioOutputDevices$() {
|
|
622
|
-
return this._devicesState$.pipe((0, rxjs.map)((state) => state.audiooutput), (0, rxjs.distinctUntilChanged)(), (0, rxjs.takeUntil)(this.destroyed$));
|
|
667
|
+
return this.cachedObservable("audioOutputDevices$", () => this._devicesState$.pipe((0, rxjs.map)((state) => state.audiooutput), (0, rxjs.distinctUntilChanged)(), (0, rxjs.takeUntil)(this.destroyed$)));
|
|
623
668
|
}
|
|
624
669
|
get videoInputDevices$() {
|
|
625
|
-
return this._devicesState$.pipe((0, rxjs.map)((state) => state.videoinput), (0, rxjs.distinctUntilChanged)(), (0, rxjs.takeUntil)(this.destroyed$));
|
|
670
|
+
return this.cachedObservable("videoInputDevices$", () => this._devicesState$.pipe((0, rxjs.map)((state) => state.videoinput), (0, rxjs.distinctUntilChanged)(), (0, rxjs.takeUntil)(this.destroyed$)));
|
|
626
671
|
}
|
|
627
672
|
get selectedAudioInputDevice$() {
|
|
628
|
-
return this._selectedDevicesState$.asObservable().pipe((0, rxjs.map)((state) => state.audioinput), (0, rxjs.distinctUntilChanged)(), (0, rxjs.takeUntil)(this.destroyed$), (0, rxjs.tap)((info) => logger$18.debug("[DeviceController] Selected audio input device changed:", info)));
|
|
673
|
+
return this.cachedObservable("selectedAudioInputDevice$", () => this._selectedDevicesState$.asObservable().pipe((0, rxjs.map)((state) => state.audioinput), (0, rxjs.distinctUntilChanged)(), (0, rxjs.takeUntil)(this.destroyed$), (0, rxjs.tap)((info) => logger$18.debug("[DeviceController] Selected audio input device changed:", info))));
|
|
629
674
|
}
|
|
630
675
|
get selectedAudioOutputDevice$() {
|
|
631
|
-
return this._selectedDevicesState$.asObservable().pipe((0, rxjs.map)((state) => state.audiooutput), (0, rxjs.distinctUntilChanged)(), (0, rxjs.takeUntil)(this.destroyed$), (0, rxjs.tap)((info) => logger$18.debug("[DeviceController] Selected audio output device changed:", info)));
|
|
676
|
+
return this.cachedObservable("selectedAudioOutputDevice$", () => this._selectedDevicesState$.asObservable().pipe((0, rxjs.map)((state) => state.audiooutput), (0, rxjs.distinctUntilChanged)(), (0, rxjs.takeUntil)(this.destroyed$), (0, rxjs.tap)((info) => logger$18.debug("[DeviceController] Selected audio output device changed:", info))));
|
|
632
677
|
}
|
|
633
678
|
get selectedVideoInputDevice$() {
|
|
634
|
-
return this._selectedDevicesState$.asObservable().pipe((0, rxjs.map)((state) => state.videoinput), (0, rxjs.distinctUntilChanged)(), (0, rxjs.takeUntil)(this.destroyed$), (0, rxjs.tap)((info) => logger$18.debug("[DeviceController] Selected video input device changed:", info)));
|
|
679
|
+
return this.cachedObservable("selectedVideoInputDevice$", () => this._selectedDevicesState$.asObservable().pipe((0, rxjs.map)((state) => state.videoinput), (0, rxjs.distinctUntilChanged)(), (0, rxjs.takeUntil)(this.destroyed$), (0, rxjs.tap)((info) => logger$18.debug("[DeviceController] Selected video input device changed:", info))));
|
|
635
680
|
}
|
|
636
681
|
get selectedAudioInputDevice() {
|
|
637
682
|
return this._selectedDevicesState$.value.audioinput;
|
|
@@ -671,24 +716,22 @@ var NavigatorDeviceController = class extends Destroyable {
|
|
|
671
716
|
});
|
|
672
717
|
}
|
|
673
718
|
init() {
|
|
674
|
-
|
|
675
|
-
this.
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
videoinput: newVideoInput
|
|
684
|
-
});
|
|
719
|
+
this.subscribeTo(this._devicesState$.pipe((0, rxjs.debounceTime)(PreferencesContainer.instance.deviceDebounceTime)), (devicesState) => {
|
|
720
|
+
const currentSelected = this._selectedDevicesState$.value;
|
|
721
|
+
const newAudioInput = selectDevice(devicesState.audioinput, currentSelected.audioinput, PreferencesContainer.instance.preferredAudioInput);
|
|
722
|
+
const newAudioOutput = selectDevice(devicesState.audiooutput, currentSelected.audiooutput, PreferencesContainer.instance.preferredAudioOutput);
|
|
723
|
+
const newVideoInput = selectDevice(devicesState.videoinput, currentSelected.videoinput, PreferencesContainer.instance.preferredVideoInput);
|
|
724
|
+
if (newAudioInput !== currentSelected.audioinput || newAudioOutput !== currentSelected.audiooutput || newVideoInput !== currentSelected.videoinput) this._selectedDevicesState$.next({
|
|
725
|
+
audioinput: newAudioInput,
|
|
726
|
+
audiooutput: newAudioOutput,
|
|
727
|
+
videoinput: newVideoInput
|
|
685
728
|
});
|
|
686
|
-
|
|
687
|
-
|
|
729
|
+
});
|
|
730
|
+
this.enumerateDevices();
|
|
688
731
|
}
|
|
689
732
|
enableDeviceMonitoring() {
|
|
690
733
|
this.disableDeviceMonitoring();
|
|
691
|
-
|
|
734
|
+
this.webRTCApiProvider.mediaDevices.addEventListener("devicechange", this.deviceChangeHandler);
|
|
692
735
|
if (PreferencesContainer.instance.devicePollingInterval > 0) this._devicesPoolingSubscription = (0, rxjs.interval)(PreferencesContainer.instance.devicePollingInterval).subscribe(() => {
|
|
693
736
|
logger$18.debug("[DeviceController] Polling devices due to interval");
|
|
694
737
|
this.enumerateDevices();
|
|
@@ -696,7 +739,7 @@ var NavigatorDeviceController = class extends Destroyable {
|
|
|
696
739
|
this.enumerateDevices();
|
|
697
740
|
}
|
|
698
741
|
disableDeviceMonitoring() {
|
|
699
|
-
|
|
742
|
+
this.webRTCApiProvider.mediaDevices.removeEventListener("devicechange", this.deviceChangeHandler);
|
|
700
743
|
if (this._devicesPoolingSubscription) {
|
|
701
744
|
this._devicesPoolingSubscription.unsubscribe();
|
|
702
745
|
this._devicesPoolingSubscription = void 0;
|
|
@@ -704,7 +747,7 @@ var NavigatorDeviceController = class extends Destroyable {
|
|
|
704
747
|
}
|
|
705
748
|
async enumerateDevices() {
|
|
706
749
|
try {
|
|
707
|
-
const devicesByKind = (await
|
|
750
|
+
const devicesByKind = (await this.webRTCApiProvider.mediaDevices.enumerateDevices()).reduce((acc, device) => {
|
|
708
751
|
acc[device.kind].push(device);
|
|
709
752
|
return acc;
|
|
710
753
|
}, {
|
|
@@ -727,7 +770,7 @@ var NavigatorDeviceController = class extends Destroyable {
|
|
|
727
770
|
if (deviceInfo.kind === "audiooutput") return null;
|
|
728
771
|
try {
|
|
729
772
|
const constraints = this.deviceInfoToConstraints(deviceInfo);
|
|
730
|
-
const stream = await
|
|
773
|
+
const stream = await this.webRTCApiProvider.mediaDevices.getUserMedia({
|
|
731
774
|
audio: deviceInfo.kind === "audioinput" ? constraints : false,
|
|
732
775
|
video: deviceInfo.kind === "videoinput" ? constraints : false
|
|
733
776
|
});
|
|
@@ -899,9 +942,23 @@ var DependencyContainer = class {
|
|
|
899
942
|
this._webSocketConstructor = WebSocketConstructor;
|
|
900
943
|
}
|
|
901
944
|
get deviceController() {
|
|
902
|
-
this._deviceController ??= new NavigatorDeviceController();
|
|
945
|
+
this._deviceController ??= new NavigatorDeviceController(this.webRTCApiProvider);
|
|
903
946
|
return this._deviceController;
|
|
904
947
|
}
|
|
948
|
+
get webRTCApiProvider() {
|
|
949
|
+
if (!this._webRTCApiProvider) {
|
|
950
|
+
if (typeof RTCPeerConnection === "undefined" || typeof navigator === "undefined") throw new require_operators.DependencyError("WebRTCApiProvider: RTCPeerConnection or navigator.mediaDevices is not available. Please provide a custom webRTCApiProvider in SignalWireOptions.");
|
|
951
|
+
this._webRTCApiProvider = {
|
|
952
|
+
RTCPeerConnection,
|
|
953
|
+
mediaDevices: navigator.mediaDevices
|
|
954
|
+
};
|
|
955
|
+
}
|
|
956
|
+
return this._webRTCApiProvider;
|
|
957
|
+
}
|
|
958
|
+
set webRTCApiProvider(webRTCApiProvider) {
|
|
959
|
+
this._webRTCApiProvider = webRTCApiProvider;
|
|
960
|
+
this._deviceController = void 0;
|
|
961
|
+
}
|
|
905
962
|
get authorizationStateKey() {
|
|
906
963
|
return `sw:${this.subscriberId}:as`;
|
|
907
964
|
}
|
|
@@ -1035,6 +1092,15 @@ const RPCConnect = (params) => {
|
|
|
1035
1092
|
});
|
|
1036
1093
|
};
|
|
1037
1094
|
|
|
1095
|
+
//#endregion
|
|
1096
|
+
//#region src/core/RPCMessages/RPCReauthenticate.ts
|
|
1097
|
+
const RPCReauthenticate = (authentication) => {
|
|
1098
|
+
return buildRPCRequest({
|
|
1099
|
+
method: "signalwire.reauthenticate",
|
|
1100
|
+
params: { authentication }
|
|
1101
|
+
});
|
|
1102
|
+
};
|
|
1103
|
+
|
|
1038
1104
|
//#endregion
|
|
1039
1105
|
//#region src/core/RPCMessages/RPCPing.ts
|
|
1040
1106
|
const RPCPingResponse = (id, timestamp) => {
|
|
@@ -1055,7 +1121,7 @@ const RPCExecute = ({ method, params }) => {
|
|
|
1055
1121
|
|
|
1056
1122
|
//#endregion
|
|
1057
1123
|
//#region src/core/RPCMessages/VertoMessages.ts
|
|
1058
|
-
const
|
|
1124
|
+
const SDK_TO_VERTO_FIELD_MAP = {
|
|
1059
1125
|
id: "callID",
|
|
1060
1126
|
destinationNumber: "destination_number",
|
|
1061
1127
|
remoteCallerName: "remote_caller_id_name",
|
|
@@ -1064,19 +1130,31 @@ const tmpMap = {
|
|
|
1064
1130
|
callerNumber: "caller_id_number",
|
|
1065
1131
|
fromCallAddressId: "from_fabric_address_id"
|
|
1066
1132
|
};
|
|
1133
|
+
const EXCLUDED_DIALOG_PARAMS = new Set([
|
|
1134
|
+
"remoteSdp",
|
|
1135
|
+
"localStream",
|
|
1136
|
+
"remoteStream"
|
|
1137
|
+
]);
|
|
1067
1138
|
/**
|
|
1068
|
-
* Translate SDK fields into verto variables
|
|
1139
|
+
* Translate SDK fields into verto variables.
|
|
1140
|
+
* Returns a new object — the input is never mutated.
|
|
1069
1141
|
*/
|
|
1142
|
+
/** @internal Exported for testing only. */
|
|
1070
1143
|
const filterVertoParams = (params) => {
|
|
1071
|
-
if (Object.prototype.hasOwnProperty.call(params, "dialogParams"))
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1144
|
+
if (!Object.prototype.hasOwnProperty.call(params, "dialogParams")) return params;
|
|
1145
|
+
const sourceDialogParams = params.dialogParams;
|
|
1146
|
+
const filteredDialogParams = Object.entries(sourceDialogParams).reduce((acc, [key, value]) => {
|
|
1147
|
+
if (EXCLUDED_DIALOG_PARAMS.has(key)) return acc;
|
|
1148
|
+
const mappedKey = SDK_TO_VERTO_FIELD_MAP[key] ?? key;
|
|
1149
|
+
return {
|
|
1150
|
+
...acc,
|
|
1151
|
+
[mappedKey]: value
|
|
1152
|
+
};
|
|
1153
|
+
}, {});
|
|
1154
|
+
return {
|
|
1155
|
+
...params,
|
|
1156
|
+
dialogParams: filteredDialogParams
|
|
1157
|
+
};
|
|
1080
1158
|
};
|
|
1081
1159
|
const buildVertoRPCMessage = (method) => {
|
|
1082
1160
|
return (params = {}) => {
|
|
@@ -1187,17 +1265,21 @@ var AttachManager = class {
|
|
|
1187
1265
|
buildCallOptions(attachment) {
|
|
1188
1266
|
const { audio: audioDirection, video: videoDirection } = attachment.mediaDirections;
|
|
1189
1267
|
const { audioInputDevice, videoInputDevice } = attachment;
|
|
1268
|
+
const receiveAudio = audioDirection.includes("recv");
|
|
1269
|
+
const receiveVideo = videoDirection.includes("recv");
|
|
1270
|
+
const sendAudio = audioDirection.includes("send");
|
|
1271
|
+
const sendVideo = videoDirection.includes("send");
|
|
1190
1272
|
return {
|
|
1191
|
-
receiveAudio
|
|
1192
|
-
receiveVideo
|
|
1193
|
-
inputAudioDeviceConstraints: {
|
|
1194
|
-
audio:
|
|
1273
|
+
receiveAudio,
|
|
1274
|
+
receiveVideo,
|
|
1275
|
+
inputAudioDeviceConstraints: sendAudio ? {
|
|
1276
|
+
audio: true,
|
|
1195
1277
|
...this.deviceController.deviceInfoToConstraints(audioInputDevice)
|
|
1196
|
-
},
|
|
1197
|
-
inputVideoDeviceConstraints: {
|
|
1198
|
-
video:
|
|
1278
|
+
} : void 0,
|
|
1279
|
+
inputVideoDeviceConstraints: sendVideo ? {
|
|
1280
|
+
video: true,
|
|
1199
1281
|
...this.deviceController.deviceInfoToConstraints(videoInputDevice)
|
|
1200
|
-
},
|
|
1282
|
+
} : void 0,
|
|
1201
1283
|
reattach: true
|
|
1202
1284
|
};
|
|
1203
1285
|
}
|
|
@@ -1375,7 +1457,7 @@ var SelfCapabilities = class extends Destroyable {
|
|
|
1375
1457
|
}
|
|
1376
1458
|
/** Observable for self member capabilities */
|
|
1377
1459
|
get self$() {
|
|
1378
|
-
return this._state$.pipe((0, rxjs.map)((state) => state.self), (0, rxjs.distinctUntilChanged)());
|
|
1460
|
+
return this.cachedObservable("self$", () => this._state$.pipe((0, rxjs.map)((state) => state.self), (0, rxjs.distinctUntilChanged)()));
|
|
1379
1461
|
}
|
|
1380
1462
|
/** Current self member capabilities */
|
|
1381
1463
|
get self() {
|
|
@@ -1383,7 +1465,7 @@ var SelfCapabilities = class extends Destroyable {
|
|
|
1383
1465
|
}
|
|
1384
1466
|
/** Observable for other member capabilities */
|
|
1385
1467
|
get member$() {
|
|
1386
|
-
return this._state$.pipe((0, rxjs.map)((state) => state.member), (0, rxjs.distinctUntilChanged)());
|
|
1468
|
+
return this.cachedObservable("member$", () => this._state$.pipe((0, rxjs.map)((state) => state.member), (0, rxjs.distinctUntilChanged)()));
|
|
1387
1469
|
}
|
|
1388
1470
|
/** Current other member capabilities */
|
|
1389
1471
|
get member() {
|
|
@@ -1391,7 +1473,7 @@ var SelfCapabilities = class extends Destroyable {
|
|
|
1391
1473
|
}
|
|
1392
1474
|
/** Observable for end call capability */
|
|
1393
1475
|
get end$() {
|
|
1394
|
-
return this._state$.pipe((0, rxjs.map)((state) => state.end), (0, rxjs.distinctUntilChanged)());
|
|
1476
|
+
return this.cachedObservable("end$", () => this._state$.pipe((0, rxjs.map)((state) => state.end), (0, rxjs.distinctUntilChanged)()));
|
|
1395
1477
|
}
|
|
1396
1478
|
/** Current end call capability */
|
|
1397
1479
|
get end() {
|
|
@@ -1399,7 +1481,7 @@ var SelfCapabilities = class extends Destroyable {
|
|
|
1399
1481
|
}
|
|
1400
1482
|
/** Observable for set layout capability */
|
|
1401
1483
|
get setLayout$() {
|
|
1402
|
-
return this._state$.pipe((0, rxjs.map)((state) => state.setLayout), (0, rxjs.distinctUntilChanged)());
|
|
1484
|
+
return this.cachedObservable("setLayout$", () => this._state$.pipe((0, rxjs.map)((state) => state.setLayout), (0, rxjs.distinctUntilChanged)()));
|
|
1403
1485
|
}
|
|
1404
1486
|
/** Current set layout capability */
|
|
1405
1487
|
get setLayout() {
|
|
@@ -1407,7 +1489,7 @@ var SelfCapabilities = class extends Destroyable {
|
|
|
1407
1489
|
}
|
|
1408
1490
|
/** Observable for send digit capability */
|
|
1409
1491
|
get sendDigit$() {
|
|
1410
|
-
return this._state$.pipe((0, rxjs.map)((state) => state.sendDigit), (0, rxjs.distinctUntilChanged)());
|
|
1492
|
+
return this.cachedObservable("sendDigit$", () => this._state$.pipe((0, rxjs.map)((state) => state.sendDigit), (0, rxjs.distinctUntilChanged)()));
|
|
1411
1493
|
}
|
|
1412
1494
|
/** Current send digit capability */
|
|
1413
1495
|
get sendDigit() {
|
|
@@ -1415,7 +1497,7 @@ var SelfCapabilities = class extends Destroyable {
|
|
|
1415
1497
|
}
|
|
1416
1498
|
/** Observable for vmuted hide capability */
|
|
1417
1499
|
get vmutedHide$() {
|
|
1418
|
-
return this._state$.pipe((0, rxjs.map)((state) => state.vmutedHide), (0, rxjs.distinctUntilChanged)());
|
|
1500
|
+
return this.cachedObservable("vmutedHide$", () => this._state$.pipe((0, rxjs.map)((state) => state.vmutedHide), (0, rxjs.distinctUntilChanged)()));
|
|
1419
1501
|
}
|
|
1420
1502
|
/** Current vmuted hide capability */
|
|
1421
1503
|
get vmutedHide() {
|
|
@@ -1423,7 +1505,7 @@ var SelfCapabilities = class extends Destroyable {
|
|
|
1423
1505
|
}
|
|
1424
1506
|
/** Observable for lock capability */
|
|
1425
1507
|
get lock$() {
|
|
1426
|
-
return this._state$.pipe((0, rxjs.map)((state) => state.lock), (0, rxjs.distinctUntilChanged)());
|
|
1508
|
+
return this.cachedObservable("lock$", () => this._state$.pipe((0, rxjs.map)((state) => state.lock), (0, rxjs.distinctUntilChanged)()));
|
|
1427
1509
|
}
|
|
1428
1510
|
/** Current lock capability */
|
|
1429
1511
|
get lock() {
|
|
@@ -1431,7 +1513,7 @@ var SelfCapabilities = class extends Destroyable {
|
|
|
1431
1513
|
}
|
|
1432
1514
|
/** Observable for device capability */
|
|
1433
1515
|
get device$() {
|
|
1434
|
-
return this._state$.pipe((0, rxjs.map)((state) => state.device), (0, rxjs.distinctUntilChanged)());
|
|
1516
|
+
return this.cachedObservable("device$", () => this._state$.pipe((0, rxjs.map)((state) => state.device), (0, rxjs.distinctUntilChanged)()));
|
|
1435
1517
|
}
|
|
1436
1518
|
/** Current device capability */
|
|
1437
1519
|
get device() {
|
|
@@ -1439,7 +1521,7 @@ var SelfCapabilities = class extends Destroyable {
|
|
|
1439
1521
|
}
|
|
1440
1522
|
/** Observable for screenshare capability */
|
|
1441
1523
|
get screenshare$() {
|
|
1442
|
-
return this._state$.pipe((0, rxjs.map)((state) => state.screenshare), (0, rxjs.distinctUntilChanged)());
|
|
1524
|
+
return this.cachedObservable("screenshare$", () => this._state$.pipe((0, rxjs.map)((state) => state.screenshare), (0, rxjs.distinctUntilChanged)()));
|
|
1443
1525
|
}
|
|
1444
1526
|
/** Current screenshare capability */
|
|
1445
1527
|
get screenshare() {
|
|
@@ -1492,83 +1574,83 @@ var Participant = class extends Destroyable {
|
|
|
1492
1574
|
}
|
|
1493
1575
|
/** Observable of the participant's display name. */
|
|
1494
1576
|
get name$() {
|
|
1495
|
-
return this._state$.pipe((0, rxjs_operators.map)((state) => state.name), (0, rxjs_operators.distinctUntilChanged)(), require_operators.filterNull());
|
|
1577
|
+
return this.cachedObservable("name$", () => this._state$.pipe((0, rxjs_operators.map)((state) => state.name), (0, rxjs_operators.distinctUntilChanged)(), require_operators.filterNull()));
|
|
1496
1578
|
}
|
|
1497
1579
|
/** Observable of the participant type (e.g. `'member'`, `'screen'`). */
|
|
1498
1580
|
get type$() {
|
|
1499
|
-
return this._state$.pipe((0, rxjs_operators.map)((state) => state.type), (0, rxjs_operators.distinctUntilChanged)(), require_operators.filterNull());
|
|
1581
|
+
return this.cachedObservable("type$", () => this._state$.pipe((0, rxjs_operators.map)((state) => state.type), (0, rxjs_operators.distinctUntilChanged)(), require_operators.filterNull()));
|
|
1500
1582
|
}
|
|
1501
1583
|
/** Observable indicating whether the participant has raised their hand. */
|
|
1502
1584
|
get handraised$() {
|
|
1503
|
-
return this._state$.pipe((0, rxjs_operators.map)((state) => state.handraised), (0, rxjs_operators.distinctUntilChanged)(), require_operators.filterNull());
|
|
1585
|
+
return this.cachedObservable("handraised$", () => this._state$.pipe((0, rxjs_operators.map)((state) => state.handraised), (0, rxjs_operators.distinctUntilChanged)(), require_operators.filterNull()));
|
|
1504
1586
|
}
|
|
1505
1587
|
/** Observable indicating whether the participant is visible in the layout. */
|
|
1506
1588
|
get visible$() {
|
|
1507
|
-
return this._state$.pipe((0, rxjs_operators.map)((state) => state.visible), (0, rxjs_operators.distinctUntilChanged)(), require_operators.filterNull());
|
|
1589
|
+
return this.cachedObservable("visible$", () => this._state$.pipe((0, rxjs_operators.map)((state) => state.visible), (0, rxjs_operators.distinctUntilChanged)(), require_operators.filterNull()));
|
|
1508
1590
|
}
|
|
1509
1591
|
/** Observable indicating whether the participant's audio is muted. */
|
|
1510
1592
|
get audioMuted$() {
|
|
1511
|
-
return this._state$.pipe((0, rxjs_operators.map)((state) => state.audio_muted), (0, rxjs_operators.distinctUntilChanged)(), require_operators.filterNull());
|
|
1593
|
+
return this.cachedObservable("audioMuted$", () => this._state$.pipe((0, rxjs_operators.map)((state) => state.audio_muted), (0, rxjs_operators.distinctUntilChanged)(), require_operators.filterNull()));
|
|
1512
1594
|
}
|
|
1513
1595
|
/** Observable indicating whether the participant's video is muted. */
|
|
1514
1596
|
get videoMuted$() {
|
|
1515
|
-
return this._state$.pipe((0, rxjs_operators.map)((state) => state.video_muted), (0, rxjs_operators.distinctUntilChanged)(), require_operators.filterNull());
|
|
1597
|
+
return this.cachedObservable("videoMuted$", () => this._state$.pipe((0, rxjs_operators.map)((state) => state.video_muted), (0, rxjs_operators.distinctUntilChanged)(), require_operators.filterNull()));
|
|
1516
1598
|
}
|
|
1517
1599
|
/** Observable indicating whether the participant is deafened. */
|
|
1518
1600
|
get deaf$() {
|
|
1519
|
-
return this._state$.pipe((0, rxjs_operators.map)((state) => state.deaf), (0, rxjs_operators.distinctUntilChanged)(), require_operators.filterNull());
|
|
1601
|
+
return this.cachedObservable("deaf$", () => this._state$.pipe((0, rxjs_operators.map)((state) => state.deaf), (0, rxjs_operators.distinctUntilChanged)(), require_operators.filterNull()));
|
|
1520
1602
|
}
|
|
1521
1603
|
/** Observable of the participant's microphone input volume. */
|
|
1522
1604
|
get inputVolume$() {
|
|
1523
|
-
return this._state$.pipe((0, rxjs_operators.map)((state) => state.input_volume), (0, rxjs_operators.distinctUntilChanged)(), require_operators.filterNull());
|
|
1605
|
+
return this.cachedObservable("inputVolume$", () => this._state$.pipe((0, rxjs_operators.map)((state) => state.input_volume), (0, rxjs_operators.distinctUntilChanged)(), require_operators.filterNull()));
|
|
1524
1606
|
}
|
|
1525
1607
|
/** Observable of the participant's speaker output volume. */
|
|
1526
1608
|
get outputVolume$() {
|
|
1527
|
-
return this._state$.pipe((0, rxjs_operators.map)((state) => state.output_volume), (0, rxjs_operators.distinctUntilChanged)(), require_operators.filterNull());
|
|
1609
|
+
return this.cachedObservable("outputVolume$", () => this._state$.pipe((0, rxjs_operators.map)((state) => state.output_volume), (0, rxjs_operators.distinctUntilChanged)(), require_operators.filterNull()));
|
|
1528
1610
|
}
|
|
1529
1611
|
/** Observable of the microphone input sensitivity level. */
|
|
1530
1612
|
get inputSensitivity$() {
|
|
1531
|
-
return this._state$.pipe((0, rxjs_operators.map)((state) => state.input_sensitivity), (0, rxjs_operators.distinctUntilChanged)(), require_operators.filterNull());
|
|
1613
|
+
return this.cachedObservable("inputSensitivity$", () => this._state$.pipe((0, rxjs_operators.map)((state) => state.input_sensitivity), (0, rxjs_operators.distinctUntilChanged)(), require_operators.filterNull()));
|
|
1532
1614
|
}
|
|
1533
1615
|
/** Observable indicating whether echo cancellation is enabled. */
|
|
1534
1616
|
get echoCancellation$() {
|
|
1535
|
-
return this._state$.pipe((0, rxjs_operators.map)((state) => state.echo_cancellation), (0, rxjs_operators.distinctUntilChanged)(), require_operators.filterNull());
|
|
1617
|
+
return this.cachedObservable("echoCancellation$", () => this._state$.pipe((0, rxjs_operators.map)((state) => state.echo_cancellation), (0, rxjs_operators.distinctUntilChanged)(), require_operators.filterNull()));
|
|
1536
1618
|
}
|
|
1537
1619
|
/** Observable indicating whether auto-gain control is enabled. */
|
|
1538
1620
|
get autoGain$() {
|
|
1539
|
-
return this._state$.pipe((0, rxjs_operators.map)((state) => state.auto_gain), (0, rxjs_operators.distinctUntilChanged)(), require_operators.filterNull());
|
|
1621
|
+
return this.cachedObservable("autoGain$", () => this._state$.pipe((0, rxjs_operators.map)((state) => state.auto_gain), (0, rxjs_operators.distinctUntilChanged)(), require_operators.filterNull()));
|
|
1540
1622
|
}
|
|
1541
1623
|
/** Observable indicating whether noise suppression is enabled. */
|
|
1542
1624
|
get noiseSuppression$() {
|
|
1543
|
-
return this._state$.pipe((0, rxjs_operators.map)((state) => state.noise_suppression), (0, rxjs_operators.distinctUntilChanged)(), require_operators.filterNull());
|
|
1625
|
+
return this.cachedObservable("noiseSuppression$", () => this._state$.pipe((0, rxjs_operators.map)((state) => state.noise_suppression), (0, rxjs_operators.distinctUntilChanged)(), require_operators.filterNull()));
|
|
1544
1626
|
}
|
|
1545
1627
|
/** Observable indicating whether low-bitrate mode is active. */
|
|
1546
1628
|
get lowbitrate$() {
|
|
1547
|
-
return this._state$.pipe((0, rxjs_operators.map)((state) => state.lowbitrate), (0, rxjs_operators.distinctUntilChanged)(), require_operators.filterNull());
|
|
1629
|
+
return this.cachedObservable("lowbitrate$", () => this._state$.pipe((0, rxjs_operators.map)((state) => state.lowbitrate), (0, rxjs_operators.distinctUntilChanged)(), require_operators.filterNull()));
|
|
1548
1630
|
}
|
|
1549
1631
|
/** Observable indicating whether noise reduction is active. */
|
|
1550
1632
|
get denoise$() {
|
|
1551
|
-
return this._state$.pipe((0, rxjs_operators.map)((state) => state.denoise), (0, rxjs_operators.distinctUntilChanged)(), require_operators.filterNull());
|
|
1633
|
+
return this.cachedObservable("denoise$", () => this._state$.pipe((0, rxjs_operators.map)((state) => state.denoise), (0, rxjs_operators.distinctUntilChanged)(), require_operators.filterNull()));
|
|
1552
1634
|
}
|
|
1553
1635
|
/** Observable of custom metadata for this participant. */
|
|
1554
1636
|
get meta$() {
|
|
1555
|
-
return this._state$.pipe((0, rxjs_operators.map)((state) => state.meta), (0, rxjs_operators.distinctUntilChanged)(), require_operators.filterNull());
|
|
1637
|
+
return this.cachedObservable("meta$", () => this._state$.pipe((0, rxjs_operators.map)((state) => state.meta), (0, rxjs_operators.distinctUntilChanged)(), require_operators.filterNull()));
|
|
1556
1638
|
}
|
|
1557
1639
|
/** Observable of the participant's subscriber ID. */
|
|
1558
1640
|
get subscriberId$() {
|
|
1559
|
-
return this._state$.pipe((0, rxjs_operators.map)((state) => state.subscriber_id), (0, rxjs_operators.distinctUntilChanged)(), require_operators.filterNull());
|
|
1641
|
+
return this.cachedObservable("subscriberId$", () => this._state$.pipe((0, rxjs_operators.map)((state) => state.subscriber_id), (0, rxjs_operators.distinctUntilChanged)(), require_operators.filterNull()));
|
|
1560
1642
|
}
|
|
1561
1643
|
/** Observable of the participant's address ID. */
|
|
1562
1644
|
get addressId$() {
|
|
1563
|
-
return this._state$.pipe((0, rxjs_operators.map)((state) => state.address_id), (0, rxjs_operators.distinctUntilChanged)(), require_operators.filterNull());
|
|
1645
|
+
return this.cachedObservable("addressId$", () => this._state$.pipe((0, rxjs_operators.map)((state) => state.address_id), (0, rxjs_operators.distinctUntilChanged)(), require_operators.filterNull()));
|
|
1564
1646
|
}
|
|
1565
1647
|
/** Observable of the server node ID for this participant. */
|
|
1566
1648
|
get nodeId$() {
|
|
1567
|
-
return this._state$.pipe((0, rxjs_operators.map)((state) => state.node_id), (0, rxjs_operators.distinctUntilChanged)(), require_operators.filterNull());
|
|
1649
|
+
return this.cachedObservable("nodeId$", () => this._state$.pipe((0, rxjs_operators.map)((state) => state.node_id), (0, rxjs_operators.distinctUntilChanged)(), require_operators.filterNull()));
|
|
1568
1650
|
}
|
|
1569
1651
|
/** Observable indicating whether the participant is currently speaking. */
|
|
1570
1652
|
get isTalking$() {
|
|
1571
|
-
return this._state$.pipe((0, rxjs_operators.map)((state) => state.talking), (0, rxjs_operators.distinctUntilChanged)(), require_operators.filterNull());
|
|
1653
|
+
return this.cachedObservable("isTalking$", () => this._state$.pipe((0, rxjs_operators.map)((state) => state.talking), (0, rxjs_operators.distinctUntilChanged)(), require_operators.filterNull()));
|
|
1572
1654
|
}
|
|
1573
1655
|
/** Whether the participant is currently speaking. */
|
|
1574
1656
|
get isTalking() {
|
|
@@ -1576,7 +1658,7 @@ var Participant = class extends Destroyable {
|
|
|
1576
1658
|
}
|
|
1577
1659
|
/** Observable of the participant's layout position. */
|
|
1578
1660
|
get position$() {
|
|
1579
|
-
return this._state$.pipe((0, rxjs_operators.map)((state) => state.position), (0, rxjs_operators.distinctUntilChanged)(), require_operators.filterNull());
|
|
1661
|
+
return this.cachedObservable("position$", () => this._state$.pipe((0, rxjs_operators.map)((state) => state.position), (0, rxjs_operators.distinctUntilChanged)(), require_operators.filterNull()));
|
|
1580
1662
|
}
|
|
1581
1663
|
/** Current layout position. */
|
|
1582
1664
|
get position() {
|
|
@@ -1727,7 +1809,13 @@ var Participant = class extends Destroyable {
|
|
|
1727
1809
|
}
|
|
1728
1810
|
/** Removes this participant from the call. */
|
|
1729
1811
|
async remove() {
|
|
1730
|
-
|
|
1812
|
+
const state = this._state$.value;
|
|
1813
|
+
const target = {
|
|
1814
|
+
member_id: this.id,
|
|
1815
|
+
call_id: state.call_id ?? "",
|
|
1816
|
+
node_id: state.node_id ?? ""
|
|
1817
|
+
};
|
|
1818
|
+
await this.executeMethod(target, "call.member.remove", {});
|
|
1731
1819
|
}
|
|
1732
1820
|
/** Ends the call for this participant. */
|
|
1733
1821
|
async end() {
|
|
@@ -1895,7 +1983,10 @@ function isJSONRPCRequest(value) {
|
|
|
1895
1983
|
return isObject(value) && hasProperty(value, "jsonrpc") && value.jsonrpc === "2.0" && hasProperty(value, "id") && typeof value.id === "string" && hasProperty(value, "method") && typeof value.method === "string";
|
|
1896
1984
|
}
|
|
1897
1985
|
function isJSONRPCResponse(value) {
|
|
1898
|
-
return isObject(value) && hasProperty(value, "jsonrpc") && value.jsonrpc === "2.0" && hasProperty(value, "id") && typeof value.id === "string" && hasProperty(value, "result");
|
|
1986
|
+
return isObject(value) && hasProperty(value, "jsonrpc") && value.jsonrpc === "2.0" && hasProperty(value, "id") && typeof value.id === "string" && (hasProperty(value, "result") || hasProperty(value, "error"));
|
|
1987
|
+
}
|
|
1988
|
+
function isJSONRPCErrorResponse(value) {
|
|
1989
|
+
return isObject(value) && hasProperty(value, "jsonrpc") && value.jsonrpc === "2.0" && hasProperty(value, "id") && typeof value.id === "string" && (hasProperty(value, "error") && isObject(value.error) && hasProperty(value.error, "code") && hasProperty(value.error, "message") || hasProperty(value, "result") && isObject(value.result) && hasProperty(value.result, "code") && value.result.code !== "200" && hasProperty(value.result, "message"));
|
|
1899
1990
|
}
|
|
1900
1991
|
|
|
1901
1992
|
//#endregion
|
|
@@ -1969,23 +2060,19 @@ var CallEventsManager = class extends Destroyable {
|
|
|
1969
2060
|
this.options = options;
|
|
1970
2061
|
this.callIds = /* @__PURE__ */ new Set();
|
|
1971
2062
|
this.roomSessionIds = /* @__PURE__ */ new Set();
|
|
1972
|
-
this._status$ = this.createBehaviorSubject("trying");
|
|
1973
2063
|
this._participants$ = this.createBehaviorSubject({});
|
|
1974
2064
|
this._self$ = this.createBehaviorSubject(null);
|
|
1975
2065
|
this._sessionState$ = this.createBehaviorSubject(initialSessionState);
|
|
1976
2066
|
this.initSubscriptions();
|
|
1977
2067
|
}
|
|
1978
2068
|
get participants$() {
|
|
1979
|
-
return this._participants$.asObservable().pipe((0, rxjs.map)((participantsRecord) => Object.values(participantsRecord)));
|
|
1980
|
-
}
|
|
1981
|
-
get self$() {
|
|
1982
|
-
return this._self$.asObservable().pipe(require_operators.filterNull());
|
|
2069
|
+
return this.cachedObservable("participants$", () => this._participants$.asObservable().pipe((0, rxjs.map)((participantsRecord) => Object.values(participantsRecord))));
|
|
1983
2070
|
}
|
|
1984
|
-
get
|
|
1985
|
-
return this.
|
|
2071
|
+
get participants() {
|
|
2072
|
+
return Object.values(this._participants$.value);
|
|
1986
2073
|
}
|
|
1987
|
-
get
|
|
1988
|
-
return this.
|
|
2074
|
+
get self$() {
|
|
2075
|
+
return this.cachedObservable("self$", () => this._self$.asObservable().pipe(require_operators.filterNull()));
|
|
1989
2076
|
}
|
|
1990
2077
|
isRoomSessionIdValid(roomSessionId) {
|
|
1991
2078
|
return this.roomSessionIds.has(roomSessionId);
|
|
@@ -1997,40 +2084,40 @@ var CallEventsManager = class extends Destroyable {
|
|
|
1997
2084
|
return this.callIds.has(callId);
|
|
1998
2085
|
}
|
|
1999
2086
|
get recording$() {
|
|
2000
|
-
return this._sessionState$.pipe((0, rxjs.map)((state) => state.recording), (0, rxjs.distinctUntilChanged)(), require_operators.filterNull());
|
|
2087
|
+
return this.cachedObservable("recording$", () => this._sessionState$.pipe((0, rxjs.map)((state) => state.recording), (0, rxjs.distinctUntilChanged)(), require_operators.filterNull()));
|
|
2001
2088
|
}
|
|
2002
2089
|
get recordings$() {
|
|
2003
|
-
return this._sessionState$.pipe((0, rxjs.map)((state) => state.recordings), (0, rxjs.distinctUntilChanged)(), require_operators.filterNull());
|
|
2090
|
+
return this.cachedObservable("recordings$", () => this._sessionState$.pipe((0, rxjs.map)((state) => state.recordings), (0, rxjs.distinctUntilChanged)(), require_operators.filterNull()));
|
|
2004
2091
|
}
|
|
2005
2092
|
get streaming$() {
|
|
2006
|
-
return this._sessionState$.pipe((0, rxjs.map)((state) => state.streaming), (0, rxjs.distinctUntilChanged)(), require_operators.filterNull());
|
|
2093
|
+
return this.cachedObservable("streaming$", () => this._sessionState$.pipe((0, rxjs.map)((state) => state.streaming), (0, rxjs.distinctUntilChanged)(), require_operators.filterNull()));
|
|
2007
2094
|
}
|
|
2008
2095
|
get streams$() {
|
|
2009
|
-
return this._sessionState$.pipe((0, rxjs.map)((state) => state.streams), (0, rxjs.distinctUntilChanged)(), require_operators.filterNull());
|
|
2096
|
+
return this.cachedObservable("streams$", () => this._sessionState$.pipe((0, rxjs.map)((state) => state.streams), (0, rxjs.distinctUntilChanged)(), require_operators.filterNull()));
|
|
2010
2097
|
}
|
|
2011
2098
|
get playbacks$() {
|
|
2012
|
-
return this._sessionState$.pipe((0, rxjs.map)((state) => state.playbacks), (0, rxjs.distinctUntilChanged)(), require_operators.filterNull());
|
|
2099
|
+
return this.cachedObservable("playbacks$", () => this._sessionState$.pipe((0, rxjs.map)((state) => state.playbacks), (0, rxjs.distinctUntilChanged)(), require_operators.filterNull()));
|
|
2013
2100
|
}
|
|
2014
2101
|
get raiseHandPriority$() {
|
|
2015
|
-
return this._sessionState$.pipe((0, rxjs.map)((state) => state.prioritize_handraise), (0, rxjs.distinctUntilChanged)(), require_operators.filterNull());
|
|
2102
|
+
return this.cachedObservable("raiseHandPriority$", () => this._sessionState$.pipe((0, rxjs.map)((state) => state.prioritize_handraise), (0, rxjs.distinctUntilChanged)(), require_operators.filterNull()));
|
|
2016
2103
|
}
|
|
2017
2104
|
get locked$() {
|
|
2018
|
-
return this._sessionState$.pipe((0, rxjs.map)((state) => state.locked), (0, rxjs.distinctUntilChanged)(), require_operators.filterNull());
|
|
2105
|
+
return this.cachedObservable("locked$", () => this._sessionState$.pipe((0, rxjs.map)((state) => state.locked), (0, rxjs.distinctUntilChanged)(), require_operators.filterNull()));
|
|
2019
2106
|
}
|
|
2020
2107
|
get meta$() {
|
|
2021
|
-
return this._sessionState$.pipe((0, rxjs.map)((state) => state.meta), (0, rxjs.distinctUntilChanged)(), require_operators.filterNull());
|
|
2108
|
+
return this.cachedObservable("meta$", () => this._sessionState$.pipe((0, rxjs.map)((state) => state.meta), (0, rxjs.distinctUntilChanged)(), require_operators.filterNull()));
|
|
2022
2109
|
}
|
|
2023
2110
|
get capabilities$() {
|
|
2024
|
-
return this._sessionState$.pipe((0, rxjs.map)((state) => state.capabilities), (0, rxjs.distinctUntilChanged)(), require_operators.filterNull());
|
|
2111
|
+
return this.cachedObservable("capabilities$", () => this._sessionState$.pipe((0, rxjs.map)((state) => state.capabilities), (0, rxjs.distinctUntilChanged)(), require_operators.filterNull()));
|
|
2025
2112
|
}
|
|
2026
2113
|
get layout$() {
|
|
2027
|
-
return this._sessionState$.pipe((0, rxjs.map)((state) => state.layout_name), (0, rxjs.distinctUntilChanged)(), require_operators.filterNull());
|
|
2114
|
+
return this.cachedObservable("layout$", () => this._sessionState$.pipe((0, rxjs.map)((state) => state.layout_name), (0, rxjs.distinctUntilChanged)(), require_operators.filterNull()));
|
|
2028
2115
|
}
|
|
2029
2116
|
get layouts$() {
|
|
2030
|
-
return this._sessionState$.pipe((0, rxjs.map)((state) => state.layouts), (0, rxjs.distinctUntilChanged)(), require_operators.filterNull());
|
|
2117
|
+
return this.cachedObservable("layouts$", () => this._sessionState$.pipe((0, rxjs.map)((state) => state.layouts), (0, rxjs.distinctUntilChanged)(), require_operators.filterNull()));
|
|
2031
2118
|
}
|
|
2032
2119
|
get layoutLayers$() {
|
|
2033
|
-
return this._sessionState$.pipe((0, rxjs.map)((state) => state.layout_layers), (0, rxjs.distinctUntilChanged)(), require_operators.filterNull());
|
|
2120
|
+
return this.cachedObservable("layoutLayers$", () => this._sessionState$.pipe((0, rxjs.map)((state) => state.layout_layers), (0, rxjs.distinctUntilChanged)(), require_operators.filterNull()));
|
|
2034
2121
|
}
|
|
2035
2122
|
get self() {
|
|
2036
2123
|
return this._self$.value;
|
|
@@ -2071,7 +2158,6 @@ var CallEventsManager = class extends Destroyable {
|
|
|
2071
2158
|
callId: callJoinedEvent.call_id,
|
|
2072
2159
|
roomSessionId: callJoinedEvent.room_session_id
|
|
2073
2160
|
});
|
|
2074
|
-
this._status$.next("connected");
|
|
2075
2161
|
const sessionState = callJoinedEvent.room_session;
|
|
2076
2162
|
const { capabilities } = callJoinedEvent;
|
|
2077
2163
|
this.selfId = this.selfId ?? callJoinedEvent.member_id;
|
|
@@ -2092,7 +2178,7 @@ var CallEventsManager = class extends Destroyable {
|
|
|
2092
2178
|
});
|
|
2093
2179
|
this.updateParticipants(sessionState.members);
|
|
2094
2180
|
this._self$.value?.capabilities.updateFromRaw(capabilities);
|
|
2095
|
-
this.updateLayouts();
|
|
2181
|
+
if (this._self$.value?.capabilities.setLayout) this.updateLayouts();
|
|
2096
2182
|
});
|
|
2097
2183
|
this.subscribeTo(this.memberUpdates$, (member) => {
|
|
2098
2184
|
logger$15.debug("[CallEventsManager] Handling member update event for member ID:", member);
|
|
@@ -2166,19 +2252,19 @@ var CallEventsManager = class extends Destroyable {
|
|
|
2166
2252
|
this._participants$.next(this._participants$.value);
|
|
2167
2253
|
}
|
|
2168
2254
|
get callJoinedEvent$() {
|
|
2169
|
-
return this.webRtcCallSession.callEvent$.pipe((0, rxjs.filter)(isCallJoinedPayload), (0, rxjs.tap)((event) => {
|
|
2255
|
+
return this.cachedObservable("callJoinedEvent$", () => this.webRtcCallSession.callEvent$.pipe((0, rxjs.filter)(isCallJoinedPayload), (0, rxjs.tap)((event) => {
|
|
2170
2256
|
logger$15.debug("[CallEventsManager] Call joined event:", event);
|
|
2171
|
-
}));
|
|
2257
|
+
})));
|
|
2172
2258
|
}
|
|
2173
2259
|
get layoutChangedEvent$() {
|
|
2174
|
-
return this.webRtcCallSession.callEvent$.pipe(require_operators.filterAs(isLayoutChangedPayload, "layout"), (0, rxjs.tap)((event) => {
|
|
2260
|
+
return this.cachedObservable("layoutChangedEvent$", () => this.webRtcCallSession.callEvent$.pipe(require_operators.filterAs(isLayoutChangedPayload, "layout"), (0, rxjs.tap)((event) => {
|
|
2175
2261
|
logger$15.debug("[CallEventsManager] Layout changed event:", event);
|
|
2176
|
-
}));
|
|
2262
|
+
})));
|
|
2177
2263
|
}
|
|
2178
2264
|
get memberUpdates$() {
|
|
2179
|
-
return (0, rxjs.merge)(this.webRtcCallSession.memberJoined$, this.webRtcCallSession.memberUpdated$, this.webRtcCallSession.memberTalking$).pipe((0, rxjs.map)((event) => event.member), (0, rxjs.tap)((event) => {
|
|
2265
|
+
return this.cachedObservable("memberUpdates$", () => (0, rxjs.merge)(this.webRtcCallSession.memberJoined$, this.webRtcCallSession.memberUpdated$, this.webRtcCallSession.memberTalking$).pipe((0, rxjs.map)((event) => event.member), (0, rxjs.tap)((event) => {
|
|
2180
2266
|
logger$15.debug("[CallEventsManager] Member update event:", event);
|
|
2181
|
-
}));
|
|
2267
|
+
})));
|
|
2182
2268
|
}
|
|
2183
2269
|
destroy() {
|
|
2184
2270
|
Object.values(this._participants$.value).forEach((participant) => {
|
|
@@ -2198,12 +2284,53 @@ var CallEventsManager = class extends Destroyable {
|
|
|
2198
2284
|
|
|
2199
2285
|
//#endregion
|
|
2200
2286
|
//#region src/helpers/SDPHelper.ts
|
|
2287
|
+
/** Valid SDP direction attribute values. */
|
|
2288
|
+
const SDP_DIRECTIONS = new Set([
|
|
2289
|
+
"sendrecv",
|
|
2290
|
+
"sendonly",
|
|
2291
|
+
"recvonly",
|
|
2292
|
+
"inactive"
|
|
2293
|
+
]);
|
|
2201
2294
|
/**
|
|
2202
|
-
*
|
|
2295
|
+
* Extracts the media directions (audio/video) from an SDP string.
|
|
2296
|
+
*
|
|
2297
|
+
* Parses each media section (`m=audio` / `m=video`) and reads the `a=` direction
|
|
2298
|
+
* attribute (`sendrecv`, `sendonly`, `recvonly`, `inactive`).
|
|
2299
|
+
* If no explicit direction attribute is found for a media section, defaults to `sendrecv`
|
|
2300
|
+
* per RFC 4566.
|
|
2301
|
+
*
|
|
2302
|
+
* @param sdp - The SDP string to parse
|
|
2303
|
+
* @returns The extracted audio and video directions
|
|
2203
2304
|
*
|
|
2204
|
-
*
|
|
2205
|
-
*
|
|
2305
|
+
* @example
|
|
2306
|
+
* ```typescript
|
|
2307
|
+
* const sdp = `v=0\r\nm=audio 9 UDP/TLS/RTP/SAVPF 111\r\na=sendrecv\r\nm=video 9 UDP/TLS/RTP/SAVPF 96\r\na=recvonly`;
|
|
2308
|
+
* extractMediaDirectionsFromSDP(sdp);
|
|
2309
|
+
* // { audio: 'sendrecv', video: 'recvonly' }
|
|
2310
|
+
* ```
|
|
2206
2311
|
*/
|
|
2312
|
+
function extractMediaDirectionsFromSDP(sdp) {
|
|
2313
|
+
const result = {
|
|
2314
|
+
audio: "inactive",
|
|
2315
|
+
video: "inactive"
|
|
2316
|
+
};
|
|
2317
|
+
if (!sdp) return result;
|
|
2318
|
+
const lines = sdp.split(/\r?\n/);
|
|
2319
|
+
let currentMediaKind = null;
|
|
2320
|
+
let currentDirection = null;
|
|
2321
|
+
for (const line of lines) if (line.startsWith("m=")) {
|
|
2322
|
+
if (currentMediaKind) result[currentMediaKind] = currentDirection ?? "sendrecv";
|
|
2323
|
+
if (line.startsWith("m=audio")) currentMediaKind = "audio";
|
|
2324
|
+
else if (line.startsWith("m=video")) currentMediaKind = "video";
|
|
2325
|
+
else currentMediaKind = null;
|
|
2326
|
+
currentDirection = null;
|
|
2327
|
+
} else if (currentMediaKind && line.startsWith("a=")) {
|
|
2328
|
+
const attr = line.substring(2).trim();
|
|
2329
|
+
if (SDP_DIRECTIONS.has(attr)) currentDirection = attr;
|
|
2330
|
+
}
|
|
2331
|
+
if (currentMediaKind) result[currentMediaKind] = currentDirection ?? "sendrecv";
|
|
2332
|
+
return result;
|
|
2333
|
+
}
|
|
2207
2334
|
/**
|
|
2208
2335
|
* Validates that an SDP string has at least one non-host ICE candidate
|
|
2209
2336
|
* for each media section (m= line).
|
|
@@ -2504,6 +2631,15 @@ var LocalStreamController = class extends Destroyable {
|
|
|
2504
2631
|
track.addEventListener("ended", this.mediaTrackEndedHandler);
|
|
2505
2632
|
}
|
|
2506
2633
|
/**
|
|
2634
|
+
* Update the controller options (e.g., when media overrides are applied).
|
|
2635
|
+
*/
|
|
2636
|
+
updateOptions(options) {
|
|
2637
|
+
this.options = {
|
|
2638
|
+
...this.options,
|
|
2639
|
+
...options
|
|
2640
|
+
};
|
|
2641
|
+
}
|
|
2642
|
+
/**
|
|
2507
2643
|
* Stop all local tracks and clean up.
|
|
2508
2644
|
*/
|
|
2509
2645
|
stopAllTracks() {
|
|
@@ -2817,7 +2953,7 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
2817
2953
|
logger$11.debug(`[RTCPeerConnectionController] ${kind} input device selected: none`);
|
|
2818
2954
|
return;
|
|
2819
2955
|
}
|
|
2820
|
-
const streamTrack = (await
|
|
2956
|
+
const streamTrack = (await this.getUserMedia({ [kind]: {
|
|
2821
2957
|
...track.getConstraints(),
|
|
2822
2958
|
...this.deviceController.deviceInfoToConstraints(deviceInfo)
|
|
2823
2959
|
} })).getTracks().find((t) => t.kind === kind);
|
|
@@ -2841,11 +2977,12 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
2841
2977
|
this._connectionState$ = this.createReplaySubject(1);
|
|
2842
2978
|
this._signalingState$ = this.createReplaySubject(1);
|
|
2843
2979
|
this._iceGatheringState$ = this.createReplaySubject(1);
|
|
2844
|
-
this._errors$ = this.
|
|
2980
|
+
this._errors$ = this.createReplaySubject(1);
|
|
2845
2981
|
this._iceCandidates$ = this.createReplaySubject(1);
|
|
2846
2982
|
this._initialized$ = this.createReplaySubject(1);
|
|
2847
2983
|
this._remoteDescription$ = this.createReplaySubject(1);
|
|
2848
2984
|
this._remoteStream$ = this.createBehaviorSubject(null);
|
|
2985
|
+
this._remoteOfferMediaDirections = null;
|
|
2849
2986
|
this.deviceController = deviceController ?? {};
|
|
2850
2987
|
this.id = options.callId ?? (0, uuid.v4)();
|
|
2851
2988
|
this._type = remoteSessionDescription ? "answer" : "offer";
|
|
@@ -2853,10 +2990,19 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
2853
2990
|
type: "offer",
|
|
2854
2991
|
sdp: remoteSessionDescription
|
|
2855
2992
|
} : void 0;
|
|
2993
|
+
this._remoteOfferMediaDirections = remoteSessionDescription ? extractMediaDirectionsFromSDP(remoteSessionDescription) : null;
|
|
2994
|
+
const offerDefaults = this._remoteOfferMediaDirections ? {
|
|
2995
|
+
audio: this._remoteOfferMediaDirections.audio.includes("recv"),
|
|
2996
|
+
video: this._remoteOfferMediaDirections.video.includes("recv"),
|
|
2997
|
+
receiveAudio: this._remoteOfferMediaDirections.audio.includes("send"),
|
|
2998
|
+
receiveVideo: this._remoteOfferMediaDirections.video.includes("send")
|
|
2999
|
+
} : {};
|
|
2856
3000
|
this.options = {
|
|
2857
|
-
|
|
2858
|
-
|
|
2859
|
-
|
|
3001
|
+
...options,
|
|
3002
|
+
audio: options.audio ?? offerDefaults.audio,
|
|
3003
|
+
video: options.video ?? offerDefaults.video,
|
|
3004
|
+
receiveAudio: options.receiveAudio ?? offerDefaults.receiveAudio ?? PreferencesContainer.instance.receiveAudio,
|
|
3005
|
+
receiveVideo: options.receiveVideo ?? offerDefaults.receiveVideo ?? PreferencesContainer.instance.receiveVideo
|
|
2860
3006
|
};
|
|
2861
3007
|
this.localStreamController = new LocalStreamController({
|
|
2862
3008
|
propose: this.propose,
|
|
@@ -2906,43 +3052,43 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
2906
3052
|
};
|
|
2907
3053
|
}
|
|
2908
3054
|
get iceGatheringState$() {
|
|
2909
|
-
return this._iceGatheringState$.asObservable().pipe((0, rxjs.takeUntil)(this.destroyed$));
|
|
3055
|
+
return this.cachedObservable("iceGatheringState$", () => this._iceGatheringState$.asObservable().pipe((0, rxjs.takeUntil)(this.destroyed$)));
|
|
2910
3056
|
}
|
|
2911
3057
|
get mediaTrackEnded$() {
|
|
2912
|
-
return this.localStreamController.mediaTrackEnded$.pipe((0, rxjs.takeUntil)(this.destroyed$));
|
|
3058
|
+
return this.cachedObservable("mediaTrackEnded$", () => this.localStreamController.mediaTrackEnded$.pipe((0, rxjs.takeUntil)(this.destroyed$)));
|
|
2913
3059
|
}
|
|
2914
3060
|
get errors$() {
|
|
2915
|
-
return this._errors$.asObservable().pipe((0, rxjs.takeUntil)(this.destroyed$));
|
|
3061
|
+
return this.cachedObservable("errors$", () => this._errors$.asObservable().pipe((0, rxjs.takeUntil)(this.destroyed$)));
|
|
2916
3062
|
}
|
|
2917
3063
|
get iceCandidates$() {
|
|
2918
|
-
return this._iceCandidates$.asObservable().pipe((0, rxjs.takeUntil)(this.destroyed$));
|
|
3064
|
+
return this.cachedObservable("iceCandidates$", () => this._iceCandidates$.asObservable().pipe((0, rxjs.takeUntil)(this.destroyed$)));
|
|
2919
3065
|
}
|
|
2920
3066
|
get initialized$() {
|
|
2921
|
-
return this._initialized$.asObservable().pipe((0, rxjs.filter)((initialized) => initialized), (0, rxjs.takeUntil)(this.destroyed$));
|
|
3067
|
+
return this.cachedObservable("initialized$", () => this._initialized$.asObservable().pipe((0, rxjs.filter)((initialized) => initialized), (0, rxjs.takeUntil)(this.destroyed$)));
|
|
2922
3068
|
}
|
|
2923
3069
|
get remoteDescription$() {
|
|
2924
|
-
return this._remoteDescription$.asObservable().pipe((0, rxjs.takeUntil)(this.destroyed$));
|
|
3070
|
+
return this.cachedObservable("remoteDescription$", () => this._remoteDescription$.asObservable().pipe((0, rxjs.takeUntil)(this.destroyed$)));
|
|
2925
3071
|
}
|
|
2926
3072
|
get localStream$() {
|
|
2927
|
-
return this.localStreamController.localStream$.pipe((0, rxjs.takeUntil)(this.destroyed$));
|
|
3073
|
+
return this.cachedObservable("localStream$", () => this.localStreamController.localStream$.pipe((0, rxjs.takeUntil)(this.destroyed$)));
|
|
2928
3074
|
}
|
|
2929
3075
|
get remoteStream$() {
|
|
2930
|
-
return this._remoteStream$.asObservable().pipe((0, rxjs.takeUntil)(this.destroyed$));
|
|
3076
|
+
return this.cachedObservable("remoteStream$", () => this._remoteStream$.asObservable().pipe((0, rxjs.takeUntil)(this.destroyed$)));
|
|
2931
3077
|
}
|
|
2932
3078
|
get localAudioTracks$() {
|
|
2933
|
-
return this.localStreamController.localAudioTracks$.pipe((0, rxjs.takeUntil)(this.destroyed$));
|
|
3079
|
+
return this.cachedObservable("localAudioTracks$", () => this.localStreamController.localAudioTracks$.pipe((0, rxjs.takeUntil)(this.destroyed$)));
|
|
2934
3080
|
}
|
|
2935
3081
|
get localVideoTracks$() {
|
|
2936
|
-
return this.localStreamController.localVideoTracks$.pipe((0, rxjs.takeUntil)(this.destroyed$));
|
|
3082
|
+
return this.cachedObservable("localVideoTracks$", () => this.localStreamController.localVideoTracks$.pipe((0, rxjs.takeUntil)(this.destroyed$)));
|
|
2937
3083
|
}
|
|
2938
3084
|
get iceConnectionState$() {
|
|
2939
|
-
return this._iceConnectionState$.asObservable().pipe((0, rxjs.takeUntil)(this.destroyed$));
|
|
3085
|
+
return this.cachedObservable("iceConnectionState$", () => this._iceConnectionState$.asObservable().pipe((0, rxjs.takeUntil)(this.destroyed$)));
|
|
2940
3086
|
}
|
|
2941
3087
|
get connectionState$() {
|
|
2942
|
-
return this._connectionState$.asObservable().pipe((0, rxjs.takeUntil)(this.destroyed$));
|
|
3088
|
+
return this.cachedObservable("connectionState$", () => this._connectionState$.asObservable().pipe((0, rxjs.takeUntil)(this.destroyed$)));
|
|
2943
3089
|
}
|
|
2944
3090
|
get signalingState$() {
|
|
2945
|
-
return this._signalingState$.asObservable().pipe((0, rxjs.takeUntil)(this.destroyed$));
|
|
3091
|
+
return this.cachedObservable("signalingState$", () => this._signalingState$.asObservable().pipe((0, rxjs.takeUntil)(this.destroyed$)));
|
|
2946
3092
|
}
|
|
2947
3093
|
get type() {
|
|
2948
3094
|
return this._type;
|
|
@@ -3001,14 +3147,14 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
3001
3147
|
};
|
|
3002
3148
|
}
|
|
3003
3149
|
get inputVideoDeviceConstraints() {
|
|
3004
|
-
if (this.options.video
|
|
3150
|
+
if (!this.options.video && !this.options.inputVideoDeviceConstraints) return false;
|
|
3005
3151
|
return {
|
|
3006
3152
|
...this.options.inputVideoDeviceConstraints,
|
|
3007
3153
|
...this.deviceController.selectedVideoInputDeviceConstraints
|
|
3008
3154
|
};
|
|
3009
3155
|
}
|
|
3010
3156
|
get WebRTCPeerConnectionConstructor() {
|
|
3011
|
-
return this.options.
|
|
3157
|
+
return this.options.webRTCApiProvider?.RTCPeerConnection ?? RTCPeerConnection;
|
|
3012
3158
|
}
|
|
3013
3159
|
get offerOptions() {
|
|
3014
3160
|
const options = { iceRestart: this.firstSDPExchangeCompleted ? true : void 0 };
|
|
@@ -3023,12 +3169,12 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
3023
3169
|
default: return {
|
|
3024
3170
|
...options,
|
|
3025
3171
|
offerToReceiveAudio: true,
|
|
3026
|
-
offerToReceiveVideo: Boolean(this.inputVideoDeviceConstraints)
|
|
3172
|
+
offerToReceiveVideo: this.options.receiveVideo ?? Boolean(this.inputVideoDeviceConstraints)
|
|
3027
3173
|
};
|
|
3028
3174
|
}
|
|
3029
3175
|
}
|
|
3030
3176
|
get answerOptions() {
|
|
3031
|
-
return {};
|
|
3177
|
+
return { iceRestart: this.firstSDPExchangeCompleted ? true : void 0 };
|
|
3032
3178
|
}
|
|
3033
3179
|
/**
|
|
3034
3180
|
* Initialize the RTCPeerConnection and setup event listeners.
|
|
@@ -3063,11 +3209,15 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
3063
3209
|
});
|
|
3064
3210
|
await this.updateSelectedInputDevice(kind, deviceInfo);
|
|
3065
3211
|
});
|
|
3066
|
-
await this.setupTrackHandling();
|
|
3067
|
-
this._initialized$.next(true);
|
|
3068
3212
|
if (this.type === "answer" && this.sdpInit) {
|
|
3213
|
+
await this.setupRemoteTracks();
|
|
3214
|
+
this._initialized$.next(true);
|
|
3069
3215
|
this.setupEventListeners();
|
|
3070
|
-
|
|
3216
|
+
this._isNegotiating$.next(true);
|
|
3217
|
+
await this._setRemoteDescription(this.sdpInit);
|
|
3218
|
+
} else {
|
|
3219
|
+
await this.setupTrackHandling();
|
|
3220
|
+
this._initialized$.next(true);
|
|
3071
3221
|
}
|
|
3072
3222
|
} catch (error) {
|
|
3073
3223
|
logger$11.error("[RTCPeerConnectionController] Initialization error:", error);
|
|
@@ -3165,6 +3315,35 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
3165
3315
|
default:
|
|
3166
3316
|
}
|
|
3167
3317
|
}
|
|
3318
|
+
/**
|
|
3319
|
+
* Accept an inbound call by creating the SDP answer.
|
|
3320
|
+
* Optionally override media options before the answer is generated.
|
|
3321
|
+
* Must be called after initialization for inbound (answer-type) connections.
|
|
3322
|
+
*/
|
|
3323
|
+
async acceptInbound(mediaOverrides) {
|
|
3324
|
+
if (mediaOverrides) {
|
|
3325
|
+
const { audio, video, receiveAudio, receiveVideo } = mediaOverrides;
|
|
3326
|
+
this.options = {
|
|
3327
|
+
...this.options,
|
|
3328
|
+
...audio !== void 0 ? { audio } : {},
|
|
3329
|
+
...video !== void 0 ? { video } : {},
|
|
3330
|
+
...receiveAudio !== void 0 ? { receiveAudio } : {},
|
|
3331
|
+
...receiveVideo !== void 0 ? { receiveVideo } : {}
|
|
3332
|
+
};
|
|
3333
|
+
this.transceiverController?.updateOptions({
|
|
3334
|
+
receiveAudio: this.receiveAudio,
|
|
3335
|
+
receiveVideo: this.receiveVideo
|
|
3336
|
+
});
|
|
3337
|
+
this.localStreamController.updateOptions({
|
|
3338
|
+
inputAudioDeviceConstraints: this.inputAudioDeviceConstraints,
|
|
3339
|
+
inputVideoDeviceConstraints: this.inputVideoDeviceConstraints
|
|
3340
|
+
});
|
|
3341
|
+
}
|
|
3342
|
+
await this.setupLocalTracks();
|
|
3343
|
+
const { answerOptions } = this;
|
|
3344
|
+
logger$11.debug("[RTCPeerConnectionController] Creating inbound answer with options:", answerOptions);
|
|
3345
|
+
await this.createAnswer(answerOptions);
|
|
3346
|
+
}
|
|
3168
3347
|
async handleOfferReceived() {
|
|
3169
3348
|
if (!this.sdpInit) throw new require_operators.DependencyError("SDP initialization parameters are not set");
|
|
3170
3349
|
this._isNegotiating$.next(true);
|
|
@@ -3239,52 +3418,51 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
3239
3418
|
}
|
|
3240
3419
|
async setupLocalTracks() {
|
|
3241
3420
|
logger$11.debug("[RTCPeerConnectionController] Setting up local tracks/transceivers.");
|
|
3242
|
-
|
|
3243
|
-
if (
|
|
3244
|
-
|
|
3245
|
-
|
|
3246
|
-
|
|
3247
|
-
|
|
3248
|
-
|
|
3249
|
-
if (localStream) {
|
|
3250
|
-
if (this.transceiverController?.useAddStream ?? false) {
|
|
3251
|
-
logger$11.warn("[RTCPeerConnectionController] Using deprecated addStream API to add local stream.");
|
|
3252
|
-
this.peerConnection?.addStream(localStream);
|
|
3253
|
-
if (!this.isNegotiating) {
|
|
3254
|
-
logger$11.debug("[RTCPeerConnectionController] Forcing negotiationneeded after local tracks setup.");
|
|
3255
|
-
this.negotiationNeeded$.next();
|
|
3256
|
-
}
|
|
3257
|
-
return;
|
|
3421
|
+
const localStream = this.localStream ?? await this.localStreamController.buildLocalStream();
|
|
3422
|
+
if (this.transceiverController?.useAddStream ?? false) {
|
|
3423
|
+
logger$11.warn("[RTCPeerConnectionController] Using deprecated addStream API to add local stream.");
|
|
3424
|
+
this.peerConnection?.addStream(localStream);
|
|
3425
|
+
if (!this.isNegotiating) {
|
|
3426
|
+
logger$11.debug("[RTCPeerConnectionController] Forcing negotiationneeded after local tracks setup.");
|
|
3427
|
+
this.negotiationNeeded$.next();
|
|
3258
3428
|
}
|
|
3259
|
-
|
|
3260
|
-
|
|
3261
|
-
|
|
3262
|
-
|
|
3263
|
-
|
|
3264
|
-
|
|
3265
|
-
|
|
3266
|
-
|
|
3267
|
-
|
|
3268
|
-
|
|
3269
|
-
|
|
3270
|
-
|
|
3271
|
-
|
|
3272
|
-
}
|
|
3429
|
+
return;
|
|
3430
|
+
}
|
|
3431
|
+
for (const kind of ["audio", "video"]) {
|
|
3432
|
+
const tracks = (kind === "audio" ? localStream.getAudioTracks() : localStream.getVideoTracks()).map((track, index) => ({
|
|
3433
|
+
index,
|
|
3434
|
+
track
|
|
3435
|
+
}));
|
|
3436
|
+
for (const { index, track } of tracks) {
|
|
3437
|
+
this.localStreamController.addTrackEndedListener(track);
|
|
3438
|
+
if (this.transceiverController?.useAddTransceivers ?? false) {
|
|
3439
|
+
const transceivers = (kind === "audio" ? this.transceiverController?.audioTransceivers : this.transceiverController?.videoTransceivers) ?? [];
|
|
3440
|
+
await this.transceiverController?.setupTransceiverSender(track, localStream, transceivers[index]);
|
|
3441
|
+
} else {
|
|
3442
|
+
logger$11.debug(`[RTCPeerConnectionController] Using addTrack for local ${kind} track:`, track.id);
|
|
3443
|
+
this.peerConnection?.addTrack(track, localStream);
|
|
3273
3444
|
}
|
|
3274
3445
|
}
|
|
3275
3446
|
}
|
|
3276
3447
|
}
|
|
3277
3448
|
async getUserMedia(constraints) {
|
|
3278
|
-
return this.options.
|
|
3449
|
+
return (this.options.webRTCApiProvider?.mediaDevices ?? navigator.mediaDevices).getUserMedia(constraints);
|
|
3279
3450
|
}
|
|
3280
3451
|
async getDisplayMedia(options) {
|
|
3281
|
-
|
|
3452
|
+
const mediaDevices = this.options.webRTCApiProvider?.mediaDevices ?? navigator.mediaDevices;
|
|
3453
|
+
if (!mediaDevices.getDisplayMedia) throw new require_operators.DependencyError("getDisplayMedia is not supported by the current WebRTC provider");
|
|
3454
|
+
return mediaDevices.getDisplayMedia(options);
|
|
3282
3455
|
}
|
|
3283
3456
|
async setupRemoteTracks() {
|
|
3284
3457
|
if (!this.peerConnection) throw new require_operators.DependencyError("RTCPeerConnection is not initialized");
|
|
3285
3458
|
this.peerConnection.ontrack = (event) => {
|
|
3286
3459
|
logger$11.debug("[RTCPeerConnectionController] Remote track received:", event.track.kind);
|
|
3287
|
-
this._remoteStream$.next(event.streams[0]);
|
|
3460
|
+
if (event.streams[0]) this._remoteStream$.next(event.streams[0]);
|
|
3461
|
+
else {
|
|
3462
|
+
const existingTracks = this._remoteStream$.value?.getTracks() ?? [];
|
|
3463
|
+
const newStream = new MediaStream([...existingTracks, event.track]);
|
|
3464
|
+
this._remoteStream$.next(newStream);
|
|
3465
|
+
}
|
|
3288
3466
|
};
|
|
3289
3467
|
await this.transceiverController?.setupRemoteTransceivers(this.type);
|
|
3290
3468
|
}
|
|
@@ -3383,7 +3561,7 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
3383
3561
|
});
|
|
3384
3562
|
}
|
|
3385
3563
|
get mediaDirections() {
|
|
3386
|
-
return this.transceiverController?.getMediaDirections() ?? {
|
|
3564
|
+
return this.transceiverController?.getMediaDirections() ?? this._remoteOfferMediaDirections ?? {
|
|
3387
3565
|
audio: "inactive",
|
|
3388
3566
|
video: "inactive"
|
|
3389
3567
|
};
|
|
@@ -3419,7 +3597,10 @@ function isVertoAttachMessage(value) {
|
|
|
3419
3597
|
return value.method === "verto.attach";
|
|
3420
3598
|
}
|
|
3421
3599
|
function isVertoAnswerInnerParams(value) {
|
|
3422
|
-
return isObject(value) && hasProperty(value, "jsonrpc") && value.jsonrpc === "2.0" && hasProperty(value, "method") && value.method === "verto.answer" && isObject(value.params) && hasProperty(value.params, "callID")
|
|
3600
|
+
return isObject(value) && hasProperty(value, "jsonrpc") && value.jsonrpc === "2.0" && hasProperty(value, "method") && value.method === "verto.answer" && isObject(value.params) && hasProperty(value.params, "callID");
|
|
3601
|
+
}
|
|
3602
|
+
function isVertoMediaInnerParams(value) {
|
|
3603
|
+
return isObject(value) && hasProperty(value, "jsonrpc") && value.jsonrpc === "2.0" && hasProperty(value, "method") && value.method === "verto.media" && isObject(value.params) && hasProperty(value.params, "callID") && hasProperty(value.params, "sdp");
|
|
3423
3604
|
}
|
|
3424
3605
|
function isVertoMediaParamsInnerParams(value) {
|
|
3425
3606
|
return isObject(value) && hasProperty(value, "jsonrpc") && value.jsonrpc === "2.0" && hasProperty(value, "method") && value.method === "verto.mediaParams" && isObject(value.params) && hasProperty(value.params, "mediaParams");
|
|
@@ -3442,11 +3623,12 @@ var VertoManager = class extends Destroyable {
|
|
|
3442
3623
|
}
|
|
3443
3624
|
};
|
|
3444
3625
|
var WebRTCVertoManager = class extends VertoManager {
|
|
3445
|
-
constructor(webRtcCallSession, attachManager, deviceController, options = {}) {
|
|
3626
|
+
constructor(webRtcCallSession, attachManager, deviceController, webRTCApiProvider, options = {}) {
|
|
3446
3627
|
super(webRtcCallSession);
|
|
3447
3628
|
this.webRtcCallSession = webRtcCallSession;
|
|
3448
3629
|
this.attachManager = attachManager;
|
|
3449
3630
|
this.deviceController = deviceController;
|
|
3631
|
+
this.webRTCApiProvider = webRTCApiProvider;
|
|
3450
3632
|
this._rtcPeerConnections$ = this.createBehaviorSubject([]);
|
|
3451
3633
|
this._selfId$ = this.createBehaviorSubject(null);
|
|
3452
3634
|
this._signalingStatus$ = this.createBehaviorSubject(null);
|
|
@@ -3520,17 +3702,32 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
3520
3702
|
return rtcPeerConnection;
|
|
3521
3703
|
}
|
|
3522
3704
|
get signalingStatus$() {
|
|
3523
|
-
return (0, rxjs.merge)(this._signalingStatus$.pipe(require_operators.filterNull()), this.mainPeerConnection.connectionState$.pipe((0, rxjs.filter)((connectionState) => [
|
|
3705
|
+
return this.cachedObservable("signalingStatus$", () => (0, rxjs.merge)(this._signalingStatus$.pipe(require_operators.filterNull()), this.mainPeerConnection.connectionState$.pipe((0, rxjs.filter)((connectionState) => [
|
|
3524
3706
|
"connected",
|
|
3525
3707
|
"disconnected",
|
|
3526
3708
|
"failed"
|
|
3527
|
-
].includes(connectionState))));
|
|
3709
|
+
].includes(connectionState)))));
|
|
3528
3710
|
}
|
|
3529
3711
|
initSubscriptions() {
|
|
3712
|
+
this.subscribeTo(this.callJoinedEvent$, (event) => {
|
|
3713
|
+
const memberNodeId = event.room_session.members.find((m) => m.call_id === event.call_id)?.node_id;
|
|
3714
|
+
if (memberNodeId) this.setNodeIdIfNull(memberNodeId);
|
|
3715
|
+
if (event.member_id) this.setSelfIdIfNull(event.member_id);
|
|
3716
|
+
});
|
|
3717
|
+
this.subscribeTo(this.vertoMedia$, (event) => {
|
|
3718
|
+
logger$10.debug("[WebRTCManager] Received Verto media event (early media SDP):", event);
|
|
3719
|
+
this._signalingStatus$.next("ringing");
|
|
3720
|
+
const { sdp, callID } = event;
|
|
3721
|
+
this._rtcPeerConnectionsMap.get(callID)?.updateAnswerStatus({
|
|
3722
|
+
status: "received",
|
|
3723
|
+
sdp
|
|
3724
|
+
});
|
|
3725
|
+
});
|
|
3530
3726
|
this.subscribeTo(this.vertoAnswer$, (event) => {
|
|
3531
3727
|
logger$10.debug("[WebRTCManager] Received Verto answer event:", event);
|
|
3532
|
-
|
|
3533
|
-
|
|
3728
|
+
this._signalingStatus$.next("connecting");
|
|
3729
|
+
const { sdp, callID } = event;
|
|
3730
|
+
this._rtcPeerConnectionsMap.get(callID)?.updateAnswerStatus({
|
|
3534
3731
|
status: "received",
|
|
3535
3732
|
sdp
|
|
3536
3733
|
});
|
|
@@ -3548,6 +3745,28 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
3548
3745
|
this.sendVertoPong(vertoPing);
|
|
3549
3746
|
});
|
|
3550
3747
|
}
|
|
3748
|
+
/**
|
|
3749
|
+
* Set node_id/selfId only when the current value is null.
|
|
3750
|
+
*
|
|
3751
|
+
* During reattach, `call.joined` and `verto.answer` events can deliver
|
|
3752
|
+
* these identifiers before the `verto.invite` RPC response (`CALL CREATED`)
|
|
3753
|
+
* arrives. These methods let early events populate them eagerly so that
|
|
3754
|
+
* downstream RPC calls (e.g. `call.layout.list`) don't fail with empty
|
|
3755
|
+
* identifiers. `processInviteResponse()` remains the authoritative source
|
|
3756
|
+
* and always overwrites unconditionally.
|
|
3757
|
+
*/
|
|
3758
|
+
setNodeIdIfNull(nodeId) {
|
|
3759
|
+
if (!this._nodeId$.value && nodeId) {
|
|
3760
|
+
logger$10.debug(`[WebRTCManager] Early node_id set: ${nodeId}`);
|
|
3761
|
+
this._nodeId$.next(nodeId);
|
|
3762
|
+
}
|
|
3763
|
+
}
|
|
3764
|
+
setSelfIdIfNull(selfId) {
|
|
3765
|
+
if (!this._selfId$.value && selfId) {
|
|
3766
|
+
logger$10.debug(`[WebRTCManager] Early selfId set: ${selfId}`);
|
|
3767
|
+
this._selfId$.next(selfId);
|
|
3768
|
+
}
|
|
3769
|
+
}
|
|
3551
3770
|
async sendVertoPong(vertoPing) {
|
|
3552
3771
|
try {
|
|
3553
3772
|
const vertoPongMessage = VertoPong({ ...vertoPing });
|
|
@@ -3571,20 +3790,26 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
3571
3790
|
get selfId() {
|
|
3572
3791
|
return this._selfId$.value;
|
|
3573
3792
|
}
|
|
3793
|
+
get callJoinedEvent$() {
|
|
3794
|
+
return this.webRtcCallSession.callEvent$.pipe((0, rxjs.filter)(isCallJoinedPayload), (0, rxjs.takeUntil)(this.destroyed$));
|
|
3795
|
+
}
|
|
3796
|
+
get vertoMedia$() {
|
|
3797
|
+
return this.webRtcCallSession.webrtcMessages$.pipe(require_operators.filterAs(isVertoMediaInnerParams, "params"), (0, rxjs.takeUntil)(this.destroyed$));
|
|
3798
|
+
}
|
|
3574
3799
|
get vertoAnswer$() {
|
|
3575
|
-
return this.webRtcCallSession.webrtcMessages$.pipe(require_operators.filterAs(isVertoAnswerInnerParams, "params"), (0, rxjs.takeUntil)(this.destroyed$));
|
|
3800
|
+
return this.cachedObservable("vertoAnswer$", () => this.webRtcCallSession.webrtcMessages$.pipe(require_operators.filterAs(isVertoAnswerInnerParams, "params"), (0, rxjs.takeUntil)(this.destroyed$)));
|
|
3576
3801
|
}
|
|
3577
3802
|
get vertoMediaParams$() {
|
|
3578
|
-
return this.webRtcCallSession.webrtcMessages$.pipe(require_operators.filterAs(isVertoMediaParamsInnerParams, "params"), (0, rxjs.takeUntil)(this.destroyed$));
|
|
3803
|
+
return this.cachedObservable("vertoMediaParams$", () => this.webRtcCallSession.webrtcMessages$.pipe(require_operators.filterAs(isVertoMediaParamsInnerParams, "params"), (0, rxjs.takeUntil)(this.destroyed$)));
|
|
3579
3804
|
}
|
|
3580
3805
|
get vertoBye$() {
|
|
3581
|
-
return this.webRtcCallSession.webrtcMessages$.pipe(require_operators.filterAs(isVertoByeMessage, "params"), (0, rxjs.takeUntil)(this.destroyed$));
|
|
3806
|
+
return this.cachedObservable("vertoBye$", () => this.webRtcCallSession.webrtcMessages$.pipe(require_operators.filterAs(isVertoByeMessage, "params"), (0, rxjs.takeUntil)(this.destroyed$)));
|
|
3582
3807
|
}
|
|
3583
3808
|
get vertoAttach$() {
|
|
3584
|
-
return this.webRtcCallSession.webrtcMessages$.pipe(require_operators.filterAs(isVertoAttachMessage, "params"), (0, rxjs.takeUntil)(this.destroyed$));
|
|
3809
|
+
return this.cachedObservable("vertoAttach$", () => this.webRtcCallSession.webrtcMessages$.pipe(require_operators.filterAs(isVertoAttachMessage, "params"), (0, rxjs.takeUntil)(this.destroyed$)));
|
|
3585
3810
|
}
|
|
3586
3811
|
get vertoPing$() {
|
|
3587
|
-
return this.webRtcCallSession.webrtcMessages$.pipe(require_operators.filterAs(isVertoPingInnerParams, "params"), (0, rxjs.takeUntil)(this.destroyed$));
|
|
3812
|
+
return this.cachedObservable("vertoPing$", () => this.webRtcCallSession.webrtcMessages$.pipe(require_operators.filterAs(isVertoPingInnerParams, "params"), (0, rxjs.takeUntil)(this.destroyed$)));
|
|
3588
3813
|
}
|
|
3589
3814
|
async executeVerto(message, optionals = {}) {
|
|
3590
3815
|
const webrtcVertoMessage = WebrtcVerto({
|
|
@@ -3597,19 +3822,19 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
3597
3822
|
if (response.error) {
|
|
3598
3823
|
const error = new require_operators.JSONRPCError(response.error.code, response.error.message, response.error.data);
|
|
3599
3824
|
this.onError?.(error);
|
|
3600
|
-
|
|
3825
|
+
return response;
|
|
3601
3826
|
}
|
|
3602
3827
|
const innerResult = require_operators.getValueFrom(response, "result.result");
|
|
3603
3828
|
if (innerResult?.error) {
|
|
3604
3829
|
const error = new require_operators.JSONRPCError(innerResult.error.code, innerResult.error.message, innerResult.error.data);
|
|
3605
3830
|
this.onError?.(error);
|
|
3606
|
-
|
|
3831
|
+
return response;
|
|
3607
3832
|
}
|
|
3608
3833
|
return response;
|
|
3609
3834
|
}
|
|
3610
3835
|
async sendLocalDescription(message, rtcPeerConnController) {
|
|
3611
3836
|
const vertoMethod = message.method;
|
|
3612
|
-
const optionalsParams = this.getSendLocalSDPOptionalParams(rtcPeerConnController);
|
|
3837
|
+
const optionalsParams = this.getSendLocalSDPOptionalParams(rtcPeerConnController, vertoMethod);
|
|
3613
3838
|
try {
|
|
3614
3839
|
const response = await this.executeVerto(message, optionalsParams);
|
|
3615
3840
|
switch (vertoMethod) {
|
|
@@ -3623,7 +3848,7 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
3623
3848
|
}
|
|
3624
3849
|
} catch (error) {
|
|
3625
3850
|
logger$10.error(`[WebRTCManager] Error sending Verto ${vertoMethod}:`, error);
|
|
3626
|
-
|
|
3851
|
+
this.onError?.(error instanceof Error ? error : new Error(String(error), { cause: error }));
|
|
3627
3852
|
}
|
|
3628
3853
|
}
|
|
3629
3854
|
async processModifyResponse(response, rtcPeerConnController) {
|
|
@@ -3637,12 +3862,14 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
3637
3862
|
});
|
|
3638
3863
|
} catch (error) {
|
|
3639
3864
|
logger$10.warn("[WebRTCManager] Error processing modify response:", error);
|
|
3640
|
-
|
|
3865
|
+
const modifyError = error instanceof Error ? error : new Error(String(error), { cause: error });
|
|
3866
|
+
this.onError?.(modifyError);
|
|
3641
3867
|
}
|
|
3642
3868
|
}
|
|
3643
3869
|
}
|
|
3644
3870
|
processInviteResponse(response, rtcPeerConnController) {
|
|
3645
3871
|
if (!response.error && require_operators.getValueFrom(response, "result.result.result.message") === "CALL CREATED") {
|
|
3872
|
+
this._signalingStatus$.next("trying");
|
|
3646
3873
|
this._nodeId$.next(require_operators.getValueFrom(response, "result.node_id") ?? null);
|
|
3647
3874
|
const memberId = require_operators.getValueFrom(response, "result.result.result.memberID") ?? null;
|
|
3648
3875
|
const callId = require_operators.getValueFrom(response, "result.result.result.callID") ?? null;
|
|
@@ -3654,7 +3881,6 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
3654
3881
|
this._selfId$.next(memberId);
|
|
3655
3882
|
rtcPeerConnController.setMemberId(memberId);
|
|
3656
3883
|
if (callId) this.webRtcCallSession.addCallId(callId);
|
|
3657
|
-
this._signalingStatus$.next("ringing");
|
|
3658
3884
|
this.attachManager.attach(this.webRtcCallSession);
|
|
3659
3885
|
logger$10.info("[WebRTCManager] Verto invite successful");
|
|
3660
3886
|
logger$10.debug(`[WebRTCManager] nodeid: ${this._nodeId$.value}, selfId: ${this._selfId$.value}`);
|
|
@@ -3686,6 +3912,7 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
3686
3912
|
inputVideoStream: options.inputVideoStream,
|
|
3687
3913
|
receiveAudio: options.receiveAudio,
|
|
3688
3914
|
receiveVideo: options.receiveVideo,
|
|
3915
|
+
webRTCApiProvider: this.webRTCApiProvider,
|
|
3689
3916
|
...this.RTCPeerConnectionConfig
|
|
3690
3917
|
}, options.initOffer, this.deviceController);
|
|
3691
3918
|
this.setupLocalDescriptionHandler(rtcPeerConnController);
|
|
@@ -3697,6 +3924,36 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
3697
3924
|
this.subscribeTo(rtcPeerConnController.errors$, (error) => {
|
|
3698
3925
|
this.onError?.(error);
|
|
3699
3926
|
});
|
|
3927
|
+
if (options.initOffer) this.handleInboundAnswer(rtcPeerConnController);
|
|
3928
|
+
}
|
|
3929
|
+
async handleInboundAnswer(rtcPeerConnController) {
|
|
3930
|
+
logger$10.debug("[WebRTCManager] Waiting for inbound call to be accepted or rejected");
|
|
3931
|
+
const vertoByeOrAccepted = await (0, rxjs.firstValueFrom)((0, rxjs.race)(this.vertoBye$, this.webRtcCallSession.answered$).pipe((0, rxjs.takeUntil)(this.destroyed$))).catch(() => null);
|
|
3932
|
+
if (vertoByeOrAccepted === null) {
|
|
3933
|
+
logger$10.debug("[WebRTCManager] Inbound answer handler aborted (destroyed).");
|
|
3934
|
+
return;
|
|
3935
|
+
}
|
|
3936
|
+
if (isVertoByeMessage(vertoByeOrAccepted)) {
|
|
3937
|
+
logger$10.info("[WebRTCManager] Inbound call ended by remote before answer.");
|
|
3938
|
+
this.callSession?.destroy();
|
|
3939
|
+
} else if (!vertoByeOrAccepted) {
|
|
3940
|
+
logger$10.info("[WebRTCManager] Inbound call rejected by user.");
|
|
3941
|
+
try {
|
|
3942
|
+
await this.bye("USER_BUSY");
|
|
3943
|
+
} finally {
|
|
3944
|
+
this._signalingStatus$.next("disconnected");
|
|
3945
|
+
this.callSession?.destroy();
|
|
3946
|
+
}
|
|
3947
|
+
} else {
|
|
3948
|
+
logger$10.debug("[WebRTCManager] Inbound call accepted, creating SDP answer");
|
|
3949
|
+
const answerOptions = this.webRtcCallSession.answerMediaOptions;
|
|
3950
|
+
try {
|
|
3951
|
+
await rtcPeerConnController.acceptInbound(answerOptions);
|
|
3952
|
+
} catch (error) {
|
|
3953
|
+
logger$10.error("[WebRTCManager] Error creating inbound answer:", error);
|
|
3954
|
+
this.onError?.(error instanceof Error ? error : new Error(String(error), { cause: error }));
|
|
3955
|
+
}
|
|
3956
|
+
}
|
|
3700
3957
|
}
|
|
3701
3958
|
setupVertoAttachHandler() {
|
|
3702
3959
|
this.subscribeTo(this.vertoAttach$, async (vertoAttach) => {
|
|
@@ -3714,7 +3971,7 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
3714
3971
|
});
|
|
3715
3972
|
}
|
|
3716
3973
|
initObservables(rtcPeerConnController) {
|
|
3717
|
-
this.mediaDirections$ = rtcPeerConnController.connectionState$.pipe((0, rxjs.filter)((state) => state === "connected"), (0, rxjs.
|
|
3974
|
+
this.mediaDirections$ = rtcPeerConnController.connectionState$.pipe((0, rxjs.filter)((state) => state === "connected"), (0, rxjs.map)(() => rtcPeerConnController.mediaDirections), (0, rxjs.startWith)(rtcPeerConnController.mediaDirections), (0, rxjs.takeUntil)(this.destroyed$));
|
|
3718
3975
|
this.localStream$ = rtcPeerConnController.localStream$.pipe(require_operators.filterNull(), (0, rxjs.takeUntil)(this.destroyed$));
|
|
3719
3976
|
this.remoteStream$ = rtcPeerConnController.remoteStream$.pipe(require_operators.filterNull(), (0, rxjs.takeUntil)(this.destroyed$));
|
|
3720
3977
|
}
|
|
@@ -3730,7 +3987,6 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
3730
3987
|
});
|
|
3731
3988
|
this.sendLocalDescriptionOnceAccepted(vertoMessageRequest, rtcPeerConnController);
|
|
3732
3989
|
} else if (initial) {
|
|
3733
|
-
this._signalingStatus$.next("trying");
|
|
3734
3990
|
const vertoMessageRequest = VertoInvite({
|
|
3735
3991
|
dialogParams,
|
|
3736
3992
|
sdp
|
|
@@ -3748,22 +4004,23 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
3748
4004
|
}
|
|
3749
4005
|
setupVertoByeHandler() {
|
|
3750
4006
|
this.subscribeTo(this.vertoBye$, () => {
|
|
4007
|
+
this._signalingStatus$.next("disconnected");
|
|
3751
4008
|
this.attachManager.detach(this.webRtcCallSession);
|
|
3752
4009
|
this.callSession?.destroy();
|
|
3753
4010
|
});
|
|
3754
4011
|
}
|
|
3755
|
-
getSendLocalSDPOptionalParams(rtcPeerConnController) {
|
|
4012
|
+
getSendLocalSDPOptionalParams(rtcPeerConnController, vertoMethod) {
|
|
3756
4013
|
let subscribe = void 0;
|
|
3757
|
-
|
|
3758
|
-
if (initial) {
|
|
4014
|
+
if (!rtcPeerConnController.firstSDPExchangeCompleted) {
|
|
3759
4015
|
subscribe = [];
|
|
3760
4016
|
if (rtcPeerConnController.isMainDevice) subscribe.push(...PreferencesContainer.instance.inviteSubscribeMainDevice);
|
|
3761
4017
|
else if (rtcPeerConnController.isAdditionalDevice) subscribe.push(...PreferencesContainer.instance.inviteSubscribeAdditionalDevice);
|
|
3762
4018
|
else if (rtcPeerConnController.isScreenShare) subscribe.push(...PreferencesContainer.instance.inviteSubscribeScreenshare);
|
|
3763
4019
|
}
|
|
4020
|
+
const isInvite = vertoMethod === "verto.invite";
|
|
3764
4021
|
return {
|
|
3765
4022
|
callID: rtcPeerConnController.id,
|
|
3766
|
-
node_id:
|
|
4023
|
+
node_id: isInvite ? "" : this._nodeId$.value ?? "",
|
|
3767
4024
|
subscribe
|
|
3768
4025
|
};
|
|
3769
4026
|
}
|
|
@@ -3775,7 +4032,12 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
3775
4032
|
this.callSession?.destroy();
|
|
3776
4033
|
} else if (!vertoByeOrAccepted) {
|
|
3777
4034
|
logger$10.info("[WebRTCManager] Call was not accepted, sending verto.bye.");
|
|
3778
|
-
|
|
4035
|
+
try {
|
|
4036
|
+
await this.bye("USER_BUSY");
|
|
4037
|
+
} finally {
|
|
4038
|
+
this._signalingStatus$.next("disconnected");
|
|
4039
|
+
this.callSession?.destroy();
|
|
4040
|
+
}
|
|
3779
4041
|
} else {
|
|
3780
4042
|
logger$10.debug("[WebRTCManager] Call accepted, sending answer");
|
|
3781
4043
|
try {
|
|
@@ -3805,8 +4067,7 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
3805
4067
|
userVariables: {
|
|
3806
4068
|
memberCallId: this.webRtcCallSession.id,
|
|
3807
4069
|
memberId,
|
|
3808
|
-
...this.webRtcCallSession.
|
|
3809
|
-
...PreferencesContainer.instance.userVariables
|
|
4070
|
+
...this.webRtcCallSession.userVariables
|
|
3810
4071
|
},
|
|
3811
4072
|
screenShare: rtcPeerConnectionController.isScreenShare,
|
|
3812
4073
|
additionalDevice: rtcPeerConnectionController.isAdditionalDevice,
|
|
@@ -3864,7 +4125,8 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
3864
4125
|
rtcPeerConnController = new RTCPeerConnectionController({
|
|
3865
4126
|
...options,
|
|
3866
4127
|
...this.RTCPeerConnectionConfig,
|
|
3867
|
-
propose
|
|
4128
|
+
propose,
|
|
4129
|
+
webRTCApiProvider: this.webRTCApiProvider
|
|
3868
4130
|
}, void 0, this.deviceController);
|
|
3869
4131
|
this.setupLocalDescriptionHandler(rtcPeerConnController);
|
|
3870
4132
|
if (propose === "screenshare") this._screenShareId = rtcPeerConnController.id;
|
|
@@ -3921,7 +4183,7 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
3921
4183
|
try {
|
|
3922
4184
|
const causeParams = cause ? {
|
|
3923
4185
|
cause,
|
|
3924
|
-
|
|
4186
|
+
causeCode: VertoByeCauseCodes[cause]
|
|
3925
4187
|
} : {};
|
|
3926
4188
|
await this.executeVerto(VertoBye({
|
|
3927
4189
|
...causeParams,
|
|
@@ -4003,6 +4265,20 @@ var ParticipantFactory = class {
|
|
|
4003
4265
|
//#endregion
|
|
4004
4266
|
//#region src/core/entities/Call.ts
|
|
4005
4267
|
const logger$9 = require_operators.getLogger();
|
|
4268
|
+
const fromDestinationParams = (destination) => {
|
|
4269
|
+
if (!destination) return {};
|
|
4270
|
+
try {
|
|
4271
|
+
const url = new URL(`destination:${destination}`);
|
|
4272
|
+
const params = {};
|
|
4273
|
+
url.searchParams.forEach((value, key) => {
|
|
4274
|
+
params[key] = value;
|
|
4275
|
+
});
|
|
4276
|
+
return params;
|
|
4277
|
+
} catch (error) {
|
|
4278
|
+
logger$9.warn(`Failed to parse destination URI: ${destination}`, error);
|
|
4279
|
+
return {};
|
|
4280
|
+
}
|
|
4281
|
+
};
|
|
4006
4282
|
/**
|
|
4007
4283
|
* Concrete WebRTC call implementation.
|
|
4008
4284
|
*
|
|
@@ -4016,27 +4292,50 @@ var WebRTCCall = class extends Destroyable {
|
|
|
4016
4292
|
this.clientSession = clientSession;
|
|
4017
4293
|
this.options = options;
|
|
4018
4294
|
this.address = address;
|
|
4019
|
-
this.
|
|
4020
|
-
this.
|
|
4295
|
+
this._errors$ = this.createReplaySubject(1);
|
|
4296
|
+
this._lastMergedStatus = "new";
|
|
4021
4297
|
this._answered$ = this.createReplaySubject();
|
|
4022
4298
|
this._holdState = false;
|
|
4299
|
+
this._userVariables$ = this.createBehaviorSubject({ ...PreferencesContainer.instance.userVariables });
|
|
4023
4300
|
this.id = options.callId ?? (0, uuid.v4)();
|
|
4024
4301
|
this.to = options.to;
|
|
4302
|
+
this._userVariables$.next({
|
|
4303
|
+
...this._userVariables$.value,
|
|
4304
|
+
...fromDestinationParams(options.to),
|
|
4305
|
+
...options.userVariables
|
|
4306
|
+
});
|
|
4307
|
+
this.subscribeTo(this.webrtcMessages$, (message) => {
|
|
4308
|
+
const userVars = require_operators.getValueFrom(message, "params.userVariables");
|
|
4309
|
+
if (userVars) this._userVariables$.next({
|
|
4310
|
+
...this._userVariables$.value,
|
|
4311
|
+
...userVars
|
|
4312
|
+
});
|
|
4313
|
+
});
|
|
4025
4314
|
const managers = initialization.initializeManagers(this);
|
|
4026
4315
|
this.vertoManager = managers.vertoManager;
|
|
4027
4316
|
this.callEventsManager = managers.callEventsManager;
|
|
4028
|
-
if (options.initOffer)
|
|
4029
|
-
|
|
4317
|
+
if (options.initOffer) {
|
|
4318
|
+
this._status$ = this.createBehaviorSubject("ringing");
|
|
4319
|
+
this._lastMergedStatus = "ringing";
|
|
4320
|
+
} else this._status$ = this.createBehaviorSubject("new");
|
|
4030
4321
|
const { deviceController } = initialization;
|
|
4031
4322
|
this.participantFactory = new ParticipantFactory(this.executeMethod.bind(this), this.vertoManager, deviceController);
|
|
4032
4323
|
}
|
|
4033
4324
|
/** Observable stream of errors from media, signaling, and peer connection layers. */
|
|
4034
4325
|
get errors$() {
|
|
4035
|
-
return this._errors$.asObservable();
|
|
4326
|
+
return this.deferEmission(this._errors$.asObservable());
|
|
4036
4327
|
}
|
|
4037
|
-
/**
|
|
4038
|
-
|
|
4039
|
-
|
|
4328
|
+
/**
|
|
4329
|
+
* @internal Push an error to the call's error stream.
|
|
4330
|
+
* Fatal errors automatically transition the call to `'failed'` and destroy it.
|
|
4331
|
+
*/
|
|
4332
|
+
emitError(callError) {
|
|
4333
|
+
if (this._status$.value === "destroyed" || this._status$.value === "failed") return;
|
|
4334
|
+
this._errors$.next(callError);
|
|
4335
|
+
if (callError.fatal) {
|
|
4336
|
+
this._status$.next("failed");
|
|
4337
|
+
this.destroy();
|
|
4338
|
+
}
|
|
4040
4339
|
}
|
|
4041
4340
|
/** Whether this call is `'inbound'` or `'outbound'`. */
|
|
4042
4341
|
get direction() {
|
|
@@ -4044,7 +4343,7 @@ var WebRTCCall = class extends Destroyable {
|
|
|
4044
4343
|
}
|
|
4045
4344
|
/** Observable of the address associated with this call. */
|
|
4046
4345
|
get address$() {
|
|
4047
|
-
return (0, rxjs.from)([this.address]);
|
|
4346
|
+
return this.deferEmission((0, rxjs.from)([this.address])).pipe((0, rxjs.takeUntil)(this._destroyed$));
|
|
4048
4347
|
}
|
|
4049
4348
|
/** Display name of the caller. */
|
|
4050
4349
|
get fromName() {
|
|
@@ -4076,7 +4375,7 @@ var WebRTCCall = class extends Destroyable {
|
|
|
4076
4375
|
}
|
|
4077
4376
|
/** Current snapshot of all participants in the call. */
|
|
4078
4377
|
get participants() {
|
|
4079
|
-
return
|
|
4378
|
+
return this.callEventsManager.participants;
|
|
4080
4379
|
}
|
|
4081
4380
|
/** The local participant, or `null` if not yet joined. */
|
|
4082
4381
|
get self() {
|
|
@@ -4085,7 +4384,6 @@ var WebRTCCall = class extends Destroyable {
|
|
|
4085
4384
|
async toggleLock() {
|
|
4086
4385
|
const method = this.locked ? "call.unlock" : "call.lock";
|
|
4087
4386
|
await this.executeMethod(this.selfId ?? "", method, {});
|
|
4088
|
-
throw new require_operators.UnimplementedError();
|
|
4089
4387
|
}
|
|
4090
4388
|
async toggleHold() {
|
|
4091
4389
|
if (this._holdState) await this.vertoManager.unhold();
|
|
@@ -4106,7 +4404,7 @@ var WebRTCCall = class extends Destroyable {
|
|
|
4106
4404
|
}
|
|
4107
4405
|
/** Observable of layout layer positions for all participants. */
|
|
4108
4406
|
get layoutLayers$() {
|
|
4109
|
-
return this.callEventsManager.layoutLayers
|
|
4407
|
+
return this.deferEmission(this.callEventsManager.layoutLayers$).pipe((0, rxjs.takeUntil)(this._destroyed$));
|
|
4110
4408
|
}
|
|
4111
4409
|
/** Current snapshot of layout layers. */
|
|
4112
4410
|
get layoutLayers() {
|
|
@@ -4120,72 +4418,80 @@ var WebRTCCall = class extends Destroyable {
|
|
|
4120
4418
|
params
|
|
4121
4419
|
});
|
|
4122
4420
|
try {
|
|
4123
|
-
|
|
4421
|
+
const response = await this.clientSession.execute(request);
|
|
4422
|
+
if (isJSONRPCErrorResponse(response)) throw new require_operators.JSONRPCError(parseInt(response.result?.code ?? "0"), `Error response from method ${method}: ${response.result?.code} ${response.result?.message}`, void 0, void 0, request.id);
|
|
4423
|
+
return response;
|
|
4124
4424
|
} catch (error) {
|
|
4125
4425
|
logger$9.error(`[Call] Error executing method ${method} with params`, params, error);
|
|
4126
4426
|
throw error;
|
|
4127
4427
|
}
|
|
4128
4428
|
}
|
|
4129
4429
|
buildMethodParams(target, args) {
|
|
4130
|
-
const
|
|
4131
|
-
node_id: this.nodeId,
|
|
4132
|
-
call_id: this.id
|
|
4430
|
+
const self = {
|
|
4431
|
+
node_id: this.nodeId ?? "",
|
|
4432
|
+
call_id: this.id,
|
|
4433
|
+
member_id: this.vertoManager.selfId ?? ""
|
|
4434
|
+
};
|
|
4435
|
+
if (typeof target === "object") return {
|
|
4436
|
+
...args,
|
|
4437
|
+
self,
|
|
4438
|
+
targets: [target]
|
|
4133
4439
|
};
|
|
4134
4440
|
return {
|
|
4135
4441
|
...args,
|
|
4136
|
-
self
|
|
4137
|
-
...reference,
|
|
4138
|
-
member_id: this.vertoManager.selfId
|
|
4139
|
-
},
|
|
4442
|
+
self,
|
|
4140
4443
|
target: {
|
|
4141
|
-
|
|
4444
|
+
node_id: this.nodeId ?? "",
|
|
4445
|
+
call_id: this.id,
|
|
4142
4446
|
member_id: target
|
|
4143
4447
|
}
|
|
4144
4448
|
};
|
|
4145
4449
|
}
|
|
4146
4450
|
/** Observable of the current call status (e.g. `'ringing'`, `'connected'`). */
|
|
4147
4451
|
get status$() {
|
|
4148
|
-
return (0, rxjs.merge)(this._status$.asObservable(), this.vertoManager.signalingStatus$)
|
|
4452
|
+
return this.publicCachedObservable("status$", () => (0, rxjs.merge)(this._status$.asObservable(), this.vertoManager.signalingStatus$).pipe((0, rxjs.distinctUntilChanged)(), (0, rxjs.tap)((status) => {
|
|
4453
|
+
this._lastMergedStatus = status;
|
|
4454
|
+
})));
|
|
4149
4455
|
}
|
|
4150
4456
|
/** Observable of the participants list, emits on join/leave/update. */
|
|
4151
4457
|
get participants$() {
|
|
4152
|
-
return this.callEventsManager.participants
|
|
4458
|
+
return this.deferEmission(this.callEventsManager.participants$).pipe((0, rxjs.takeUntil)(this._destroyed$));
|
|
4153
4459
|
}
|
|
4154
4460
|
/** Observable of the local (self) participant. */
|
|
4155
4461
|
get self$() {
|
|
4156
|
-
return this.callEventsManager.self
|
|
4462
|
+
return this.deferEmission(this.callEventsManager.self$).pipe((0, rxjs.takeUntil)(this._destroyed$));
|
|
4157
4463
|
}
|
|
4158
4464
|
/** Observable indicating whether the call is being recorded. */
|
|
4159
4465
|
get recording$() {
|
|
4160
|
-
return this.callEventsManager.recording
|
|
4466
|
+
return this.deferEmission(this.callEventsManager.recording$).pipe((0, rxjs.takeUntil)(this._destroyed$));
|
|
4161
4467
|
}
|
|
4162
4468
|
/** Observable indicating whether the call is being streamed. */
|
|
4163
4469
|
get streaming$() {
|
|
4164
|
-
return this.callEventsManager.streaming
|
|
4470
|
+
return this.deferEmission(this.callEventsManager.streaming$).pipe((0, rxjs.takeUntil)(this._destroyed$));
|
|
4165
4471
|
}
|
|
4166
4472
|
/** Observable indicating whether raise-hand priority is active. */
|
|
4167
4473
|
get raiseHandPriority$() {
|
|
4168
|
-
return this.callEventsManager.raiseHandPriority
|
|
4474
|
+
return this.deferEmission(this.callEventsManager.raiseHandPriority$).pipe((0, rxjs.takeUntil)(this._destroyed$));
|
|
4169
4475
|
}
|
|
4170
4476
|
/** Observable indicating whether the call room is locked. */
|
|
4171
4477
|
get locked$() {
|
|
4172
|
-
return this.callEventsManager.locked
|
|
4478
|
+
return this.deferEmission(this.callEventsManager.locked$).pipe((0, rxjs.takeUntil)(this._destroyed$));
|
|
4173
4479
|
}
|
|
4174
4480
|
/** Observable of custom metadata associated with the call. */
|
|
4175
4481
|
get meta$() {
|
|
4176
|
-
return this.callEventsManager.meta
|
|
4482
|
+
return this.deferEmission(this.callEventsManager.meta$).pipe((0, rxjs.takeUntil)(this._destroyed$));
|
|
4177
4483
|
}
|
|
4178
4484
|
/** Observable of the call's capability flags. */
|
|
4179
4485
|
get capabilities$() {
|
|
4180
|
-
return this.callEventsManager.capabilities
|
|
4486
|
+
return this.deferEmission(this.callEventsManager.capabilities$).pipe((0, rxjs.takeUntil)(this._destroyed$));
|
|
4181
4487
|
}
|
|
4182
4488
|
/** Observable of the current layout name. */
|
|
4183
4489
|
get layout$() {
|
|
4184
|
-
return this.callEventsManager.layout
|
|
4490
|
+
return this.deferEmission(this.callEventsManager.layout$).pipe((0, rxjs.takeUntil)(this._destroyed$));
|
|
4185
4491
|
}
|
|
4186
4492
|
/** Current call status. */
|
|
4187
4493
|
get status() {
|
|
4188
|
-
return this.
|
|
4494
|
+
return this._lastMergedStatus;
|
|
4189
4495
|
}
|
|
4190
4496
|
/** Whether the call is currently being recorded. */
|
|
4191
4497
|
get recording() {
|
|
@@ -4213,7 +4519,7 @@ var WebRTCCall = class extends Destroyable {
|
|
|
4213
4519
|
}
|
|
4214
4520
|
/** Observable of available layout names. */
|
|
4215
4521
|
get layouts$() {
|
|
4216
|
-
return this.callEventsManager.layouts
|
|
4522
|
+
return this.deferEmission(this.callEventsManager.layouts$).pipe((0, rxjs.takeUntil)(this._destroyed$));
|
|
4217
4523
|
}
|
|
4218
4524
|
/** Current snapshot of available layout names. */
|
|
4219
4525
|
get layouts() {
|
|
@@ -4221,7 +4527,7 @@ var WebRTCCall = class extends Destroyable {
|
|
|
4221
4527
|
}
|
|
4222
4528
|
/** Observable of the local media stream (camera/microphone). */
|
|
4223
4529
|
get localStream$() {
|
|
4224
|
-
return this.vertoManager.localStream
|
|
4530
|
+
return this.deferEmission(this.vertoManager.localStream$).pipe((0, rxjs.takeUntil)(this._destroyed$));
|
|
4225
4531
|
}
|
|
4226
4532
|
/** Current local media stream, or `null` if not available. */
|
|
4227
4533
|
get localStream() {
|
|
@@ -4229,12 +4535,27 @@ var WebRTCCall = class extends Destroyable {
|
|
|
4229
4535
|
}
|
|
4230
4536
|
/** Observable of the remote media stream from the far end. */
|
|
4231
4537
|
get remoteStream$() {
|
|
4232
|
-
return this.vertoManager.remoteStream
|
|
4538
|
+
return this.deferEmission(this.vertoManager.remoteStream$).pipe((0, rxjs.takeUntil)(this._destroyed$));
|
|
4233
4539
|
}
|
|
4234
4540
|
/** Current remote media stream, or `null` if not available. */
|
|
4235
4541
|
get remoteStream() {
|
|
4236
4542
|
return this.vertoManager.remoteStream;
|
|
4237
4543
|
}
|
|
4544
|
+
/** Observable of custom user variables associated with the call. */
|
|
4545
|
+
get userVariables$() {
|
|
4546
|
+
return this.deferEmission(this._userVariables$.asObservable());
|
|
4547
|
+
}
|
|
4548
|
+
/** a copy of the current custom user variables of the call. */
|
|
4549
|
+
get userVariables() {
|
|
4550
|
+
return { ...this._userVariables$.value };
|
|
4551
|
+
}
|
|
4552
|
+
/** Merge current custom user variables of the call. */
|
|
4553
|
+
set userVariables(variables) {
|
|
4554
|
+
this._userVariables$.next({
|
|
4555
|
+
...this._userVariables$.value,
|
|
4556
|
+
...variables
|
|
4557
|
+
});
|
|
4558
|
+
}
|
|
4238
4559
|
/** @internal */
|
|
4239
4560
|
createParticipant(memberId, selfId) {
|
|
4240
4561
|
if (memberId === (selfId ?? this.vertoManager.selfId)) return this.participantFactory.createSelfParticipant(memberId);
|
|
@@ -4242,14 +4563,14 @@ var WebRTCCall = class extends Destroyable {
|
|
|
4242
4563
|
}
|
|
4243
4564
|
/** Observable of the current audio/video send/receive directions. */
|
|
4244
4565
|
get mediaDirections$() {
|
|
4245
|
-
return this.vertoManager.mediaDirections
|
|
4566
|
+
return this.deferEmission(this.vertoManager.mediaDirections$).pipe((0, rxjs.takeUntil)(this._destroyed$));
|
|
4246
4567
|
}
|
|
4247
4568
|
/** Current audio/video send/receive directions. */
|
|
4248
4569
|
get mediaDirections() {
|
|
4249
4570
|
return this.vertoManager.mediaDirections;
|
|
4250
4571
|
}
|
|
4251
4572
|
get participantsId$() {
|
|
4252
|
-
return this.participants$.pipe((0, rxjs.map)((participants) => participants.map((participant) => participant.id)));
|
|
4573
|
+
return this.cachedObservable("participantsId$", () => this.participants$.pipe((0, rxjs.map)((participants) => participants.map((participant) => participant.id))));
|
|
4253
4574
|
}
|
|
4254
4575
|
/** Executes a raw JSON-RPC request on the client session. */
|
|
4255
4576
|
async execute(request, options) {
|
|
@@ -4284,35 +4605,35 @@ var WebRTCCall = class extends Destroyable {
|
|
|
4284
4605
|
}
|
|
4285
4606
|
}
|
|
4286
4607
|
get callSessionEvents$() {
|
|
4287
|
-
return this.clientSession.signalingEvent$.pipe((0, rxjs.filter)((event) => this.isCallSessionEvent(event)), (0, rxjs.tap)((event) => logger$9.debug("[Call] Received call session event:", event)), (0, rxjs.takeUntil)(this.destroyed$));
|
|
4608
|
+
return this.cachedObservable("callSessionEvents$", () => this.clientSession.signalingEvent$.pipe((0, rxjs.filter)((event) => this.isCallSessionEvent(event)), (0, rxjs.tap)((event) => logger$9.debug("[Call] Received call session event:", event)), (0, rxjs.takeUntil)(this.destroyed$), (0, rxjs.share)()));
|
|
4288
4609
|
}
|
|
4289
4610
|
/** Observable of call-updated events. */
|
|
4290
4611
|
get callUpdated$() {
|
|
4291
|
-
return this.callSessionEvents$.pipe(require_operators.filterAs(isCallUpdatedMetadata, "params"), (0, rxjs.takeUntil)(this.destroyed$));
|
|
4612
|
+
return this.publicCachedObservable("callUpdated$", () => this.callSessionEvents$.pipe(require_operators.filterAs(isCallUpdatedMetadata, "params"), (0, rxjs.takeUntil)(this.destroyed$)));
|
|
4292
4613
|
}
|
|
4293
4614
|
/** Observable of member-joined events. */
|
|
4294
4615
|
get memberJoined$() {
|
|
4295
|
-
return this.callSessionEvents$.pipe(require_operators.filterAs(isMemberJoinedMetadata, "params"), (0, rxjs.takeUntil)(this.destroyed$));
|
|
4616
|
+
return this.publicCachedObservable("memberJoined$", () => this.callSessionEvents$.pipe(require_operators.filterAs(isMemberJoinedMetadata, "params"), (0, rxjs.takeUntil)(this.destroyed$)));
|
|
4296
4617
|
}
|
|
4297
4618
|
/** Observable of member-left events. */
|
|
4298
4619
|
get memberLeft$() {
|
|
4299
|
-
return this.callSessionEvents$.pipe(require_operators.filterAs(isMemberLeftMetadata, "params"), (0, rxjs.takeUntil)(this.destroyed$));
|
|
4620
|
+
return this.publicCachedObservable("memberLeft$", () => this.callSessionEvents$.pipe(require_operators.filterAs(isMemberLeftMetadata, "params"), (0, rxjs.takeUntil)(this.destroyed$)));
|
|
4300
4621
|
}
|
|
4301
4622
|
/** Observable of member-updated events (mute, volume, etc.). */
|
|
4302
4623
|
get memberUpdated$() {
|
|
4303
|
-
return this.callSessionEvents$.pipe(require_operators.filterAs(isMemberUpdatedMetadata, "params"), (0, rxjs.takeUntil)(this.destroyed$));
|
|
4624
|
+
return this.publicCachedObservable("memberUpdated$", () => this.callSessionEvents$.pipe(require_operators.filterAs(isMemberUpdatedMetadata, "params"), (0, rxjs.takeUntil)(this.destroyed$)));
|
|
4304
4625
|
}
|
|
4305
4626
|
/** Observable of member-talking events (speech start/stop). */
|
|
4306
4627
|
get memberTalking$() {
|
|
4307
|
-
return this.callSessionEvents$.pipe(require_operators.filterAs(isMemberTalkingMetadata, "params"), (0, rxjs.takeUntil)(this.destroyed$));
|
|
4628
|
+
return this.publicCachedObservable("memberTalking$", () => this.callSessionEvents$.pipe(require_operators.filterAs(isMemberTalkingMetadata, "params"), (0, rxjs.takeUntil)(this.destroyed$)));
|
|
4308
4629
|
}
|
|
4309
4630
|
/** Observable of call state-change events. */
|
|
4310
4631
|
get callStates$() {
|
|
4311
|
-
return this.callSessionEvents$.pipe(require_operators.filterAs(isCallStateMetadata, "params"), (0, rxjs.takeUntil)(this.destroyed$));
|
|
4632
|
+
return this.publicCachedObservable("callStates$", () => this.callSessionEvents$.pipe(require_operators.filterAs(isCallStateMetadata, "params"), (0, rxjs.takeUntil)(this.destroyed$)));
|
|
4312
4633
|
}
|
|
4313
4634
|
/** Observable of layout-changed events. */
|
|
4314
4635
|
get layoutUpdates$() {
|
|
4315
|
-
return this.callSessionEvents$.pipe(require_operators.filterAs(isLayoutChangedMetadata, "params"), (0, rxjs.takeUntil)(this.destroyed$));
|
|
4636
|
+
return this.publicCachedObservable("layoutUpdates$", () => this.callSessionEvents$.pipe(require_operators.filterAs(isLayoutChangedMetadata, "params"), (0, rxjs.takeUntil)(this.destroyed$)));
|
|
4316
4637
|
}
|
|
4317
4638
|
/** Underlying `RTCPeerConnection`, for advanced use cases. */
|
|
4318
4639
|
get rtcPeerConnection() {
|
|
@@ -4320,19 +4641,19 @@ var WebRTCCall = class extends Destroyable {
|
|
|
4320
4641
|
}
|
|
4321
4642
|
/** Observable of raw signaling events as plain objects. */
|
|
4322
4643
|
get signalingEvent$() {
|
|
4323
|
-
return this.callEvent$.pipe((0, rxjs.map)((event) => JSON.parse(JSON.stringify(event))));
|
|
4644
|
+
return this.publicCachedObservable("signalingEvent$", () => this.callEvent$.pipe((0, rxjs.map)((event) => JSON.parse(JSON.stringify(event)))));
|
|
4324
4645
|
}
|
|
4325
4646
|
/** Observable of WebRTC-specific signaling messages. */
|
|
4326
4647
|
get webrtcMessages$() {
|
|
4327
|
-
return this.callSessionEvents$.pipe(require_operators.filterAs(isWebrtcMessageMetadata, "params"), (0, rxjs.tap)((event) => logger$9.debug("[Call] Event is a WebRTC message event:", event)), (0, rxjs.takeUntil)(this.destroyed$));
|
|
4648
|
+
return this.cachedObservable("webrtcMessages$", () => this.callSessionEvents$.pipe(require_operators.filterAs(isWebrtcMessageMetadata, "params"), (0, rxjs.tap)((event) => logger$9.debug("[Call] Event is a WebRTC message event:", event)), (0, rxjs.takeUntil)(this.destroyed$), (0, rxjs.share)()));
|
|
4328
4649
|
}
|
|
4329
4650
|
/** Observable of call-level signaling events. */
|
|
4330
4651
|
get callEvent$() {
|
|
4331
|
-
return this.callSessionEvents$.pipe(require_operators.filterAs(isSignalwireCallMetadata, "params"), (0, rxjs.tap)((event) => logger$9.debug("[Call] Event is a call event:", event)), (0, rxjs.takeUntil)(this.destroyed$));
|
|
4652
|
+
return this.cachedObservable("callEvent$", () => this.callSessionEvents$.pipe(require_operators.filterAs(isSignalwireCallMetadata, "params"), (0, rxjs.tap)((event) => logger$9.debug("[Call] Event is a call event:", event)), (0, rxjs.takeUntil)(this.destroyed$), (0, rxjs.share)()));
|
|
4332
4653
|
}
|
|
4333
4654
|
/** Observable of layout-changed signaling events. */
|
|
4334
4655
|
get layoutEvent$() {
|
|
4335
|
-
return this.callEvent$.pipe(require_operators.filterAs(isLayoutChangedMetadata, "params"));
|
|
4656
|
+
return this.cachedObservable("layoutEvent$", () => this.callEvent$.pipe(require_operators.filterAs(isLayoutChangedMetadata, "params")));
|
|
4336
4657
|
}
|
|
4337
4658
|
/** Hangs up the call and releases all resources. */
|
|
4338
4659
|
async hangup() {
|
|
@@ -4340,7 +4661,6 @@ var WebRTCCall = class extends Destroyable {
|
|
|
4340
4661
|
try {
|
|
4341
4662
|
await this.vertoManager.bye();
|
|
4342
4663
|
} finally {
|
|
4343
|
-
this._status$.next("destroyed");
|
|
4344
4664
|
this.destroy();
|
|
4345
4665
|
}
|
|
4346
4666
|
}
|
|
@@ -4348,17 +4668,22 @@ var WebRTCCall = class extends Destroyable {
|
|
|
4348
4668
|
async sendDigits(dtmf) {
|
|
4349
4669
|
return this.vertoManager.sendDigits(dtmf);
|
|
4350
4670
|
}
|
|
4351
|
-
/** Accepts an inbound call. */
|
|
4352
|
-
answer() {
|
|
4671
|
+
/** Accepts an inbound call, optionally overriding media options for the answer. */
|
|
4672
|
+
answer(options) {
|
|
4673
|
+
this._answerMediaOptions = options;
|
|
4353
4674
|
this._answered$.next(true);
|
|
4354
4675
|
}
|
|
4676
|
+
/** Media options provided when answering. Used internally by the VertoManager. */
|
|
4677
|
+
get answerMediaOptions() {
|
|
4678
|
+
return this._answerMediaOptions;
|
|
4679
|
+
}
|
|
4355
4680
|
/** Rejects an inbound call. */
|
|
4356
4681
|
reject() {
|
|
4357
4682
|
this._answered$.next(false);
|
|
4358
4683
|
}
|
|
4359
4684
|
/** Observable that emits `true` when answered, `false` when rejected. */
|
|
4360
4685
|
get answered$() {
|
|
4361
|
-
return this._answered$.asObservable();
|
|
4686
|
+
return this.deferEmission(this._answered$.asObservable());
|
|
4362
4687
|
}
|
|
4363
4688
|
/**
|
|
4364
4689
|
* Sets the call layout and participant positions.
|
|
@@ -4379,9 +4704,10 @@ var WebRTCCall = class extends Destroyable {
|
|
|
4379
4704
|
}
|
|
4380
4705
|
/** Destroys the call, releasing all resources and subscriptions. */
|
|
4381
4706
|
destroy() {
|
|
4707
|
+
if (this._status$.value === "destroyed") return;
|
|
4708
|
+
this._status$.next("destroyed");
|
|
4382
4709
|
this.vertoManager.destroy();
|
|
4383
4710
|
this.callEventsManager.destroy();
|
|
4384
|
-
this.participantsMap.clear();
|
|
4385
4711
|
super.destroy();
|
|
4386
4712
|
}
|
|
4387
4713
|
};
|
|
@@ -4389,14 +4715,32 @@ var WebRTCCall = class extends Destroyable {
|
|
|
4389
4715
|
//#endregion
|
|
4390
4716
|
//#region src/managers/CallFactory.ts
|
|
4391
4717
|
/**
|
|
4718
|
+
* Infers the semantic error category from a raw Error thrown by VertoManager
|
|
4719
|
+
* or an RTCPeerConnection layer.
|
|
4720
|
+
*/
|
|
4721
|
+
function inferCallErrorKind(error) {
|
|
4722
|
+
if (error instanceof require_operators.RPCTimeoutError) return "timeout";
|
|
4723
|
+
if (error instanceof require_operators.JSONRPCError) return "signaling";
|
|
4724
|
+
if (error instanceof require_operators.MediaTrackError) return "media";
|
|
4725
|
+
if (error instanceof require_operators.WebSocketConnectionError || error instanceof require_operators.TransportConnectionError) return "network";
|
|
4726
|
+
return "internal";
|
|
4727
|
+
}
|
|
4728
|
+
/** Determines whether an error should be fatal (destroy the call). */
|
|
4729
|
+
function isFatalError(error) {
|
|
4730
|
+
if (error instanceof require_operators.VertoPongError) return false;
|
|
4731
|
+
if (error instanceof require_operators.MediaTrackError) return false;
|
|
4732
|
+
return true;
|
|
4733
|
+
}
|
|
4734
|
+
/**
|
|
4392
4735
|
* Factory for creating WebRTCCall instances with proper manager wiring.
|
|
4393
4736
|
* Eliminates circular dependencies by centralizing Call and Manager creation.
|
|
4394
4737
|
*/
|
|
4395
4738
|
var CallFactory = class {
|
|
4396
|
-
constructor(sessionManager, deviceController, attachManager) {
|
|
4739
|
+
constructor(sessionManager, deviceController, attachManager, webRTCApiProvider) {
|
|
4397
4740
|
this.sessionManager = sessionManager;
|
|
4398
4741
|
this.deviceController = deviceController;
|
|
4399
4742
|
this.attachManager = attachManager;
|
|
4743
|
+
this.webRTCApiProvider = webRTCApiProvider;
|
|
4400
4744
|
}
|
|
4401
4745
|
/**
|
|
4402
4746
|
* Create a new WebRTCCall with properly initialized managers
|
|
@@ -4405,10 +4749,16 @@ var CallFactory = class {
|
|
|
4405
4749
|
return new WebRTCCall(this.sessionManager, options, {
|
|
4406
4750
|
initializeManagers: (callInstance) => {
|
|
4407
4751
|
return {
|
|
4408
|
-
vertoManager: new WebRTCVertoManager(callInstance, this.attachManager, this.deviceController, {
|
|
4752
|
+
vertoManager: new WebRTCVertoManager(callInstance, this.attachManager, this.deviceController, this.webRTCApiProvider, {
|
|
4409
4753
|
nodeId: options.nodeId,
|
|
4410
4754
|
onError: (error) => {
|
|
4411
|
-
|
|
4755
|
+
const callError = {
|
|
4756
|
+
kind: inferCallErrorKind(error),
|
|
4757
|
+
fatal: isFatalError(error),
|
|
4758
|
+
error,
|
|
4759
|
+
callId: callInstance.id
|
|
4760
|
+
};
|
|
4761
|
+
callInstance.emitError(callError);
|
|
4412
4762
|
}
|
|
4413
4763
|
}),
|
|
4414
4764
|
callEventsManager: new CallEventsManager(callInstance)
|
|
@@ -4431,7 +4781,10 @@ var Fetcher = class {
|
|
|
4431
4781
|
this.nextUrl = `${this.endpoint}?${params}`;
|
|
4432
4782
|
}
|
|
4433
4783
|
async next() {
|
|
4434
|
-
if (!this.nextUrl)
|
|
4784
|
+
if (!this.nextUrl) {
|
|
4785
|
+
this.hasMore = false;
|
|
4786
|
+
return [];
|
|
4787
|
+
}
|
|
4435
4788
|
const response = await this.http.request({
|
|
4436
4789
|
...GET_PARAMS,
|
|
4437
4790
|
url: this.nextUrl
|
|
@@ -4439,6 +4792,7 @@ var Fetcher = class {
|
|
|
4439
4792
|
if (response.ok && !!response.body) {
|
|
4440
4793
|
const result = JSON.parse(response.body);
|
|
4441
4794
|
this.nextUrl = result.links.next;
|
|
4795
|
+
this.hasMore = !!this.nextUrl;
|
|
4442
4796
|
return result.data.filter(this.filter).map(this.mapper);
|
|
4443
4797
|
}
|
|
4444
4798
|
logger$8.error("Failed to fetch entity");
|
|
@@ -4472,10 +4826,11 @@ var EntityCollection = class extends Destroyable {
|
|
|
4472
4826
|
this.observablesRegistry.get(data.id)?.next(updated);
|
|
4473
4827
|
this.values$.next(Array.from(this.collectionData.values()));
|
|
4474
4828
|
};
|
|
4829
|
+
this._hasMore$ = this.createBehaviorSubject(true);
|
|
4475
4830
|
this._destroy$ = new rxjs.Subject();
|
|
4476
4831
|
this.updateSubscription = this.update$.subscribe(this.upsertData);
|
|
4477
4832
|
this.loading$.next(false);
|
|
4478
|
-
this.hasMore$ = (0, rxjs.defer)(() => (0, rxjs.from)(this.init())).pipe((0, rxjs.shareReplay)(1), (0, rxjs.takeUntil)(this._destroy$));
|
|
4833
|
+
this.hasMore$ = (0, rxjs.defer)(() => (0, rxjs.from)(this.init())).pipe((0, rxjs.switchMap)(() => this._hasMore$), (0, rxjs.distinctUntilChanged)(), (0, rxjs.shareReplay)(1), (0, rxjs.takeUntil)(this._destroy$));
|
|
4479
4834
|
}
|
|
4480
4835
|
get loading() {
|
|
4481
4836
|
return this.loading$.value;
|
|
@@ -4484,23 +4839,27 @@ var EntityCollection = class extends Destroyable {
|
|
|
4484
4839
|
return this.fetchController.hasMore ?? true;
|
|
4485
4840
|
}
|
|
4486
4841
|
get updated$() {
|
|
4487
|
-
return this.loading$.pipe((0, rxjs.distinctUntilChanged)(), (0, rxjs.skip)(1), (0, rxjs.filter)((loading) => !loading), (0, rxjs.map)(() => void 0), (0, rxjs.takeUntil)(this._destroy$));
|
|
4842
|
+
return this.cachedObservable("updated$", () => this.loading$.pipe((0, rxjs.distinctUntilChanged)(), (0, rxjs.skip)(1), (0, rxjs.filter)((loading) => !loading), (0, rxjs.map)(() => void 0), (0, rxjs.takeUntil)(this._destroy$)));
|
|
4488
4843
|
}
|
|
4489
4844
|
get values() {
|
|
4490
4845
|
return Array.from(this.collectionData.values());
|
|
4491
4846
|
}
|
|
4492
4847
|
async init() {
|
|
4493
|
-
if (this.fetchController.hasMore === false)
|
|
4848
|
+
if (this.fetchController.hasMore === false) {
|
|
4849
|
+
this._hasMore$.next(false);
|
|
4850
|
+
return;
|
|
4851
|
+
}
|
|
4494
4852
|
await this.fetchMore();
|
|
4495
|
-
return this.fetchController.hasMore ?? true;
|
|
4496
4853
|
}
|
|
4497
4854
|
async fetchMore() {
|
|
4498
4855
|
try {
|
|
4499
4856
|
this.loading$.next(true);
|
|
4500
4857
|
(await this.fetchController.next()).forEach(this.upsertData);
|
|
4858
|
+
this._hasMore$.next(this.fetchController.hasMore ?? false);
|
|
4501
4859
|
this.loading$.next(false);
|
|
4502
4860
|
} catch (error) {
|
|
4503
4861
|
logger$8.error(`Failed to fetch initial collection data`, error);
|
|
4862
|
+
this._hasMore$.next(this.fetchController.hasMore ?? false);
|
|
4504
4863
|
this.loading$.next(false);
|
|
4505
4864
|
this.onError?.(new require_operators.CollectionFetchError("fetchMore", error));
|
|
4506
4865
|
}
|
|
@@ -4564,7 +4923,7 @@ var EntityCollectionTransformed = class {
|
|
|
4564
4923
|
return this.originalCollection.values.filter(this.filter).map(this.mapper);
|
|
4565
4924
|
}
|
|
4566
4925
|
get values$() {
|
|
4567
|
-
return this.originalCollection.values$.pipe((0, rxjs.map)((values) => values.filter(this.filter).map(this.mapper)));
|
|
4926
|
+
return this._values$ ??= this.originalCollection.values$.pipe((0, rxjs.map)((values) => values.filter(this.filter).map(this.mapper)));
|
|
4568
4927
|
}
|
|
4569
4928
|
get$(id) {
|
|
4570
4929
|
const original$ = this.originalCollection.get$(id);
|
|
@@ -4637,7 +4996,7 @@ var Address = class extends Destroyable {
|
|
|
4637
4996
|
}
|
|
4638
4997
|
/** Observable of the human-readable display name. */
|
|
4639
4998
|
get displayName$() {
|
|
4640
|
-
return this._state$.pipe(require_operators.filterNull(), (0, rxjs.map)((state) => state.display_name), (0, rxjs.takeUntil)(this.destroyed$));
|
|
4999
|
+
return this.cachedObservable("displayName$", () => this._state$.pipe(require_operators.filterNull(), (0, rxjs.map)((state) => state.display_name), (0, rxjs.takeUntil)(this.destroyed$)));
|
|
4641
5000
|
}
|
|
4642
5001
|
/** Human-readable display name. */
|
|
4643
5002
|
get displayName() {
|
|
@@ -4646,7 +5005,7 @@ var Address = class extends Destroyable {
|
|
|
4646
5005
|
}
|
|
4647
5006
|
/** Observable of the preview image URL. */
|
|
4648
5007
|
get previewUrl$() {
|
|
4649
|
-
return this._state$.pipe(require_operators.filterNull(), (0, rxjs.map)((state) => state.preview_url), (0, rxjs.takeUntil)(this.destroyed$));
|
|
5008
|
+
return this.cachedObservable("previewUrl$", () => this._state$.pipe(require_operators.filterNull(), (0, rxjs.map)((state) => state.preview_url), (0, rxjs.takeUntil)(this.destroyed$)));
|
|
4650
5009
|
}
|
|
4651
5010
|
/** Preview image URL. */
|
|
4652
5011
|
get previewUrl() {
|
|
@@ -4655,7 +5014,7 @@ var Address = class extends Destroyable {
|
|
|
4655
5014
|
}
|
|
4656
5015
|
/** Observable of the cover image URL. */
|
|
4657
5016
|
get coverUrl$() {
|
|
4658
|
-
return this._state$.pipe(require_operators.filterNull(), (0, rxjs.shareReplay)(1), (0, rxjs.map)((state) => state.cover_url), (0, rxjs.takeUntil)(this.destroyed$));
|
|
5017
|
+
return this.cachedObservable("coverUrl$", () => this._state$.pipe(require_operators.filterNull(), (0, rxjs.shareReplay)(1), (0, rxjs.map)((state) => state.cover_url), (0, rxjs.takeUntil)(this.destroyed$)));
|
|
4659
5018
|
}
|
|
4660
5019
|
/** Cover image URL. */
|
|
4661
5020
|
get coverUrl() {
|
|
@@ -4664,7 +5023,7 @@ var Address = class extends Destroyable {
|
|
|
4664
5023
|
}
|
|
4665
5024
|
/** Observable of the underlying resource ID. */
|
|
4666
5025
|
get resourceId$() {
|
|
4667
|
-
return this._state$.pipe(require_operators.filterNull(), (0, rxjs.shareReplay)(1), (0, rxjs.map)((state) => state.resource_id), (0, rxjs.takeUntil)(this.destroyed$));
|
|
5026
|
+
return this.cachedObservable("resourceId$", () => this._state$.pipe(require_operators.filterNull(), (0, rxjs.shareReplay)(1), (0, rxjs.map)((state) => state.resource_id), (0, rxjs.takeUntil)(this.destroyed$)));
|
|
4668
5027
|
}
|
|
4669
5028
|
/** Underlying resource ID. */
|
|
4670
5029
|
get resourceId() {
|
|
@@ -4673,7 +5032,7 @@ var Address = class extends Destroyable {
|
|
|
4673
5032
|
}
|
|
4674
5033
|
/** Observable of the resource type (e.g. `'room'`, `'subscriber'`). */
|
|
4675
5034
|
get type$() {
|
|
4676
|
-
return this._state$.pipe(require_operators.filterNull(), (0, rxjs.shareReplay)(1), (0, rxjs.map)((state) => state.type), (0, rxjs.takeUntil)(this.destroyed$));
|
|
5035
|
+
return this.cachedObservable("type$", () => this._state$.pipe(require_operators.filterNull(), (0, rxjs.shareReplay)(1), (0, rxjs.map)((state) => state.type), (0, rxjs.takeUntil)(this.destroyed$)));
|
|
4677
5036
|
}
|
|
4678
5037
|
/** Resource type (e.g. `'room'`, `'subscriber'`). */
|
|
4679
5038
|
get type() {
|
|
@@ -4682,7 +5041,7 @@ var Address = class extends Destroyable {
|
|
|
4682
5041
|
}
|
|
4683
5042
|
/** Observable of available communication channels (audio, video, messaging). */
|
|
4684
5043
|
get channels$() {
|
|
4685
|
-
return this._state$.pipe(require_operators.filterNull(), (0, rxjs.shareReplay)(1), (0, rxjs.map)((state) => state.channels), (0, rxjs.takeUntil)(this.destroyed$));
|
|
5044
|
+
return this.cachedObservable("channels$", () => this._state$.pipe(require_operators.filterNull(), (0, rxjs.shareReplay)(1), (0, rxjs.map)((state) => state.channels), (0, rxjs.takeUntil)(this.destroyed$)));
|
|
4686
5045
|
}
|
|
4687
5046
|
/** Available communication channels. */
|
|
4688
5047
|
get channels() {
|
|
@@ -4696,7 +5055,7 @@ var Address = class extends Destroyable {
|
|
|
4696
5055
|
}
|
|
4697
5056
|
/** Observable indicating whether the address (room) is locked. */
|
|
4698
5057
|
get locked$() {
|
|
4699
|
-
return this._state$.pipe(require_operators.filterNull(), (0, rxjs.shareReplay)(1), (0, rxjs.map)((state) => state.locked), (0, rxjs.takeUntil)(this.destroyed$));
|
|
5058
|
+
return this.cachedObservable("locked$", () => this._state$.pipe(require_operators.filterNull(), (0, rxjs.shareReplay)(1), (0, rxjs.map)((state) => state.locked), (0, rxjs.takeUntil)(this.destroyed$)));
|
|
4700
5059
|
}
|
|
4701
5060
|
/** Sends a text message to this address. */
|
|
4702
5061
|
async sendText(text) {
|
|
@@ -4776,9 +5135,15 @@ var PendingRPC = class PendingRPC {
|
|
|
4776
5135
|
return () => signal.removeEventListener("abort", abortHandler);
|
|
4777
5136
|
}) : rxjs.NEVER).subscribe({
|
|
4778
5137
|
next: (response) => {
|
|
4779
|
-
logger$7.debug(`[PendingRPC(${this.id}) request:${request.id}] Resolving promise with response:`, response);
|
|
4780
5138
|
isSettled = true;
|
|
4781
|
-
|
|
5139
|
+
if (response.error) {
|
|
5140
|
+
const rpcError = new require_operators.JSONRPCError(response.error.code, response.error.message, response.error.data, void 0, request.id);
|
|
5141
|
+
logger$7.debug(`[PendingRPC(${this.id}) request:${request.id}] Rejecting promise with RPC error:`, rpcError);
|
|
5142
|
+
reject(rpcError);
|
|
5143
|
+
} else {
|
|
5144
|
+
logger$7.debug(`[PendingRPC(${this.id}) request:${request.id}] Resolving promise with response:`, response);
|
|
5145
|
+
resolve(response);
|
|
5146
|
+
}
|
|
4782
5147
|
subscription.unsubscribe();
|
|
4783
5148
|
},
|
|
4784
5149
|
error: (error) => {
|
|
@@ -4817,7 +5182,7 @@ const getAddressSearchURI = (options) => {
|
|
|
4817
5182
|
return name;
|
|
4818
5183
|
};
|
|
4819
5184
|
var ClientSessionManager = class extends Destroyable {
|
|
4820
|
-
constructor(credential, transport, storage, authorizationStateKey, deviceController, attachManager) {
|
|
5185
|
+
constructor(credential, transport, storage, authorizationStateKey, deviceController, attachManager, webRTCApiProvider) {
|
|
4821
5186
|
super();
|
|
4822
5187
|
this.credential = credential;
|
|
4823
5188
|
this.transport = transport;
|
|
@@ -4827,24 +5192,24 @@ var ClientSessionManager = class extends Destroyable {
|
|
|
4827
5192
|
this.callCreateTimeout = 6e3;
|
|
4828
5193
|
this.agent = `signalwire-typescript-sdk/1.0.0`;
|
|
4829
5194
|
this.eventAcks = true;
|
|
4830
|
-
this.authorization$ = this.createSubject();
|
|
4831
5195
|
this.authorizationState$ = this.createReplaySubject(1);
|
|
4832
5196
|
this.connectVersion = {
|
|
4833
5197
|
major: 4,
|
|
4834
5198
|
minor: 0,
|
|
4835
5199
|
revision: 0
|
|
4836
5200
|
};
|
|
4837
|
-
this.
|
|
5201
|
+
this._authorization$ = this.createBehaviorSubject(void 0);
|
|
5202
|
+
this._errors$ = this.createReplaySubject(1);
|
|
4838
5203
|
this._authenticated$ = this.createBehaviorSubject(false);
|
|
4839
5204
|
this._subscriberInfo$ = this.createBehaviorSubject(null);
|
|
4840
5205
|
this._calls$ = this.createBehaviorSubject({});
|
|
4841
5206
|
this._iceServers$ = this.createBehaviorSubject([]);
|
|
4842
5207
|
attachManager.setSession(this);
|
|
4843
|
-
this.callFactory = new CallFactory(this, deviceController, attachManager);
|
|
5208
|
+
this.callFactory = new CallFactory(this, deviceController, attachManager, webRTCApiProvider);
|
|
4844
5209
|
this.initialized$ = (0, rxjs.defer)(() => (0, rxjs.from)(this.init())).pipe((0, rxjs.shareReplay)(1), (0, rxjs.takeUntil)(this.destroyed$));
|
|
4845
5210
|
}
|
|
4846
5211
|
get incomingCalls$() {
|
|
4847
|
-
return this.calls$.pipe((0, rxjs.map)((calls) => calls.filter((call) => call.direction === "inbound")));
|
|
5212
|
+
return this.cachedObservable("incomingCalls$", () => this.calls$.pipe((0, rxjs.map)((calls) => calls.filter((call) => call.direction === "inbound"))));
|
|
4848
5213
|
}
|
|
4849
5214
|
get incomingCalls() {
|
|
4850
5215
|
return Object.values(this._calls$.value).filter((call) => call.direction === "inbound");
|
|
@@ -4856,7 +5221,7 @@ var ClientSessionManager = class extends Destroyable {
|
|
|
4856
5221
|
return this._subscriberInfo$.value;
|
|
4857
5222
|
}
|
|
4858
5223
|
get calls$() {
|
|
4859
|
-
return this._calls$.pipe((0, rxjs.map)((calls) => Object.values(calls)));
|
|
5224
|
+
return this.cachedObservable("calls$", () => this._calls$.pipe((0, rxjs.map)((calls) => Object.values(calls))));
|
|
4860
5225
|
}
|
|
4861
5226
|
get calls() {
|
|
4862
5227
|
return Object.values(this._calls$.value);
|
|
@@ -4864,6 +5229,12 @@ var ClientSessionManager = class extends Destroyable {
|
|
|
4864
5229
|
get iceServers() {
|
|
4865
5230
|
return this._iceServers$.value;
|
|
4866
5231
|
}
|
|
5232
|
+
get authorization$() {
|
|
5233
|
+
return this._authorization$.asObservable();
|
|
5234
|
+
}
|
|
5235
|
+
get authorization() {
|
|
5236
|
+
return this._authorization$.value;
|
|
5237
|
+
}
|
|
4867
5238
|
get errors$() {
|
|
4868
5239
|
return this._errors$.asObservable();
|
|
4869
5240
|
}
|
|
@@ -4959,20 +5330,20 @@ var ClientSessionManager = class extends Destroyable {
|
|
|
4959
5330
|
}
|
|
4960
5331
|
}
|
|
4961
5332
|
get authStateEvent$() {
|
|
4962
|
-
return this.signalingEvent$.pipe((0, rxjs.tap)((msg) => {
|
|
5333
|
+
return this.cachedObservable("authStateEvent$", () => this.signalingEvent$.pipe((0, rxjs.tap)((msg) => {
|
|
4963
5334
|
logger$6.debug("[Session] Received incoming message:", msg);
|
|
4964
5335
|
}), require_operators.filterAs(isSignalwireAuthorizationStateMetadata, "params"), (0, rxjs.tap)((event) => {
|
|
4965
5336
|
logger$6.debug("[Session] Authorization state event received:", event.authorization_state);
|
|
4966
|
-
}));
|
|
5337
|
+
})));
|
|
4967
5338
|
}
|
|
4968
5339
|
get signalingEvent$() {
|
|
4969
|
-
return this.transport.incomingEvent$.pipe(require_operators.filterAs(isSignalwireRequest, "params"));
|
|
5340
|
+
return this.cachedObservable("signalingEvent$", () => this.transport.incomingEvent$.pipe(require_operators.filterAs(isSignalwireRequest, "params"), (0, rxjs.share)()));
|
|
4970
5341
|
}
|
|
4971
5342
|
get vertoInvite$() {
|
|
4972
|
-
return this.signalingEvent$.pipe((0, rxjs.filter)(isWebrtcMessageMetadata), (0, rxjs.filter)((event) => isVertoInviteMessage(event.params)), (0, rxjs.map)((event) => ({
|
|
5343
|
+
return this.cachedObservable("vertoInvite$", () => this.signalingEvent$.pipe((0, rxjs.filter)(isWebrtcMessageMetadata), (0, rxjs.filter)((event) => isVertoInviteMessage(event.params)), (0, rxjs.map)((event) => ({
|
|
4973
5344
|
node_id: event.node_id,
|
|
4974
5345
|
...event.params.params
|
|
4975
|
-
})));
|
|
5346
|
+
}))));
|
|
4976
5347
|
}
|
|
4977
5348
|
get contexts() {
|
|
4978
5349
|
return [];
|
|
@@ -5015,6 +5386,24 @@ var ClientSessionManager = class extends Destroyable {
|
|
|
5015
5386
|
this._errors$.next(new require_operators.AuthStateHandlerError(error));
|
|
5016
5387
|
}
|
|
5017
5388
|
}
|
|
5389
|
+
async reauthenticate(token) {
|
|
5390
|
+
logger$6.debug("[Session] Re-authenticating session");
|
|
5391
|
+
try {
|
|
5392
|
+
const request = RPCReauthenticate({
|
|
5393
|
+
project: this._authorization$.value?.project_id ?? "",
|
|
5394
|
+
jwt_token: token
|
|
5395
|
+
});
|
|
5396
|
+
await (0, rxjs.lastValueFrom)((0, rxjs.from)(this.transport.execute(request)).pipe(require_operators.throwOnRPCError(), (0, rxjs.take)(1), (0, rxjs.catchError)((err) => {
|
|
5397
|
+
logger$6.error("[Session] Re-authentication RPC failed:", err);
|
|
5398
|
+
throw err;
|
|
5399
|
+
})));
|
|
5400
|
+
logger$6.debug("[Session] Re-authentication successful, updating stored auth state");
|
|
5401
|
+
} catch (error) {
|
|
5402
|
+
logger$6.error("[Session] Re-authentication failed:", error);
|
|
5403
|
+
this._errors$.next(new require_operators.AuthStateHandlerError(error));
|
|
5404
|
+
throw error;
|
|
5405
|
+
}
|
|
5406
|
+
}
|
|
5018
5407
|
async authenticate() {
|
|
5019
5408
|
logger$6.debug("[Session] Starting authentication process");
|
|
5020
5409
|
const params = {
|
|
@@ -5038,6 +5427,7 @@ var ClientSessionManager = class extends Destroyable {
|
|
|
5038
5427
|
...params,
|
|
5039
5428
|
...persistedParams
|
|
5040
5429
|
});
|
|
5430
|
+
this.transport.resetSessionEpoch();
|
|
5041
5431
|
const response = await (0, rxjs.lastValueFrom)((0, rxjs.from)(this.transport.execute(rpcConnectRequest)).pipe(require_operators.throwOnRPCError(), (0, rxjs.map)((res) => res.result), (0, rxjs.filter)(isRPCConnectResult), (0, rxjs.tap)(() => {
|
|
5042
5432
|
logger$6.debug("[Session] Response passed filter, processing authentication result");
|
|
5043
5433
|
}), (0, rxjs.take)(1), (0, rxjs.catchError)((err) => {
|
|
@@ -5050,7 +5440,7 @@ var ClientSessionManager = class extends Destroyable {
|
|
|
5050
5440
|
hasIceServers: !!response.ice_servers
|
|
5051
5441
|
});
|
|
5052
5442
|
if (response.protocol) await this.transport.setProtocol(response.protocol);
|
|
5053
|
-
this.
|
|
5443
|
+
this._authorization$.next(response.authorization);
|
|
5054
5444
|
this._iceServers$.next(response.ice_servers ?? []);
|
|
5055
5445
|
this._authenticated$.next(true);
|
|
5056
5446
|
logger$6.debug("[Session] Authentication completed successfully");
|
|
@@ -5069,7 +5459,8 @@ var ClientSessionManager = class extends Destroyable {
|
|
|
5069
5459
|
to: invite.callee_id_number,
|
|
5070
5460
|
fromName: invite.caller_id_name,
|
|
5071
5461
|
from: invite.caller_id_number,
|
|
5072
|
-
displayDirection: invite.display_direction
|
|
5462
|
+
displayDirection: invite.display_direction,
|
|
5463
|
+
userVariables: invite.userVariables
|
|
5073
5464
|
});
|
|
5074
5465
|
await (0, rxjs.firstValueFrom)(callSession.status$);
|
|
5075
5466
|
this._calls$.next({
|
|
@@ -5079,12 +5470,13 @@ var ClientSessionManager = class extends Destroyable {
|
|
|
5079
5470
|
}
|
|
5080
5471
|
async createOutboundCall(destination, options = {}) {
|
|
5081
5472
|
const destinationURI = destination instanceof Address ? destination.defaultChannel : destination;
|
|
5473
|
+
let callSession;
|
|
5082
5474
|
try {
|
|
5083
|
-
|
|
5475
|
+
callSession = await this.createCall({
|
|
5084
5476
|
to: destinationURI,
|
|
5085
5477
|
...options
|
|
5086
5478
|
});
|
|
5087
|
-
await (0, rxjs.firstValueFrom)(callSession.selfId$.pipe((0, rxjs.filter)((id) => Boolean(id)), (0, rxjs.take)(1), (0, rxjs.timeout)(this.callCreateTimeout)));
|
|
5479
|
+
await (0, rxjs.firstValueFrom)((0, rxjs.race)(callSession.selfId$.pipe((0, rxjs.filter)((id) => Boolean(id)), (0, rxjs.take)(1), (0, rxjs.timeout)(this.callCreateTimeout)), callSession.errors$.pipe((0, rxjs.take)(1), (0, rxjs.switchMap)((callError) => (0, rxjs.throwError)(() => callError.error)))));
|
|
5088
5480
|
this._calls$.next({
|
|
5089
5481
|
[`${callSession.id}`]: callSession,
|
|
5090
5482
|
...this._calls$.value
|
|
@@ -5092,19 +5484,25 @@ var ClientSessionManager = class extends Destroyable {
|
|
|
5092
5484
|
return callSession;
|
|
5093
5485
|
} catch (error) {
|
|
5094
5486
|
logger$6.error("[Session] Error creating outbound call:", error);
|
|
5095
|
-
|
|
5487
|
+
callSession?.destroy();
|
|
5488
|
+
const callError = new require_operators.CallCreateError(error instanceof rxjs.TimeoutError ? "Call create timeout" : "Call creation failed", error, "outbound");
|
|
5096
5489
|
this._errors$.next(callError);
|
|
5097
5490
|
throw callError;
|
|
5098
5491
|
}
|
|
5099
5492
|
}
|
|
5100
5493
|
async createCall(options = {}) {
|
|
5101
5494
|
try {
|
|
5102
|
-
if (!this._directory) throw new require_operators.DependencyError("Directory not initialized");
|
|
5103
5495
|
const addressURI = getAddressSearchURI(options);
|
|
5104
|
-
|
|
5105
|
-
|
|
5106
|
-
|
|
5107
|
-
|
|
5496
|
+
let address;
|
|
5497
|
+
try {
|
|
5498
|
+
if (!this._directory) throw new require_operators.DependencyError("Directory not initialized");
|
|
5499
|
+
const addressId = await this._directory.findAddressIdByURI(addressURI);
|
|
5500
|
+
if (!addressId) throw new require_operators.DependencyError(`Address name: ${addressURI} not found`);
|
|
5501
|
+
address = this._directory.get(addressId);
|
|
5502
|
+
if (!address) throw new require_operators.DependencyError(`Address ID: ${addressId} not found`);
|
|
5503
|
+
} catch (error) {
|
|
5504
|
+
logger$6.warn(`[Session] Directory lookup failed for ${addressURI}, proceeding with raw URI`);
|
|
5505
|
+
}
|
|
5108
5506
|
const callSession = this.callFactory.createCall(address, { ...options });
|
|
5109
5507
|
callSession.status$.pipe((0, rxjs.filter)((status) => status === "destroyed"), (0, rxjs.take)(1)).subscribe(() => {
|
|
5110
5508
|
const { [`${callSession.id}`]: _, ...remainingCalls } = this._calls$.value;
|
|
@@ -5113,7 +5511,7 @@ var ClientSessionManager = class extends Destroyable {
|
|
|
5113
5511
|
return callSession;
|
|
5114
5512
|
} catch (error) {
|
|
5115
5513
|
logger$6.error("[Session] Error creating call session:", error);
|
|
5116
|
-
throw new require_operators.CallCreateError("Call create error", error);
|
|
5514
|
+
throw new require_operators.CallCreateError("Call create error", error, options.initOffer ? "inbound" : "outbound");
|
|
5117
5515
|
}
|
|
5118
5516
|
}
|
|
5119
5517
|
destroy() {
|
|
@@ -5134,6 +5532,9 @@ var ClientSessionWrapper = class {
|
|
|
5134
5532
|
get signalingEvent$() {
|
|
5135
5533
|
return this.clientSessionManager.signalingEvent$;
|
|
5136
5534
|
}
|
|
5535
|
+
get iceServers() {
|
|
5536
|
+
return this.clientSessionManager.iceServers;
|
|
5537
|
+
}
|
|
5137
5538
|
async execute(request, options) {
|
|
5138
5539
|
return this.clientSessionManager.execute(request, options);
|
|
5139
5540
|
}
|
|
@@ -5356,7 +5757,7 @@ var WebSocketController = class WebSocketController extends Destroyable {
|
|
|
5356
5757
|
this.shouldReconnect = false;
|
|
5357
5758
|
this._status$ = this.createBehaviorSubject("disconnected");
|
|
5358
5759
|
this._incomingMessages$ = this.createSubject();
|
|
5359
|
-
this._errors$ = this.
|
|
5760
|
+
this._errors$ = this.createReplaySubject(1);
|
|
5360
5761
|
this.reconnectDelayMin = options.reconnectDelayMin ?? WebSocketController.DEFAULT_RECONNECT_DELAY_MIN_MS;
|
|
5361
5762
|
this.reconnectDelayMax = options.reconnectDelayMax ?? WebSocketController.DEFAULT_RECONNECT_DELAY_MAX_MS;
|
|
5362
5763
|
this.connectionTimeout = options.connectionTimeout ?? WebSocketController.DEFAULT_CONNECTION_TIMEOUT_MS;
|
|
@@ -5506,7 +5907,30 @@ function isSignalwirePingRequest(value) {
|
|
|
5506
5907
|
//#endregion
|
|
5507
5908
|
//#region src/managers/TransportManager.ts
|
|
5508
5909
|
const logger$2 = require_operators.getLogger();
|
|
5509
|
-
var TransportManager = class extends Destroyable {
|
|
5910
|
+
var TransportManager = class TransportManager extends Destroyable {
|
|
5911
|
+
/**
|
|
5912
|
+
* Normalise a server event timestamp to epoch seconds.
|
|
5913
|
+
*
|
|
5914
|
+
* The server uses two formats:
|
|
5915
|
+
* - `webrtc.message`: float epoch seconds (e.g. 1774372099.022817)
|
|
5916
|
+
* - all other events: int epoch microseconds (e.g. 1774372099925857)
|
|
5917
|
+
*
|
|
5918
|
+
* Values above 1e12 are treated as microseconds and divided by 1e6.
|
|
5919
|
+
*/
|
|
5920
|
+
static toEpochSeconds(ts) {
|
|
5921
|
+
const n = typeof ts === "string" ? Number(ts) : ts;
|
|
5922
|
+
return n > 0xe8d4a51000 ? n / 1e6 : n;
|
|
5923
|
+
}
|
|
5924
|
+
/**
|
|
5925
|
+
* Extract the event timestamp from a signalwire.event message.
|
|
5926
|
+
* Returns `null` for messages that have no timestamp
|
|
5927
|
+
* (e.g. signalwire.authorization.state, RPC responses).
|
|
5928
|
+
*/
|
|
5929
|
+
static extractEventTimestamp(message) {
|
|
5930
|
+
if (!isSignalwireRequest(message)) return null;
|
|
5931
|
+
if (message.params.event_type === "signalwire.authorization.state") return null;
|
|
5932
|
+
return TransportManager.toEpochSeconds(message.params.timestamp);
|
|
5933
|
+
}
|
|
5510
5934
|
constructor(storage, protocolKey, webSocketConstructor, relayHost, onError) {
|
|
5511
5935
|
super();
|
|
5512
5936
|
this.storage = storage;
|
|
@@ -5539,6 +5963,23 @@ var TransportManager = class extends Destroyable {
|
|
|
5539
5963
|
return true;
|
|
5540
5964
|
});
|
|
5541
5965
|
};
|
|
5966
|
+
this.discardStaleEvents = () => {
|
|
5967
|
+
return (0, rxjs.filter)((message) => {
|
|
5968
|
+
const ts = TransportManager.extractEventTimestamp(message);
|
|
5969
|
+
if (ts === null) return true;
|
|
5970
|
+
if (this._sessionEpoch === null) {
|
|
5971
|
+
this._sessionEpoch = ts;
|
|
5972
|
+
return true;
|
|
5973
|
+
}
|
|
5974
|
+
if (ts < this._sessionEpoch) {
|
|
5975
|
+
const eventType = isSignalwireRequest(message) ? message.params.event_type : "unknown";
|
|
5976
|
+
logger$2.warn(`[Transport] Discarding stale event: ${eventType} (timestamp=${ts.toFixed(3)}, sessionEpoch=${this._sessionEpoch.toFixed(3)}, delta=${(this._sessionEpoch - ts).toFixed(3)}s)`);
|
|
5977
|
+
return false;
|
|
5978
|
+
}
|
|
5979
|
+
return true;
|
|
5980
|
+
});
|
|
5981
|
+
};
|
|
5982
|
+
this._sessionEpoch = null;
|
|
5542
5983
|
this._outgoingMessages$ = this.createSubject();
|
|
5543
5984
|
this._webSocketConnections = new WebSocketController(webSocketConstructor, relayHost, this._outgoingMessages$.asObservable(), {
|
|
5544
5985
|
connectionTimeout: PreferencesContainer.instance.connectionTimeout,
|
|
@@ -5563,7 +6004,14 @@ var TransportManager = class extends Destroyable {
|
|
|
5563
6004
|
return rxjs.EMPTY;
|
|
5564
6005
|
}), (0, rxjs.share)(), (0, rxjs.takeUntil)(this.destroyed$));
|
|
5565
6006
|
this._jsonRPCResponse$ = this._jsonRPCMessage$.pipe((0, rxjs.filter)(isJSONRPCResponse));
|
|
5566
|
-
this._incomingEvent$ = this._jsonRPCMessage$.pipe(this.ackEvent(), this.replySignalwirePing(), (0, rxjs.filter)((message) => !isJSONRPCResponse(message)), (0, rxjs.share)(), (0, rxjs.takeUntil)(this.destroyed$));
|
|
6007
|
+
this._incomingEvent$ = this._jsonRPCMessage$.pipe(this.ackEvent(), this.replySignalwirePing(), (0, rxjs.filter)((message) => !isJSONRPCResponse(message)), this.discardStaleEvents(), (0, rxjs.share)(), (0, rxjs.takeUntil)(this.destroyed$));
|
|
6008
|
+
}
|
|
6009
|
+
/**
|
|
6010
|
+
* Reset the session epoch. Call this before each signalwire.connect
|
|
6011
|
+
* so that the first event after authentication establishes the new baseline.
|
|
6012
|
+
*/
|
|
6013
|
+
resetSessionEpoch() {
|
|
6014
|
+
this._sessionEpoch = null;
|
|
5567
6015
|
}
|
|
5568
6016
|
async setProtocol(protocol) {
|
|
5569
6017
|
this.protocol$.next(protocol);
|
|
@@ -5681,7 +6129,8 @@ const buildOptionsFromDestination = (destination) => {
|
|
|
5681
6129
|
const channel = new URLSearchParams(queryString).get("channel");
|
|
5682
6130
|
if (channel === "video") return {
|
|
5683
6131
|
audio: true,
|
|
5684
|
-
video: true
|
|
6132
|
+
video: true,
|
|
6133
|
+
receiveVideo: true
|
|
5685
6134
|
};
|
|
5686
6135
|
else if (channel === "audio") return {
|
|
5687
6136
|
audio: true,
|
|
@@ -5711,7 +6160,7 @@ var SignalWire = class extends Destroyable {
|
|
|
5711
6160
|
this._directory$ = this.createBehaviorSubject(void 0);
|
|
5712
6161
|
this._isConnected$ = this.createBehaviorSubject(false);
|
|
5713
6162
|
this._isRegistered$ = this.createBehaviorSubject(false);
|
|
5714
|
-
this._errors$ = this.
|
|
6163
|
+
this._errors$ = this.createReplaySubject(1);
|
|
5715
6164
|
this._options = {};
|
|
5716
6165
|
this._deps = new DependencyContainer();
|
|
5717
6166
|
this._options = {
|
|
@@ -5721,6 +6170,7 @@ var SignalWire = class extends Destroyable {
|
|
|
5721
6170
|
if (this._options.storageImplementation) this._deps.storageImpl = this._options.storageImplementation;
|
|
5722
6171
|
if (this._options.webSocketConstructor) this._deps.WebSocket = this._options.webSocketConstructor;
|
|
5723
6172
|
if (this._options.savePreferences) this.preferences.enableSavePreferences(this._deps.storage);
|
|
6173
|
+
if (this._options.webRTCApiProvider) this._deps.webRTCApiProvider = this._options.webRTCApiProvider;
|
|
5724
6174
|
this._deviceController = this._deps.deviceController;
|
|
5725
6175
|
if (!this._options.skipDeviceMonitoring) this._deviceController.enableDeviceMonitoring();
|
|
5726
6176
|
this.subscribeTo(this._deviceController.errors$, (error) => {
|
|
@@ -5754,7 +6204,10 @@ var SignalWire = class extends Destroyable {
|
|
|
5754
6204
|
throw new require_operators.InvalidCredentialsError("Provided credentials have expired.");
|
|
5755
6205
|
}
|
|
5756
6206
|
if (_credentials.expiry_at && credentialProvider.refresh) {
|
|
5757
|
-
const refreshFn =
|
|
6207
|
+
const refreshFn = async () => {
|
|
6208
|
+
if (!credentialProvider.refresh) throw new require_operators.InvalidCredentialsError("Credential provider does not support refresh");
|
|
6209
|
+
return credentialProvider.refresh();
|
|
6210
|
+
};
|
|
5758
6211
|
const refreshInterval = Math.max(_credentials.expiry_at - Date.now() - 5e3, 1e3);
|
|
5759
6212
|
this._refreshTimerId = setTimeout(async () => {
|
|
5760
6213
|
try {
|
|
@@ -5772,12 +6225,24 @@ var SignalWire = class extends Destroyable {
|
|
|
5772
6225
|
}, refreshInterval);
|
|
5773
6226
|
}
|
|
5774
6227
|
this._deps.credential = _credentials;
|
|
6228
|
+
if (this.isConnected && this._clientSession.authenticated && _credentials.token) try {
|
|
6229
|
+
await this._clientSession.reauthenticate(_credentials.token);
|
|
6230
|
+
logger$1.info("[SignalWire] Session refreshed with new credentials.");
|
|
6231
|
+
} catch (error) {
|
|
6232
|
+
logger$1.error("[SignalWire] Failed to refresh session with new credentials:", error);
|
|
6233
|
+
this._errors$.next(error instanceof Error ? error : new Error(String(error), { cause: error }));
|
|
6234
|
+
}
|
|
5775
6235
|
}
|
|
5776
6236
|
async init() {
|
|
5777
6237
|
this._subscriber$.next(new Subscriber(this._deps.http));
|
|
5778
6238
|
if (!this._options.skipConnection) await this.connect();
|
|
5779
|
-
if (this._options.
|
|
5780
|
-
if (!this._options.skipRegister)
|
|
6239
|
+
if (!this._options.reconnectAttachedCalls && this._attachManager) await this._attachManager.flush();
|
|
6240
|
+
if (!this._options.skipRegister) try {
|
|
6241
|
+
await this.register();
|
|
6242
|
+
} catch (error) {
|
|
6243
|
+
logger$1.error("[SignalWire] Registration failed:", error);
|
|
6244
|
+
this._errors$.next(error instanceof Error ? error : new Error(String(error), { cause: error }));
|
|
6245
|
+
}
|
|
5781
6246
|
this.handleAttachments();
|
|
5782
6247
|
}
|
|
5783
6248
|
async handleAttachments() {
|
|
@@ -5845,7 +6310,7 @@ var SignalWire = class extends Destroyable {
|
|
|
5845
6310
|
};
|
|
5846
6311
|
this._transport = new TransportManager(this._deps.storage, this._deps.protocolKey, this._deps.WebSocket, PreferencesContainer.instance.relayHost ?? this._deps.relayHost, errorHandler);
|
|
5847
6312
|
this._attachManager = new AttachManager(this._deps.storage, this._deps.deviceController, PreferencesContainer.instance.reconnectCallsTimeout, this._deps.attachedCallsKey);
|
|
5848
|
-
this._clientSession = new ClientSessionManager(this._deps.credential, this._transport, this._deps.storage, this._deps.authorizationStateKey, this._deps.deviceController, this._attachManager);
|
|
6313
|
+
this._clientSession = new ClientSessionManager(this._deps.credential, this._transport, this._deps.storage, this._deps.authorizationStateKey, this._deps.deviceController, this._attachManager, this._deps.webRTCApiProvider);
|
|
5849
6314
|
this._publicSession = new ClientSessionWrapper(this._clientSession);
|
|
5850
6315
|
this.subscribeTo(this._clientSession.errors$, (error) => {
|
|
5851
6316
|
this._errors$.next(error);
|
|
@@ -5869,7 +6334,7 @@ var SignalWire = class extends Destroyable {
|
|
|
5869
6334
|
* ```
|
|
5870
6335
|
*/
|
|
5871
6336
|
get subscriber$() {
|
|
5872
|
-
return this._subscriber$.asObservable();
|
|
6337
|
+
return this.deferEmission(this._subscriber$.asObservable());
|
|
5873
6338
|
}
|
|
5874
6339
|
/** Current subscriber snapshot, or `undefined` if not yet authenticated. */
|
|
5875
6340
|
get subscriber() {
|
|
@@ -5888,7 +6353,7 @@ var SignalWire = class extends Destroyable {
|
|
|
5888
6353
|
* ```
|
|
5889
6354
|
*/
|
|
5890
6355
|
get directory$() {
|
|
5891
|
-
return this._directory$.asObservable();
|
|
6356
|
+
return this.deferEmission(this._directory$.asObservable());
|
|
5892
6357
|
}
|
|
5893
6358
|
/**
|
|
5894
6359
|
* Current directory snapshot, or `undefined` if the client is not yet connected.
|
|
@@ -5899,7 +6364,7 @@ var SignalWire = class extends Destroyable {
|
|
|
5899
6364
|
}
|
|
5900
6365
|
/** Observable that emits when the subscriber registration state changes. */
|
|
5901
6366
|
get isRegistered$() {
|
|
5902
|
-
return this._isRegistered$.asObservable();
|
|
6367
|
+
return this.deferEmission(this._isRegistered$.asObservable());
|
|
5903
6368
|
}
|
|
5904
6369
|
/** Whether the subscriber is currently registered. */
|
|
5905
6370
|
get isRegistered() {
|
|
@@ -5911,15 +6376,15 @@ var SignalWire = class extends Destroyable {
|
|
|
5911
6376
|
}
|
|
5912
6377
|
/** Observable that emits when the connection state changes. */
|
|
5913
6378
|
get isConnected$() {
|
|
5914
|
-
return this._isConnected$.asObservable();
|
|
6379
|
+
return this.deferEmission(this._isConnected$.asObservable());
|
|
5915
6380
|
}
|
|
5916
6381
|
/** Observable that emits `true` when the client is both connected and authenticated. */
|
|
5917
6382
|
get ready$() {
|
|
5918
|
-
return this._isConnected$.pipe((0, rxjs.switchMap)((connected) => connected ? this._clientSession.authenticated$ : (0, rxjs.of)(false)));
|
|
6383
|
+
return this.publicCachedObservable("ready$", () => this._isConnected$.pipe((0, rxjs.switchMap)((connected) => connected ? this._clientSession.authenticated$ : (0, rxjs.of)(false))));
|
|
5919
6384
|
}
|
|
5920
6385
|
/** Observable stream of errors from transport, authentication, and devices. */
|
|
5921
6386
|
get errors$() {
|
|
5922
|
-
return this._errors$.asObservable();
|
|
6387
|
+
return this.deferEmission(this._errors$.asObservable());
|
|
5923
6388
|
}
|
|
5924
6389
|
/** Disconnects the WebSocket and tears down the session. */
|
|
5925
6390
|
async disconnect() {
|
|
@@ -5940,8 +6405,22 @@ var SignalWire = class extends Destroyable {
|
|
|
5940
6405
|
}));
|
|
5941
6406
|
this._isRegistered$.next(true);
|
|
5942
6407
|
} catch (error) {
|
|
5943
|
-
logger$1.
|
|
6408
|
+
logger$1.debug("[SignalWire] Failed to register subscriber, trying reauthentication...");
|
|
6409
|
+
if (this._deps.credential.token) this._clientSession.reauthenticate(this._deps.credential.token).then(async () => {
|
|
6410
|
+
logger$1.debug("[SignalWire] Reauthentication successful, retrying register()");
|
|
6411
|
+
await this._transport.execute(RPCExecute({
|
|
6412
|
+
method: "subscriber.online",
|
|
6413
|
+
params: {}
|
|
6414
|
+
}));
|
|
6415
|
+
this._isRegistered$.next(true);
|
|
6416
|
+
}).catch((reauthError) => {
|
|
6417
|
+
logger$1.error("[SignalWire] Reauthentication failed during register():", reauthError);
|
|
6418
|
+
const registerError = new require_operators.InvalidCredentialsError("Failed to register subscriber, and reauthentication attempt also failed. Please check your credentials.", { cause: reauthError instanceof Error ? reauthError : new Error(String(reauthError), { cause: reauthError }) });
|
|
6419
|
+
this._errors$.next(registerError);
|
|
6420
|
+
throw registerError;
|
|
6421
|
+
});
|
|
5944
6422
|
this._errors$.next(error instanceof Error ? error : new Error(String(error), { cause: error }));
|
|
6423
|
+
throw error;
|
|
5945
6424
|
}
|
|
5946
6425
|
}
|
|
5947
6426
|
/** Unregisters the subscriber, going offline for inbound calls. */
|
|
@@ -5980,7 +6459,7 @@ var SignalWire = class extends Destroyable {
|
|
|
5980
6459
|
}
|
|
5981
6460
|
/** Observable list of available audio input (microphone) devices. */
|
|
5982
6461
|
get audioInputDevices$() {
|
|
5983
|
-
return this._deviceController.audioInputDevices
|
|
6462
|
+
return this.deferEmission(this._deviceController.audioInputDevices$);
|
|
5984
6463
|
}
|
|
5985
6464
|
/** Current snapshot of available audio input devices. */
|
|
5986
6465
|
get audioInputDevices() {
|
|
@@ -5988,7 +6467,7 @@ var SignalWire = class extends Destroyable {
|
|
|
5988
6467
|
}
|
|
5989
6468
|
/** Observable list of available audio output (speaker) devices. */
|
|
5990
6469
|
get audioOutputDevices$() {
|
|
5991
|
-
return this._deviceController.audioOutputDevices
|
|
6470
|
+
return this.deferEmission(this._deviceController.audioOutputDevices$);
|
|
5992
6471
|
}
|
|
5993
6472
|
/** Current snapshot of available audio output devices. */
|
|
5994
6473
|
get audioOutputDevices() {
|
|
@@ -5996,7 +6475,7 @@ var SignalWire = class extends Destroyable {
|
|
|
5996
6475
|
}
|
|
5997
6476
|
/** Observable list of available video input (camera) devices. */
|
|
5998
6477
|
get videoInputDevices$() {
|
|
5999
|
-
return this._deviceController.videoInputDevices
|
|
6478
|
+
return this.deferEmission(this._deviceController.videoInputDevices$);
|
|
6000
6479
|
}
|
|
6001
6480
|
/** Current snapshot of available video input devices. */
|
|
6002
6481
|
get videoInputDevices() {
|
|
@@ -6004,15 +6483,15 @@ var SignalWire = class extends Destroyable {
|
|
|
6004
6483
|
}
|
|
6005
6484
|
/** Observable of the currently selected audio input device. */
|
|
6006
6485
|
get selectedAudioInputDevice$() {
|
|
6007
|
-
return this._deviceController.selectedAudioInputDevice
|
|
6486
|
+
return this.deferEmission(this._deviceController.selectedAudioInputDevice$);
|
|
6008
6487
|
}
|
|
6009
6488
|
/** Observable of the currently selected audio output device. */
|
|
6010
6489
|
get selectedAudioOutputDevice$() {
|
|
6011
|
-
return this._deviceController.selectedAudioOutputDevice
|
|
6490
|
+
return this.deferEmission(this._deviceController.selectedAudioOutputDevice$);
|
|
6012
6491
|
}
|
|
6013
6492
|
/** Observable of the currently selected video input device. */
|
|
6014
6493
|
get selectedVideoInputDevice$() {
|
|
6015
|
-
return this._deviceController.selectedVideoInputDevice
|
|
6494
|
+
return this.deferEmission(this._deviceController.selectedVideoInputDevice$);
|
|
6016
6495
|
}
|
|
6017
6496
|
/** Currently selected audio input device, or `null` if none. */
|
|
6018
6497
|
get selectedAudioInputDevice() {
|
|
@@ -6194,13 +6673,16 @@ exports.Address = Address;
|
|
|
6194
6673
|
exports.CallCreateError = require_operators.CallCreateError;
|
|
6195
6674
|
exports.ClientPreferences = ClientPreferences;
|
|
6196
6675
|
exports.CollectionFetchError = require_operators.CollectionFetchError;
|
|
6676
|
+
exports.InvalidCredentialsError = require_operators.InvalidCredentialsError;
|
|
6197
6677
|
exports.MediaTrackError = require_operators.MediaTrackError;
|
|
6198
6678
|
exports.MessageParseError = require_operators.MessageParseError;
|
|
6199
6679
|
exports.Participant = Participant;
|
|
6680
|
+
exports.SelfCapabilities = SelfCapabilities;
|
|
6200
6681
|
exports.SelfParticipant = SelfParticipant;
|
|
6201
6682
|
exports.SignalWire = SignalWire;
|
|
6202
6683
|
exports.StaticCredentialProvider = StaticCredentialProvider;
|
|
6203
6684
|
exports.Subscriber = Subscriber;
|
|
6685
|
+
exports.UnexpectedError = require_operators.UnexpectedError;
|
|
6204
6686
|
exports.VertoPongError = require_operators.VertoPongError;
|
|
6205
6687
|
exports.WebRTCCall = WebRTCCall;
|
|
6206
6688
|
exports.embeddableCall = embeddableCall;
|