@3dsource/angular-unreal-module 0.0.46 → 0.0.50

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.
@@ -1,10 +1,10 @@
1
1
  import * as i0 from '@angular/core';
2
2
  import { InjectionToken, inject, Injectable, ChangeDetectionStrategy, Component, Pipe, DestroyRef, signal, ElementRef, input, HostListener, Input, ViewChild, computed, output } from '@angular/core';
3
- import { filter, withLatestFrom, distinctUntilChanged, switchMap, first, catchError, map as map$1, tap, delay, takeUntil, debounceTime, exhaustMap, takeWhile, skip as skip$1 } from 'rxjs/operators';
3
+ import { filter, withLatestFrom, distinctUntilChanged, switchMap, first, catchError, timeout, map as map$1, tap, takeUntil, exhaustMap, debounceTime, takeWhile, skip as skip$1, delay } from 'rxjs/operators';
4
4
  import { createAction, props, Store, provideState, createReducer, on, createFeature, createSelector } from '@ngrx/store';
5
- import { provideEffects, Actions, createEffect, ofType } from '@ngrx/effects';
6
- import { skip, share, merge, Subject, interval, of, map, from, take, fromEvent, timer, combineLatest, switchMap as switchMap$1, timeout, retryWhen, tap as tap$1, startWith, combineLatestWith, takeUntil as takeUntil$1, auditTime, EMPTY, debounceTime as debounceTime$1, scan, concatMap, animationFrameScheduler, Observable, BehaviorSubject, first as first$1, distinctUntilChanged as distinctUntilChanged$1, concat } from 'rxjs';
7
- import { Falsy, Truthy, Logger, calculateMedian, clampf, Signal, tapLog, generateUuid, COLOR_CODES, where, KeyboardNumericCode, InvertedKeyMap, Semaphore, isEmpty, lerp, getCanvasCached, getSnapshot, whereNot, HEXtoRGB, RGBtoHSV, inverseLerp, HSVtoRGB, RGBtoHEX, fpIsASameAsB, fitIntoRectangle } from '@3dsource/utils';
5
+ import { Actions, ofType, provideEffects, createEffect } from '@ngrx/effects';
6
+ import { skip, share, merge, Subject, interval, of, map, from, take, fromEvent, timer, throwError, defer, Observable, switchMap as switchMap$1, retry, timeout as timeout$1, tap as tap$1, startWith, combineLatestWith, takeUntil as takeUntil$1, auditTime, debounceTime as debounceTime$1, EMPTY, mergeMap, scan, concatMap, animationFrameScheduler, BehaviorSubject, combineLatest, first as first$1, distinctUntilChanged as distinctUntilChanged$1, concat } from 'rxjs';
7
+ import { Falsy, Truthy, Logger, calculateMedian, clampf, Signal, tapLog, generateUuid, COLOR_CODES, where, KeyboardNumericCode, InvertedKeyMap, Semaphore, lerp, getCanvasCached, getSnapshot, whereNot, HEXtoRGB, RGBtoHSV, inverseLerp, HSVtoRGB, RGBtoHEX, fpIsASameAsB, fitIntoRectangle } from '@3dsource/utils';
8
8
  import { HttpClient } from '@angular/common/http';
9
9
  import { toSignal, takeUntilDestroyed, toObservable } from '@angular/core/rxjs-interop';
10
10
  import { DialogRef, DIALOG_DATA, Dialog } from '@angular/cdk/dialog';
@@ -19,21 +19,30 @@ import { FormsModule } from '@angular/forms';
19
19
  const WSCloseCode_NORMAL_CLOSURE = 3000;
20
20
  const WSCloseCode_NORMAL_AFK_TIMEOUT = 3001;
21
21
  const WSCloseCode_NORMAL_MANUAL_DISCONNECT = 3002;
22
- const WSCloseCode_NORMAL_CIRRUS_CLOSED = 3003;
22
+ const WSCloseCode_FORCE_CIRRUS_CLOSE = 3003;
23
+ const WSCloseCode_CIRRUS_PLAYER_DISCONNECTED = 1001;
24
+ const WSCloseCode_CIRRUS_ABNORMAL_CLOSURE = 1006;
25
+ const WSCloseCode_CIRRUS_MAX_PLAYERS_ERROR = 1013;
26
+ const WSCloseCode_CIRRUS_STREAMER_KIKED_PLAYER = 1011;
23
27
  const WSCloseCodes = [
24
28
  WSCloseCode_NORMAL_CLOSURE,
25
29
  WSCloseCode_NORMAL_AFK_TIMEOUT,
26
30
  WSCloseCode_NORMAL_MANUAL_DISCONNECT,
27
- WSCloseCode_NORMAL_CIRRUS_CLOSED,
31
+ WSCloseCode_FORCE_CIRRUS_CLOSE,
32
+ WSCloseCode_CIRRUS_MAX_PLAYERS_ERROR,
33
+ WSCloseCode_CIRRUS_ABNORMAL_CLOSURE,
28
34
  ];
29
35
 
30
36
  const DisconnectReason = {
31
- afk: 'afk',
32
- none: 'none',
33
- reset: 'reset',
34
- wsOnError: 'wsOnError',
35
- dataChannelClosed: 'dataChannelClosed',
36
- dataChannelTimeout: 'dataChannelTimeout',
37
+ Afk: 'Afk',
38
+ None: 'None',
39
+ Destroy: 'Destroy',
40
+ DataChannelClosed: 'DataChannelClosed',
41
+ DataChannelTimeout: 'DataChannelTimeout',
42
+ WebRTCError: 'WebRTCError',
43
+ WebSocketError: 'WebSocketError',
44
+ WebSocketClose: 'WebSocketClose',
45
+ DropConnection: 'DropConnection',
37
46
  };
38
47
 
39
48
  /*
@@ -90,7 +99,7 @@ const trackMixpanelEvent = createAction(scoped `track mixpanel event`, props());
90
99
  const changeLowBandwidth = createAction(scoped `change low bandwidth`, props());
91
100
  const setMaxFps = createAction(scoped `change fps`, props());
92
101
  const destroyRemoteConnections = createAction(scoped `destroyRemoteConnections`, props());
93
- const destroyConnectionsAndResetState = createAction(scoped `destroyConnections and reset`);
102
+ const destroyUnrealScene = createAction(scoped `destroyUnrealScene`);
94
103
  const setCirrusConnected = createAction(scoped `cirrusConnected`);
95
104
  const setCirrusDisconnected = createAction(scoped `cirrusDisconnected`);
96
105
  const changeStatusMainVideoOnScene = createAction(scoped `change status main video on scene`, props());
@@ -109,9 +118,10 @@ const setFreezeFrameFromVideo = createAction(scoped `set freeze frame from video
109
118
  const setEstablishingConnection = createAction(scoped `set establishing connection`, props());
110
119
  const setDataChannelConnected = createAction(scoped `set data channel connected`, props());
111
120
  const setConfig = createAction(scoped `set config`, props());
112
- const setMatchMakerUrls = createAction(scoped `set match makers urls`, props());
113
- const setErrorMessage = createAction(scoped `set error message`, props());
114
- const setViewportReady = createAction(scoped `set viewport ready`, props());
121
+ const disconnectStream = createAction(scoped `disconnectStream`, props());
122
+ const dropConnection = createAction(scoped `dropConnection`);
123
+ const setViewportReady = createAction(scoped `set viewport ready`);
124
+ const setViewportNotReady = createAction(scoped `set viewport not ready`);
115
125
  const changeStreamResolutionAction = createAction(scoped `change stream resolution`, props());
116
126
  const changeStreamResolutionSuccessAction = createAction(scoped `change stream resolution success action`, props());
117
127
  const setSignalingName = createAction(scoped `set aws instanceName`, props());
@@ -120,13 +130,16 @@ const commandStarted = createAction(scoped `command started`, props());
120
130
  const commandCompleted = createAction(scoped `command completed`, props());
121
131
  const setLoopBackCommandIsCompleted = createAction(scoped `set loopBack command is completed`);
122
132
  const showUnrealErrorMessage = createAction(scoped `show unreal error message`, props());
123
- const initSignalling = createAction(scoped `init signalling`);
124
- const setIsFreezeLoaderPercents = createAction(scoped `set is freeze loader percents`);
133
+ const initSignalling = createAction(scoped `init signalling`, (data = {
134
+ resetDisconnectionReason: true,
135
+ }) => ({
136
+ resetDisconnectionReason: data.resetDisconnectionReason,
137
+ }));
138
+ const startStream = createAction(scoped `startStream`, props());
125
139
  const resetConfig = createAction(scoped `reset config`);
126
140
  const resetAfkAction = createAction(scoped `reset afk action`);
127
141
  const resetWarnTimeout = createAction(scoped `reset config warn timeout`);
128
- const resetUnrealStateAction = createAction(scoped `reset state`);
129
- const resetUnrealState = createAction(scoped `reset unreal state`);
142
+ const abortEstablishingConnection = createAction(scoped `abortEstablishingConnection`);
130
143
 
131
144
  const SpecialKeyCodes = {
132
145
  BackSpace: 8,
@@ -237,6 +250,7 @@ const CONSOLE_COMMAND_PIXEL_QUALITY = 'PixelStreaming.FreezeFrameQuality 95';
237
250
  const FULL_HD_WIDTH = 1920;
238
251
  const FULL_HD_HEIGHT = 1080;
239
252
  const WS_TIMEOUT = 2000;
253
+ const POLLING_TIME = 4000;
240
254
  const WS_OPEN_STATE = 1;
241
255
  const DEFAULT_AFK_TIMEOUT_PERIOD = 15;
242
256
  const DEFAULT_AFK_TIMEOUT = 120;
@@ -344,8 +358,10 @@ class AFKService extends SubService {
344
358
  if (this.countdown === 0) {
345
359
  // The user failed to click so disconnect them
346
360
  this.hideOverlay();
347
- // TODO possible way (Blinking), because postponed close event: destroyRemoteConnections({ disconnectReason: DisconnectReason.afk }),
348
- this.store.dispatch(destroyConnectionsAndResetState());
361
+ this.store.dispatch(disconnectStream({
362
+ reason: DisconnectReason.Afk,
363
+ message: `AFK timeout:${this.selectWarnTimeout()} seconds, popup timeout:${this.closeTimeout} seconds`,
364
+ }));
349
365
  clearInterval(this.countdownTimer);
350
366
  }
351
367
  else {
@@ -353,10 +369,10 @@ class AFKService extends SubService {
353
369
  }
354
370
  }, 1000);
355
371
  }
356
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.1", ngImport: i0, type: AFKService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
357
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.2.1", ngImport: i0, type: AFKService }); }
372
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.4", ngImport: i0, type: AFKService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
373
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.2.4", ngImport: i0, type: AFKService }); }
358
374
  }
359
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.1", ngImport: i0, type: AFKService, decorators: [{
375
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.4", ngImport: i0, type: AFKService, decorators: [{
360
376
  type: Injectable
361
377
  }], ctorParameters: () => [] });
362
378
 
@@ -431,10 +447,10 @@ class FreezeFrameService extends SubService {
431
447
  progress: 1,
432
448
  }));
433
449
  }
434
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.1", ngImport: i0, type: FreezeFrameService, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
435
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.2.1", ngImport: i0, type: FreezeFrameService }); }
450
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.4", ngImport: i0, type: FreezeFrameService, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
451
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.2.4", ngImport: i0, type: FreezeFrameService }); }
436
452
  }
437
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.1", ngImport: i0, type: FreezeFrameService, decorators: [{
453
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.4", ngImport: i0, type: FreezeFrameService, decorators: [{
438
454
  type: Injectable
439
455
  }] });
440
456
 
@@ -738,10 +754,10 @@ class VideoService extends SubService {
738
754
  error: () => ({}),
739
755
  });
740
756
  }
741
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.1", ngImport: i0, type: VideoService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
742
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.2.1", ngImport: i0, type: VideoService }); }
757
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.4", ngImport: i0, type: VideoService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
758
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.2.4", ngImport: i0, type: VideoService }); }
743
759
  }
744
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.1", ngImport: i0, type: VideoService, decorators: [{
760
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.4", ngImport: i0, type: VideoService, decorators: [{
745
761
  type: Injectable
746
762
  }], ctorParameters: () => [] });
747
763
 
@@ -955,10 +971,10 @@ class CommandTelemetryService {
955
971
  this.trackTime(out);
956
972
  funcToDecorate(out);
957
973
  }
958
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.1", ngImport: i0, type: CommandTelemetryService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
959
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.2.1", ngImport: i0, type: CommandTelemetryService }); }
974
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.4", ngImport: i0, type: CommandTelemetryService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
975
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.2.4", ngImport: i0, type: CommandTelemetryService }); }
960
976
  }
961
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.1", ngImport: i0, type: CommandTelemetryService, decorators: [{
977
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.4", ngImport: i0, type: CommandTelemetryService, decorators: [{
962
978
  type: Injectable
963
979
  }], ctorParameters: () => [] });
964
980
  function TelemetryStart(externalId) {
@@ -982,99 +998,221 @@ function OfferHandler(msg) {
982
998
  this.onOffer$.next(msg);
983
999
  }
984
1000
 
1001
+ function httpUrlToWs(url) {
1002
+ return url.replace('http://', 'ws://').replace('https://', 'wss://');
1003
+ }
1004
+
1005
+ function createWebSocket(wsUrl) {
1006
+ if (typeof window === 'undefined' || !('WebSocket' in window)) {
1007
+ return throwError(() => new Error("Your browser doesn't support WebSocket"));
1008
+ }
1009
+ Logger.info('Creating socket', wsUrl);
1010
+ return defer(() => new Observable((observer) => {
1011
+ const ws = new WebSocket(wsUrl);
1012
+ const onOpen = () => {
1013
+ observer.next(ws); // connection established
1014
+ };
1015
+ const onError = (ev) => {
1016
+ const anyEv = ev;
1017
+ const err = anyEv?.error instanceof Error
1018
+ ? anyEv.error
1019
+ : new Error('WebSocket failed to connect');
1020
+ observer.error(err);
1021
+ };
1022
+ const onClose = (ev) => {
1023
+ if (ws.readyState !== WebSocket.OPEN) {
1024
+ observer.error(new Error(`WebSocket closed before open (code ${ev.code})`));
1025
+ }
1026
+ };
1027
+ ws.addEventListener('open', onOpen);
1028
+ ws.addEventListener('error', onError);
1029
+ ws.addEventListener('close', onClose);
1030
+ return () => {
1031
+ ws.removeEventListener('open', onOpen);
1032
+ ws.removeEventListener('error', onError);
1033
+ ws.removeEventListener('close', onClose);
1034
+ };
1035
+ })).pipe(timeout({
1036
+ first: WS_TIMEOUT, // fail if no 'open' event in this window
1037
+ with: () => throwError(() => new Error(`WebSocket connection timed out after ${WS_TIMEOUT}ms`)),
1038
+ }));
1039
+ }
1040
+
985
1041
  class SignallingService extends SubService {
986
1042
  constructor() {
987
1043
  super();
1044
+ this.action$ = inject(Actions);
988
1045
  this.httpClient = inject(HttpClient);
989
1046
  this.regionsPingService = inject(RegionsPingService);
990
1047
  this.onOffer$ = new Subject();
991
1048
  this.onConfig$ = new Subject();
992
1049
  this.onWebRtcIce$ = new Subject();
993
1050
  this.onWebRtcAnswer$ = new Subject();
1051
+ this.abort$ = this.action$.pipe(ofType(abortEstablishingConnection));
994
1052
  this.wsMsgHandlers = {};
995
- this.establishingConnection = toSignal(this.store.select(unrealFeature.selectEstablishingConnection));
996
- this.isCirrusConnected = toSignal(this.store.select(unrealFeature.selectCirrusConnected));
997
- this.establishingConnectionDrop$ = this.store
998
- .select(unrealFeature.selectEstablishingConnection)
999
- .pipe(skip(1), filter(Falsy), tapLog('selectEstablishingConnection'), share());
1000
1053
  this.setHandlersFromStream();
1001
1054
  this.store
1002
1055
  .select(unrealFeature.selectDataChannelConnected)
1003
1056
  .pipe(filter(Truthy))
1004
1057
  .subscribe(() => {
1005
- this.send(JSON.stringify({
1058
+ this.send({
1006
1059
  type: 'p2pEstablished',
1007
1060
  source: 'front',
1008
1061
  sessionId: generateUuid(),
1009
- }));
1010
- });
1011
- combineLatest([
1012
- this.store
1013
- .select(selectMatchMakerUrls)
1014
- .pipe(tapLog('MatchMakerUrls changed:')),
1015
- this.store.select(selectIsAutostart).pipe(tapLog('Autostart is:')),
1016
- ])
1017
- .pipe(filter(([, autoStart]) => autoStart), map$1(([matchMakerUrls]) => [...matchMakerUrls].filter(Truthy)), filter((urls) => urls.length > 0))
1018
- .subscribe((urls) => this.connectToSignaling(urls));
1019
- this.store
1020
- .select(selectWsUrl)
1021
- .pipe(filter(Truthy))
1022
- .subscribe((url) => {
1023
- this.initWebSocket(url);
1062
+ });
1024
1063
  });
1025
1064
  }
1026
- initEstablishingConnection() {
1027
- this.showStatusMessage(UnrealStatusMessage.STARTING_YOUR_SESSION);
1028
- this.store.dispatch(setEstablishingConnection({ value: true }));
1029
- }
1030
- stopEstablishingConnection() {
1031
- this.store.dispatch(setEstablishingConnection({ value: false }));
1032
- }
1033
1065
  connectToSignaling(urlList) {
1066
+ Logger.log('CONNECT TO SIGNALLING');
1034
1067
  // Preparation for WebSocket Orchestration
1035
1068
  this.correlationId = generateUuid();
1036
1069
  this.environmentId = '7e356e8d-8fa5-4cf7-83d0-394903e7b0d6';
1037
1070
  ResetTelemetry();
1038
- if (this.establishingConnection() || this.isCirrusConnected()) {
1039
- Logger.warn(`SIGNALING REQUEST can't be called again!. Waiting for connection or error.`);
1040
- return;
1041
- }
1042
- this.initEstablishingConnection();
1043
- this.regionsPingService
1044
- .getFastest()
1045
- .pipe(first())
1046
- .subscribe((region) => {
1047
- const out = urlList.map((url) => {
1048
- if (region && !url.includes(':region')) {
1049
- return url.replace(/signallingserver/gi, `signallingserver/region:${region}`);
1050
- }
1051
- return url;
1052
- });
1053
- this.connectToSignalingAfterPing(out);
1071
+ this.startEstablishingConnection();
1072
+ return defer(() => this.getRegion().pipe(map$1((region) => this.adaptUrlsToRegion(urlList, region)), switchMap$1((urls) => this.getAwsInstance(urls).pipe(first())), tap((awsInstance) => this.store.dispatch(setAwsInstance(awsInstance))), switchMap$1(({ wsUrl }) => this.connectToCirrus(wsUrl)), filter(Truthy), first(), tap((ws) => (this.ws = ws)), takeUntil(this.abort$))).pipe(
1073
+ // Retry the whole attempt on error, advancing to the next URL each time.
1074
+ retry({
1075
+ delay: (err, attempt) => {
1076
+ Logger.info(`Retrying Signalling Connection in ${POLLING_TIME}ms. Attempt# ${attempt}.`, err?.message);
1077
+ return timer(POLLING_TIME);
1078
+ },
1079
+ // count: 10, // Optional: cap the number of attempts.
1080
+ }));
1081
+ }
1082
+ startEstablishingConnection() {
1083
+ this.showStatusMessage(UnrealStatusMessage.STARTING_YOUR_SESSION);
1084
+ this.store.dispatch(setEstablishingConnection({ value: true }));
1085
+ }
1086
+ adaptUrlsToRegion(urlList, region) {
1087
+ return urlList.map((url) => {
1088
+ if (region && !url.includes(':region')) {
1089
+ return url.replace(/signallingserver/gi, `signallingserver/region:${region}`);
1090
+ }
1091
+ return url;
1054
1092
  });
1055
1093
  }
1056
- connectToSignalingAfterPing(urls) {
1057
- const urlGen = getActiveUrl(urls);
1094
+ /**
1095
+ * Resolves an active AWS *signaling* instance and returns a WebSocket endpoint.
1096
+ *
1097
+ * The observable produced by this method is **cold** and executes inside a `defer`,
1098
+ * so each subscription (including those triggered by `retry`) pulls the **next**
1099
+ * URL candidate from a generator created by `getActiveUrl(urlsPool)`.
1100
+ *
1101
+ * ### Execution flow
1102
+ *
1103
+ * 1. **Telemetry** — Starts a `getSignaling` span for end-to-end timing.
1104
+ * 2. **Candidate URL selection** — A stateful generator (`urlGen`) is created
1105
+ * from `urlsPool`. Each resubscription (e.g. via `retry`) advances to the next URL.
1106
+ * 3. **Short-circuit for WS URLs** — If the picked candidate already matches
1107
+ * `ws://` or `wss://`, emit `{ wsUrl, pollingUrl: null, instanceName: null }`
1108
+ * immediately and complete (no HTTP request).
1109
+ * 4. **Await client/view identifiers** — `this.store.select(selectClientAndViewIds)`
1110
+ * is tapped for logging (missing IDs) and then filtered to require both `clientId`
1111
+ * and `viewId` to be truthy.
1112
+ * 5. **Single in-flight HTTP orchestration call** — Uses `exhaustMap` to issue
1113
+ * `GET {signalingUrl}{clientId}/{viewId}`. New `{clientId, viewId}` emissions
1114
+ * while the request is in flight are **ignored** until completion, preventing overlap.
1115
+ * 6. **Per-attempt timeout** — `timeout(WS_TIMEOUT)` caps how long we wait for a response.
1116
+ * On timeout, the attempt errors and the outer `retry` schedules the next URL.
1117
+ * 7. **Response validation & progress reporting** — A `filter`:
1118
+ * - Calls `TelemetryStop('getSignaling', { ...data, multi: true })` on receipt.
1119
+ * - If `data.signallingServer === ''` or `data.error`:
1120
+ * shows a status message, optionally dispatches `setStatusPercentSignallingServer`
1121
+ * with `data.info.percent`, and **throws** to fail the attempt (triggers `retry`).
1122
+ * 8. **Mapping to `AwsInstance`** — Converts the validated orchestration payload into:
1123
+ * - `wsUrl`: via `httpUrlToWs(\`\${location.protocol}//\${data.signallingServer}\`)`
1124
+ * - `pollingUrl`: the base `signalingUrl` that succeeded
1125
+ * - `instanceName`: the (validated) `data.signallingServer`
1126
+ * 9. **Retry policy** — On *any* upstream error (timeout, HTTP error, invalid payload),
1127
+ * `retry({ delay })`:
1128
+ * - Shows a “connecting” status,
1129
+ * - Logs the attempt number,
1130
+ * - Waits `WS_TIMEOUT` ms (via `timer`) and **resubscribes**, advancing `urlGen`.
1131
+ *
1132
+ * ### Concurrency semantics
1133
+ *
1134
+ * - `exhaustMap` guarantees a **single** HTTP request per attempt; subsequent
1135
+ * `{clientId, viewId}` emissions are ignored until the current request completes.
1136
+ *
1137
+ * ### Telemetry semantics
1138
+ *
1139
+ * - `TelemetryStart('getSignaling')` begins before work.
1140
+ * - `TelemetryStop('getSignaling', {...})` runs on receipt of an orchestration response.
1141
+ * If an attempt fails (e.g., timeout), stopping the span is the responsibility of
1142
+ * your telemetry layer or a `finalize` elsewhere if desired.
1143
+ *
1144
+ * ### Error & retry semantics
1145
+ *
1146
+ * - Missing/never-emitted IDs → timeout → retry with next URL.
1147
+ * - HTTP/network error → retry with next URL.
1148
+ * - Invalid orchestration payload (`error` set or empty `signallingServer`) → throw in
1149
+ * validation filter → retry with next URL.
1150
+ * - Short-circuit WS path **does not** retry (emits once, completes).
1151
+ *
1152
+ * @param urlsPool - Ordered list of base URLs to probe. Retries advance through this list
1153
+ * until a working signaling server is found. A candidate may also be a direct `ws://`/`wss://`
1154
+ * URL to short-circuit HTTP orchestration.
1155
+ *
1156
+ * @returns Observable that emits exactly one {@link AwsInstance} on success and then completes.
1157
+ * On failure, the stream errors; the built-in `retry` operator re-subscribes after `WS_TIMEOUT`
1158
+ * and advances to the next URL candidate.
1159
+ *
1160
+ * @throws Emits an error within the observable chain (not a thrown synchronous exception) when:
1161
+ * - The HTTP request fails or times out.
1162
+ * - The orchestration response indicates an error or an empty `signallingServer`.
1163
+ * - Any other operator in the chain surfaces an error.
1164
+ *
1165
+ * @remarks
1166
+ * - The URL generator (`urlGen`) is created **outside** `defer`, so resubscriptions
1167
+ * advance the pool. Creating it inside `defer` would restart from the first URL each retry.
1168
+ * - `location.protocol` is used to derive `ws` vs `wss`. If this may run in non-browser
1169
+ * contexts (e.g., SSR), guard or abstract this logic.
1170
+ * - Consider capping retries with `count` in `retry({ count, delay })` when appropriate.
1171
+ *
1172
+ * @example
1173
+ * ```ts
1174
+ * getAwsInstance(['https://signaling.example.com/', 'wss://direct.example.com'])
1175
+ * .subscribe({
1176
+ * next: ({ wsUrl }) => connect(wsUrl),
1177
+ * error: (e) => console.error('Unable to establish signaling:', e),
1178
+ * });
1179
+ * ```
1180
+ *
1181
+ * @see httpUrlToWs
1182
+ * @see selectClientAndViewIds
1183
+ * @see setStatusPercentSignallingServer
1184
+ */
1185
+ getAwsInstance(urlsPool) {
1058
1186
  TelemetryStart('getSignaling');
1059
- const createSubscription = () => {
1187
+ // Stateful iterator over candidate URLs; retries advance this sequence.
1188
+ const urlGen = getActiveUrl(urlsPool);
1189
+ return defer(() => {
1060
1190
  const signalingUrl = `${urlGen.next().value}`;
1191
+ // Short-circuit if the candidate is already a WS endpoint.
1061
1192
  if (signalingUrl.match(/^ws(s?):\/\//i)) {
1062
- this.store.dispatch(setAwsInstance({
1193
+ return of({
1063
1194
  wsUrl: signalingUrl,
1064
1195
  pollingUrl: null,
1065
1196
  instanceName: null,
1066
- }));
1067
- return;
1197
+ });
1068
1198
  }
1069
- const subscription = combineLatest([
1070
- this.store.select(unrealFeature.selectStreamClientCompanyId),
1071
- this.store.select(unrealFeature.selectStreamViewId),
1072
- ])
1073
- .pipe(tap(([clientId, viewId]) => {
1199
+ return this.store.select(selectClientAndViewIds).pipe(
1200
+ // Log missing IDs without altering the stream.
1201
+ tap(({ clientId, viewId }) => {
1074
1202
  if (!clientId || !viewId) {
1075
1203
  console.error('Client ID or View ID is not set');
1076
1204
  }
1077
- }), filter(([clientId, viewId]) => !!clientId && !!viewId), tapLog('Stream Id =>'), switchMap$1(([clientId, viewId]) => this.httpClient.get(`${signalingUrl}${clientId}/${viewId}`)), timeout(4000), filter((data) => {
1205
+ }),
1206
+ // Only proceed when both identifiers are available.
1207
+ filter(({ clientId, viewId }) => !!clientId && !!viewId),
1208
+ // Take first value
1209
+ first(),
1210
+ // Ensure a single in-flight HTTP request per attempt.
1211
+ exhaustMap(({ clientId, viewId }) => this.httpClient.get(`${signalingUrl}${clientId}/${viewId}`)),
1212
+ // Bound the time spent waiting for the orchestration response.
1213
+ timeout$1(POLLING_TIME),
1214
+ // Validate response; report progress; fail fast on invalid payloads.
1215
+ filter((data) => {
1078
1216
  TelemetryStop('getSignaling', { ...data, multi: true });
1079
1217
  if (data.signallingServer === '' || data.error) {
1080
1218
  this.showStatusMessage(data?.mm_message || 'Server not found');
@@ -1083,27 +1221,44 @@ class SignallingService extends SubService {
1083
1221
  percent: data.info.percent,
1084
1222
  }));
1085
1223
  }
1086
- throw new Error('Invalid Value');
1224
+ // Throwing here fails the attempt and activates the retry strategy.
1225
+ throw new Error(`Orchestration message => ${data?.mm_message || 'Polling retry'}`);
1087
1226
  }
1088
- this.store.dispatch(setStatusPercentSignallingServer({ percent: 100 }));
1089
1227
  return true;
1090
- }), retryWhen((error) => error.pipe(tap(() => this.showStatusMessage(UnrealStatusMessage.CONNECTING_TO_SESSION)), tap(() => Logger.log('Retrying with new URL')), delay(4000), tap(() => {
1091
- // Unsubscribe the previous subscription and create a new one
1092
- subscription.unsubscribe();
1093
- createSubscription();
1094
- }))), takeUntil(merge(this.disconnect$, this.establishingConnectionDrop$)))
1095
- .subscribe((data) => {
1096
- subscription.unsubscribe();
1097
- const wsProtocol = location.protocol.match(/https/i) ? 'wss' : 'ws';
1098
- const wsUrl = `${wsProtocol}://${data.signallingServer}`;
1099
- this.store.dispatch(setAwsInstance({
1228
+ }),
1229
+ // Map a valid orchestration payload into the final AwsInstance.
1230
+ map$1((data) => {
1231
+ const wsUrl = httpUrlToWs(`${location.protocol}//${data.signallingServer}`);
1232
+ return {
1100
1233
  wsUrl,
1101
1234
  pollingUrl: signalingUrl,
1102
1235
  instanceName: data.signallingServer,
1103
- }));
1104
- });
1105
- };
1106
- createSubscription();
1236
+ };
1237
+ }));
1238
+ }).pipe(
1239
+ // Retry the whole attempt on error, advancing to the next URL each time.
1240
+ retry({
1241
+ delay: (err, attempt) => {
1242
+ this.showStatusMessage(UnrealStatusMessage.CONNECTING_TO_SESSION);
1243
+ Logger.log(`Retrying with new URL in ${POLLING_TIME}ms. Attempt# ${attempt}`, err?.message);
1244
+ return timer(POLLING_TIME);
1245
+ },
1246
+ // count: 10, // Optional: cap the number of attempts.
1247
+ }));
1248
+ }
1249
+ connectToCirrus(wsUrl) {
1250
+ this.clearWs();
1251
+ return createWebSocket(wsUrl).pipe(tapLog('WS CREATED'), tap((ws) => {
1252
+ TelemetryStart('iceCandidate');
1253
+ this.addWsHandlers(ws);
1254
+ }));
1255
+ }
1256
+ addWsHandlers(ws) {
1257
+ ws.onmessage = OnMessageHandler.bind(this);
1258
+ ws.onclose = OnCloseHandler.bind(this);
1259
+ ws.onerror = OnErrorHandler.bind(this);
1260
+ Logger.log('WS HANDLERS ADDED');
1261
+ OnOpenHandler.call(this);
1107
1262
  }
