@arcware-cloud/pixelstreaming-websdk 1.2.14 → 1.2.15

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 CHANGED
@@ -23351,7 +23351,7 @@ class ArcwareConfig extends lib_pixelstreamingfrontend_ue5_5_1.Config {
23351
23351
  if (!config.initialSettings.ss)
23352
23352
  config.initialSettings.ss = exports.DefaultUrl;
23353
23353
  super(config);
23354
- this.VERSION = "1.2.14";
23354
+ this.VERSION = "1.2.15";
23355
23355
  this.settings = settings;
23356
23356
  this.session = new Session_1.Session();
23357
23357
  this._initialSettings = config.initialSettings;
@@ -23492,6 +23492,7 @@ exports.ArcwareInit = ArcwareInit;
23492
23492
 
23493
23493
  Object.defineProperty(exports, "__esModule", ({ value: true }));
23494
23494
  exports.ArcwarePixelStreaming = void 0;
23495
+ const tslib_1 = __webpack_require__(655);
23495
23496
  const shared_pixelstreaming_websdk_1 = __webpack_require__(7910);
23496
23497
  const lib_pixelstreamingfrontend_ue5_5_1 = __webpack_require__(693);
23497
23498
  const ApplyUrlHack_1 = __webpack_require__(4790);
@@ -23502,6 +23503,7 @@ const LoveLetters_1 = __webpack_require__(4572);
23502
23503
  const ArcwareLogoLoader_1 = __webpack_require__(6469);
23503
23504
  const MicrophoneOverlay_1 = __webpack_require__(3613);
23504
23505
  const ConnectionIdentifier_1 = __webpack_require__(5999);
23506
+ const DiagnosticsCollector_1 = __webpack_require__(6478);
23505
23507
  class ArcwarePixelStreaming extends lib_pixelstreamingfrontend_ue5_5_1.PixelStreaming {
23506
23508
  /** Returns a list of WebSocketStates of all PixelStreaming Instances generated. */
23507
23509
  get WebsocketStates() {
@@ -23549,6 +23551,9 @@ class ArcwarePixelStreaming extends lib_pixelstreamingfrontend_ue5_5_1.PixelStre
23549
23551
  this.config = config;
23550
23552
  this.loveLettersList = [];
23551
23553
  this.microphoneOverlay = new MicrophoneOverlay_1.MicrophoneOverlay(this);
23554
+ this.diagnosticsCollector = new DiagnosticsCollector_1.DiagnosticsCollector({
23555
+ enableBandwidthProbe: false,
23556
+ });
23552
23557
  // this.loveLettersContainer = null;
23553
23558
  this.wrapWebSocketOnCloseHandler();
23554
23559
  // Bind the event listener function to the class instance
@@ -23607,7 +23612,10 @@ class ArcwarePixelStreaming extends lib_pixelstreamingfrontend_ue5_5_1.PixelStre
23607
23612
  */
23608
23613
  /** On version requested, the version of the WebSDK would be returned. */
23609
23614
  onVersion(message) {
23610
- this.send({ type: "version", version: this.config.VERSION });
23615
+ return tslib_1.__awaiter(this, void 0, void 0, function* () {
23616
+ const diagnostics = yield this.diagnosticsCollector.collect();
23617
+ this.send({ type: "version", version: this.config.VERSION, diagnostics });
23618
+ });
23611
23619
  }
23612
23620
  /** On ping the session creation timestamp will be updated. */
23613
23621
  onPing(message) {
@@ -23939,6 +23947,339 @@ class ArcwarePixelStreaming extends lib_pixelstreamingfrontend_ue5_5_1.PixelStre
23939
23947
  exports.ArcwarePixelStreaming = ArcwarePixelStreaming;
23940
23948
 
23941
23949
 
23950
+ /***/ }),
23951
+
23952
+ /***/ 6478:
23953
+ /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
23954
+
23955
+
23956
+ /**
23957
+ * DiagnosticsCollector.ts
23958
+ * Lightweight, privacy-aware client diagnostics for troubleshooting + analytics.
23959
+ * WebRTC collection intentionally omitted (to add later).
23960
+ *
23961
+ * Notes:
23962
+ * - Some fields are best-effort due to browser restrictions; they're nullable.
23963
+ * - Bandwidth probe requires a small binary served with:
23964
+ * Content-Type: application/octet-stream
23965
+ * Content-Encoding: identity
23966
+ * Cache-Control: no-store
23967
+ * Default location: /diag/probe.bin
23968
+ */
23969
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
23970
+ exports.DiagnosticsCollector = void 0;
23971
+ const tslib_1 = __webpack_require__(655);
23972
+ /**
23973
+ * DiagnosticsCollector
23974
+ */
23975
+ class DiagnosticsCollector {
23976
+ constructor(opts = {}) {
23977
+ var _a, _b, _c, _d;
23978
+ this.opts = {
23979
+ enableBandwidthProbe: (_a = opts.enableBandwidthProbe) !== null && _a !== void 0 ? _a : true,
23980
+ probeUrl: (_b = opts.probeUrl) !== null && _b !== void 0 ? _b : '/diag/probe.bin',
23981
+ respectSaveData: (_c = opts.respectSaveData) !== null && _c !== void 0 ? _c : true,
23982
+ sampleRate: Math.max(0, Math.min(1, (_d = opts.sampleRate) !== null && _d !== void 0 ? _d : 1))
23983
+ };
23984
+ }
23985
+ /**
23986
+ * Collect the diagnostics payload.
23987
+ */
23988
+ collect() {
23989
+ var _a, _b;
23990
+ return tslib_1.__awaiter(this, void 0, void 0, function* () {
23991
+ if (!this.shouldSample()) {
23992
+ return {
23993
+ device: { type: 'desktop', touchSupport: false },
23994
+ runtime: { browser: { family: 'Unknown', version: null }, os: { family: 'Unknown', version: null } },
23995
+ powerHints: { saveData: null, prefersReducedData: null, prefersReducedMotion: null },
23996
+ network: { type: null, effectiveType: null, downlinkMbps: null, rttMs: null, measuredDownlinkMbps: null },
23997
+ timestamps: { collectedAt: Date.now() }
23998
+ };
23999
+ }
24000
+ const collectedAt = Date.now();
24001
+ const [uaInfo, codecSupport, measuredDownlinkMbps] = yield Promise.all([
24002
+ this.getUAInfo(),
24003
+ this.getCodecSupport(),
24004
+ this.maybeMeasureBandwidth()
24005
+ ]);
24006
+ return {
24007
+ device: {
24008
+ type: this.inferDeviceType(),
24009
+ vendor: null,
24010
+ model: uaInfo.model,
24011
+ architecture: uaInfo.architecture,
24012
+ bitness: uaInfo.bitness,
24013
+ touchSupport: this.hasTouch(),
24014
+ hardwareConcurrency: (_a = navigator.hardwareConcurrency) !== null && _a !== void 0 ? _a : null,
24015
+ deviceMemory: (_b = navigator.deviceMemory) !== null && _b !== void 0 ? _b : null,
24016
+ orientation: this.getOrientation(),
24017
+ webgl: this.hasWebGL(),
24018
+ codecs: codecSupport
24019
+ },
24020
+ runtime: {
24021
+ browser: { family: uaInfo.browserFamily, version: uaInfo.browserVersion },
24022
+ os: { family: uaInfo.osFamily, version: uaInfo.osVersion }
24023
+ },
24024
+ powerHints: this.getPowerHints(),
24025
+ network: this.getNetworkInfo(measuredDownlinkMbps),
24026
+ timestamps: { collectedAt }
24027
+ };
24028
+ });
24029
+ }
24030
+ /**
24031
+ * Collect a safe subset of WebRTC stats once PC is connected.
24032
+ */
24033
+ collectWebRTC(pc) {
24034
+ var _a, _b, _c, _d, _e, _f;
24035
+ return tslib_1.__awaiter(this, void 0, void 0, function* () {
24036
+ try {
24037
+ const stats = yield pc.getStats();
24038
+ let selected, transport, local, remote;
24039
+ stats.forEach((r) => {
24040
+ if (r.type === 'transport' && r.selectedCandidatePairId)
24041
+ transport = r;
24042
+ if (r.type === 'candidate-pair' && (r.selected || r.nominated))
24043
+ selected = r;
24044
+ });
24045
+ if (selected) {
24046
+ local = stats.get(selected.localCandidateId);
24047
+ remote = stats.get(selected.remoteCandidateId);
24048
+ }
24049
+ return {
24050
+ candidatePairId: (_a = selected === null || selected === void 0 ? void 0 : selected.id) !== null && _a !== void 0 ? _a : null,
24051
+ localCandidateType: (_b = local === null || local === void 0 ? void 0 : local.candidateType) !== null && _b !== void 0 ? _b : null,
24052
+ remoteCandidateType: (_c = remote === null || remote === void 0 ? void 0 : remote.candidateType) !== null && _c !== void 0 ? _c : null,
24053
+ protocol: (_d = local === null || local === void 0 ? void 0 : local.protocol) !== null && _d !== void 0 ? _d : null,
24054
+ networkType: (_e = local === null || local === void 0 ? void 0 : local.networkType) !== null && _e !== void 0 ? _e : null,
24055
+ dtlsCipher: (_f = transport === null || transport === void 0 ? void 0 : transport.dtlsCipher) !== null && _f !== void 0 ? _f : null
24056
+ };
24057
+ }
24058
+ catch (_g) {
24059
+ return {};
24060
+ }
24061
+ });
24062
+ }
24063
+ /**
24064
+ * Helper to embed diagnostics in a hello envelope.
24065
+ */
24066
+ buildHelloEnvelope(base, pc) {
24067
+ return tslib_1.__awaiter(this, void 0, void 0, function* () {
24068
+ const diag = yield this.collect();
24069
+ const webrtc = pc ? yield this.collectWebRTC(pc) : undefined;
24070
+ const ext = webrtc ? { diag: Object.assign(Object.assign({}, diag), { webrtc }) } : { diag };
24071
+ return Object.assign(Object.assign({}, base), { ext });
24072
+ });
24073
+ }
24074
+ // ---------- Internals ----------
24075
+ shouldSample() {
24076
+ if (this.opts.sampleRate >= 1)
24077
+ return true;
24078
+ return Math.random() < this.opts.sampleRate;
24079
+ }
24080
+ hasTouch() {
24081
+ var _a;
24082
+ const nav = navigator;
24083
+ return 'ontouchstart' in window || ((_a = nav.maxTouchPoints) !== null && _a !== void 0 ? _a : 0) > 0;
24084
+ }
24085
+ getOrientation() {
24086
+ var _a;
24087
+ try {
24088
+ if ((_a = screen.orientation) === null || _a === void 0 ? void 0 : _a.type) {
24089
+ return screen.orientation.type.startsWith('portrait') ? 'portrait' : 'landscape';
24090
+ }
24091
+ if (window.matchMedia) {
24092
+ return window.matchMedia('(orientation: portrait)').matches ? 'portrait' : 'landscape';
24093
+ }
24094
+ }
24095
+ catch (_b) { }
24096
+ return null;
24097
+ }
24098
+ hasWebGL() {
24099
+ try {
24100
+ const canvas = document.createElement('canvas');
24101
+ return !!(canvas.getContext('webgl') || canvas.getContext('experimental-webgl'));
24102
+ }
24103
+ catch (_a) {
24104
+ return false;
24105
+ }
24106
+ }
24107
+ /**
24108
+ * Heuristic device type: best-effort only.
24109
+ */
24110
+ inferDeviceType() {
24111
+ const uaData = navigator.userAgentData;
24112
+ const isMobileCH = (uaData === null || uaData === void 0 ? void 0 : uaData.mobile) === true;
24113
+ const minDim = Math.min(screen.width, screen.height);
24114
+ if (isMobileCH && minDim >= 600)
24115
+ return 'tablet';
24116
+ if (isMobileCH)
24117
+ return 'mobile';
24118
+ if (/\b(iPad|Tablet)\b/i.test(navigator.userAgent))
24119
+ return 'tablet';
24120
+ if (('ontouchstart' in window) && minDim >= 600 && minDim <= 1100)
24121
+ return 'tablet';
24122
+ return 'desktop';
24123
+ }
24124
+ getPowerHints() {
24125
+ const conn = navigator.connection;
24126
+ const saveData = typeof (conn === null || conn === void 0 ? void 0 : conn.saveData) === 'boolean' ? conn.saveData : null;
24127
+ let prefersReducedData = null;
24128
+ let prefersReducedMotion = null;
24129
+ if (typeof window.matchMedia === 'function') {
24130
+ try {
24131
+ const mqData = window.matchMedia('(prefers-reduced-data: reduce)');
24132
+ if (typeof mqData.matches === 'boolean') {
24133
+ prefersReducedData = mqData.matches;
24134
+ }
24135
+ }
24136
+ catch (_a) { }
24137
+ try {
24138
+ const mqMotion = window.matchMedia('(prefers-reduced-motion: reduce)');
24139
+ if (typeof mqMotion.matches === 'boolean') {
24140
+ prefersReducedMotion = mqMotion.matches;
24141
+ }
24142
+ }
24143
+ catch (_b) { }
24144
+ }
24145
+ return { saveData, prefersReducedData, prefersReducedMotion };
24146
+ }
24147
+ getNetworkInfo(measuredDownlinkMbps) {
24148
+ const conn = navigator.connection;
24149
+ return {
24150
+ type: (typeof (conn === null || conn === void 0 ? void 0 : conn.type) === 'string') ? conn.type : null,
24151
+ effectiveType: (typeof (conn === null || conn === void 0 ? void 0 : conn.effectiveType) === 'string') ? conn.effectiveType : null,
24152
+ downlinkMbps: (typeof (conn === null || conn === void 0 ? void 0 : conn.downlink) === 'number') ? conn.downlink : null,
24153
+ rttMs: (typeof (conn === null || conn === void 0 ? void 0 : conn.rtt) === 'number') ? conn.rtt : null,
24154
+ measuredDownlinkMbps
24155
+ };
24156
+ }
24157
+ maybeMeasureBandwidth() {
24158
+ return tslib_1.__awaiter(this, void 0, void 0, function* () {
24159
+ const conn = navigator.connection;
24160
+ const saveData = (conn === null || conn === void 0 ? void 0 : conn.saveData) === true;
24161
+ if (!this.opts.enableBandwidthProbe)
24162
+ return null;
24163
+ if (this.opts.respectSaveData && saveData)
24164
+ return null;
24165
+ try {
24166
+ const t0 = performance.now();
24167
+ const res = yield fetch(this.withCacheBuster(this.opts.probeUrl), {
24168
+ cache: 'no-store',
24169
+ credentials: 'omit'
24170
+ });
24171
+ const buf = yield res.arrayBuffer();
24172
+ const t1 = performance.now();
24173
+ const bits = buf.byteLength * 8;
24174
+ const seconds = (t1 - t0) / 1000;
24175
+ if (seconds <= 0.05)
24176
+ return null; // ignore unstable samples
24177
+ return +((bits / seconds) / 1000000).toFixed(2);
24178
+ }
24179
+ catch (_a) {
24180
+ return null;
24181
+ }
24182
+ });
24183
+ }
24184
+ withCacheBuster(url) {
24185
+ var _a, _b;
24186
+ const u = new URL(url, location.origin);
24187
+ 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());
24188
+ u.searchParams.set('cb', token);
24189
+ return u.toString();
24190
+ }
24191
+ getCodecSupport() {
24192
+ return tslib_1.__awaiter(this, void 0, void 0, function* () {
24193
+ const [h264, hevc] = yield Promise.all([
24194
+ this.supportsCodec('video/mp4; codecs="avc1.42E01E"'),
24195
+ this.supportsCodec('video/mp4; codecs="hvc1.1.6.L93.B0"')
24196
+ ]);
24197
+ return { h264, hevc };
24198
+ });
24199
+ }
24200
+ supportsCodec(mime) {
24201
+ return tslib_1.__awaiter(this, void 0, void 0, function* () {
24202
+ try {
24203
+ if ('mediaCapabilities' in navigator) {
24204
+ // @ts-ignore
24205
+ const res = yield navigator.mediaCapabilities.decodingInfo({
24206
+ type: 'file',
24207
+ video: { contentType: mime, width: 1920, height: 1080, bitrate: 5000000, framerate: 30 }
24208
+ });
24209
+ return !!(res === null || res === void 0 ? void 0 : res.supported);
24210
+ }
24211
+ }
24212
+ catch (_a) { }
24213
+ try {
24214
+ const v = document.createElement('video');
24215
+ return v.canPlayType(mime) !== '';
24216
+ }
24217
+ catch (_b) {
24218
+ return false;
24219
+ }
24220
+ });
24221
+ }
24222
+ getUAInfo() {
24223
+ var _a, _b;
24224
+ return tslib_1.__awaiter(this, void 0, void 0, function* () {
24225
+ const nav = navigator;
24226
+ const uaData = nav.userAgentData;
24227
+ let browserFamily = 'Unknown', browserVersion = null;
24228
+ let osFamily = 'Unknown', osVersion = null;
24229
+ let model = null, architecture = null, bitness = null;
24230
+ if (uaData === null || uaData === void 0 ? void 0 : uaData.getHighEntropyValues) {
24231
+ try {
24232
+ const high = yield uaData.getHighEntropyValues([
24233
+ 'platform', 'platformVersion', 'model', 'architecture', 'bitness', 'fullVersionList'
24234
+ ]);
24235
+ osFamily = high.platform || 'Unknown';
24236
+ osVersion = high.platformVersion || null;
24237
+ model = high.model || null;
24238
+ architecture = high.architecture || null;
24239
+ bitness = high.bitness || null;
24240
+ const brands = high.fullVersionList || uaData.brands || [];
24241
+ const real = brands.find(b => b.brand && !/Chromium|Not:?A-?Brand/i.test(b.brand));
24242
+ browserFamily = (real === null || real === void 0 ? void 0 : real.brand) || ((_a = brands[0]) === null || _a === void 0 ? void 0 : _a.brand) || 'Unknown';
24243
+ browserVersion = (real === null || real === void 0 ? void 0 : real.version) || ((_b = brands[0]) === null || _b === void 0 ? void 0 : _b.version) || null;
24244
+ }
24245
+ catch (_c) { }
24246
+ }
24247
+ if (browserFamily === 'Unknown') {
24248
+ const ua = navigator.userAgent;
24249
+ if (/Firefox\/(\S+)/.test(ua)) {
24250
+ browserFamily = 'Firefox';
24251
+ browserVersion = RegExp.$1;
24252
+ }
24253
+ else if (/Edg\/(\S+)/.test(ua)) {
24254
+ browserFamily = 'Edge';
24255
+ browserVersion = RegExp.$1;
24256
+ }
24257
+ else if (/Chrome\/(\S+)/.test(ua)) {
24258
+ browserFamily = 'Chrome';
24259
+ browserVersion = RegExp.$1;
24260
+ }
24261
+ else if (/Version\/(\S+).*Safari/.test(ua)) {
24262
+ browserFamily = 'Safari';
24263
+ browserVersion = RegExp.$1;
24264
+ }
24265
+ if (/Windows/.test(ua))
24266
+ osFamily = 'Windows';
24267
+ else if (/Mac OS X/.test(ua))
24268
+ osFamily = 'macOS';
24269
+ else if (/Android/.test(ua))
24270
+ osFamily = 'Android';
24271
+ else if (/iPhone|iPad|iPod/.test(ua))
24272
+ osFamily = 'iOS';
24273
+ else if (/Linux/.test(ua))
24274
+ osFamily = 'Linux';
24275
+ }
24276
+ return { browserFamily, browserVersion, osFamily, osVersion, model, architecture, bitness };
24277
+ });
24278
+ }
24279
+ }
24280
+ exports.DiagnosticsCollector = DiagnosticsCollector;
24281
+
24282
+
23942
24283
  /***/ }),
