@arcware-cloud/pixelstreaming-websdk 1.2.18 → 1.3.1
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/index.cjs.js +1184 -727
- package/index.esm.js +1226 -762
- package/index.umd.js +1184 -727
- package/package.json +1 -1
- package/types/lib/ArcwareApplication.d.ts +4 -0
- package/types/lib/ArcwareConfig.d.ts +1 -1
- package/types/lib/ArcwarePixelStreaming.d.ts +30 -1
- package/types/lib/features/ArcwareEventUtil.d.ts +28 -0
- package/types/lib/features/ArcwareFileTransferUtil.d.ts +13 -0
- package/types/lib/features/common.d.ts +13 -0
- /package/types/lib/{DiagnosticsCollector.d.ts → features/DiagnosticsCollector.d.ts} +0 -0
package/index.umd.js
CHANGED
|
@@ -22853,7 +22853,7 @@ function UrlBuilder(input, urlFlags) {
|
|
|
22853
22853
|
flags.split("&").forEach((val) => {
|
|
22854
22854
|
const [key, value] = val.split("=");
|
|
22855
22855
|
// Ensure the value is encoded
|
|
22856
|
-
params.
|
|
22856
|
+
params.set(key, value);
|
|
22857
22857
|
});
|
|
22858
22858
|
}
|
|
22859
22859
|
return url.toString();
|
|
@@ -22891,6 +22891,9 @@ const ArcwarePixelStreamingApplicationStyles_1 = __webpack_require__(2299);
|
|
|
22891
22891
|
const AudioButton_1 = __webpack_require__(7734);
|
|
22892
22892
|
const MicButton_1 = __webpack_require__(2293);
|
|
22893
22893
|
const StopButton_1 = __webpack_require__(9684);
|
|
22894
|
+
const ArcwareEventUtil_1 = __webpack_require__(471);
|
|
22895
|
+
const ArcwareFileTransferUtil_1 = __webpack_require__(2768);
|
|
22896
|
+
const common_1 = __webpack_require__(2483);
|
|
22894
22897
|
const DEBUG = false;
|
|
22895
22898
|
const TextKeyRegex = /^(\['([a-zA-Z 0-9-_]+)'\] )/;
|
|
22896
22899
|
function findElementByTextContent(root, selector) {
|
|
@@ -22940,7 +22943,7 @@ const removals = {
|
|
|
22940
22943
|
// By default the UI settings should be disabled, since we have a custom method for them.
|
|
22941
22944
|
"['UI'] section.settingsContainer:not([id])": true,
|
|
22942
22945
|
// Hide option of start audio muted or not
|
|
22943
|
-
"#StartVideoMuted": true
|
|
22946
|
+
"#StartVideoMuted": true
|
|
22944
22947
|
};
|
|
22945
22948
|
if (DEBUG)
|
|
22946
22949
|
Object.keys(removals).forEach((key) => {
|
|
@@ -22966,6 +22969,8 @@ class ArcwareApplication extends lib_pixelstreamingfrontend_ui_ue5_5_1.Applicati
|
|
|
22966
22969
|
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
|
|
22967
22970
|
super(options);
|
|
22968
22971
|
this.responseCallback = null;
|
|
22972
|
+
this.analyticsEventCallback = null;
|
|
22973
|
+
this.fileDownloadCallback = null;
|
|
22969
22974
|
this.ArcwareSection = this.configUI.buildSectionWithHeading(this.settingsPanel.settingsContentElement, "Arcware Cloud");
|
|
22970
22975
|
this.stream = options === null || options === void 0 ? void 0 : options.stream;
|
|
22971
22976
|
this.emitUIInteraction = this.emitUIInteraction.bind(this);
|
|
@@ -22978,7 +22983,7 @@ class ArcwareApplication extends lib_pixelstreamingfrontend_ui_ue5_5_1.Applicati
|
|
|
22978
22983
|
this.parentElement = (_b = this === null || this === void 0 ? void 0 : this.videoElementParent) === null || _b === void 0 ? void 0 : _b.parentElement;
|
|
22979
22984
|
this.webRtcController = (_c = this === null || this === void 0 ? void 0 : this.stream) === null || _c === void 0 ? void 0 : _c["_webRtcController"];
|
|
22980
22985
|
this.addLoveLetterhandler();
|
|
22981
|
-
(_d = this === null || this === void 0 ? void 0 : this.stream) === null || _d === void 0 ? void 0 : _d.addResponseEventListener("ue-response", (response) => this
|
|
22986
|
+
(_d = this === null || this === void 0 ? void 0 : this.stream) === null || _d === void 0 ? void 0 : _d.addResponseEventListener("ue-response-internal", (response) => this.applicationResponse(response));
|
|
22982
22987
|
(_f = (_e = this === null || this === void 0 ? void 0 : this.stream) === null || _e === void 0 ? void 0 : _e.sessionIdHandler) === null || _f === void 0 ? void 0 : _f.add((sessionId) => {
|
|
22983
22988
|
var _a;
|
|
22984
22989
|
(_a = this === null || this === void 0 ? void 0 : this.statsPanel) === null || _a === void 0 ? void 0 : _a.addOrUpdateSessionStat("sessionId", "SessionId", sessionId);
|
|
@@ -23007,6 +23012,8 @@ class ArcwareApplication extends lib_pixelstreamingfrontend_ui_ue5_5_1.Applicati
|
|
|
23007
23012
|
this.uiElementsVisibility(false);
|
|
23008
23013
|
this.addTextToConnectOverlay();
|
|
23009
23014
|
this.preventDefaultKeyboardEvents();
|
|
23015
|
+
this.analyticsEventCallback = this.analyticsEvent;
|
|
23016
|
+
this.fileDownloadCallback = this.fileDownload;
|
|
23010
23017
|
}
|
|
23011
23018
|
addLoveLetterhandler() {
|
|
23012
23019
|
var _a, _b;
|
|
@@ -23237,8 +23244,26 @@ class ArcwareApplication extends lib_pixelstreamingfrontend_ui_ue5_5_1.Applicati
|
|
|
23237
23244
|
});
|
|
23238
23245
|
}
|
|
23239
23246
|
applicationResponse(response) {
|
|
23240
|
-
|
|
23241
|
-
|
|
23247
|
+
var _a, _b;
|
|
23248
|
+
let obj = null;
|
|
23249
|
+
try {
|
|
23250
|
+
obj = (0, common_1.parseUnknownToObject)(response, { allowJsonish: true });
|
|
23251
|
+
}
|
|
23252
|
+
catch (_c) {
|
|
23253
|
+
// If not parseable, fall through to generic callback
|
|
23254
|
+
}
|
|
23255
|
+
const t = (0, common_1.normalizeType)(obj["type"]);
|
|
23256
|
+
// route to exactly one callback
|
|
23257
|
+
if (t === "event") {
|
|
23258
|
+
(_a = this.analyticsEventCallback) === null || _a === void 0 ? void 0 : _a.call(this, response);
|
|
23259
|
+
return;
|
|
23260
|
+
}
|
|
23261
|
+
if (t === "filetransfer" || t === "createscreenshot") {
|
|
23262
|
+
(_b = this.fileDownloadCallback) === null || _b === void 0 ? void 0 : _b.call(this, response);
|
|
23263
|
+
return;
|
|
23264
|
+
}
|
|
23265
|
+
if (this.responseCallback) {
|
|
23266
|
+
this.responseCallback(response);
|
|
23242
23267
|
}
|
|
23243
23268
|
}
|
|
23244
23269
|
applyArcwareStyles() {
|
|
@@ -23277,6 +23302,49 @@ class ArcwareApplication extends lib_pixelstreamingfrontend_ui_ue5_5_1.Applicati
|
|
|
23277
23302
|
}
|
|
23278
23303
|
}
|
|
23279
23304
|
}
|
|
23305
|
+
analyticsEvent(response) {
|
|
23306
|
+
var _a;
|
|
23307
|
+
const event = (0, ArcwareEventUtil_1.toAnalyticsEvent)(response, { maxPayloadBytes: 512, allowJsonish: true });
|
|
23308
|
+
if (event.ok === false) {
|
|
23309
|
+
console.warn("Invalid AnalyticsEvent:", event.error, response);
|
|
23310
|
+
return;
|
|
23311
|
+
}
|
|
23312
|
+
(_a = this.stream) === null || _a === void 0 ? void 0 : _a.send(event.value); // send the sanitized object
|
|
23313
|
+
}
|
|
23314
|
+
fileDownload(response) {
|
|
23315
|
+
var _a;
|
|
23316
|
+
let msg;
|
|
23317
|
+
try {
|
|
23318
|
+
msg = (0, ArcwareFileTransferUtil_1.parseControl)(response, ArcwareFileTransferUtil_1.ZFileTransfer);
|
|
23319
|
+
}
|
|
23320
|
+
catch (e) {
|
|
23321
|
+
console.warn("Invalid control message:", e);
|
|
23322
|
+
return;
|
|
23323
|
+
}
|
|
23324
|
+
const file = (_a = this.webRtcController) === null || _a === void 0 ? void 0 : _a.file;
|
|
23325
|
+
if (!file || !file.data || !file.mimetype)
|
|
23326
|
+
return;
|
|
23327
|
+
const ext = (0, common_1.extFromMime)(file.mimetype);
|
|
23328
|
+
const base = msg.filename && msg.filename.trim() ? (0, common_1.sanitizeFilename)(msg.filename) : (0, common_1.randomHash)();
|
|
23329
|
+
const name = base + ext;
|
|
23330
|
+
try {
|
|
23331
|
+
// ✅ Make safe Blob parts (clone each chunk to ensure regular ArrayBuffer)
|
|
23332
|
+
const chunks = file.data; // <-- remove the generic
|
|
23333
|
+
const safeParts = chunks.map((u8) => u8.slice()); // fresh ArrayBuffers
|
|
23334
|
+
const blob = new Blob(safeParts, { type: file.mimetype });
|
|
23335
|
+
const url = URL.createObjectURL(blob);
|
|
23336
|
+
const a = document.createElement("a");
|
|
23337
|
+
a.href = url;
|
|
23338
|
+
a.download = name;
|
|
23339
|
+
document.body.appendChild(a);
|
|
23340
|
+
a.click();
|
|
23341
|
+
document.body.removeChild(a);
|
|
23342
|
+
setTimeout(() => URL.revokeObjectURL(url), 0);
|
|
23343
|
+
}
|
|
23344
|
+
catch (err) {
|
|
23345
|
+
console.error("Download failed:", err);
|
|
23346
|
+
}
|
|
23347
|
+
}
|
|
23280
23348
|
}
|
|
23281
23349
|
ArcwareApplication.Flags = (_a = class {
|
|
23282
23350
|
},
|
|
@@ -23361,7 +23429,7 @@ class ArcwareConfig extends lib_pixelstreamingfrontend_ue5_5_1.Config {
|
|
|
23361
23429
|
if (!config.initialSettings.ss)
|
|
23362
23430
|
config.initialSettings.ss = exports.DefaultUrl;
|
|
23363
23431
|
super(config);
|
|
23364
|
-
this.VERSION = "1.
|
|
23432
|
+
this.VERSION = "1.3.1";
|
|
23365
23433
|
this.settings = settings;
|
|
23366
23434
|
this.session = new Session_1.Session();
|
|
23367
23435
|
this._initialSettings = config.initialSettings;
|
|
@@ -23513,8 +23581,75 @@ const LoveLetters_1 = __webpack_require__(4572);
|
|
|
23513
23581
|
const ArcwareLogoLoader_1 = __webpack_require__(6469);
|
|
23514
23582
|
const MicrophoneOverlay_1 = __webpack_require__(3613);
|
|
23515
23583
|
const ConnectionIdentifier_1 = __webpack_require__(5999);
|
|
23516
|
-
const DiagnosticsCollector_1 = __webpack_require__(
|
|
23584
|
+
const DiagnosticsCollector_1 = __webpack_require__(8429);
|
|
23517
23585
|
class ArcwarePixelStreaming extends lib_pixelstreamingfrontend_ue5_5_1.PixelStreaming {
|
|
23586
|
+
bindTransportEvents() {
|
|
23587
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
23588
|
+
const current = (_a = this.webRtcController) === null || _a === void 0 ? void 0 : _a.transport;
|
|
23589
|
+
if (!current || current === this._boundTransport)
|
|
23590
|
+
return;
|
|
23591
|
+
// Unbind from previous
|
|
23592
|
+
if (this._boundTransport) {
|
|
23593
|
+
if (this._onWsOpen)
|
|
23594
|
+
(_c = (_b = this._boundTransport).removeEventListener) === null || _c === void 0 ? void 0 : _c.call(_b, "open", this._onWsOpen);
|
|
23595
|
+
if (this._onWsClose)
|
|
23596
|
+
(_e = (_d = this._boundTransport).removeEventListener) === null || _e === void 0 ? void 0 : _e.call(_d, "close", this._onWsClose);
|
|
23597
|
+
}
|
|
23598
|
+
// Define (or reuse) callbacks
|
|
23599
|
+
if (!this._onWsOpen) {
|
|
23600
|
+
this._onWsOpen = () => {
|
|
23601
|
+
this.flushOutbox();
|
|
23602
|
+
// fallback nudge for videoInitialized
|
|
23603
|
+
if (!this.videoInitializedSent)
|
|
23604
|
+
setTimeout(() => this.sendVideoInitializedOnce(), 150);
|
|
23605
|
+
};
|
|
23606
|
+
}
|
|
23607
|
+
if (!this._onWsClose) {
|
|
23608
|
+
this._onWsClose = (evt) => {
|
|
23609
|
+
// Bubble to your public close handler
|
|
23610
|
+
EventHandler_1.EventHandler.Emit(this.websocketOnCloseHandler, evt);
|
|
23611
|
+
};
|
|
23612
|
+
}
|
|
23613
|
+
// Bind to current
|
|
23614
|
+
(_f = current.addEventListener) === null || _f === void 0 ? void 0 : _f.call(current, "open", this._onWsOpen);
|
|
23615
|
+
(_g = current.addEventListener) === null || _g === void 0 ? void 0 : _g.call(current, "close", this._onWsClose);
|
|
23616
|
+
this._boundTransport = current;
|
|
23617
|
+
}
|
|
23618
|
+
startTransportWatcher() {
|
|
23619
|
+
// Rebind if the transport object reference changes (cheap safety net)
|
|
23620
|
+
if (this._transportWatchTimer)
|
|
23621
|
+
return;
|
|
23622
|
+
this._transportWatchTimer = window.setInterval(() => {
|
|
23623
|
+
var _a;
|
|
23624
|
+
const cur = (_a = this.webRtcController) === null || _a === void 0 ? void 0 : _a.transport;
|
|
23625
|
+
if (cur && cur !== this._boundTransport)
|
|
23626
|
+
this.bindTransportEvents();
|
|
23627
|
+
}, 3000); // light-touch; adjust if you like
|
|
23628
|
+
}
|
|
23629
|
+
stopTransportWatcher() {
|
|
23630
|
+
if (this._transportWatchTimer) {
|
|
23631
|
+
window.clearInterval(this._transportWatchTimer);
|
|
23632
|
+
this._transportWatchTimer = undefined;
|
|
23633
|
+
}
|
|
23634
|
+
}
|
|
23635
|
+
bindVideoElPlayingOnce() {
|
|
23636
|
+
var _a, _b, _c;
|
|
23637
|
+
const videoEl = (_c = (_b = (_a = this === null || this === void 0 ? void 0 : this.webRtcController) === null || _a === void 0 ? void 0 : _a.videoPlayer) === null || _b === void 0 ? void 0 : _b.getVideoElement) === null || _c === void 0 ? void 0 : _c.call(_b);
|
|
23638
|
+
if (!videoEl || videoEl === this._boundVideoEl)
|
|
23639
|
+
return;
|
|
23640
|
+
// Unbind older one if replaced
|
|
23641
|
+
if (this._boundVideoEl && this._onVideoPlaying) {
|
|
23642
|
+
this._boundVideoEl.removeEventListener("playing", this._onVideoPlaying);
|
|
23643
|
+
}
|
|
23644
|
+
this._onVideoPlaying = () => this.sendVideoInitializedOnce();
|
|
23645
|
+
videoEl.addEventListener("playing", this._onVideoPlaying, { once: true });
|
|
23646
|
+
this._boundVideoEl = videoEl;
|
|
23647
|
+
}
|
|
23648
|
+
get isWsOpen() {
|
|
23649
|
+
var _a, _b;
|
|
23650
|
+
const ws = (_b = (_a = this.webRtcController) === null || _a === void 0 ? void 0 : _a.transport) === null || _b === void 0 ? void 0 : _b.webSocket;
|
|
23651
|
+
return !!ws && ws.readyState === WebSocket.OPEN;
|
|
23652
|
+
}
|
|
23518
23653
|
/** Returns a list of WebSocketStates of all PixelStreaming Instances generated. */
|
|
23519
23654
|
get WebsocketStates() {
|
|
23520
23655
|
return ConnectionIdentifier_1.ConnectionIdentifier.Instance.GetWebSocketStates();
|
|
@@ -23530,11 +23665,18 @@ class ArcwarePixelStreaming extends lib_pixelstreamingfrontend_ue5_5_1.PixelStre
|
|
|
23530
23665
|
return state !== undefined ? state : WebSocket.CLOSED;
|
|
23531
23666
|
}
|
|
23532
23667
|
constructor(config, overrides) {
|
|
23668
|
+
var _a, _b, _c;
|
|
23533
23669
|
/** As soon as upstream is fixed, we got to adjust the url building process. */
|
|
23534
23670
|
(0, ApplyUrlHack_1.ApplyUrlHack)();
|
|
23535
23671
|
super(config, overrides);
|
|
23536
23672
|
this.loveLettersQueue = [];
|
|
23537
23673
|
this.isProcessingQueue = false;
|
|
23674
|
+
// --- reliable send / idempotence ---
|
|
23675
|
+
this.outbox = [];
|
|
23676
|
+
this.retryTimers = new Map(); // reserved if you later add ACKs
|
|
23677
|
+
this.videoInitializedSent = false;
|
|
23678
|
+
this.versionReplyInFlight = false;
|
|
23679
|
+
this.nextMsgId = 1;
|
|
23538
23680
|
// Externalized
|
|
23539
23681
|
/** On ping the session creation timestamp will be updated. */
|
|
23540
23682
|
this.queueHandler = new EventHandler_1.EventHandler();
|
|
@@ -23557,13 +23699,29 @@ class ArcwarePixelStreaming extends lib_pixelstreamingfrontend_ue5_5_1.PixelStre
|
|
|
23557
23699
|
// const signallingServerUrl = this.config.getTextSettingValue(TextParameters.SignallingServerUrl);
|
|
23558
23700
|
// return signallingServerUrl + "?" + this.config.urlFlags;
|
|
23559
23701
|
// });
|
|
23702
|
+
const transport = (_a = this.webRtcController) === null || _a === void 0 ? void 0 : _a.transport;
|
|
23703
|
+
(_b = transport === null || transport === void 0 ? void 0 : transport.addEventListener) === null || _b === void 0 ? void 0 : _b.call(transport, "open", () => {
|
|
23704
|
+
this.flushOutbox();
|
|
23705
|
+
});
|
|
23706
|
+
(_c = transport === null || transport === void 0 ? void 0 : transport.addEventListener) === null || _c === void 0 ? void 0 : _c.call(transport, "close", (evt) => {
|
|
23707
|
+
// Bubble to your public close handler if you expose one
|
|
23708
|
+
if (this.websocketOnCloseHandler) {
|
|
23709
|
+
EventHandler_1.EventHandler.Emit(this.websocketOnCloseHandler, evt);
|
|
23710
|
+
}
|
|
23711
|
+
});
|
|
23712
|
+
this.setupVideoInitFallbacks();
|
|
23560
23713
|
// Set override config.
|
|
23561
23714
|
this.config = config;
|
|
23562
23715
|
this.loveLettersList = [];
|
|
23563
23716
|
this.microphoneOverlay = new MicrophoneOverlay_1.MicrophoneOverlay(this);
|
|
23564
23717
|
this.diagnosticsCollector = new DiagnosticsCollector_1.DiagnosticsCollector({
|
|
23565
|
-
enableBandwidthProbe: false
|
|
23718
|
+
enableBandwidthProbe: false
|
|
23566
23719
|
});
|
|
23720
|
+
// after super(...) and once webRtcController is available
|
|
23721
|
+
this.bindTransportEvents();
|
|
23722
|
+
this.startTransportWatcher();
|
|
23723
|
+
// ensure video 'playing' fallback is attached to the current element
|
|
23724
|
+
this.bindVideoElPlayingOnce();
|
|
23567
23725
|
// this.loveLettersContainer = null;
|
|
23568
23726
|
this.wrapWebSocketOnCloseHandler();
|
|
23569
23727
|
// Bind the event listener function to the class instance
|
|
@@ -23590,7 +23748,7 @@ class ArcwarePixelStreaming extends lib_pixelstreamingfrontend_ue5_5_1.PixelStre
|
|
|
23590
23748
|
this.webRtcController.streamMessageController.registerMessageHandler(0, // MessageDirection.ToStreamer,
|
|
23591
23749
|
"TextboxEntry", (messageData) => {
|
|
23592
23750
|
try {
|
|
23593
|
-
this.webRtcController.sendMessageController.sendMessageToStreamer(
|
|
23751
|
+
this.webRtcController.sendMessageController.sendMessageToStreamer("TextboxEntry", messageData);
|
|
23594
23752
|
}
|
|
23595
23753
|
catch (e) {
|
|
23596
23754
|
console.error(`Error: ToStreamer.TextboxEntry`, e);
|
|
@@ -23621,10 +23779,26 @@ class ArcwarePixelStreaming extends lib_pixelstreamingfrontend_ue5_5_1.PixelStre
|
|
|
23621
23779
|
* * * * * * *
|
|
23622
23780
|
*/
|
|
23623
23781
|
/** On version requested, the version of the WebSDK would be returned. */
|
|
23624
|
-
onVersion(
|
|
23782
|
+
onVersion(_msg) {
|
|
23783
|
+
var _a, _b;
|
|
23625
23784
|
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
23626
|
-
|
|
23627
|
-
|
|
23785
|
+
let diagnostics;
|
|
23786
|
+
try {
|
|
23787
|
+
diagnostics = yield this.diagnosticsCollector.collect();
|
|
23788
|
+
}
|
|
23789
|
+
catch (e) {
|
|
23790
|
+
(_a = lib_pixelstreamingfrontend_ue5_5_1.Logger.Warning) === null || _a === void 0 ? void 0 : _a.call(lib_pixelstreamingfrontend_ue5_5_1.Logger, `Diagnostics collection failed: ${(_b = e === null || e === void 0 ? void 0 : e.message) !== null && _b !== void 0 ? _b : e}`);
|
|
23791
|
+
}
|
|
23792
|
+
finally {
|
|
23793
|
+
// Build payload with required fields only; append diagnostics if available
|
|
23794
|
+
const payload = {
|
|
23795
|
+
type: "version",
|
|
23796
|
+
version: this.config.VERSION
|
|
23797
|
+
};
|
|
23798
|
+
if (diagnostics !== undefined)
|
|
23799
|
+
payload.diagnostics = diagnostics;
|
|
23800
|
+
this.send(payload); // uses your buffered send
|
|
23801
|
+
}
|
|
23628
23802
|
});
|
|
23629
23803
|
}
|
|
23630
23804
|
/** On ping the session creation timestamp will be updated. */
|
|
@@ -23691,16 +23865,67 @@ class ArcwarePixelStreaming extends lib_pixelstreamingfrontend_ue5_5_1.PixelStre
|
|
|
23691
23865
|
this.session.set(message.sessionId);
|
|
23692
23866
|
EventHandler_1.EventHandler.Emit(this.sessionIdHandler, message.sessionId);
|
|
23693
23867
|
}
|
|
23868
|
+
sendVideoInitializedOnce() {
|
|
23869
|
+
if (this.videoInitializedSent)
|
|
23870
|
+
return;
|
|
23871
|
+
this.videoInitializedSent = true;
|
|
23872
|
+
// Use withId if you plan to support idempotence on the server
|
|
23873
|
+
this.send(/* this.withId( */ { type: "onVideoInitialized" } /* ) */);
|
|
23874
|
+
if (this.videoInitializedHandler) {
|
|
23875
|
+
EventHandler_1.EventHandler.Emit(this.videoInitializedHandler, undefined);
|
|
23876
|
+
}
|
|
23877
|
+
}
|
|
23878
|
+
// Attach fallbacks once (call this in constructor after transport wiring)
|
|
23879
|
+
setupVideoInitFallbacks() {
|
|
23880
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
23881
|
+
// Fallback #1: HTMLVideoElement 'playing'
|
|
23882
|
+
const videoEl = (_c = (_b = (_a = this.webRtcController) === null || _a === void 0 ? void 0 : _a.videoPlayer) === null || _b === void 0 ? void 0 : _b.getVideoElement) === null || _c === void 0 ? void 0 : _c.call(_b);
|
|
23883
|
+
(_d = videoEl === null || videoEl === void 0 ? void 0 : videoEl.addEventListener) === null || _d === void 0 ? void 0 : _d.call(videoEl, "playing", () => this.sendVideoInitializedOnce(), { once: true });
|
|
23884
|
+
// Fallback #2: stats hook (if you emit one)
|
|
23885
|
+
(_e = this.addEventListener) === null || _e === void 0 ? void 0 : _e.call(this, "statsReceived", (e) => {
|
|
23886
|
+
var _a, _b;
|
|
23887
|
+
const stats = e === null || e === void 0 ? void 0 : e.detail;
|
|
23888
|
+
if (!this.videoInitializedSent && ((_b = (_a = stats === null || stats === void 0 ? void 0 : stats.video) === null || _a === void 0 ? void 0 : _a.framesDecoded) !== null && _b !== void 0 ? _b : 0) > 0) {
|
|
23889
|
+
this.sendVideoInitializedOnce();
|
|
23890
|
+
}
|
|
23891
|
+
});
|
|
23892
|
+
// Fallback #3: after socket opens, give it a tick
|
|
23893
|
+
const transport = (_f = this.webRtcController) === null || _f === void 0 ? void 0 : _f.transport;
|
|
23894
|
+
(_g = transport === null || transport === void 0 ? void 0 : transport.addEventListener) === null || _g === void 0 ? void 0 : _g.call(transport, "open", () => {
|
|
23895
|
+
if (!this.videoInitializedSent) {
|
|
23896
|
+
setTimeout(() => this.sendVideoInitializedOnce(), 150);
|
|
23897
|
+
}
|
|
23898
|
+
});
|
|
23899
|
+
}
|
|
23694
23900
|
onVideoInitialized() {
|
|
23695
|
-
|
|
23696
|
-
|
|
23697
|
-
this.
|
|
23698
|
-
|
|
23699
|
-
|
|
23700
|
-
|
|
23701
|
-
|
|
23702
|
-
|
|
23703
|
-
|
|
23901
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
23902
|
+
// send early and once
|
|
23903
|
+
this.sendVideoInitializedOnce();
|
|
23904
|
+
// keep side-effects guarded so they can't break the send
|
|
23905
|
+
try {
|
|
23906
|
+
(_a = this.handleMouseLock) === null || _a === void 0 ? void 0 : _a.call(this);
|
|
23907
|
+
}
|
|
23908
|
+
catch (_h) { }
|
|
23909
|
+
try {
|
|
23910
|
+
(_b = this.handleResolutionChange) === null || _b === void 0 ? void 0 : _b.call(this);
|
|
23911
|
+
}
|
|
23912
|
+
catch (_j) { }
|
|
23913
|
+
try {
|
|
23914
|
+
(_c = this.handleRemoveLoveLetters) === null || _c === void 0 ? void 0 : _c.call(this);
|
|
23915
|
+
}
|
|
23916
|
+
catch (_k) { }
|
|
23917
|
+
try {
|
|
23918
|
+
(_e = (_d = this.microphoneOverlay) === null || _d === void 0 ? void 0 : _d.toggleVisibility) === null || _e === void 0 ? void 0 : _e.call(_d, false);
|
|
23919
|
+
}
|
|
23920
|
+
catch (_l) { }
|
|
23921
|
+
try {
|
|
23922
|
+
(_f = this.applyResolutionIfPlaying) === null || _f === void 0 ? void 0 : _f.call(this);
|
|
23923
|
+
}
|
|
23924
|
+
catch (_m) { }
|
|
23925
|
+
try {
|
|
23926
|
+
(_g = this.removeXRIconIfDisabled) === null || _g === void 0 ? void 0 : _g.call(this);
|
|
23927
|
+
}
|
|
23928
|
+
catch (_o) { }
|
|
23704
23929
|
}
|
|
23705
23930
|
/** Adding a zod-safe handler. */
|
|
23706
23931
|
addMessageHandler(type, zod, boundMethod) {
|
|
@@ -23715,7 +23940,7 @@ class ArcwarePixelStreaming extends lib_pixelstreamingfrontend_ue5_5_1.PixelStre
|
|
|
23715
23940
|
lib_pixelstreamingfrontend_ue5_5_1.Logger.Error(error.message);
|
|
23716
23941
|
}
|
|
23717
23942
|
if (type === "error") {
|
|
23718
|
-
this.disconnect();
|
|
23943
|
+
//this.disconnect();
|
|
23719
23944
|
}
|
|
23720
23945
|
});
|
|
23721
23946
|
}
|
|
@@ -23729,19 +23954,48 @@ class ArcwarePixelStreaming extends lib_pixelstreamingfrontend_ue5_5_1.PixelStre
|
|
|
23729
23954
|
// This cast has to be done, since Frontend does not use typescript-strict setting.
|
|
23730
23955
|
this.send(message);
|
|
23731
23956
|
}
|
|
23732
|
-
send(
|
|
23733
|
-
|
|
23734
|
-
|
|
23735
|
-
|
|
23736
|
-
|
|
23737
|
-
|
|
23738
|
-
|
|
23739
|
-
|
|
23740
|
-
lib_pixelstreamingfrontend_ue5_5_1.Logger.Error(`
|
|
23957
|
+
send(a, b) {
|
|
23958
|
+
var _a, _b;
|
|
23959
|
+
const msg = typeof a === "string" ? Object.assign({ type: a }, (b !== null && b !== void 0 ? b : {})) : a;
|
|
23960
|
+
// Optional zod validation if you have schemas for this type
|
|
23961
|
+
const schema = (_a = shared_pixelstreaming_websdk_1.Messages.Send) === null || _a === void 0 ? void 0 : _a[msg.type];
|
|
23962
|
+
if (schema) {
|
|
23963
|
+
const result = schema.safeParse(msg);
|
|
23964
|
+
if (!result.success) {
|
|
23965
|
+
(_b = lib_pixelstreamingfrontend_ue5_5_1.Logger.Error) === null || _b === void 0 ? void 0 : _b.call(lib_pixelstreamingfrontend_ue5_5_1.Logger, `Send validation failed for ${msg.type}: ${result.error}`);
|
|
23966
|
+
return;
|
|
23741
23967
|
}
|
|
23968
|
+
this._dispatchOrBuffer(result.data);
|
|
23742
23969
|
}
|
|
23743
23970
|
else {
|
|
23744
|
-
this.
|
|
23971
|
+
this._dispatchOrBuffer(msg);
|
|
23972
|
+
}
|
|
23973
|
+
}
|
|
23974
|
+
_dispatchOrBuffer(message) {
|
|
23975
|
+
if (this.isWsOpen) {
|
|
23976
|
+
try {
|
|
23977
|
+
this.signallingProtocol.sendMessage(message);
|
|
23978
|
+
return;
|
|
23979
|
+
}
|
|
23980
|
+
catch (_a) {
|
|
23981
|
+
// fallthrough to buffer
|
|
23982
|
+
}
|
|
23983
|
+
}
|
|
23984
|
+
this.outbox.push(message);
|
|
23985
|
+
}
|
|
23986
|
+
flushOutbox() {
|
|
23987
|
+
if (!this.isWsOpen || this.outbox.length === 0)
|
|
23988
|
+
return;
|
|
23989
|
+
const batch = this.outbox.splice(0, this.outbox.length);
|
|
23990
|
+
for (const m of batch) {
|
|
23991
|
+
try {
|
|
23992
|
+
this.signallingProtocol.sendMessage(m);
|
|
23993
|
+
}
|
|
23994
|
+
catch (_a) {
|
|
23995
|
+
// if we fail mid-flush, put remaining back and bail
|
|
23996
|
+
this.outbox.unshift(m, ...batch.slice(batch.indexOf(m) + 1));
|
|
23997
|
+
break;
|
|
23998
|
+
}
|
|
23745
23999
|
}
|
|
23746
24000
|
}
|
|
23747
24001
|
handleResolutionChange() {
|
|
@@ -23805,7 +24059,18 @@ class ArcwarePixelStreaming extends lib_pixelstreamingfrontend_ue5_5_1.PixelStre
|
|
|
23805
24059
|
}
|
|
23806
24060
|
}
|
|
23807
24061
|
removePlayer() {
|
|
23808
|
-
|
|
24062
|
+
var _a, _b, _c, _d;
|
|
24063
|
+
this.stopTransportWatcher();
|
|
24064
|
+
// Optional: unbind handlers
|
|
24065
|
+
if (this._boundTransport) {
|
|
24066
|
+
if (this._onWsOpen)
|
|
24067
|
+
(_b = (_a = this._boundTransport).removeEventListener) === null || _b === void 0 ? void 0 : _b.call(_a, "open", this._onWsOpen);
|
|
24068
|
+
if (this._onWsClose)
|
|
24069
|
+
(_d = (_c = this._boundTransport).removeEventListener) === null || _d === void 0 ? void 0 : _d.call(_c, "close", this._onWsClose);
|
|
24070
|
+
}
|
|
24071
|
+
if (this._boundVideoEl && this._onVideoPlaying) {
|
|
24072
|
+
this._boundVideoEl.removeEventListener("playing", this._onVideoPlaying);
|
|
24073
|
+
}
|
|
23809
24074
|
this.disconnect();
|
|
23810
24075
|
}
|
|
23811
24076
|
handleMouseLock() {
|
|
@@ -23903,11 +24168,11 @@ class ArcwarePixelStreaming extends lib_pixelstreamingfrontend_ue5_5_1.PixelStre
|
|
|
23903
24168
|
(_a = this === null || this === void 0 ? void 0 : this.config) === null || _a === void 0 ? void 0 : _a.setFlagEnabled(lib_pixelstreamingfrontend_ue5_5_1.Flags.UseMic, enable);
|
|
23904
24169
|
if (!isDefault) {
|
|
23905
24170
|
(_b = this === null || this === void 0 ? void 0 : this.microphoneOverlay) === null || _b === void 0 ? void 0 : _b.toggleMessage(enable);
|
|
24171
|
+
setTimeout(() => { var _a; return (_a = this === null || this === void 0 ? void 0 : this.microphoneOverlay) === null || _a === void 0 ? void 0 : _a.toggleVisibility(true); }, 200);
|
|
23906
24172
|
setTimeout(() => {
|
|
23907
|
-
|
|
23908
|
-
|
|
23909
|
-
|
|
23910
|
-
setTimeout(() => {
|
|
24173
|
+
this.videoInitializedSent = false; // <-- reset before a real media restart
|
|
24174
|
+
this.bindVideoElPlayingOnce(); // in case a new element will appear
|
|
24175
|
+
this.bindTransportEvents(); // cheap rebind now
|
|
23911
24176
|
this.reconnect();
|
|
23912
24177
|
}, 1000);
|
|
23913
24178
|
}
|
|
@@ -23959,767 +24224,959 @@ exports.ArcwarePixelStreaming = ArcwarePixelStreaming;
|
|
|
23959
24224
|
|
|
23960
24225
|
/***/ }),
|
|
23961
24226
|
|
|
23962
|
-
/***/
|
|
24227
|
+
/***/ 5602:
|
|
23963
24228
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
23964
24229
|
|
|
23965
24230
|
|
|
23966
|
-
/**
|
|
23967
|
-
* DiagnosticsCollector.ts
|
|
23968
|
-
* Lightweight, privacy-aware client diagnostics for troubleshooting + analytics.
|
|
23969
|
-
* WebRTC collection intentionally omitted (to add later).
|
|
23970
|
-
*
|
|
23971
|
-
* Notes:
|
|
23972
|
-
* - Some fields are best-effort due to browser restrictions; they're nullable.
|
|
23973
|
-
* - Bandwidth probe requires a small binary served with:
|
|
23974
|
-
* Content-Type: application/octet-stream
|
|
23975
|
-
* Content-Encoding: identity
|
|
23976
|
-
* Cache-Control: no-store
|
|
23977
|
-
* Default location: /diag/probe.bin
|
|
23978
|
-
*/
|
|
23979
24231
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
23980
|
-
exports.
|
|
23981
|
-
const
|
|
23982
|
-
|
|
23983
|
-
|
|
23984
|
-
|
|
23985
|
-
|
|
23986
|
-
|
|
23987
|
-
|
|
23988
|
-
|
|
23989
|
-
|
|
23990
|
-
|
|
23991
|
-
|
|
23992
|
-
|
|
23993
|
-
/**
|
|
23994
|
-
|
|
23995
|
-
*/
|
|
23996
|
-
|
|
23997
|
-
|
|
23998
|
-
|
|
23999
|
-
|
|
24000
|
-
|
|
24001
|
-
|
|
24002
|
-
|
|
24003
|
-
|
|
24004
|
-
|
|
24005
|
-
|
|
24232
|
+
exports.ArcwareSettingsSchema = void 0;
|
|
24233
|
+
const zod_1 = __webpack_require__(8754);
|
|
24234
|
+
const shared_pixelstreaming_websdk_1 = __webpack_require__(7910);
|
|
24235
|
+
/** Arcware Settings. */
|
|
24236
|
+
exports.ArcwareSettingsSchema = zod_1.z.object({
|
|
24237
|
+
/** Overwrites the Session-Tool and uses the provided session instead. */
|
|
24238
|
+
session: zod_1.z.string().optional(),
|
|
24239
|
+
/** Can be used to be added to the request in order to verify access to private projects.
|
|
24240
|
+
* For internal use only. => Preview page.
|
|
24241
|
+
*/
|
|
24242
|
+
token: zod_1.z.string().optional(),
|
|
24243
|
+
/** @deprecated in there for legacy use. Can only be used when token is provided. */
|
|
24244
|
+
bypass: zod_1.z.boolean().optional(),
|
|
24245
|
+
// /** Configure DirectFlow Token. */
|
|
24246
|
+
// directFlow: z.string().optional(),
|
|
24247
|
+
/** Handler for server side error messages. */
|
|
24248
|
+
errorHandler: zod_1.z.function().args(shared_pixelstreaming_websdk_1.Messages.ZErrorMessage).returns(zod_1.z.void()).optional(),
|
|
24249
|
+
/** Handler for queue events. */
|
|
24250
|
+
queueHandler: zod_1.z.function().args(shared_pixelstreaming_websdk_1.Messages.ZQueue).returns(zod_1.z.void()).optional(),
|
|
24251
|
+
/** Handler for sessionId message. */
|
|
24252
|
+
sessionIdHandler: zod_1.z.function().args(zod_1.z.string()).returns(zod_1.z.void()).optional(),
|
|
24253
|
+
/** Handler for love letters.
|
|
24254
|
+
* "LoveLetters" are send from backend to the SDK to state what phase the connection currently is in. */
|
|
24255
|
+
loveLetterHandler: zod_1.z.function().args(shared_pixelstreaming_websdk_1.Messages.ZLoveLetter).returns(zod_1.z.void()).optional(),
|
|
24256
|
+
/** Show or hide the fullscreen button. */
|
|
24257
|
+
fullscreenButton: zod_1.z.boolean().optional(),
|
|
24258
|
+
/** Show or hide the settings button. */
|
|
24259
|
+
settingsButton: zod_1.z.boolean().optional(),
|
|
24260
|
+
/** Show or hide the info button. */
|
|
24261
|
+
infoButton: zod_1.z.boolean().optional(),
|
|
24262
|
+
/** Show or hide the audio button. */
|
|
24263
|
+
audioButton: zod_1.z.boolean().optional(),
|
|
24264
|
+
/** Show or hide the microphone button. */
|
|
24265
|
+
micButton: zod_1.z.boolean().optional(),
|
|
24266
|
+
/** Show or hide the microphone button. */
|
|
24267
|
+
stopButton: zod_1.z.boolean().optional(),
|
|
24268
|
+
/** Show or hide the connectionStrengthIcon button. */
|
|
24269
|
+
connectionStrengthIcon: zod_1.z.boolean().optional(),
|
|
24270
|
+
/** ShareId, used for sharing your project.
|
|
24271
|
+
* Using ArcwareInit will set this required property for you. */
|
|
24272
|
+
shareId: zod_1.z.string().startsWith("share-").optional(),
|
|
24273
|
+
/** Id of your project, only required if your shareId refers to multiple projects.
|
|
24274
|
+
* Using ArcwareInit will set this required property for you. */
|
|
24275
|
+
projectId: zod_1.z.string().optional(),
|
|
24276
|
+
/** Enable/Disable LoveLetter logging to the console. */
|
|
24277
|
+
loveLetterLogging: zod_1.z.boolean().optional(),
|
|
24278
|
+
/** Enable/Disable Connection Identifier logging to the console. */
|
|
24279
|
+
connectionIdentifierLoggingDisabled: zod_1.z.boolean().optional(),
|
|
24280
|
+
/** Width with which instance should be started */
|
|
24281
|
+
startWidth: zod_1.z.number().optional(),
|
|
24282
|
+
/** Height with which instance should be started */
|
|
24283
|
+
startHeight: zod_1.z.number().optional()
|
|
24284
|
+
});
|
|
24285
|
+
|
|
24286
|
+
|
|
24287
|
+
/***/ }),
|
|
24288
|
+
|
|
24289
|
+
/***/ 5999:
|
|
24290
|
+
/***/ ((__unused_webpack_module, exports) => {
|
|
24291
|
+
|
|
24292
|
+
|
|
24293
|
+
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
24294
|
+
exports.ConnectionIdentifier = exports.WebsocketState = void 0;
|
|
24295
|
+
var WebsocketState;
|
|
24296
|
+
(function (WebsocketState) {
|
|
24297
|
+
// Socket has been created. The connection is not yet open.
|
|
24298
|
+
WebsocketState[WebsocketState["CONNECTING"] = 0] = "CONNECTING";
|
|
24299
|
+
// The connection is open and ready to communicate.
|
|
24300
|
+
WebsocketState[WebsocketState["OPEN"] = 1] = "OPEN";
|
|
24301
|
+
// The connection is in the process of closing.
|
|
24302
|
+
WebsocketState[WebsocketState["CLOSING"] = 2] = "CLOSING";
|
|
24303
|
+
// The connection is closed or couldn't be opened.
|
|
24304
|
+
WebsocketState[WebsocketState["CLOSED"] = 3] = "CLOSED";
|
|
24305
|
+
})(WebsocketState = exports.WebsocketState || (exports.WebsocketState = {}));
|
|
24306
|
+
class ConnectionIdentifier {
|
|
24307
|
+
static get Instance() {
|
|
24308
|
+
if (!this.instance) {
|
|
24309
|
+
this.instance = new ConnectionIdentifier();
|
|
24310
|
+
}
|
|
24311
|
+
return this.instance;
|
|
24312
|
+
}
|
|
24313
|
+
get WebsocketStates() {
|
|
24314
|
+
return this.aps.map((ps) => ps.websocketState);
|
|
24315
|
+
}
|
|
24316
|
+
constructor() {
|
|
24317
|
+
this.aps = [];
|
|
24318
|
+
this.enabled = true;
|
|
24319
|
+
}
|
|
24320
|
+
register(ps) {
|
|
24321
|
+
var _a;
|
|
24322
|
+
if (!this.aps.includes(ps)) {
|
|
24323
|
+
this.aps.push(ps);
|
|
24324
|
+
if ((_a = ps.config.settings) === null || _a === void 0 ? void 0 : _a.connectionIdentifierLoggingDisabled)
|
|
24325
|
+
this.disable();
|
|
24326
|
+
}
|
|
24327
|
+
if (!this.interval)
|
|
24328
|
+
this.interval = setInterval(this.connectionWatcher.bind(this), 10 * 1000);
|
|
24329
|
+
}
|
|
24330
|
+
GetWebSocketStates() {
|
|
24331
|
+
return this.aps.map((ps) => ps.websocketState);
|
|
24332
|
+
}
|
|
24333
|
+
ActiveInstances() {
|
|
24334
|
+
return this.GetWebSocketStates().filter((state) => state <= WebsocketState.OPEN).length;
|
|
24335
|
+
}
|
|
24336
|
+
disable() {
|
|
24337
|
+
this.enabled = false;
|
|
24006
24338
|
}
|
|
24007
24339
|
/**
|
|
24008
|
-
*
|
|
24340
|
+
* The purpose of this method is to periodically tell the developer the amount of connected instances.
|
|
24341
|
+
* This way the developer can figure out, when they messed up the implementation and there's shadow instances still running.
|
|
24342
|
+
* Or when they accidentally set up multiple connections!
|
|
24343
|
+
* Things like that can happen, for example if the React.useEffect was not setup perfectly!
|
|
24009
24344
|
*/
|
|
24010
|
-
|
|
24011
|
-
|
|
24012
|
-
|
|
24013
|
-
|
|
24014
|
-
|
|
24015
|
-
|
|
24016
|
-
|
|
24017
|
-
|
|
24018
|
-
|
|
24019
|
-
|
|
24020
|
-
};
|
|
24021
|
-
}
|
|
24022
|
-
const collectedAt = Date.now();
|
|
24023
|
-
const [uaInfo, codecSupport, measuredDownlinkMbps] = yield Promise.all([
|
|
24024
|
-
this.getUAInfo(),
|
|
24025
|
-
this.getCodecSupport(),
|
|
24026
|
-
this.maybeMeasureBandwidth()
|
|
24027
|
-
]);
|
|
24028
|
-
return {
|
|
24029
|
-
device: {
|
|
24030
|
-
type: this.inferDeviceType(),
|
|
24031
|
-
vendor: null,
|
|
24032
|
-
model: uaInfo.model,
|
|
24033
|
-
architecture: uaInfo.architecture,
|
|
24034
|
-
bitness: uaInfo.bitness,
|
|
24035
|
-
touchSupport: this.hasTouch(),
|
|
24036
|
-
hardwareConcurrency: (_a = navigator.hardwareConcurrency) !== null && _a !== void 0 ? _a : null,
|
|
24037
|
-
deviceMemory: (_b = navigator.deviceMemory) !== null && _b !== void 0 ? _b : null,
|
|
24038
|
-
orientation: this.getOrientation(),
|
|
24039
|
-
webgl: this.hasWebGL(),
|
|
24040
|
-
codecs: codecSupport
|
|
24041
|
-
},
|
|
24042
|
-
runtime: {
|
|
24043
|
-
browser: { family: uaInfo.browserFamily, version: uaInfo.browserVersion },
|
|
24044
|
-
os: { family: uaInfo.osFamily, version: uaInfo.osVersion }
|
|
24045
|
-
},
|
|
24046
|
-
powerHints: this.getPowerHints(),
|
|
24047
|
-
network: this.getNetworkInfo(measuredDownlinkMbps),
|
|
24048
|
-
timestamps: { collectedAt }
|
|
24049
|
-
};
|
|
24050
|
-
});
|
|
24345
|
+
connectionWatcher() {
|
|
24346
|
+
if (!this.enabled)
|
|
24347
|
+
return;
|
|
24348
|
+
const activeStates = this.GetWebSocketStates().filter((state) => state <= WebsocketState.OPEN);
|
|
24349
|
+
if (activeStates.length === 1) {
|
|
24350
|
+
console.log(`PixelStreaming Instance is connected.`);
|
|
24351
|
+
}
|
|
24352
|
+
else if (activeStates.length !== 0) {
|
|
24353
|
+
console.warn(`${activeStates.length} PixelStreaming Instances are connected!`);
|
|
24354
|
+
}
|
|
24051
24355
|
}
|
|
24052
|
-
|
|
24053
|
-
|
|
24054
|
-
|
|
24055
|
-
|
|
24056
|
-
|
|
24057
|
-
|
|
24058
|
-
|
|
24059
|
-
|
|
24060
|
-
|
|
24061
|
-
|
|
24062
|
-
|
|
24063
|
-
|
|
24064
|
-
|
|
24065
|
-
|
|
24066
|
-
|
|
24067
|
-
|
|
24068
|
-
|
|
24069
|
-
|
|
24070
|
-
|
|
24071
|
-
|
|
24072
|
-
|
|
24073
|
-
localCandidateType: (_b = local === null || local === void 0 ? void 0 : local.candidateType) !== null && _b !== void 0 ? _b : null,
|
|
24074
|
-
remoteCandidateType: (_c = remote === null || remote === void 0 ? void 0 : remote.candidateType) !== null && _c !== void 0 ? _c : null,
|
|
24075
|
-
protocol: (_d = local === null || local === void 0 ? void 0 : local.protocol) !== null && _d !== void 0 ? _d : null,
|
|
24076
|
-
networkType: (_e = local === null || local === void 0 ? void 0 : local.networkType) !== null && _e !== void 0 ? _e : null,
|
|
24077
|
-
dtlsCipher: (_f = transport === null || transport === void 0 ? void 0 : transport.dtlsCipher) !== null && _f !== void 0 ? _f : null
|
|
24078
|
-
};
|
|
24079
|
-
}
|
|
24080
|
-
catch (_g) {
|
|
24081
|
-
return {};
|
|
24082
|
-
}
|
|
24083
|
-
});
|
|
24356
|
+
}
|
|
24357
|
+
exports.ConnectionIdentifier = ConnectionIdentifier;
|
|
24358
|
+
|
|
24359
|
+
|
|
24360
|
+
/***/ }),
|
|
24361
|
+
|
|
24362
|
+
/***/ 3379:
|
|
24363
|
+
/***/ ((__unused_webpack_module, exports) => {
|
|
24364
|
+
|
|
24365
|
+
|
|
24366
|
+
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
24367
|
+
exports.EventHandler = void 0;
|
|
24368
|
+
/** A helper class to spread the event to additional event handlers added from external sources. */
|
|
24369
|
+
class EventHandler {
|
|
24370
|
+
/** Returns the added callback on success or null, if something went wrong. */
|
|
24371
|
+
add(callback) {
|
|
24372
|
+
const cb = this.callbacks.find((cb) => cb === callback);
|
|
24373
|
+
if (cb)
|
|
24374
|
+
return null;
|
|
24375
|
+
this.callbacks.push(callback);
|
|
24376
|
+
return callback;
|
|
24084
24377
|
}
|
|
24085
|
-
/**
|
|
24086
|
-
|
|
24087
|
-
|
|
24088
|
-
|
|
24089
|
-
|
|
24090
|
-
|
|
24091
|
-
const webrtc = pc ? yield this.collectWebRTC(pc) : undefined;
|
|
24092
|
-
const ext = webrtc ? { diag: Object.assign(Object.assign({}, diag), { webrtc }) } : { diag };
|
|
24093
|
-
return Object.assign(Object.assign({}, base), { ext });
|
|
24094
|
-
});
|
|
24378
|
+
/** Returns true if the input callback has been found and removed and false if not. */
|
|
24379
|
+
remove(callback) {
|
|
24380
|
+
const cb = this.callbacks.find((cb) => cb === callback);
|
|
24381
|
+
if (cb)
|
|
24382
|
+
this.callbacks.splice(this.callbacks.indexOf(cb), 1);
|
|
24383
|
+
return !!cb;
|
|
24095
24384
|
}
|
|
24096
|
-
|
|
24097
|
-
|
|
24098
|
-
if (this.opts.sampleRate >= 1)
|
|
24099
|
-
return true;
|
|
24100
|
-
return Math.random() < this.opts.sampleRate;
|
|
24385
|
+
constructor() {
|
|
24386
|
+
this.callbacks = new Array();
|
|
24101
24387
|
}
|
|
24102
|
-
|
|
24103
|
-
|
|
24104
|
-
|
|
24105
|
-
return "ontouchstart" in window || ((_a = nav.maxTouchPoints) !== null && _a !== void 0 ? _a : 0) > 0;
|
|
24388
|
+
/** Emits the event-data for each of the existing handlers. */
|
|
24389
|
+
static Emit(handler, event) {
|
|
24390
|
+
handler.callbacks.forEach((callback) => callback(event));
|
|
24106
24391
|
}
|
|
24107
|
-
|
|
24108
|
-
|
|
24109
|
-
|
|
24110
|
-
|
|
24111
|
-
|
|
24112
|
-
|
|
24113
|
-
|
|
24114
|
-
|
|
24115
|
-
|
|
24116
|
-
|
|
24117
|
-
|
|
24118
|
-
|
|
24392
|
+
}
|
|
24393
|
+
exports.EventHandler = EventHandler;
|
|
24394
|
+
|
|
24395
|
+
|
|
24396
|
+
/***/ }),
|
|
24397
|
+
|
|
24398
|
+
/***/ 2469:
|
|
24399
|
+
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
24400
|
+
|
|
24401
|
+
|
|
24402
|
+
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
24403
|
+
exports.Session = void 0;
|
|
24404
|
+
const addSeconds_1 = __webpack_require__(1973);
|
|
24405
|
+
const isBefore_1 = __webpack_require__(313);
|
|
24406
|
+
const zod_1 = __webpack_require__(8754);
|
|
24407
|
+
const ZSession = zod_1.z
|
|
24408
|
+
.object({
|
|
24409
|
+
id: zod_1.z.string().min(1),
|
|
24410
|
+
created: zod_1.z
|
|
24411
|
+
.date()
|
|
24412
|
+
.or(zod_1.z.string())
|
|
24413
|
+
.transform((arg) => new Date(arg)),
|
|
24414
|
+
expire: zod_1.z.boolean().default(false).optional(),
|
|
24415
|
+
})
|
|
24416
|
+
.strict();
|
|
24417
|
+
const ZOptions = zod_1.z.object({
|
|
24418
|
+
localStorageKey: zod_1.z.string().min(3).default("pxss"),
|
|
24419
|
+
keepSession: zod_1.z
|
|
24420
|
+
.number()
|
|
24421
|
+
.int()
|
|
24422
|
+
.min(3)
|
|
24423
|
+
/** Default keep is 10, since this is how long instances will be kept alive by default. */
|
|
24424
|
+
.default(10),
|
|
24425
|
+
});
|
|
24426
|
+
/** The sessionId is stored in the localStorage to allow for reconnection and
|
|
24427
|
+
* to prevent spamming start requests of instances, when smashing F5.
|
|
24428
|
+
*/
|
|
24429
|
+
class Session {
|
|
24430
|
+
get current() {
|
|
24431
|
+
return this._current;
|
|
24119
24432
|
}
|
|
24120
|
-
|
|
24121
|
-
|
|
24122
|
-
const canvas = document.createElement("canvas");
|
|
24123
|
-
return !!(canvas.getContext("webgl") || canvas.getContext("experimental-webgl"));
|
|
24124
|
-
}
|
|
24125
|
-
catch (_a) {
|
|
24126
|
-
return false;
|
|
24127
|
-
}
|
|
24433
|
+
get noSession() {
|
|
24434
|
+
return new URLSearchParams(window.location.search).has("noSession");
|
|
24128
24435
|
}
|
|
24129
|
-
|
|
24130
|
-
|
|
24131
|
-
|
|
24132
|
-
|
|
24133
|
-
|
|
24134
|
-
|
|
24135
|
-
|
|
24136
|
-
|
|
24137
|
-
const minDim = Math.min(screen.width, screen.height);
|
|
24138
|
-
// 1. Explicit iPad / tablet detection via UA (iOS often lies in CH)
|
|
24139
|
-
if (/\b(iPad|Tablet)\b/i.test(ua)) {
|
|
24140
|
-
return Type.Tablet;
|
|
24141
|
-
}
|
|
24142
|
-
// 2. UA-CH mobile hint (Chromium only, often accurate for Android)
|
|
24143
|
-
if (isMobileCH) {
|
|
24144
|
-
if (minDim >= 600)
|
|
24145
|
-
return Type.Tablet;
|
|
24146
|
-
return Type.Mobile;
|
|
24147
|
-
}
|
|
24148
|
-
// 3. UA sniffing fallback for mobile
|
|
24149
|
-
if (/\b(iPhone|Android.*Mobile|Windows Phone)\b/i.test(ua)) {
|
|
24150
|
-
return Type.Mobile;
|
|
24436
|
+
get id() {
|
|
24437
|
+
// If the query-parameter "noSession" or "nosession" is set, it will be skipped.
|
|
24438
|
+
if (this.noSession)
|
|
24439
|
+
return null;
|
|
24440
|
+
const sessionString = window.localStorage.getItem(this.localStorageKey);
|
|
24441
|
+
// No session yet set.
|
|
24442
|
+
if (sessionString === null) {
|
|
24443
|
+
return null;
|
|
24151
24444
|
}
|
|
24152
|
-
|
|
24153
|
-
|
|
24154
|
-
|
|
24445
|
+
const parsed = ZSession.safeParse(JSON.parse(sessionString));
|
|
24446
|
+
// Clear the session if it's not valid.
|
|
24447
|
+
if (!parsed.success) {
|
|
24448
|
+
this.unset();
|
|
24449
|
+
return null;
|
|
24155
24450
|
}
|
|
24156
|
-
|
|
24157
|
-
|
|
24158
|
-
|
|
24159
|
-
|
|
24160
|
-
|
|
24161
|
-
const saveData = typeof (conn === null || conn === void 0 ? void 0 : conn.saveData) === "boolean" ? conn.saveData : null;
|
|
24162
|
-
let prefersReducedData = null;
|
|
24163
|
-
let prefersReducedMotion = null;
|
|
24164
|
-
if (typeof window.matchMedia === "function") {
|
|
24165
|
-
try {
|
|
24166
|
-
const mqData = window.matchMedia("(prefers-reduced-data: reduce)");
|
|
24167
|
-
if (typeof mqData.matches === "boolean") {
|
|
24168
|
-
prefersReducedData = mqData.matches;
|
|
24169
|
-
}
|
|
24170
|
-
}
|
|
24171
|
-
catch (_a) { }
|
|
24172
|
-
try {
|
|
24173
|
-
const mqMotion = window.matchMedia("(prefers-reduced-motion: reduce)");
|
|
24174
|
-
if (typeof mqMotion.matches === "boolean") {
|
|
24175
|
-
prefersReducedMotion = mqMotion.matches;
|
|
24176
|
-
}
|
|
24177
|
-
}
|
|
24178
|
-
catch (_b) { }
|
|
24451
|
+
const session = parsed.data;
|
|
24452
|
+
const expirationTime = (0, addSeconds_1.default)(new Date(session.created), this.options.keepSession);
|
|
24453
|
+
if ((0, isBefore_1.default)(expirationTime, new Date())) {
|
|
24454
|
+
this.unset();
|
|
24455
|
+
return null;
|
|
24179
24456
|
}
|
|
24180
|
-
|
|
24181
|
-
|
|
24182
|
-
getNetworkInfo(measuredDownlinkMbps) {
|
|
24183
|
-
const conn = navigator.connection;
|
|
24184
|
-
return {
|
|
24185
|
-
type: typeof (conn === null || conn === void 0 ? void 0 : conn.type) === "string" ? conn.type : null,
|
|
24186
|
-
effectiveType: typeof (conn === null || conn === void 0 ? void 0 : conn.effectiveType) === "string" ? conn.effectiveType : null,
|
|
24187
|
-
downlinkMbps: typeof (conn === null || conn === void 0 ? void 0 : conn.downlink) === "number" ? conn.downlink : null,
|
|
24188
|
-
rttMs: typeof (conn === null || conn === void 0 ? void 0 : conn.rtt) === "number" ? conn.rtt : null,
|
|
24189
|
-
measuredDownlinkMbps
|
|
24190
|
-
};
|
|
24191
|
-
}
|
|
24192
|
-
maybeMeasureBandwidth() {
|
|
24193
|
-
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
24194
|
-
const conn = navigator.connection;
|
|
24195
|
-
const saveData = (conn === null || conn === void 0 ? void 0 : conn.saveData) === true;
|
|
24196
|
-
if (!this.opts.enableBandwidthProbe)
|
|
24197
|
-
return null;
|
|
24198
|
-
if (this.opts.respectSaveData && saveData)
|
|
24199
|
-
return null;
|
|
24200
|
-
try {
|
|
24201
|
-
const t0 = performance.now();
|
|
24202
|
-
const res = yield fetch(this.withCacheBuster(this.opts.probeUrl), {
|
|
24203
|
-
cache: "no-store",
|
|
24204
|
-
credentials: "omit"
|
|
24205
|
-
});
|
|
24206
|
-
const buf = yield res.arrayBuffer();
|
|
24207
|
-
const t1 = performance.now();
|
|
24208
|
-
const bits = buf.byteLength * 8;
|
|
24209
|
-
const seconds = (t1 - t0) / 1000;
|
|
24210
|
-
if (seconds <= 0.05)
|
|
24211
|
-
return null; // ignore unstable samples
|
|
24212
|
-
return +(bits / seconds / 1000000).toFixed(2);
|
|
24213
|
-
}
|
|
24214
|
-
catch (_a) {
|
|
24215
|
-
return null;
|
|
24216
|
-
}
|
|
24217
|
-
});
|
|
24457
|
+
// Return the sessionId.
|
|
24458
|
+
return session.id;
|
|
24218
24459
|
}
|
|
24219
|
-
|
|
24220
|
-
|
|
24221
|
-
const u = new URL(url, location.origin);
|
|
24222
|
-
const token = (_b = (_a = crypto === null || crypto === void 0 ? void 0 : crypto.randomUUID) === null || _a === void 0 ? void 0 : _a.call(crypto)) !== null && _b !== void 0 ? _b : String(Date.now());
|
|
24223
|
-
u.searchParams.set("cb", token);
|
|
24224
|
-
return u.toString();
|
|
24460
|
+
get localStorageKey() {
|
|
24461
|
+
return this.options.localStorageKey;
|
|
24225
24462
|
}
|
|
24226
|
-
|
|
24227
|
-
|
|
24228
|
-
const [h264, hevc] = yield Promise.all([
|
|
24229
|
-
this.supportsCodec('video/mp4; codecs="avc1.42E01E"'),
|
|
24230
|
-
this.supportsCodec('video/mp4; codecs="hvc1.1.6.L93.B0"')
|
|
24231
|
-
]);
|
|
24232
|
-
return { h264, hevc };
|
|
24233
|
-
});
|
|
24463
|
+
constructor(options) {
|
|
24464
|
+
this.options = ZOptions.parse(options || {});
|
|
24234
24465
|
}
|
|
24235
|
-
|
|
24236
|
-
|
|
24237
|
-
|
|
24238
|
-
|
|
24239
|
-
|
|
24240
|
-
|
|
24241
|
-
|
|
24242
|
-
|
|
24243
|
-
|
|
24244
|
-
|
|
24245
|
-
}
|
|
24246
|
-
}
|
|
24247
|
-
catch (_a) { }
|
|
24248
|
-
try {
|
|
24249
|
-
const v = document.createElement("video");
|
|
24250
|
-
return v.canPlayType(mime) !== "";
|
|
24251
|
-
}
|
|
24252
|
-
catch (_b) {
|
|
24253
|
-
return false;
|
|
24254
|
-
}
|
|
24255
|
-
});
|
|
24466
|
+
/** Set's the session with creation date for the given storage key to the localStorage. */
|
|
24467
|
+
set(sessionId) {
|
|
24468
|
+
ZSession.shape.id.parse(sessionId);
|
|
24469
|
+
this._current = sessionId;
|
|
24470
|
+
const session = {
|
|
24471
|
+
id: sessionId,
|
|
24472
|
+
created: new Date(),
|
|
24473
|
+
expire: false,
|
|
24474
|
+
};
|
|
24475
|
+
window.localStorage.setItem(this.localStorageKey, JSON.stringify(session));
|
|
24256
24476
|
}
|
|
24257
|
-
|
|
24258
|
-
|
|
24259
|
-
|
|
24260
|
-
return this.uaInfoCache;
|
|
24261
|
-
const nav = navigator;
|
|
24262
|
-
const uaData = nav.userAgentData;
|
|
24263
|
-
const ua = navigator.userAgent;
|
|
24264
|
-
let browserFamily = "Unknown";
|
|
24265
|
-
let browserVersion = null;
|
|
24266
|
-
let osFamily = "Unknown";
|
|
24267
|
-
let osVersion = null;
|
|
24268
|
-
let model = null;
|
|
24269
|
-
let architecture = null;
|
|
24270
|
-
let bitness = null;
|
|
24271
|
-
// --- UA-CH (modern browsers) ---
|
|
24272
|
-
if (uaData === null || uaData === void 0 ? void 0 : uaData.getHighEntropyValues) {
|
|
24273
|
-
try {
|
|
24274
|
-
const high = yield uaData.getHighEntropyValues([
|
|
24275
|
-
"platform",
|
|
24276
|
-
"platformVersion",
|
|
24277
|
-
"model",
|
|
24278
|
-
"architecture",
|
|
24279
|
-
"bitness",
|
|
24280
|
-
"fullVersionList"
|
|
24281
|
-
]);
|
|
24282
|
-
osFamily = high.platform || "Unknown";
|
|
24283
|
-
osVersion = high.platformVersion || null;
|
|
24284
|
-
model = high.model || null;
|
|
24285
|
-
architecture = high.architecture || null;
|
|
24286
|
-
bitness = high.bitness || null;
|
|
24287
|
-
const brands = high.fullVersionList || uaData.brands || [];
|
|
24288
|
-
const realBrand = brands.find((b) => {
|
|
24289
|
-
if (!b.brand)
|
|
24290
|
-
return false;
|
|
24291
|
-
const normalized = b.brand.replace(/[^a-zA-Z]/g, "").toLowerCase();
|
|
24292
|
-
return !normalized.includes("chromium") && !normalized.includes("notabrand");
|
|
24293
|
-
});
|
|
24294
|
-
if (realBrand) {
|
|
24295
|
-
browserFamily = realBrand.brand;
|
|
24296
|
-
browserVersion = realBrand.version;
|
|
24297
|
-
}
|
|
24298
|
-
}
|
|
24299
|
-
catch (_a) {
|
|
24300
|
-
// silently fail
|
|
24301
|
-
}
|
|
24302
|
-
}
|
|
24303
|
-
// --- Fallback to classic UA parsing if browser unknown ---
|
|
24304
|
-
if (!browserFamily || browserFamily === "Unknown") {
|
|
24305
|
-
const browserRegexes = [
|
|
24306
|
-
[/Edg\/(\S+)/, "Edge"],
|
|
24307
|
-
[/OPR\/(\S+)/, "Opera"],
|
|
24308
|
-
[/SamsungBrowser\/(\S+)/, "Samsung Internet"],
|
|
24309
|
-
[/Firefox\/(\S+)/, "Firefox"],
|
|
24310
|
-
[/Chrome\/(\S+)/, "Chrome"],
|
|
24311
|
-
[/Version\/(\S+).*Safari/, "Safari"]
|
|
24312
|
-
];
|
|
24313
|
-
for (const [regex, name] of browserRegexes) {
|
|
24314
|
-
const match = ua.match(regex);
|
|
24315
|
-
if (match) {
|
|
24316
|
-
browserFamily = name;
|
|
24317
|
-
browserVersion = match[1];
|
|
24318
|
-
break;
|
|
24319
|
-
}
|
|
24320
|
-
}
|
|
24321
|
-
}
|
|
24322
|
-
// --- OS detection (always run, iOS first) ---
|
|
24323
|
-
if (/iPhone|iPad|iPod/.test(ua)) {
|
|
24324
|
-
osFamily = "iOS";
|
|
24325
|
-
const match = ua.match(/OS (\d+[_\d]*)/);
|
|
24326
|
-
if (match)
|
|
24327
|
-
osVersion = match[1].replace(/_/g, ".");
|
|
24328
|
-
}
|
|
24329
|
-
else if (uaData === null || uaData === void 0 ? void 0 : uaData.platform) {
|
|
24330
|
-
osFamily = uaData.platform;
|
|
24331
|
-
}
|
|
24332
|
-
else if (/Windows/.test(ua)) {
|
|
24333
|
-
osFamily = "Windows";
|
|
24334
|
-
const match = ua.match(/Windows NT (\d+\.\d+)/);
|
|
24335
|
-
if (match)
|
|
24336
|
-
osVersion = match[1];
|
|
24337
|
-
}
|
|
24338
|
-
else if (/Mac OS X/.test(ua)) {
|
|
24339
|
-
osFamily = "macOS";
|
|
24340
|
-
const match = ua.match(/Mac OS X (\d+[_\d]*)/);
|
|
24341
|
-
if (match)
|
|
24342
|
-
osVersion = match[1].replace(/_/g, ".");
|
|
24343
|
-
}
|
|
24344
|
-
else if (/Android/.test(ua)) {
|
|
24345
|
-
osFamily = "Android";
|
|
24346
|
-
const match = ua.match(/Android (\d+(\.\d+)?)/);
|
|
24347
|
-
if (match)
|
|
24348
|
-
osVersion = match[1];
|
|
24349
|
-
}
|
|
24350
|
-
else if (/Linux/.test(ua)) {
|
|
24351
|
-
osFamily = "Linux";
|
|
24352
|
-
}
|
|
24353
|
-
const result = { browserFamily, browserVersion, osFamily, osVersion, model, architecture, bitness };
|
|
24354
|
-
this.uaInfoCache = result;
|
|
24355
|
-
return result;
|
|
24356
|
-
});
|
|
24477
|
+
/** Removes a session from the localStorage. */
|
|
24478
|
+
unset() {
|
|
24479
|
+
window.localStorage.removeItem(this.localStorageKey);
|
|
24357
24480
|
}
|
|
24358
24481
|
}
|
|
24359
|
-
exports.
|
|
24482
|
+
exports.Session = Session;
|
|
24483
|
+
|
|
24484
|
+
|
|
24485
|
+
/***/ }),
|
|
24486
|
+
|
|
24487
|
+
/***/ 9764:
|
|
24488
|
+
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
24489
|
+
|
|
24490
|
+
|
|
24491
|
+
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
24492
|
+
exports.Stats = void 0;
|
|
24493
|
+
const shared_pixelstreaming_websdk_1 = __webpack_require__(7910);
|
|
24494
|
+
function Stats(stats) {
|
|
24495
|
+
const result = shared_pixelstreaming_websdk_1.Messages.ZStats.shape.stats.parse({
|
|
24496
|
+
/**
|
|
24497
|
+
* Other known properties.
|
|
24498
|
+
*/
|
|
24499
|
+
codecs: stats.codecs,
|
|
24500
|
+
candidatePair: stats.candidatePairs,
|
|
24501
|
+
localCandidates: stats.localCandidates,
|
|
24502
|
+
remoteCandidates: stats.remoteCandidates,
|
|
24503
|
+
DataChannelStats: stats.datachannelStats,
|
|
24504
|
+
// Received (last) for ticket
|
|
24505
|
+
bytesReceived: forceNumber(stats.inboundVideoStats.bytesReceived),
|
|
24506
|
+
// Packets Lost (last) for ticket
|
|
24507
|
+
packetsLost: forceNumber(stats.inboundVideoStats.packetsLost),
|
|
24508
|
+
// Video resolution: highest lowest average (portrait) and highest lowest average (landscape) for ticket
|
|
24509
|
+
frameWidth: forceNumber(stats.inboundVideoStats.frameWidth),
|
|
24510
|
+
// Video resolution: highest lowest average (portrait) and highest lowest average (landscape) for ticket
|
|
24511
|
+
frameHeight: forceNumber(stats.inboundVideoStats.frameHeight),
|
|
24512
|
+
// Frames decoded (Last) for ticket
|
|
24513
|
+
framesDecoded: forceNumber(stats.inboundVideoStats.framesDecoded),
|
|
24514
|
+
// Framerate (low / high, avg) for ticket
|
|
24515
|
+
framesPerSecond: forceNumber(stats.inboundVideoStats.framesPerSecond),
|
|
24516
|
+
// frames dropped (last) for ticket
|
|
24517
|
+
framesDropped: forceNumber(stats.inboundVideoStats.framesDropped),
|
|
24518
|
+
// Videocodec (once) for ticket
|
|
24519
|
+
videoCodec: stats.inboundVideoStats.codecId,
|
|
24520
|
+
// audiocodec (once) for ticket
|
|
24521
|
+
audioCodec: stats.inboundAudioStats.codecId,
|
|
24522
|
+
// browser type and version for ticket (arcware / addition)
|
|
24523
|
+
browserInfo: {
|
|
24524
|
+
// to be received!
|
|
24525
|
+
userAgent: navigator.userAgent,
|
|
24526
|
+
platform: navigator.oscpu || navigator.platform || null,
|
|
24527
|
+
language: navigator.language,
|
|
24528
|
+
},
|
|
24529
|
+
// Net RTT (low, high, avg)
|
|
24530
|
+
// BEGIN TW CHANGE
|
|
24531
|
+
currentRTT: calcRTT(stats.candidatePairs),
|
|
24532
|
+
// END TW CHANGE
|
|
24533
|
+
// Duration (last)
|
|
24534
|
+
sessionRunTime: stats.sessionStats.runTime,
|
|
24535
|
+
// Controls stream input (??)
|
|
24536
|
+
controlsStreamInput: stats.sessionStats.controlsStreamInput,
|
|
24537
|
+
// video quantization parameter (low / high / avg if applicable)
|
|
24538
|
+
videoEncoderAvgQP: forceNumber(stats.sessionStats.videoEncoderAvgQP),
|
|
24539
|
+
// Video bitrate (min / max / avg)
|
|
24540
|
+
videoBitrate: forceNumber(stats.inboundVideoStats.bitrate),
|
|
24541
|
+
// Audio bitrate (min / max / avg)
|
|
24542
|
+
audioBitrate: forceNumber(stats.inboundAudioStats.bitrate),
|
|
24543
|
+
});
|
|
24544
|
+
return result;
|
|
24545
|
+
}
|
|
24546
|
+
exports.Stats = Stats;
|
|
24547
|
+
/**
|
|
24548
|
+
* Given an array of candidate pairs this function will find the highest RTT for the selected pair
|
|
24549
|
+
* @param pairs - An array of candidate pairs
|
|
24550
|
+
* @returns The highest round trip time of a selected candidate pair
|
|
24551
|
+
*/
|
|
24552
|
+
function calcRTT(pairs) {
|
|
24553
|
+
let rtt = 0;
|
|
24554
|
+
pairs.forEach((pair) => {
|
|
24555
|
+
if (pair.selected && pair.currentRoundTripTime > rtt) {
|
|
24556
|
+
rtt = pair.currentRoundTripTime;
|
|
24557
|
+
}
|
|
24558
|
+
});
|
|
24559
|
+
return rtt;
|
|
24560
|
+
}
|
|
24561
|
+
/**
|
|
24562
|
+
* Takes a number and forces it to return a number. If the value passed in is NaN, 0 will be returned.
|
|
24563
|
+
* @param value - A number
|
|
24564
|
+
* @returns The number passed in as value or 0 if vlaue was NaN
|
|
24565
|
+
*/
|
|
24566
|
+
function forceNumber(value) {
|
|
24567
|
+
return isNaN(value) ? 0 : value;
|
|
24568
|
+
}
|
|
24360
24569
|
|
|
24361
24570
|
|
|
24362
24571
|
/***/ }),
|
|
24363
24572
|
|
|
24364
|
-
/***/
|
|
24573
|
+
/***/ 9580:
|
|
24574
|
+
/***/ ((__unused_webpack_module, exports) => {
|
|
24575
|
+
|
|
24576
|
+
|
|
24577
|
+
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
24578
|
+
function debounce(func, wait) {
|
|
24579
|
+
let timeout;
|
|
24580
|
+
return function (...args) {
|
|
24581
|
+
clearTimeout(timeout);
|
|
24582
|
+
timeout = window.setTimeout(() => func(...args), wait);
|
|
24583
|
+
};
|
|
24584
|
+
}
|
|
24585
|
+
exports["default"] = debounce;
|
|
24586
|
+
|
|
24587
|
+
|
|
24588
|
+
/***/ }),
|
|
24589
|
+
|
|
24590
|
+
/***/ 471:
|
|
24365
24591
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
24366
24592
|
|
|
24367
24593
|
|
|
24368
24594
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
24369
|
-
exports.
|
|
24595
|
+
exports.isAnalyticsEvent = exports.toAnalyticsEvent = void 0;
|
|
24596
|
+
// analytics.ts
|
|
24597
|
+
const common_1 = __webpack_require__(2483);
|
|
24598
|
+
/**
|
|
24599
|
+
* Build an AnalyticsEvent from unknown input.
|
|
24600
|
+
* - accepts object or JSON/JSON-ish string
|
|
24601
|
+
* - drops extra fields
|
|
24602
|
+
* - requires non-empty string `type` and `customName`
|
|
24603
|
+
* - accepts `payload` only if it's a string; truncates by **bytes**
|
|
24604
|
+
*/
|
|
24605
|
+
function toAnalyticsEvent(input, opts = {}) {
|
|
24606
|
+
var _a, _b, _c;
|
|
24607
|
+
const maxBytes = (_a = opts.maxPayloadBytes) !== null && _a !== void 0 ? _a : 512;
|
|
24608
|
+
let obj;
|
|
24609
|
+
try {
|
|
24610
|
+
obj = (0, common_1.parseUnknownToObject)(input, { allowJsonish: (_b = opts.allowJsonish) !== null && _b !== void 0 ? _b : true });
|
|
24611
|
+
}
|
|
24612
|
+
catch (e) {
|
|
24613
|
+
return { ok: false, error: (_c = e === null || e === void 0 ? void 0 : e.message) !== null && _c !== void 0 ? _c : "Invalid input" };
|
|
24614
|
+
}
|
|
24615
|
+
const typeVal = safeString(obj["type"]);
|
|
24616
|
+
const customNameVal = safeString(obj["customName"]);
|
|
24617
|
+
if (!typeVal)
|
|
24618
|
+
return { ok: false, error: "`type` must be a non-empty string." };
|
|
24619
|
+
if (!customNameVal)
|
|
24620
|
+
return { ok: false, error: "`customName` must be a non-empty string." };
|
|
24621
|
+
let payloadStr;
|
|
24622
|
+
if ("payload" in obj && typeof obj["payload"] === "string") {
|
|
24623
|
+
payloadStr = (0, common_1.truncateByBytes)(obj["payload"], maxBytes);
|
|
24624
|
+
}
|
|
24625
|
+
const value = payloadStr !== undefined
|
|
24626
|
+
? { type: typeVal, customName: customNameVal, payload: payloadStr }
|
|
24627
|
+
: { type: typeVal, customName: customNameVal };
|
|
24628
|
+
return { ok: true, value };
|
|
24629
|
+
}
|
|
24630
|
+
exports.toAnalyticsEvent = toAnalyticsEvent;
|
|
24631
|
+
/** Type guard */
|
|
24632
|
+
function isAnalyticsEvent(x) {
|
|
24633
|
+
return (!!x &&
|
|
24634
|
+
typeof x === "object" &&
|
|
24635
|
+
typeof x.type === "string" &&
|
|
24636
|
+
typeof x.customName === "string" &&
|
|
24637
|
+
(typeof x.payload === "string" || x.payload === undefined));
|
|
24638
|
+
}
|
|
24639
|
+
exports.isAnalyticsEvent = isAnalyticsEvent;
|
|
24640
|
+
function safeString(x) {
|
|
24641
|
+
if (typeof x !== "string")
|
|
24642
|
+
return undefined;
|
|
24643
|
+
const trimmed = x.trim();
|
|
24644
|
+
return trimmed.length ? trimmed : undefined;
|
|
24645
|
+
}
|
|
24646
|
+
|
|
24647
|
+
|
|
24648
|
+
/***/ }),
|
|
24649
|
+
|
|
24650
|
+
/***/ 2768:
|
|
24651
|
+
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
24652
|
+
|
|
24653
|
+
|
|
24654
|
+
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
24655
|
+
exports.parseControl = exports.ZFileTransfer = void 0;
|
|
24656
|
+
// fileTransfer.ts
|
|
24370
24657
|
const zod_1 = __webpack_require__(8754);
|
|
24371
|
-
const
|
|
24372
|
-
|
|
24373
|
-
exports.
|
|
24374
|
-
|
|
24375
|
-
|
|
24376
|
-
/** Can be used to be added to the request in order to verify access to private projects.
|
|
24377
|
-
* For internal use only. => Preview page.
|
|
24378
|
-
*/
|
|
24379
|
-
token: zod_1.z.string().optional(),
|
|
24380
|
-
/** @deprecated in there for legacy use. Can only be used when token is provided. */
|
|
24381
|
-
bypass: zod_1.z.boolean().optional(),
|
|
24382
|
-
// /** Configure DirectFlow Token. */
|
|
24383
|
-
// directFlow: z.string().optional(),
|
|
24384
|
-
/** Handler for server side error messages. */
|
|
24385
|
-
errorHandler: zod_1.z.function().args(shared_pixelstreaming_websdk_1.Messages.ZErrorMessage).returns(zod_1.z.void()).optional(),
|
|
24386
|
-
/** Handler for queue events. */
|
|
24387
|
-
queueHandler: zod_1.z.function().args(shared_pixelstreaming_websdk_1.Messages.ZQueue).returns(zod_1.z.void()).optional(),
|
|
24388
|
-
/** Handler for sessionId message. */
|
|
24389
|
-
sessionIdHandler: zod_1.z.function().args(zod_1.z.string()).returns(zod_1.z.void()).optional(),
|
|
24390
|
-
/** Handler for love letters.
|
|
24391
|
-
* "LoveLetters" are send from backend to the SDK to state what phase the connection currently is in. */
|
|
24392
|
-
loveLetterHandler: zod_1.z.function().args(shared_pixelstreaming_websdk_1.Messages.ZLoveLetter).returns(zod_1.z.void()).optional(),
|
|
24393
|
-
/** Show or hide the fullscreen button. */
|
|
24394
|
-
fullscreenButton: zod_1.z.boolean().optional(),
|
|
24395
|
-
/** Show or hide the settings button. */
|
|
24396
|
-
settingsButton: zod_1.z.boolean().optional(),
|
|
24397
|
-
/** Show or hide the info button. */
|
|
24398
|
-
infoButton: zod_1.z.boolean().optional(),
|
|
24399
|
-
/** Show or hide the audio button. */
|
|
24400
|
-
audioButton: zod_1.z.boolean().optional(),
|
|
24401
|
-
/** Show or hide the microphone button. */
|
|
24402
|
-
micButton: zod_1.z.boolean().optional(),
|
|
24403
|
-
/** Show or hide the microphone button. */
|
|
24404
|
-
stopButton: zod_1.z.boolean().optional(),
|
|
24405
|
-
/** Show or hide the connectionStrengthIcon button. */
|
|
24406
|
-
connectionStrengthIcon: zod_1.z.boolean().optional(),
|
|
24407
|
-
/** ShareId, used for sharing your project.
|
|
24408
|
-
* Using ArcwareInit will set this required property for you. */
|
|
24409
|
-
shareId: zod_1.z.string().startsWith("share-").optional(),
|
|
24410
|
-
/** Id of your project, only required if your shareId refers to multiple projects.
|
|
24411
|
-
* Using ArcwareInit will set this required property for you. */
|
|
24412
|
-
projectId: zod_1.z.string().optional(),
|
|
24413
|
-
/** Enable/Disable LoveLetter logging to the console. */
|
|
24414
|
-
loveLetterLogging: zod_1.z.boolean().optional(),
|
|
24415
|
-
/** Enable/Disable Connection Identifier logging to the console. */
|
|
24416
|
-
connectionIdentifierLoggingDisabled: zod_1.z.boolean().optional(),
|
|
24417
|
-
/** Width with which instance should be started */
|
|
24418
|
-
startWidth: zod_1.z.number().optional(),
|
|
24419
|
-
/** Height with which instance should be started */
|
|
24420
|
-
startHeight: zod_1.z.number().optional()
|
|
24658
|
+
const common_1 = __webpack_require__(2483);
|
|
24659
|
+
// Schema
|
|
24660
|
+
exports.ZFileTransfer = zod_1.z.object({
|
|
24661
|
+
type: zod_1.z.literal("fileTransfer"),
|
|
24662
|
+
filename: zod_1.z.string().trim().optional()
|
|
24421
24663
|
});
|
|
24664
|
+
// Normalized parse + validate
|
|
24665
|
+
function parseControl(input, schema) {
|
|
24666
|
+
const obj = (0, common_1.parseUnknownToObject)(input, { allowJsonish: true });
|
|
24667
|
+
return schema.parse(obj);
|
|
24668
|
+
}
|
|
24669
|
+
exports.parseControl = parseControl;
|
|
24422
24670
|
|
|
24423
24671
|
|
|
24424
24672
|
/***/ }),
|
|
24425
24673
|
|
|
24426
|
-
/***/
|
|
24427
|
-
/***/ ((__unused_webpack_module, exports) => {
|
|
24674
|
+
/***/ 8429:
|
|
24675
|
+
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
24428
24676
|
|
|
24429
24677
|
|
|
24678
|
+
/**
|
|
24679
|
+
* DiagnosticsCollector.ts
|
|
24680
|
+
* Lightweight, privacy-aware client diagnostics for troubleshooting + analytics.
|
|
24681
|
+
* WebRTC collection intentionally omitted (to add later).
|
|
24682
|
+
*
|
|
24683
|
+
* Notes:
|
|
24684
|
+
* - Some fields are best-effort due to browser restrictions; they're nullable.
|
|
24685
|
+
* - Bandwidth probe requires a small binary served with:
|
|
24686
|
+
* Content-Type: application/octet-stream
|
|
24687
|
+
* Content-Encoding: identity
|
|
24688
|
+
* Cache-Control: no-store
|
|
24689
|
+
* Default location: /diag/probe.bin
|
|
24690
|
+
*/
|
|
24430
24691
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
24431
|
-
exports.
|
|
24432
|
-
|
|
24433
|
-
|
|
24434
|
-
|
|
24435
|
-
|
|
24436
|
-
|
|
24437
|
-
|
|
24438
|
-
|
|
24439
|
-
|
|
24440
|
-
|
|
24441
|
-
|
|
24442
|
-
|
|
24443
|
-
|
|
24444
|
-
|
|
24445
|
-
|
|
24446
|
-
|
|
24447
|
-
|
|
24448
|
-
|
|
24692
|
+
exports.DiagnosticsCollector = exports.Type = exports.Orientation = void 0;
|
|
24693
|
+
const tslib_1 = __webpack_require__(655);
|
|
24694
|
+
var Orientation;
|
|
24695
|
+
(function (Orientation) {
|
|
24696
|
+
Orientation["Landscape"] = "landscape";
|
|
24697
|
+
Orientation["Portrait"] = "portrait";
|
|
24698
|
+
})(Orientation = exports.Orientation || (exports.Orientation = {}));
|
|
24699
|
+
var Type;
|
|
24700
|
+
(function (Type) {
|
|
24701
|
+
Type["Desktop"] = "desktop";
|
|
24702
|
+
Type["Mobile"] = "mobile";
|
|
24703
|
+
Type["Tablet"] = "tablet";
|
|
24704
|
+
})(Type = exports.Type || (exports.Type = {}));
|
|
24705
|
+
/**
|
|
24706
|
+
* DiagnosticsCollector
|
|
24707
|
+
*/
|
|
24708
|
+
class DiagnosticsCollector {
|
|
24709
|
+
constructor(opts = {}) {
|
|
24710
|
+
var _a, _b, _c, _d;
|
|
24711
|
+
this.uaInfoCache = null;
|
|
24712
|
+
this.opts = {
|
|
24713
|
+
enableBandwidthProbe: (_a = opts.enableBandwidthProbe) !== null && _a !== void 0 ? _a : true,
|
|
24714
|
+
probeUrl: (_b = opts.probeUrl) !== null && _b !== void 0 ? _b : "/diag/probe.bin",
|
|
24715
|
+
respectSaveData: (_c = opts.respectSaveData) !== null && _c !== void 0 ? _c : true,
|
|
24716
|
+
sampleRate: Math.max(0, Math.min(1, (_d = opts.sampleRate) !== null && _d !== void 0 ? _d : 1))
|
|
24717
|
+
};
|
|
24718
|
+
}
|
|
24719
|
+
/**
|
|
24720
|
+
* Collect the diagnostics payload.
|
|
24721
|
+
*/
|
|
24722
|
+
collect() {
|
|
24723
|
+
var _a, _b;
|
|
24724
|
+
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
24725
|
+
if (!this.shouldSample()) {
|
|
24726
|
+
return {
|
|
24727
|
+
device: { type: Type.Desktop, touchSupport: false },
|
|
24728
|
+
runtime: { browser: { family: "Unknown", version: null }, os: { family: "Unknown", version: null } },
|
|
24729
|
+
powerHints: { saveData: null, prefersReducedData: null, prefersReducedMotion: null },
|
|
24730
|
+
network: { type: null, effectiveType: null, downlinkMbps: null, rttMs: null, measuredDownlinkMbps: null },
|
|
24731
|
+
timestamps: { collectedAt: Date.now() }
|
|
24732
|
+
};
|
|
24733
|
+
}
|
|
24734
|
+
const collectedAt = Date.now();
|
|
24735
|
+
const [uaInfo, codecSupport, measuredDownlinkMbps] = yield Promise.all([
|
|
24736
|
+
this.getUAInfo(),
|
|
24737
|
+
this.getCodecSupport(),
|
|
24738
|
+
this.maybeMeasureBandwidth()
|
|
24739
|
+
]);
|
|
24740
|
+
return {
|
|
24741
|
+
device: {
|
|
24742
|
+
type: this.inferDeviceType(),
|
|
24743
|
+
vendor: null,
|
|
24744
|
+
model: uaInfo.model,
|
|
24745
|
+
architecture: uaInfo.architecture,
|
|
24746
|
+
bitness: uaInfo.bitness,
|
|
24747
|
+
touchSupport: this.hasTouch(),
|
|
24748
|
+
hardwareConcurrency: (_a = navigator.hardwareConcurrency) !== null && _a !== void 0 ? _a : null,
|
|
24749
|
+
deviceMemory: (_b = navigator.deviceMemory) !== null && _b !== void 0 ? _b : null,
|
|
24750
|
+
orientation: this.getOrientation(),
|
|
24751
|
+
webgl: this.hasWebGL(),
|
|
24752
|
+
codecs: codecSupport
|
|
24753
|
+
},
|
|
24754
|
+
runtime: {
|
|
24755
|
+
browser: { family: uaInfo.browserFamily, version: uaInfo.browserVersion },
|
|
24756
|
+
os: { family: uaInfo.osFamily, version: uaInfo.osVersion }
|
|
24757
|
+
},
|
|
24758
|
+
powerHints: this.getPowerHints(),
|
|
24759
|
+
network: this.getNetworkInfo(measuredDownlinkMbps),
|
|
24760
|
+
timestamps: { collectedAt }
|
|
24761
|
+
};
|
|
24762
|
+
});
|
|
24763
|
+
}
|
|
24764
|
+
/**
|
|
24765
|
+
* Collect a safe subset of WebRTC stats once PC is connected.
|
|
24766
|
+
*/
|
|
24767
|
+
collectWebRTC(pc) {
|
|
24768
|
+
var _a, _b, _c, _d, _e, _f;
|
|
24769
|
+
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
24770
|
+
try {
|
|
24771
|
+
const stats = yield pc.getStats();
|
|
24772
|
+
let selected, transport, local, remote;
|
|
24773
|
+
stats.forEach((r) => {
|
|
24774
|
+
if (r.type === "transport" && r.selectedCandidatePairId)
|
|
24775
|
+
transport = r;
|
|
24776
|
+
if (r.type === "candidate-pair" && (r.selected || r.nominated))
|
|
24777
|
+
selected = r;
|
|
24778
|
+
});
|
|
24779
|
+
if (selected) {
|
|
24780
|
+
local = stats.get(selected.localCandidateId);
|
|
24781
|
+
remote = stats.get(selected.remoteCandidateId);
|
|
24782
|
+
}
|
|
24783
|
+
return {
|
|
24784
|
+
candidatePairId: (_a = selected === null || selected === void 0 ? void 0 : selected.id) !== null && _a !== void 0 ? _a : null,
|
|
24785
|
+
localCandidateType: (_b = local === null || local === void 0 ? void 0 : local.candidateType) !== null && _b !== void 0 ? _b : null,
|
|
24786
|
+
remoteCandidateType: (_c = remote === null || remote === void 0 ? void 0 : remote.candidateType) !== null && _c !== void 0 ? _c : null,
|
|
24787
|
+
protocol: (_d = local === null || local === void 0 ? void 0 : local.protocol) !== null && _d !== void 0 ? _d : null,
|
|
24788
|
+
networkType: (_e = local === null || local === void 0 ? void 0 : local.networkType) !== null && _e !== void 0 ? _e : null,
|
|
24789
|
+
dtlsCipher: (_f = transport === null || transport === void 0 ? void 0 : transport.dtlsCipher) !== null && _f !== void 0 ? _f : null
|
|
24790
|
+
};
|
|
24791
|
+
}
|
|
24792
|
+
catch (_g) {
|
|
24793
|
+
return {};
|
|
24794
|
+
}
|
|
24795
|
+
});
|
|
24449
24796
|
}
|
|
24450
|
-
|
|
24451
|
-
|
|
24797
|
+
/**
|
|
24798
|
+
* Helper to embed diagnostics in a hello envelope.
|
|
24799
|
+
*/
|
|
24800
|
+
buildHelloEnvelope(base, pc) {
|
|
24801
|
+
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
24802
|
+
const diag = yield this.collect();
|
|
24803
|
+
const webrtc = pc ? yield this.collectWebRTC(pc) : undefined;
|
|
24804
|
+
const ext = webrtc ? { diag: Object.assign(Object.assign({}, diag), { webrtc }) } : { diag };
|
|
24805
|
+
return Object.assign(Object.assign({}, base), { ext });
|
|
24806
|
+
});
|
|
24452
24807
|
}
|
|
24453
|
-
|
|
24454
|
-
|
|
24455
|
-
this.
|
|
24808
|
+
// ---------- Internals ----------
|
|
24809
|
+
shouldSample() {
|
|
24810
|
+
if (this.opts.sampleRate >= 1)
|
|
24811
|
+
return true;
|
|
24812
|
+
return Math.random() < this.opts.sampleRate;
|
|
24456
24813
|
}
|
|
24457
|
-
|
|
24814
|
+
hasTouch() {
|
|
24458
24815
|
var _a;
|
|
24459
|
-
|
|
24460
|
-
|
|
24461
|
-
if ((_a = ps.config.settings) === null || _a === void 0 ? void 0 : _a.connectionIdentifierLoggingDisabled)
|
|
24462
|
-
this.disable();
|
|
24463
|
-
}
|
|
24464
|
-
if (!this.interval)
|
|
24465
|
-
this.interval = setInterval(this.connectionWatcher.bind(this), 10 * 1000);
|
|
24466
|
-
}
|
|
24467
|
-
GetWebSocketStates() {
|
|
24468
|
-
return this.aps.map((ps) => ps.websocketState);
|
|
24816
|
+
const nav = navigator;
|
|
24817
|
+
return "ontouchstart" in window || ((_a = nav.maxTouchPoints) !== null && _a !== void 0 ? _a : 0) > 0;
|
|
24469
24818
|
}
|
|
24470
|
-
|
|
24471
|
-
|
|
24819
|
+
getOrientation() {
|
|
24820
|
+
var _a;
|
|
24821
|
+
try {
|
|
24822
|
+
if ((_a = screen.orientation) === null || _a === void 0 ? void 0 : _a.type) {
|
|
24823
|
+
return screen.orientation.type.startsWith("portrait") ? Orientation.Portrait : Orientation.Landscape;
|
|
24824
|
+
}
|
|
24825
|
+
if (window.matchMedia) {
|
|
24826
|
+
return window.matchMedia("(orientation: portrait)").matches ? Orientation.Portrait : Orientation.Landscape;
|
|
24827
|
+
}
|
|
24828
|
+
}
|
|
24829
|
+
catch (_b) { }
|
|
24830
|
+
return null;
|
|
24472
24831
|
}
|
|
24473
|
-
|
|
24474
|
-
|
|
24832
|
+
hasWebGL() {
|
|
24833
|
+
try {
|
|
24834
|
+
const canvas = document.createElement("canvas");
|
|
24835
|
+
return !!(canvas.getContext("webgl") || canvas.getContext("experimental-webgl"));
|
|
24836
|
+
}
|
|
24837
|
+
catch (_a) {
|
|
24838
|
+
return false;
|
|
24839
|
+
}
|
|
24475
24840
|
}
|
|
24476
24841
|
/**
|
|
24477
|
-
*
|
|
24478
|
-
*
|
|
24479
|
-
* Or when they accidentally set up multiple connections!
|
|
24480
|
-
* Things like that can happen, for example if the React.useEffect was not setup perfectly!
|
|
24842
|
+
* Heuristic device type: best-effort only.
|
|
24843
|
+
* Tries UA-CH, then UA fallback, then touch + screen size heuristics.
|
|
24481
24844
|
*/
|
|
24482
|
-
|
|
24483
|
-
|
|
24484
|
-
|
|
24485
|
-
const
|
|
24486
|
-
|
|
24487
|
-
|
|
24845
|
+
inferDeviceType() {
|
|
24846
|
+
const uaData = navigator.userAgentData;
|
|
24847
|
+
const ua = navigator.userAgent || "";
|
|
24848
|
+
const isMobileCH = (uaData === null || uaData === void 0 ? void 0 : uaData.mobile) === true;
|
|
24849
|
+
const minDim = Math.min(screen.width, screen.height);
|
|
24850
|
+
// 1. Explicit iPad / tablet detection via UA (iOS often lies in CH)
|
|
24851
|
+
if (/\b(iPad|Tablet)\b/i.test(ua)) {
|
|
24852
|
+
return Type.Tablet;
|
|
24488
24853
|
}
|
|
24489
|
-
|
|
24490
|
-
|
|
24854
|
+
// 2. UA-CH mobile hint (Chromium only, often accurate for Android)
|
|
24855
|
+
if (isMobileCH) {
|
|
24856
|
+
if (minDim >= 600)
|
|
24857
|
+
return Type.Tablet;
|
|
24858
|
+
return Type.Mobile;
|
|
24491
24859
|
}
|
|
24492
|
-
|
|
24493
|
-
|
|
24494
|
-
|
|
24495
|
-
|
|
24496
|
-
|
|
24497
|
-
/***/ }),
|
|
24498
|
-
|
|
24499
|
-
/***/ 3379:
|
|
24500
|
-
/***/ ((__unused_webpack_module, exports) => {
|
|
24501
|
-
|
|
24502
|
-
|
|
24503
|
-
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
24504
|
-
exports.EventHandler = void 0;
|
|
24505
|
-
/** A helper class to spread the event to additional event handlers added from external sources. */
|
|
24506
|
-
class EventHandler {
|
|
24507
|
-
/** Returns the added callback on success or null, if something went wrong. */
|
|
24508
|
-
add(callback) {
|
|
24509
|
-
const cb = this.callbacks.find((cb) => cb === callback);
|
|
24510
|
-
if (cb)
|
|
24511
|
-
return null;
|
|
24512
|
-
this.callbacks.push(callback);
|
|
24513
|
-
return callback;
|
|
24514
|
-
}
|
|
24515
|
-
/** Returns true if the input callback has been found and removed and false if not. */
|
|
24516
|
-
remove(callback) {
|
|
24517
|
-
const cb = this.callbacks.find((cb) => cb === callback);
|
|
24518
|
-
if (cb)
|
|
24519
|
-
this.callbacks.splice(this.callbacks.indexOf(cb), 1);
|
|
24520
|
-
return !!cb;
|
|
24521
|
-
}
|
|
24522
|
-
constructor() {
|
|
24523
|
-
this.callbacks = new Array();
|
|
24524
|
-
}
|
|
24525
|
-
/** Emits the event-data for each of the existing handlers. */
|
|
24526
|
-
static Emit(handler, event) {
|
|
24527
|
-
handler.callbacks.forEach((callback) => callback(event));
|
|
24528
|
-
}
|
|
24529
|
-
}
|
|
24530
|
-
exports.EventHandler = EventHandler;
|
|
24531
|
-
|
|
24532
|
-
|
|
24533
|
-
/***/ }),
|
|
24534
|
-
|
|
24535
|
-
/***/ 2469:
|
|
24536
|
-
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
24537
|
-
|
|
24538
|
-
|
|
24539
|
-
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
24540
|
-
exports.Session = void 0;
|
|
24541
|
-
const addSeconds_1 = __webpack_require__(1973);
|
|
24542
|
-
const isBefore_1 = __webpack_require__(313);
|
|
24543
|
-
const zod_1 = __webpack_require__(8754);
|
|
24544
|
-
const ZSession = zod_1.z
|
|
24545
|
-
.object({
|
|
24546
|
-
id: zod_1.z.string().min(1),
|
|
24547
|
-
created: zod_1.z
|
|
24548
|
-
.date()
|
|
24549
|
-
.or(zod_1.z.string())
|
|
24550
|
-
.transform((arg) => new Date(arg)),
|
|
24551
|
-
expire: zod_1.z.boolean().default(false).optional(),
|
|
24552
|
-
})
|
|
24553
|
-
.strict();
|
|
24554
|
-
const ZOptions = zod_1.z.object({
|
|
24555
|
-
localStorageKey: zod_1.z.string().min(3).default("pxss"),
|
|
24556
|
-
keepSession: zod_1.z
|
|
24557
|
-
.number()
|
|
24558
|
-
.int()
|
|
24559
|
-
.min(3)
|
|
24560
|
-
/** Default keep is 10, since this is how long instances will be kept alive by default. */
|
|
24561
|
-
.default(10),
|
|
24562
|
-
});
|
|
24563
|
-
/** The sessionId is stored in the localStorage to allow for reconnection and
|
|
24564
|
-
* to prevent spamming start requests of instances, when smashing F5.
|
|
24565
|
-
*/
|
|
24566
|
-
class Session {
|
|
24567
|
-
get current() {
|
|
24568
|
-
return this._current;
|
|
24569
|
-
}
|
|
24570
|
-
get noSession() {
|
|
24571
|
-
return new URLSearchParams(window.location.search).has("noSession");
|
|
24572
|
-
}
|
|
24573
|
-
get id() {
|
|
24574
|
-
// If the query-parameter "noSession" or "nosession" is set, it will be skipped.
|
|
24575
|
-
if (this.noSession)
|
|
24576
|
-
return null;
|
|
24577
|
-
const sessionString = window.localStorage.getItem(this.localStorageKey);
|
|
24578
|
-
// No session yet set.
|
|
24579
|
-
if (sessionString === null) {
|
|
24580
|
-
return null;
|
|
24860
|
+
// 3. UA sniffing fallback for mobile
|
|
24861
|
+
if (/\b(iPhone|Android.*Mobile|Windows Phone)\b/i.test(ua)) {
|
|
24862
|
+
return Type.Mobile;
|
|
24581
24863
|
}
|
|
24582
|
-
|
|
24583
|
-
|
|
24584
|
-
|
|
24585
|
-
this.unset();
|
|
24586
|
-
return null;
|
|
24864
|
+
// 4. Touch-capable with "tablet-like" dimensions
|
|
24865
|
+
if (("ontouchstart" in window || navigator.maxTouchPoints > 0) && minDim >= 600 && minDim <= 1100) {
|
|
24866
|
+
return Type.Tablet;
|
|
24587
24867
|
}
|
|
24588
|
-
|
|
24589
|
-
|
|
24590
|
-
|
|
24591
|
-
|
|
24592
|
-
|
|
24868
|
+
// 5. Default fallback
|
|
24869
|
+
return Type.Desktop;
|
|
24870
|
+
}
|
|
24871
|
+
getPowerHints() {
|
|
24872
|
+
const conn = navigator.connection;
|
|
24873
|
+
const saveData = typeof (conn === null || conn === void 0 ? void 0 : conn.saveData) === "boolean" ? conn.saveData : null;
|
|
24874
|
+
let prefersReducedData = null;
|
|
24875
|
+
let prefersReducedMotion = null;
|
|
24876
|
+
if (typeof window.matchMedia === "function") {
|
|
24877
|
+
try {
|
|
24878
|
+
const mqData = window.matchMedia("(prefers-reduced-data: reduce)");
|
|
24879
|
+
if (typeof mqData.matches === "boolean") {
|
|
24880
|
+
prefersReducedData = mqData.matches;
|
|
24881
|
+
}
|
|
24882
|
+
}
|
|
24883
|
+
catch (_a) { }
|
|
24884
|
+
try {
|
|
24885
|
+
const mqMotion = window.matchMedia("(prefers-reduced-motion: reduce)");
|
|
24886
|
+
if (typeof mqMotion.matches === "boolean") {
|
|
24887
|
+
prefersReducedMotion = mqMotion.matches;
|
|
24888
|
+
}
|
|
24889
|
+
}
|
|
24890
|
+
catch (_b) { }
|
|
24593
24891
|
}
|
|
24594
|
-
|
|
24595
|
-
|
|
24892
|
+
return { saveData, prefersReducedData, prefersReducedMotion };
|
|
24893
|
+
}
|
|
24894
|
+
getNetworkInfo(measuredDownlinkMbps) {
|
|
24895
|
+
const conn = navigator.connection;
|
|
24896
|
+
return {
|
|
24897
|
+
type: typeof (conn === null || conn === void 0 ? void 0 : conn.type) === "string" ? conn.type : null,
|
|
24898
|
+
effectiveType: typeof (conn === null || conn === void 0 ? void 0 : conn.effectiveType) === "string" ? conn.effectiveType : null,
|
|
24899
|
+
downlinkMbps: typeof (conn === null || conn === void 0 ? void 0 : conn.downlink) === "number" ? conn.downlink : null,
|
|
24900
|
+
rttMs: typeof (conn === null || conn === void 0 ? void 0 : conn.rtt) === "number" ? conn.rtt : null,
|
|
24901
|
+
measuredDownlinkMbps
|
|
24902
|
+
};
|
|
24903
|
+
}
|
|
24904
|
+
maybeMeasureBandwidth() {
|
|
24905
|
+
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
24906
|
+
const conn = navigator.connection;
|
|
24907
|
+
const saveData = (conn === null || conn === void 0 ? void 0 : conn.saveData) === true;
|
|
24908
|
+
if (!this.opts.enableBandwidthProbe)
|
|
24909
|
+
return null;
|
|
24910
|
+
if (this.opts.respectSaveData && saveData)
|
|
24911
|
+
return null;
|
|
24912
|
+
try {
|
|
24913
|
+
const t0 = performance.now();
|
|
24914
|
+
const res = yield fetch(this.withCacheBuster(this.opts.probeUrl), {
|
|
24915
|
+
cache: "no-store",
|
|
24916
|
+
credentials: "omit"
|
|
24917
|
+
});
|
|
24918
|
+
const buf = yield res.arrayBuffer();
|
|
24919
|
+
const t1 = performance.now();
|
|
24920
|
+
const bits = buf.byteLength * 8;
|
|
24921
|
+
const seconds = (t1 - t0) / 1000;
|
|
24922
|
+
if (seconds <= 0.05)
|
|
24923
|
+
return null; // ignore unstable samples
|
|
24924
|
+
return +(bits / seconds / 1000000).toFixed(2);
|
|
24925
|
+
}
|
|
24926
|
+
catch (_a) {
|
|
24927
|
+
return null;
|
|
24928
|
+
}
|
|
24929
|
+
});
|
|
24596
24930
|
}
|
|
24597
|
-
|
|
24598
|
-
|
|
24931
|
+
withCacheBuster(url) {
|
|
24932
|
+
var _a, _b;
|
|
24933
|
+
const u = new URL(url, location.origin);
|
|
24934
|
+
const token = (_b = (_a = crypto === null || crypto === void 0 ? void 0 : crypto.randomUUID) === null || _a === void 0 ? void 0 : _a.call(crypto)) !== null && _b !== void 0 ? _b : String(Date.now());
|
|
24935
|
+
u.searchParams.set("cb", token);
|
|
24936
|
+
return u.toString();
|
|
24599
24937
|
}
|
|
24600
|
-
|
|
24601
|
-
this
|
|
24938
|
+
getCodecSupport() {
|
|
24939
|
+
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
24940
|
+
const [h264, hevc] = yield Promise.all([
|
|
24941
|
+
this.supportsCodec('video/mp4; codecs="avc1.42E01E"'),
|
|
24942
|
+
this.supportsCodec('video/mp4; codecs="hvc1.1.6.L93.B0"')
|
|
24943
|
+
]);
|
|
24944
|
+
return { h264, hevc };
|
|
24945
|
+
});
|
|
24602
24946
|
}
|
|
24603
|
-
|
|
24604
|
-
|
|
24605
|
-
|
|
24606
|
-
|
|
24607
|
-
|
|
24608
|
-
|
|
24609
|
-
|
|
24610
|
-
|
|
24611
|
-
|
|
24612
|
-
|
|
24947
|
+
supportsCodec(mime) {
|
|
24948
|
+
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
24949
|
+
try {
|
|
24950
|
+
if ("mediaCapabilities" in navigator) {
|
|
24951
|
+
// @ts-ignore
|
|
24952
|
+
const res = yield navigator.mediaCapabilities.decodingInfo({
|
|
24953
|
+
type: "file",
|
|
24954
|
+
video: { contentType: mime, width: 1920, height: 1080, bitrate: 5000000, framerate: 30 }
|
|
24955
|
+
});
|
|
24956
|
+
return !!(res === null || res === void 0 ? void 0 : res.supported);
|
|
24957
|
+
}
|
|
24958
|
+
}
|
|
24959
|
+
catch (_a) { }
|
|
24960
|
+
try {
|
|
24961
|
+
const v = document.createElement("video");
|
|
24962
|
+
return v.canPlayType(mime) !== "";
|
|
24963
|
+
}
|
|
24964
|
+
catch (_b) {
|
|
24965
|
+
return false;
|
|
24966
|
+
}
|
|
24967
|
+
});
|
|
24613
24968
|
}
|
|
24614
|
-
|
|
24615
|
-
|
|
24616
|
-
|
|
24969
|
+
getUAInfo() {
|
|
24970
|
+
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
24971
|
+
if (this.uaInfoCache)
|
|
24972
|
+
return this.uaInfoCache;
|
|
24973
|
+
const nav = navigator;
|
|
24974
|
+
const uaData = nav.userAgentData;
|
|
24975
|
+
const ua = navigator.userAgent;
|
|
24976
|
+
let browserFamily = "Unknown";
|
|
24977
|
+
let browserVersion = null;
|
|
24978
|
+
let osFamily = "Unknown";
|
|
24979
|
+
let osVersion = null;
|
|
24980
|
+
let model = null;
|
|
24981
|
+
let architecture = null;
|
|
24982
|
+
let bitness = null;
|
|
24983
|
+
// --- UA-CH (modern browsers) ---
|
|
24984
|
+
if (uaData === null || uaData === void 0 ? void 0 : uaData.getHighEntropyValues) {
|
|
24985
|
+
try {
|
|
24986
|
+
const high = yield uaData.getHighEntropyValues([
|
|
24987
|
+
"platform",
|
|
24988
|
+
"platformVersion",
|
|
24989
|
+
"model",
|
|
24990
|
+
"architecture",
|
|
24991
|
+
"bitness",
|
|
24992
|
+
"fullVersionList"
|
|
24993
|
+
]);
|
|
24994
|
+
osFamily = high.platform || "Unknown";
|
|
24995
|
+
osVersion = high.platformVersion || null;
|
|
24996
|
+
model = high.model || null;
|
|
24997
|
+
architecture = high.architecture || null;
|
|
24998
|
+
bitness = high.bitness || null;
|
|
24999
|
+
const brands = high.fullVersionList || uaData.brands || [];
|
|
25000
|
+
const realBrand = brands.find((b) => {
|
|
25001
|
+
if (!b.brand)
|
|
25002
|
+
return false;
|
|
25003
|
+
const normalized = b.brand.replace(/[^a-zA-Z]/g, "").toLowerCase();
|
|
25004
|
+
return !normalized.includes("chromium") && !normalized.includes("notabrand");
|
|
25005
|
+
});
|
|
25006
|
+
if (realBrand) {
|
|
25007
|
+
browserFamily = realBrand.brand;
|
|
25008
|
+
browserVersion = realBrand.version;
|
|
25009
|
+
}
|
|
25010
|
+
}
|
|
25011
|
+
catch (_a) {
|
|
25012
|
+
// silently fail
|
|
25013
|
+
}
|
|
25014
|
+
}
|
|
25015
|
+
// --- Fallback to classic UA parsing if browser unknown ---
|
|
25016
|
+
if (!browserFamily || browserFamily === "Unknown") {
|
|
25017
|
+
const browserRegexes = [
|
|
25018
|
+
[/Edg\/(\S+)/, "Edge"],
|
|
25019
|
+
[/OPR\/(\S+)/, "Opera"],
|
|
25020
|
+
[/SamsungBrowser\/(\S+)/, "Samsung Internet"],
|
|
25021
|
+
[/Firefox\/(\S+)/, "Firefox"],
|
|
25022
|
+
[/Chrome\/(\S+)/, "Chrome"],
|
|
25023
|
+
[/Version\/(\S+).*Safari/, "Safari"]
|
|
25024
|
+
];
|
|
25025
|
+
for (const [regex, name] of browserRegexes) {
|
|
25026
|
+
const match = ua.match(regex);
|
|
25027
|
+
if (match) {
|
|
25028
|
+
browserFamily = name;
|
|
25029
|
+
browserVersion = match[1];
|
|
25030
|
+
break;
|
|
25031
|
+
}
|
|
25032
|
+
}
|
|
25033
|
+
}
|
|
25034
|
+
// --- OS detection (always run, iOS first) ---
|
|
25035
|
+
if (/iPhone|iPad|iPod/.test(ua)) {
|
|
25036
|
+
osFamily = "iOS";
|
|
25037
|
+
const match = ua.match(/OS (\d+[_\d]*)/);
|
|
25038
|
+
if (match)
|
|
25039
|
+
osVersion = match[1].replace(/_/g, ".");
|
|
25040
|
+
}
|
|
25041
|
+
else if (uaData === null || uaData === void 0 ? void 0 : uaData.platform) {
|
|
25042
|
+
osFamily = uaData.platform;
|
|
25043
|
+
}
|
|
25044
|
+
else if (/Windows/.test(ua)) {
|
|
25045
|
+
osFamily = "Windows";
|
|
25046
|
+
const match = ua.match(/Windows NT (\d+\.\d+)/);
|
|
25047
|
+
if (match)
|
|
25048
|
+
osVersion = match[1];
|
|
25049
|
+
}
|
|
25050
|
+
else if (/Mac OS X/.test(ua)) {
|
|
25051
|
+
osFamily = "macOS";
|
|
25052
|
+
const match = ua.match(/Mac OS X (\d+[_\d]*)/);
|
|
25053
|
+
if (match)
|
|
25054
|
+
osVersion = match[1].replace(/_/g, ".");
|
|
25055
|
+
}
|
|
25056
|
+
else if (/Android/.test(ua)) {
|
|
25057
|
+
osFamily = "Android";
|
|
25058
|
+
const match = ua.match(/Android (\d+(\.\d+)?)/);
|
|
25059
|
+
if (match)
|
|
25060
|
+
osVersion = match[1];
|
|
25061
|
+
}
|
|
25062
|
+
else if (/Linux/.test(ua)) {
|
|
25063
|
+
osFamily = "Linux";
|
|
25064
|
+
}
|
|
25065
|
+
const result = { browserFamily, browserVersion, osFamily, osVersion, model, architecture, bitness };
|
|
25066
|
+
this.uaInfoCache = result;
|
|
25067
|
+
return result;
|
|
25068
|
+
});
|
|
24617
25069
|
}
|
|
24618
25070
|
}
|
|
24619
|
-
exports.
|
|
25071
|
+
exports.DiagnosticsCollector = DiagnosticsCollector;
|
|
24620
25072
|
|
|
24621
25073
|
|
|
24622
25074
|
/***/ }),
|
|
24623
25075
|
|
|
24624
|
-
/***/
|
|
24625
|
-
/***/ ((__unused_webpack_module, exports
|
|
25076
|
+
/***/ 2483:
|
|
25077
|
+
/***/ ((__unused_webpack_module, exports) => {
|
|
24626
25078
|
|
|
24627
25079
|
|
|
24628
25080
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
24629
|
-
exports.
|
|
24630
|
-
|
|
24631
|
-
function
|
|
24632
|
-
|
|
24633
|
-
|
|
24634
|
-
|
|
24635
|
-
|
|
24636
|
-
|
|
24637
|
-
|
|
24638
|
-
|
|
24639
|
-
|
|
24640
|
-
|
|
24641
|
-
|
|
24642
|
-
|
|
24643
|
-
|
|
24644
|
-
|
|
24645
|
-
|
|
24646
|
-
|
|
24647
|
-
|
|
24648
|
-
|
|
24649
|
-
|
|
24650
|
-
|
|
24651
|
-
|
|
24652
|
-
framesPerSecond: forceNumber(stats.inboundVideoStats.framesPerSecond),
|
|
24653
|
-
// frames dropped (last) for ticket
|
|
24654
|
-
framesDropped: forceNumber(stats.inboundVideoStats.framesDropped),
|
|
24655
|
-
// Videocodec (once) for ticket
|
|
24656
|
-
videoCodec: stats.inboundVideoStats.codecId,
|
|
24657
|
-
// audiocodec (once) for ticket
|
|
24658
|
-
audioCodec: stats.inboundAudioStats.codecId,
|
|
24659
|
-
// browser type and version for ticket (arcware / addition)
|
|
24660
|
-
browserInfo: {
|
|
24661
|
-
// to be received!
|
|
24662
|
-
userAgent: navigator.userAgent,
|
|
24663
|
-
platform: navigator.oscpu || navigator.platform || null,
|
|
24664
|
-
language: navigator.language,
|
|
24665
|
-
},
|
|
24666
|
-
// Net RTT (low, high, avg)
|
|
24667
|
-
// BEGIN TW CHANGE
|
|
24668
|
-
currentRTT: calcRTT(stats.candidatePairs),
|
|
24669
|
-
// END TW CHANGE
|
|
24670
|
-
// Duration (last)
|
|
24671
|
-
sessionRunTime: stats.sessionStats.runTime,
|
|
24672
|
-
// Controls stream input (??)
|
|
24673
|
-
controlsStreamInput: stats.sessionStats.controlsStreamInput,
|
|
24674
|
-
// video quantization parameter (low / high / avg if applicable)
|
|
24675
|
-
videoEncoderAvgQP: forceNumber(stats.sessionStats.videoEncoderAvgQP),
|
|
24676
|
-
// Video bitrate (min / max / avg)
|
|
24677
|
-
videoBitrate: forceNumber(stats.inboundVideoStats.bitrate),
|
|
24678
|
-
// Audio bitrate (min / max / avg)
|
|
24679
|
-
audioBitrate: forceNumber(stats.inboundAudioStats.bitrate),
|
|
24680
|
-
});
|
|
24681
|
-
return result;
|
|
24682
|
-
}
|
|
24683
|
-
exports.Stats = Stats;
|
|
24684
|
-
/**
|
|
24685
|
-
* Given an array of candidate pairs this function will find the highest RTT for the selected pair
|
|
24686
|
-
* @param pairs - An array of candidate pairs
|
|
24687
|
-
* @returns The highest round trip time of a selected candidate pair
|
|
24688
|
-
*/
|
|
24689
|
-
function calcRTT(pairs) {
|
|
24690
|
-
let rtt = 0;
|
|
24691
|
-
pairs.forEach((pair) => {
|
|
24692
|
-
if (pair.selected && pair.currentRoundTripTime > rtt) {
|
|
24693
|
-
rtt = pair.currentRoundTripTime;
|
|
25081
|
+
exports.normalizeType = exports.randomHash = exports.extFromMime = exports.sanitizeFilename = exports.truncateByBytes = exports.parseUnknownToObject = void 0;
|
|
25082
|
+
/** Conservative normalizer: accepts object, strict JSON string, or JSON-ish like {foo: "bar"} */
|
|
25083
|
+
function parseUnknownToObject(input, opts = { allowJsonish: true }) {
|
|
25084
|
+
if (input && typeof input === "object")
|
|
25085
|
+
return input;
|
|
25086
|
+
if (typeof input === "string") {
|
|
25087
|
+
try {
|
|
25088
|
+
const parsed = JSON.parse(input);
|
|
25089
|
+
if (parsed && typeof parsed === "object")
|
|
25090
|
+
return parsed;
|
|
25091
|
+
}
|
|
25092
|
+
catch (_a) { }
|
|
25093
|
+
if (opts.allowJsonish) {
|
|
25094
|
+
const repaired = input
|
|
25095
|
+
.trim()
|
|
25096
|
+
.replace(/'/g, '"')
|
|
25097
|
+
.replace(/([{,]\s*)([A-Za-z_][$\w-]*)(\s*:)/g, '$1"$2"$3');
|
|
25098
|
+
try {
|
|
25099
|
+
const parsed = JSON.parse(repaired);
|
|
25100
|
+
if (parsed && typeof parsed === "object")
|
|
25101
|
+
return parsed;
|
|
25102
|
+
}
|
|
25103
|
+
catch (_b) { }
|
|
24694
25104
|
}
|
|
24695
|
-
}
|
|
24696
|
-
|
|
24697
|
-
}
|
|
24698
|
-
/**
|
|
24699
|
-
* Takes a number and forces it to return a number. If the value passed in is NaN, 0 will be returned.
|
|
24700
|
-
* @param value - A number
|
|
24701
|
-
* @returns The number passed in as value or 0 if vlaue was NaN
|
|
24702
|
-
*/
|
|
24703
|
-
function forceNumber(value) {
|
|
24704
|
-
return isNaN(value) ? 0 : value;
|
|
25105
|
+
}
|
|
25106
|
+
throw new Error("Input must be an object or a JSON string of an object.");
|
|
24705
25107
|
}
|
|
24706
|
-
|
|
24707
|
-
|
|
24708
|
-
|
|
24709
|
-
|
|
24710
|
-
|
|
24711
|
-
|
|
24712
|
-
|
|
24713
|
-
|
|
24714
|
-
|
|
24715
|
-
|
|
24716
|
-
|
|
24717
|
-
|
|
24718
|
-
|
|
24719
|
-
|
|
25108
|
+
exports.parseUnknownToObject = parseUnknownToObject;
|
|
25109
|
+
/** Byte-safe string truncation (no broken unicode) */
|
|
25110
|
+
function truncateByBytes(input, maxBytes) {
|
|
25111
|
+
const enc = new TextEncoder();
|
|
25112
|
+
const dec = new TextDecoder();
|
|
25113
|
+
const bytes = enc.encode(input);
|
|
25114
|
+
if (bytes.byteLength <= maxBytes)
|
|
25115
|
+
return input;
|
|
25116
|
+
// Back off until decode works
|
|
25117
|
+
for (let cut = maxBytes; cut > 0; cut--) {
|
|
25118
|
+
try {
|
|
25119
|
+
return dec.decode(bytes.subarray(0, cut), { stream: false });
|
|
25120
|
+
}
|
|
25121
|
+
catch (_a) { }
|
|
25122
|
+
}
|
|
25123
|
+
return "";
|
|
25124
|
+
}
|
|
25125
|
+
exports.truncateByBytes = truncateByBytes;
|
|
25126
|
+
/** Cross-platform safe filename */
|
|
25127
|
+
function sanitizeFilename(input) {
|
|
25128
|
+
let name = input.replace(/\s+/g, " ").trim();
|
|
25129
|
+
name = name.replace(/[\\\/:\*\?"<>\|\u0000-\u001F]+/g, "");
|
|
25130
|
+
name = name.replace(/^\.+/, ""); // avoid hidden files
|
|
25131
|
+
const reserved = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\..*)?$/i;
|
|
25132
|
+
if (reserved.test(name) || !name)
|
|
25133
|
+
name = randomHash();
|
|
25134
|
+
if (name.length > 100)
|
|
25135
|
+
name = name.slice(0, 100);
|
|
25136
|
+
return name;
|
|
25137
|
+
}
|
|
25138
|
+
exports.sanitizeFilename = sanitizeFilename;
|
|
25139
|
+
/** MIME -> extension */
|
|
25140
|
+
function extFromMime(mime) {
|
|
25141
|
+
const map = {
|
|
25142
|
+
"image/png": ".png",
|
|
25143
|
+
"image/jpeg": ".jpg",
|
|
25144
|
+
"image/jpg": ".jpg",
|
|
25145
|
+
"image/webp": ".webp",
|
|
25146
|
+
"image/gif": ".gif",
|
|
25147
|
+
"image/bmp": ".bmp",
|
|
25148
|
+
"image/tiff": ".tiff",
|
|
25149
|
+
"video/mp4": ".mp4",
|
|
25150
|
+
"video/webm": ".webm",
|
|
25151
|
+
"video/ogg": ".ogv",
|
|
25152
|
+
"audio/mpeg": ".mp3",
|
|
25153
|
+
"audio/ogg": ".ogg",
|
|
25154
|
+
"audio/wav": ".wav",
|
|
25155
|
+
"audio/webm": ".weba",
|
|
25156
|
+
"application/pdf": ".pdf",
|
|
25157
|
+
"application/zip": ".zip",
|
|
25158
|
+
"application/x-zip-compressed": ".zip",
|
|
25159
|
+
"application/json": ".json",
|
|
25160
|
+
"text/plain": ".txt",
|
|
25161
|
+
"text/csv": ".csv"
|
|
24720
25162
|
};
|
|
25163
|
+
if (map[mime])
|
|
25164
|
+
return map[mime];
|
|
25165
|
+
if (mime.startsWith("image/") || mime.startsWith("video/") || mime.startsWith("audio/")) {
|
|
25166
|
+
return "." + mime.split("/")[1];
|
|
25167
|
+
}
|
|
25168
|
+
return "";
|
|
24721
25169
|
}
|
|
24722
|
-
exports
|
|
25170
|
+
exports.extFromMime = extFromMime;
|
|
25171
|
+
/** Short random fallback */
|
|
25172
|
+
function randomHash() {
|
|
25173
|
+
return Math.random().toString(36).slice(2, 8);
|
|
25174
|
+
}
|
|
25175
|
+
exports.randomHash = randomHash;
|
|
25176
|
+
function normalizeType(v) {
|
|
25177
|
+
return typeof v === "string" ? v.trim().toLowerCase() : "";
|
|
25178
|
+
}
|
|
25179
|
+
exports.normalizeType = normalizeType;
|
|
24723
25180
|
|
|
24724
25181
|
|
|
24725
25182
|
/***/ }),
|