@3dsource/angular-unreal-module 0.0.99 → 0.0.100

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.
@@ -3,7 +3,7 @@ import { InjectionToken, inject, ChangeDetectionStrategy, Component, Injectable,
3
3
  import { SourceButtonComponent, SourceLoadingComponent } from '@3dsource/source-ui-native';
4
4
  import { map as map$1, filter, catchError, distinctUntilChanged, takeWhile, tap, withLatestFrom, exhaustMap, takeUntil, switchMap as switchMap$1, timeout as timeout$1, debounceTime as debounceTime$1, delay, skip as skip$1 } from 'rxjs/operators';
5
5
  import { Logger, generateUuid, tapLog, Truthy, calculateMedian, clampf, Signal, lerp, getCanvasCached, getSnapshot, whereNot, Falsy, COLOR_CODES, where, KeyboardNumericCode, InvertedKeyMap, Semaphore, HEXtoRGB, RGBtoHSV, inverseLerp, HSVtoRGB, RGBtoHEX, fpIsASameAsB, fitIntoRectangle } from '@3dsource/utils';
6
- import { merge, map, scan, timeout, of, take, concatMap, animationFrameScheduler, interval, Observable, debounceTime, switchMap, fromEvent, EMPTY, timer, mergeMap, skip, share, Subject, from, throwError, defer, retry, tap as tap$1, startWith, takeUntil as takeUntil$1, auditTime, filter as filter$1, throttleTime, combineLatestWith, distinctUntilChanged as distinctUntilChanged$1, concat } from 'rxjs';
6
+ import { merge, map, scan, timeout, of, take, concatMap, animationFrameScheduler, interval, Observable, debounceTime, switchMap, fromEvent, EMPTY, timer, mergeMap, skip, share, Subject, from, throwError, defer, retry, tap as tap$1, startWith, takeUntil as takeUntil$1, auditTime, filter as filter$1, throttleTime, BehaviorSubject, combineLatestWith, distinctUntilChanged as distinctUntilChanged$1, concat } from 'rxjs';
7
7
  import { createAction, props, createReducer, on, createFeature, Store, createSelector, provideState } from '@ngrx/store';
8
8
  import { concatLatestFrom } from '@ngrx/operators';
9
9
  import { Actions, createEffect, ofType, provideEffects } from '@ngrx/effects';
@@ -12,7 +12,7 @@ import { HttpClient } from '@angular/common/http';
12
12
  import { ScrollStrategyOptions } from '@angular/cdk/overlay';
13
13
  import { MetaBoxCommand } from '@3dsource/types-unreal';
14
14
  import { DomSanitizer } from '@angular/platform-browser';
15
- import { NgOptimizedImage, JsonPipe } from '@angular/common';
15
+ import { NgOptimizedImage, AsyncPipe, JsonPipe } from '@angular/common';
16
16
  import { toSignal, takeUntilDestroyed, toObservable } from '@angular/core/rxjs-interop';
17
17
  import * as i1 from '@angular/forms';
18
18
  import { FormsModule } from '@angular/forms';
@@ -197,7 +197,7 @@ const initSignalling = createAction(scoped `init signalling`, (data = {
197
197
  }));
198
198
  const startStream = createAction(scoped `startStream`, props());
199
199
  const resetConfig = createAction(scoped `reset config`);
200
- const resetAfkAction = createAction(scoped `reset afk action`);
200
+ const resetAfk = createAction(scoped `reset afk action`);
201
201
  const resetWarnTimeout = createAction(scoped `reset config warn timeout`);
202
202
  const abortEstablishingConnection = createAction(scoped `abortEstablishingConnection`);
203
203
  const setUnrealPlaywrightConfig = createAction(scoped `set unreal playwright config`);
@@ -212,6 +212,9 @@ const reconnectPeerSuccess = createAction(scoped `reconnect peer success`);
212
212
  const reconnectPeerFailed = createAction(scoped `reconnect peer failed`, props());
213
213
  /** Action dispatched when ICE connection state changes to failed/disconnected */
214
214
  const iceConnectionFailed = createAction(scoped `ice connection failed`, props());
215
+ const forceResizeViewport = createAction(scoped `force resize viewport`);
216
+ const videoAdaptedToContainer = createAction(scoped `video adapted to container`);
217
+ const videoStreamInitialized = createAction(scoped `video stream initialized`);
215
218
 
216
219
  const WSCloseCode_NORMAL_CLOSURE = 3000;
217
220
  const WSCloseCode_NORMAL_AFK_TIMEOUT = 3001;
@@ -277,13 +280,7 @@ const OrchestrationMessageTypes = {
277
280
  };
278
281
 
279
282
  const UnrealInternalSignalEvents = {
280
- OnVideoInitialized: 'OnVideoInitialized',
281
- RestAfkTimer: 'RestAfkTimer',
282
283
  UnrealCallback: 'UnrealCallback',
283
- VideoPlayClick: 'VideoPlayClick',
284
- ShowPlayButton: 'ShowPlayButton',
285
- ForceResizeViewport: 'ForceResizeViewport',
286
- VideoAdaptedToContainer: 'VideoAdaptedToContainer',
287
284
  };
288
285
 
289
286
  function AnswerHandler(msg) {
@@ -386,7 +383,7 @@ function observeCommandResponse(data, sender, timeOut = 60000, dispatchOnTimeout
386
383
  const observable = fromSignal(UnrealInternalSignalEvents.UnrealCallback).pipe(map$1(({ json }) => {
387
384
  // Some callbacks do not have commandCallback wrapper,
388
385
  // so first we check if it exists,
389
- // then fallback to JSON itself
386
+ // then fall back to JSON itself
390
387
  return 'commandCallback' in json
391
388
  ? { json }
392
389
  : { json: { commandCallback: json } };
@@ -489,14 +486,26 @@ class DataFlowMonitor {
489
486
  }
490
487
  }
491
488
 
489
+ const dispatchResize = () => {
490
+ window.dispatchEvent(new Event('resize'));
491
+ };
492
+
493
+ const errorCodes = {
494
+ code404: 'Your asset is being synced on Metabox servers and is not yet available in Metabox Studio or Metabox Configurator. Please check again later after syncing is complete. ',
495
+ };
496
+ function getRtcErrorMessage(code) {
497
+ if (code === null) {
498
+ return undefined;
499
+ }
500
+ return errorCodes[`code${code}`];
501
+ }
502
+
492
503
  /**
493
504
  * UnrealInternalSignalEvents commands list wrapper listener
494
505
  * @param event
495
506
  */
496
507
  function fromSignal(event) {
497
- return Signal.on(event).pipe(
498
- //tapLog('fromSignal', event), // <== for debugging, do not remove
499
- map$1((data) => data && typeof data === 'object' && 'detail' in data ? data.detail : ''));
508
+ return Signal.on(event).pipe(map$1((data) => data && typeof data === 'object' && 'detail' in data ? data.detail : ''));
500
509
  }
501
510
  /**
502
511
  * UnrealInternalSignalEvents commands list wrapper sender
@@ -525,23 +534,6 @@ function fromUnrealCallBackSignal(command) {
525
534
  }));
526
535
  }
527
536
 
528
- const dispatchResize = () => {
529
- window.dispatchEvent(new Event('resize'));
530
- };
531
- const forceResizeUnrealVideo = () => {
532
- sendSignal(UnrealInternalSignalEvents.ForceResizeViewport);
533
- };
534
-
535
- const errorCodes = {
536
- code404: 'Your asset is being synced on Metabox servers and is not yet available in Metabox Studio or Metabox Configurator. Please check again later after syncing is complete. ',
537
- };
538
- function getRtcErrorMessage(code) {
539
- if (code === null) {
540
- return undefined;
541
- }
542
- return errorCodes[`code${code}`];
543
- }
544
-
545
537
  const floatToSmoothPercents = () => {
546
538
  return (source) => source.pipe(scan((acc, value) => ({
547
539
  previous: acc.current,
@@ -723,10 +715,6 @@ const removeExileCommands = (state, idToRemove) => {
723
715
  return out;
724
716
  };
725
717
 
726
- const resetAfk = () => {
727
- sendSignal(UnrealInternalSignalEvents.RestAfkTimer);
728
- };
729
-
730
718
  function fromResizeObserver(elem) {
731
719
  return new Observable((subscriber) => {
732
720
  const observer = new window.ResizeObserver((entries) => subscriber.next(entries));
@@ -1099,7 +1087,7 @@ class UnrealEffects {
1099
1087
  })));
1100
1088
  });
1101
1089
  this.forceLBMOff$ = createEffect(() => {
1102
- return fromEvent(document, 'visibilitychange').pipe(map(() => document.visibilityState === 'visible'), filter(Truthy), withLatestFrom(this.store.select(unrealFeature.selectLowBandwidth)), filter(([, isLowBandwidth]) => isLowBandwidth), tapLog('forceLBMOff$'), map(() => changeLowBandwidth({ lowBandwidth: false })));
1090
+ return fromEvent(document, 'visibilitychange').pipe(map(() => document.visibilityState === 'visible'), filter(Truthy), withLatestFrom(this.store.select(unrealFeature.selectLowBandwidth)), filter(([, isLowBandwidth]) => isLowBandwidth), map(() => changeLowBandwidth({ lowBandwidth: false })));
1103
1091
  });
1104
1092
  this.resetFreezeFrameOnLowBandwidthTriggered$ = createEffect(() => {
1105
1093
  return this.actions$.pipe(ofType(changeLowBandwidth), map(({ lowBandwidth }) => lowBandwidth), distinctUntilChanged(), map(() => setFreezeFrame({ dataUrl: null, progress: null })));
@@ -1120,7 +1108,7 @@ class UnrealEffects {
1120
1108
  .pipe(catchError(() => EMPTY))))))
1121
1109
  .subscribe();
1122
1110
  this.resetAfk$ = createEffect(() => {
1123
- return this.actions$.pipe(ofType(setConfig, resetWarnTimeout, resetConfig), map(() => resetAfkAction()));
1111
+ return this.actions$.pipe(ofType(setConfig, resetWarnTimeout, resetConfig), map(() => resetAfk()));
1124
1112
  });
1125
1113
  this.abortEstablishingConnection$ = createEffect(() => {
1126
1114
  const viewportReady$ = this.store
@@ -1137,9 +1125,6 @@ class UnrealEffects {
1137
1125
  });
1138
1126
  }));
1139
1127
  }, { dispatch: false });
1140
- this.resetAfkAction$ = createEffect(() => {
1141
- return this.actions$.pipe(ofType(resetAfkAction), tap(() => resetAfk()));
1142
- }, { dispatch: false });
1143
1128
  this.setSignalingTo100$ = createEffect(() => {
1144
1129
  return this.actions$.pipe(ofType(setAwsInstance), map(() => setStatusPercentSignallingServer({ percent: 100 })));
1145
1130
  });
@@ -1237,7 +1222,7 @@ class UnrealEffects {
1237
1222
  return this.actions$.pipe(ofType(setLoopBackCommandIsCompleted, reconnectPeerSuccess), tap(() => this.commandTelemetryService.trackStopCommand('EXT-SetViewportReady', false, { ready: true })), map(() => setViewportReady()));
1238
1223
  });
1239
1224
  this.startStream$ = createEffect(() => {
1240
- return this.actions$.pipe(ofType(startStream), tapLog('Start Stream Pressed'), map(() => initSignalling()));
1225
+ return this.actions$.pipe(ofType(startStream), map(() => initSignalling()));
1241
1226
  });
1242
1227
  this.listenUnrealCallbackByInitSignalling$ = createEffect(() => {
1243
1228
  return this.actions$.pipe(ofType(initSignalling), filter(() => !this.unrealInitialConfig?.playwright), switchMap(() => fromSignal(UnrealInternalSignalEvents.UnrealCallback).pipe(map(({ json }) => json?.commandCallback
@@ -1338,7 +1323,7 @@ class UnrealEffects {
1338
1323
  }
1339
1324
  }));
1340
1325
  }),
1341
- // Cancel if scene is destroyed
1326
+ // Cancel if a scene is destroyed
1342
1327
  takeUntil(this.actions$.pipe(ofType(destroyUnrealScene), take(1))))));
1343
1328
  });
1344
1329
  /**
@@ -1443,6 +1428,7 @@ const selectIsLoaderScreenVisible = createSelector(unrealFeature.selectViewportR
1443
1428
 
1444
1429
  class SubService {
1445
1430
  constructor() {
1431
+ this.actions$ = inject(Actions);
1446
1432
  this.store = inject(Store);
1447
1433
  this.disconnect$ = this.store
1448
1434
  .select(unrealFeature.selectCirrusConnected)
@@ -1463,7 +1449,7 @@ class AFKService extends SubService {
1463
1449
  this.init();
1464
1450
  }
1465
1451
  init() {
1466
- merge(this.store.select(selectWarnTimeout), fromSignal(UnrealInternalSignalEvents.RestAfkTimer))
1452
+ merge(this.store.select(selectWarnTimeout), this.actions$.pipe(ofType(resetAfk)))
1467
1453
  .pipe(withLatestFrom(this.store.select(unrealFeature.selectViewportReady)), filter(([, viewportReady]) => viewportReady))
1468
1454
  .subscribe(() => this.resetAfkWarningTimer());
1469
1455
  this.store
@@ -1561,6 +1547,9 @@ class FreezeFrameService extends SubService {
1561
1547
  .select(unrealFeature.selectViewportReady)
1562
1548
  .pipe(filter(Truthy))
1563
1549
  .subscribe(() => this.invalidate());
1550
+ this.actions$
1551
+ .pipe(ofType(videoStreamInitialized))
1552
+ .subscribe(() => this.invalidate());
1564
1553
  }
1565
1554
  setData(view) {
1566
1555
  view = view.slice(1 + 4);
@@ -1907,7 +1896,7 @@ class VideoService extends SubService {
1907
1896
  .pipe(take(1), filter((data) => this.video === data.target), tapLog('VideoService loadedmetadata:'))
1908
1897
  .subscribe(() => {
1909
1898
  if (this.video) {
1910
- sendSignal(UnrealInternalSignalEvents.OnVideoInitialized, this.video);
1899
+ this.store.dispatch(videoStreamInitialized());
1911
1900
  }
1912
1901
  });
1913
1902
  }
@@ -2117,7 +2106,7 @@ class CommandTelemetryService {
2117
2106
  * Finally, calls the provided function with the modified data object.
2118
2107
  *
2119
2108
  * @param {IToBeDecorated} funcToDecorate - The function to be decorated with telemetry tracking.
2120
- * @param {any} data - The data object to be passed to the function. It will be augmented with a unique tracking ID.
2109
+ * @param {MetaBoxCommandPacket} data - The data object to be passed to the function. It will be augmented with a unique tracking ID.
2121
2110
  */
2122
2111
  wrapper(funcToDecorate, data) {
2123
2112
  const out = { ...data, trackingId: generateUuid() };
@@ -3313,6 +3302,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImpor
3313
3302
 
3314
3303
  class ConsoleExtensionsService extends SubService {
3315
3304
  #httpClient = inject(HttpClient);
3305
+ #commandsSender = inject(UnrealCommunicatorService);
3316
3306
  #isDevMode = inject(DevModeService).isDevMode;
3317
3307
  constructor() {
3318
3308
  super();
@@ -3329,6 +3319,21 @@ class ConsoleExtensionsService extends SubService {
3329
3319
  }));
3330
3320
  return true;
3331
3321
  };
3322
+ window.dropDC = () => {
3323
+ Signal.broadcast('dropDC');
3324
+ return true;
3325
+ };
3326
+ window.dropPC = () => {
3327
+ Signal.broadcast('dropPC');
3328
+ return true;
3329
+ };
3330
+ window.setResolution = ({ w, h }) => {
3331
+ this.#commandsSender.sendCommandToUnreal({
3332
+ command: MetaBoxCommand.FChangeResolutionCommand,
3333
+ payload: { resolution: { x: w, y: h } },
3334
+ });
3335
+ return 'LowBandwidth => toggled';
3336
+ };
3332
3337
  window.toggleBandwidth = () => {
3333
3338
  this.store
3334
3339
  .select(unrealFeature.selectLowBandwidth)
@@ -3343,7 +3348,7 @@ class ConsoleExtensionsService extends SubService {
3343
3348
  window.restartApp = () => {
3344
3349
  this.store
3345
3350
  .select(unrealFeature.selectAwsInstance)
3346
- .pipe(take(1), filter((data) => !!data.instanceName), tapLog('Instance', `Restart initiated`), switchMap((data) => this.#httpClient.get(`//${data.instanceName}/restartapp`)), catchError(() => of(null)))
3351
+ .pipe(take(1), filter((data) => !!data.instanceName), switchMap((data) => this.#httpClient.get(`//${data.instanceName}/restartapp`)), catchError(() => of(null)))
3347
3352
  .subscribe();
3348
3353
  };
3349
3354
  window.unrealHelp = () => this.unrealHelp();
@@ -3388,7 +3393,6 @@ class UnrealCommunicatorService {
3388
3393
  constructor() {
3389
3394
  this.store = inject(Store);
3390
3395
  this.commandTelemetryService = inject(CommandTelemetryService);
3391
- this.freezeFrameService = inject(FreezeFrameService);
3392
3396
  this.webRtcPlayerService = inject(WebRtcPlayerService);
3393
3397
  this.destroy$ = new Subject();
3394
3398
  this.cirrusConnected = this.store.selectSignal(unrealFeature.selectCirrusConnected);
@@ -3396,7 +3400,6 @@ class UnrealCommunicatorService {
3396
3400
  }
3397
3401
  init() {
3398
3402
  this.emitUIInteraction = this.commandTelemetryService.decorate(this.emitUIInteraction.bind(this));
3399
- this.listenVideo();
3400
3403
  this.store
3401
3404
  .select(unrealFeature.selectDataChannelConnected)
3402
3405
  .pipe(filter(Truthy))
@@ -3437,7 +3440,7 @@ class UnrealCommunicatorService {
3437
3440
  }
3438
3441
  sendInputData(data) {
3439
3442
  try {
3440
- resetAfk();
3443
+ this.store.dispatch(resetAfk());
3441
3444
  this.webRtcPlayerService.send(data);
3442
3445
  }
3443
3446
  catch (error) {
@@ -3469,12 +3472,6 @@ class UnrealCommunicatorService {
3469
3472
  requestQualityControl() {
3470
3473
  this.sendInputData(new Uint8Array([MessageType.RequestQualityControl]).buffer);
3471
3474
  }
3472
- listenVideo() {
3473
- fromSignal(UnrealInternalSignalEvents.OnVideoInitialized).subscribe(() => {
3474
- sendSignal(UnrealInternalSignalEvents.ShowPlayButton);
3475
- this.freezeFrameService.invalidate();
3476
- });
3477
- }
3478
3475
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: UnrealCommunicatorService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
3479
3476
  static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: UnrealCommunicatorService }); }
3480
3477
  }
@@ -3540,11 +3537,9 @@ class InputService extends SubService {
3540
3537
  Logger.log('DEBUG: video initialized: ', video);
3541
3538
  this.options = InputOptions;
3542
3539
  this.reInit$.next();
3543
- merge(fromResizeObserver(video), fromSignal(UnrealInternalSignalEvents.VideoAdaptedToContainer))
3540
+ merge(fromResizeObserver(video), this.actions$.pipe(ofType(videoAdaptedToContainer)))
3544
3541
  .pipe(debounceTime$1(300), takeUntil$1(this.deactivatedVideoTrigger$))
3545
- .subscribe(() => {
3546
- this.setupNormalizeAndQuantize(video);
3547
- });
3542
+ .subscribe(() => this.setupNormalizeAndQuantize(video));
3548
3543
  this.setupNormalizeAndQuantize(video);
3549
3544
  this.registerInputs(video);
3550
3545
  }
@@ -4147,9 +4142,6 @@ class UnrealCommunicatorPlaywrightService extends UnrealCommunicatorService {
4147
4142
  sendInputData() {
4148
4143
  return;
4149
4144
  }
4150
- listenVideo() {
4151
- return;
4152
- }
4153
4145
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: UnrealCommunicatorPlaywrightService, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
4154
4146
  static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: UnrealCommunicatorPlaywrightService }); }
4155
4147
  }
@@ -4700,11 +4692,11 @@ class AfkTimeoutModalComponent {
4700
4692
  this.#afkService.reset();
4701
4693
  }
4702
4694
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: AfkTimeoutModalComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
4703
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.5", type: AfkTimeoutModalComponent, isStandalone: true, selector: "app-afk-timeout-modal", ngImport: i0, template: "@if (isAfkTimerVisible()) {\n <div (click)=\"resetAfk()\" class=\"clickableState\" id=\"videoPlayOverlay\">\n <div class=\"resume-box\">\n <div aria-hidden=\"true\" class=\"resume-box__pic\" role=\"presentation\">\n <div [innerHTML]=\"afkCountdown()\" 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 [isFullWidth]=\"true\"\n [data-testid]=\"'continue-session'\"\n weight=\"primary\"\n size=\"lg\"\n >\n Continue\n </src-button>\n </div>\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: "component", type: SourceButtonComponent, selector: "src-button", inputs: ["type", "appearance", "weight", "size", "context", "customClass", "isFullWidth", "isPressed", "isDisabled", "isLoading", "isInverted", "iconButton", "srcButtonConfig", "formID", "data-testid", "ariaLabel"], outputs: ["onClick", "onSubmit"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
4695
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.5", type: AfkTimeoutModalComponent, isStandalone: true, selector: "app-afk-timeout-modal", ngImport: i0, template: "@if (isAfkTimerVisible()) {\n <div (click)=\"resetAfk()\" class=\"clickableState\" id=\"videoPlayOverlay\">\n <div class=\"resume-box\">\n <div aria-hidden=\"true\" class=\"resume-box__pic\" role=\"presentation\">\n <div [innerHTML]=\"afkCountdown()\" 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 [isFullWidth]=\"true\"\n [data-testid]=\"'continue-session'\"\n weight=\"primary\"\n size=\"lg\"\n >\n Continue\n </src-button>\n </div>\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-surface-container-main, #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-text-body-secondary, #6b7280)}.resume-box__text .resume-box__heading{color:var(--src-text-body-main, #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: "component", type: SourceButtonComponent, selector: "src-button", inputs: ["type", "appearance", "weight", "size", "context", "customClass", "isFullWidth", "isPressed", "isDisabled", "isLoading", "isInverted", "iconButton", "srcButtonConfig", "formID", "data-testid", "ariaLabel"], outputs: ["onClick", "onSubmit"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
4704
4696
  }
4705
4697
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: AfkTimeoutModalComponent, decorators: [{
4706
4698
  type: Component,
4707
- args: [{ selector: 'app-afk-timeout-modal', changeDetection: ChangeDetectionStrategy.OnPush, imports: [SourceButtonComponent], template: "@if (isAfkTimerVisible()) {\n <div (click)=\"resetAfk()\" class=\"clickableState\" id=\"videoPlayOverlay\">\n <div class=\"resume-box\">\n <div aria-hidden=\"true\" class=\"resume-box__pic\" role=\"presentation\">\n <div [innerHTML]=\"afkCountdown()\" 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 [isFullWidth]=\"true\"\n [data-testid]=\"'continue-session'\"\n weight=\"primary\"\n size=\"lg\"\n >\n Continue\n </src-button>\n </div>\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"] }]
4699
+ args: [{ selector: 'app-afk-timeout-modal', changeDetection: ChangeDetectionStrategy.OnPush, imports: [SourceButtonComponent], template: "@if (isAfkTimerVisible()) {\n <div (click)=\"resetAfk()\" class=\"clickableState\" id=\"videoPlayOverlay\">\n <div class=\"resume-box\">\n <div aria-hidden=\"true\" class=\"resume-box__pic\" role=\"presentation\">\n <div [innerHTML]=\"afkCountdown()\" 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 [isFullWidth]=\"true\"\n [data-testid]=\"'continue-session'\"\n weight=\"primary\"\n size=\"lg\"\n >\n Continue\n </src-button>\n </div>\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-surface-container-main, #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-text-body-secondary, #6b7280)}.resume-box__text .resume-box__heading{color:var(--src-text-body-main, #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"] }]
4708
4700
  }] });
4709
4701
 
4710
4702
  class FreezeFrameComponent {
@@ -4787,20 +4779,17 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImpor
4787
4779
 
4788
4780
  class StatGraphComponent {
4789
4781
  constructor() {
4782
+ this.label = input.required(...(ngDevMode ? [{ debugName: "label" }] : []));
4790
4783
  this.stat = input(...(ngDevMode ? [undefined, { debugName: "stat" }] : []));
4791
- this.el = inject(ElementRef);
4792
- this.graph = viewChild('graph', ...(ngDevMode ? [{ debugName: "graph" }] : []));
4793
4784
  this.color = input('#417bc9', ...(ngDevMode ? [{ debugName: "color" }] : []));
4794
4785
  this.tickStep = input(3, ...(ngDevMode ? [{ debugName: "tickStep" }] : []));
4795
- this.label = input.required(...(ngDevMode ? [{ debugName: "label" }] : []));
4786
+ this.el = inject(ElementRef);
4787
+ this.graph = viewChild('graph', ...(ngDevMode ? [{ debugName: "graph" }] : []));
4796
4788
  this.data = [];
4797
4789
  this.max = signal(0, ...(ngDevMode ? [{ debugName: "max" }] : []));
4798
4790
  this.min = signal(0, ...(ngDevMode ? [{ debugName: "min" }] : []));
4799
4791
  this.current = signal(0, ...(ngDevMode ? [{ debugName: "current" }] : []));
4800
- effect(() => {
4801
- const stat = this.stat();
4802
- this.pushData(stat ?? null);
4803
- });
4792
+ effect(() => this.pushData(this.stat()?.value ?? null));
4804
4793
  afterNextRender({
4805
4794
  read: () => {
4806
4795
  const graph = this.graph();
@@ -4822,7 +4811,7 @@ class StatGraphComponent {
4822
4811
  const all = this.data.filter((r) => r !== null && !isNaN(r));
4823
4812
  this.max.set(Math.max(...all));
4824
4813
  this.min.set(Math.min(...all));
4825
- this.scaleY = this.canvas.height / (this.max() || 1);
4814
+ const scaleY = this.canvas.height / (this.max() || 1);
4826
4815
  this.current.set(all[all.length - 1] || 0);
4827
4816
  this.ctx.save();
4828
4817
  const bounds = this.el.nativeElement.getBoundingClientRect();
@@ -4830,7 +4819,7 @@ class StatGraphComponent {
4830
4819
  this.canvas.height = bounds.height - 30; // -p height
4831
4820
  this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
4832
4821
  [...this.data].reverse().forEach((val, index) => {
4833
- const h = (val || 0) * this.scaleY;
4822
+ const h = (val || 0) * scaleY;
4834
4823
  this.ctx.fillStyle = this.getColor(this.color(), h);
4835
4824
  this.ctx.fillRect(index * this.tickStep(), this.canvas.height - h, this.tickStep(), h);
4836
4825
  });
@@ -4857,12 +4846,12 @@ class StatGraphComponent {
4857
4846
  this.draw();
4858
4847
  }
4859
4848
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: StatGraphComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
4860
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "21.1.5", type: StatGraphComponent, isStandalone: true, selector: "app-stat-graph", inputs: { stat: { classPropertyName: "stat", publicName: "stat", isSignal: true, isRequired: false, transformFunction: null }, 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 } }, host: { listeners: { "window:resize": "resize()" } }, viewQueries: [{ propertyName: "graph", first: true, predicate: ["graph"], descendants: true, isSignal: 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 }); }
4849
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "21.1.5", type: StatGraphComponent, isStandalone: true, selector: "app-stat-graph", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: true, transformFunction: null }, stat: { classPropertyName: "stat", publicName: "stat", isSignal: true, isRequired: false, transformFunction: null }, color: { classPropertyName: "color", publicName: "color", isSignal: true, isRequired: false, transformFunction: null }, tickStep: { classPropertyName: "tickStep", publicName: "tickStep", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "window:resize": "resize()" } }, viewQueries: [{ propertyName: "graph", first: true, predicate: ["graph"], descendants: true, isSignal: 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 }); }
4861
4850
  }
4862
4851
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: StatGraphComponent, decorators: [{
4863
4852
  type: Component,
4864
4853
  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"] }]
4865
- }], ctorParameters: () => [], propDecorators: { stat: [{ type: i0.Input, args: [{ isSignal: true, alias: "stat", required: false }] }], graph: [{ type: i0.ViewChild, args: ['graph', { isSignal: true }] }], color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], tickStep: [{ type: i0.Input, args: [{ isSignal: true, alias: "tickStep", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: true }] }], resize: [{
4854
+ }], ctorParameters: () => [], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: true }] }], stat: [{ type: i0.Input, args: [{ isSignal: true, alias: "stat", required: false }] }], color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], tickStep: [{ type: i0.Input, args: [{ isSignal: true, alias: "tickStep", required: false }] }], graph: [{ type: i0.ViewChild, args: ['graph', { isSignal: true }] }], resize: [{
4866
4855
  type: HostListener,
4867
4856
  args: ['window:resize']
4868
4857
  }] } });