23943
24284
 
23944
24285
  /***/ 5602:
package/index.esm.js CHANGED
@@ -23356,7 +23356,7 @@ class ArcwareConfig extends _epicgames_ps_lib_pixelstreamingfrontend_ue5_5__WEBP
23356
23356
  if (!config.initialSettings.ss)
23357
23357
  config.initialSettings.ss = DefaultUrl;
23358
23358
  super(config);
23359
- this.VERSION = "1.2.14";
23359
+ this.VERSION = "1.2.15";
23360
23360
  this.settings = settings;
23361
23361
  this.session = new _domain_Session__WEBPACK_IMPORTED_MODULE_0__.Session();
23362
23362
  this._initialSettings = config.initialSettings;
@@ -23500,18 +23500,22 @@ __webpack_require__.r(__webpack_exports__);
23500
23500
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
23501
23501
  /* harmony export */ "ArcwarePixelStreaming": () => (/* binding */ ArcwarePixelStreaming)
23502
23502
  /* harmony export */ });
23503
+ /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(655);
23503
23504
  /* harmony import */ var _arcware_cloud_shared_pixelstreaming_websdk__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(7910);
23504
23505
  /* harmony import */ var _epicgames_ps_lib_pixelstreamingfrontend_ue5_5__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(516);
23505
- /* harmony import */ var _epicgames_ps_lib_pixelstreamingfrontend_ue5_5__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(7800);
23506
- /* harmony import */ var _epicgames_ps_lib_pixelstreamingfrontend_ue5_5__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(7463);
23506
+ /* harmony import */ var _epicgames_ps_lib_pixelstreamingfrontend_ue5_5__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(7800);
23507
+ /* harmony import */ var _epicgames_ps_lib_pixelstreamingfrontend_ue5_5__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(7463);
23507
23508
  /* harmony import */ var _ApplyUrlHack__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(4790);