1108
1263
  showStatusMessage(message) {
1109
1264
  this.store.dispatch(setStatusMessage({ message }));
@@ -1113,10 +1268,7 @@ class SignallingService extends SubService {
1113
1268
  * @param data
1114
1269
  */
1115
1270
  close(data) {
1116
- const { code, reason } = data || {
1117
- code: WSCloseCode_NORMAL_CLOSURE,
1118
- reason: 'NoReason',
1119
- };
1271
+ const { code, reason } = data;
1120
1272
  if (this.ws)
1121
1273
  Logger.warn('Closing existing WebSocket connection');
1122
1274
  this.ws?.close(code, reason);
@@ -1142,47 +1294,6 @@ class SignallingService extends SubService {
1142
1294
  }
1143
1295
  }
1144
1296
  }
1145
- watchTimeoutOrErrorAndReconnectLater() {
1146
- this.stopRetryTimer();
1147
- this.wsTimeoutHandler = setTimeout(() => {
1148
- Logger.warn('No WS Response, retrying new signaling');
1149
- this.showStatusMessage(UnrealStatusMessage.CONNECTING_TO_SESSION);
1150
- this.stopEstablishingConnection();
1151
- this.store.dispatch(initSignalling());
1152
- }, WS_TIMEOUT);
1153
- }
1154
- stopRetryTimer() {
1155
- clearTimeout(this.wsTimeoutHandler);
1156
- }
1157
- initWebSocket(url) {
1158
- if (!window?.['WebSocket']) {
1159
- alert("Your browser doesn't support WebSocket");
1160
- return;
1161
- }
1162
- this.clearWs();
1163
- const wsUrl = this.httpUrlToWs(url);
1164
- Logger.info('Creating socket', wsUrl);
1165
- try {
1166
- this.ws = new WebSocket(wsUrl);
1167
- }
1168
- catch (error) {
1169
- this.ws = {};
1170
- this.store.dispatch(setErrorMessage({
1171
- errorType: 'WebSocketError',
1172
- message: 'WebSocket Error',
1173
- }));
1174
- Logger.error('Error creating WebSocket', error);
1175
- }
1176
- this.ws.onmessage = OnMessageHandler.bind(this);
1177
- this.ws.onerror = OnErrorHandler.bind(this);
1178
- this.ws.onclose = OnCloseHandler.bind(this);
1179
- this.ws.onopen = OnOpenHandler.bind(this);
1180
- this.watchTimeoutOrErrorAndReconnectLater();
1181
- TelemetryStart('iceCandidate');
1182
- }
1183
- httpUrlToWs(url) {
1184
- return url.replace('http://', 'ws://').replace('https://', 'wss://');
1185
- }
1186
1297
  clearWs() {
1187
1298
  this.onWebRtcAnswer$.next(null);
1188
1299
  if (this.ws) {
@@ -1214,10 +1325,14 @@ class SignallingService extends SubService {
1214
1325
  this.wsMsgHandlers.instanceReserved = InstanceReservedHandler.bind(this);
1215
1326
  this.wsMsgHandlers.offer = OfferHandler.bind(this);
1216
1327
  }
1217
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.1", ngImport: i0, type: SignallingService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1218
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.2.1", ngImport: i0, type: SignallingService }); }
1328
+ getRegion() {
1329
+ Logger.log('Start Getting Region');
1330
+ return this.regionsPingService.getFastest().pipe(first());
1331
+ }
1332
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.4", ngImport: i0, type: SignallingService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1333
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.2.4", ngImport: i0, type: SignallingService }); }
1219
1334
  }
1220
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.1", ngImport: i0, type: SignallingService, decorators: [{
1335
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.4", ngImport: i0, type: SignallingService, decorators: [{
1221
1336
  type: Injectable
1222
1337
  }], ctorParameters: () => [] });
1223
1338
 
@@ -1270,17 +1385,13 @@ class WebRtcPlayerService extends SubService {
1270
1385
  Logger.info('Creating offer');
1271
1386
  let offer;
1272
1387
  try {
1273
- clearTimeout(this.webRtcErrorTimeout);
1274
1388
  offer = await this.createPeerConnection(this.cfg);
1275
- this.webRtcErrorTimeout = setTimeout(() => {
1276
- if (this.pcClient?.connectionState?.match(/connecting|failed/gi)) {
1277
- this.dispatchWebRtcError('WebRTCError: Timeout');
1278
- }
1279
- }, 10000);
1280
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
1281
1389
  }
1282
- catch (error) {
1283
- this.dispatchWebRtcError('WebRTCError: Offer Error');
1390
+ catch {
1391
+ this.store.dispatch(disconnectStream({
1392
+ reason: DisconnectReason.WebRTCError,
1393
+ message: 'WebRTCError: Offer Error',
1394
+ }));
1284
1395
  }
1285
1396
  return offer;
1286
1397
  }
@@ -1338,6 +1449,8 @@ class WebRtcPlayerService extends SubService {
1338
1449
  Logger.warn('Closing existing PeerConnection');
1339
1450
  this.pcClient?.close();
1340
1451
  this.pcClient = null;
1452
+ if (this.dcClient)
1453
+ Logger.warn('Closing existing DataChannel');
1341
1454
  this.dcClient?.close();
1342
1455
  this.dcClient = null;
1343
1456
  }
@@ -1380,13 +1493,6 @@ class WebRtcPlayerService extends SubService {
1380
1493
  Logger.error("For testing you can enable HTTP microphone access Chrome by visiting chrome://flags/ and enabling 'unsafely-treat-insecure-origin-as-secure'");
1381
1494
  }
1382
1495
  }
1383
- dispatchWebRtcError(message) {
1384
- Logger.error(message);
1385
- this.store.dispatch(setErrorMessage({
1386
- errorType: 'WebRTCError',
1387
- message,
1388
- }));
1389
- }
1390
1496
  async createPeerConnection(config) {
1391
1497
  this.closePC();
1392
1498
  this.pcClient = new RTCPeerConnection(config);
@@ -1515,8 +1621,9 @@ class WebRtcPlayerService extends SubService {
1515
1621
  .pipe(first())
1516
1622
  .subscribe((e) => {
1517
1623
  Logger.warn(`[DATACHANNEL] Data channel disconnected: ${datachannel.label}(${datachannel.id})`, e);
1518
- this.store.dispatch(destroyRemoteConnections({
1519
- disconnectReason: DisconnectReason.dataChannelClosed,
1624
+ this.store.dispatch(disconnectStream({
1625
+ reason: DisconnectReason.DataChannelClosed,
1626
+ message: 'DataChannelClosed',
1520
1627
  }));
1521
1628
  });
1522
1629
  fromEvent(datachannel, 'error')
@@ -1549,8 +1656,7 @@ class WebRtcPlayerService extends SubService {
1549
1656
  text +=
1550
1657
  '\n If you are experiencing connection problems please try Google Chrome';
1551
1658
  }
1552
- this.store.dispatch(setStatusMessage({ message: text }));
1553
- this.store.dispatch(setDataChannelConnected({ value: true }));
1659
+ this.store.dispatch(setDataChannelConnected({ message: text }));
1554
1660
  }
1555
1661
  async createOffer(pcClient) {
1556
1662
  try {
@@ -1566,10 +1672,10 @@ class WebRtcPlayerService extends SubService {
1566
1672
  Logger.error("Couldn't create offer");
1567
1673
  }
1568
1674
  }
1569
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.1", ngImport: i0, type: WebRtcPlayerService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1570
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.2.1", ngImport: i0, type: WebRtcPlayerService }); }
1675
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.4", ngImport: i0, type: WebRtcPlayerService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1676
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.2.4", ngImport: i0, type: WebRtcPlayerService }); }
1571
1677
  }
1572
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.1", ngImport: i0, type: WebRtcPlayerService, decorators: [{
1678
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.4", ngImport: i0, type: WebRtcPlayerService, decorators: [{
1573
1679
  type: Injectable
1574
1680
  }], ctorParameters: () => [] });
1575
1681
 
@@ -1684,7 +1790,7 @@ class AggregatorService extends SubService {
1684
1790
  ?.remove();
1685
1791
  }
1686
1792
  startListenCallbacks() {
1687
- Logger.info('Start Listen Callbacks');
1793
+ Logger.info('Start Listen Unreal Callbacks');
1688
1794
  let previousJson = null;
1689
1795
  this.addResponseEventListener('unrealEvents', (data) => {
1690
1796
  try {
@@ -1788,10 +1894,10 @@ class AggregatorService extends SubService {
1788
1894
  Logger.warn(`unrecognized data received, packet ID ${view[0]}`);
1789
1895
  }
1790
1896
  }
1791
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.1", ngImport: i0, type: AggregatorService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1792
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.2.1", ngImport: i0, type: AggregatorService }); }
1897
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.4", ngImport: i0, type: AggregatorService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1898
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.2.4", ngImport: i0, type: AggregatorService }); }
1793
1899
  }
1794
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.1", ngImport: i0, type: AggregatorService, decorators: [{
1900
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.4", ngImport: i0, type: AggregatorService, decorators: [{
1795
1901
  type: Injectable
1796
1902
  }], ctorParameters: () => [] });
1797
1903
 
@@ -1806,7 +1912,10 @@ class ConsoleExtensionsService extends SubService {
1806
1912
  return;
1807
1913
  }
1808
1914
  window.dropConnection = () => {
1809
- this.store.dispatch(destroyConnectionsAndResetState());
1915
+ this.store.dispatch(disconnectStream({
1916
+ reason: DisconnectReason.DropConnection,
1917
+ message: 'Manual Console Drop',
1918
+ }));
1810
1919
  return true;
1811
1920
  };
1812
1921
  window.toggleBandwidth = () => {
@@ -1840,10 +1949,10 @@ class ConsoleExtensionsService extends SubService {
1840
1949
  Logger.info('setWarnTime() => set time to appear the AFK window.');
1841
1950
  Logger.info('emitCommand(command) => send command to Unreal Engine.');
1842
1951
  }
1843
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.1", ngImport: i0, type: ConsoleExtensionsService, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
1844
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.2.1", ngImport: i0, type: ConsoleExtensionsService }); }
1952
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.4", ngImport: i0, type: ConsoleExtensionsService, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
1953
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.2.4", ngImport: i0, type: ConsoleExtensionsService }); }
1845
1954
  }
1846
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.1", ngImport: i0, type: ConsoleExtensionsService, decorators: [{
1955
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.4", ngImport: i0, type: ConsoleExtensionsService, decorators: [{
1847
1956
  type: Injectable
1848
1957
  }] });
1849
1958
 
@@ -1854,10 +1963,10 @@ class DevModeService {
1854
1963
  setDevMode(value) {
1855
1964
  return localStorage.setItem('devMode', value.toString());
1856
1965
  }
1857
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.1", ngImport: i0, type: DevModeService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1858
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.2.1", ngImport: i0, type: DevModeService, providedIn: 'root' }); }
1966
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.4", ngImport: i0, type: DevModeService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1967
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.2.4", ngImport: i0, type: DevModeService, providedIn: 'root' }); }
1859
1968
  }
1860
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.1", ngImport: i0, type: DevModeService, decorators: [{
1969
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.4", ngImport: i0, type: DevModeService, decorators: [{
1861
1970
  type: Injectable,
1862
1971
  args: [{
1863
1972
  providedIn: 'root',
@@ -2132,10 +2241,10 @@ class UnrealCommunicatorService {
2132
2241
  callback,
2133
2242
  });
2134
2243
  }
2135
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.1", ngImport: i0, type: UnrealCommunicatorService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
2136
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.2.1", ngImport: i0, type: UnrealCommunicatorService }); }
2244
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.4", ngImport: i0, type: UnrealCommunicatorService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
2245
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.2.4", ngImport: i0, type: UnrealCommunicatorService }); }
2137
2246
  }
2138
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.1", ngImport: i0, type: UnrealCommunicatorService, decorators: [{
2247
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.4", ngImport: i0, type: UnrealCommunicatorService, decorators: [{
2139
2248
  type: Injectable
2140
2249
  }], ctorParameters: () => [] });
2141
2250
 
@@ -2634,7 +2743,7 @@ class RegionsPingService {
2634
2743
  }
2635
2744
  }
2636
2745
  getFastest(regionListUrl = this.unrealInitialConfig?.regionsPingUrl || '') {
2637
- return this.getProviders(regionListUrl).pipe(switchMap$1((providers) => this.getPingResult(providers)), catchError(() => of(null)), map$1((data) => data?.region_code));
2746
+ return this.getProviders(regionListUrl).pipe(switchMap$1((providers) => this.getPingResult(providers)), catchError(() => of(null)), tapLog('PingResult'), map$1((data) => data?.region_code));
2638
2747
  }
2639
2748
  getPingResult(providers) {
2640
2749
  const regions = providers.regions;
@@ -2691,6 +2800,9 @@ class RegionsPingService {
2691
2800
  credentials: 'omit', // Optional: prevents sending or receiving cookies, which can affect caching.
2692
2801
  }, timeout);
2693
2802
  }
2803
+ catch {
2804
+ //Do not remove this block, else finally will not work!
2805
+ }
2694
2806
  finally {
2695
2807
  const latency = Math.round(performance.now() - startTime);
2696
2808
  pingResults.push(latency);
@@ -2712,10 +2824,10 @@ class RegionsPingService {
2712
2824
  throw error;
2713
2825
  }
2714
2826
  }
2715
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.1", ngImport: i0, type: RegionsPingService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
2716
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.2.1", ngImport: i0, type: RegionsPingService }); }
2827
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.4", ngImport: i0, type: RegionsPingService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
2828
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.2.4", ngImport: i0, type: RegionsPingService }); }
2717
2829
  }
2718
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.1", ngImport: i0, type: RegionsPingService, decorators: [{
2830
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.4", ngImport: i0, type: RegionsPingService, decorators: [{
2719
2831
  type: Injectable
2720
2832
  }], ctorParameters: () => [] });
2721
2833
 
@@ -2755,10 +2867,10 @@ class StreamStatusTelemetryService {
2755
2867
  init() {
2756
2868
  // do nothing, just to not forget to initialize Service
2757
2869
  }
2758
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.1", ngImport: i0, type: StreamStatusTelemetryService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
2759
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.2.1", ngImport: i0, type: StreamStatusTelemetryService }); }
2870
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.4", ngImport: i0, type: StreamStatusTelemetryService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
2871
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.2.4", ngImport: i0, type: StreamStatusTelemetryService }); }
2760
2872
  }
2761
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.1", ngImport: i0, type: StreamStatusTelemetryService, decorators: [{
2873
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.4", ngImport: i0, type: StreamStatusTelemetryService, decorators: [{
2762
2874
  type: Injectable
2763
2875
  }], ctorParameters: () => [] });
2764
2876
 