@@ -4941,11 +4930,11 @@ class UnrealStatusComponent {
4941
4930
  }
4942
4931
  }
4943
4932
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: UnrealStatusComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
4944
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.5", type: UnrealStatusComponent, isStandalone: true, selector: "app-unreal-status", ngImport: i0, template: "@if (showLoader()) {\n <div class=\"status-box\">\n @if (awsInstance()?.message) {\n <p>{{ awsInstance()?.message }}</p>\n } @else {\n <div class=\"status-box__message\">\n <src-loading\n [size]=\"30\"\n [backgroundStrokeColor]=\"'#E5E7EB'\"\n [progressStrokeColor]=\"'#1F2937'\"\n />\n {{ messagePercents() }}%\n </div>\n }\n </div>\n}\n", styles: ["app-stat-graph{height:30px;width:100%}.status-box{position:absolute;top:80%;left:50%;transform:translate(-50%,-50%);z-index:5;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 p{padding:10px 15px;margin:0;text-align:center}.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: SourceLoadingComponent, selector: "src-loading", inputs: ["size", "progress", "lineCap", "backgroundStrokeColor", "progressStrokeColor", "strokeWidth", "data-testid", "role", "ariaLabel", "ariaValueNow", "ariaValueMin", "ariaValueMax"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
4933
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.5", type: UnrealStatusComponent, isStandalone: true, selector: "app-unreal-status", ngImport: i0, template: "@if (showLoader()) {\n <div class=\"status-box\">\n @if (awsInstance()?.message) {\n <p>{{ awsInstance()?.message }}</p>\n } @else {\n <div class=\"status-box__message\">\n <src-loading\n [size]=\"30\"\n [backgroundStrokeColor]=\"'#E5E7EB'\"\n [progressStrokeColor]=\"'#1F2937'\"\n />\n {{ messagePercents() }}%\n </div>\n }\n </div>\n}\n", styles: ["app-stat-graph{height:30px;width:100%}.status-box{position:absolute;top:80%;left:50%;transform:translate(-50%,-50%);z-index:5;display:flex;justify-content:center;align-items:center;width:auto;max-width:500px;margin:0;background:var(--src-surface-container-main, #fff);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 p{padding:10px 15px;margin:0;text-align:center}.status-box__message{display:flex;align-items:center;padding:12px 20px 12px 16px;color:var(--src-text-body-main, #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: SourceLoadingComponent, selector: "src-loading", inputs: ["size", "progress", "lineCap", "backgroundStrokeColor", "progressStrokeColor", "strokeWidth", "data-testid", "role", "ariaLabel", "ariaValueNow", "ariaValueMin", "ariaValueMax"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
4945
4934
  }
4946
4935
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: UnrealStatusComponent, decorators: [{
4947
4936
  type: Component,
4948
- args: [{ selector: 'app-unreal-status', changeDetection: ChangeDetectionStrategy.OnPush, imports: [SourceLoadingComponent], template: "@if (showLoader()) {\n <div class=\"status-box\">\n @if (awsInstance()?.message) {\n <p>{{ awsInstance()?.message }}</p>\n } @else {\n <div class=\"status-box__message\">\n <src-loading\n [size]=\"30\"\n [backgroundStrokeColor]=\"'#E5E7EB'\"\n [progressStrokeColor]=\"'#1F2937'\"\n />\n {{ messagePercents() }}%\n </div>\n }\n </div>\n}\n", styles: ["app-stat-graph{height:30px;width:100%}.status-box{position:absolute;top:80%;left:50%;transform:translate(-50%,-50%);z-index:5;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 p{padding:10px 15px;margin:0;text-align:center}.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"] }]
4937
+ args: [{ selector: 'app-unreal-status', changeDetection: ChangeDetectionStrategy.OnPush, imports: [SourceLoadingComponent], template: "@if (showLoader()) {\n <div class=\"status-box\">\n @if (awsInstance()?.message) {\n <p>{{ awsInstance()?.message }}</p>\n } @else {\n <div class=\"status-box__message\">\n <src-loading\n [size]=\"30\"\n [backgroundStrokeColor]=\"'#E5E7EB'\"\n [progressStrokeColor]=\"'#1F2937'\"\n />\n {{ messagePercents() }}%\n </div>\n }\n </div>\n}\n", styles: ["app-stat-graph{height:30px;width:100%}.status-box{position:absolute;top:80%;left:50%;transform:translate(-50%,-50%);z-index:5;display:flex;justify-content:center;align-items:center;width:auto;max-width:500px;margin:0;background:var(--src-surface-container-main, #fff);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 p{padding:10px 15px;margin:0;text-align:center}.status-box__message{display:flex;align-items:center;padding:12px 20px 12px 16px;color:var(--src-text-body-main, #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"] }]
4949
4938
  }] });
4950
4939
 
4951
4940
  class VideoStatsComponent {
@@ -4954,31 +4943,45 @@ class VideoStatsComponent {
4954
4943
  this.store = inject(Store);
4955
4944
  this.videoService = inject(VideoService);
4956
4945
  this.isDevMode = inject(DevModeService).isDevMode;
4957
- this.videoStats = toSignal(this.videoService.videoStats$);
4946
+ this.obs$ = this.videoService.videoStats$;
4958
4947
  this.viewportReady = this.store.selectSignal(unrealFeature.selectViewportReady);
4959
4948
  this.ssInfo = this.store.selectSignal(selectSignalingParameters);
4960
- this.fpsTick = computed(() => this.videoStats()?.aggregatedStats?.framesPerSecond || 0, ...(ngDevMode ? [{ debugName: "fpsTick" }] : []));
4961
- this.fpsAvgTick = computed(() => this.videoStats()?.aggregatedStats?.avgFrameRate || 0, ...(ngDevMode ? [{ debugName: "fpsAvgTick" }] : []));
4962
- this.bitrateTick = computed(() => this.videoStats()?.aggregatedStats?.bitrate || 0, ...(ngDevMode ? [{ debugName: "bitrateTick" }] : []));
4963
- this.videoQP = computed(() => this.videoStats()?.aggregatedStats?.VideoEncoderQP || 0, ...(ngDevMode ? [{ debugName: "videoQP" }] : []));
4964
- this.bitrateAverageTick = computed(() => this.videoStats()?.aggregatedStats?.avgBitrate || 0, ...(ngDevMode ? [{ debugName: "bitrateAverageTick" }] : []));
4965
- this.videoStatus = computed(() => {
4966
- const videoStats = this.videoStats();
4967
- if (this.isDevMode && videoStats) {
4968
- const data = {
4969
- ...videoStats.aggregatedStats,
4970
- quality: videoStats.quality,
4971
- };
4972
- return this.fields
4973
- .map((key) => ({
4949
+ this.fpsTick = toSignal(this.obs$.pipe(map$1((stat) => ({
4950
+ value: stat.aggregatedStats.framesPerSecond || 0,
4951
+ }))));
4952
+ this.fpsAvgTick = toSignal(this.obs$.pipe(map$1((stat) => ({
4953
+ value: stat.aggregatedStats.avgFrameRate,
4954
+ }))));
4955
+ this.bitrateTick = toSignal(this.obs$.pipe(map$1((stat) => ({
4956
+ value: stat.aggregatedStats.bitrate,
4957
+ }))));
4958
+ this.videoQP = toSignal(this.obs$.pipe(map$1((stat) => ({
4959
+ value: stat.aggregatedStats.VideoEncoderQP,
4960
+ }))));
4961
+ this.bitrateAverageTick = toSignal(this.obs$.pipe(map$1((stat) => ({
4962
+ value: stat.aggregatedStats.avgBitrate,
4963
+ }))));
4964
+ this.videoStatus = toSignal(this.obs$.pipe(map$1((event) => this.isDevMode &&
4965
+ {
4966
+ ...event.aggregatedStats,
4967
+ quality: event.quality,
4968
+ }), filter(Boolean), map$1((data) => {
4969
+ return this.fields
4970
+ .map((key) => {
4971
+ return {
4974
4972
  key,
4975
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
4976
4973
  value: data[key],
4977
- }))
4978
- .filter((value) => !this.elementsToShow.includes(value.key));
4979
- }
4980
- return undefined;
4981
- }, ...(ngDevMode ? [{ debugName: "videoStatus" }] : []));
4974
+ };
4975
+ })
4976
+ .filter((r) => !this.elementsToShow.includes(r.key));
4977
+ })));
4978
+ this.graphList = [];
4979
+ this.idKey = 'com.source3d.unreal.stat';
4980
+ this.elementsToShow = [];
4981
+ this.trigger$ = new BehaviorSubject(undefined);
4982
+ this.getFields();
4983
+ }
4984
+ ngOnInit() {
4982
4985
  this.fields = [
4983
4986
  'kalmanBitrate',
4984
4987
  'bitrateDrop',
@@ -5005,35 +5008,32 @@ class VideoStatsComponent {
5005
5008
  //'pliCount',
5006
5009
  //'sliCount',
5007
5010
  //'transportId',
5008
- //'id'
5011
+ //'id',
5009
5012
  ];
5010
- this.graphList = signal([], ...(ngDevMode ? [{ debugName: "graphList" }] : []));
5011
- this.idKey = 'com.source3d.unreal.stat';
5012
- this.elementsToShow = [];
5013
- this.getFields();
5014
- }
5015
- ngOnInit() {
5016
5013
  this.updateGraph();
5017
5014
  }
5018
5015
  updateGraph() {
5019
- this.graphList.set(this.fields
5020
- .map((key) => {
5016
+ this.graphList = this.fields.map((key) => {
5017
+ const stat = this.obs$.pipe(map$1((val) => {
5018
+ const value = val.aggregatedStats[key];
5019
+ return { value };
5020
+ }));
5021
5021
  return {
5022
5022
  key,
5023
5023
  color: Math.floor(Math.random() * 16777216).toString(),
5024
- stat: this.videoStats()?.aggregatedStats?.[key] || 0,
5024
+ stat,
5025
5025
  };
5026
- })
5027
- .filter((value) => this.elementsToShow.includes(value.key)));
5026
+ });
5027
+ this.graphList$ = of(this.graphList).pipe(combineLatestWith(this.trigger$), map$1(([graphList]) => graphList.filter((r) => this.elementsToShow.includes(r.key))));
5028
5028
  }
5029
5029
  toggle() {
5030
5030
  this.collapsed.update((collapsed) => !collapsed);
5031
5031
  this.writeFields();
5032
5032
  }
5033
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
5034
5033
  toggleGraph($event, el, value) {
5035
5034
  $event.stopPropagation();
5036
- if ((value && typeof value !== 'number') || isNaN(value)) {
5035
+ if ((value && typeof value !== 'number') ||
5036
+ (typeof value === 'number' && isNaN(value))) {
5037
5037
  return;
5038
5038
  }
5039
5039
  if (this.elementsToShow.includes(el)) {
@@ -5043,7 +5043,7 @@ class VideoStatsComponent {
5043
5043
  this.elementsToShow.push(el);
5044
5044
  }
5045
5045
  this.writeFields();
5046
- this.updateGraph();
5046
+ this.trigger$.next();
5047
5047
  }
5048
5048
  getFields() {
5049
5049
  try {
@@ -5062,15 +5062,16 @@ class VideoStatsComponent {
5062
5062
  }));
5063
5063
  }
5064
5064
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: VideoStatsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
5065
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.5", type: VideoStatsComponent, isStandalone: true, selector: "app-video-stats", ngImport: i0, template: "@if (videoStatus() && 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 [stat]=\"fpsTick()\" label=\"FPS (higher is better)\" />\n </li>\n <li>\n <app-stat-graph\n [stat]=\"videoQP()\"\n label=\"QP (lower is better)\"\n color=\"#D5ff07\"\n />\n </li>\n <li>\n <app-stat-graph\n [stat]=\"bitrateTick()\"\n label=\"Bitrate\"\n color=\"#D57F07\"\n />\n </li>\n </div>\n <div>\n @for (graph of graphList(); track graph.key) {\n <li (click)=\"toggleGraph($event, graph.key, 0)\" class=\"graph\">\n <app-stat-graph\n [label]=\"graph.key\"\n [stat]=\"graph.stat\"\n [color]=\"graph.color\"\n />\n </li>\n }\n </div>\n </div>\n\n @for (el of videoStatus(); track el.key) {\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", 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 span{font-weight:700}#aggregatedStats .stat,#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: ["stat", "color", "tickStep", "label"] }, { kind: "pipe", type: JsonPipe, name: "json" }, { kind: "pipe", type: SafePipe, name: "safe" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
5065
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.5", type: VideoStatsComponent, isStandalone: true, selector: "app-video-stats", ngImport: i0, template: "@if (videoStatus() && viewportReady()) {\n <div class=\"settings-container\">\n <button (click)=\"toggle()\" class=\"gear-button\">Stats 2</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 [stat]=\"fpsTick()!\"\n label=\"FPS (higher is better)\"\n />\n </li>\n <li>\n <app-stat-graph\n [stat]=\"videoQP()!\"\n label=\"QP (lower is better)\"\n color=\"#D5ff07\"\n />\n </li>\n <li>\n <app-stat-graph\n [stat]=\"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 [stat]=\"(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", 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 span{font-weight:700}#aggregatedStats .stat,#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: ["label", "stat", "color", "tickStep"] }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "pipe", type: JsonPipe, name: "json" }, { kind: "pipe", type: SafePipe, name: "safe" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
5066
5066
  }
5067
5067
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: VideoStatsComponent, decorators: [{
5068
5068
  type: Component,
5069
- args: [{ selector: 'app-video-stats', changeDetection: ChangeDetectionStrategy.OnPush, imports: [StatGraphComponent, JsonPipe, SafePipe], template: "@if (videoStatus() && 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 [stat]=\"fpsTick()\" label=\"FPS (higher is better)\" />\n </li>\n <li>\n <app-stat-graph\n [stat]=\"videoQP()\"\n label=\"QP (lower is better)\"\n color=\"#D5ff07\"\n />\n </li>\n <li>\n <app-stat-graph\n [stat]=\"bitrateTick()\"\n label=\"Bitrate\"\n color=\"#D57F07\"\n />\n </li>\n </div>\n <div>\n @for (graph of graphList(); track graph.key) {\n <li (click)=\"toggleGraph($event, graph.key, 0)\" class=\"graph\">\n <app-stat-graph\n [label]=\"graph.key\"\n [stat]=\"graph.stat\"\n [color]=\"graph.color\"\n />\n </li>\n }\n </div>\n </div>\n\n @for (el of videoStatus(); track el.key) {\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", 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 span{font-weight:700}#aggregatedStats .stat,#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"] }]
5069
+ args: [{ selector: 'app-video-stats', changeDetection: ChangeDetectionStrategy.OnPush, imports: [StatGraphComponent, AsyncPipe, JsonPipe, SafePipe], template: "@if (videoStatus() && viewportReady()) {\n <div class=\"settings-container\">\n <button (click)=\"toggle()\" class=\"gear-button\">Stats 2</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 [stat]=\"fpsTick()!\"\n label=\"FPS (higher is better)\"\n />\n </li>\n <li>\n <app-stat-graph\n [stat]=\"videoQP()!\"\n label=\"QP (lower is better)\"\n color=\"#D5ff07\"\n />\n </li>\n <li>\n <app-stat-graph\n [stat]=\"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 [stat]=\"(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", 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 span{font-weight:700}#aggregatedStats .stat,#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"] }]
5070
5070
  }], ctorParameters: () => [] });
5071
5071
 
5072
5072
  class ResumeStreamButtonComponent {
5073
5073
  constructor() {
5074
+ this.actions$ = inject(Actions);
5074
5075
  this.store = inject(Store);
5075
5076
  this.videoService = inject(VideoService);
5076
5077
  this.destroyRef = inject(DestroyRef);
@@ -5090,14 +5091,12 @@ class ResumeStreamButtonComponent {
5090
5091
  .subscribe(() => this.onDisconnect());
5091
5092
  }
5092
5093
  ngAfterViewInit() {
5093
- fromSignal(UnrealInternalSignalEvents.ShowPlayButton)
5094
- .pipe(takeUntilDestroyed(this.destroyRef))
5094
+ this.actions$
5095
+ .pipe(ofType(videoStreamInitialized), takeUntilDestroyed(this.destroyRef), filter(() => !!this.videoService.video?.paused))
5095
5096
  .subscribe(() => {
5096
- if (this.videoService.video?.paused) {
5097
- Logger.info('Simulate Press Play');
5098
- this.videoService.play();
5099
- resetAfk();
5100
- }
5097
+ Logger.info('Simulate Press Play');
5098
+ this.videoService.play();
5099
+ this.store.dispatch(resetAfk());
5101
5100
  });
5102
5101
  }
5103
5102
  connect() {
@@ -5107,11 +5106,11 @@ class ResumeStreamButtonComponent {
5107
5106
  this.isSecondStart.set(true);
5108
5107
  }
5109
5108
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: ResumeStreamButtonComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
5110
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.5", type: ResumeStreamButtonComponent, isStandalone: true, selector: "app-resume-stream-button", ngImport: i0, template: "@if (isShowResumeButton()) {\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 [data-testid]=\"'connect-button'\"\n size=\"lg\"\n weight=\"primary\"\n class=\"connect-button\"\n >\n {{ isSecondStart() ? 'Resume' : 'Start' }}\n </src-button>\n </div>\n}\n", styles: [".resume-box{padding:16px;position:absolute;bottom:0;left:50%;gap:12px;z-index:6;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 .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}\n"], dependencies: [{ kind: "component", type: SourceButtonComponent, selector: "src-button", inputs: ["type", "appearance", "weight", "size", "context", "customClass", "isFullWidth", "isPressed", "isDisabled", "isLoading", "isInverted", "iconButton", "srcButtonConfig", "formID", "data-testid", "ariaLabel"], outputs: ["onClick", "onSubmit"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
5109
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.5", type: ResumeStreamButtonComponent, isStandalone: true, selector: "app-resume-stream-button", ngImport: i0, template: "@if (isShowResumeButton()) {\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 [data-testid]=\"'connect-button'\"\n size=\"lg\"\n weight=\"primary\"\n class=\"connect-button\"\n >\n {{ isSecondStart() ? 'Resume' : 'Start' }}\n </src-button>\n </div>\n}\n", styles: [".resume-box{padding:16px;position:absolute;bottom:0;left:50%;gap:12px;z-index:6;display:flex;transform:translate(-50%,-50%);flex-direction:column;align-items:center;border-radius:var(--src-border-rounded-parent, 8px);background:var(--src-surface-container-main, #fff);box-shadow:0 26px 80px #0003,0 0 1px #0003}.resume-box .connect-button{width:100%}.resume-box .resume-box__text{color:var(--src-color-grey-500, #6b7280);text-align:center;font-family:var(--src-font-family-body);font-size:14px;font-style:normal;font-weight:400;line-height:24px}\n"], dependencies: [{ kind: "component", type: SourceButtonComponent, selector: "src-button", inputs: ["type", "appearance", "weight", "size", "context", "customClass", "isFullWidth", "isPressed", "isDisabled", "isLoading", "isInverted", "iconButton", "srcButtonConfig", "formID", "data-testid", "ariaLabel"], outputs: ["onClick", "onSubmit"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
5111
5110
  }
5112
5111
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: ResumeStreamButtonComponent, decorators: [{
5113
5112
  type: Component,
5114
- args: [{ selector: 'app-resume-stream-button', changeDetection: ChangeDetectionStrategy.OnPush, imports: [SourceButtonComponent], template: "@if (isShowResumeButton()) {\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 [data-testid]=\"'connect-button'\"\n size=\"lg\"\n weight=\"primary\"\n class=\"connect-button\"\n >\n {{ isSecondStart() ? 'Resume' : 'Start' }}\n </src-button>\n </div>\n}\n", styles: [".resume-box{padding:16px;position:absolute;bottom:0;left:50%;gap:12px;z-index:6;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 .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}\n"] }]
5113
+ args: [{ selector: 'app-resume-stream-button', changeDetection: ChangeDetectionStrategy.OnPush, imports: [SourceButtonComponent], template: "@if (isShowResumeButton()) {\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 [data-testid]=\"'connect-button'\"\n size=\"lg\"\n weight=\"primary\"\n class=\"connect-button\"\n >\n {{ isSecondStart() ? 'Resume' : 'Start' }}\n </src-button>\n </div>\n}\n", styles: [".resume-box{padding:16px;position:absolute;bottom:0;left:50%;gap:12px;z-index:6;display:flex;transform:translate(-50%,-50%);flex-direction:column;align-items:center;border-radius:var(--src-border-rounded-parent, 8px);background:var(--src-surface-container-main, #fff);box-shadow:0 26px 80px #0003,0 0 1px #0003}.resume-box .connect-button{width:100%}.resume-box .resume-box__text{color:var(--src-color-grey-500, #6b7280);text-align:center;font-family:var(--src-font-family-body);font-size:14px;font-style:normal;font-weight:400;line-height:24px}\n"] }]
5115
5114
  }] });
5116
5115
 
5117
5116
  class IntroSrcComponent {
@@ -5205,6 +5204,7 @@ class UnrealSceneComponent {
5205
5204
  this.changeMouseOverScene = output();
5206
5205
  this.width = FULL_HD_WIDTH;
5207
5206
  this.height = FULL_HD_HEIGHT;
5207
+ this.actions$ = inject(Actions);
5208
5208
  this.store = inject(Store);
5209
5209
  this.isExistMatchUrls = this.store.selectSignal(selectIsExistMatchUrls);
5210
5210
  this.isDevMode = inject(DevModeService).isDevMode;
@@ -5242,7 +5242,7 @@ class UnrealSceneComponent {
5242
5242
  this.width = width;
5243
5243
  this.height = height;
5244
5244
  }));
5245
- const resizeRequired$ = merge(fromSignal(UnrealInternalSignalEvents.OnVideoInitialized), fromEvent(window, 'resize'));
5245
+ const resizeRequired$ = merge(this.actions$.pipe(ofType(videoStreamInitialized)), fromEvent(window, 'resize'));
5246
5246
  const videoStreamSizeChanged$ = this.videoService?.videoStats$.pipe(filter(() => !this.isFreezeFrameLoading()), map$1((stats) => ({
5247
5247
  w: stats.aggregatedStats.frameWidth || 0,
5248
5248
  h: stats.aggregatedStats.frameHeight || 0,
@@ -5263,11 +5263,9 @@ class UnrealSceneComponent {
5263
5263
  this.store.dispatch(changeStreamResolutionAction({ width: size.w, height: size.h }));
5264
5264
  this.sendResize(size);
5265
5265
  });
5266
- fromSignal(UnrealInternalSignalEvents.ForceResizeViewport)
5267
- .pipe(takeUntilDestroyed(this.destroyRef))
5268
- .subscribe(() => {
5269
- this.sendResize(this.resizeValues);
5270
- });
5266
+ this.actions$
5267
+ .pipe(ofType(forceResizeViewport), takeUntilDestroyed(this.destroyRef))
5268
+ .subscribe(() => this.sendResize(this.resizeValues));
5271
5269
  }
5272
5270
  adaptVideo(size) {
5273
5271
  const video = this.videoService.video;
@@ -5283,7 +5281,7 @@ class UnrealSceneComponent {
5283
5281
  video.style.height = `${video.height}px`;
5284
5282
  }
5285
5283
  }
5286
- sendSignal(UnrealInternalSignalEvents.VideoAdaptedToContainer);
5284
+ this.store.dispatch(videoAdaptedToContainer());
5287
5285
  }
5288
5286
  /**
5289
5287
  * This method calculates the dimensions for resizing a layout in a configurator stream.
@@ -5403,11 +5401,11 @@ class WebrtcErrorModalComponent {
5403
5401
  });
5404
5402
  }
5405
5403
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: WebrtcErrorModalComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
5406
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.1.5", 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\"></header>\n <section class=\"src-modal__body\">\n <div [attr.data-testid]=\"'title'\" class=\"src-modal__title\">\n WebRTC error\n </div>\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 weight=\"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", "weight", "size", "context", "customClass", "isFullWidth", "isPressed", "isDisabled", "isLoading", "isInverted", "iconButton", "srcButtonConfig", "formID", "data-testid", "ariaLabel"], outputs: ["onClick", "onSubmit"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
5404
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.1.5", 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\"></header>\n <section class=\"src-modal__body\">\n <div [attr.data-testid]=\"'title'\" class=\"src-modal__title\">\n WebRTC error\n </div>\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 weight=\"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-text-body-main, #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", "weight", "size", "context", "customClass", "isFullWidth", "isPressed", "isDisabled", "isLoading", "isInverted", "iconButton", "srcButtonConfig", "formID", "data-testid", "ariaLabel"], outputs: ["onClick", "onSubmit"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
5407
5405
  }
5408
5406
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: WebrtcErrorModalComponent, decorators: [{
5409
5407
  type: Component,
5410
- 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\"></header>\n <section class=\"src-modal__body\">\n <div [attr.data-testid]=\"'title'\" class=\"src-modal__title\">\n WebRTC error\n </div>\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 weight=\"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"] }]
5408
+ 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\"></header>\n <section class=\"src-modal__body\">\n <div [attr.data-testid]=\"'title'\" class=\"src-modal__title\">\n WebRTC error\n </div>\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 weight=\"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-text-body-main, #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"] }]
5411
5409
  }] });
5412
5410
 
5413
5411
  class FilterSettingsComponent {
@@ -5475,7 +5473,7 @@ class LowBandwidthDetectorComponent {
5475
5473
  .pipe(combineLatestWith(this.isLowBandwidth$), map(([viewPortReady, isLowBandwidth]) => viewPortReady && !isLowBandwidth))
5476
5474
  .pipe(share());
5477
5475
  this.reTrigger$ = this.monitoringTrigger$.pipe(map(() => ({ quality: 'lime' })));
5478
- this.canSwitchToLowBand$ = this.monitoringTrigger$.pipe(debounceTime(100), switchMap((canSwitch) => concat(of(false), timer(FilterModel.monitoringDelayTime).pipe(map(() => canSwitch))).pipe(take(2), takeUntil$1(this.monitoringTrigger$))), distinctUntilChanged$1(), tapLog('DROP: [LOWBANDWIDTH] Monitoring Active =>'), share());
5476
+ this.canSwitchToLowBand$ = this.monitoringTrigger$.pipe(debounceTime(100), switchMap((canSwitch) => concat(of(false), timer(FilterModel.monitoringDelayTime).pipe(map(() => canSwitch))).pipe(take(2), takeUntil$1(this.monitoringTrigger$))), distinctUntilChanged$1(), share());
5479
5477
  this.videoQuality$ = merge(this.nativeQuality$, this.reTrigger$).pipe(share(), takeUntil$1(this.viewPortDestroyedTrigger$));
5480
5478
  this.fps$ = this.aggregatedStats$.pipe(map((data) => data.framesPerSecond || 0));
5481
5479
  this.bitrateDrop$ = this.aggregatedStats$.pipe(map((data) => data.dataFlowCheckResult), filter((br) => br.isDropDetected), takeUntil$1(merge(this.viewPortDestroyedTrigger$, this.reTrigger$)));
@@ -5647,5 +5645,5 @@ function provideAngularUnrealModule(config) {
5647
5645
  * Generated bundle index. Do not edit.
5648
5646
  */
5649
5647
 
5650
- export { AFKService, AfkPlaywrightService, AfkTimeoutModalComponent, AggregatorPlaywrightService, AggregatorService, AnalyticsService, AnswerHandler, CONSOLE_COMMAND_DISABLE_MESSAGES, CONSOLE_COMMAND_ENABLE_MESSAGES, CONSOLE_COMMAND_PIXEL_QUALITY, CommandTelemetryPlaywrightService, CommandTelemetryService, ConfigHandler, ConsoleExtensionsPlaywrightService, ConsoleExtensionsService, ControlScheme, DATA_CHANNEL_CONNECTION_TIMEOUT, DEBOUNCE_TO_MANY_RESIZE_CALLS, DEFAULT_AFK_TIMEOUT, DEFAULT_AFK_TIMEOUT_PERIOD, DEFAULT_RECONNECT_DELAY_MS, DEFAULT_RECONNECT_ENABLED, DEFAULT_RECONNECT_MAX_ATTEMPTS, DEFAULT_RECONNECT_ON_DATACHANNEL_CLOSE, DEFAULT_RECONNECT_ON_ICE_FAILURE, DataFlowMonitor, DevModeService, DisconnectReason, FULL_HD_HEIGHT, FULL_HD_WIDTH, FileHandlerService, FileReceiverPlaywrightService, FileReceiverService, FilterSettingsComponent, FpsMonitorService, FreezeFrameComponent, FreezeFramePlaywrightService, FreezeFrameService, IceCandidateHandler, ImageLoadingSrcComponent, InputOptions, InputPlaywrightService, InputService, InstanceReadyHandler, InstanceReservedHandler, IntroSrcComponent, KalmanFilter1D, LatencyTimings, LowBandwidthDetectorComponent, LowBandwidthModalComponent, MINIMAL_FPS, MessageType, MouseButton, MouseButtonsMask, OnCloseHandler, OnErrorHandler, OnMessageHandler, OnOpenHandler, OrchestrationMessageTypes, POLLING_TIME, PingHandler, PlayerCountHandler, RegionsPingService, SAME_SIZE_THRESHOLD, SCREEN_LOCKER_CONTAINER_ID, SIGNALLING_PERCENT_VALUE, SSInfoHandler, STREAMING_VIDEO_ID, SafePipe, SignallingPlaywrightService, SignallingService, SpecialKeyCodes, StatGraphComponent, StreamStatusTelemetryPlaywrightService, StreamStatusTelemetryService, SubService, ToClientMessage, UNREAL_CONFIG, UnrealCommunicatorPlaywrightService, UnrealCommunicatorService, UnrealEffects, UnrealInternalSignalEvents, UnrealSceneComponent, UnrealStatusMessage, 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, WSCloseCode_UNKNOWN, WSCloseCodes, WS_OPEN_STATE, WS_TIMEOUT, WebRtcPlayerService, WebrtcErrorModalComponent, abortEstablishingConnection, changeLowBandwidth, changeStatusMainVideoOnScene, changeStreamResolutionAction, changeStreamResolutionSuccessAction, commandCompleted, commandStarted, dataChannelConnected, dataChannelReady, decodeData, destroyRemoteConnections, destroyUnrealScene, disconnectStream, dispatchResize, dropConnection, floatToSmoothPercents, forceResizeUnrealVideo, fromResizeObserver, fromSignal, fromUnrealCallBackSignal, getActiveUrl, getImageFromVideoStream, getRtcErrorMessage, iceConnectionFailed, initSignalling, initialState, keepMaxUntilReset, observeCommandResponse, provideAngularUnrealModule, qpToQuality, reconnectPeer, reconnectPeerFailed, reconnectPeerSuccess, removeExileCommands, resetAfk, resetAfkAction, resetConfig, resetDataChannelForReconnect, resetIntroSrc, resetWarnTimeout, saveAnalyticsEvent, selectClientAndViewIds, selectCommandProgress, selectCommandsInProgress, selectFreezeFrameCombinedDataUrl, selectFreezeFrameDataUrl, selectFreezeFrameDataUrlFromVideo, selectFreezeFrameProgressMessageFromVideo, selectIsAutostart, selectIsExistMatchUrls, selectIsFreezeFrameLoading, selectIsLoaderScreenVisible, selectIsShowPopupWithoutAutoStart, selectIsVideoPlayingAndDataChannelConnected, selectLastCommandInProgress, selectLoaderCommands, selectShowLoader, selectShowReconnectPopup, selectSignalingParameters, selectStreamConfig, selectTotalProgress, selectWarnTimeout, sendSignal, setAfkTimerCountdown, setAfkTimerHide, setAfkTimerVisible, setAwsInstance, setCirrusConnected, setCirrusDisconnected, setConfig, setDataChannelConnected, setEstablishingConnection, setFreezeFrame, setFreezeFrameFromVideo, setIntroImageSrc, setIntroVideoSrc, setLoadingImageSrc, setLoopBackCommandIsCompleted, setMaxFps, setOrchestrationContext, setOrchestrationMessage, setOrchestrationParameters, setOrchestrationProgress, setSignalingName, setStatusMessage, setStatusPercentSignallingServer, setStreamClientCompanyId, setStreamViewId, setUnrealPlaywrightConfig, setViewportNotReady, setViewportReady, showUnrealErrorMessage, smoothTransition, startStream, trackMixpanelEvent, unrealFeature, unrealReducer, updateCirrusInfo };
5648
+ export { AFKService, AfkPlaywrightService, AfkTimeoutModalComponent, AggregatorPlaywrightService, AggregatorService, AnalyticsService, AnswerHandler, CONSOLE_COMMAND_DISABLE_MESSAGES, CONSOLE_COMMAND_ENABLE_MESSAGES, CONSOLE_COMMAND_PIXEL_QUALITY, CommandTelemetryPlaywrightService, CommandTelemetryService, ConfigHandler, ConsoleExtensionsPlaywrightService, ConsoleExtensionsService, ControlScheme, DATA_CHANNEL_CONNECTION_TIMEOUT, DEBOUNCE_TO_MANY_RESIZE_CALLS, DEFAULT_AFK_TIMEOUT, DEFAULT_AFK_TIMEOUT_PERIOD, DEFAULT_RECONNECT_DELAY_MS, DEFAULT_RECONNECT_ENABLED, DEFAULT_RECONNECT_MAX_ATTEMPTS, DEFAULT_RECONNECT_ON_DATACHANNEL_CLOSE, DEFAULT_RECONNECT_ON_ICE_FAILURE, DataFlowMonitor, DevModeService, DisconnectReason, FULL_HD_HEIGHT, FULL_HD_WIDTH, FileHandlerService, FileReceiverPlaywrightService, FileReceiverService, FilterSettingsComponent, FpsMonitorService, FreezeFrameComponent, FreezeFramePlaywrightService, FreezeFrameService, IceCandidateHandler, ImageLoadingSrcComponent, InputOptions, InputPlaywrightService, InputService, InstanceReadyHandler, InstanceReservedHandler, IntroSrcComponent, KalmanFilter1D, LatencyTimings, LowBandwidthDetectorComponent, LowBandwidthModalComponent, MINIMAL_FPS, MessageType, MouseButton, MouseButtonsMask, OnCloseHandler, OnErrorHandler, OnMessageHandler, OnOpenHandler, OrchestrationMessageTypes, POLLING_TIME, PingHandler, PlayerCountHandler, RegionsPingService, SAME_SIZE_THRESHOLD, SCREEN_LOCKER_CONTAINER_ID, SIGNALLING_PERCENT_VALUE, SSInfoHandler, STREAMING_VIDEO_ID, SafePipe, SignallingPlaywrightService, SignallingService, SpecialKeyCodes, StatGraphComponent, StreamStatusTelemetryPlaywrightService, StreamStatusTelemetryService, SubService, ToClientMessage, UNREAL_CONFIG, UnrealCommunicatorPlaywrightService, UnrealCommunicatorService, UnrealEffects, UnrealInternalSignalEvents, UnrealSceneComponent, UnrealStatusMessage, 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, WSCloseCode_UNKNOWN, WSCloseCodes, WS_OPEN_STATE, WS_TIMEOUT, WebRtcPlayerService, WebrtcErrorModalComponent, abortEstablishingConnection, changeLowBandwidth, changeStatusMainVideoOnScene, changeStreamResolutionAction, changeStreamResolutionSuccessAction, commandCompleted, commandStarted, dataChannelConnected, dataChannelReady, decodeData, destroyRemoteConnections, destroyUnrealScene, disconnectStream, dispatchResize, dropConnection, floatToSmoothPercents, forceResizeViewport, fromResizeObserver, fromSignal, fromUnrealCallBackSignal, getActiveUrl, getImageFromVideoStream, getRtcErrorMessage, iceConnectionFailed, initSignalling, initialState, keepMaxUntilReset, observeCommandResponse, provideAngularUnrealModule, qpToQuality, reconnectPeer, reconnectPeerFailed, reconnectPeerSuccess, removeExileCommands, resetAfk, resetConfig, resetDataChannelForReconnect, resetIntroSrc, resetWarnTimeout, saveAnalyticsEvent, selectClientAndViewIds, selectCommandProgress, selectCommandsInProgress, selectFreezeFrameCombinedDataUrl, selectFreezeFrameDataUrl, selectFreezeFrameDataUrlFromVideo, selectFreezeFrameProgressMessageFromVideo, selectIsAutostart, selectIsExistMatchUrls, selectIsFreezeFrameLoading, selectIsLoaderScreenVisible, selectIsShowPopupWithoutAutoStart, selectIsVideoPlayingAndDataChannelConnected, selectLastCommandInProgress, selectLoaderCommands, selectShowLoader, selectShowReconnectPopup, selectSignalingParameters, selectStreamConfig, selectTotalProgress, selectWarnTimeout, sendSignal, setAfkTimerCountdown, setAfkTimerHide, setAfkTimerVisible, setAwsInstance, setCirrusConnected, setCirrusDisconnected, setConfig, setDataChannelConnected, setEstablishingConnection, setFreezeFrame, setFreezeFrameFromVideo, setIntroImageSrc, setIntroVideoSrc, setLoadingImageSrc, setLoopBackCommandIsCompleted, setMaxFps, setOrchestrationContext, setOrchestrationMessage, setOrchestrationParameters, setOrchestrationProgress, setSignalingName, setStatusMessage, setStatusPercentSignallingServer, setStreamClientCompanyId, setStreamViewId, setUnrealPlaywrightConfig, setViewportNotReady, setViewportReady, showUnrealErrorMessage, smoothTransition, startStream, trackMixpanelEvent, unrealFeature, unrealReducer, updateCirrusInfo, videoAdaptedToContainer, videoStreamInitialized };
5651
5649
  //# sourceMappingURL=3dsource-angular-unreal-module.mjs.map