23508
23509
  /* harmony import */ var _domain_EventHandler__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(3379);
23509
23510
  /* harmony import */ var _domain_Stats__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(9764);
23510
- /* harmony import */ var _domain_debounce__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(9580);
23511
- /* harmony import */ var _ui_LoveLetters__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(4572);
23512
- /* harmony import */ var _ui_ArcwareLogoLoader__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(6469);
23511
+ /* harmony import */ var _domain_debounce__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(9580);
23512
+ /* harmony import */ var _ui_LoveLetters__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(4572);
23513
+ /* harmony import */ var _ui_ArcwareLogoLoader__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(6469);
23513
23514
  /* harmony import */ var _ui_MicrophoneOverlay__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(3613);
23514
23515
  /* harmony import */ var _domain_ConnectionIdentifier__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(5999);
23516
+ /* harmony import */ var _DiagnosticsCollector__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(6478);
23517
+
23518
+
23515
23519
 
23516
23520
 
23517
23521
 
@@ -23569,6 +23573,9 @@ class ArcwarePixelStreaming extends _epicgames_ps_lib_pixelstreamingfrontend_ue5
23569
23573
  this.config = config;
23570
23574
  this.loveLettersList = [];
23571
23575
  this.microphoneOverlay = new _ui_MicrophoneOverlay__WEBPACK_IMPORTED_MODULE_6__.MicrophoneOverlay(this);
23576
+ this.diagnosticsCollector = new _DiagnosticsCollector__WEBPACK_IMPORTED_MODULE_7__.DiagnosticsCollector({
23577
+ enableBandwidthProbe: false,
23578
+ });
23572
23579
  // this.loveLettersContainer = null;
23573
23580
  this.wrapWebSocketOnCloseHandler();
23574
23581
  // Bind the event listener function to the class instance
@@ -23582,7 +23589,7 @@ class ArcwarePixelStreaming extends _epicgames_ps_lib_pixelstreamingfrontend_ue5
23582
23589
  this.addMessageHandler("queue", _arcware_cloud_shared_pixelstreaming_websdk__WEBPACK_IMPORTED_MODULE_0__.Messages.ZQueue, this.onQueue);
23583
23590
  this.addMessageHandler("version", _arcware_cloud_shared_pixelstreaming_websdk__WEBPACK_IMPORTED_MODULE_0__.Messages.ZVersion, this.onVersion);
23584
23591
  // Create a debounced version of the handleResolutionChange function