@@ -2792,7 +2904,6 @@ const initialState = {
2792
2904
  viewportReady: false,
2793
2905
  dataChannelConnected: false,
2794
2906
  isVideoPlaying: false,
2795
- isFreezeLoaderPercents: false,
2796
2907
  statusPercentSignallingServer: null,
2797
2908
  statusMessage: null,
2798
2909
  errorMessage: null,
@@ -2801,7 +2912,7 @@ const initialState = {
2801
2912
  streamResolution: { width: null, height: null },
2802
2913
  freezeFrameFromVideo: { dataUrl: null, progress: null },
2803
2914
  freezeFrame: { dataUrl: null, progress: null },
2804
- disconnectReason: DisconnectReason.none,
2915
+ disconnectReason: DisconnectReason.None,
2805
2916
  awsInstance: {
2806
2917
  wsUrl: null,
2807
2918
  instanceName: null,
@@ -2811,7 +2922,6 @@ const initialState = {
2811
2922
  autoStart: true,
2812
2923
  warnTimeout: DEFAULT_AFK_TIMEOUT,
2813
2924
  },
2814
- matchMakerUrls: [],
2815
2925
  loaderCommands: {
2816
2926
  commandsInProgress: [],
2817
2927
  totalCommandsStarted: 0,
@@ -2844,12 +2954,17 @@ const unrealReducer = createReducer(initialState, on(changeLowBandwidth, (state,
2844
2954
  pollingUrl,
2845
2955
  },
2846
2956
  };
2847
- }), on(setViewportReady, (state, { value }) => {
2957
+ }), on(setViewportReady, (state) => {
2848
2958
  return {
2849
2959
  ...state,
2850
- viewportReady: value,
2851
- statusMessage: value ? null : state.statusMessage,
2852
- errorMessage: value ? null : state.errorMessage,
2960
+ viewportReady: true,
2961
+ statusMessage: null,
2962
+ errorMessage: null,
2963
+ };
2964
+ }), on(setViewportNotReady, (state) => {
2965
+ return {
2966
+ ...state,
2967
+ viewportReady: false,
2853
2968
  };
2854
2969
  }), on(updateCirrusInfo, (state, { ssInfo, ssData }) => {
2855
2970
  return {
@@ -2877,14 +2992,15 @@ const unrealReducer = createReducer(initialState, on(changeLowBandwidth, (state,
2877
2992
  progress: freezeFrame.progress || null,
2878
2993
  },
2879
2994
  };
2880
- }), on(setErrorMessage, (state, errorMessage) => {
2995
+ }), on(disconnectStream, (state, errorMessage) => {
2881
2996
  if (state.dataChannelConnected) {
2882
2997
  return state;
2883
2998
  }
2884
2999
  return {
2885
3000
  ...state,
2886
- errorMessage: errorMessage,
3001
+ errorMessage,
2887
3002
  statusMessage: null,
3003
+ wasInitialized: true,
2888
3004
  };
2889
3005
  }), on(setFreezeFrameFromVideo, (state, freezeFrameFromVideo) => {
2890
3006
  return {
@@ -2894,7 +3010,7 @@ const unrealReducer = createReducer(initialState, on(changeLowBandwidth, (state,
2894
3010
  progress: freezeFrameFromVideo.progress || null,
2895
3011
  },
2896
3012
  };
2897
- }), on(setStatusMessage, (state, { message }) => {
3013
+ }), on(setStatusMessage, setDataChannelConnected, (state, { message }) => {
2898
3014
  return {
2899
3015
  ...state,
2900
3016
  statusMessage: message,
@@ -2904,32 +3020,23 @@ const unrealReducer = createReducer(initialState, on(changeLowBandwidth, (state,
2904
3020
  ...state,
2905
3021
  establishingConnection: value,
2906
3022
  };
2907
- }), on(setIsFreezeLoaderPercents, (state) => {
2908
- return {
2909
- ...state,
2910
- isFreezeLoaderPercents: true,
2911
- };
2912
3023
  }), on(setStatusPercentSignallingServer, (state, { percent }) => {
2913
3024
  return {
2914
3025
  ...state,
2915
3026
  statusPercentSignallingServer: percent,
2916
3027
  };
2917
- }), on(setDataChannelConnected, (state, { value }) => {
3028
+ }), on(setDataChannelConnected, (state) => {
2918
3029
  return {
2919
3030
  ...state,
2920
- dataChannelConnected: value,
2921
- wasInitialized: value ? true : state.wasInitialized,
3031
+ dataChannelConnected: true,
3032
+ establishingConnection: false,
3033
+ wasInitialized: true,
2922
3034
  };
2923
- }), on(setConfig, (state, { config }) => {
3035
+ }), on(setConfig, startStream, (state, { config }) => {
2924
3036
  return {
2925
3037
  ...state,
2926
3038
  streamConfig: { ...state.streamConfig, ...config },
2927
3039
  };
2928
- }), on(setMatchMakerUrls, (state, { matchMakerUrls }) => {
2929
- return {
2930
- ...state,
2931
- matchMakerUrls,
2932
- };
2933
3040
  }), on(resetConfig, (state) => {
2934
3041
  return {
2935
3042
  ...state,
@@ -2943,20 +3050,17 @@ const unrealReducer = createReducer(initialState, on(changeLowBandwidth, (state,
2943
3050
  warnTimeout: DEFAULT_AFK_TIMEOUT,
2944
3051
  },
2945
3052
  };
2946
- }), on(setCirrusConnected, (state) => {
2947
- return {
2948
- ...state,
2949
- cirrusConnected: true,
2950
- };
2951
- }), on(setCirrusDisconnected, (state) => {
3053
+ }), on(initSignalling, (state, { resetDisconnectionReason = true }) => {
2952
3054
  return {
2953
3055
  ...state,
2954
- cirrusConnected: false,
3056
+ disconnectReason: resetDisconnectionReason
3057
+ ? DisconnectReason.None
3058
+ : state.disconnectReason,
2955
3059
  };
2956
- }), on(initSignalling, (state) => {
3060
+ }), on(destroyRemoteConnections, (state, { reason }) => {
2957
3061
  return {
2958
3062
  ...state,
2959
- disconnectReason: DisconnectReason.none,
3063
+ disconnectReason: reason,
2960
3064
  };
2961
3065
  }), on(setSignalingName, (state, { instanceName }) => {
2962
3066
  return {
@@ -3021,9 +3125,16 @@ const unrealReducer = createReducer(initialState, on(changeLowBandwidth, (state,
3021
3125
  ...state,
3022
3126
  loaderCommands: removeExileCommands(state.loaderCommands, id),
3023
3127
  };
3024
- }), on(resetUnrealState, (state) => {
3128
+ }), on(setCirrusConnected, (state) => {
3129
+ return {
3130
+ ...state,
3131
+ cirrusConnected: true,
3132
+ };
3133
+ }), on(setCirrusDisconnected, (state) => {
3025
3134
  return {
3026
3135
  ...initialState,
3136
+ establishingConnection: state.establishingConnection,
3137
+ disconnectReason: state.disconnectReason,
3027
3138
  wasInitialized: state.wasInitialized,
3028
3139
  isFirstSuccessLoad: state.isFirstSuccessLoad,
3029
3140
  matchUrls: state.matchUrls,
@@ -3033,7 +3144,12 @@ const unrealReducer = createReducer(initialState, on(changeLowBandwidth, (state,
3033
3144
  videoIntroSrc: state.videoIntroSrc,
3034
3145
  imageLoadingSrc: state.imageLoadingSrc,
3035
3146
  };
3036
- }), on(resetUnrealStateAction, () => {
3147
+ }), on(dropConnection, (state) => {
3148
+ return {
3149
+ ...state,
3150
+ establishingConnection: false,
3151
+ };
3152
+ }), on(destroyUnrealScene, () => {
3037
3153
  return initialState;
3038
3154
  }));
3039
3155
 
@@ -3050,10 +3166,10 @@ class UnrealErrorModalComponent {
3050
3166
  close() {
3051
3167
  this.dialogRef.close();
3052
3168
  }
3053
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.1", ngImport: i0, type: UnrealErrorModalComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
3054
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.2.1", type: UnrealErrorModalComponent, isStandalone: true, selector: "app-unreal-error-modal", ngImport: i0, template: "<div class=\"src-modal src-modal--small\">\n <div class=\"src-modal__header\">\n <div\n class=\"src-modal__title\"\n [attr.data-testid]=\"'unreal-error-header-title'\"\n >\n Warning\n </div>\n </div>\n <div class=\"src-modal__body\">\n <div>{{ dialogData.content }}</div>\n </div>\n <div class=\"src-modal__footer\">\n <src-button [colorScheme]=\"'secondary'\" (onClick)=\"close()\">\n Ok\n </src-button>\n </div>\n</div>\n", styles: [""], dependencies: [{ kind: "component", type: SourceButtonComponent, selector: "src-button", inputs: ["type", "appearance", "colorScheme", "size", "state", "customClass", "hasDisclosure", "isFullWidth", "isPressed", "isDisabled", "isLoading", "iconButton", "srcButtonConfig", "formID", "data-testid"], outputs: ["onClick", "onSubmit"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
3169
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.4", ngImport: i0, type: UnrealErrorModalComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
3170
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.2.4", type: UnrealErrorModalComponent, isStandalone: true, selector: "app-unreal-error-modal", ngImport: i0, template: "<div class=\"src-modal src-modal--small\">\n <div class=\"src-modal__header\">\n <div\n class=\"src-modal__title\"\n [attr.data-testid]=\"'unreal-error-header-title'\"\n >\n Warning\n </div>\n </div>\n <div class=\"src-modal__body\">\n <div>{{ dialogData.content }}</div>\n </div>\n <div class=\"src-modal__footer\">\n <src-button [colorScheme]=\"'secondary'\" (onClick)=\"close()\">\n Ok\n </src-button>\n </div>\n</div>\n", styles: [""], dependencies: [{ kind: "component", type: SourceButtonComponent, selector: "src-button", inputs: ["type", "appearance", "colorScheme", "size", "state", "customClass", "hasDisclosure", "isFullWidth", "isPressed", "isDisabled", "isLoading", "iconButton", "srcButtonConfig", "formID", "data-testid"], outputs: ["onClick", "onSubmit"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
3055
3171
  }
3056
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.1", ngImport: i0, type: UnrealErrorModalComponent, decorators: [{
3172
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.4", ngImport: i0, type: UnrealErrorModalComponent, decorators: [{
3057
3173
  type: Component,
3058
3174
  args: [{ selector: 'app-unreal-error-modal', changeDetection: ChangeDetectionStrategy.OnPush, imports: [SourceButtonComponent], template: "<div class=\"src-modal src-modal--small\">\n <div class=\"src-modal__header\">\n <div\n class=\"src-modal__title\"\n [attr.data-testid]=\"'unreal-error-header-title'\"\n >\n Warning\n </div>\n </div>\n <div class=\"src-modal__body\">\n <div>{{ dialogData.content }}</div>\n </div>\n <div class=\"src-modal__footer\">\n <src-button [colorScheme]=\"'secondary'\" (onClick)=\"close()\">\n Ok\n </src-button>\n </div>\n</div>\n" }]
3059
3175
  }] });
@@ -3073,23 +3189,38 @@ class UnrealEffects {
3073
3189
  this.videoService = inject(VideoService);
3074
3190
  this.dataChannelConnectionTimeout = this.unrealInitialConfig?.dataChannelConnectionTimeout ??
3075
3191
  DATA_CHANNEL_CONNECTION_TIMEOUT;
3076
- this.cirrusDisconnectEffect$ = createEffect(() => {
3077
- return this.actions$.pipe(ofType(setCirrusDisconnected), map(() => resetUnrealState()));
3192
+ this.disconnectReasonHandling$ = createEffect(() => {
3193
+ const destroyReasons = [
3194
+ DisconnectReason.Afk,
3195
+ DisconnectReason.DataChannelClosed,
3196
+ DisconnectReason.DataChannelTimeout,
3197
+ DisconnectReason.WebSocketError,
3198
+ DisconnectReason.WebSocketClose,
3199
+ DisconnectReason.WebRTCError,
3200
+ DisconnectReason.DropConnection,
3201
+ ];
3202
+ return this.actions$.pipe(ofType(disconnectStream), filter(({ reason }) => destroyReasons.some((r) => r === reason)), tap(({ reason, message }) => {
3203
+ Logger.log(`Disconnect Call=> reason:'${reason}', message:'${message}'`);
3204
+ }), map(({ reason }) => destroyRemoteConnections({ reason })));
3078
3205
  });
3079
3206
  this.destroyConnections$ = createEffect(() => {
3080
- return this.actions$.pipe(ofType(destroyConnectionsAndResetState), map(() => destroyRemoteConnections({ disconnectReason: DisconnectReason.reset })));
3081
- });
3082
- this.resetState$ = createEffect(() => {
3083
- return this.actions$.pipe(ofType(destroyConnectionsAndResetState), map(() => resetUnrealState()));
3207
+ return this.actions$.pipe(ofType(destroyUnrealScene), map(() => destroyRemoteConnections({
3208
+ reason: DisconnectReason.Destroy,
3209
+ })));
3084
3210
  });
3085
3211
  this.destroyRemoteConnections$ = createEffect(() => {
3086
- return this.actions$.pipe(ofType(destroyRemoteConnections), tap(({ disconnectReason }) => {
3212
+ return this.actions$.pipe(ofType(destroyRemoteConnections), tap(({ reason }) => {
3087
3213
  this.signallingService.close({
3088
- code: WSCloseCode_NORMAL_CIRRUS_CLOSED,
3089
- reason: disconnectReason,
3214
+ code: WSCloseCode_FORCE_CIRRUS_CLOSE,
3215
+ reason,
3090
3216
  });
3091
3217
  this.player.closePC();
3092
- }));
3218
+ }), filter(({ reason }) => reason === DisconnectReason.DropConnection), map(() => dropConnection()));
3219
+ });
3220
+ this.webrtcErrorModalComponent$ = createEffect(() => {
3221
+ return this.actions$.pipe(ofType(disconnectStream), filter(({ reason }) => reason === DisconnectReason.WebRTCError), debounceTime$1(400), switchMap$1(() => this.store
3222
+ .select(unrealFeature.selectDataChannelConnected)
3223
+ .pipe(take(1), filter(Falsy))), tap(() => this.dialog.open(WebrtcErrorModalComponent)));
3093
3224
  }, { dispatch: false });
3094
3225
  this.changeStreamResolution$ = createEffect(() => {
3095
3226
  return this.actions$.pipe(ofType(changeStreamResolutionAction), filter((size) => !!(size?.width && size?.height)), withLatestFrom(this.store.select(unrealFeature.selectStreamResolution)), filter(([newSizes, savedSizes]) => !(newSizes.width === savedSizes.width &&
@@ -3122,45 +3253,67 @@ class UnrealEffects {
3122
3253
  this.resetAfk$ = createEffect(() => {
3123
3254
  return this.actions$.pipe(ofType(setConfig, resetWarnTimeout, resetConfig), map(() => resetAfkAction()));
3124
3255
  });
3125
- this.resetFreezeFrameOnViewportDestroy$ = createEffect(() => {
3126
- return this.actions$.pipe(ofType(setViewportReady), filter(Falsy), map(() => setFreezeFrame({ dataUrl: null, progress: null })));
3256
+ this.abortEstablishingConnection$ = createEffect(() => {
3257
+ const viewportReady$ = this.store
3258
+ .select(unrealFeature.selectViewportReady)
3259
+ .pipe(filter(Truthy), map(() => abortEstablishingConnection()));
3260
+ const disconnectEvents$ = this.actions$.pipe(ofType(setCirrusDisconnected, destroyUnrealScene, dropConnection), map(() => abortEstablishingConnection()));
3261
+ return merge(viewportReady$, disconnectEvents$).pipe(tapLog('ABORT'));
3127
3262
  });
3128
3263
  this.setMaxFps$ = createEffect(() => {
3129
3264
  return this.actions$.pipe(ofType(setMaxFps), tap(({ maxFps }) => {
3130
3265
  this.commandsSender.sendCommandToUnreal(getSetFpsCommand(maxFps));
3131
3266
  }));
3132
3267
  }, { dispatch: false });
3133
- this.webrtcErrorModalComponent$ = createEffect(() => {
3134
- return this.actions$.pipe(ofType(setErrorMessage), debounceTime$1(400), combineLatestWith(this.store.select(unrealFeature.selectDataChannelConnected)), filter(([error, isConnected]) => {
3135
- return !isConnected && error?.errorType === 'WebRTCError';
3136
- }), tap(() => this.dialog.open(WebrtcErrorModalComponent)));
3137
- }, { dispatch: false });
3138
3268
  this.resetAfkAction$ = createEffect(() => {
3139
3269
  return this.actions$.pipe(ofType(resetAfkAction), tap(() => resetAfk()));
3140
3270
  }, { dispatch: false });
3141
- this.setDataChannelTimeoutCheck$ = createEffect(() => {
3142
- return this.actions$.pipe(ofType(setAwsInstance), filter(({ wsUrl }) => !!wsUrl), tap(() => Logger.info(`DataChannel timeout check started with next timeout: ${this.dataChannelConnectionTimeout}`)), debounceTime$1(this.dataChannelConnectionTimeout), // Timeout, if not connected, sends an error report, then reconnects
3143
- withLatestFrom(this.store.select(unrealFeature.selectSsData), this.store.select(unrealFeature.selectCirrusConnected), this.store.select(unrealFeature.selectDataChannelConnected)), filter(([, , isCirrusConnected, isDataChannelConnected]) => isCirrusConnected && !isDataChannelConnected), switchMap$1(([awsInstance, ssData]) => {
3144
- const error = `DataChannel connection timeout ${this.dataChannelConnectionTimeout}ms, requesting new signaling.`;
3145
- Logger.error(error);
3146
- return this.http
3147
- .post(awsInstance.pollingUrl || '', {
3148
- awsInstance,
3149
- connectionId: ssData?.connectionId,
3150
- href: location.href,
3151
- userAgent: navigator.userAgent,
3152
- error,
3153
- })
3154
- .pipe(catchError((error) => {
3155
- Logger.error('Error sending timeout info:', error);
3156
- return of(null);
3271
+ this.setSignalingTo100$ = createEffect(() => this.actions$.pipe(ofType(setAwsInstance), map(() => setStatusPercentSignallingServer({ percent: 100 }))));
3272
+ this.setDataChannelTimeoutCheck$ = createEffect(() => this.actions$.pipe(ofType(setAwsInstance),
3273
+ // require wsUrl present on the action payload
3274
+ filter((action) => !!action.wsUrl),
3275
+ // for each awsInstance action capture one ssData snapshot, then wait for dataChannelConnected
3276
+ switchMap$1((awsInstance) => {
3277
+ return this.store.select(unrealFeature.selectSsData).pipe(filter(Truthy), take(1), tap(() => Logger.log(`DataChannel timeout check started with next timeout: ${this.dataChannelConnectionTimeout}ms`)), switchMap$1((ssData) => {
3278
+ const abort$ = this.actions$.pipe(ofType(setCirrusDisconnected), take(1));
3279
+ return this.store
3280
+ .select(unrealFeature.selectDataChannelConnected)
3281
+ .pipe(
3282
+ // wait until data channel reports connected (truthy)
3283
+ filter(Truthy), take(1),
3284
+ // 🚫 If Cirrus (or anything else) disconnects first, abort BEFORE timeout fires.
3285
+ takeUntil(abort$),
3286
+ // if it becomes true within timeout -> complete without dispatching any action
3287
+ timeout$1(this.dataChannelConnectionTimeout),
3288
+ // successful connect → no action
3289
+ mergeMap(() => EMPTY),
3290
+ // ⏱️ Only actual timeout (or real upstream error) ends up here.
3291
+ catchError(() => {
3292
+ const error = `⏱️ DataChannel connection timeout ${this.dataChannelConnectionTimeout}ms, requesting new signaling.`;
3293
+ Logger.error(error);
3294
+ const body = {
3295
+ awsInstance,
3296
+ connectionId: ssData?.connectionId,
3297
+ href: location.href,
3298
+ userAgent: navigator.userAgent,
3299
+ error,
3300
+ };
3301
+ return this.http
3302
+ .post(awsInstance.pollingUrl || '', body)
3303
+ .pipe(catchError((postError) => {
3304
+ Logger.error('Error sending timeout info:', postError);
3305
+ return of(null);
3306
+ }),
3307
+ // map response to the destroy action which ngrx will dispatch
3308
+ map(() => disconnectStream({
3309
+ reason: DisconnectReason.DataChannelTimeout,
3310
+ message: 'Data Channel Timeout',
3311
+ })));
3157
3312
  }));
3158
- }), map(() => destroyRemoteConnections({
3159
- disconnectReason: DisconnectReason.dataChannelTimeout,
3160
- })));
3161
- });
3313
+ }));
3314
+ })));
3162
3315
  this.destroyConnectionAndRestart$ = createEffect(() => {
3163
- return this.actions$.pipe(ofType(destroyRemoteConnections), filter(({ disconnectReason }) => disconnectReason === DisconnectReason.dataChannelTimeout), tap(() => this.store.dispatch(setIsFreezeLoaderPercents())), switchMap$1(() => this.actions$.pipe(ofType(resetUnrealState), first())), map(() => initSignalling()));
3316
+ return this.actions$.pipe(ofType(destroyRemoteConnections), filter(({ reason }) => reason === DisconnectReason.DataChannelTimeout), switchMap$1(() => this.actions$.pipe(ofType(setCirrusDisconnected), first())), map(() => initSignalling()));
3164
3317
  });
3165
3318
  this.showUnrealError$ = createEffect(() => {
3166
3319
  return this.actions$.pipe(ofType(showUnrealErrorMessage), map(({ code }) => getRtcErrorMessage(code)), distinctUntilChanged(), filter(Truthy), switchMap$1((content) => this.dialog.open(UnrealErrorModalComponent, {
@@ -3198,27 +3351,51 @@ class UnrealEffects {
3198
3351
  (videoStats.aggregatedStats.framesDecoded || 0) > 15), first(), map(() => setLoopBackCommandIsCompleted()))));
3199
3352
  });
3200
3353
  this.setViewportReadyBySetLoopBackCommandIsCompleted$ = createEffect(() => {
3201
- return this.actions$.pipe(ofType(setLoopBackCommandIsCompleted), tap(() => TelemetryStop('SetViewportReady', { ready: true })), map(() => setViewportReady({ value: true })));
3354
+ return this.actions$.pipe(ofType(setLoopBackCommandIsCompleted), tap(() => TelemetryStop('SetViewportReady', { ready: true })), map(() => setViewportReady()));
3355
+ });
3356
+ this.startStream$ = createEffect(() => {
3357
+ return this.actions$.pipe(ofType(startStream), tapLog('Start Stream Pressed'), map(() => initSignalling()));
3358
+ });
3359
+ this.setMatchUrls$ = createEffect(() => {
3360
+ return this.actions$.pipe(ofType(setMatchUrls), tapLog('setMatchUrls'), map(() => initSignalling()));
3202
3361
  });
3203
3362
  this.listenUnrealCallbackByInitSignalling$ = createEffect(() => {
3204
3363
  return this.actions$.pipe(ofType(initSignalling), switchMap$1(() => fromSignal(UnrealInternalSignalEvents.UnrealCallback).pipe(map(({ json }) => json?.commandCallback
3205
3364
  ?.correlationId), filter(Truthy), map((id) => commandCompleted({ id })))));
3206
3365
  });
3207
- this.setConfigByInitSignalling$ = createEffect(() => {
3208
- return this.actions$.pipe(ofType(initSignalling), withLatestFrom(this.store.select(unrealFeature.selectMatchUrls)), switchMap$1(() => this.store
3209
- .select(unrealFeature.selectMatchUrls)
3210
- .pipe(filter((item) => item?.length > 0))), map((matchMakerUrls) => {
3211
- if (isEmpty(matchMakerUrls)) {
3212
- throw Error('Signalling URL(s) is empty');
3366
+ this.connectToSignaling$ = createEffect(() => {
3367
+ return this.actions$.pipe(ofType(initSignalling), withLatestFrom(this.store.select(unrealFeature.selectMatchUrls), this.store.select(selectIsAutostart), this.store.select(unrealFeature.selectCirrusConnected)), filter(([, , autoStart, cirrusConnected]) => {
3368
+ if (cirrusConnected) {
3369
+ Logger.warn(`SIGNALING REQUEST can't be called when cirrus connection is already established.`);
3213
3370
  }
3214
- return setMatchMakerUrls({ matchMakerUrls });
3215
- }));
3371
+ return autoStart && !cirrusConnected;
3372
+ }), map(([, matchMakerUrls]) => [...matchMakerUrls].filter(Truthy)), filter((urls) => urls.length > 0),
3373
+ // Ensure a single in-flight request per attempt.
3374
+ exhaustMap((urls) => this.signallingService.connectToSignaling(urls)));
3375
+ }, { dispatch: false });
3376
+ /**
3377
+ * Effect: `forceViewportNotReady$`
3378
+ *
3379
+ * Ensures the viewport is explicitly marked as *not ready* to prevent
3380
+ * a temporary black screen flash when disconnecting.
3381
+ *
3382
+ * ### Why
3383
+ * - The video stream is disconnected immediately.
3384
+ * - The DataChannel closes slightly later.
3385
+ * - Closing the DataChannel resets the Unreal scene,
3386
+ * which also sets `viewPortReady` to `false`.
3387
+ *
3388
+ * Without this effect, the order of these events may cause
3389
+ * a visible flicker (video flashing to black).
3390
+ */
3391
+ this.forceViewportNotReady$ = createEffect(() => {
3392
+ return this.actions$.pipe(ofType(destroyRemoteConnections), map(() => setViewportNotReady()));
3216
3393
  });
3217
3394
  }
3218
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.1", ngImport: i0, type: UnrealEffects, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
3219
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.2.1", ngImport: i0, type: UnrealEffects }); }
3395
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.4", ngImport: i0, type: UnrealEffects, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
3396
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.2.4", ngImport: i0, type: UnrealEffects }); }
3220
3397
  }
3221
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.1", ngImport: i0, type: UnrealEffects, decorators: [{
3398
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.4", ngImport: i0, type: UnrealEffects, decorators: [{
3222
3399
  type: Injectable
3223
3400
  }] });
3224
3401
 
@@ -3231,11 +3408,11 @@ const selectIsFreezeFrameLoading = createSelector(unrealFeature.selectFreezeFram
3231
3408
  const selectFreezeFrameCombinedDataUrl = createSelector(selectFreezeFrameDataUrlFromVideo, selectFreezeFrameDataUrl, (dataUrlFromVideo, remoteDataUrl) => dataUrlFromVideo || remoteDataUrl || null);
3232
3409
  const selectStreamConfig = createSelector(unrealFeature.selectStreamConfig, (config) => config);
3233
3410
  const selectWarnTimeout = createSelector(selectStreamConfig, (config) => config?.warnTimeout || DEFAULT_AFK_TIMEOUT);
3234
- const selectMatchMakerUrls = createSelector(unrealFeature.selectMatchMakerUrls, (urls) => (urls || []).filter(Truthy));
3411
+ const selectIsExistMatchUrls = createSelector(unrealFeature.selectMatchUrls, (urls) => urls?.length > 0);
3235
3412
  const selectIsAutostart = createSelector(selectStreamConfig, (config) => config?.autoStart);
3236
- const selectWsUrl = createSelector(unrealFeature.selectAwsInstance, (instance) => instance?.wsUrl);
3237
- const selectShowReconnectPopup = createSelector(unrealFeature.selectWasInitialized, unrealFeature.selectCirrusConnected, unrealFeature.selectEstablishingConnection, unrealFeature.selectImageIntroSrc, unrealFeature.selectVideoIntroSrc, (wasInitialized, connected, establishing, imageSrc, videoSrc) => wasInitialized && !connected && !establishing && !imageSrc && !videoSrc);
3238
- const selectShowLoader = createSelector(unrealFeature.selectWasInitialized, unrealFeature.selectViewportReady, selectStreamConfig, selectShowReconnectPopup, (wasInitialized, viewportReady, config, showPopup) => ((config.autoStart && !wasInitialized) || !showPopup) && !viewportReady);
3413
+ const showPopupWithoutAutoStart = createSelector(selectStreamConfig, unrealFeature.selectWasInitialized, (config, wasInitialized) => !config.autoStart && !wasInitialized);
3414
+ const selectShowReconnectPopup = createSelector(unrealFeature.selectCirrusConnected, unrealFeature.selectEstablishingConnection, (connected, establishing) => !connected && !establishing);
3415
+ const selectShowLoader = createSelector(selectShowReconnectPopup, unrealFeature.selectViewportReady, (showPopup, viewPortReady) => !showPopup && !viewPortReady);
3239
3416
  const selectIsVideoPlayingAndDataChannelConnected = createSelector(unrealFeature.selectIsVideoPlaying, unrealFeature.selectDataChannelConnected, (isVideoPlaying, isDataChannelConnected) => isVideoPlaying && isDataChannelConnected);
3240
3417
  const selectSignalingParameters = createSelector(unrealFeature.selectSsData, unrealFeature.selectAwsInstance, unrealFeature.selectSsInfo, (data, instance, ssInfo) => {
3241
3418
  const info = [];
@@ -3279,6 +3456,8 @@ const selectTotalProgress = createSelector(unrealFeature.selectStatusPercentSign
3279
3456
  const percentRest = lerp(0, 1 - splitPoint, commandProgress);
3280
3457
  return clampf(0, 1, percentSignaling + percentRest);
3281
3458
  });
3459
+ const selectClientAndViewIds = createSelector(unrealFeature.selectStreamClientCompanyId, unrealFeature.selectStreamViewId, (clientId, viewId) => ({ clientId, viewId }));
3460
+ const isLoaderScreenVisible = createSelector(unrealFeature.selectViewportReady, unrealFeature.selectDataChannelConnected, unrealFeature.selectCirrusConnected, (viewReady, cirrusConnected, dataChannelConnected) => !viewReady || !cirrusConnected || !dataChannelConnected);
3282
3461
 
3283
3462
  function InstanceReservedHandler(msg) {
3284
3463
  this.store.dispatch(setSignalingName({
@@ -3302,26 +3481,30 @@ function SSInfoHandler(msg) {
3302
3481
  return null;
3303
3482
  }
3304
3483
 
3484
+ const dropCodes = [
3485
+ WSCloseCode_CIRRUS_PLAYER_DISCONNECTED,
3486
+ WSCloseCode_CIRRUS_ABNORMAL_CLOSURE,
3487
+ WSCloseCode_CIRRUS_STREAMER_KIKED_PLAYER,
3488
+ WSCloseCode_CIRRUS_MAX_PLAYERS_ERROR,
3489
+ ];
3305
3490
  function OnCloseHandler(e) {
3306
- this.stopRetryTimer();
3307
- Logger.warn(`WS closed: ${JSON.stringify(e.code)} - ${e.reason}`);
3491
+ const message = `WebSocket closed: ${JSON.stringify(e.code)} - ${e.reason}`;
3492
+ Logger.warn(message);
3308
3493
  this.store.dispatch(setCirrusDisconnected());
3494
+ if (dropCodes.includes(e.code)) {
3495
+ this.store.dispatch(dropConnection());
3496
+ }
3309
3497
  }
3310
3498
 
3311
3499
  function OnErrorHandler(e) {
3312
- clearTimeout(this.wsTimeoutHandler);
3313
3500
  Logger.warn(`WS error: ${JSON.stringify(e)}`);
3314
- this.store.dispatch(setErrorMessage({
3315
- errorType: 'WebSocketError',
3501
+ this.store.dispatch(disconnectStream({
3502
+ reason: DisconnectReason.WebSocketError,
3316
3503
  message: 'WebSocket Error',
3317
3504
  }));
3318
- this.store.dispatch(destroyRemoteConnections({ disconnectReason: DisconnectReason.wsOnError }));
3319
- this.initEstablishingConnection();
3320
- this.watchTimeoutOrErrorAndReconnectLater();
3321
3505
  }
3322
3506
 
3323
3507
  function OnMessageHandler(e) {
3324
- clearTimeout(this.wsTimeoutHandler);
3325
3508
  const handleData = (data) => {
3326
3509
  //Logger.colored(...COLOR_CODES.FROM_SIGNALING, data);
3327
3510
  const msg = JSON.parse(data);
@@ -3336,7 +3519,6 @@ function OnMessageHandler(e) {
3336
3519
  }
3337
3520
 
3338
3521
  function OnOpenHandler() {
3339
- this.stopRetryTimer();
3340
3522
  this.store.dispatch(setCirrusConnected());
3341
3523
  this.send({
3342
3524
  type: OrchestrationMessageTypes.requestReservation,
@@ -3351,8 +3533,12 @@ function OnOpenHandler() {
3351
3533
  });
3352
3534
  }
3353
3535
 
3354
- const clampAndKeepMaxPercents = () => {
3355
- return (source) => source.pipe(scan((maxProgress, currentProgress) => currentProgress > maxProgress ? currentProgress : maxProgress, 0));
3536
+ /**
3537
+ * Keeps the max of numbers seen so far; resets to 0 whenever `reset$` emits.
3538
+ * Emits `0` immediately on reset.
3539
+ */
3540
+ const clampAndKeepMaxPercents = (reset$) => {
3541
+ return (source$) => merge(source$.pipe(map((value) => ({ type: 'value', value }))), reset$.pipe(map(() => ({ type: 'reset' })))).pipe(scan((max, evt) => (evt.type === 'reset' ? 0 : Math.max(max, evt.value)), 0));
3356
3542
  };
3357
3543
 
3358
3544
  function observeCommandResponse(data, sender, timeOut = 60000, dispatchOnTimeout = true) {
@@ -3367,7 +3553,7 @@ function observeCommandResponse(data, sender, timeOut = 60000, dispatchOnTimeout
3367
3553
  : { json: { commandCallback: json } };
3368
3554
  }), filter(({ json }) => {
3369
3555
  return json.commandCallback.correlationId === correlationId;
3370
- }), timeout(timeOut), catchError(() => dispatchOnTimeout
3556
+ }), timeout$1(timeOut), catchError(() => dispatchOnTimeout
3371
3557
  ? of({ json: { commandCallback: { correlationId: 'timeout' } } })
3372
3558
  : of(null)), first(), tapLog('Command Response Observer'), filter(Truthy));
3373
3559
  setTimeout(() => sender(out), 0);
@@ -3872,10 +4058,10 @@ class ClickableOverlayComponent {
3872
4058
  constructor() {
3873
4059
  this.state = toSignal(fromSignal(UnrealInternalSignalEvents.ClickableOverlay).pipe(map$1((data) => (typeof data === 'object' ? data : null))));
3874
4060
  }
3875
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.1", ngImport: i0, type: ClickableOverlayComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
3876
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.2.1", type: ClickableOverlayComponent, isStandalone: true, selector: "app-clickable-overlay", ngImport: i0, template: "@if (state()) {\n <div\n (click)=\"state()?.onOverlayClick()\"\n [ngClass]=\"state()?.className\"\n id=\"videoPlayOverlay\"\n >\n @if (state()?.isActivityDetected) {\n <div class=\"resume-box\">\n <div aria-hidden=\"true\" class=\"resume-box__pic\" role=\"presentation\">\n <div [innerHTML]=\"state()?.message\" class=\"text-number\"></div>\n </div>\n <div class=\"resume-box__text\">\n <h3 class=\"resume-box__heading\">Session will time out soon</h3>\n <p>\n No activity detected. Press 'Continue' if you wish to keep your\n session active\n </p>\n </div>\n <src-button\n [colorScheme]=\"'primary'\"\n [isFullWidth]=\"true\"\n [size]=\"'large'\"\n [data-testid]=\"'continue-session'\"\n >\n Continue\n </src-button>\n </div>\n }\n </div>\n}\n", styles: ["#videoPlayOverlay{position:absolute;z-index:30;top:0;width:100%;height:100%;font-size:1.8em;font-family:var(--src-font-family-body);background-color:#646464b3}.clickableState{display:flex;justify-content:center;align-items:center;cursor:pointer}.textDisplayState{display:flex}.hiddenState{display:none}.resume-box{width:340px;padding:32px 20px 20px;flex-direction:column;align-items:center;border-radius:var(--src-border-rounded-parent, 8px);background:var(--src-color-bg-default, #fff);box-shadow:0 26px 80px #0003,0 0 1px #0003}.resume-box .resume-box__pic{width:72px;height:72px;margin:0 auto 22px;border-radius:48px;background:#ecf0f2;padding:12px;display:flex;align-items:center;justify-content:center}.resume-box .resume-box__pic .text-number{color:var(--src-colors-text-default, #1f2937);text-align:center;font-family:var(--src-font-family-body);font-size:30px;font-style:normal;font-weight:400;line-height:24px}.resume-box__text{margin-bottom:18px}.resume-box__text p{text-align:center;font-family:var(--src-font-family-body);font-size:var(--src-font-size-sm, 14px);font-style:normal;font-weight:400;line-height:24px;color:var(--src-color-text-default-subdued, #6b7280)}.resume-box__text .resume-box__heading{color:var(--src-color-bg-default, #1f2937);text-align:center;font-family:var(--src-font-family-body);font-size:18px;font-style:normal;font-weight:500;line-height:26px;margin-bottom:8px}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: SourceButtonComponent, selector: "src-button", inputs: ["type", "appearance", "colorScheme", "size", "state", "customClass", "hasDisclosure", "isFullWidth", "isPressed", "isDisabled", "isLoading", "iconButton", "srcButtonConfig", "formID", "data-testid"], outputs: ["onClick", "onSubmit"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
4061
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.4", ngImport: i0, type: ClickableOverlayComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
4062
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.2.4", type: ClickableOverlayComponent, isStandalone: true, selector: "app-clickable-overlay", ngImport: i0, template: "@if (state()) {\n <div\n (click)=\"state()?.onOverlayClick()\"\n [ngClass]=\"state()?.className\"\n id=\"videoPlayOverlay\"\n >\n @if (state()?.isActivityDetected) {\n <div class=\"resume-box\">\n <div aria-hidden=\"true\" class=\"resume-box__pic\" role=\"presentation\">\n <div [innerHTML]=\"state()?.message\" class=\"text-number\"></div>\n </div>\n <div class=\"resume-box__text\">\n <h3 class=\"resume-box__heading\">Session will time out soon</h3>\n <p>\n No activity detected. Press 'Continue' if you wish to keep your\n session active\n </p>\n </div>\n <src-button\n [colorScheme]=\"'primary'\"\n [isFullWidth]=\"true\"\n [size]=\"'large'\"\n [data-testid]=\"'continue-session'\"\n >\n Continue\n </src-button>\n </div>\n }\n </div>\n}\n", styles: ["#videoPlayOverlay{position:absolute;z-index:30;top:0;width:100%;height:100%;font-size:1.8em;font-family:var(--src-font-family-body);background-color:#646464b3}.clickableState{display:flex;justify-content:center;align-items:center;cursor:pointer}.textDisplayState{display:flex}.hiddenState{display:none}.resume-box{width:340px;padding:32px 20px 20px;flex-direction:column;align-items:center;border-radius:var(--src-border-rounded-parent, 8px);background:var(--src-color-bg-default, #fff);box-shadow:0 26px 80px #0003,0 0 1px #0003}.resume-box .resume-box__pic{width:72px;height:72px;margin:0 auto 22px;border-radius:48px;background:#ecf0f2;padding:12px;display:flex;align-items:center;justify-content:center}.resume-box .resume-box__pic .text-number{color:var(--src-colors-text-default, #1f2937);text-align:center;font-family:var(--src-font-family-body);font-size:30px;font-style:normal;font-weight:400;line-height:24px}.resume-box__text{margin-bottom:18px}.resume-box__text p{text-align:center;font-family:var(--src-font-family-body);font-size:var(--src-font-size-sm, 14px);font-style:normal;font-weight:400;line-height:24px;color:var(--src-color-text-default-subdued, #6b7280)}.resume-box__text .resume-box__heading{color:var(--src-color-bg-default, #1f2937);text-align:center;font-family:var(--src-font-family-body);font-size:18px;font-style:normal;font-weight:500;line-height:26px;margin-bottom:8px}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: SourceButtonComponent, selector: "src-button", inputs: ["type", "appearance", "colorScheme", "size", "state", "customClass", "hasDisclosure", "isFullWidth", "isPressed", "isDisabled", "isLoading", "iconButton", "srcButtonConfig", "formID", "data-testid"], outputs: ["onClick", "onSubmit"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
3877
4063
  }
3878
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.1", ngImport: i0, type: ClickableOverlayComponent, decorators: [{
4064
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.4", ngImport: i0, type: ClickableOverlayComponent, decorators: [{
3879
4065
  type: Component,
3880
4066
  args: [{ selector: 'app-clickable-overlay', changeDetection: ChangeDetectionStrategy.OnPush, imports: [NgClass, SourceButtonComponent], template: "@if (state()) {\n <div\n (click)=\"state()?.onOverlayClick()\"\n [ngClass]=\"state()?.className\"\n id=\"videoPlayOverlay\"\n >\n @if (state()?.isActivityDetected) {\n <div class=\"resume-box\">\n <div aria-hidden=\"true\" class=\"resume-box__pic\" role=\"presentation\">\n <div [innerHTML]=\"state()?.message\" class=\"text-number\"></div>\n </div>\n <div class=\"resume-box__text\">\n <h3 class=\"resume-box__heading\">Session will time out soon</h3>\n <p>\n No activity detected. Press 'Continue' if you wish to keep your\n session active\n </p>\n </div>\n <src-button\n [colorScheme]=\"'primary'\"\n [isFullWidth]=\"true\"\n [size]=\"'large'\"\n [data-testid]=\"'continue-session'\"\n >\n Continue\n </src-button>\n </div>\n }\n </div>\n}\n", styles: ["#videoPlayOverlay{position:absolute;z-index:30;top:0;width:100%;height:100%;font-size:1.8em;font-family:var(--src-font-family-body);background-color:#646464b3}.clickableState{display:flex;justify-content:center;align-items:center;cursor:pointer}.textDisplayState{display:flex}.hiddenState{display:none}.resume-box{width:340px;padding:32px 20px 20px;flex-direction:column;align-items:center;border-radius:var(--src-border-rounded-parent, 8px);background:var(--src-color-bg-default, #fff);box-shadow:0 26px 80px #0003,0 0 1px #0003}.resume-box .resume-box__pic{width:72px;height:72px;margin:0 auto 22px;border-radius:48px;background:#ecf0f2;padding:12px;display:flex;align-items:center;justify-content:center}.resume-box .resume-box__pic .text-number{color:var(--src-colors-text-default, #1f2937);text-align:center;font-family:var(--src-font-family-body);font-size:30px;font-style:normal;font-weight:400;line-height:24px}.resume-box__text{margin-bottom:18px}.resume-box__text p{text-align:center;font-family:var(--src-font-family-body);font-size:var(--src-font-size-sm, 14px);font-style:normal;font-weight:400;line-height:24px;color:var(--src-color-text-default-subdued, #6b7280)}.resume-box__text .resume-box__heading{color:var(--src-color-bg-default, #1f2937);text-align:center;font-family:var(--src-font-family-body);font-size:18px;font-style:normal;font-weight:500;line-height:26px;margin-bottom:8px}\n"] }]
3881
4067
  }] });
@@ -3886,10 +4072,10 @@ class FreezeFrameComponent {
3886
4072
  this.freezeFrameProgressMessageFromVideo = toSignal(this.store.select(selectFreezeFrameProgressMessageFromVideo));
3887
4073
  this.combinedFreeze = toSignal(this.store.select(selectFreezeFrameCombinedDataUrl));
3888
4074
  }
3889
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.1", ngImport: i0, type: FreezeFrameComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
3890
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.2.1", type: FreezeFrameComponent, isStandalone: true, selector: "app-freeze-frame", ngImport: i0, template: "<div class=\"freeze-images\">\n @if (combinedFreeze()) {\n <img\n [src]=\"combinedFreeze()\"\n class=\"videoStillImage\"\n alt=\"freezeFrameImage\"\n />\n }\n\n @if (freezeFrameProgressMessageFromVideo()) {\n <div class=\"progress-status\">\n {{ freezeFrameProgressMessageFromVideo() }}\n </div>\n }\n</div>\n", styles: [".freeze-images{pointer-events:none;position:absolute;left:0;top:0;width:100%;height:100%;z-index:1}.freeze-images .freezeFrameOverlay{top:0;left:0;width:100%;height:100%;position:absolute;object-fit:cover;object-position:center}.freeze-images .videoStillImage{position:absolute;z-index:1;top:0;left:0;width:100%;height:100%;object-fit:cover}.freeze-images .progress-status{position:absolute;top:50%;left:50%;z-index:1;display:flex;flex-direction:column;justify-content:center;align-items:center;width:auto;height:auto;margin:0;padding:10px;background-color:#ffffffb3;border:1px solid grey;transform:translate(-50%,-50%)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
4075
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.4", ngImport: i0, type: FreezeFrameComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
4076
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.2.4", type: FreezeFrameComponent, isStandalone: true, selector: "app-freeze-frame", ngImport: i0, template: "<div class=\"freeze-images\">\n @if (combinedFreeze()) {\n <img\n [src]=\"combinedFreeze()\"\n class=\"videoStillImage\"\n alt=\"freezeFrameImage\"\n />\n }\n\n @if (freezeFrameProgressMessageFromVideo()) {\n <div class=\"progress-status\">\n {{ freezeFrameProgressMessageFromVideo() }}\n </div>\n }\n</div>\n", styles: [".freeze-images{pointer-events:none;position:absolute;left:0;top:0;width:100%;height:100%;z-index:1}.freeze-images .freezeFrameOverlay{top:0;left:0;width:100%;height:100%;position:absolute;object-fit:cover;object-position:center}.freeze-images .videoStillImage{position:absolute;z-index:1;top:0;left:0;width:100%;height:100%;object-fit:cover}.freeze-images .progress-status{position:absolute;top:50%;left:50%;z-index:1;display:flex;flex-direction:column;justify-content:center;align-items:center;width:auto;height:auto;margin:0;padding:10px;background-color:#ffffffb3;border:1px solid grey;transform:translate(-50%,-50%)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
3891
4077
  }
3892
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.1", ngImport: i0, type: FreezeFrameComponent, decorators: [{
4078
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.4", ngImport: i0, type: FreezeFrameComponent, decorators: [{
3893
4079
  type: Component,
3894
4080
  args: [{ selector: 'app-freeze-frame', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"freeze-images\">\n @if (combinedFreeze()) {\n <img\n [src]=\"combinedFreeze()\"\n class=\"videoStillImage\"\n alt=\"freezeFrameImage\"\n />\n }\n\n @if (freezeFrameProgressMessageFromVideo()) {\n <div class=\"progress-status\">\n {{ freezeFrameProgressMessageFromVideo() }}\n </div>\n }\n</div>\n", styles: [".freeze-images{pointer-events:none;position:absolute;left:0;top:0;width:100%;height:100%;z-index:1}.freeze-images .freezeFrameOverlay{top:0;left:0;width:100%;height:100%;position:absolute;object-fit:cover;object-position:center}.freeze-images .videoStillImage{position:absolute;z-index:1;top:0;left:0;width:100%;height:100%;object-fit:cover}.freeze-images .progress-status{position:absolute;top:50%;left:50%;z-index:1;display:flex;flex-direction:column;justify-content:center;align-items:center;width:auto;height:auto;margin:0;padding:10px;background-color:#ffffffb3;border:1px solid grey;transform:translate(-50%,-50%)}\n"] }]
3895
4081
  }] });
@@ -3917,10 +4103,10 @@ class SafePipe {
3917
4103
  throw new Error(`Invalid safe type specified: ${type}`);
3918
4104
  }
3919
4105
  }
3920
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.1", ngImport: i0, type: SafePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
3921
- static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "20.2.1", ngImport: i0, type: SafePipe, isStandalone: true, name: "safe" }); }
4106
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.4", ngImport: i0, type: SafePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
4107
+ static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "20.2.4", ngImport: i0, type: SafePipe, isStandalone: true, name: "safe" }); }
3922
4108
  }
3923
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.1", ngImport: i0, type: SafePipe, decorators: [{
4109
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.4", ngImport: i0, type: SafePipe, decorators: [{
3924
4110
  type: Pipe,
3925
4111
  args: [{
3926
4112
  name: 'safe',
@@ -3934,10 +4120,10 @@ class LowBandwidthModalComponent {
3934
4120
  close(value) {
3935
4121
  this.dialogRef.close(value || false);
3936
4122
  }
3937
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.1", ngImport: i0, type: LowBandwidthModalComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
3938
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.2.1", type: LowBandwidthModalComponent, isStandalone: true, selector: "app-low-bandwidth-modal", ngImport: i0, template: "<div [attr.data-testid]=\"'low-bandwidth'\" class=\"src-modal src-modal--lbm\">\n <header class=\"src-modal__header\">\n <h6 [attr.data-testid]=\"'title'\" class=\"src-modal__title\">\n Unstable Connection\n </h6>\n </header>\n <section class=\"src-modal__body\">\n <div\n [innerHtml]=\"\n 'Fluid Interactivity Modes were disabled due to an unstable connection. Showcase Gallery Mode is enabled. To regain full functionality, switch to Interactive Mode.'\n | safe: 'html'\n \"\n class=\"src-modal__scroll-box\"\n ></div>\n </section>\n <footer class=\"src-modal__footer\">\n <div class=\"src-modal__buttons\">\n <src-button\n (onClick)=\"close(true)\"\n [data-testid]=\"'switch-to-interactive-mode'\"\n >\n Switch\n </src-button>\n\n <src-button\n (onClick)=\"close()\"\n [data-testid]=\"'close-lbm-modal'\"\n colorScheme=\"primary\"\n >\n Ok\n </src-button>\n </div>\n </footer>\n</div>\n", styles: [".src-modal--lbm{width:360px}.src-modal--lbm .src-modal__body{font-size:14px;line-height:24px}.src-modal--lbm .src-modal__buttons{display:flex;gap:8px}\n"], dependencies: [{ kind: "component", type: SourceButtonComponent, selector: "src-button", inputs: ["type", "appearance", "colorScheme", "size", "state", "customClass", "hasDisclosure", "isFullWidth", "isPressed", "isDisabled", "isLoading", "iconButton", "srcButtonConfig", "formID", "data-testid"], outputs: ["onClick", "onSubmit"] }, { kind: "pipe", type: SafePipe, name: "safe" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
4123
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.4", ngImport: i0, type: LowBandwidthModalComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
4124
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.2.4", type: LowBandwidthModalComponent, isStandalone: true, selector: "app-low-bandwidth-modal", ngImport: i0, template: "<div [attr.data-testid]=\"'low-bandwidth'\" class=\"src-modal src-modal--lbm\">\n <header class=\"src-modal__header\">\n <h6 [attr.data-testid]=\"'title'\" class=\"src-modal__title\">\n Unstable Connection\n </h6>\n </header>\n <section class=\"src-modal__body\">\n <div\n [innerHtml]=\"\n 'Fluid Interactivity Modes were disabled due to an unstable connection. Showcase Gallery Mode is enabled. To regain full functionality, switch to Interactive Mode.'\n | safe: 'html'\n \"\n class=\"src-modal__scroll-box\"\n ></div>\n </section>\n <footer class=\"src-modal__footer\">\n <div class=\"src-modal__buttons\">\n <src-button\n (onClick)=\"close(true)\"\n [data-testid]=\"'switch-to-interactive-mode'\"\n >\n Switch\n </src-button>\n\n <src-button\n (onClick)=\"close()\"\n [data-testid]=\"'close-lbm-modal'\"\n colorScheme=\"primary\"\n >\n Ok\n </src-button>\n </div>\n </footer>\n</div>\n", styles: [".src-modal--lbm{width:360px}.src-modal--lbm .src-modal__body{font-size:14px;line-height:24px}.src-modal--lbm .src-modal__buttons{display:flex;gap:8px}\n"], dependencies: [{ kind: "component", type: SourceButtonComponent, selector: "src-button", inputs: ["type", "appearance", "colorScheme", "size", "state", "customClass", "hasDisclosure", "isFullWidth", "isPressed", "isDisabled", "isLoading", "iconButton", "srcButtonConfig", "formID", "data-testid"], outputs: ["onClick", "onSubmit"] }, { kind: "pipe", type: SafePipe, name: "safe" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
3939
4125
  }
3940
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.1", ngImport: i0, type: LowBandwidthModalComponent, decorators: [{
4126
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.4", ngImport: i0, type: LowBandwidthModalComponent, decorators: [{
3941
4127
  type: Component,
3942
4128
  args: [{ selector: 'app-low-bandwidth-modal', changeDetection: ChangeDetectionStrategy.OnPush, imports: [SourceIconButtonComponent, SafePipe, SourceButtonComponent], template: "<div [attr.data-testid]=\"'low-bandwidth'\" class=\"src-modal src-modal--lbm\">\n <header class=\"src-modal__header\">\n <h6 [attr.data-testid]=\"'title'\" class=\"src-modal__title\">\n Unstable Connection\n </h6>\n </header>\n <section class=\"src-modal__body\">\n <div\n [innerHtml]=\"\n 'Fluid Interactivity Modes were disabled due to an unstable connection. Showcase Gallery Mode is enabled. To regain full functionality, switch to Interactive Mode.'\n | safe: 'html'\n \"\n class=\"src-modal__scroll-box\"\n ></div>\n </section>\n <footer class=\"src-modal__footer\">\n <div class=\"src-modal__buttons\">\n <src-button\n (onClick)=\"close(true)\"\n [data-testid]=\"'switch-to-interactive-mode'\"\n >\n Switch\n </src-button>\n\n <src-button\n (onClick)=\"close()\"\n [data-testid]=\"'close-lbm-modal'\"\n colorScheme=\"primary\"\n >\n Ok\n </src-button>\n </div>\n </footer>\n</div>\n", styles: [".src-modal--lbm{width:360px}.src-modal--lbm .src-modal__body{font-size:14px;line-height:24px}.src-modal--lbm .src-modal__buttons{display:flex;gap:8px}\n"] }]
3943
4129
  }] });
@@ -3947,10 +4133,11 @@ class AfkRestartScreenLockerComponent {
3947
4133
  this.store = inject(Store);
3948
4134
  this.videoService = inject(VideoService);
3949
4135
  this.destroyRef = inject(DestroyRef);
3950
- this.showReconnectPopup = toSignal(this.store.select(selectShowReconnectPopup));
3951
- this.isViewportReady = toSignal(this.store.select(unrealFeature.selectViewportReady));
3952
- this.imageLoadingSrc = toSignal(this.store.select(unrealFeature.selectImageLoadingSrc));
3953
- this.streamConfig = toSignal(this.store.select(selectStreamConfig));
4136
+ this.showReconnectPopup = this.store.selectSignal(selectShowReconnectPopup);
4137
+ this.isLoaderScreenVisible = this.store.selectSignal(isLoaderScreenVisible);
4138
+ this.imageLoadingSrc = this.store.selectSignal(unrealFeature.selectImageLoadingSrc);
4139
+ this.streamConfig = this.store.selectSignal(selectStreamConfig);
4140
+ this.isExistMatchUrls = this.store.selectSignal(selectIsExistMatchUrls);
3954
4141
  this.isSecondStart = signal(!!(this.streamConfig()?.autoStart && location.href.match(/^https/gi)), ...(ngDevMode ? [{ debugName: "isSecondStart" }] : []));
3955
4142
  this.playCallBack = null;
3956
4143
  }
@@ -3972,18 +4159,18 @@ class AfkRestartScreenLockerComponent {
3972
4159
  });
3973
4160
  }
3974
4161
  connect() {
3975
- this.store.dispatch(initSignalling());
4162
+ this.store.dispatch(startStream({ config: { autoStart: true } }));
3976
4163
  }
3977
4164
  onDisconnect() {
3978
4165
  this.isSecondStart.set(true);
3979
4166
  this.playCallBack = null;
3980
4167
  }
3981
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.1", ngImport: i0, type: AfkRestartScreenLockerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
3982
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.2.1", type: AfkRestartScreenLockerComponent, isStandalone: true, selector: "app-afk-restart-screen-locker", ngImport: i0, template: "@if (!isViewportReady()) {\n <div class=\"preload\">\n <div class=\"back\">\n @if (imageLoadingSrc()) {\n <img\n [ngSrc]=\"imageLoadingSrc()!\"\n fill\n loading=\"lazy\"\n alt=\"image loading src\"\n />\n }\n </div>\n\n @if (showReconnectPopup()) {\n <div class=\"stream-message-wrapper\">\n <div class=\"resume-box\">\n @if (isSecondStart()) {\n <div class=\"resume-box__text\">\n Your stream has been paused due to inactivity\n </div>\n }\n\n <src-button\n (onClick)=\"connect()\"\n [isFullWidth]=\"true\"\n [size]=\"'large'\"\n [colorScheme]=\"'primary'\"\n [data-testid]=\"'connect-button'\"\n class=\"connect-button\"\n >\n {{ isSecondStart() ? 'Resume' : 'Start' }}\n </src-button>\n </div>\n </div>\n }\n </div>\n}\n", styles: [".preload{position:absolute;top:0;left:0;width:100%;height:100%;text-align:center}.preload .back{position:absolute;top:0;left:0;display:flex;justify-content:center;align-items:center;width:100%;height:100%}.preload .back img{width:100%;height:100%;object-fit:cover}.preload .stream-message-wrapper{position:absolute;top:0;left:0;width:100%;height:100%;background-color:transparent;z-index:3;display:flex;align-items:center;justify-content:center}.resume-box{padding:16px;position:absolute;bottom:0;left:50%;gap:12px;display:flex;transform:translate(-50%,-50%);flex-direction:column;align-items:center;border-radius:var(--src-border-rounded-parent, 8px);background:var(--src-color-bg-default, #fff);box-shadow:0 26px 80px #0003,0 0 1px #0003}.resume-box .connect-button{width:100%}.resume-box__text{color:var(--src-color-gray-500, #6b7280);text-align:center;font-family:var(--src-font-family-body);font-size:14px;font-style:normal;font-weight:400;line-height:24px}.preload .message-loader{position:absolute;bottom:20px;left:50%;display:block;margin:auto;transform:translate(-50%)}.preload .message-loader>p{margin:0;line-height:1;transition:all ease .35s}.preload .message-loader>p span{font-size:10px;transition:all ease .35s}@media (min-width: 1900px){.preload .message-loader{bottom:40px}}\n"], dependencies: [{ kind: "directive", type: NgOptimizedImage, selector: "img[ngSrc]", inputs: ["ngSrc", "ngSrcset", "sizes", "width", "height", "decoding", "loading", "priority", "loaderParams", "disableOptimizedSrcset", "fill", "placeholder", "placeholderConfig", "src", "srcset"] }, { kind: "component", type: SourceButtonComponent, selector: "src-button", inputs: ["type", "appearance", "colorScheme", "size", "state", "customClass", "hasDisclosure", "isFullWidth", "isPressed", "isDisabled", "isLoading", "iconButton", "srcButtonConfig", "formID", "data-testid"], outputs: ["onClick", "onSubmit"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
4168
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.4", ngImport: i0, type: AfkRestartScreenLockerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
4169
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.2.4", type: AfkRestartScreenLockerComponent, isStandalone: true, selector: "app-afk-restart-screen-locker", ngImport: i0, template: "@if (isLoaderScreenVisible()) {\n <div class=\"preload\">\n <div class=\"back\">\n @if (imageLoadingSrc()) {\n <img\n [ngSrc]=\"imageLoadingSrc()!\"\n fill\n loading=\"lazy\"\n alt=\"image loading src\"\n />\n }\n </div>\n\n @if (showReconnectPopup() && isExistMatchUrls()) {\n <div class=\"stream-message-wrapper\">\n <div class=\"resume-box\">\n @if (isSecondStart()) {\n <div class=\"resume-box__text\">\n Your stream has been paused due to inactivity\n </div>\n }\n\n <src-button\n (onClick)=\"connect()\"\n [isFullWidth]=\"true\"\n [size]=\"'large'\"\n [colorScheme]=\"'primary'\"\n [data-testid]=\"'connect-button'\"\n class=\"connect-button\"\n >\n {{ isSecondStart() ? 'Resume' : 'Start' }}\n </src-button>\n </div>\n </div>\n }\n </div>\n}\n", styles: [".preload{position:absolute;top:0;left:0;width:100%;height:100%;text-align:center}.preload .back{position:absolute;top:0;left:0;display:flex;justify-content:center;align-items:center;width:100%;height:100%;background-color:#fff}.preload .back img{width:100%;height:100%;object-fit:cover}.preload .stream-message-wrapper{position:absolute;top:0;left:0;width:100%;height:100%;background-color:transparent;z-index:3;display:flex;align-items:center;justify-content:center}.resume-box{padding:16px;position:absolute;bottom:0;left:50%;gap:12px;display:flex;transform:translate(-50%,-50%);flex-direction:column;align-items:center;border-radius:var(--src-border-rounded-parent, 8px);background:var(--src-color-bg-default, #fff);box-shadow:0 26px 80px #0003,0 0 1px #0003}.resume-box .connect-button{width:100%}.resume-box__text{color:var(--src-color-gray-500, #6b7280);text-align:center;font-family:var(--src-font-family-body);font-size:14px;font-style:normal;font-weight:400;line-height:24px}.preload .message-loader{position:absolute;bottom:20px;left:50%;display:block;margin:auto;transform:translate(-50%)}.preload .message-loader>p{margin:0;line-height:1;transition:all ease .35s}.preload .message-loader>p span{font-size:10px;transition:all ease .35s}@media (min-width: 1900px){.preload .message-loader{bottom:40px}}\n"], dependencies: [{ kind: "directive", type: NgOptimizedImage, selector: "img[ngSrc]", inputs: ["ngSrc", "ngSrcset", "sizes", "width", "height", "decoding", "loading", "priority", "loaderParams", "disableOptimizedSrcset", "fill", "placeholder", "placeholderConfig", "src", "srcset"] }, { kind: "component", type: SourceButtonComponent, selector: "src-button", inputs: ["type", "appearance", "colorScheme", "size", "state", "customClass", "hasDisclosure", "isFullWidth", "isPressed", "isDisabled", "isLoading", "iconButton", "srcButtonConfig", "formID", "data-testid"], outputs: ["onClick", "onSubmit"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
3983
4170
  }
3984
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.1", ngImport: i0, type: AfkRestartScreenLockerComponent, decorators: [{
4171
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.4", ngImport: i0, type: AfkRestartScreenLockerComponent, decorators: [{
3985
4172
  type: Component,
3986
- args: [{ selector: 'app-afk-restart-screen-locker', changeDetection: ChangeDetectionStrategy.OnPush, imports: [NgOptimizedImage, SourceButtonComponent, SourceButtonComponent], template: "@if (!isViewportReady()) {\n <div class=\"preload\">\n <div class=\"back\">\n @if (imageLoadingSrc()) {\n <img\n [ngSrc]=\"imageLoadingSrc()!\"\n fill\n loading=\"lazy\"\n alt=\"image loading src\"\n />\n }\n </div>\n\n @if (showReconnectPopup()) {\n <div class=\"stream-message-wrapper\">\n <div class=\"resume-box\">\n @if (isSecondStart()) {\n <div class=\"resume-box__text\">\n Your stream has been paused due to inactivity\n </div>\n }\n\n <src-button\n (onClick)=\"connect()\"\n [isFullWidth]=\"true\"\n [size]=\"'large'\"\n [colorScheme]=\"'primary'\"\n [data-testid]=\"'connect-button'\"\n class=\"connect-button\"\n >\n {{ isSecondStart() ? 'Resume' : 'Start' }}\n </src-button>\n </div>\n </div>\n }\n </div>\n}\n", styles: [".preload{position:absolute;top:0;left:0;width:100%;height:100%;text-align:center}.preload .back{position:absolute;top:0;left:0;display:flex;justify-content:center;align-items:center;width:100%;height:100%}.preload .back img{width:100%;height:100%;object-fit:cover}.preload .stream-message-wrapper{position:absolute;top:0;left:0;width:100%;height:100%;background-color:transparent;z-index:3;display:flex;align-items:center;justify-content:center}.resume-box{padding:16px;position:absolute;bottom:0;left:50%;gap:12px;display:flex;transform:translate(-50%,-50%);flex-direction:column;align-items:center;border-radius:var(--src-border-rounded-parent, 8px);background:var(--src-color-bg-default, #fff);box-shadow:0 26px 80px #0003,0 0 1px #0003}.resume-box .connect-button{width:100%}.resume-box__text{color:var(--src-color-gray-500, #6b7280);text-align:center;font-family:var(--src-font-family-body);font-size:14px;font-style:normal;font-weight:400;line-height:24px}.preload .message-loader{position:absolute;bottom:20px;left:50%;display:block;margin:auto;transform:translate(-50%)}.preload .message-loader>p{margin:0;line-height:1;transition:all ease .35s}.preload .message-loader>p span{font-size:10px;transition:all ease .35s}@media (min-width: 1900px){.preload .message-loader{bottom:40px}}\n"] }]
4173
+ args: [{ selector: 'app-afk-restart-screen-locker', changeDetection: ChangeDetectionStrategy.OnPush, imports: [NgOptimizedImage, SourceButtonComponent, SourceButtonComponent], template: "@if (isLoaderScreenVisible()) {\n <div class=\"preload\">\n <div class=\"back\">\n @if (imageLoadingSrc()) {\n <img\n [ngSrc]=\"imageLoadingSrc()!\"\n fill\n loading=\"lazy\"\n alt=\"image loading src\"\n />\n }\n </div>\n\n @if (showReconnectPopup() && isExistMatchUrls()) {\n <div class=\"stream-message-wrapper\">\n <div class=\"resume-box\">\n @if (isSecondStart()) {\n <div class=\"resume-box__text\">\n Your stream has been paused due to inactivity\n </div>\n }\n\n <src-button\n (onClick)=\"connect()\"\n [isFullWidth]=\"true\"\n [size]=\"'large'\"\n [colorScheme]=\"'primary'\"\n [data-testid]=\"'connect-button'\"\n class=\"connect-button\"\n >\n {{ isSecondStart() ? 'Resume' : 'Start' }}\n </src-button>\n </div>\n </div>\n }\n </div>\n}\n", styles: [".preload{position:absolute;top:0;left:0;width:100%;height:100%;text-align:center}.preload .back{position:absolute;top:0;left:0;display:flex;justify-content:center;align-items:center;width:100%;height:100%;background-color:#fff}.preload .back img{width:100%;height:100%;object-fit:cover}.preload .stream-message-wrapper{position:absolute;top:0;left:0;width:100%;height:100%;background-color:transparent;z-index:3;display:flex;align-items:center;justify-content:center}.resume-box{padding:16px;position:absolute;bottom:0;left:50%;gap:12px;display:flex;transform:translate(-50%,-50%);flex-direction:column;align-items:center;border-radius:var(--src-border-rounded-parent, 8px);background:var(--src-color-bg-default, #fff);box-shadow:0 26px 80px #0003,0 0 1px #0003}.resume-box .connect-button{width:100%}.resume-box__text{color:var(--src-color-gray-500, #6b7280);text-align:center;font-family:var(--src-font-family-body);font-size:14px;font-style:normal;font-weight:400;line-height:24px}.preload .message-loader{position:absolute;bottom:20px;left:50%;display:block;margin:auto;transform:translate(-50%)}.preload .message-loader>p{margin:0;line-height:1;transition:all ease .35s}.preload .message-loader>p span{font-size:10px;transition:all ease .35s}@media (min-width: 1900px){.preload .message-loader{bottom:40px}}\n"] }]
3987
4174
  }] });
3988
4175
 
3989
4176
  class StatGraphComponent {
@@ -4048,10 +4235,10 @@ class StatGraphComponent {
4048
4235
  }
4049
4236
  this.draw();
4050
4237
  }
4051
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.1", ngImport: i0, type: StatGraphComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
4052
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.2.1", type: StatGraphComponent, isStandalone: true, selector: "app-stat-graph", inputs: { color: { classPropertyName: "color", publicName: "color", isSignal: true, isRequired: false, transformFunction: null }, tickStep: { classPropertyName: "tickStep", publicName: "tickStep", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: true, transformFunction: null }, dataTick: { classPropertyName: "dataTick", publicName: "dataTick", isSignal: false, isRequired: false, transformFunction: null } }, host: { listeners: { "window:resize": "resize($event)" } }, viewQueries: [{ propertyName: "graph", first: true, predicate: ["graph"], descendants: true }], ngImport: i0, template: "<div class=\"content\">\n <p>{{ label() }}: {{ current }} | Min:{{ min }} | Max:{{ max }}</p>\n <canvas #graph class=\"graph\"></canvas>\n</div>\n", styles: [".content{width:100%;height:100%}.content p{color:#fff;margin:5px 0 0;height:25px}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
4238
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.4", ngImport: i0, type: StatGraphComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
4239
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.2.4", type: StatGraphComponent, isStandalone: true, selector: "app-stat-graph", inputs: { color: { classPropertyName: "color", publicName: "color", isSignal: true, isRequired: false, transformFunction: null }, tickStep: { classPropertyName: "tickStep", publicName: "tickStep", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: true, transformFunction: null }, dataTick: { classPropertyName: "dataTick", publicName: "dataTick", isSignal: false, isRequired: false, transformFunction: null } }, host: { listeners: { "window:resize": "resize($event)" } }, viewQueries: [{ propertyName: "graph", first: true, predicate: ["graph"], descendants: true }], ngImport: i0, template: "<div class=\"content\">\n <p>{{ label() }}: {{ current }} | Min:{{ min }} | Max:{{ max }}</p>\n <canvas #graph class=\"graph\"></canvas>\n</div>\n", styles: [".content{width:100%;height:100%}.content p{color:#fff;margin:5px 0 0;height:25px}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
4053
4240
  }
4054
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.1", ngImport: i0, type: StatGraphComponent, decorators: [{
4241
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.4", ngImport: i0, type: StatGraphComponent, decorators: [{
4055
4242
  type: Component,
4056
4243
  args: [{ selector: 'app-stat-graph', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"content\">\n <p>{{ label() }}: {{ current }} | Min:{{ min }} | Max:{{ max }}</p>\n <canvas #graph class=\"graph\"></canvas>\n</div>\n", styles: [".content{width:100%;height:100%}.content p{color:#fff;margin:5px 0 0;height:25px}\n"] }]
4057
4244
  }], propDecorators: { graph: [{
@@ -4176,29 +4363,28 @@ class VideoStatsComponent {
4176
4363
  elements: this.elementsToShow,
4177
4364
  }));
4178
4365
  }
4179
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.1", ngImport: i0, type: VideoStatsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
4180
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.2.1", type: VideoStatsComponent, isStandalone: true, selector: "app-video-stats", ngImport: i0, template: "@if (videoStatus()) {\n @if (viewportReady()) {\n <div class=\"settings-container\">\n <button (click)=\"toggle()\" class=\"gear-button\">Stats</button>\n <div (click)=\"toggle()\" [class.min]=\"collapsed\" id=\"aggregatedStats\">\n <div class=\"forNerds\">\n <div (click)=\"$event.stopPropagation()\" class=\"static\">\n <li>\n <app-stat-graph\n [dataTick]=\"fpsTick()\"\n label=\"FPS (higher is better)\"\n />\n </li>\n <li>\n <app-stat-graph\n [dataTick]=\"videoQP()\"\n label=\"QP (lower is better)\"\n color=\"#D5ff07\"\n />\n </li>\n <li>\n <app-stat-graph\n [dataTick]=\"bitrateTick()\"\n label=\"Bitrate\"\n color=\"#D57F07\"\n />\n </li>\n </div>\n <div>\n @for (graph of graphList$ | async; track graph) {\n <li (click)=\"toggleGraph($event, graph.key, 0)\" class=\"graph\">\n <app-stat-graph\n [label]=\"graph.key\"\n [dataTick]=\"graph.stat | async\"\n [color]=\"graph.color\"\n />\n </li>\n }\n </div>\n </div>\n\n @for (el of videoStatus(); track el.key + $index) {\n <div (click)=\"toggleGraph($event, el.key, el.value)\" class=\"stat\">\n <span>{{ el.key }}: </span>{{ el.value | json }}\n </div>\n }\n </div>\n </div>\n @if (!collapsed) {\n <div [innerHTML]=\"ssInfo() | safe: 'html'\" class=\"ssInfo\"></div>\n }\n }\n}\n", styles: [".settings-container{position:absolute;top:65px;left:10px;z-index:1000;bottom:10px}.gear-button{left:0;width:50px;position:absolute;background:none;cursor:pointer;font-size:10px;font-weight:500;border:1px solid;border-radius:9px;background:#0162cc;color:#fff;padding:4px}.gear-button>*{color:#fff;filter:drop-shadow(1px 1px 1px rgb(0,0,0))}#aggregatedStats{max-height:calc(100% - 25px);overflow-y:auto;margin-top:25px;left:20px;z-index:31;max-width:400px;padding:10px;background-color:#fff3;border:1px solid grey}#aggregatedStats>*{color:#fff;text-shadow:-1px -1px 0 #000,1px -1px 0 #000,-1px 1px 0 #000,1px 1px 0 #000}#aggregatedStats:empty{display:none}#aggregatedStats button{position:absolute;right:5px;top:5px}#aggregatedStats.min{display:none}#aggregatedStats .forNerds{width:100%}#aggregatedStats .forNerds li{list-style-type:none;height:60px}#aggregatedStats .forNerds li app-stat-graph{display:block;width:100%;height:100%}#aggregatedStats .stat{cursor:pointer}#aggregatedStats .stat span{font-weight:700}#aggregatedStats .graph{cursor:pointer}#aggregatedStats .static{pointer-events:all}.ssInfo{position:absolute;top:0;left:50%;transform:translate(-50%);color:#fff;text-shadow:-1px -1px 0 #000,1px -1px 0 #000,-1px 1px 0 #000,1px 1px 0 #000;text-align:center;width:80%;pointer-events:none}\n"], dependencies: [{ kind: "component", type: StatGraphComponent, selector: "app-stat-graph", inputs: ["color", "tickStep", "label", "dataTick"] }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "pipe", type: JsonPipe, name: "json" }, { kind: "pipe", type: SafePipe, name: "safe" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
4366
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.4", ngImport: i0, type: VideoStatsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
4367
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.2.4", type: VideoStatsComponent, isStandalone: true, selector: "app-video-stats", ngImport: i0, template: "@if (videoStatus()) {\n @if (viewportReady()) {\n <div class=\"settings-container\">\n <button (click)=\"toggle()\" class=\"gear-button\">Stats</button>\n <div (click)=\"toggle()\" [class.min]=\"collapsed\" id=\"aggregatedStats\">\n <div class=\"forNerds\">\n <div (click)=\"$event.stopPropagation()\" class=\"static\">\n <li>\n <app-stat-graph\n [dataTick]=\"fpsTick()\"\n label=\"FPS (higher is better)\"\n />\n </li>\n <li>\n <app-stat-graph\n [dataTick]=\"videoQP()\"\n label=\"QP (lower is better)\"\n color=\"#D5ff07\"\n />\n </li>\n <li>\n <app-stat-graph\n [dataTick]=\"bitrateTick()\"\n label=\"Bitrate\"\n color=\"#D57F07\"\n />\n </li>\n </div>\n <div>\n @for (graph of graphList$ | async; track graph) {\n <li (click)=\"toggleGraph($event, graph.key, 0)\" class=\"graph\">\n <app-stat-graph\n [label]=\"graph.key\"\n [dataTick]=\"graph.stat | async\"\n [color]=\"graph.color\"\n />\n </li>\n }\n </div>\n </div>\n\n @for (el of videoStatus(); track el.key + $index) {\n <div (click)=\"toggleGraph($event, el.key, el.value)\" class=\"stat\">\n <span>{{ el.key }}: </span>{{ el.value | json }}\n </div>\n }\n </div>\n </div>\n @if (!collapsed) {\n <div [innerHTML]=\"ssInfo() | safe: 'html'\" class=\"ssInfo\"></div>\n }\n }\n}\n", styles: [".settings-container{position:absolute;top:65px;left:10px;z-index:1000;bottom:10px}.gear-button{left:0;width:50px;position:absolute;background:none;cursor:pointer;font-size:10px;font-weight:500;border:1px solid;border-radius:9px;background:#0162cc;color:#fff;padding:4px}.gear-button>*{color:#fff;filter:drop-shadow(1px 1px 1px rgb(0,0,0))}#aggregatedStats{max-height:calc(100% - 25px);overflow-y:auto;margin-top:25px;left:20px;z-index:31;max-width:400px;padding:10px;background-color:#fff3;border:1px solid grey}#aggregatedStats>*{color:#fff;text-shadow:-1px -1px 0 #000,1px -1px 0 #000,-1px 1px 0 #000,1px 1px 0 #000}#aggregatedStats:empty{display:none}#aggregatedStats button{position:absolute;right:5px;top:5px}#aggregatedStats.min{display:none}#aggregatedStats .forNerds{width:100%}#aggregatedStats .forNerds li{list-style-type:none;height:60px}#aggregatedStats .forNerds li app-stat-graph{display:block;width:100%;height:100%}#aggregatedStats .stat{cursor:pointer}#aggregatedStats .stat span{font-weight:700}#aggregatedStats .graph{cursor:pointer}#aggregatedStats .static{pointer-events:all}.ssInfo{position:absolute;top:0;left:50%;transform:translate(-50%);color:#fff;text-shadow:-1px -1px 0 #000,1px -1px 0 #000,-1px 1px 0 #000,1px 1px 0 #000;text-align:center;width:80%;pointer-events:none}\n"], dependencies: [{ kind: "component", type: StatGraphComponent, selector: "app-stat-graph", inputs: ["color", "tickStep", "label", "dataTick"] }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "pipe", type: JsonPipe, name: "json" }, { kind: "pipe", type: SafePipe, name: "safe" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
4181
4368
  }
4182
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.1", ngImport: i0, type: VideoStatsComponent, decorators: [{
4369
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.4", ngImport: i0, type: VideoStatsComponent, decorators: [{
4183
4370
  type: Component,
4184
4371
  args: [{ selector: 'app-video-stats', changeDetection: ChangeDetectionStrategy.OnPush, imports: [StatGraphComponent, AsyncPipe, JsonPipe, SafePipe], template: "@if (videoStatus()) {\n @if (viewportReady()) {\n <div class=\"settings-container\">\n <button (click)=\"toggle()\" class=\"gear-button\">Stats</button>\n <div (click)=\"toggle()\" [class.min]=\"collapsed\" id=\"aggregatedStats\">\n <div class=\"forNerds\">\n <div (click)=\"$event.stopPropagation()\" class=\"static\">\n <li>\n <app-stat-graph\n [dataTick]=\"fpsTick()\"\n label=\"FPS (higher is better)\"\n />\n </li>\n <li>\n <app-stat-graph\n [dataTick]=\"videoQP()\"\n label=\"QP (lower is better)\"\n color=\"#D5ff07\"\n />\n </li>\n <li>\n <app-stat-graph\n [dataTick]=\"bitrateTick()\"\n label=\"Bitrate\"\n color=\"#D57F07\"\n />\n </li>\n </div>\n <div>\n @for (graph of graphList$ | async; track graph) {\n <li (click)=\"toggleGraph($event, graph.key, 0)\" class=\"graph\">\n <app-stat-graph\n [label]=\"graph.key\"\n [dataTick]=\"graph.stat | async\"\n [color]=\"graph.color\"\n />\n </li>\n }\n </div>\n </div>\n\n @for (el of videoStatus(); track el.key + $index) {\n <div (click)=\"toggleGraph($event, el.key, el.value)\" class=\"stat\">\n <span>{{ el.key }}: </span>{{ el.value | json }}\n </div>\n }\n </div>\n </div>\n @if (!collapsed) {\n <div [innerHTML]=\"ssInfo() | safe: 'html'\" class=\"ssInfo\"></div>\n }\n }\n}\n", styles: [".settings-container{position:absolute;top:65px;left:10px;z-index:1000;bottom:10px}.gear-button{left:0;width:50px;position:absolute;background:none;cursor:pointer;font-size:10px;font-weight:500;border:1px solid;border-radius:9px;background:#0162cc;color:#fff;padding:4px}.gear-button>*{color:#fff;filter:drop-shadow(1px 1px 1px rgb(0,0,0))}#aggregatedStats{max-height:calc(100% - 25px);overflow-y:auto;margin-top:25px;left:20px;z-index:31;max-width:400px;padding:10px;background-color:#fff3;border:1px solid grey}#aggregatedStats>*{color:#fff;text-shadow:-1px -1px 0 #000,1px -1px 0 #000,-1px 1px 0 #000,1px 1px 0 #000}#aggregatedStats:empty{display:none}#aggregatedStats button{position:absolute;right:5px;top:5px}#aggregatedStats.min{display:none}#aggregatedStats .forNerds{width:100%}#aggregatedStats .forNerds li{list-style-type:none;height:60px}#aggregatedStats .forNerds li app-stat-graph{display:block;width:100%;height:100%}#aggregatedStats .stat{cursor:pointer}#aggregatedStats .stat span{font-weight:700}#aggregatedStats .graph{cursor:pointer}#aggregatedStats .static{pointer-events:all}.ssInfo{position:absolute;top:0;left:50%;transform:translate(-50%);color:#fff;text-shadow:-1px -1px 0 #000,1px -1px 0 #000,-1px 1px 0 #000,1px 1px 0 #000;text-align:center;width:80%;pointer-events:none}\n"] }]
4185
4372
  }], ctorParameters: () => [] });
4186
4373
 
4187
4374
  class UnrealStatusComponent {
4188
4375
  constructor() {
4189
- this.store = inject(Store);
4190
- this.unrealInitialConfig = inject(UNREAL_CONFIG, {
4191
- optional: true,
4192
- });
4193
- this.resetLoaderTrigger$ = this.store
4194
- .select(unrealFeature.selectCirrusConnected)
4195
- .pipe(filter(Falsy));
4196
4376
  this.isDevMode = inject(DevModeService).isDevMode;
4377
+ this.unrealInitialConfig = inject(UNREAL_CONFIG);
4197
4378
  this.destroyRef = inject(DestroyRef);
4379
+ this.store = inject(Store);
4380
+ this.resetPercentageSignal$ = this.store
4381
+ .select(selectShowLoader)
4382
+ .pipe(filter(Falsy));
4383
+ this.showLoader = this.store.selectSignal(selectShowLoader);
4198
4384
  /**
4199
4385
  * An observable that emits smoothed percentage values from 0 to 100.
4200
4386
  */
4201
- this.messagePercents$ = toSignal(this.resetLoaderTrigger$.pipe(withLatestFrom(this.store.select(unrealFeature.selectIsFreezeLoaderPercents)), filter(([, isFreezeLoaderPercents]) => !isFreezeLoaderPercents), switchMap$1(() => this.store.select(selectTotalProgress).pipe(startWith(0), clampAndKeepMaxPercents(), floatToSmoothPercents(), combineLatestWith(this.store.select(selectShowLoader)), map$1(([progress, showLoader]) => (showLoader ? progress || 0 : null))))));
4387
+ this.messagePercents = toSignal(this.store.select(selectTotalProgress).pipe(clampAndKeepMaxPercents(this.resetPercentageSignal$), floatToSmoothPercents(), distinctUntilChanged(), map$1((progress) => progress || 0)));
4202
4388
  }
4203
4389
  ngOnInit() {
4204
4390
  /**
@@ -4236,7 +4422,7 @@ class UnrealStatusComponent {
4236
4422
  * A subscription that merges various status observables and emits debounced status via postMessage.
4237
4423
  */
4238
4424
  merge(nullifyObs$, cirrusConnected$, signalingStatus$, streamToggle$)
4239
- .pipe(debounceTime(0), tapLog('STATUS'), takeUntilDestroyed(this.destroyRef))
4425
+ .pipe(debounceTime(0), tapLog('STATUS=>'), takeUntilDestroyed(this.destroyRef))
4240
4426
  .subscribe((status) => this.sendMessageToIndex(status));
4241
4427
  }
4242
4428
  /**
@@ -4258,15 +4444,30 @@ class UnrealStatusComponent {
4258
4444
  // Fails silently if the iframe's content window cannot be accessed
4259
4445
  }
4260
4446
  }
4261
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.1", ngImport: i0, type: UnrealStatusComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
4262
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.2.1", type: UnrealStatusComponent, isStandalone: true, selector: "app-unreal-status", ngImport: i0, template: "@if (messagePercents$() !== null) {\n <div class=\"status-box\">\n <div class=\"status-box__message\">\n <src-loading\n [size]=\"30\"\n [backgroundStrokeColor]=\"'#E5E7EB'\"\n [progressStrokeColor]=\"'#1F2937'\"\n />\n {{ messagePercents$() }}%\n </div>\n </div>\n}\n\n@if (isDevMode) {\n <app-video-stats />\n}\n", styles: ["app-stat-graph{height:30px;width:100%}.status-box{position:absolute;top:80%;left:50%;transform:translate(-50%,-50%);z-index:101;display:flex;justify-content:center;align-items:center;width:auto;max-width:500px;margin:0;background:var(--src-color-bg-default);border:none;border-radius:var(--src-border-rounded-full, 9999px);box-shadow:0 8px 20px #1718181f,0 3px 6px #17181814;pointer-events:none}.status-box__message{display:flex;align-items:center;padding:12px 20px 12px 16px;color:var(--src-color-text-default, #1f2937);font-size:16px;font-weight:400;line-height:24px}.status-box__message .status-box__message_text{display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}.status-box__message src-loading{margin-right:12px}\n"], dependencies: [{ kind: "component", type: VideoStatsComponent, selector: "app-video-stats" }, { kind: "component", type: SourceLoadingComponent, selector: "src-loading", inputs: ["size", "progress", "lineCap", "backgroundStrokeColor", "progressStrokeColor", "strokeWidth", "data-testid"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
4447
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.4", ngImport: i0, type: UnrealStatusComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
4448
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.2.4", type: UnrealStatusComponent, isStandalone: true, selector: "app-unreal-status", ngImport: i0, template: "@if (showLoader()) {\n <div class=\"status-box\">\n <div class=\"status-box__message\">\n <src-loading\n [size]=\"30\"\n [backgroundStrokeColor]=\"'#E5E7EB'\"\n [progressStrokeColor]=\"'#1F2937'\"\n />\n {{ messagePercents() }}%\n </div>\n </div>\n}\n\n@if (isDevMode) {\n <app-video-stats />\n}\n", styles: ["app-stat-graph{height:30px;width:100%}.status-box{position:absolute;top:80%;left:50%;transform:translate(-50%,-50%);z-index:101;display:flex;justify-content:center;align-items:center;width:auto;max-width:500px;margin:0;background:var(--src-color-bg-default);border:none;border-radius:var(--src-border-rounded-full, 9999px);box-shadow:0 8px 20px #1718181f,0 3px 6px #17181814;pointer-events:none}.status-box__message{display:flex;align-items:center;padding:12px 20px 12px 16px;color:var(--src-color-text-default, #1f2937);font-size:16px;font-weight:400;line-height:24px}.status-box__message .status-box__message_text{display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}.status-box__message src-loading{margin-right:12px}\n"], dependencies: [{ kind: "component", type: VideoStatsComponent, selector: "app-video-stats" }, { kind: "component", type: SourceLoadingComponent, selector: "src-loading", inputs: ["size", "progress", "lineCap", "backgroundStrokeColor", "progressStrokeColor", "strokeWidth", "data-testid"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
4263
4449
  }
4264
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.1", ngImport: i0, type: UnrealStatusComponent, decorators: [{
4450
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.4", ngImport: i0, type: UnrealStatusComponent, decorators: [{
4265
4451
  type: Component,
4266
- args: [{ selector: 'app-unreal-status', changeDetection: ChangeDetectionStrategy.OnPush, imports: [VideoStatsComponent, SourceLoadingComponent], template: "@if (messagePercents$() !== null) {\n <div class=\"status-box\">\n <div class=\"status-box__message\">\n <src-loading\n [size]=\"30\"\n [backgroundStrokeColor]=\"'#E5E7EB'\"\n [progressStrokeColor]=\"'#1F2937'\"\n />\n {{ messagePercents$() }}%\n </div>\n </div>\n}\n\n@if (isDevMode) {\n <app-video-stats />\n}\n", styles: ["app-stat-graph{height:30px;width:100%}.status-box{position:absolute;top:80%;left:50%;transform:translate(-50%,-50%);z-index:101;display:flex;justify-content:center;align-items:center;width:auto;max-width:500px;margin:0;background:var(--src-color-bg-default);border:none;border-radius:var(--src-border-rounded-full, 9999px);box-shadow:0 8px 20px #1718181f,0 3px 6px #17181814;pointer-events:none}.status-box__message{display:flex;align-items:center;padding:12px 20px 12px 16px;color:var(--src-color-text-default, #1f2937);font-size:16px;font-weight:400;line-height:24px}.status-box__message .status-box__message_text{display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}.status-box__message src-loading{margin-right:12px}\n"] }]
4452
+ args: [{ selector: 'app-unreal-status', changeDetection: ChangeDetectionStrategy.OnPush, imports: [VideoStatsComponent, SourceLoadingComponent], template: "@if (showLoader()) {\n <div class=\"status-box\">\n <div class=\"status-box__message\">\n <src-loading\n [size]=\"30\"\n [backgroundStrokeColor]=\"'#E5E7EB'\"\n [progressStrokeColor]=\"'#1F2937'\"\n />\n {{ messagePercents() }}%\n </div>\n </div>\n}\n\n@if (isDevMode) {\n <app-video-stats />\n}\n", styles: ["app-stat-graph{height:30px;width:100%}.status-box{position:absolute;top:80%;left:50%;transform:translate(-50%,-50%);z-index:101;display:flex;justify-content:center;align-items:center;width:auto;max-width:500px;margin:0;background:var(--src-color-bg-default);border:none;border-radius:var(--src-border-rounded-full, 9999px);box-shadow:0 8px 20px #1718181f,0 3px 6px #17181814;pointer-events:none}.status-box__message{display:flex;align-items:center;padding:12px 20px 12px 16px;color:var(--src-color-text-default, #1f2937);font-size:16px;font-weight:400;line-height:24px}.status-box__message .status-box__message_text{display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}.status-box__message src-loading{margin-right:12px}\n"] }]
4267
4453
  }] });
4268
4454
 
4269
4455
  class UnrealSceneComponent {
4456
+ get resizeValues() {
4457
+ if (!this.isStudio()) {
4458
+ return this.getResizeValuesUniversal();
4459
+ }
4460
+ return this.getResizeValues();
4461
+ }
4462
+ get pixelRatio() {
4463
+ return window.devicePixelRatio;
4464
+ }
4465
+ onMouseOver() {
4466
+ this.changeMouseOverScene.emit(true);
4467
+ }
4468
+ onMouseOut() {
4469
+ this.changeMouseOverScene.emit(false);
4470
+ }
4270
4471
  constructor() {
4271
4472
  this.isStudio = input(false, ...(ngDevMode ? [{ debugName: "isStudio" }] : []));
4272
4473
  this.useContainerAsSizeProvider = input(true, ...(ngDevMode ? [{ debugName: "useContainerAsSizeProvider" }] : []));
@@ -4282,8 +4483,9 @@ class UnrealSceneComponent {
4282
4483
  this.width = FULL_HD_WIDTH;
4283
4484
  this.height = FULL_HD_HEIGHT;
4284
4485
  this.store = inject(Store);
4285
- this.lightMode = toSignal(this.store.select(unrealFeature.selectLowBandwidth));
4286
- this.isFreezeFrameLoading = toSignal(this.store.select(selectIsFreezeFrameLoading));
4486
+ this.lightMode = this.store.selectSignal(unrealFeature.selectLowBandwidth);
4487
+ this.isFreezeFrameLoading = this.store.selectSignal(selectIsFreezeFrameLoading);
4488
+ this.isExistMatchUrls = this.store.selectSignal(selectIsExistMatchUrls);
4287
4489
  this.aggregatorService = inject(AggregatorService);
4288
4490
  this.commandsSender = inject(UnrealCommunicatorService);
4289
4491
  this.inputService = inject(InputService);
@@ -4291,27 +4493,16 @@ class UnrealSceneComponent {
4291
4493
  this.streamTelemetryService = inject(StreamStatusTelemetryService);
4292
4494
  this.element = inject(ElementRef);
4293
4495
  this.destroyRef = inject(DestroyRef);
4294
- }
4295
- get resizeValues() {
4296
- if (!this.isStudio()) {
4297
- return this.getResizeValuesUniversal();
4298
- }
4299
- return this.getResizeValues();
4300
- }
4301
- get pixelRatio() {
4302
- return window.devicePixelRatio;
4303
- }
4304
- onMouseOver() {
4305
- this.changeMouseOverScene.emit(true);
4306
- }
4307
- onMouseOut() {
4308
- this.changeMouseOverScene.emit(false);
4309
- }
4310
- ngOnInit() {
4496
+ this.destroyRef.onDestroy(() => {
4497
+ this.commandsSender.destroy();
4498
+ this.store.dispatch(destroyUnrealScene());
4499
+ });
4311
4500
  this.streamTelemetryService.init();
4312
4501
  this.aggregatorService.init();
4313
4502
  this.inputService.useKeyboardKeys(this.inputService.defaultKeys);
4314
- this.store.dispatch(initSignalling());
4503
+ if (this.isExistMatchUrls()) {
4504
+ this.store.dispatch(initSignalling());
4505
+ }
4315
4506
  }
4316
4507
  ngAfterViewInit() {
4317
4508
  fromEvent(this.element.nativeElement, 'contextmenu')
@@ -4349,11 +4540,6 @@ class UnrealSceneComponent {
4349
4540
  this.sendResize(this.resizeValues);
4350
4541
  });
4351
4542
  }
4352
- ngOnDestroy() {
4353
- this.commandsSender.destroy();
4354
- this.store.dispatch(destroyConnectionsAndResetState());
4355
- this.store.dispatch(resetUnrealStateAction());
4356
- }
4357
4543
  adaptVideo(size) {
4358
4544
  const video = this.videoService.video;
4359
4545
  const areaSize = this.resizeValues;
@@ -4447,10 +4633,10 @@ class UnrealSceneComponent {
4447
4633
  makeEven(value) {
4448
4634
  return Math.floor((value + 1) / 2) * 2;
4449
4635
  }
4450
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.1", ngImport: i0, type: UnrealSceneComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
4451
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.2.1", type: UnrealSceneComponent, isStandalone: true, selector: "app-unreal-scene", inputs: { isStudio: { classPropertyName: "isStudio", publicName: "isStudio", isSignal: true, isRequired: false, transformFunction: null }, useContainerAsSizeProvider: { classPropertyName: "useContainerAsSizeProvider", publicName: "useContainerAsSizeProvider", isSignal: true, isRequired: false, transformFunction: null }, studioResolutionSize: { classPropertyName: "studioResolutionSize", publicName: "studioResolutionSize", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { changeMouseOverScene: "changeMouseOverScene" }, host: { listeners: { "mouseover": "onMouseOver()", "mouseout": "onMouseOut()" } }, viewQueries: [{ propertyName: "container", first: true, predicate: ["container"], descendants: true }], ngImport: i0, template: "<div class=\"frame unreal-container\">\n <div #container [class.lightModeCursor]=\"lightMode()\" id=\"player\"></div>\n\n <app-unreal-status />\n <app-freeze-frame />\n <app-clickable-overlay />\n <app-afk-restart-screen-locker />\n\n <ng-content select=\"app-video-locker\"></ng-content>\n <ng-content select=\"app-pdf\"></ng-content>\n <ng-content select=\"app-show-case\"></ng-content>\n <ng-content select=\"app-low-bandwidth-detector\"></ng-content>\n</div>\n", styles: ["#player{position:absolute;width:100%;height:100%;display:flex;justify-content:center;align-items:center;overflow:hidden}.unreal-container{position:absolute;top:0;left:0;width:100%;height:100%;background-color:#fff}.unreal-container.select{cursor:url('data:image/svg+xml,<svg width=\"24\" height=\"24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M15.15 21.375a1.423 1.423 0 0 1-1.15.063 1.487 1.487 0 0 1-.85-.788l-3-6.45-2.325 3.25c-.283.4-.658.525-1.125.375-.467-.15-.7-.466-.7-.95V4.05c0-.417.188-.717.563-.9.375-.183.729-.142 1.062.125l10.1 7.95c.383.284.496.65.337 1.1-.158.45-.479.675-.962.675h-4.2l2.975 6.375c.183.384.204.767.063 1.15a1.487 1.487 0 0 1-.788.85Z\" fill=\"%23000\"/><path d=\"m12.697 20.861.002.005c.237.495.617.852 1.128 1.04.515.191 1.039.16 1.539-.08a1.987 1.987 0 0 0 1.04-1.128 1.922 1.922 0 0 0-.079-1.536v-.003L13.684 13.5H17.1c.32 0 .628-.075.89-.26.263-.184.438-.447.544-.749.106-.3.135-.617.04-.925a1.458 1.458 0 0 0-.545-.738L7.936 2.883a1.51 1.51 0 0 0-.768-.336 1.471 1.471 0 0 0-.825.154 1.495 1.495 0 0 0-.626.547 1.492 1.492 0 0 0-.217.802v12.825c0 .324.08.634.272.897.193.261.467.43.775.53.31.099.632.12.942.016.31-.103.555-.313.743-.578h.001l1.825-2.552 2.639 5.673Z\" stroke=\"%23fff\" stroke-opacity=\".7\"/></svg>') 6 2,auto}.unreal-container.orbit{cursor:url('data:image/svg+xml,<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" fill=\"none\"><path fill=\"%23000\" d=\"M11.998 21.6c-1.966 0-3.737-.53-5.312-1.588-1.575-1.058-2.738-2.437-3.488-4.137a.852.852 0 0 1 .013-.713.867.867 0 0 1 .512-.487.86.86 0 0 1 .688.037c.225.109.387.28.487.513.617 1.35 1.559 2.45 2.825 3.3 1.267.85 2.692 1.275 4.275 1.275 1.384 0 2.646-.33 3.788-.988a7.985 7.985 0 0 0 2.762-2.612h-.85a.873.873 0 0 1-.64-.257.863.863 0 0 1-.26-.638.88.88 0 0 1 .26-.643.864.864 0 0 1 .64-.262h3c.255 0 .47.086.642.259a.87.87 0 0 1 .258.64v3a.874.874 0 0 1-.257.642.863.863 0 0 1-.637.259.88.88 0 0 1-.643-.259.865.865 0 0 1-.263-.641v-.725a9.95 9.95 0 0 1-3.35 2.925c-1.35.733-2.833 1.1-4.45 1.1Zm0-17.4c-1.383 0-2.645.33-3.787.987A7.985 7.985 0 0 0 5.448 7.8h.85c.255 0 .47.086.642.257a.863.863 0 0 1 .258.638.88.88 0 0 1-.258.642.864.864 0 0 1-.642.263h-3a.87.87 0 0 1-.64-.259.87.87 0 0 1-.26-.641v-3c0-.255.086-.469.258-.641a.863.863 0 0 1 .637-.26.88.88 0 0 1 .643.26.864.864 0 0 1 .262.64v.726A9.95 9.95 0 0 1 7.548 3.5c1.35-.733 2.834-1.1 4.45-1.1 2 0 3.788.542 5.363 1.625 1.575 1.083 2.736 2.49 3.482 4.22a.724.724 0 0 1-.045.646.926.926 0 0 1-.525.437.87.87 0 0 1-.687-.04.977.977 0 0 1-.488-.513c-.616-1.35-1.558-2.45-2.825-3.3-1.266-.85-2.691-1.275-4.275-1.275Zm0 10.8a2.893 2.893 0 0 1-2.125-.875A2.893 2.893 0 0 1 8.998 12c0-.833.292-1.542.875-2.125A2.893 2.893 0 0 1 11.998 9c.834 0 1.542.292 2.125.875.584.583.875 1.292.875 2.125s-.291 1.542-.875 2.125a2.893 2.893 0 0 1-2.125.875Z\"/><path stroke=\"%23fff\" stroke-opacity=\".7\" d=\"m2.739 16.072.002.005c.789 1.788 2.014 3.24 3.666 4.35 1.66 1.116 3.53 1.673 5.591 1.673 1.696 0 3.262-.386 4.69-1.16a10.54 10.54 0 0 0 2.714-2.097c.069.167.171.32.308.454.272.268.613.403.994.403.38 0 .722-.135.992-.406s.402-.614.402-.994v-3c0-.381-.134-.724-.405-.995a1.37 1.37 0 0 0-.995-.405h-3c-.383 0-.727.137-.997.411a1.38 1.38 0 0 0-.403.994c0 .38.135.723.407.992.238.237.532.369.858.397a7.552 7.552 0 0 1-2.027 1.685c-1.062.613-2.237.92-3.538.92-1.488 0-2.815-.397-3.996-1.19-1.19-.798-2.07-1.826-2.647-3.087-.147-.34-.393-.6-.727-.76a1.36 1.36 0 0 0-1.073-.058c-.37.133-.64.397-.8.754a1.351 1.351 0 0 0-.016 1.114Zm4.553-8.37a1.36 1.36 0 0 0-.858-.396A7.552 7.552 0 0 1 8.46 5.62c1.062-.613 2.237-.921 3.537-.921 1.489 0 2.816.398 3.997 1.19 1.19.8 2.07 1.827 2.646 3.088.148.34.394.6.728.76a1.37 1.37 0 0 0 1.068.063c.347-.12.62-.346.799-.668.187-.338.215-.71.072-1.072l-.003-.007-.003-.007c-.784-1.818-2.006-3.298-3.658-4.434C15.982 2.47 14.094 1.9 11.998 1.9c-1.695 0-3.261.385-4.688 1.16a10.536 10.536 0 0 0-2.715 2.096 1.364 1.364 0 0 0-.308-.453 1.38 1.38 0 0 0-.994-.403c-.38 0-.722.135-.992.406s-.403.614-.403.994v3c0 .38.135.724.406.995.27.27.614.405.994.405h3c.384 0 .727-.137.998-.412a1.38 1.38 0 0 0 .402-.993c0-.38-.135-.723-.406-.992ZM9.52 14.48a3.393 3.393 0 0 0 2.478 1.02c.965 0 1.8-.342 2.479-1.02a3.392 3.392 0 0 0 1.021-2.48c0-.963-.343-1.8-1.021-2.478A3.392 3.392 0 0 0 11.998 8.5c-.964 0-1.8.343-2.478 1.021A3.392 3.392 0 0 0 8.498 12c0 .964.344 1.8 1.022 2.479Z\"/></svg>') 12 12,auto}.unreal-container.pan{cursor:url('data:image/svg+xml,<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" fill=\"none\"><path fill=\"%23000\" d=\"M11.997 10.075a1.01 1.01 0 0 1-.738-.313 1.008 1.008 0 0 1-.312-.737V6.15l-.95.95a.998.998 0 0 1-.763.312 1.09 1.09 0 0 1-.763-.337 1.06 1.06 0 0 1-.324-.775c0-.3.108-.558.324-.775l2.776-2.775c.117-.116.237-.2.362-.25a1.04 1.04 0 0 1 .775 0c.125.05.246.134.363.25l2.8 2.8c.216.217.32.47.313.762a1.096 1.096 0 0 1-.338.763 1.058 1.058 0 0 1-.775.325c-.3 0-.558-.108-.775-.325l-.925-.925v2.875c0 .283-.104.53-.312.737a1.01 1.01 0 0 1-.738.313Zm0 11.5a1.04 1.04 0 0 1-.388-.075 1.103 1.103 0 0 1-.362-.25l-2.8-2.8a1.002 1.002 0 0 1-.313-.762c.009-.292.121-.546.337-.763.217-.217.475-.325.775-.325.3 0 .559.108.775.325l.926.925v-2.875c0-.283.104-.529.312-.737a1.01 1.01 0 0 1 .738-.313c.283 0 .529.104.738.313.208.208.312.454.312.737v2.875l.95-.95a.998.998 0 0 1 .762-.312c.292.008.546.12.763.337.216.217.324.475.324.775 0 .3-.108.559-.324.775l-2.775 2.775c-.117.116-.238.2-.363.25a1.04 1.04 0 0 1-.387.075Zm4.925-6.05a1.058 1.058 0 0 1-.326-.774c0-.3.109-.559.326-.776l.925-.925H14.97c-.283 0-.528-.104-.736-.312a1.01 1.01 0 0 1-.313-.738c0-.283.104-.53.313-.738.208-.208.453-.312.737-.312h2.875l-.95-.95a.998.998 0 0 1-.313-.762 1.09 1.09 0 0 1 .338-.764 1.06 1.06 0 0 1 .775-.324c.3 0 .558.108.775.324l2.774 2.776c.117.117.2.238.251.363a1.04 1.04 0 0 1 0 .775c-.05.124-.134.245-.25.362l-2.8 2.8c-.217.216-.471.32-.762.313a1.096 1.096 0 0 1-.763-.337Zm-11.4 0L2.746 12.75a1.103 1.103 0 0 1-.25-.362 1.04 1.04 0 0 1 0-.775c.05-.125.133-.246.25-.363l2.8-2.8c.216-.216.47-.32.762-.313.292.01.546.121.763.337.217.217.325.476.325.776 0 .3-.108.558-.325.775l-.925.925h2.875c.283 0 .529.104.737.312.208.209.313.455.313.738s-.105.53-.313.738a1.008 1.008 0 0 1-.737.312H6.147l.95.95c.217.217.32.471.312.762a1.09 1.09 0 0 1-.337.764 1.06 1.06 0 0 1-.775.324c-.3 0-.559-.108-.776-.324Z\"/><path stroke=\"%23fff\" stroke-opacity=\".7\" d=\"M9.22 7.912c.436.013.821-.15 1.13-.458l.097-.097v1.668c0 .422.16.793.458 1.09.298.299.67.46 1.092.46.422 0 .793-.161 1.091-.46.298-.297.459-.668.459-1.09V7.357l.071.072c.309.308.693.471 1.13.471.435 0 .82-.163 1.128-.471.301-.303.47-.676.483-1.102v-.001a1.501 1.501 0 0 0-.46-1.13l-2.799-2.8a1.6 1.6 0 0 0-.528-.36l-.003-.001a1.54 1.54 0 0 0-1.145 0l-.002.001a1.6 1.6 0 0 0-.529.36L8.118 5.172l-.001.001a1.56 1.56 0 0 0-.47 1.128c0 .435.163.82.47 1.128.303.303.676.472 1.103.484Zm0 0 .014-.5-.015.5Zm-1.311 6.865a1.497 1.497 0 0 0-.458-1.13l-.097-.097h1.668c.421 0 .793-.16 1.09-.458.298-.299.46-.67.46-1.092a1.51 1.51 0 0 0-.46-1.091 1.507 1.507 0 0 0-1.09-.459H7.354l.071-.072c.309-.308.472-.692.472-1.128 0-.436-.163-.82-.472-1.13a1.596 1.596 0 0 0-1.101-.482h-.002a1.501 1.501 0 0 0-1.129.459l-2.8 2.8a1.6 1.6 0 0 0-.36.528l-.001.003a1.54 1.54 0 0 0 0 1.144v.003c.081.2.208.375.362.529l2.774 2.775c.309.308.693.47 1.129.47.435 0 .82-.162 1.128-.47.303-.302.472-.676.484-1.102Zm0 0-.5-.014.5.015v-.001Zm3.038-8.627-.5.5.5.207V6.15Zm.475 15.814.002.001a1.54 1.54 0 0 0 1.145 0h.002c.2-.081.375-.208.53-.362l2.775-2.774a1.56 1.56 0 0 0 .47-1.129c0-.435-.162-.82-.47-1.128a1.589 1.589 0 0 0-1.103-.484 1.497 1.497 0 0 0-1.13.458l-.096.097v-1.668c0-.421-.161-.793-.459-1.09a1.509 1.509 0 0 0-1.091-.46c-.422 0-.794.161-1.092.46a1.507 1.507 0 0 0-.458 1.09v1.668l-.072-.072a1.558 1.558 0 0 0-1.129-.471c-.436 0-.82.163-1.128.471l-.001.001c-.301.302-.47.675-.483 1.101v.001c-.012.437.151.821.46 1.13l2.8 2.8c.153.153.328.28.528.36Zm5.146-6.085c.303.302.676.47 1.102.484a1.5 1.5 0 0 0 1.13-.46l2.8-2.8a1.6 1.6 0 0 0 .36-.528l.002-.003a1.54 1.54 0 0 0 0-1.144l-.001-.003a1.6 1.6 0 0 0-.361-.529l-2.774-2.775h-.001a1.56 1.56 0 0 0-1.128-.47c-.436 0-.82.162-1.128.47h-.001a1.59 1.59 0 0 0-.484 1.102c-.012.437.15.822.459 1.13l.097.097h-1.668c-.422 0-.793.16-1.09.459-.299.298-.46.67-.46 1.091 0 .422.161.793.46 1.092.297.297.668.458 1.09.458h1.668l-.072.072a1.558 1.558 0 0 0-.472 1.129c0 .435.164.82.472 1.128ZM6.147 13.05l.5.5.207-.5h-.707Z\"/></svg>') 12 12,auto}.unreal-container.dolly{cursor:url('data:image/svg+xml,<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" fill=\"none\"><mask id=\"a\" width=\"24\" height=\"24\" x=\"0\" y=\"0\" maskUnits=\"userSpaceOnUse\" style=\"mask-type:alpha\"><path fill=\"%23127392\" d=\"M0 0h24v24H0z\"/></mask><g mask=\"url(%23a)\"><path fill=\"%23000\" d=\"M12.002 20.575a1.026 1.026 0 0 1-.75-.325l-2.55-2.55a.933.933 0 0 1-.287-.713c.008-.275.113-.513.313-.713.2-.2.441-.3.725-.3.283 0 .524.1.724.3l.776.776V6.95l-.8.8c-.2.2-.438.296-.712.288a1.018 1.018 0 0 1-.713-.312c-.2-.2-.3-.442-.3-.726s.1-.525.3-.725l2.524-2.525a1.026 1.026 0 0 1 1.5 0l2.55 2.55c.2.2.296.438.289.713a1.023 1.023 0 0 1-.314.713c-.2.2-.441.3-.724.3a.988.988 0 0 1-.725-.3l-.775-.776v10.1l.8-.8c.2-.2.437-.296.712-.288.275.008.512.112.712.312.2.2.3.442.3.726s-.1.525-.3.725l-2.524 2.525a1.026 1.026 0 0 1-.75.325Z\"/><path stroke=\"%23fff\" stroke-opacity=\".7\" d=\"M13.553 8.153c.28.245.62.373 1 .373.415 0 .784-.153 1.078-.447.287-.287.446-.644.46-1.05v-.002a1.432 1.432 0 0 0-.435-1.08l-2.55-2.55-.354.353.354-.354a1.526 1.526 0 0 0-2.207 0L8.374 5.921A1.487 1.487 0 0 0 7.928 7c0 .416.152.785.446 1.08.288.287.645.446 1.052.457l4.127-.384Zm0 0v7.693m0-7.693a1.667 1.667 0 0 1-.079-.074l-3.021.075v7.693a1.482 1.482 0 0 0-1-.373c-.416 0-.785.153-1.079.447a1.522 1.522 0 0 0-.46 1.05v.002c-.011.417.14.786.435 1.08l2.55 2.55a1.527 1.527 0 0 0 2.207 0l2.525-2.524c.294-.294.446-.663.446-1.079 0-.416-.152-.785-.446-1.08a1.518 1.518 0 0 0-1.052-.457m0 0-.014.5.014-.5Zm0 0a1.424 1.424 0 0 0-1.027.383m0 0a1.583 1.583 0 0 0-.053.05l.354.354m-.3-.404v.104l.3.3m0 0-.3-.3v.6l.3-.3Z\"/></g></svg>') 12 12,auto}.unreal-container.disabled:before{content:\"\";position:absolute;top:0;left:0;width:100%;height:100%;pointer-events:none;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px)}#playerUI{position:absolute;z-index:10;width:100%}#statsContainer{display:none;text-align:left;background-color:#000c}#stats{padding:6px;font-weight:700;font-size:14px;color:#0f0}canvas{position:absolute;image-rendering:crisp-edges}#overlay{position:absolute;top:0;right:2%;z-index:100;padding:4px;border-top-width:0;-webkit-border-bottom-right-radius:5px;-moz-border-radius-bottomright:5px;border-bottom-right-radius:5px;-webkit-border-bottom-left-radius:5px;-moz-border-radius-bottomleft:5px;border-bottom-left-radius:5px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-touch-callout:none}.overlay{font-weight:lighter;font-family:var(--src-font-family-body)}#overlayButton:hover{cursor:pointer}#overlayButton{font-size:40px;text-align:right}#overlaySettings{display:none;width:300px;padding:4px}#videoMessageOverlay{position:absolute;z-index:20;width:100%;margin:auto;font-size:1.8em;font-family:var(--src-font-family-body)}#playButton{display:inline-block;height:auto}img#playButton{width:10%;max-width:241px}#UIInteraction{position:fixed}#UIInteractionButtonBoundary{padding:2px}#UIInteractionButton{cursor:pointer}#hiddenInput{position:absolute;left:-10%;width:0;opacity:0}#editTextButton{position:absolute;width:40px;height:40px}\n"], dependencies: [{ kind: "component", type: AfkRestartScreenLockerComponent, selector: "app-afk-restart-screen-locker" }, { kind: "component", type: ClickableOverlayComponent, selector: "app-clickable-overlay" }, { kind: "component", type: UnrealStatusComponent, selector: "app-unreal-status" }, { kind: "component", type: FreezeFrameComponent, selector: "app-freeze-frame" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
4636
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.4", ngImport: i0, type: UnrealSceneComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
4637
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.2.4", type: UnrealSceneComponent, isStandalone: true, selector: "app-unreal-scene", inputs: { isStudio: { classPropertyName: "isStudio", publicName: "isStudio", isSignal: true, isRequired: false, transformFunction: null }, useContainerAsSizeProvider: { classPropertyName: "useContainerAsSizeProvider", publicName: "useContainerAsSizeProvider", isSignal: true, isRequired: false, transformFunction: null }, studioResolutionSize: { classPropertyName: "studioResolutionSize", publicName: "studioResolutionSize", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { changeMouseOverScene: "changeMouseOverScene" }, host: { listeners: { "mouseover": "onMouseOver()", "mouseout": "onMouseOut()" } }, viewQueries: [{ propertyName: "container", first: true, predicate: ["container"], descendants: true }], ngImport: i0, template: "<div class=\"frame unreal-container\">\n <div #container [class.lightModeCursor]=\"lightMode()\" id=\"player\"></div>\n\n <app-unreal-status />\n <app-freeze-frame />\n <app-clickable-overlay />\n <app-afk-restart-screen-locker />\n\n <ng-content select=\"app-video-locker\"></ng-content>\n <ng-content select=\"app-pdf\"></ng-content>\n <ng-content select=\"app-show-case\"></ng-content>\n <ng-content select=\"app-low-bandwidth-detector\"></ng-content>\n</div>\n", styles: ["#player{position:absolute;width:100%;height:100%;display:flex;justify-content:center;align-items:center;overflow:hidden}.unreal-container{position:absolute;top:0;left:0;width:100%;height:100%;background-color:#fff}.unreal-container.select{cursor:url('data:image/svg+xml,<svg width=\"24\" height=\"24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M15.15 21.375a1.423 1.423 0 0 1-1.15.063 1.487 1.487 0 0 1-.85-.788l-3-6.45-2.325 3.25c-.283.4-.658.525-1.125.375-.467-.15-.7-.466-.7-.95V4.05c0-.417.188-.717.563-.9.375-.183.729-.142 1.062.125l10.1 7.95c.383.284.496.65.337 1.1-.158.45-.479.675-.962.675h-4.2l2.975 6.375c.183.384.204.767.063 1.15a1.487 1.487 0 0 1-.788.85Z\" fill=\"%23000\"/><path d=\"m12.697 20.861.002.005c.237.495.617.852 1.128 1.04.515.191 1.039.16 1.539-.08a1.987 1.987 0 0 0 1.04-1.128 1.922 1.922 0 0 0-.079-1.536v-.003L13.684 13.5H17.1c.32 0 .628-.075.89-.26.263-.184.438-.447.544-.749.106-.3.135-.617.04-.925a1.458 1.458 0 0 0-.545-.738L7.936 2.883a1.51 1.51 0 0 0-.768-.336 1.471 1.471 0 0 0-.825.154 1.495 1.495 0 0 0-.626.547 1.492 1.492 0 0 0-.217.802v12.825c0 .324.08.634.272.897.193.261.467.43.775.53.31.099.632.12.942.016.31-.103.555-.313.743-.578h.001l1.825-2.552 2.639 5.673Z\" stroke=\"%23fff\" stroke-opacity=\".7\"/></svg>') 6 2,auto}.unreal-container.orbit{cursor:url('data:image/svg+xml,<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" fill=\"none\"><path fill=\"%23000\" d=\"M11.998 21.6c-1.966 0-3.737-.53-5.312-1.588-1.575-1.058-2.738-2.437-3.488-4.137a.852.852 0 0 1 .013-.713.867.867 0 0 1 .512-.487.86.86 0 0 1 .688.037c.225.109.387.28.487.513.617 1.35 1.559 2.45 2.825 3.3 1.267.85 2.692 1.275 4.275 1.275 1.384 0 2.646-.33 3.788-.988a7.985 7.985 0 0 0 2.762-2.612h-.85a.873.873 0 0 1-.64-.257.863.863 0 0 1-.26-.638.88.88 0 0 1 .26-.643.864.864 0 0 1 .64-.262h3c.255 0 .47.086.642.259a.87.87 0 0 1 .258.64v3a.874.874 0 0 1-.257.642.863.863 0 0 1-.637.259.88.88 0 0 1-.643-.259.865.865 0 0 1-.263-.641v-.725a9.95 9.95 0 0 1-3.35 2.925c-1.35.733-2.833 1.1-4.45 1.1Zm0-17.4c-1.383 0-2.645.33-3.787.987A7.985 7.985 0 0 0 5.448 7.8h.85c.255 0 .47.086.642.257a.863.863 0 0 1 .258.638.88.88 0 0 1-.258.642.864.864 0 0 1-.642.263h-3a.87.87 0 0 1-.64-.259.87.87 0 0 1-.26-.641v-3c0-.255.086-.469.258-.641a.863.863 0 0 1 .637-.26.88.88 0 0 1 .643.26.864.864 0 0 1 .262.64v.726A9.95 9.95 0 0 1 7.548 3.5c1.35-.733 2.834-1.1 4.45-1.1 2 0 3.788.542 5.363 1.625 1.575 1.083 2.736 2.49 3.482 4.22a.724.724 0 0 1-.045.646.926.926 0 0 1-.525.437.87.87 0 0 1-.687-.04.977.977 0 0 1-.488-.513c-.616-1.35-1.558-2.45-2.825-3.3-1.266-.85-2.691-1.275-4.275-1.275Zm0 10.8a2.893 2.893 0 0 1-2.125-.875A2.893 2.893 0 0 1 8.998 12c0-.833.292-1.542.875-2.125A2.893 2.893 0 0 1 11.998 9c.834 0 1.542.292 2.125.875.584.583.875 1.292.875 2.125s-.291 1.542-.875 2.125a2.893 2.893 0 0 1-2.125.875Z\"/><path stroke=\"%23fff\" stroke-opacity=\".7\" d=\"m2.739 16.072.002.005c.789 1.788 2.014 3.24 3.666 4.35 1.66 1.116 3.53 1.673 5.591 1.673 1.696 0 3.262-.386 4.69-1.16a10.54 10.54 0 0 0 2.714-2.097c.069.167.171.32.308.454.272.268.613.403.994.403.38 0 .722-.135.992-.406s.402-.614.402-.994v-3c0-.381-.134-.724-.405-.995a1.37 1.37 0 0 0-.995-.405h-3c-.383 0-.727.137-.997.411a1.38 1.38 0 0 0-.403.994c0 .38.135.723.407.992.238.237.532.369.858.397a7.552 7.552 0 0 1-2.027 1.685c-1.062.613-2.237.92-3.538.92-1.488 0-2.815-.397-3.996-1.19-1.19-.798-2.07-1.826-2.647-3.087-.147-.34-.393-.6-.727-.76a1.36 1.36 0 0 0-1.073-.058c-.37.133-.64.397-.8.754a1.351 1.351 0 0 0-.016 1.114Zm4.553-8.37a1.36 1.36 0 0 0-.858-.396A7.552 7.552 0 0 1 8.46 5.62c1.062-.613 2.237-.921 3.537-.921 1.489 0 2.816.398 3.997 1.19 1.19.8 2.07 1.827 2.646 3.088.148.34.394.6.728.76a1.37 1.37 0 0 0 1.068.063c.347-.12.62-.346.799-.668.187-.338.215-.71.072-1.072l-.003-.007-.003-.007c-.784-1.818-2.006-3.298-3.658-4.434C15.982 2.47 14.094 1.9 11.998 1.9c-1.695 0-3.261.385-4.688 1.16a10.536 10.536 0 0 0-2.715 2.096 1.364 1.364 0 0 0-.308-.453 1.38 1.38 0 0 0-.994-.403c-.38 0-.722.135-.992.406s-.403.614-.403.994v3c0 .38.135.724.406.995.27.27.614.405.994.405h3c.384 0 .727-.137.998-.412a1.38 1.38 0 0 0 .402-.993c0-.38-.135-.723-.406-.992ZM9.52 14.48a3.393 3.393 0 0 0 2.478 1.02c.965 0 1.8-.342 2.479-1.02a3.392 3.392 0 0 0 1.021-2.48c0-.963-.343-1.8-1.021-2.478A3.392 3.392 0 0 0 11.998 8.5c-.964 0-1.8.343-2.478 1.021A3.392 3.392 0 0 0 8.498 12c0 .964.344 1.8 1.022 2.479Z\"/></svg>') 12 12,auto}.unreal-container.pan{cursor:url('data:image/svg+xml,<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" fill=\"none\"><path fill=\"%23000\" d=\"M11.997 10.075a1.01 1.01 0 0 1-.738-.313 1.008 1.008 0 0 1-.312-.737V6.15l-.95.95a.998.998 0 0 1-.763.312 1.09 1.09 0 0 1-.763-.337 1.06 1.06 0 0 1-.324-.775c0-.3.108-.558.324-.775l2.776-2.775c.117-.116.237-.2.362-.25a1.04 1.04 0 0 1 .775 0c.125.05.246.134.363.25l2.8 2.8c.216.217.32.47.313.762a1.096 1.096 0 0 1-.338.763 1.058 1.058 0 0 1-.775.325c-.3 0-.558-.108-.775-.325l-.925-.925v2.875c0 .283-.104.53-.312.737a1.01 1.01 0 0 1-.738.313Zm0 11.5a1.04 1.04 0 0 1-.388-.075 1.103 1.103 0 0 1-.362-.25l-2.8-2.8a1.002 1.002 0 0 1-.313-.762c.009-.292.121-.546.337-.763.217-.217.475-.325.775-.325.3 0 .559.108.775.325l.926.925v-2.875c0-.283.104-.529.312-.737a1.01 1.01 0 0 1 .738-.313c.283 0 .529.104.738.313.208.208.312.454.312.737v2.875l.95-.95a.998.998 0 0 1 .762-.312c.292.008.546.12.763.337.216.217.324.475.324.775 0 .3-.108.559-.324.775l-2.775 2.775c-.117.116-.238.2-.363.25a1.04 1.04 0 0 1-.387.075Zm4.925-6.05a1.058 1.058 0 0 1-.326-.774c0-.3.109-.559.326-.776l.925-.925H14.97c-.283 0-.528-.104-.736-.312a1.01 1.01 0 0 1-.313-.738c0-.283.104-.53.313-.738.208-.208.453-.312.737-.312h2.875l-.95-.95a.998.998 0 0 1-.313-.762 1.09 1.09 0 0 1 .338-.764 1.06 1.06 0 0 1 .775-.324c.3 0 .558.108.775.324l2.774 2.776c.117.117.2.238.251.363a1.04 1.04 0 0 1 0 .775c-.05.124-.134.245-.25.362l-2.8 2.8c-.217.216-.471.32-.762.313a1.096 1.096 0 0 1-.763-.337Zm-11.4 0L2.746 12.75a1.103 1.103 0 0 1-.25-.362 1.04 1.04 0 0 1 0-.775c.05-.125.133-.246.25-.363l2.8-2.8c.216-.216.47-.32.762-.313.292.01.546.121.763.337.217.217.325.476.325.776 0 .3-.108.558-.325.775l-.925.925h2.875c.283 0 .529.104.737.312.208.209.313.455.313.738s-.105.53-.313.738a1.008 1.008 0 0 1-.737.312H6.147l.95.95c.217.217.32.471.312.762a1.09 1.09 0 0 1-.337.764 1.06 1.06 0 0 1-.775.324c-.3 0-.559-.108-.776-.324Z\"/><path stroke=\"%23fff\" stroke-opacity=\".7\" d=\"M9.22 7.912c.436.013.821-.15 1.13-.458l.097-.097v1.668c0 .422.16.793.458 1.09.298.299.67.46 1.092.46.422 0 .793-.161 1.091-.46.298-.297.459-.668.459-1.09V7.357l.071.072c.309.308.693.471 1.13.471.435 0 .82-.163 1.128-.471.301-.303.47-.676.483-1.102v-.001a1.501 1.501 0 0 0-.46-1.13l-2.799-2.8a1.6 1.6 0 0 0-.528-.36l-.003-.001a1.54 1.54 0 0 0-1.145 0l-.002.001a1.6 1.6 0 0 0-.529.36L8.118 5.172l-.001.001a1.56 1.56 0 0 0-.47 1.128c0 .435.163.82.47 1.128.303.303.676.472 1.103.484Zm0 0 .014-.5-.015.5Zm-1.311 6.865a1.497 1.497 0 0 0-.458-1.13l-.097-.097h1.668c.421 0 .793-.16 1.09-.458.298-.299.46-.67.46-1.092a1.51 1.51 0 0 0-.46-1.091 1.507 1.507 0 0 0-1.09-.459H7.354l.071-.072c.309-.308.472-.692.472-1.128 0-.436-.163-.82-.472-1.13a1.596 1.596 0 0 0-1.101-.482h-.002a1.501 1.501 0 0 0-1.129.459l-2.8 2.8a1.6 1.6 0 0 0-.36.528l-.001.003a1.54 1.54 0 0 0 0 1.144v.003c.081.2.208.375.362.529l2.774 2.775c.309.308.693.47 1.129.47.435 0 .82-.162 1.128-.47.303-.302.472-.676.484-1.102Zm0 0-.5-.014.5.015v-.001Zm3.038-8.627-.5.5.5.207V6.15Zm.475 15.814.002.001a1.54 1.54 0 0 0 1.145 0h.002c.2-.081.375-.208.53-.362l2.775-2.774a1.56 1.56 0 0 0 .47-1.129c0-.435-.162-.82-.47-1.128a1.589 1.589 0 0 0-1.103-.484 1.497 1.497 0 0 0-1.13.458l-.096.097v-1.668c0-.421-.161-.793-.459-1.09a1.509 1.509 0 0 0-1.091-.46c-.422 0-.794.161-1.092.46a1.507 1.507 0 0 0-.458 1.09v1.668l-.072-.072a1.558 1.558 0 0 0-1.129-.471c-.436 0-.82.163-1.128.471l-.001.001c-.301.302-.47.675-.483 1.101v.001c-.012.437.151.821.46 1.13l2.8 2.8c.153.153.328.28.528.36Zm5.146-6.085c.303.302.676.47 1.102.484a1.5 1.5 0 0 0 1.13-.46l2.8-2.8a1.6 1.6 0 0 0 .36-.528l.002-.003a1.54 1.54 0 0 0 0-1.144l-.001-.003a1.6 1.6 0 0 0-.361-.529l-2.774-2.775h-.001a1.56 1.56 0 0 0-1.128-.47c-.436 0-.82.162-1.128.47h-.001a1.59 1.59 0 0 0-.484 1.102c-.012.437.15.822.459 1.13l.097.097h-1.668c-.422 0-.793.16-1.09.459-.299.298-.46.67-.46 1.091 0 .422.161.793.46 1.092.297.297.668.458 1.09.458h1.668l-.072.072a1.558 1.558 0 0 0-.472 1.129c0 .435.164.82.472 1.128ZM6.147 13.05l.5.5.207-.5h-.707Z\"/></svg>') 12 12,auto}.unreal-container.dolly{cursor:url('data:image/svg+xml,<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" fill=\"none\"><mask id=\"a\" width=\"24\" height=\"24\" x=\"0\" y=\"0\" maskUnits=\"userSpaceOnUse\" style=\"mask-type:alpha\"><path fill=\"%23127392\" d=\"M0 0h24v24H0z\"/></mask><g mask=\"url(%23a)\"><path fill=\"%23000\" d=\"M12.002 20.575a1.026 1.026 0 0 1-.75-.325l-2.55-2.55a.933.933 0 0 1-.287-.713c.008-.275.113-.513.313-.713.2-.2.441-.3.725-.3.283 0 .524.1.724.3l.776.776V6.95l-.8.8c-.2.2-.438.296-.712.288a1.018 1.018 0 0 1-.713-.312c-.2-.2-.3-.442-.3-.726s.1-.525.3-.725l2.524-2.525a1.026 1.026 0 0 1 1.5 0l2.55 2.55c.2.2.296.438.289.713a1.023 1.023 0 0 1-.314.713c-.2.2-.441.3-.724.3a.988.988 0 0 1-.725-.3l-.775-.776v10.1l.8-.8c.2-.2.437-.296.712-.288.275.008.512.112.712.312.2.2.3.442.3.726s-.1.525-.3.725l-2.524 2.525a1.026 1.026 0 0 1-.75.325Z\"/><path stroke=\"%23fff\" stroke-opacity=\".7\" d=\"M13.553 8.153c.28.245.62.373 1 .373.415 0 .784-.153 1.078-.447.287-.287.446-.644.46-1.05v-.002a1.432 1.432 0 0 0-.435-1.08l-2.55-2.55-.354.353.354-.354a1.526 1.526 0 0 0-2.207 0L8.374 5.921A1.487 1.487 0 0 0 7.928 7c0 .416.152.785.446 1.08.288.287.645.446 1.052.457l4.127-.384Zm0 0v7.693m0-7.693a1.667 1.667 0 0 1-.079-.074l-3.021.075v7.693a1.482 1.482 0 0 0-1-.373c-.416 0-.785.153-1.079.447a1.522 1.522 0 0 0-.46 1.05v.002c-.011.417.14.786.435 1.08l2.55 2.55a1.527 1.527 0 0 0 2.207 0l2.525-2.524c.294-.294.446-.663.446-1.079 0-.416-.152-.785-.446-1.08a1.518 1.518 0 0 0-1.052-.457m0 0-.014.5.014-.5Zm0 0a1.424 1.424 0 0 0-1.027.383m0 0a1.583 1.583 0 0 0-.053.05l.354.354m-.3-.404v.104l.3.3m0 0-.3-.3v.6l.3-.3Z\"/></g></svg>') 12 12,auto}.unreal-container.disabled:before{content:\"\";position:absolute;top:0;left:0;width:100%;height:100%;pointer-events:none;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px)}#playerUI{position:absolute;z-index:10;width:100%}#statsContainer{display:none;text-align:left;background-color:#000c}#stats{padding:6px;font-weight:700;font-size:14px;color:#0f0}canvas{position:absolute;image-rendering:crisp-edges}#overlay{position:absolute;top:0;right:2%;z-index:100;padding:4px;border-top-width:0;-webkit-border-bottom-right-radius:5px;-moz-border-radius-bottomright:5px;border-bottom-right-radius:5px;-webkit-border-bottom-left-radius:5px;-moz-border-radius-bottomleft:5px;border-bottom-left-radius:5px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-touch-callout:none}.overlay{font-weight:lighter;font-family:var(--src-font-family-body)}#overlayButton:hover{cursor:pointer}#overlayButton{font-size:40px;text-align:right}#overlaySettings{display:none;width:300px;padding:4px}#videoMessageOverlay{position:absolute;z-index:20;width:100%;margin:auto;font-size:1.8em;font-family:var(--src-font-family-body)}#playButton{display:inline-block;height:auto}img#playButton{width:10%;max-width:241px}#UIInteraction{position:fixed}#UIInteractionButtonBoundary{padding:2px}#UIInteractionButton{cursor:pointer}#hiddenInput{position:absolute;left:-10%;width:0;opacity:0}#editTextButton{position:absolute;width:40px;height:40px}\n"], dependencies: [{ kind: "component", type: AfkRestartScreenLockerComponent, selector: "app-afk-restart-screen-locker" }, { kind: "component", type: ClickableOverlayComponent, selector: "app-clickable-overlay" }, { kind: "component", type: UnrealStatusComponent, selector: "app-unreal-status" }, { kind: "component", type: FreezeFrameComponent, selector: "app-freeze-frame" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
4452
4638
  }
4453
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.1", ngImport: i0, type: UnrealSceneComponent, decorators: [{
4639
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.4", ngImport: i0, type: UnrealSceneComponent, decorators: [{
4454
4640
  type: Component,
4455
4641
  args: [{ selector: 'app-unreal-scene', changeDetection: ChangeDetectionStrategy.OnPush, imports: [
4456
4642
  AfkRestartScreenLockerComponent,
@@ -4458,7 +4644,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.1", ngImpor
4458
4644
  UnrealStatusComponent,
4459
4645
  FreezeFrameComponent,
4460
4646
  ], template: "<div class=\"frame unreal-container\">\n <div #container [class.lightModeCursor]=\"lightMode()\" id=\"player\"></div>\n\n <app-unreal-status />\n <app-freeze-frame />\n <app-clickable-overlay />\n <app-afk-restart-screen-locker />\n\n <ng-content select=\"app-video-locker\"></ng-content>\n <ng-content select=\"app-pdf\"></ng-content>\n <ng-content select=\"app-show-case\"></ng-content>\n <ng-content select=\"app-low-bandwidth-detector\"></ng-content>\n</div>\n", styles: ["#player{position:absolute;width:100%;height:100%;display:flex;justify-content:center;align-items:center;overflow:hidden}.unreal-container{position:absolute;top:0;left:0;width:100%;height:100%;background-color:#fff}.unreal-container.select{cursor:url('data:image/svg+xml,<svg width=\"24\" height=\"24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M15.15 21.375a1.423 1.423 0 0 1-1.15.063 1.487 1.487 0 0 1-.85-.788l-3-6.45-2.325 3.25c-.283.4-.658.525-1.125.375-.467-.15-.7-.466-.7-.95V4.05c0-.417.188-.717.563-.9.375-.183.729-.142 1.062.125l10.1 7.95c.383.284.496.65.337 1.1-.158.45-.479.675-.962.675h-4.2l2.975 6.375c.183.384.204.767.063 1.15a1.487 1.487 0 0 1-.788.85Z\" fill=\"%23000\"/><path d=\"m12.697 20.861.002.005c.237.495.617.852 1.128 1.04.515.191 1.039.16 1.539-.08a1.987 1.987 0 0 0 1.04-1.128 1.922 1.922 0 0 0-.079-1.536v-.003L13.684 13.5H17.1c.32 0 .628-.075.89-.26.263-.184.438-.447.544-.749.106-.3.135-.617.04-.925a1.458 1.458 0 0 0-.545-.738L7.936 2.883a1.51 1.51 0 0 0-.768-.336 1.471 1.471 0 0 0-.825.154 1.495 1.495 0 0 0-.626.547 1.492 1.492 0 0 0-.217.802v12.825c0 .324.08.634.272.897.193.261.467.43.775.53.31.099.632.12.942.016.31-.103.555-.313.743-.578h.001l1.825-2.552 2.639 5.673Z\" stroke=\"%23fff\" stroke-opacity=\".7\"/></svg>') 6 2,auto}.unreal-container.orbit{cursor:url('data:image/svg+xml,<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" fill=\"none\"><path fill=\"%23000\" d=\"M11.998 21.6c-1.966 0-3.737-.53-5.312-1.588-1.575-1.058-2.738-2.437-3.488-4.137a.852.852 0 0 1 .013-.713.867.867 0 0 1 .512-.487.86.86 0 0 1 .688.037c.225.109.387.28.487.513.617 1.35 1.559 2.45 2.825 3.3 1.267.85 2.692 1.275 4.275 1.275 1.384 0 2.646-.33 3.788-.988a7.985 7.985 0 0 0 2.762-2.612h-.85a.873.873 0 0 1-.64-.257.863.863 0 0 1-.26-.638.88.88 0 0 1 .26-.643.864.864 0 0 1 .64-.262h3c.255 0 .47.086.642.259a.87.87 0 0 1 .258.64v3a.874.874 0 0 1-.257.642.863.863 0 0 1-.637.259.88.88 0 0 1-.643-.259.865.865 0 0 1-.263-.641v-.725a9.95 9.95 0 0 1-3.35 2.925c-1.35.733-2.833 1.1-4.45 1.1Zm0-17.4c-1.383 0-2.645.33-3.787.987A7.985 7.985 0 0 0 5.448 7.8h.85c.255 0 .47.086.642.257a.863.863 0 0 1 .258.638.88.88 0 0 1-.258.642.864.864 0 0 1-.642.263h-3a.87.87 0 0 1-.64-.259.87.87 0 0 1-.26-.641v-3c0-.255.086-.469.258-.641a.863.863 0 0 1 .637-.26.88.88 0 0 1 .643.26.864.864 0 0 1 .262.64v.726A9.95 9.95 0 0 1 7.548 3.5c1.35-.733 2.834-1.1 4.45-1.1 2 0 3.788.542 5.363 1.625 1.575 1.083 2.736 2.49 3.482 4.22a.724.724 0 0 1-.045.646.926.926 0 0 1-.525.437.87.87 0 0 1-.687-.04.977.977 0 0 1-.488-.513c-.616-1.35-1.558-2.45-2.825-3.3-1.266-.85-2.691-1.275-4.275-1.275Zm0 10.8a2.893 2.893 0 0 1-2.125-.875A2.893 2.893 0 0 1 8.998 12c0-.833.292-1.542.875-2.125A2.893 2.893 0 0 1 11.998 9c.834 0 1.542.292 2.125.875.584.583.875 1.292.875 2.125s-.291 1.542-.875 2.125a2.893 2.893 0 0 1-2.125.875Z\"/><path stroke=\"%23fff\" stroke-opacity=\".7\" d=\"m2.739 16.072.002.005c.789 1.788 2.014 3.24 3.666 4.35 1.66 1.116 3.53 1.673 5.591 1.673 1.696 0 3.262-.386 4.69-1.16a10.54 10.54 0 0 0 2.714-2.097c.069.167.171.32.308.454.272.268.613.403.994.403.38 0 .722-.135.992-.406s.402-.614.402-.994v-3c0-.381-.134-.724-.405-.995a1.37 1.37 0 0 0-.995-.405h-3c-.383 0-.727.137-.997.411a1.38 1.38 0 0 0-.403.994c0 .38.135.723.407.992.238.237.532.369.858.397a7.552 7.552 0 0 1-2.027 1.685c-1.062.613-2.237.92-3.538.92-1.488 0-2.815-.397-3.996-1.19-1.19-.798-2.07-1.826-2.647-3.087-.147-.34-.393-.6-.727-.76a1.36 1.36 0 0 0-1.073-.058c-.37.133-.64.397-.8.754a1.351 1.351 0 0 0-.016 1.114Zm4.553-8.37a1.36 1.36 0 0 0-.858-.396A7.552 7.552 0 0 1 8.46 5.62c1.062-.613 2.237-.921 3.537-.921 1.489 0 2.816.398 3.997 1.19 1.19.8 2.07 1.827 2.646 3.088.148.34.394.6.728.76a1.37 1.37 0 0 0 1.068.063c.347-.12.62-.346.799-.668.187-.338.215-.71.072-1.072l-.003-.007-.003-.007c-.784-1.818-2.006-3.298-3.658-4.434C15.982 2.47 14.094 1.9 11.998 1.9c-1.695 0-3.261.385-4.688 1.16a10.536 10.536 0 0 0-2.715 2.096 1.364 1.364 0 0 0-.308-.453 1.38 1.38 0 0 0-.994-.403c-.38 0-.722.135-.992.406s-.403.614-.403.994v3c0 .38.135.724.406.995.27.27.614.405.994.405h3c.384 0 .727-.137.998-.412a1.38 1.38 0 0 0 .402-.993c0-.38-.135-.723-.406-.992ZM9.52 14.48a3.393 3.393 0 0 0 2.478 1.02c.965 0 1.8-.342 2.479-1.02a3.392 3.392 0 0 0 1.021-2.48c0-.963-.343-1.8-1.021-2.478A3.392 3.392 0 0 0 11.998 8.5c-.964 0-1.8.343-2.478 1.021A3.392 3.392 0 0 0 8.498 12c0 .964.344 1.8 1.022 2.479Z\"/></svg>') 12 12,auto}.unreal-container.pan{cursor:url('data:image/svg+xml,<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" fill=\"none\"><path fill=\"%23000\" d=\"M11.997 10.075a1.01 1.01 0 0 1-.738-.313 1.008 1.008 0 0 1-.312-.737V6.15l-.95.95a.998.998 0 0 1-.763.312 1.09 1.09 0 0 1-.763-.337 1.06 1.06 0 0 1-.324-.775c0-.3.108-.558.324-.775l2.776-2.775c.117-.116.237-.2.362-.25a1.04 1.04 0 0 1 .775 0c.125.05.246.134.363.25l2.8 2.8c.216.217.32.47.313.762a1.096 1.096 0 0 1-.338.763 1.058 1.058 0 0 1-.775.325c-.3 0-.558-.108-.775-.325l-.925-.925v2.875c0 .283-.104.53-.312.737a1.01 1.01 0 0 1-.738.313Zm0 11.5a1.04 1.04 0 0 1-.388-.075 1.103 1.103 0 0 1-.362-.25l-2.8-2.8a1.002 1.002 0 0 1-.313-.762c.009-.292.121-.546.337-.763.217-.217.475-.325.775-.325.3 0 .559.108.775.325l.926.925v-2.875c0-.283.104-.529.312-.737a1.01 1.01 0 0 1 .738-.313c.283 0 .529.104.738.313.208.208.312.454.312.737v2.875l.95-.95a.998.998 0 0 1 .762-.312c.292.008.546.12.763.337.216.217.324.475.324.775 0 .3-.108.559-.324.775l-2.775 2.775c-.117.116-.238.2-.363.25a1.04 1.04 0 0 1-.387.075Zm4.925-6.05a1.058 1.058 0 0 1-.326-.774c0-.3.109-.559.326-.776l.925-.925H14.97c-.283 0-.528-.104-.736-.312a1.01 1.01 0 0 1-.313-.738c0-.283.104-.53.313-.738.208-.208.453-.312.737-.312h2.875l-.95-.95a.998.998 0 0 1-.313-.762 1.09 1.09 0 0 1 .338-.764 1.06 1.06 0 0 1 .775-.324c.3 0 .558.108.775.324l2.774 2.776c.117.117.2.238.251.363a1.04 1.04 0 0 1 0 .775c-.05.124-.134.245-.25.362l-2.8 2.8c-.217.216-.471.32-.762.313a1.096 1.096 0 0 1-.763-.337Zm-11.4 0L2.746 12.75a1.103 1.103 0 0 1-.25-.362 1.04 1.04 0 0 1 0-.775c.05-.125.133-.246.25-.363l2.8-2.8c.216-.216.47-.32.762-.313.292.01.546.121.763.337.217.217.325.476.325.776 0 .3-.108.558-.325.775l-.925.925h2.875c.283 0 .529.104.737.312.208.209.313.455.313.738s-.105.53-.313.738a1.008 1.008 0 0 1-.737.312H6.147l.95.95c.217.217.32.471.312.762a1.09 1.09 0 0 1-.337.764 1.06 1.06 0 0 1-.775.324c-.3 0-.559-.108-.776-.324Z\"/><path stroke=\"%23fff\" stroke-opacity=\".7\" d=\"M9.22 7.912c.436.013.821-.15 1.13-.458l.097-.097v1.668c0 .422.16.793.458 1.09.298.299.67.46 1.092.46.422 0 .793-.161 1.091-.46.298-.297.459-.668.459-1.09V7.357l.071.072c.309.308.693.471 1.13.471.435 0 .82-.163 1.128-.471.301-.303.47-.676.483-1.102v-.001a1.501 1.501 0 0 0-.46-1.13l-2.799-2.8a1.6 1.6 0 0 0-.528-.36l-.003-.001a1.54 1.54 0 0 0-1.145 0l-.002.001a1.6 1.6 0 0 0-.529.36L8.118 5.172l-.001.001a1.56 1.56 0 0 0-.47 1.128c0 .435.163.82.47 1.128.303.303.676.472 1.103.484Zm0 0 .014-.5-.015.5Zm-1.311 6.865a1.497 1.497 0 0 0-.458-1.13l-.097-.097h1.668c.421 0 .793-.16 1.09-.458.298-.299.46-.67.46-1.092a1.51 1.51 0 0 0-.46-1.091 1.507 1.507 0 0 0-1.09-.459H7.354l.071-.072c.309-.308.472-.692.472-1.128 0-.436-.163-.82-.472-1.13a1.596 1.596 0 0 0-1.101-.482h-.002a1.501 1.501 0 0 0-1.129.459l-2.8 2.8a1.6 1.6 0 0 0-.36.528l-.001.003a1.54 1.54 0 0 0 0 1.144v.003c.081.2.208.375.362.529l2.774 2.775c.309.308.693.47 1.129.47.435 0 .82-.162 1.128-.47.303-.302.472-.676.484-1.102Zm0 0-.5-.014.5.015v-.001Zm3.038-8.627-.5.5.5.207V6.15Zm.475 15.814.002.001a1.54 1.54 0 0 0 1.145 0h.002c.2-.081.375-.208.53-.362l2.775-2.774a1.56 1.56 0 0 0 .47-1.129c0-.435-.162-.82-.47-1.128a1.589 1.589 0 0 0-1.103-.484 1.497 1.497 0 0 0-1.13.458l-.096.097v-1.668c0-.421-.161-.793-.459-1.09a1.509 1.509 0 0 0-1.091-.46c-.422 0-.794.161-1.092.46a1.507 1.507 0 0 0-.458 1.09v1.668l-.072-.072a1.558 1.558 0 0 0-1.129-.471c-.436 0-.82.163-1.128.471l-.001.001c-.301.302-.47.675-.483 1.101v.001c-.012.437.151.821.46 1.13l2.8 2.8c.153.153.328.28.528.36Zm5.146-6.085c.303.302.676.47 1.102.484a1.5 1.5 0 0 0 1.13-.46l2.8-2.8a1.6 1.6 0 0 0 .36-.528l.002-.003a1.54 1.54 0 0 0 0-1.144l-.001-.003a1.6 1.6 0 0 0-.361-.529l-2.774-2.775h-.001a1.56 1.56 0 0 0-1.128-.47c-.436 0-.82.162-1.128.47h-.001a1.59 1.59 0 0 0-.484 1.102c-.012.437.15.822.459 1.13l.097.097h-1.668c-.422 0-.793.16-1.09.459-.299.298-.46.67-.46 1.091 0 .422.161.793.46 1.092.297.297.668.458 1.09.458h1.668l-.072.072a1.558 1.558 0 0 0-.472 1.129c0 .435.164.82.472 1.128ZM6.147 13.05l.5.5.207-.5h-.707Z\"/></svg>') 12 12,auto}.unreal-container.dolly{cursor:url('data:image/svg+xml,<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" fill=\"none\"><mask id=\"a\" width=\"24\" height=\"24\" x=\"0\" y=\"0\" maskUnits=\"userSpaceOnUse\" style=\"mask-type:alpha\"><path fill=\"%23127392\" d=\"M0 0h24v24H0z\"/></mask><g mask=\"url(%23a)\"><path fill=\"%23000\" d=\"M12.002 20.575a1.026 1.026 0 0 1-.75-.325l-2.55-2.55a.933.933 0 0 1-.287-.713c.008-.275.113-.513.313-.713.2-.2.441-.3.725-.3.283 0 .524.1.724.3l.776.776V6.95l-.8.8c-.2.2-.438.296-.712.288a1.018 1.018 0 0 1-.713-.312c-.2-.2-.3-.442-.3-.726s.1-.525.3-.725l2.524-2.525a1.026 1.026 0 0 1 1.5 0l2.55 2.55c.2.2.296.438.289.713a1.023 1.023 0 0 1-.314.713c-.2.2-.441.3-.724.3a.988.988 0 0 1-.725-.3l-.775-.776v10.1l.8-.8c.2-.2.437-.296.712-.288.275.008.512.112.712.312.2.2.3.442.3.726s-.1.525-.3.725l-2.524 2.525a1.026 1.026 0 0 1-.75.325Z\"/><path stroke=\"%23fff\" stroke-opacity=\".7\" d=\"M13.553 8.153c.28.245.62.373 1 .373.415 0 .784-.153 1.078-.447.287-.287.446-.644.46-1.05v-.002a1.432 1.432 0 0 0-.435-1.08l-2.55-2.55-.354.353.354-.354a1.526 1.526 0 0 0-2.207 0L8.374 5.921A1.487 1.487 0 0 0 7.928 7c0 .416.152.785.446 1.08.288.287.645.446 1.052.457l4.127-.384Zm0 0v7.693m0-7.693a1.667 1.667 0 0 1-.079-.074l-3.021.075v7.693a1.482 1.482 0 0 0-1-.373c-.416 0-.785.153-1.079.447a1.522 1.522 0 0 0-.46 1.05v.002c-.011.417.14.786.435 1.08l2.55 2.55a1.527 1.527 0 0 0 2.207 0l2.525-2.524c.294-.294.446-.663.446-1.079 0-.416-.152-.785-.446-1.08a1.518 1.518 0 0 0-1.052-.457m0 0-.014.5.014-.5Zm0 0a1.424 1.424 0 0 0-1.027.383m0 0a1.583 1.583 0 0 0-.053.05l.354.354m-.3-.404v.104l.3.3m0 0-.3-.3v.6l.3-.3Z\"/></g></svg>') 12 12,auto}.unreal-container.disabled:before{content:\"\";position:absolute;top:0;left:0;width:100%;height:100%;pointer-events:none;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px)}#playerUI{position:absolute;z-index:10;width:100%}#statsContainer{display:none;text-align:left;background-color:#000c}#stats{padding:6px;font-weight:700;font-size:14px;color:#0f0}canvas{position:absolute;image-rendering:crisp-edges}#overlay{position:absolute;top:0;right:2%;z-index:100;padding:4px;border-top-width:0;-webkit-border-bottom-right-radius:5px;-moz-border-radius-bottomright:5px;border-bottom-right-radius:5px;-webkit-border-bottom-left-radius:5px;-moz-border-radius-bottomleft:5px;border-bottom-left-radius:5px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-touch-callout:none}.overlay{font-weight:lighter;font-family:var(--src-font-family-body)}#overlayButton:hover{cursor:pointer}#overlayButton{font-size:40px;text-align:right}#overlaySettings{display:none;width:300px;padding:4px}#videoMessageOverlay{position:absolute;z-index:20;width:100%;margin:auto;font-size:1.8em;font-family:var(--src-font-family-body)}#playButton{display:inline-block;height:auto}img#playButton{width:10%;max-width:241px}#UIInteraction{position:fixed}#UIInteractionButtonBoundary{padding:2px}#UIInteractionButton{cursor:pointer}#hiddenInput{position:absolute;left:-10%;width:0;opacity:0}#editTextButton{position:absolute;width:40px;height:40px}\n"] }]
4461
- }], propDecorators: { container: [{
4647
+ }], ctorParameters: () => [], propDecorators: { container: [{
4462
4648
  type: ViewChild,
4463
4649
  args: ['container']
4464
4650
  }], onMouseOver: [{
@@ -4503,6 +4689,7 @@ class VideoLockerComponent {
4503
4689
  .subscribe((src) => this.createVideo(src));
4504
4690
  }
4505
4691
  createVideo(src) {
4692
+ const matchAbsolutePath = !!src.match(/.*\.(mp4|WebM)(\?.*)?$/i);
4506
4693
  // Select the parent layout where the video will be inserted
4507
4694
  const videoContainer = this.videoElement.nativeElement;
4508
4695
  videoContainer.innerHTML = ''; // This will remove all existing content within the layout
@@ -4511,13 +4698,20 @@ class VideoLockerComponent {
4511
4698
  videoElement.autoplay = true;
4512
4699
  videoElement.muted = true;
4513
4700
  videoElement.loop = true;
4514
- videoElement.poster = `${src}/cover.webp`;
4701
+ if (!matchAbsolutePath) {
4702
+ videoElement.poster = `${src}/cover.webp`;
4703
+ }
4515
4704
  videoElement.style.position = 'absolute';
4516
4705
  videoElement.style.width = '100%';
4517
4706
  videoElement.style.height = '100%';
4518
4707
  videoElement.style.objectFit = 'cover';
4519
4708
  const sourceElement = document.createElement('source');
4520
- sourceElement.src = `${src}/video.mp4`;
4709
+ if (matchAbsolutePath) {
4710
+ sourceElement.src = src;
4711
+ }
4712
+ else {
4713
+ sourceElement.src = `${src}/video.mp4`;
4714
+ }
4521
4715
  sourceElement.type = 'video/mp4';
4522
4716
  // Append the source element to the video element
4523
4717
  videoElement.appendChild(sourceElement);
@@ -4526,10 +4720,10 @@ class VideoLockerComponent {
4526
4720
  // Append the video element to the layout
4527
4721
  videoContainer.appendChild(videoElement);
4528
4722
  }
4529
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.1", ngImport: i0, type: VideoLockerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
4530
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.2.1", type: VideoLockerComponent, isStandalone: true, selector: "app-video-locker", viewQueries: [{ propertyName: "videoElement", first: true, predicate: ["videoPlayerCover"], descendants: true }], ngImport: i0, template: "@if (imageIntroSrc$ | async; as url) {\n <div class=\"backImage\">\n <img [ngSrc]=\"url\" fill alt=\"Loading...\" />\n </div>\n} @else if (videoIntroSrc$ | async) {\n <div #videoPlayerCover class=\"backVideo\"></div>\n}\n", styles: [".backVideo{position:absolute;top:0;left:0;display:flex;justify-content:center;align-items:center;width:100%;height:100%}.backVideo video{position:absolute;width:100%;height:100%;object-fit:cover}.backImage{position:absolute;top:0;left:0;display:flex;justify-content:center;align-items:center;width:100%;height:100%}.backImage img{position:absolute;width:100%;height:100%;object-fit:cover}\n"], dependencies: [{ kind: "directive", type: NgOptimizedImage, selector: "img[ngSrc]", inputs: ["ngSrc", "ngSrcset", "sizes", "width", "height", "decoding", "loading", "priority", "loaderParams", "disableOptimizedSrcset", "fill", "placeholder", "placeholderConfig", "src", "srcset"] }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
4723
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.4", ngImport: i0, type: VideoLockerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
4724
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.2.4", type: VideoLockerComponent, isStandalone: true, selector: "app-video-locker", viewQueries: [{ propertyName: "videoElement", first: true, predicate: ["videoPlayerCover"], descendants: true }], ngImport: i0, template: "@if (imageIntroSrc$ | async; as url) {\n <div class=\"backImage\">\n <img [ngSrc]=\"url\" fill alt=\"Loading...\" />\n </div>\n} @else if (videoIntroSrc$ | async) {\n <div #videoPlayerCover class=\"backVideo\"></div>\n}\n", styles: [".backVideo{position:absolute;top:0;left:0;display:flex;justify-content:center;align-items:center;width:100%;height:100%}.backVideo video{position:absolute;width:100%;height:100%;object-fit:cover}.backImage{position:absolute;top:0;left:0;display:flex;justify-content:center;align-items:center;width:100%;height:100%}.backImage img{position:absolute;width:100%;height:100%;object-fit:cover}\n"], dependencies: [{ kind: "directive", type: NgOptimizedImage, selector: "img[ngSrc]", inputs: ["ngSrc", "ngSrcset", "sizes", "width", "height", "decoding", "loading", "priority", "loaderParams", "disableOptimizedSrcset", "fill", "placeholder", "placeholderConfig", "src", "srcset"] }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
4531
4725
  }
4532
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.1", ngImport: i0, type: VideoLockerComponent, decorators: [{
4726
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.4", ngImport: i0, type: VideoLockerComponent, decorators: [{
4533
4727
  type: Component,
4534
4728
  args: [{ selector: 'app-video-locker', imports: [AsyncPipe, NgOptimizedImage], changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (imageIntroSrc$ | async; as url) {\n <div class=\"backImage\">\n <img [ngSrc]=\"url\" fill alt=\"Loading...\" />\n </div>\n} @else if (videoIntroSrc$ | async) {\n <div #videoPlayerCover class=\"backVideo\"></div>\n}\n", styles: [".backVideo{position:absolute;top:0;left:0;display:flex;justify-content:center;align-items:center;width:100%;height:100%}.backVideo video{position:absolute;width:100%;height:100%;object-fit:cover}.backImage{position:absolute;top:0;left:0;display:flex;justify-content:center;align-items:center;width:100%;height:100%}.backImage img{position:absolute;width:100%;height:100%;object-fit:cover}\n"] }]
4535
4729
  }], propDecorators: { videoElement: [{
@@ -4551,15 +4745,18 @@ class WebrtcErrorModalComponent {
4551
4745
  .pipe(first())
4552
4746
  .subscribe((isConnected) => {
4553
4747
  if (!isConnected) {
4554
- this.store.dispatch(destroyConnectionsAndResetState());
4748
+ this.store.dispatch(disconnectStream({
4749
+ reason: DisconnectReason.DropConnection,
4750
+ message: 'Modal Drop Connection',
4751
+ }));
4555
4752
  }
4556
4753
  this.close();
4557
4754
  });
4558
4755
  }
4559
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.1", ngImport: i0, type: WebrtcErrorModalComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
4560
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.2.1", type: WebrtcErrorModalComponent, isStandalone: true, selector: "app-webrtc-error-modal", ngImport: i0, template: "<div [attr.data-testid]=\"'webrtc-error-modal'\" class=\"src-modal\">\n <header class=\"src-modal__header\">\n <div [attr.data-testid]=\"'title'\" class=\"src-modal__title\">\n WebRTC error\n </div>\n </header>\n <section class=\"src-modal__body\">\n <div style=\"text-align: left\">\n An internet connection type (WebRTC) appears to be blocked either by your\n browser settings or your current network. If WebRTC is blocked on your\n browser you may be able to adjust these settings yourself based on\n instructions here:\n <a href=\"https://myownconference.com/blog/en/webrtc/\" target=\"blank\"\n >https://myownconference.com/blog/en/webrtc/</a\n >\n <br /><br />\n Trying a different web browser may help confirm this as well. If WebRTC is\n blocked by your network, try switching to a different network if possible\n or contact your network administrator.<br /><br />\n WebRTC is common, safe and increasingly utilised method for streaming real\n time 3D experiences via a web browser. It typically consumes no more\n bandwidth than streaming an HD video.\n </div>\n </section>\n <footer class=\"src-modal__footer\">\n <src-button\n (onClick)=\"closeModalWithCirrusDisconnect()\"\n [data-testid]=\"'close-webrtc-error-modal'\"\n [colorScheme]=\"'primary'\"\n >\n Ok\n </src-button>\n </footer>\n</div>\n", styles: [".src-modal{--modalBodyPadding: 20px 8px 20px 20px;display:grid;grid-template-columns:minmax(0,1fr);grid-template-rows:auto minmax(0,1fr) auto}.src-modal ::ng-deep .ng-scroll-content{--_scrollbar-content-width: initial;--_viewport-padding-right: 12px}.src-modal__body{width:100%}.src-modal__body p{color:var(--src-color-bg-default, #1f2937);font-size:14px;font-style:normal;font-weight:400;line-height:24px;margin-top:0}.src-modal__body a{word-wrap:break-word;white-space:normal}\n"], dependencies: [{ kind: "component", type: SourceButtonComponent, selector: "src-button", inputs: ["type", "appearance", "colorScheme", "size", "state", "customClass", "hasDisclosure", "isFullWidth", "isPressed", "isDisabled", "isLoading", "iconButton", "srcButtonConfig", "formID", "data-testid"], outputs: ["onClick", "onSubmit"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
4756
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.4", ngImport: i0, type: WebrtcErrorModalComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
4757
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.2.4", type: WebrtcErrorModalComponent, isStandalone: true, selector: "app-webrtc-error-modal", ngImport: i0, template: "<div [attr.data-testid]=\"'webrtc-error-modal'\" class=\"src-modal\">\n <header class=\"src-modal__header\">\n <div [attr.data-testid]=\"'title'\" class=\"src-modal__title\">\n WebRTC error\n </div>\n </header>\n <section class=\"src-modal__body\">\n <div style=\"text-align: left\">\n An internet connection type (WebRTC) appears to be blocked either by your\n browser settings or your current network. If WebRTC is blocked on your\n browser you may be able to adjust these settings yourself based on\n instructions here:\n <a href=\"https://myownconference.com/blog/en/webrtc/\" target=\"blank\"\n >https://myownconference.com/blog/en/webrtc/</a\n >\n <br /><br />\n Trying a different web browser may help confirm this as well. If WebRTC is\n blocked by your network, try switching to a different network if possible\n or contact your network administrator.<br /><br />\n WebRTC is common, safe and increasingly utilised method for streaming real\n time 3D experiences via a web browser. It typically consumes no more\n bandwidth than streaming an HD video.\n </div>\n </section>\n <footer class=\"src-modal__footer\">\n <src-button\n (onClick)=\"closeModalWithCirrusDisconnect()\"\n [data-testid]=\"'close-webrtc-error-modal'\"\n [colorScheme]=\"'primary'\"\n >\n Ok\n </src-button>\n </footer>\n</div>\n", styles: [".src-modal{--modalBodyPadding: 20px 8px 20px 20px;display:grid;grid-template-columns:minmax(0,1fr);grid-template-rows:auto minmax(0,1fr) auto}.src-modal ::ng-deep .ng-scroll-content{--_scrollbar-content-width: initial;--_viewport-padding-right: 12px}.src-modal__body{width:100%}.src-modal__body p{color:var(--src-color-bg-default, #1f2937);font-size:14px;font-style:normal;font-weight:400;line-height:24px;margin-top:0}.src-modal__body a{word-wrap:break-word;white-space:normal}\n"], dependencies: [{ kind: "component", type: SourceButtonComponent, selector: "src-button", inputs: ["type", "appearance", "colorScheme", "size", "state", "customClass", "hasDisclosure", "isFullWidth", "isPressed", "isDisabled", "isLoading", "iconButton", "srcButtonConfig", "formID", "data-testid"], outputs: ["onClick", "onSubmit"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
4561
4758
  }
4562
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.1", ngImport: i0, type: WebrtcErrorModalComponent, decorators: [{
4759
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.4", ngImport: i0, type: WebrtcErrorModalComponent, decorators: [{
4563
4760
  type: Component,
4564
4761
  args: [{ selector: 'app-webrtc-error-modal', changeDetection: ChangeDetectionStrategy.OnPush, imports: [SourceButtonComponent], template: "<div [attr.data-testid]=\"'webrtc-error-modal'\" class=\"src-modal\">\n <header class=\"src-modal__header\">\n <div [attr.data-testid]=\"'title'\" class=\"src-modal__title\">\n WebRTC error\n </div>\n </header>\n <section class=\"src-modal__body\">\n <div style=\"text-align: left\">\n An internet connection type (WebRTC) appears to be blocked either by your\n browser settings or your current network. If WebRTC is blocked on your\n browser you may be able to adjust these settings yourself based on\n instructions here:\n <a href=\"https://myownconference.com/blog/en/webrtc/\" target=\"blank\"\n >https://myownconference.com/blog/en/webrtc/</a\n >\n <br /><br />\n Trying a different web browser may help confirm this as well. If WebRTC is\n blocked by your network, try switching to a different network if possible\n or contact your network administrator.<br /><br />\n WebRTC is common, safe and increasingly utilised method for streaming real\n time 3D experiences via a web browser. It typically consumes no more\n bandwidth than streaming an HD video.\n </div>\n </section>\n <footer class=\"src-modal__footer\">\n <src-button\n (onClick)=\"closeModalWithCirrusDisconnect()\"\n [data-testid]=\"'close-webrtc-error-modal'\"\n [colorScheme]=\"'primary'\"\n >\n Ok\n </src-button>\n </footer>\n</div>\n", styles: [".src-modal{--modalBodyPadding: 20px 8px 20px 20px;display:grid;grid-template-columns:minmax(0,1fr);grid-template-rows:auto minmax(0,1fr) auto}.src-modal ::ng-deep .ng-scroll-content{--_scrollbar-content-width: initial;--_viewport-padding-right: 12px}.src-modal__body{width:100%}.src-modal__body p{color:var(--src-color-bg-default, #1f2937);font-size:14px;font-style:normal;font-weight:400;line-height:24px;margin-top:0}.src-modal__body a{word-wrap:break-word;white-space:normal}\n"] }]
4565
4762
  }] });
@@ -4603,10 +4800,10 @@ class FilterSettingsComponent {
4603
4800
  panelOpen: this.settings.panelOpen,
4604
4801
  });
4605
4802
  }
4606
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.1", ngImport: i0, type: FilterSettingsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
4607
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.2.1", type: FilterSettingsComponent, isStandalone: true, selector: "app-filter-settings", ngImport: i0, template: "<div class=\"settings-container\">\n <button (click)=\"togglePanel()\" class=\"gear-button\">LBM</button>\n @if (settings.panelOpen) {\n <div class=\"settings-panel\">\n <h3>LBM Trigger Settings</h3>\n <h5>Data Flow Monitor</h5>\n <form>\n <label>\n Monitoring delay:\n <input\n [(ngModel)]=\"settings.monitoringDelayTime\"\n [placeholder]=\"defaultFilterModel.monitoringDelayTime\"\n type=\"number\"\n name=\"monitoringDelayTime\"\n />\n </label>\n\n <label>\n Minimum Bitrate (kbit/s):\n <input\n [(ngModel)]=\"settings.minimumBitrate\"\n [placeholder]=\"defaultFilterModel.minimumBitrate\"\n type=\"number\"\n name=\"minimumBitrate\"\n />\n </label>\n <label>\n Yellow Flag (%):\n <input\n [(ngModel)]=\"settings.yellowFlag\"\n [placeholder]=\"defaultFilterModel.yellowFlag\"\n type=\"number\"\n name=\"yellowFlag\"\n />\n </label>\n <label>\n Red Flag (%):\n <input\n [(ngModel)]=\"settings.redFlag\"\n [placeholder]=\"defaultFilterModel.redFlag\"\n type=\"number\"\n name=\"redFlag\"\n />\n </label>\n <label>\n Minimum FPS:\n <input\n [(ngModel)]=\"settings.minimumFps\"\n [placeholder]=\"defaultFilterModel.minimumFps\"\n type=\"number\"\n name=\"minimumFps\"\n />\n </label>\n <hr />\n <h5>Kalman Filter</h5>\n <label>\n Initial Bitrate Estimate (kbit/s):\n <input\n [(ngModel)]=\"settings.initialBitrateEstimate\"\n [placeholder]=\"defaultFilterModel.initialBitrateEstimate\"\n type=\"number\"\n name=\"initialBitrateEstimate\"\n />\n </label>\n <label>\n Initial Error Covariance:\n <input\n [(ngModel)]=\"settings.initialErrorCovariance\"\n [placeholder]=\"defaultFilterModel.initialErrorCovariance\"\n type=\"number\"\n name=\"initialErrorCovariance\"\n />\n </label>\n <label>\n Process Noise (Q):\n <input\n [(ngModel)]=\"settings.processNoise\"\n [placeholder]=\"defaultFilterModel.processNoise\"\n type=\"number\"\n name=\"processNoise\"\n />\n </label>\n <label>\n Measurement Noise (R):\n <input\n [(ngModel)]=\"settings.measurementNoise\"\n [placeholder]=\"defaultFilterModel.measurementNoise\"\n type=\"number\"\n name=\"measurementNoise\"\n />\n </label>\n </form>\n <br />\n <br />\n <div class=\"apply-button-container\">\n <button (click)=\"reset()\">Reset</button>\n <button (click)=\"saveSettings()\">Apply</button>\n </div>\n </div>\n }\n</div>\n", styles: [".settings-container{position:absolute;top:65px;right:10px;z-index:1000}.gear-button{right:0;width:50px;position:absolute;cursor:pointer;font-size:10px;background:none;font-weight:500;border:1px solid;border-radius:9px;background:#0162cc;color:#fff;padding:4px}.gear-button>*{color:#e6f419;filter:drop-shadow(1px 1px 1px rgb(0,0,0))}.settings-panel{font-size:13px;background:#fff;border:1px solid #ccc;padding:15px;margin-top:25px;border-radius:4px;box-shadow:0 2px 8px #0003}.settings-panel h3{margin-top:0}.settings-panel form{display:flex;flex-direction:column}.settings-panel label{margin-bottom:10px;display:flex;flex-direction:column}.settings-panel input{padding:4px;margin-top:4px;border:1px solid #ccc;border-radius:2px}.apply-button-container{position:absolute;bottom:15px;right:15px}.apply-button-container button{padding:6px 12px;border:none;background-color:#1976d2;color:#fff;border-radius:4px;cursor:pointer;margin:2px}.apply-button-container button:hover{background-color:#1565c0}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i1.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
4803
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.4", ngImport: i0, type: FilterSettingsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
4804
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.2.4", type: FilterSettingsComponent, isStandalone: true, selector: "app-filter-settings", ngImport: i0, template: "<div class=\"settings-container\">\n <button (click)=\"togglePanel()\" class=\"gear-button\">LBM</button>\n @if (settings.panelOpen) {\n <div class=\"settings-panel\">\n <h3>LBM Trigger Settings</h3>\n <h5>Data Flow Monitor</h5>\n <form>\n <label>\n Monitoring delay:\n <input\n [(ngModel)]=\"settings.monitoringDelayTime\"\n [placeholder]=\"defaultFilterModel.monitoringDelayTime\"\n type=\"number\"\n name=\"monitoringDelayTime\"\n />\n </label>\n\n <label>\n Minimum Bitrate (kbit/s):\n <input\n [(ngModel)]=\"settings.minimumBitrate\"\n [placeholder]=\"defaultFilterModel.minimumBitrate\"\n type=\"number\"\n name=\"minimumBitrate\"\n />\n </label>\n <label>\n Yellow Flag (%):\n <input\n [(ngModel)]=\"settings.yellowFlag\"\n [placeholder]=\"defaultFilterModel.yellowFlag\"\n type=\"number\"\n name=\"yellowFlag\"\n />\n </label>\n <label>\n Red Flag (%):\n <input\n [(ngModel)]=\"settings.redFlag\"\n [placeholder]=\"defaultFilterModel.redFlag\"\n type=\"number\"\n name=\"redFlag\"\n />\n </label>\n <label>\n Minimum FPS:\n <input\n [(ngModel)]=\"settings.minimumFps\"\n [placeholder]=\"defaultFilterModel.minimumFps\"\n type=\"number\"\n name=\"minimumFps\"\n />\n </label>\n <hr />\n <h5>Kalman Filter</h5>\n <label>\n Initial Bitrate Estimate (kbit/s):\n <input\n [(ngModel)]=\"settings.initialBitrateEstimate\"\n [placeholder]=\"defaultFilterModel.initialBitrateEstimate\"\n type=\"number\"\n name=\"initialBitrateEstimate\"\n />\n </label>\n <label>\n Initial Error Covariance:\n <input\n [(ngModel)]=\"settings.initialErrorCovariance\"\n [placeholder]=\"defaultFilterModel.initialErrorCovariance\"\n type=\"number\"\n name=\"initialErrorCovariance\"\n />\n </label>\n <label>\n Process Noise (Q):\n <input\n [(ngModel)]=\"settings.processNoise\"\n [placeholder]=\"defaultFilterModel.processNoise\"\n type=\"number\"\n name=\"processNoise\"\n />\n </label>\n <label>\n Measurement Noise (R):\n <input\n [(ngModel)]=\"settings.measurementNoise\"\n [placeholder]=\"defaultFilterModel.measurementNoise\"\n type=\"number\"\n name=\"measurementNoise\"\n />\n </label>\n </form>\n <br />\n <br />\n <div class=\"apply-button-container\">\n <button (click)=\"reset()\">Reset</button>\n <button (click)=\"saveSettings()\">Apply</button>\n </div>\n </div>\n }\n</div>\n", styles: [".settings-container{position:absolute;top:65px;right:10px;z-index:1000}.gear-button{right:0;width:50px;position:absolute;cursor:pointer;font-size:10px;background:none;font-weight:500;border:1px solid;border-radius:9px;background:#0162cc;color:#fff;padding:4px}.gear-button>*{color:#e6f419;filter:drop-shadow(1px 1px 1px rgb(0,0,0))}.settings-panel{font-size:13px;background:#fff;border:1px solid #ccc;padding:15px;margin-top:25px;border-radius:4px;box-shadow:0 2px 8px #0003}.settings-panel h3{margin-top:0}.settings-panel form{display:flex;flex-direction:column}.settings-panel label{margin-bottom:10px;display:flex;flex-direction:column}.settings-panel input{padding:4px;margin-top:4px;border:1px solid #ccc;border-radius:2px}.apply-button-container{position:absolute;bottom:15px;right:15px}.apply-button-container button{padding:6px 12px;border:none;background-color:#1976d2;color:#fff;border-radius:4px;cursor:pointer;margin:2px}.apply-button-container button:hover{background-color:#1565c0}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i1.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
4608
4805
  }
4609
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.1", ngImport: i0, type: FilterSettingsComponent, decorators: [{
4806
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.4", ngImport: i0, type: FilterSettingsComponent, decorators: [{
4610
4807
  type: Component,
4611
4808
  args: [{ selector: 'app-filter-settings', imports: [FormsModule], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"settings-container\">\n <button (click)=\"togglePanel()\" class=\"gear-button\">LBM</button>\n @if (settings.panelOpen) {\n <div class=\"settings-panel\">\n <h3>LBM Trigger Settings</h3>\n <h5>Data Flow Monitor</h5>\n <form>\n <label>\n Monitoring delay:\n <input\n [(ngModel)]=\"settings.monitoringDelayTime\"\n [placeholder]=\"defaultFilterModel.monitoringDelayTime\"\n type=\"number\"\n name=\"monitoringDelayTime\"\n />\n </label>\n\n <label>\n Minimum Bitrate (kbit/s):\n <input\n [(ngModel)]=\"settings.minimumBitrate\"\n [placeholder]=\"defaultFilterModel.minimumBitrate\"\n type=\"number\"\n name=\"minimumBitrate\"\n />\n </label>\n <label>\n Yellow Flag (%):\n <input\n [(ngModel)]=\"settings.yellowFlag\"\n [placeholder]=\"defaultFilterModel.yellowFlag\"\n type=\"number\"\n name=\"yellowFlag\"\n />\n </label>\n <label>\n Red Flag (%):\n <input\n [(ngModel)]=\"settings.redFlag\"\n [placeholder]=\"defaultFilterModel.redFlag\"\n type=\"number\"\n name=\"redFlag\"\n />\n </label>\n <label>\n Minimum FPS:\n <input\n [(ngModel)]=\"settings.minimumFps\"\n [placeholder]=\"defaultFilterModel.minimumFps\"\n type=\"number\"\n name=\"minimumFps\"\n />\n </label>\n <hr />\n <h5>Kalman Filter</h5>\n <label>\n Initial Bitrate Estimate (kbit/s):\n <input\n [(ngModel)]=\"settings.initialBitrateEstimate\"\n [placeholder]=\"defaultFilterModel.initialBitrateEstimate\"\n type=\"number\"\n name=\"initialBitrateEstimate\"\n />\n </label>\n <label>\n Initial Error Covariance:\n <input\n [(ngModel)]=\"settings.initialErrorCovariance\"\n [placeholder]=\"defaultFilterModel.initialErrorCovariance\"\n type=\"number\"\n name=\"initialErrorCovariance\"\n />\n </label>\n <label>\n Process Noise (Q):\n <input\n [(ngModel)]=\"settings.processNoise\"\n [placeholder]=\"defaultFilterModel.processNoise\"\n type=\"number\"\n name=\"processNoise\"\n />\n </label>\n <label>\n Measurement Noise (R):\n <input\n [(ngModel)]=\"settings.measurementNoise\"\n [placeholder]=\"defaultFilterModel.measurementNoise\"\n type=\"number\"\n name=\"measurementNoise\"\n />\n </label>\n </form>\n <br />\n <br />\n <div class=\"apply-button-container\">\n <button (click)=\"reset()\">Reset</button>\n <button (click)=\"saveSettings()\">Apply</button>\n </div>\n </div>\n }\n</div>\n", styles: [".settings-container{position:absolute;top:65px;right:10px;z-index:1000}.gear-button{right:0;width:50px;position:absolute;cursor:pointer;font-size:10px;background:none;font-weight:500;border:1px solid;border-radius:9px;background:#0162cc;color:#fff;padding:4px}.gear-button>*{color:#e6f419;filter:drop-shadow(1px 1px 1px rgb(0,0,0))}.settings-panel{font-size:13px;background:#fff;border:1px solid #ccc;padding:15px;margin-top:25px;border-radius:4px;box-shadow:0 2px 8px #0003}.settings-panel h3{margin-top:0}.settings-panel form{display:flex;flex-direction:column}.settings-panel label{margin-bottom:10px;display:flex;flex-direction:column}.settings-panel input{padding:4px;margin-top:4px;border:1px solid #ccc;border-radius:2px}.apply-button-container{position:absolute;bottom:15px;right:15px}.apply-button-container button{padding:6px 12px;border:none;background-color:#1976d2;color:#fff;border-radius:4px;cursor:pointer;margin:2px}.apply-button-container button:hover{background-color:#1565c0}\n"] }]
4612
4809
  }] });
@@ -4711,10 +4908,10 @@ class LowBandwidthDetectorComponent {
4711
4908
  this.store.dispatch(changeLowBandwidth({ lowBandwidth: false }));
4712
4909
  });
4713
4910
  }
4714
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.1", ngImport: i0, type: LowBandwidthDetectorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
4715
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.2.1", type: LowBandwidthDetectorComponent, isStandalone: true, selector: "app-low-bandwidth-detector", ngImport: i0, template: "@if (isReducedQuality() || isLowBandwidth()) {\n <div\n [class.expanded]=\"isIndicatorExpanded() && isLowBandwidth()\"\n class=\"lbm-indicator freeze-loader\"\n >\n <div (click)=\"toggleIndicator(true)\" class=\"lbm-icon\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 20 20\">\n <path\n fill=\"#85888E\"\n d=\"M7.189 3.605c-.73.145-1.438.35-2.126.614A14.412 14.412 0 0 0 .896 6.666a1.08 1.08 0 0 0-.375.844c0 .34.118.629.354.865s.524.36.865.375c.34.014.65-.09.927-.313a11.89 11.89 0 0 1 3.385-1.916 10.94 10.94 0 0 1 1.235-.375l-.098-2.541ZM7.385 8.708a9.107 9.107 0 0 0-2.906 1.48c-.264.194-.402.464-.416.812-.014.347.104.646.354.896.236.236.524.364.864.385.34.02.664-.073.97-.281.422-.29.878-.53 1.368-.721a2.545 2.545 0 0 1-.166-.814l-.068-1.757ZM12.386 11.267c.094-.25.15-.52.161-.802l.068-1.755a9.019 9.019 0 0 1 2.927 1.52c.264.193.4.46.406.801.007.34-.114.635-.364.885a1.213 1.213 0 0 1-.865.365A1.614 1.614 0 0 1 13.77 12a6.574 6.574 0 0 0-1.385-.733ZM12.713 6.146l.098-2.542c.73.146 1.438.351 2.127.615 1.541.59 2.93 1.406 4.166 2.447.25.223.379.5.386.834.007.333-.115.625-.365.875a1.253 1.253 0 0 1-.864.375c-.34.014-.65-.09-.927-.313a11.892 11.892 0 0 0-3.386-1.916 10.94 10.94 0 0 0-1.235-.375ZM8.813 16.187c.32.32.715.48 1.187.48.472 0 .868-.16 1.188-.48.32-.32.479-.715.479-1.187 0-.473-.16-.868-.48-1.188-.319-.32-.715-.479-1.187-.479-.472 0-.868.16-1.187.48-.32.319-.48.714-.48 1.187 0 .472.16.868.48 1.187Z\"\n />\n <path\n fill=\"#fff\"\n fill-rule=\"evenodd\"\n d=\"M10 .833c-.91 0-1.637.756-1.602 1.665l.304 7.92a1.299 1.299 0 0 0 2.596 0l.305-7.92A1.604 1.604 0 0 0 10 .833ZM8.813 16.187c.32.32.715.48 1.187.48.472 0 .868-.16 1.188-.48.32-.32.479-.715.479-1.187 0-.473-.16-.868-.48-1.188-.319-.32-.715-.479-1.187-.479-.472 0-.868.16-1.187.48-.32.319-.48.714-.48 1.187 0 .472.16.868.48 1.187Z\"\n clip-rule=\"evenodd\"\n />\n </svg>\n </div>\n\n <div\n [class.lbm-message--open]=\"isLowBandwidth() && isIndicatorExpanded()\"\n class=\"lbm-message\"\n >\n <p class=\"lbm-description\">\n Fluid Interactivity Modes were disabled due to an unstable connection.\n\n <button\n (click)=\"openLBMDialog()\"\n [attr.data-testid]=\"'learn-more-lbm'\"\n type=\"button\"\n class=\"lbm-learn-more\"\n >\n Learn more\n </button>\n </p>\n <button\n (click)=\"toggleIndicator(false)\"\n [attr.data-testid]=\"'close-lbm-indicator'\"\n type=\"button\"\n class=\"lbm-close\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 20 20\"\n fill=\"none\"\n >\n <path\n d=\"M10.0001 11.2289L6.68618 14.5428C6.51951 14.7095 6.31818 14.7895 6.08218 14.7828C5.84618 14.7755 5.64485 14.6885 5.47818 14.5218C5.31151 14.3552 5.22818 14.1505 5.22818 13.9078C5.22818 13.6645 5.31151 13.4595 5.47818 13.2928L8.77107 9.99992L5.45718 6.68603C5.29051 6.51936 5.21051 6.3147 5.21718 6.07203C5.22451 5.8287 5.31151 5.6237 5.47818 5.45703C5.64485 5.29036 5.84951 5.20703 6.09218 5.20703C6.33551 5.20703 6.54051 5.29036 6.70718 5.45703L10.0001 8.77092L13.314 5.45703C13.4806 5.29036 13.6853 5.20703 13.928 5.20703C14.1713 5.20703 14.3763 5.29036 14.543 5.45703C14.7096 5.6237 14.793 5.8287 14.793 6.07203C14.793 6.3147 14.7096 6.51936 14.543 6.68603L11.2291 9.99992L14.543 13.3138C14.7096 13.4805 14.793 13.6818 14.793 13.9178C14.793 14.1538 14.7096 14.3552 14.543 14.5218C14.3763 14.6885 14.1713 14.7718 13.928 14.7718C13.6853 14.7718 13.4806 14.6885 13.314 14.5218L10.0001 11.2289Z\"\n fill=\"white\"\n />\n </svg>\n </button>\n </div>\n </div>\n}\n\n@if (devModeService.isDevMode) {\n <app-filter-settings />\n}\n", styles: [".freeze-loader,.lbm-indicator{--lbmPositionTop: 18px;--lbmPositionLeft: 18px;--lbmPositionRight: 18px;--lbmIndicatorSize: 36px;--lbmIndicatorBorderRadius: 8px;--lbmIndicatorCloseSize: 20px;--lbmPadding: 10px;--lbmTextSize: 13px;--lbmLineHeight: 20px;--lbmTextColor: #ffffff;--lbmBackgroundColor: rgba(17, 24, 39, .7);position:absolute;top:var(--lbmPositionTop);left:var(--lbmPositionLeft);z-index:6;display:flex;justify-content:center;align-items:flex-start;min-width:var(--lbmIndicatorSize);min-height:var(--lbmIndicatorSize);overflow:hidden}.freeze-loader.expanded,.lbm-indicator.expanded{--lbmPositionTop: 8px;--lbmPositionLeft: 8px;--lbmPositionRight: 8px;width:auto;max-width:calc(100% - var(--lbmPositionLeft) - var(--lbmPositionRight));padding:var(--lbmPadding);background:var(--lbmBackgroundColor);-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);border-radius:var(--lbmIndicatorBorderRadius);gap:12px}.freeze-loader .lbm-icon,.lbm-indicator .lbm-icon{display:flex;width:var(--lbmIndicatorSize);height:var(--lbmIndicatorSize);padding:8px;color:#fff;background-color:var(--lbmBackgroundColor);border-radius:50%;flex-shrink:0;cursor:pointer}.freeze-loader .lbm-icon svg,.freeze-loader .lbm-icon img,.lbm-indicator .lbm-icon svg,.lbm-indicator .lbm-icon img{width:100%;height:100%}.freeze-loader .lbm-close,.lbm-indicator .lbm-close{position:absolute;top:0;right:0;width:var(--lbmIndicatorCloseSize);height:var(--lbmIndicatorCloseSize);background-color:transparent;border:none;padding:0;cursor:pointer}.freeze-loader .lbm-message,.lbm-indicator .lbm-message{position:relative;opacity:0;height:0;max-width:0;padding-right:24px;pointer-events:none;visibility:hidden;animation:closeMessage .3s forwards}.freeze-loader .lbm-message--open,.lbm-indicator .lbm-message--open{position:relative;visibility:visible;display:flex;align-items:center;align-self:center;pointer-events:all;gap:12px;max-width:fit-content;height:auto;opacity:1;animation:openMessage .3s forwards}.freeze-loader .lbm-description,.lbm-indicator .lbm-description{margin:0;font-size:var(--lbmTextSize);font-weight:400;line-height:var(--lbmLineHeight);color:var(--lbmTextColor)}.freeze-loader .lbm-learn-more,.lbm-indicator .lbm-learn-more{display:inline-flex;padding:0;font-size:var(--lbmTextSize);font-weight:400;line-height:var(--lbmLineHeight);color:var(--lbmTextColor);-webkit-text-decoration-line:underline;text-decoration-line:underline;background-color:transparent;border:none;cursor:pointer}.freeze-loader .lbm-learn-more:hover,.lbm-indicator .lbm-learn-more:hover{text-decoration:none}@keyframes openMessage{0%{opacity:0;max-width:0;height:0}10%{height:auto;max-width:fit-content}to{opacity:1;height:auto;max-width:fit-content}}@keyframes closeMessage{0%{opacity:1;max-width:fit-content}to{opacity:0;max-width:0}}\n"], dependencies: [{ kind: "component", type: FilterSettingsComponent, selector: "app-filter-settings" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
4911
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.4", ngImport: i0, type: LowBandwidthDetectorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
4912
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.2.4", type: LowBandwidthDetectorComponent, isStandalone: true, selector: "app-low-bandwidth-detector", ngImport: i0, template: "@if (isReducedQuality() || isLowBandwidth()) {\n <div\n [class.expanded]=\"isIndicatorExpanded() && isLowBandwidth()\"\n class=\"lbm-indicator freeze-loader\"\n >\n <div (click)=\"toggleIndicator(true)\" class=\"lbm-icon\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 20 20\">\n <path\n fill=\"#85888E\"\n d=\"M7.189 3.605c-.73.145-1.438.35-2.126.614A14.412 14.412 0 0 0 .896 6.666a1.08 1.08 0 0 0-.375.844c0 .34.118.629.354.865s.524.36.865.375c.34.014.65-.09.927-.313a11.89 11.89 0 0 1 3.385-1.916 10.94 10.94 0 0 1 1.235-.375l-.098-2.541ZM7.385 8.708a9.107 9.107 0 0 0-2.906 1.48c-.264.194-.402.464-.416.812-.014.347.104.646.354.896.236.236.524.364.864.385.34.02.664-.073.97-.281.422-.29.878-.53 1.368-.721a2.545 2.545 0 0 1-.166-.814l-.068-1.757ZM12.386 11.267c.094-.25.15-.52.161-.802l.068-1.755a9.019 9.019 0 0 1 2.927 1.52c.264.193.4.46.406.801.007.34-.114.635-.364.885a1.213 1.213 0 0 1-.865.365A1.614 1.614 0 0 1 13.77 12a6.574 6.574 0 0 0-1.385-.733ZM12.713 6.146l.098-2.542c.73.146 1.438.351 2.127.615 1.541.59 2.93 1.406 4.166 2.447.25.223.379.5.386.834.007.333-.115.625-.365.875a1.253 1.253 0 0 1-.864.375c-.34.014-.65-.09-.927-.313a11.892 11.892 0 0 0-3.386-1.916 10.94 10.94 0 0 0-1.235-.375ZM8.813 16.187c.32.32.715.48 1.187.48.472 0 .868-.16 1.188-.48.32-.32.479-.715.479-1.187 0-.473-.16-.868-.48-1.188-.319-.32-.715-.479-1.187-.479-.472 0-.868.16-1.187.48-.32.319-.48.714-.48 1.187 0 .472.16.868.48 1.187Z\"\n />\n <path\n fill=\"#fff\"\n fill-rule=\"evenodd\"\n d=\"M10 .833c-.91 0-1.637.756-1.602 1.665l.304 7.92a1.299 1.299 0 0 0 2.596 0l.305-7.92A1.604 1.604 0 0 0 10 .833ZM8.813 16.187c.32.32.715.48 1.187.48.472 0 .868-.16 1.188-.48.32-.32.479-.715.479-1.187 0-.473-.16-.868-.48-1.188-.319-.32-.715-.479-1.187-.479-.472 0-.868.16-1.187.48-.32.319-.48.714-.48 1.187 0 .472.16.868.48 1.187Z\"\n clip-rule=\"evenodd\"\n />\n </svg>\n </div>\n\n <div\n [class.lbm-message--open]=\"isLowBandwidth() && isIndicatorExpanded()\"\n class=\"lbm-message\"\n >\n <p class=\"lbm-description\">\n Fluid Interactivity Modes were disabled due to an unstable connection.\n\n <button\n (click)=\"openLBMDialog()\"\n [attr.data-testid]=\"'learn-more-lbm'\"\n type=\"button\"\n class=\"lbm-learn-more\"\n >\n Learn more\n </button>\n </p>\n <button\n (click)=\"toggleIndicator(false)\"\n [attr.data-testid]=\"'close-lbm-indicator'\"\n type=\"button\"\n class=\"lbm-close\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 20 20\"\n fill=\"none\"\n >\n <path\n d=\"M10.0001 11.2289L6.68618 14.5428C6.51951 14.7095 6.31818 14.7895 6.08218 14.7828C5.84618 14.7755 5.64485 14.6885 5.47818 14.5218C5.31151 14.3552 5.22818 14.1505 5.22818 13.9078C5.22818 13.6645 5.31151 13.4595 5.47818 13.2928L8.77107 9.99992L5.45718 6.68603C5.29051 6.51936 5.21051 6.3147 5.21718 6.07203C5.22451 5.8287 5.31151 5.6237 5.47818 5.45703C5.64485 5.29036 5.84951 5.20703 6.09218 5.20703C6.33551 5.20703 6.54051 5.29036 6.70718 5.45703L10.0001 8.77092L13.314 5.45703C13.4806 5.29036 13.6853 5.20703 13.928 5.20703C14.1713 5.20703 14.3763 5.29036 14.543 5.45703C14.7096 5.6237 14.793 5.8287 14.793 6.07203C14.793 6.3147 14.7096 6.51936 14.543 6.68603L11.2291 9.99992L14.543 13.3138C14.7096 13.4805 14.793 13.6818 14.793 13.9178C14.793 14.1538 14.7096 14.3552 14.543 14.5218C14.3763 14.6885 14.1713 14.7718 13.928 14.7718C13.6853 14.7718 13.4806 14.6885 13.314 14.5218L10.0001 11.2289Z\"\n fill=\"white\"\n />\n </svg>\n </button>\n </div>\n </div>\n}\n\n@if (devModeService.isDevMode) {\n <app-filter-settings />\n}\n", styles: [".freeze-loader,.lbm-indicator{--lbmPositionTop: 18px;--lbmPositionLeft: 18px;--lbmPositionRight: 18px;--lbmIndicatorSize: 36px;--lbmIndicatorBorderRadius: 8px;--lbmIndicatorCloseSize: 20px;--lbmPadding: 10px;--lbmTextSize: 13px;--lbmLineHeight: 20px;--lbmTextColor: #ffffff;--lbmBackgroundColor: rgba(17, 24, 39, .7);position:absolute;top:var(--lbmPositionTop);left:var(--lbmPositionLeft);z-index:6;display:flex;justify-content:center;align-items:flex-start;min-width:var(--lbmIndicatorSize);min-height:var(--lbmIndicatorSize);overflow:hidden}.freeze-loader.expanded,.lbm-indicator.expanded{--lbmPositionTop: 8px;--lbmPositionLeft: 8px;--lbmPositionRight: 8px;width:auto;max-width:calc(100% - var(--lbmPositionLeft) - var(--lbmPositionRight));padding:var(--lbmPadding);background:var(--lbmBackgroundColor);-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);border-radius:var(--lbmIndicatorBorderRadius);gap:12px}.freeze-loader .lbm-icon,.lbm-indicator .lbm-icon{display:flex;width:var(--lbmIndicatorSize);height:var(--lbmIndicatorSize);padding:8px;color:#fff;background-color:var(--lbmBackgroundColor);border-radius:50%;flex-shrink:0;cursor:pointer}.freeze-loader .lbm-icon svg,.freeze-loader .lbm-icon img,.lbm-indicator .lbm-icon svg,.lbm-indicator .lbm-icon img{width:100%;height:100%}.freeze-loader .lbm-close,.lbm-indicator .lbm-close{position:absolute;top:0;right:0;width:var(--lbmIndicatorCloseSize);height:var(--lbmIndicatorCloseSize);background-color:transparent;border:none;padding:0;cursor:pointer}.freeze-loader .lbm-message,.lbm-indicator .lbm-message{position:relative;opacity:0;height:0;max-width:0;padding-right:24px;pointer-events:none;visibility:hidden;animation:closeMessage .3s forwards}.freeze-loader .lbm-message--open,.lbm-indicator .lbm-message--open{position:relative;visibility:visible;display:flex;align-items:center;align-self:center;pointer-events:all;gap:12px;max-width:fit-content;height:auto;opacity:1;animation:openMessage .3s forwards}.freeze-loader .lbm-description,.lbm-indicator .lbm-description{margin:0;font-size:var(--lbmTextSize);font-weight:400;line-height:var(--lbmLineHeight);color:var(--lbmTextColor)}.freeze-loader .lbm-learn-more,.lbm-indicator .lbm-learn-more{display:inline-flex;padding:0;font-size:var(--lbmTextSize);font-weight:400;line-height:var(--lbmLineHeight);color:var(--lbmTextColor);-webkit-text-decoration-line:underline;text-decoration-line:underline;background-color:transparent;border:none;cursor:pointer}.freeze-loader .lbm-learn-more:hover,.lbm-indicator .lbm-learn-more:hover{text-decoration:none}@keyframes openMessage{0%{opacity:0;max-width:0;height:0}10%{height:auto;max-width:fit-content}to{opacity:1;height:auto;max-width:fit-content}}@keyframes closeMessage{0%{opacity:1;max-width:fit-content}to{opacity:0;max-width:0}}\n"], dependencies: [{ kind: "component", type: FilterSettingsComponent, selector: "app-filter-settings" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
4716
4913
  }
4717
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.1", ngImport: i0, type: LowBandwidthDetectorComponent, decorators: [{
4914
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.4", ngImport: i0, type: LowBandwidthDetectorComponent, decorators: [{
4718
4915
  type: Component,
4719
4916
  args: [{ selector: 'app-low-bandwidth-detector', changeDetection: ChangeDetectionStrategy.OnPush, imports: [FilterSettingsComponent], template: "@if (isReducedQuality() || isLowBandwidth()) {\n <div\n [class.expanded]=\"isIndicatorExpanded() && isLowBandwidth()\"\n class=\"lbm-indicator freeze-loader\"\n >\n <div (click)=\"toggleIndicator(true)\" class=\"lbm-icon\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 20 20\">\n <path\n fill=\"#85888E\"\n d=\"M7.189 3.605c-.73.145-1.438.35-2.126.614A14.412 14.412 0 0 0 .896 6.666a1.08 1.08 0 0 0-.375.844c0 .34.118.629.354.865s.524.36.865.375c.34.014.65-.09.927-.313a11.89 11.89 0 0 1 3.385-1.916 10.94 10.94 0 0 1 1.235-.375l-.098-2.541ZM7.385 8.708a9.107 9.107 0 0 0-2.906 1.48c-.264.194-.402.464-.416.812-.014.347.104.646.354.896.236.236.524.364.864.385.34.02.664-.073.97-.281.422-.29.878-.53 1.368-.721a2.545 2.545 0 0 1-.166-.814l-.068-1.757ZM12.386 11.267c.094-.25.15-.52.161-.802l.068-1.755a9.019 9.019 0 0 1 2.927 1.52c.264.193.4.46.406.801.007.34-.114.635-.364.885a1.213 1.213 0 0 1-.865.365A1.614 1.614 0 0 1 13.77 12a6.574 6.574 0 0 0-1.385-.733ZM12.713 6.146l.098-2.542c.73.146 1.438.351 2.127.615 1.541.59 2.93 1.406 4.166 2.447.25.223.379.5.386.834.007.333-.115.625-.365.875a1.253 1.253 0 0 1-.864.375c-.34.014-.65-.09-.927-.313a11.892 11.892 0 0 0-3.386-1.916 10.94 10.94 0 0 0-1.235-.375ZM8.813 16.187c.32.32.715.48 1.187.48.472 0 .868-.16 1.188-.48.32-.32.479-.715.479-1.187 0-.473-.16-.868-.48-1.188-.319-.32-.715-.479-1.187-.479-.472 0-.868.16-1.187.48-.32.319-.48.714-.48 1.187 0 .472.16.868.48 1.187Z\"\n />\n <path\n fill=\"#fff\"\n fill-rule=\"evenodd\"\n d=\"M10 .833c-.91 0-1.637.756-1.602 1.665l.304 7.92a1.299 1.299 0 0 0 2.596 0l.305-7.92A1.604 1.604 0 0 0 10 .833ZM8.813 16.187c.32.32.715.48 1.187.48.472 0 .868-.16 1.188-.48.32-.32.479-.715.479-1.187 0-.473-.16-.868-.48-1.188-.319-.32-.715-.479-1.187-.479-.472 0-.868.16-1.187.48-.32.319-.48.714-.48 1.187 0 .472.16.868.48 1.187Z\"\n clip-rule=\"evenodd\"\n />\n </svg>\n </div>\n\n <div\n [class.lbm-message--open]=\"isLowBandwidth() && isIndicatorExpanded()\"\n class=\"lbm-message\"\n >\n <p class=\"lbm-description\">\n Fluid Interactivity Modes were disabled due to an unstable connection.\n\n <button\n (click)=\"openLBMDialog()\"\n [attr.data-testid]=\"'learn-more-lbm'\"\n type=\"button\"\n class=\"lbm-learn-more\"\n >\n Learn more\n </button>\n </p>\n <button\n (click)=\"toggleIndicator(false)\"\n [attr.data-testid]=\"'close-lbm-indicator'\"\n type=\"button\"\n class=\"lbm-close\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 20 20\"\n fill=\"none\"\n >\n <path\n d=\"M10.0001 11.2289L6.68618 14.5428C6.51951 14.7095 6.31818 14.7895 6.08218 14.7828C5.84618 14.7755 5.64485 14.6885 5.47818 14.5218C5.31151 14.3552 5.22818 14.1505 5.22818 13.9078C5.22818 13.6645 5.31151 13.4595 5.47818 13.2928L8.77107 9.99992L5.45718 6.68603C5.29051 6.51936 5.21051 6.3147 5.21718 6.07203C5.22451 5.8287 5.31151 5.6237 5.47818 5.45703C5.64485 5.29036 5.84951 5.20703 6.09218 5.20703C6.33551 5.20703 6.54051 5.29036 6.70718 5.45703L10.0001 8.77092L13.314 5.45703C13.4806 5.29036 13.6853 5.20703 13.928 5.20703C14.1713 5.20703 14.3763 5.29036 14.543 5.45703C14.7096 5.6237 14.793 5.8287 14.793 6.07203C14.793 6.3147 14.7096 6.51936 14.543 6.68603L11.2291 9.99992L14.543 13.3138C14.7096 13.4805 14.793 13.6818 14.793 13.9178C14.793 14.1538 14.7096 14.3552 14.543 14.5218C14.3763 14.6885 14.1713 14.7718 13.928 14.7718C13.6853 14.7718 13.4806 14.6885 13.314 14.5218L10.0001 11.2289Z\"\n fill=\"white\"\n />\n </svg>\n </button>\n </div>\n </div>\n}\n\n@if (devModeService.isDevMode) {\n <app-filter-settings />\n}\n", styles: [".freeze-loader,.lbm-indicator{--lbmPositionTop: 18px;--lbmPositionLeft: 18px;--lbmPositionRight: 18px;--lbmIndicatorSize: 36px;--lbmIndicatorBorderRadius: 8px;--lbmIndicatorCloseSize: 20px;--lbmPadding: 10px;--lbmTextSize: 13px;--lbmLineHeight: 20px;--lbmTextColor: #ffffff;--lbmBackgroundColor: rgba(17, 24, 39, .7);position:absolute;top:var(--lbmPositionTop);left:var(--lbmPositionLeft);z-index:6;display:flex;justify-content:center;align-items:flex-start;min-width:var(--lbmIndicatorSize);min-height:var(--lbmIndicatorSize);overflow:hidden}.freeze-loader.expanded,.lbm-indicator.expanded{--lbmPositionTop: 8px;--lbmPositionLeft: 8px;--lbmPositionRight: 8px;width:auto;max-width:calc(100% - var(--lbmPositionLeft) - var(--lbmPositionRight));padding:var(--lbmPadding);background:var(--lbmBackgroundColor);-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);border-radius:var(--lbmIndicatorBorderRadius);gap:12px}.freeze-loader .lbm-icon,.lbm-indicator .lbm-icon{display:flex;width:var(--lbmIndicatorSize);height:var(--lbmIndicatorSize);padding:8px;color:#fff;background-color:var(--lbmBackgroundColor);border-radius:50%;flex-shrink:0;cursor:pointer}.freeze-loader .lbm-icon svg,.freeze-loader .lbm-icon img,.lbm-indicator .lbm-icon svg,.lbm-indicator .lbm-icon img{width:100%;height:100%}.freeze-loader .lbm-close,.lbm-indicator .lbm-close{position:absolute;top:0;right:0;width:var(--lbmIndicatorCloseSize);height:var(--lbmIndicatorCloseSize);background-color:transparent;border:none;padding:0;cursor:pointer}.freeze-loader .lbm-message,.lbm-indicator .lbm-message{position:relative;opacity:0;height:0;max-width:0;padding-right:24px;pointer-events:none;visibility:hidden;animation:closeMessage .3s forwards}.freeze-loader .lbm-message--open,.lbm-indicator .lbm-message--open{position:relative;visibility:visible;display:flex;align-items:center;align-self:center;pointer-events:all;gap:12px;max-width:fit-content;height:auto;opacity:1;animation:openMessage .3s forwards}.freeze-loader .lbm-description,.lbm-indicator .lbm-description{margin:0;font-size:var(--lbmTextSize);font-weight:400;line-height:var(--lbmLineHeight);color:var(--lbmTextColor)}.freeze-loader .lbm-learn-more,.lbm-indicator .lbm-learn-more{display:inline-flex;padding:0;font-size:var(--lbmTextSize);font-weight:400;line-height:var(--lbmLineHeight);color:var(--lbmTextColor);-webkit-text-decoration-line:underline;text-decoration-line:underline;background-color:transparent;border:none;cursor:pointer}.freeze-loader .lbm-learn-more:hover,.lbm-indicator .lbm-learn-more:hover{text-decoration:none}@keyframes openMessage{0%{opacity:0;max-width:0;height:0}10%{height:auto;max-width:fit-content}to{opacity:1;height:auto;max-width:fit-content}}@keyframes closeMessage{0%{opacity:1;max-width:fit-content}to{opacity:0;max-width:0}}\n"] }]
4720
4917
  }] });
@@ -4723,5 +4920,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.1", ngImpor
4723
4920
  * Generated bundle index. Do not edit.
4724
4921
  */
4725
4922
 
4726
- export { AFKService, AfkRestartScreenLockerComponent, AggregatorService, AnswerHandler, CONSOLE_COMMAND_DISABLE_MESSAGES, CONSOLE_COMMAND_ENABLE_MESSAGES, CONSOLE_COMMAND_PIXEL_QUALITY, ClickableOverlayComponent, CommandTelemetryService, ConfigHandler, ConsoleExtensionsService, DATA_CHANNEL_CONNECTION_TIMEOUT, DEBOUNCE_TO_MANY_RESIZE_CALLS, DEFAULT_AFK_TIMEOUT, DEFAULT_AFK_TIMEOUT_PERIOD, DataFlowMonitor, DevModeService, DisconnectReason, EControlSchemeType, EMessageType, EToClientMessageType, FULL_HD_HEIGHT, FULL_HD_WIDTH, FilterSettingsComponent, FreezeFrameComponent, FreezeFrameService, IceCandidateHandler, InputOptions, InputService, InstanceReadyHandler, InstanceReservedHandler, KalmanFilter1D, LatencyTimings, LowBandwidthDetectorComponent, LowBandwidthModalComponent, MINIMAL_FPS, MouseButton, MouseButtonsMask, OnCloseHandler, OnErrorHandler, OnMessageHandler, OnOpenHandler, OrchestrationMessageTypes, PingHandler, PlayerCountHandler, RegionsPingService, ResetTelemetry, SAME_SIZE_THRESHOLD, SCREEN_LOCKER_CONTAINER_ID, SIGNALLING_PERCENT_VALUE, SSInfoHandler, STREAMING_VIDEO_ID, SafePipe, SignallingService, SpecialKeyCodes, StatGraphComponent, StreamStatusTelemetryService, SubService, TelemetryStart, TelemetryStop, UNREAL_CONFIG, UnrealCommunicatorService, UnrealEffects, UnrealInternalSignalEvents, UnrealSceneComponent, UnrealStatusMessage, VideoLockerComponent, VideoRecorder, VideoService, VideoStatsComponent, WSCloseCode_NORMAL_AFK_TIMEOUT, WSCloseCode_NORMAL_CIRRUS_CLOSED, WSCloseCode_NORMAL_CLOSURE, WSCloseCode_NORMAL_MANUAL_DISCONNECT, WSCloseCodes, WS_OPEN_STATE, WS_TIMEOUT, WebRtcPlayerService, WebrtcErrorModalComponent, alignProductsToPlaneCommand, changeLowBandwidth, changeStatusMainVideoOnScene, changeStreamResolutionAction, changeStreamResolutionSuccessAction, clampAndKeepMaxPercents, clampPanToProductsCommand, commandCompleted, commandStarted, decodeData, destroyConnectionsAndResetState, destroyRemoteConnections, dispatchResize, floatToSmoothPercents, forceResizeUnrealVideo, fromResizeObserver, fromSignal, fromUnrealCallBackSignal, getActiveUrl, getApplyCameraPresetCommand, getApplyZoomCommand, getCameraBoxCommand, getCameraRecenterCommand, getCameraSettingsCommand, getChangeGizmoTypeCommand, getChangeResolutionCommand, getClickSnapCommand, getControlSensitivityCommand, getDebugModeCommand, getDragCommand, getDragSequenceCommand, getDropCommand, getEnableComposureCommand, getEnableControlsCommand, getEnableSceneStateCallbackCommand, getEnableSpinnerModeCommand, getEnableTeleportCommand, getExecuteConsoleCommand, getFitToObjectsCommand, getFreezeFrameCommand, getFreezeFrameNative, getImageFromVideoStream, getInitSequenceByObjectNameCommand, getJumpToSequenceCommand, getLoadLevelCommand, getLoadProductCommand, getLoadSceneStateCommand, getLoopBackCommand, getMoveSelectedCommand, getPauseSequenceCommand, getPlaySequenceCommand, getRequestCameraPresetCommand, getResetControlClampsCommand, getRotateSelectedCommand, getRtcErrorMessage, getSelectProductByObjectNameCommand, getSetCameraControlClampsCommand, getSetControlCameraModeCommand, getSetFpsCommand, getSetMaterialCommand, getSetPawnMovementModeCommand, getSetSettingsSequenceCommand, getStopSequenceCommand, getTakeRenderCommand, getTakeSpinnerRenderCommand, getTakeSpinnerRenderPreviewCommand, getUnLoadAllProductsCommand, getUnLoadProductByObjectNameCommand, getUnfreezeFrameNative, getUnselectAllProductsCommand, getWeatherCommand, initSignalling, initialState, mapQpToQuality, observeCommandResponse, provideAngularUnrealModule, removeExileCommands, resetAfk, resetAfkAction, resetConfig, resetIntroSrc, resetUnrealState, resetUnrealStateAction, resetWarnTimeout, selectCommandProgress, selectCommandsInProgress, selectFreezeFrameCombinedDataUrl, selectFreezeFrameDataUrl, selectFreezeFrameDataUrlFromVideo, selectFreezeFrameProgressMessageFromVideo, selectIsAutostart, selectIsFreezeFrameLoading, selectIsVideoPlayingAndDataChannelConnected, selectLastCommandInProgress, selectLoaderCommands, selectMatchMakerUrls, selectShowLoader, selectShowReconnectPopup, selectSignalingParameters, selectStreamConfig, selectTotalProgress, selectWarnTimeout, selectWsUrl, sendSignal, setAwsInstance, setCirrusConnected, setCirrusDisconnected, setConfig, setDataChannelConnected, setErrorMessage, setEstablishingConnection, setFreezeFrame, setFreezeFrameFromVideo, setIntroImageSrc, setIntroVideoSrc, setIsFreezeLoaderPercents, setLoadingImageSrc, setLoopBackCommandIsCompleted, setMatchMakerUrls, setMatchUrls, setMaxFps, setProductsLocationCommand, setSignalingName, setStatusMessage, setStatusPercentSignallingServer, setStreamClientCompanyId, setStreamViewId, setViewportReady, showUnrealErrorMessage, smoothTransition, trackMixpanelEvent, unLoadAllLevelsCommand, unrealFeature, unrealReducer, updateCirrusInfo };
4923
+ export { AFKService, AfkRestartScreenLockerComponent, AggregatorService, AnswerHandler, CONSOLE_COMMAND_DISABLE_MESSAGES, CONSOLE_COMMAND_ENABLE_MESSAGES, CONSOLE_COMMAND_PIXEL_QUALITY, ClickableOverlayComponent, CommandTelemetryService, ConfigHandler, ConsoleExtensionsService, DATA_CHANNEL_CONNECTION_TIMEOUT, DEBOUNCE_TO_MANY_RESIZE_CALLS, DEFAULT_AFK_TIMEOUT, DEFAULT_AFK_TIMEOUT_PERIOD, DataFlowMonitor, DevModeService, DisconnectReason, EControlSchemeType, EMessageType, EToClientMessageType, FULL_HD_HEIGHT, FULL_HD_WIDTH, FilterSettingsComponent, FreezeFrameComponent, FreezeFrameService, IceCandidateHandler, InputOptions, InputService, InstanceReadyHandler, InstanceReservedHandler, KalmanFilter1D, LatencyTimings, LowBandwidthDetectorComponent, LowBandwidthModalComponent, MINIMAL_FPS, MouseButton, MouseButtonsMask, OnCloseHandler, OnErrorHandler, OnMessageHandler, OnOpenHandler, OrchestrationMessageTypes, POLLING_TIME, PingHandler, PlayerCountHandler, RegionsPingService, ResetTelemetry, SAME_SIZE_THRESHOLD, SCREEN_LOCKER_CONTAINER_ID, SIGNALLING_PERCENT_VALUE, SSInfoHandler, STREAMING_VIDEO_ID, SafePipe, SignallingService, SpecialKeyCodes, StatGraphComponent, StreamStatusTelemetryService, SubService, TelemetryStart, TelemetryStop, UNREAL_CONFIG, UnrealCommunicatorService, UnrealEffects, UnrealInternalSignalEvents, UnrealSceneComponent, UnrealStatusMessage, VideoLockerComponent, VideoRecorder, VideoService, VideoStatsComponent, WSCloseCode_CIRRUS_ABNORMAL_CLOSURE, WSCloseCode_CIRRUS_MAX_PLAYERS_ERROR, WSCloseCode_CIRRUS_PLAYER_DISCONNECTED, WSCloseCode_CIRRUS_STREAMER_KIKED_PLAYER, WSCloseCode_FORCE_CIRRUS_CLOSE, WSCloseCode_NORMAL_AFK_TIMEOUT, WSCloseCode_NORMAL_CLOSURE, WSCloseCode_NORMAL_MANUAL_DISCONNECT, WSCloseCodes, WS_OPEN_STATE, WS_TIMEOUT, WebRtcPlayerService, WebrtcErrorModalComponent, abortEstablishingConnection, alignProductsToPlaneCommand, changeLowBandwidth, changeStatusMainVideoOnScene, changeStreamResolutionAction, changeStreamResolutionSuccessAction, clampAndKeepMaxPercents, clampPanToProductsCommand, commandCompleted, commandStarted, decodeData, destroyRemoteConnections, destroyUnrealScene, disconnectStream, dispatchResize, dropConnection, floatToSmoothPercents, forceResizeUnrealVideo, fromResizeObserver, fromSignal, fromUnrealCallBackSignal, getActiveUrl, getApplyCameraPresetCommand, getApplyZoomCommand, getCameraBoxCommand, getCameraRecenterCommand, getCameraSettingsCommand, getChangeGizmoTypeCommand, getChangeResolutionCommand, getClickSnapCommand, getControlSensitivityCommand, getDebugModeCommand, getDragCommand, getDragSequenceCommand, getDropCommand, getEnableComposureCommand, getEnableControlsCommand, getEnableSceneStateCallbackCommand, getEnableSpinnerModeCommand, getEnableTeleportCommand, getExecuteConsoleCommand, getFitToObjectsCommand, getFreezeFrameCommand, getFreezeFrameNative, getImageFromVideoStream, getInitSequenceByObjectNameCommand, getJumpToSequenceCommand, getLoadLevelCommand, getLoadProductCommand, getLoadSceneStateCommand, getLoopBackCommand, getMoveSelectedCommand, getPauseSequenceCommand, getPlaySequenceCommand, getRequestCameraPresetCommand, getResetControlClampsCommand, getRotateSelectedCommand, getRtcErrorMessage, getSelectProductByObjectNameCommand, getSetCameraControlClampsCommand, getSetControlCameraModeCommand, getSetFpsCommand, getSetMaterialCommand, getSetPawnMovementModeCommand, getSetSettingsSequenceCommand, getStopSequenceCommand, getTakeRenderCommand, getTakeSpinnerRenderCommand, getTakeSpinnerRenderPreviewCommand, getUnLoadAllProductsCommand, getUnLoadProductByObjectNameCommand, getUnfreezeFrameNative, getUnselectAllProductsCommand, getWeatherCommand, initSignalling, initialState, isLoaderScreenVisible, mapQpToQuality, observeCommandResponse, provideAngularUnrealModule, removeExileCommands, resetAfk, resetAfkAction, resetConfig, resetIntroSrc, resetWarnTimeout, selectClientAndViewIds, selectCommandProgress, selectCommandsInProgress, selectFreezeFrameCombinedDataUrl, selectFreezeFrameDataUrl, selectFreezeFrameDataUrlFromVideo, selectFreezeFrameProgressMessageFromVideo, selectIsAutostart, selectIsExistMatchUrls, selectIsFreezeFrameLoading, selectIsVideoPlayingAndDataChannelConnected, selectLastCommandInProgress, selectLoaderCommands, selectShowLoader, selectShowReconnectPopup, selectSignalingParameters, selectStreamConfig, selectTotalProgress, selectWarnTimeout, sendSignal, setAwsInstance, setCirrusConnected, setCirrusDisconnected, setConfig, setDataChannelConnected, setEstablishingConnection, setFreezeFrame, setFreezeFrameFromVideo, setIntroImageSrc, setIntroVideoSrc, setLoadingImageSrc, setLoopBackCommandIsCompleted, setMatchUrls, setMaxFps, setProductsLocationCommand, setSignalingName, setStatusMessage, setStatusPercentSignallingServer, setStreamClientCompanyId, setStreamViewId, setViewportNotReady, setViewportReady, showPopupWithoutAutoStart, showUnrealErrorMessage, smoothTransition, startStream, trackMixpanelEvent, unLoadAllLevelsCommand, unrealFeature, unrealReducer, updateCirrusInfo };
4727
4924
  //# sourceMappingURL=3dsource-angular-unreal-module.mjs.map