23585
- const debouncedResolutionChange = (0,_domain_debounce__WEBPACK_IMPORTED_MODULE_7__["default"])(() => {
23592
+ const debouncedResolutionChange = (0,_domain_debounce__WEBPACK_IMPORTED_MODULE_8__["default"])(() => {
23586
23593
  this.handleResolutionChange();
23587
23594
  }, 0);
23588
23595
  // Register event listeners.
@@ -23627,7 +23634,10 @@ class ArcwarePixelStreaming extends _epicgames_ps_lib_pixelstreamingfrontend_ue5
23627
23634
  */
23628
23635
  /** On version requested, the version of the WebSDK would be returned. */
23629
23636
  onVersion(message) {
23630
- this.send({ type: "version", version: this.config.VERSION });
23637
+ return (0,tslib__WEBPACK_IMPORTED_MODULE_9__.__awaiter)(this, void 0, void 0, function* () {
23638
+ const diagnostics = yield this.diagnosticsCollector.collect();
23639
+ this.send({ type: "version", version: this.config.VERSION, diagnostics });
23640
+ });
23631
23641
  }
23632
23642
  /** On ping the session creation timestamp will be updated. */
23633
23643
  onPing(message) {
@@ -23641,7 +23651,7 @@ class ArcwarePixelStreaming extends _epicgames_ps_lib_pixelstreamingfrontend_ue5
23641
23651
  // public readonly streamInfoHandler = new EventHandler<never>();
23642
23652
  onStreamInfo(streamInfo) {
23643
23653
  var _a, _b, _c, _d;
23644
- _epicgames_ps_lib_pixelstreamingfrontend_ue5_5__WEBPACK_IMPORTED_MODULE_8__.Logger.Info(`StreamInfo received.`);
23654
+ _epicgames_ps_lib_pixelstreamingfrontend_ue5_5__WEBPACK_IMPORTED_MODULE_10__.Logger.Info(`StreamInfo received.`);
23645
23655
  // Save the streamInfo to the instance variable
23646
23656
  this.streamInfo = streamInfo;
23647
23657
  // By setting this hidden flag, the evaluation of the streamInfo can be cut off.
@@ -23649,8 +23659,8 @@ class ArcwarePixelStreaming extends _epicgames_ps_lib_pixelstreamingfrontend_ue5
23649
23659
  if (!((_b = (_a = this.config) === null || _a === void 0 ? void 0 : _a.settings) === null || _b === void 0 ? void 0 : _b["do-not-eval-streamInfo"])) {
23650
23660
  const { afk } = streamInfo.streamInfo;
23651
23661
  if (afk) {
23652
- this.config.setFlagEnabled(_epicgames_ps_lib_pixelstreamingfrontend_ue5_5__WEBPACK_IMPORTED_MODULE_9__.Flags.AFKDetection, afk.enabled);
23653
- this.config.setNumericSetting(_epicgames_ps_lib_pixelstreamingfrontend_ue5_5__WEBPACK_IMPORTED_MODULE_9__.NumericParameters.AFKTimeoutSecs, afk.warn + afk.error);
23662
+ this.config.setFlagEnabled(_epicgames_ps_lib_pixelstreamingfrontend_ue5_5__WEBPACK_IMPORTED_MODULE_11__.Flags.AFKDetection, afk.enabled);
23663
+ this.config.setNumericSetting(_epicgames_ps_lib_pixelstreamingfrontend_ue5_5__WEBPACK_IMPORTED_MODULE_11__.NumericParameters.AFKTimeoutSecs, afk.warn + afk.error);
23654
23664
  // Hack
23655
23665
  const { afkController } = this.webRtcController;
23656
23666
  afkController.countDown = afk.action;
@@ -23673,11 +23683,11 @@ class ArcwarePixelStreaming extends _epicgames_ps_lib_pixelstreamingfrontend_ue5
23673
23683
  // EventHandler.Emit(this.streamInfoHandler, undefined as never);
23674
23684
  }
23675
23685
  onQueue(message) {
23676
- _epicgames_ps_lib_pixelstreamingfrontend_ue5_5__WEBPACK_IMPORTED_MODULE_8__.Logger.Info(`QueueInfo received.`);
23686
+ _epicgames_ps_lib_pixelstreamingfrontend_ue5_5__WEBPACK_IMPORTED_MODULE_10__.Logger.Info(`QueueInfo received.`);
23677
23687
  _domain_EventHandler__WEBPACK_IMPORTED_MODULE_5__.EventHandler.Emit(this.queueHandler, message);
23678
23688
  }
23679
23689
  onError(error) {
23680
- _epicgames_ps_lib_pixelstreamingfrontend_ue5_5__WEBPACK_IMPORTED_MODULE_8__.Logger.Error(error.type);
23690
+ _epicgames_ps_lib_pixelstreamingfrontend_ue5_5__WEBPACK_IMPORTED_MODULE_10__.Logger.Error(error.type);
23681
23691
  _domain_EventHandler__WEBPACK_IMPORTED_MODULE_5__.EventHandler.Emit(this.errorHandler, error);
23682
23692
  }
23683
23693
  onLoveLetter(loveLetter) {
@@ -23688,7 +23698,7 @@ class ArcwarePixelStreaming extends _epicgames_ps_lib_pixelstreamingfrontend_ue5
23688
23698
  this.pushLetter(loveLetter.reason);
23689
23699
  }
23690
23700
  onSessionId(message) {
23691
- _epicgames_ps_lib_pixelstreamingfrontend_ue5_5__WEBPACK_IMPORTED_MODULE_8__.Logger.Info(message.sessionId);
23701
+ _epicgames_ps_lib_pixelstreamingfrontend_ue5_5__WEBPACK_IMPORTED_MODULE_10__.Logger.Info(message.sessionId);
23692
23702
  // console.info(`Session: ${message.sessionId}`);
23693
23703
  this.session.set(message.sessionId);
23694
23704
  _domain_EventHandler__WEBPACK_IMPORTED_MODULE_5__.EventHandler.Emit(this.sessionIdHandler, message.sessionId);
@@ -23714,7 +23724,7 @@ class ArcwarePixelStreaming extends _epicgames_ps_lib_pixelstreamingfrontend_ue5
23714
23724
  // This cast has to be done, since Frontend does not use typescript-strict setting.
23715
23725
  const parsedError = parsed;
23716
23726
  const error = new Error(`Unexpected message content. Event:'${type}', ZodError: ${parsedError.error.message}`);
23717
- _epicgames_ps_lib_pixelstreamingfrontend_ue5_5__WEBPACK_IMPORTED_MODULE_8__.Logger.Error(error.message);
23727
+ _epicgames_ps_lib_pixelstreamingfrontend_ue5_5__WEBPACK_IMPORTED_MODULE_10__.Logger.Error(error.message);
23718
23728
  }
23719
23729
  if (type === "error") {
23720
23730
  this.disconnect();
@@ -23739,7 +23749,7 @@ class ArcwarePixelStreaming extends _epicgames_ps_lib_pixelstreamingfrontend_ue5
23739
23749
  else {
23740
23750
  // This cast has to be done, since Frontend does not use typescript-strict setting.
23741
23751
  const parsedError = result;
23742
- _epicgames_ps_lib_pixelstreamingfrontend_ue5_5__WEBPACK_IMPORTED_MODULE_8__.Logger.Error(`Failed to send. ${parsedError.error}`);
23752
+ _epicgames_ps_lib_pixelstreamingfrontend_ue5_5__WEBPACK_IMPORTED_MODULE_10__.Logger.Error(`Failed to send. ${parsedError.error}`);
23743
23753
  }
23744
23754
  }
23745
23755
  else {
@@ -23816,7 +23826,7 @@ class ArcwarePixelStreaming extends _epicgames_ps_lib_pixelstreamingfrontend_ue5
23816
23826
  }
23817
23827
  initLoveLettersContainer() {
23818
23828
  var _a;
23819
- const logoLoader = new _ui_ArcwareLogoLoader__WEBPACK_IMPORTED_MODULE_10__.ArcwareLogoLoader();
23829
+ const logoLoader = new _ui_ArcwareLogoLoader__WEBPACK_IMPORTED_MODULE_12__.ArcwareLogoLoader();
23820
23830
  if (!this.loveLettersContainer) {
23821
23831
  const loveLettersContainer = document === null || document === void 0 ? void 0 : document.createElement("div");
23822
23832
  const { videoPlayer } = this === null || this === void 0 ? void 0 : this.webRtcController;
@@ -23857,7 +23867,7 @@ class ArcwarePixelStreaming extends _epicgames_ps_lib_pixelstreamingfrontend_ue5
23857
23867
  if (letter !== undefined) {
23858
23868
  const formattedLoveLetter = letter === null || letter === void 0 ? void 0 : letter.replace(/LL: |\.$/g, "");
23859
23869
  (_a = this === null || this === void 0 ? void 0 : this.loveLettersList) === null || _a === void 0 ? void 0 : _a.push(formattedLoveLetter);
23860
- const loveLettersBox = new _ui_LoveLetters__WEBPACK_IMPORTED_MODULE_11__.LoveLetters();
23870
+ const loveLettersBox = new _ui_LoveLetters__WEBPACK_IMPORTED_MODULE_13__.LoveLetters();
23861
23871
  loveLettersBox === null || loveLettersBox === void 0 ? void 0 : loveLettersBox.addLetter(formattedLoveLetter, (_b = this === null || this === void 0 ? void 0 : this.loveLettersList) === null || _b === void 0 ? void 0 : _b.length);
23862
23872
  // Process the next item in the queue after a delay
23863
23873
  setTimeout(() => {
@@ -23902,7 +23912,7 @@ class ArcwarePixelStreaming extends _epicgames_ps_lib_pixelstreamingfrontend_ue5
23902
23912
  }
23903
23913
  toggleMic(enable, isDefault) {
23904
23914
  var _a, _b;
23905
- (_a = this === null || this === void 0 ? void 0 : this.config) === null || _a === void 0 ? void 0 : _a.setFlagEnabled(_epicgames_ps_lib_pixelstreamingfrontend_ue5_5__WEBPACK_IMPORTED_MODULE_9__.Flags.UseMic, enable);
23915
+ (_a = this === null || this === void 0 ? void 0 : this.config) === null || _a === void 0 ? void 0 : _a.setFlagEnabled(_epicgames_ps_lib_pixelstreamingfrontend_ue5_5__WEBPACK_IMPORTED_MODULE_11__.Flags.UseMic, enable);
23906
23916
  if (!isDefault) {
23907
23917
  (_b = this === null || this === void 0 ? void 0 : this.microphoneOverlay) === null || _b === void 0 ? void 0 : _b.toggleMessage(enable);
23908
23918
  setTimeout(() => {
@@ -23939,7 +23949,7 @@ class ArcwarePixelStreaming extends _epicgames_ps_lib_pixelstreamingfrontend_ue5
23939
23949
  removeXRIconIfDisabled() {
23940
23950
  var _a, _b, _c, _d, _e;
23941
23951
  if (!((_b = (_a = this === null || this === void 0 ? void 0 : this.config) === null || _a === void 0 ? void 0 : _a.initialSettings) === null || _b === void 0 ? void 0 : _b.XRControllerInput)) {
23942
- (_c = this === null || this === void 0 ? void 0 : this.config) === null || _c === void 0 ? void 0 : _c.setFlagEnabled(_epicgames_ps_lib_pixelstreamingfrontend_ue5_5__WEBPACK_IMPORTED_MODULE_9__.Flags.XRControllerInput, false);
23952
+ (_c = this === null || this === void 0 ? void 0 : this.config) === null || _c === void 0 ? void 0 : _c.setFlagEnabled(_epicgames_ps_lib_pixelstreamingfrontend_ue5_5__WEBPACK_IMPORTED_MODULE_11__.Flags.XRControllerInput, false);
23943
23953
  if (this.videoElementParent) {
23944
23954
  if ((_d = this === null || this === void 0 ? void 0 : this.videoElementParent) === null || _d === void 0 ? void 0 : _d.parentElement) {
23945
23955
  const xrBtn = (_e = this === null || this === void 0 ? void 0 : this.videoElementParent) === null || _e === void 0 ? void 0 : _e.parentElement.querySelector("#xrBtn");
@@ -23958,6 +23968,340 @@ class ArcwarePixelStreaming extends _epicgames_ps_lib_pixelstreamingfrontend_ue5
23958
23968
  }
23959
23969
 
23960
23970
 
23971
+ /***/ }),
23972
+
23973
+ /***/ 6478:
23974
+ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
23975
+
23976
+ __webpack_require__.r(__webpack_exports__);
23977
+ /* harmony export */ __webpack_require__.d(__webpack_exports__, {
23978
+ /* harmony export */ "DiagnosticsCollector": () => (/* binding */ DiagnosticsCollector)
23979
+ /* harmony export */ });
23980
+ /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(655);
23981
+ /**
23982
+ * DiagnosticsCollector.ts
23983
+ * Lightweight, privacy-aware client diagnostics for troubleshooting + analytics.
23984
+ * WebRTC collection intentionally omitted (to add later).
23985
+ *
23986
+ * Notes:
23987
+ * - Some fields are best-effort due to browser restrictions; they're nullable.
23988
+ * - Bandwidth probe requires a small binary served with:
23989
+ * Content-Type: application/octet-stream
23990
+ * Content-Encoding: identity
23991
+ * Cache-Control: no-store
23992
+ * Default location: /diag/probe.bin
23993
+ */
23994
+
23995
+ /**
23996
+ * DiagnosticsCollector
23997
+ */
23998
+ class DiagnosticsCollector {
23999
+ constructor(opts = {}) {
24000
+ var _a, _b, _c, _d;
24001
+ this.opts = {
24002
+ enableBandwidthProbe: (_a = opts.enableBandwidthProbe) !== null && _a !== void 0 ? _a : true,
24003
+ probeUrl: (_b = opts.probeUrl) !== null && _b !== void 0 ? _b : '/diag/probe.bin',
24004
+ respectSaveData: (_c = opts.respectSaveData) !== null && _c !== void 0 ? _c : true,
24005
+ sampleRate: Math.max(0, Math.min(1, (_d = opts.sampleRate) !== null && _d !== void 0 ? _d : 1))
24006
+ };
24007
+ }
24008
+ /**
24009
+ * Collect the diagnostics payload.
24010
+ */
24011
+ collect() {
24012
+ var _a, _b;
24013
+ return (0,tslib__WEBPACK_IMPORTED_MODULE_0__.__awaiter)(this, void 0, void 0, function* () {
24014
+ if (!this.shouldSample()) {
24015
+ return {
24016
+ device: { type: 'desktop', touchSupport: false },
24017
+ runtime: { browser: { family: 'Unknown', version: null }, os: { family: 'Unknown', version: null } },
24018
+ powerHints: { saveData: null, prefersReducedData: null, prefersReducedMotion: null },
24019
+ network: { type: null, effectiveType: null, downlinkMbps: null, rttMs: null, measuredDownlinkMbps: null },
24020
+ timestamps: { collectedAt: Date.now() }
24021
+ };
24022
+ }
24023
+ const collectedAt = Date.now();
24024
+ const [uaInfo, codecSupport, measuredDownlinkMbps] = yield Promise.all([
24025
+ this.getUAInfo(),
24026
+ this.getCodecSupport(),
24027
+ this.maybeMeasureBandwidth()
24028
+ ]);
24029
+ return {
24030
+ device: {
24031
+ type: this.inferDeviceType(),
24032
+ vendor: null,
24033
+ model: uaInfo.model,
24034
+ architecture: uaInfo.architecture,
24035
+ bitness: uaInfo.bitness,
24036
+ touchSupport: this.hasTouch(),
24037
+ hardwareConcurrency: (_a = navigator.hardwareConcurrency) !== null && _a !== void 0 ? _a : null,
24038
+ deviceMemory: (_b = navigator.deviceMemory) !== null && _b !== void 0 ? _b : null,
24039
+ orientation: this.getOrientation(),
24040
+ webgl: this.hasWebGL(),
24041
+ codecs: codecSupport
24042
+ },
24043
+ runtime: {
24044
+ browser: { family: uaInfo.browserFamily, version: uaInfo.browserVersion },
24045
+ os: { family: uaInfo.osFamily, version: uaInfo.osVersion }
24046
+ },
24047
+ powerHints: this.getPowerHints(),
24048
+ network: this.getNetworkInfo(measuredDownlinkMbps),
24049
+ timestamps: { collectedAt }
24050
+ };
24051
+ });
24052
+ }
24053
+ /**
24054
+ * Collect a safe subset of WebRTC stats once PC is connected.
24055
+ */
24056
+ collectWebRTC(pc) {
24057
+ var _a, _b, _c, _d, _e, _f;
24058
+ return (0,tslib__WEBPACK_IMPORTED_MODULE_0__.__awaiter)(this, void 0, void 0, function* () {
24059
+ try {
24060
+ const stats = yield pc.getStats();
24061
+ let selected, transport, local, remote;
24062
+ stats.forEach((r) => {
24063
+ if (r.type === 'transport' && r.selectedCandidatePairId)
24064
+ transport = r;
24065
+ if (r.type === 'candidate-pair' && (r.selected || r.nominated))
24066
+ selected = r;
24067
+ });
24068
+ if (selected) {
24069
+ local = stats.get(selected.localCandidateId);
24070
+ remote = stats.get(selected.remoteCandidateId);
24071
+ }
24072
+ return {
24073
+ candidatePairId: (_a = selected === null || selected === void 0 ? void 0 : selected.id) !== null && _a !== void 0 ? _a : null,
24074
+ localCandidateType: (_b = local === null || local === void 0 ? void 0 : local.candidateType) !== null && _b !== void 0 ? _b : null,
24075
+ remoteCandidateType: (_c = remote === null || remote === void 0 ? void 0 : remote.candidateType) !== null && _c !== void 0 ? _c : null,
24076
+ protocol: (_d = local === null || local === void 0 ? void 0 : local.protocol) !== null && _d !== void 0 ? _d : null,
24077
+ networkType: (_e = local === null || local === void 0 ? void 0 : local.networkType) !== null && _e !== void 0 ? _e : null,
24078
+ dtlsCipher: (_f = transport === null || transport === void 0 ? void 0 : transport.dtlsCipher) !== null && _f !== void 0 ? _f : null
24079
+ };
24080
+ }
24081
+ catch (_g) {
24082
+ return {};
24083
+ }
24084
+ });
24085
+ }
24086
+ /**
24087
+ * Helper to embed diagnostics in a hello envelope.
24088
+ */
24089
+ buildHelloEnvelope(base, pc) {
24090
+ return (0,tslib__WEBPACK_IMPORTED_MODULE_0__.__awaiter)(this, void 0, void 0, function* () {
24091
+ const diag = yield this.collect();
24092
+ const webrtc = pc ? yield this.collectWebRTC(pc) : undefined;
24093
+ const ext = webrtc ? { diag: Object.assign(Object.assign({}, diag), { webrtc }) } : { diag };
24094
+ return Object.assign(Object.assign({}, base), { ext });
24095
+ });
24096
+ }
24097
+ // ---------- Internals ----------
24098
+ shouldSample() {
24099
+ if (this.opts.sampleRate >= 1)
24100
+ return true;
24101
+ return Math.random() < this.opts.sampleRate;
24102
+ }
24103
+ hasTouch() {
24104
+ var _a;
24105
+ const nav = navigator;
24106
+ return 'ontouchstart' in window || ((_a = nav.maxTouchPoints) !== null && _a !== void 0 ? _a : 0) > 0;
24107
+ }
24108
+ getOrientation() {
24109
+ var _a;
24110
+ try {
24111
+ if ((_a = screen.orientation) === null || _a === void 0 ? void 0 : _a.type) {
24112
+ return screen.orientation.type.startsWith('portrait') ? 'portrait' : 'landscape';
24113
+ }
24114
+ if (window.matchMedia) {
24115
+ return window.matchMedia('(orientation: portrait)').matches ? 'portrait' : 'landscape';
24116
+ }
24117
+ }
24118
+ catch (_b) { }
24119
+ return null;
24120
+ }
24121
+ hasWebGL() {
24122
+ try {
24123
+ const canvas = document.createElement('canvas');
24124
+ return !!(canvas.getContext('webgl') || canvas.getContext('experimental-webgl'));
24125
+ }
24126
+ catch (_a) {
24127
+ return false;
24128
+ }
24129
+ }
24130
+ /**
24131
+ * Heuristic device type: best-effort only.
24132
+ */
24133
+ inferDeviceType() {
24134
+ const uaData = navigator.userAgentData;
24135
+ const isMobileCH = (uaData === null || uaData === void 0 ? void 0 : uaData.mobile) === true;
24136
+ const minDim = Math.min(screen.width, screen.height);
24137
+ if (isMobileCH && minDim >= 600)
24138
+ return 'tablet';
24139
+ if (isMobileCH)
24140
+ return 'mobile';
24141
+ if (/\b(iPad|Tablet)\b/i.test(navigator.userAgent))
24142
+ return 'tablet';
24143
+ if (('ontouchstart' in window) && minDim >= 600 && minDim <= 1100)
24144
+ return 'tablet';
24145
+ return 'desktop';
24146
+ }
24147
+ getPowerHints() {
24148
+ const conn = navigator.connection;
24149
+ const saveData = typeof (conn === null || conn === void 0 ? void 0 : conn.saveData) === 'boolean' ? conn.saveData : null;
24150
+ let prefersReducedData = null;
24151
+ let prefersReducedMotion = null;
24152
+ if (typeof window.matchMedia === 'function') {
24153
+ try {
24154
+ const mqData = window.matchMedia('(prefers-reduced-data: reduce)');
24155
+ if (typeof mqData.matches === 'boolean') {
24156
+ prefersReducedData = mqData.matches;
24157
+ }
24158
+ }
24159
+ catch (_a) { }
24160
+ try {
24161
+ const mqMotion = window.matchMedia('(prefers-reduced-motion: reduce)');
24162
+ if (typeof mqMotion.matches === 'boolean') {
24163
+ prefersReducedMotion = mqMotion.matches;
24164
+ }
24165
+ }
24166
+ catch (_b) { }
24167
+ }
24168
+ return { saveData, prefersReducedData, prefersReducedMotion };
24169
+ }
24170
+ getNetworkInfo(measuredDownlinkMbps) {
24171
+ const conn = navigator.connection;
24172
+ return {
24173
+ type: (typeof (conn === null || conn === void 0 ? void 0 : conn.type) === 'string') ? conn.type : null,
24174
+ effectiveType: (typeof (conn === null || conn === void 0 ? void 0 : conn.effectiveType) === 'string') ? conn.effectiveType : null,
24175
+ downlinkMbps: (typeof (conn === null || conn === void 0 ? void 0 : conn.downlink) === 'number') ? conn.downlink : null,
24176
+ rttMs: (typeof (conn === null || conn === void 0 ? void 0 : conn.rtt) === 'number') ? conn.rtt : null,
24177
+ measuredDownlinkMbps
24178
+ };
24179
+ }
24180
+ maybeMeasureBandwidth() {
24181
+ return (0,tslib__WEBPACK_IMPORTED_MODULE_0__.__awaiter)(this, void 0, void 0, function* () {
24182
+ const conn = navigator.connection;
24183
+ const saveData = (conn === null || conn === void 0 ? void 0 : conn.saveData) === true;
24184
+ if (!this.opts.enableBandwidthProbe)
24185
+ return null;
24186
+ if (this.opts.respectSaveData && saveData)
24187
+ return null;
24188
+ try {
24189
+ const t0 = performance.now();
24190
+ const res = yield fetch(this.withCacheBuster(this.opts.probeUrl), {
24191
+ cache: 'no-store',
24192
+ credentials: 'omit'
24193
+ });
24194
+ const buf = yield res.arrayBuffer();
24195
+ const t1 = performance.now();
24196
+ const bits = buf.byteLength * 8;
24197
+ const seconds = (t1 - t0) / 1000;
24198
+ if (seconds <= 0.05)
24199
+ return null; // ignore unstable samples
24200
+ return +((bits / seconds) / 1000000).toFixed(2);
24201
+ }
24202
+ catch (_a) {
24203
+ return null;
24204
+ }
24205
+ });
24206
+ }
24207
+ withCacheBuster(url) {
24208
+ var _a, _b;
24209
+ const u = new URL(url, location.origin);
24210
+ 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());
24211
+ u.searchParams.set('cb', token);
24212
+ return u.toString();
24213
+ }
24214
+ getCodecSupport() {
24215
+ return (0,tslib__WEBPACK_IMPORTED_MODULE_0__.__awaiter)(this, void 0, void 0, function* () {
24216
+ const [h264, hevc] = yield Promise.all([
24217
+ this.supportsCodec('video/mp4; codecs="avc1.42E01E"'),
24218
+ this.supportsCodec('video/mp4; codecs="hvc1.1.6.L93.B0"')
24219
+ ]);
24220
+ return { h264, hevc };
24221
+ });
24222
+ }
24223
+ supportsCodec(mime) {
24224
+ return (0,tslib__WEBPACK_IMPORTED_MODULE_0__.__awaiter)(this, void 0, void 0, function* () {
24225
+ try {
24226
+ if ('mediaCapabilities' in navigator) {
24227
+ // @ts-ignore
24228
+ const res = yield navigator.mediaCapabilities.decodingInfo({
24229
+ type: 'file',
24230
+ video: { contentType: mime, width: 1920, height: 1080, bitrate: 5000000, framerate: 30 }
24231
+ });
24232
+ return !!(res === null || res === void 0 ? void 0 : res.supported);
24233
+ }
24234
+ }
24235
+ catch (_a) { }
24236
+ try {
24237
+ const v = document.createElement('video');
24238
+ return v.canPlayType(mime) !== '';
24239
+ }
24240
+ catch (_b) {
24241
+ return false;
24242
+ }
24243
+ });
24244
+ }
24245
+ getUAInfo() {
24246
+ var _a, _b;
24247
+ return (0,tslib__WEBPACK_IMPORTED_MODULE_0__.__awaiter)(this, void 0, void 0, function* () {
24248
+ const nav = navigator;
24249
+ const uaData = nav.userAgentData;
24250
+ let browserFamily = 'Unknown', browserVersion = null;
24251
+ let osFamily = 'Unknown', osVersion = null;
24252
+ let model = null, architecture = null, bitness = null;
24253
+ if (uaData === null || uaData === void 0 ? void 0 : uaData.getHighEntropyValues) {
24254
+ try {
24255
+ const high = yield uaData.getHighEntropyValues([
24256
+ 'platform', 'platformVersion', 'model', 'architecture', 'bitness', 'fullVersionList'
24257
+ ]);
24258
+ osFamily = high.platform || 'Unknown';
24259
+ osVersion = high.platformVersion || null;
24260
+ model = high.model || null;
24261
+ architecture = high.architecture || null;
24262
+ bitness = high.bitness || null;
24263
+ const brands = high.fullVersionList || uaData.brands || [];
24264
+ const real = brands.find(b => b.brand && !/Chromium|Not:?A-?Brand/i.test(b.brand));
24265
+ browserFamily = (real === null || real === void 0 ? void 0 : real.brand) || ((_a = brands[0]) === null || _a === void 0 ? void 0 : _a.brand) || 'Unknown';
24266
+ browserVersion = (real === null || real === void 0 ? void 0 : real.version) || ((_b = brands[0]) === null || _b === void 0 ? void 0 : _b.version) || null;
24267
+ }
24268
+ catch (_c) { }
24269
+ }
24270
+ if (browserFamily === 'Unknown') {
24271
+ const ua = navigator.userAgent;
24272
+ if (/Firefox\/(\S+)/.test(ua)) {
24273
+ browserFamily = 'Firefox';
24274
+ browserVersion = RegExp.$1;
24275
+ }
24276
+ else if (/Edg\/(\S+)/.test(ua)) {
24277
+ browserFamily = 'Edge';
24278
+ browserVersion = RegExp.$1;
24279
+ }
24280
+ else if (/Chrome\/(\S+)/.test(ua)) {
24281
+ browserFamily = 'Chrome';
24282
+ browserVersion = RegExp.$1;
24283
+ }
24284
+ else if (/Version\/(\S+).*Safari/.test(ua)) {
24285
+ browserFamily = 'Safari';
24286
+ browserVersion = RegExp.$1;
24287
+ }
24288
+ if (/Windows/.test(ua))
24289
+ osFamily = 'Windows';
24290
+ else if (/Mac OS X/.test(ua))
24291
+ osFamily = 'macOS';
24292
+ else if (/Android/.test(ua))
24293
+ osFamily = 'Android';
24294
+ else if (/iPhone|iPad|iPod/.test(ua))
24295
+ osFamily = 'iOS';
24296
+ else if (/Linux/.test(ua))
24297
+ osFamily = 'Linux';
24298
+ }
24299
+ return { browserFamily, browserVersion, osFamily, osVersion, model, architecture, bitness };
24300
+ });
24301
+ }
24302
+ }
24303
+
24304
+
23961
24305
  /***/ }),
23962
24306
 
23963
24307
  /***/ 5602:
package/index.umd.js CHANGED
@@ -23361,7 +23361,7 @@ class ArcwareConfig extends lib_pixelstreamingfrontend_ue5_5_1.Config {
23361
23361
  if (!config.initialSettings.ss)
23362
23362
  config.initialSettings.ss = exports.DefaultUrl;
23363
23363
  super(config);
23364
- this.VERSION = "1.2.14";
23364
+ this.VERSION = "1.2.15";
23365
23365
  this.settings = settings;
23366
23366
  this.session = new Session_1.Session();
23367
23367
  this._initialSettings = config.initialSettings;
@@ -23502,6 +23502,7 @@ exports.ArcwareInit = ArcwareInit;
23502
23502
 
23503
23503
  Object.defineProperty(exports, "__esModule", ({ value: true }));
23504
23504
  exports.ArcwarePixelStreaming = void 0;
23505
+ const tslib_1 = __webpack_require__(655);
23505
23506
  const shared_pixelstreaming_websdk_1 = __webpack_require__(7910);
23506
23507
  const lib_pixelstreamingfrontend_ue5_5_1 = __webpack_require__(693);
23507
23508
  const ApplyUrlHack_1 = __webpack_require__(4790);
@@ -23512,6 +23513,7 @@ const LoveLetters_1 = __webpack_require__(4572);
23512
23513
  const ArcwareLogoLoader_1 = __webpack_require__(6469);
23513
23514
  const MicrophoneOverlay_1 = __webpack_require__(3613);
23514
23515
  const ConnectionIdentifier_1 = __webpack_require__(5999);
23516
+ const DiagnosticsCollector_1 = __webpack_require__(6478);
23515
23517
  class ArcwarePixelStreaming extends lib_pixelstreamingfrontend_ue5_5_1.PixelStreaming {
23516
23518
  /** Returns a list of WebSocketStates of all PixelStreaming Instances generated. */
23517
23519
  get WebsocketStates() {
@@ -23559,6 +23561,9 @@ class ArcwarePixelStreaming extends lib_pixelstreamingfrontend_ue5_5_1.PixelStre
23559
23561
  this.config = config;
23560
23562
  this.loveLettersList = [];
23561
23563
  this.microphoneOverlay = new MicrophoneOverlay_1.MicrophoneOverlay(this);
23564
+ this.diagnosticsCollector = new DiagnosticsCollector_1.DiagnosticsCollector({
23565
+ enableBandwidthProbe: false,
23566
+ });
23562
23567
  // this.loveLettersContainer = null;
23563
23568
  this.wrapWebSocketOnCloseHandler();
23564
23569
  // Bind the event listener function to the class instance
@@ -23617,7 +23622,10 @@ class ArcwarePixelStreaming extends lib_pixelstreamingfrontend_ue5_5_1.PixelStre
23617
23622
  */
23618
23623
  /** On version requested, the version of the WebSDK would be returned. */
23619
23624
  onVersion(message) {
23620
- this.send({ type: "version", version: this.config.VERSION });
23625
+ return tslib_1.__awaiter(this, void 0, void 0, function* () {
23626
+ const diagnostics = yield this.diagnosticsCollector.collect();
23627
+ this.send({ type: "version", version: this.config.VERSION, diagnostics });
23628
+ });
23621
23629
  }
23622
23630
  /** On ping the session creation timestamp will be updated. */
23623
23631
  onPing(message) {
@@ -23949,6 +23957,339 @@ class ArcwarePixelStreaming extends lib_pixelstreamingfrontend_ue5_5_1.PixelStre
23949
23957
  exports.ArcwarePixelStreaming = ArcwarePixelStreaming;
23950
23958
 
23951
23959
 
23960
+ /***/ }),
23961
+
23962
+ /***/ 6478:
23963
+ /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
23964
+
23965
+
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
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
23980
+ exports.DiagnosticsCollector = void 0;
23981
+ const tslib_1 = __webpack_require__(655);
23982
+ /**
23983
+ * DiagnosticsCollector
23984
+ */
23985
+ class DiagnosticsCollector {
23986
+ constructor(opts = {}) {
23987
+ var _a, _b, _c, _d;
23988
+ this.opts = {
23989
+ enableBandwidthProbe: (_a = opts.enableBandwidthProbe) !== null && _a !== void 0 ? _a : true,
23990
+ probeUrl: (_b = opts.probeUrl) !== null && _b !== void 0 ? _b : '/diag/probe.bin',
23991
+ respectSaveData: (_c = opts.respectSaveData) !== null && _c !== void 0 ? _c : true,
23992
+ sampleRate: Math.max(0, Math.min(1, (_d = opts.sampleRate) !== null && _d !== void 0 ? _d : 1))
23993
+ };
23994
+ }
23995
+ /**
23996
+ * Collect the diagnostics payload.
23997
+ */
23998
+ collect() {
23999
+ var _a, _b;
24000
+ return tslib_1.__awaiter(this, void 0, void 0, function* () {
24001
+ if (!this.shouldSample()) {
24002
+ return {
24003
+ device: { type: 'desktop', touchSupport: false },
24004
+ runtime: { browser: { family: 'Unknown', version: null }, os: { family: 'Unknown', version: null } },
24005
+ powerHints: { saveData: null, prefersReducedData: null, prefersReducedMotion: null },
24006
+ network: { type: null, effectiveType: null, downlinkMbps: null, rttMs: null, measuredDownlinkMbps: null },
24007
+ timestamps: { collectedAt: Date.now() }
24008
+ };
24009
+ }
24010
+ const collectedAt = Date.now();
24011
+ const [uaInfo, codecSupport, measuredDownlinkMbps] = yield Promise.all([
24012
+ this.getUAInfo(),
24013
+ this.getCodecSupport(),
24014
+ this.maybeMeasureBandwidth()
24015
+ ]);
24016
+ return {
24017
+ device: {
24018
+ type: this.inferDeviceType(),
24019
+ vendor: null,
24020
+ model: uaInfo.model,
24021
+ architecture: uaInfo.architecture,
24022
+ bitness: uaInfo.bitness,
24023
+ touchSupport: this.hasTouch(),
24024
+ hardwareConcurrency: (_a = navigator.hardwareConcurrency) !== null && _a !== void 0 ? _a : null,
24025
+ deviceMemory: (_b = navigator.deviceMemory) !== null && _b !== void 0 ? _b : null,
24026
+ orientation: this.getOrientation(),
24027
+ webgl: this.hasWebGL(),
24028
+ codecs: codecSupport
24029
+ },
24030
+ runtime: {
24031
+ browser: { family: uaInfo.browserFamily, version: uaInfo.browserVersion },
24032
+ os: { family: uaInfo.osFamily, version: uaInfo.osVersion }
24033
+ },
24034
+ powerHints: this.getPowerHints(),
24035
+ network: this.getNetworkInfo(measuredDownlinkMbps),
24036
+ timestamps: { collectedAt }
24037
+ };
24038
+ });
24039
+ }
24040
+ /**
24041
+ * Collect a safe subset of WebRTC stats once PC is connected.
24042
+ */
24043
+ collectWebRTC(pc) {
24044
+ var _a, _b, _c, _d, _e, _f;
24045
+ return tslib_1.__awaiter(this, void 0, void 0, function* () {
24046
+ try {
24047
+ const stats = yield pc.getStats();
24048
+ let selected, transport, local, remote;
24049
+ stats.forEach((r) => {
24050
+ if (r.type === 'transport' && r.selectedCandidatePairId)
24051
+ transport = r;
24052
+ if (r.type === 'candidate-pair' && (r.selected || r.nominated))
24053
+ selected = r;
24054
+ });
24055
+ if (selected) {
24056
+ local = stats.get(selected.localCandidateId);
24057
+ remote = stats.get(selected.remoteCandidateId);
24058
+ }
24059
+ return {
24060
+ candidatePairId: (_a = selected === null || selected === void 0 ? void 0 : selected.id) !== null && _a !== void 0 ? _a : null,
24061
+ localCandidateType: (_b = local === null || local === void 0 ? void 0 : local.candidateType) !== null && _b !== void 0 ? _b : null,
24062
+ remoteCandidateType: (_c = remote === null || remote === void 0 ? void 0 : remote.candidateType) !== null && _c !== void 0 ? _c : null,
24063
+ protocol: (_d = local === null || local === void 0 ? void 0 : local.protocol) !== null && _d !== void 0 ? _d : null,
24064
+ networkType: (_e = local === null || local === void 0 ? void 0 : local.networkType) !== null && _e !== void 0 ? _e : null,
24065
+ dtlsCipher: (_f = transport === null || transport === void 0 ? void 0 : transport.dtlsCipher) !== null && _f !== void 0 ? _f : null
24066
+ };
24067
+ }
24068
+ catch (_g) {
24069
+ return {};
24070
+ }
24071
+ });
24072
+ }
24073
+ /**
24074
+ * Helper to embed diagnostics in a hello envelope.
24075
+ */
24076
+ buildHelloEnvelope(base, pc) {
24077
+ return tslib_1.__awaiter(this, void 0, void 0, function* () {
24078
+ const diag = yield this.collect();
24079
+ const webrtc = pc ? yield this.collectWebRTC(pc) : undefined;
24080
+ const ext = webrtc ? { diag: Object.assign(Object.assign({}, diag), { webrtc }) } : { diag };
24081
+ return Object.assign(Object.assign({}, base), { ext });
24082
+ });
24083
+ }
24084
+ // ---------- Internals ----------
24085
+ shouldSample() {
24086
+ if (this.opts.sampleRate >= 1)
24087
+ return true;
24088
+ return Math.random() < this.opts.sampleRate;
24089
+ }
24090
+ hasTouch() {
24091
+ var _a;
24092
+ const nav = navigator;
24093
+ return 'ontouchstart' in window || ((_a = nav.maxTouchPoints) !== null && _a !== void 0 ? _a : 0) > 0;
24094
+ }
24095
+ getOrientation() {
24096
+ var _a;
24097
+ try {
24098
+ if ((_a = screen.orientation) === null || _a === void 0 ? void 0 : _a.type) {
24099
+ return screen.orientation.type.startsWith('portrait') ? 'portrait' : 'landscape';
24100
+ }
24101
+ if (window.matchMedia) {
24102
+ return window.matchMedia('(orientation: portrait)').matches ? 'portrait' : 'landscape';
24103
+ }
24104
+ }
24105
+ catch (_b) { }
24106
+ return null;
24107
+ }
24108
+ hasWebGL() {
24109
+ try {
24110
+ const canvas = document.createElement('canvas');
24111
+ return !!(canvas.getContext('webgl') || canvas.getContext('experimental-webgl'));
24112
+ }
24113
+ catch (_a) {
24114
+ return false;
24115
+ }
24116
+ }
24117
+ /**
24118
+ * Heuristic device type: best-effort only.
24119
+ */
24120
+ inferDeviceType() {
24121
+ const uaData = navigator.userAgentData;
24122
+ const isMobileCH = (uaData === null || uaData === void 0 ? void 0 : uaData.mobile) === true;
24123
+ const minDim = Math.min(screen.width, screen.height);
24124
+ if (isMobileCH && minDim >= 600)
24125
+ return 'tablet';
24126
+ if (isMobileCH)
24127
+ return 'mobile';
24128
+ if (/\b(iPad|Tablet)\b/i.test(navigator.userAgent))
24129
+ return 'tablet';
24130
+ if (('ontouchstart' in window) && minDim >= 600 && minDim <= 1100)
24131
+ return 'tablet';
24132
+ return 'desktop';
24133
+ }
24134
+ getPowerHints() {
24135
+ const conn = navigator.connection;
24136
+ const saveData = typeof (conn === null || conn === void 0 ? void 0 : conn.saveData) === 'boolean' ? conn.saveData : null;
24137
+ let prefersReducedData = null;
24138
+ let prefersReducedMotion = null;
24139
+ if (typeof window.matchMedia === 'function') {
24140
+ try {
24141
+ const mqData = window.matchMedia('(prefers-reduced-data: reduce)');
24142
+ if (typeof mqData.matches === 'boolean') {
24143
+ prefersReducedData = mqData.matches;
24144
+ }
24145
+ }
24146
+ catch (_a) { }
24147
+ try {
24148
+ const mqMotion = window.matchMedia('(prefers-reduced-motion: reduce)');
24149
+ if (typeof mqMotion.matches === 'boolean') {
24150
+ prefersReducedMotion = mqMotion.matches;
24151
+ }
24152
+ }
24153
+ catch (_b) { }
24154
+ }
24155
+ return { saveData, prefersReducedData, prefersReducedMotion };
24156
+ }
24157
+ getNetworkInfo(measuredDownlinkMbps) {
24158
+ const conn = navigator.connection;
24159
+ return {
24160
+ type: (typeof (conn === null || conn === void 0 ? void 0 : conn.type) === 'string') ? conn.type : null,
24161
+ effectiveType: (typeof (conn === null || conn === void 0 ? void 0 : conn.effectiveType) === 'string') ? conn.effectiveType : null,
24162
+ downlinkMbps: (typeof (conn === null || conn === void 0 ? void 0 : conn.downlink) === 'number') ? conn.downlink : null,
24163
+ rttMs: (typeof (conn === null || conn === void 0 ? void 0 : conn.rtt) === 'number') ? conn.rtt : null,
24164
+ measuredDownlinkMbps
24165
+ };
24166
+ }
24167
+ maybeMeasureBandwidth() {
24168
+ return tslib_1.__awaiter(this, void 0, void 0, function* () {
24169
+ const conn = navigator.connection;
24170
+ const saveData = (conn === null || conn === void 0 ? void 0 : conn.saveData) === true;
24171
+ if (!this.opts.enableBandwidthProbe)
24172
+ return null;
24173
+ if (this.opts.respectSaveData && saveData)
24174
+ return null;
24175
+ try {
24176
+ const t0 = performance.now();
24177
+ const res = yield fetch(this.withCacheBuster(this.opts.probeUrl), {
24178
+ cache: 'no-store',
24179
+ credentials: 'omit'
24180
+ });
24181
+ const buf = yield res.arrayBuffer();
24182
+ const t1 = performance.now();
24183
+ const bits = buf.byteLength * 8;
24184
+ const seconds = (t1 - t0) / 1000;
24185
+ if (seconds <= 0.05)
24186
+ return null; // ignore unstable samples
24187
+ return +((bits / seconds) / 1000000).toFixed(2);
24188
+ }
24189
+ catch (_a) {
24190
+ return null;
24191
+ }
24192
+ });
24193
+ }
24194
+ withCacheBuster(url) {
24195
+ var _a, _b;
24196
+ const u = new URL(url, location.origin);
24197
+ 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());
24198
+ u.searchParams.set('cb', token);
24199
+ return u.toString();
24200
+ }
24201
+ getCodecSupport() {
24202
+ return tslib_1.__awaiter(this, void 0, void 0, function* () {
24203
+ const [h264, hevc] = yield Promise.all([
24204
+ this.supportsCodec('video/mp4; codecs="avc1.42E01E"'),
24205
+ this.supportsCodec('video/mp4; codecs="hvc1.1.6.L93.B0"')
24206
+ ]);
24207
+ return { h264, hevc };
24208
+ });
24209
+ }
24210
+ supportsCodec(mime) {
24211
+ return tslib_1.__awaiter(this, void 0, void 0, function* () {
24212
+ try {
24213
+ if ('mediaCapabilities' in navigator) {
24214
+ // @ts-ignore
24215
+ const res = yield navigator.mediaCapabilities.decodingInfo({
24216
+ type: 'file',
24217
+ video: { contentType: mime, width: 1920, height: 1080, bitrate: 5000000, framerate: 30 }
24218
+ });
24219
+ return !!(res === null || res === void 0 ? void 0 : res.supported);
24220
+ }
24221
+ }
24222
+ catch (_a) { }
24223
+ try {
24224
+ const v = document.createElement('video');
24225
+ return v.canPlayType(mime) !== '';
24226
+ }
24227
+ catch (_b) {
24228
+ return false;
24229
+ }
24230
+ });
24231
+ }
24232
+ getUAInfo() {
24233
+ var _a, _b;
24234
+ return tslib_1.__awaiter(this, void 0, void 0, function* () {
24235
+ const nav = navigator;
24236
+ const uaData = nav.userAgentData;
24237
+ let browserFamily = 'Unknown', browserVersion = null;
24238
+ let osFamily = 'Unknown', osVersion = null;
24239
+ let model = null, architecture = null, bitness = null;
24240
+ if (uaData === null || uaData === void 0 ? void 0 : uaData.getHighEntropyValues) {
24241
+ try {
24242
+ const high = yield uaData.getHighEntropyValues([
24243
+ 'platform', 'platformVersion', 'model', 'architecture', 'bitness', 'fullVersionList'
24244
+ ]);
24245
+ osFamily = high.platform || 'Unknown';
24246
+ osVersion = high.platformVersion || null;
24247
+ model = high.model || null;
24248
+ architecture = high.architecture || null;
24249
+ bitness = high.bitness || null;
24250
+ const brands = high.fullVersionList || uaData.brands || [];
24251
+ const real = brands.find(b => b.brand && !/Chromium|Not:?A-?Brand/i.test(b.brand));
24252
+ browserFamily = (real === null || real === void 0 ? void 0 : real.brand) || ((_a = brands[0]) === null || _a === void 0 ? void 0 : _a.brand) || 'Unknown';
24253
+ browserVersion = (real === null || real === void 0 ? void 0 : real.version) || ((_b = brands[0]) === null || _b === void 0 ? void 0 : _b.version) || null;
24254
+ }
24255
+ catch (_c) { }
24256
+ }
24257
+ if (browserFamily === 'Unknown') {
24258
+ const ua = navigator.userAgent;
24259
+ if (/Firefox\/(\S+)/.test(ua)) {
24260
+ browserFamily = 'Firefox';
24261
+ browserVersion = RegExp.$1;
24262
+ }
24263
+ else if (/Edg\/(\S+)/.test(ua)) {
24264
+ browserFamily = 'Edge';
24265
+ browserVersion = RegExp.$1;
24266
+ }
24267
+ else if (/Chrome\/(\S+)/.test(ua)) {
24268
+ browserFamily = 'Chrome';
24269
+ browserVersion = RegExp.$1;
24270
+ }
24271
+ else if (/Version\/(\S+).*Safari/.test(ua)) {
24272
+ browserFamily = 'Safari';
24273
+ browserVersion = RegExp.$1;
24274
+ }
24275
+ if (/Windows/.test(ua))
24276
+ osFamily = 'Windows';
24277
+ else if (/Mac OS X/.test(ua))
24278
+ osFamily = 'macOS';
24279
+ else if (/Android/.test(ua))
24280
+ osFamily = 'Android';
24281
+ else if (/iPhone|iPad|iPod/.test(ua))
24282
+ osFamily = 'iOS';
24283
+ else if (/Linux/.test(ua))
24284
+ osFamily = 'Linux';
24285
+ }
24286
+ return { browserFamily, browserVersion, osFamily, osVersion, model, architecture, bitness };
24287
+ });
24288
+ }
24289
+ }
24290
+ exports.DiagnosticsCollector = DiagnosticsCollector;
24291
+
24292
+
23952
24293
  /***/ }),
23953
24294
 
23954
24295
  /***/ 5602:
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@arcware-cloud/pixelstreaming-websdk",
3
3
  "description": "WebSDK for easy implementation of pixel streaming with Arcware Cloud Services. Heavily based on the '@epicgames-ps' library.",
4
- "version": "1.2.14",
4
+ "version": "1.2.15",
5
5
  "type": "commonjs",
6
6
  "main": "./index.umd.js",
7
7
  "module": "./index.umd.js",
@@ -15,7 +15,7 @@
15
15
  ],
16
16
  "author": {
17
17
  "name": "Arcware GmbH",
18
- "email": "sales@arcware.com",
18
+ "email": "info@arcware.com",
19
19
  "url": "https://www.arcware.com"
20
20
  },
21
21
  "license": "MIT",