@3dsource/angular-unreal-module 0.0.112 → 0.0.113-dev.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { InjectionToken, inject, ChangeDetectionStrategy, Component, Injectable, DestroyRef, effect, untracked, signal, Pipe, input, ElementRef, viewChild, afterNextRender, HostListener,
|
|
2
|
+
import { InjectionToken, inject, ChangeDetectionStrategy, Component, Injectable, DestroyRef, effect, untracked, signal, computed, Pipe, input, ElementRef, viewChild, afterNextRender, HostListener, output, makeEnvironmentProviders, provideEnvironmentInitializer } from '@angular/core';
|
|
3
3
|
import { SourceButtonComponent, SourceLoadingComponent } from '@3dsource/source-ui-native';
|
|
4
|
-
import { merge, map, scan, concatMap, of, animationFrameScheduler, interval, Observable,
|
|
4
|
+
import { merge, map, scan, concatMap, of, animationFrameScheduler, interval, Observable, skip, switchMap, concat, delay, debounceTime, timer, take, timeout, mergeMap, EMPTY, Subject, share, from, fromEvent, throwError, defer, retry, tap as tap$1, takeUntil as takeUntil$1, NEVER, startWith, throttleTime, asyncScheduler, filter as filter$1, withLatestFrom as withLatestFrom$1, pairwise, Subscription, bufferTime, combineLatestWith, distinctUntilChanged as distinctUntilChanged$1 } from 'rxjs';
|
|
5
5
|
import { createAction, props, createReducer, on, createFeature, createSelector, Store, provideState } from '@ngrx/store';
|
|
6
6
|
import { Actions, createEffect, ofType, provideEffects } from '@ngrx/effects';
|
|
7
|
-
import { map as map$1, distinctUntilChanged, takeWhile, filter, tap,
|
|
8
|
-
import { Logger, calculateMedian, clampf, lerp, getCanvasCached, getSnapshot, fitIntoRectangle, whereNot, Truthy,
|
|
7
|
+
import { map as map$1, distinctUntilChanged, takeWhile, filter, tap, takeUntil, catchError, withLatestFrom, exhaustMap, switchMap as switchMap$1, timeout as timeout$1, debounceTime as debounceTime$1, take as take$1, startWith as startWith$1 } from 'rxjs/operators';
|
|
8
|
+
import { Logger, calculateMedian, clampf, lerp, getCanvasCached, getSnapshot, fitIntoRectangle, whereNot, Truthy, tapLog, Falsy, generateUuid, COLOR_CODES, where, KeyboardNumericCode, InvertedKeyMap, Semaphore, HEXtoRGB, RGBtoHSV, inverseLerp, HSVtoRGB, RGBtoHEX, fpIsASameAsB } from '@3dsource/utils';
|
|
9
9
|
import { concatLatestFrom } from '@ngrx/operators';
|
|
10
10
|
import { DialogRef, DIALOG_DATA, Dialog } from '@angular/cdk/dialog';
|
|
11
11
|
import { HttpClient } from '@angular/common/http';
|
|
12
12
|
import { ScrollStrategyOptions } from '@angular/cdk/overlay';
|
|
13
13
|
import { MetaBoxCommand, EPayloadVersion } from '@3dsource/types-unreal';
|
|
14
|
-
import { toSignal,
|
|
14
|
+
import { toSignal, toObservable, takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
15
15
|
import { v4 } from 'uuid';
|
|
16
16
|
import { DomSanitizer } from '@angular/platform-browser';
|
|
17
17
|
import { NgOptimizedImage, AsyncPipe, JsonPipe } from '@angular/common';
|
|
@@ -116,10 +116,92 @@ const InputOptions = {
|
|
|
116
116
|
suppressBrowserKeys: true,
|
|
117
117
|
};
|
|
118
118
|
|
|
119
|
+
const WSCloseCode_NORMAL_CLOSURE = 3000;
|
|
120
|
+
const WSCloseCode_NORMAL_AFK_TIMEOUT = 3001;
|
|
121
|
+
const WSCloseCode_NORMAL_MANUAL_DISCONNECT = 3002;
|
|
122
|
+
const WSCloseCode_FORCE_CIRRUS_CLOSE = 3003;
|
|
123
|
+
const WSCloseCode_UNKNOWN = 1000;
|
|
124
|
+
const WSCloseCode_CIRRUS_PLAYER_DISCONNECTED = 1001;
|
|
125
|
+
const WSCloseCode_CIRRUS_ABNORMAL_CLOSURE = 1006;
|
|
126
|
+
const WSCloseCode_CIRRUS_MAX_PLAYERS_ERROR = 1013;
|
|
127
|
+
const WSCloseCode_CIRRUS_STREAMER_KIKED_PLAYER = 1011;
|
|
128
|
+
const WSCloseCodes = [
|
|
129
|
+
WSCloseCode_NORMAL_CLOSURE,
|
|
130
|
+
WSCloseCode_NORMAL_AFK_TIMEOUT,
|
|
131
|
+
WSCloseCode_NORMAL_MANUAL_DISCONNECT,
|
|
132
|
+
WSCloseCode_FORCE_CIRRUS_CLOSE,
|
|
133
|
+
WSCloseCode_UNKNOWN,
|
|
134
|
+
WSCloseCode_CIRRUS_PLAYER_DISCONNECTED,
|
|
135
|
+
WSCloseCode_CIRRUS_ABNORMAL_CLOSURE,
|
|
136
|
+
WSCloseCode_CIRRUS_MAX_PLAYERS_ERROR,
|
|
137
|
+
WSCloseCode_CIRRUS_STREAMER_KIKED_PLAYER,
|
|
138
|
+
];
|
|
139
|
+
|
|
140
|
+
const DisconnectReason = {
|
|
141
|
+
Afk: 'Afk',
|
|
142
|
+
None: 'None',
|
|
143
|
+
Destroy: 'Destroy',
|
|
144
|
+
DataChannelClosed: 'DataChannelClosed',
|
|
145
|
+
DataChannelTimeout: 'DataChannelTimeout',
|
|
146
|
+
WebRTCError: 'WebRTCError',
|
|
147
|
+
WebSocketError: 'WebSocketError',
|
|
148
|
+
WebSocketClose: 'WebSocketClose',
|
|
149
|
+
DropConnection: 'DropConnection',
|
|
150
|
+
OrchestrationPlayerDisconnected: 'OrchestrationPlayerDisconnected',
|
|
151
|
+
OrchestrationStreamerDisconnected: 'OrchestrationStreamerDisconnected',
|
|
152
|
+
IceConnectionFailed: 'IceConnectionFailed',
|
|
153
|
+
ReconnectFailed: 'ReconnectFailed',
|
|
154
|
+
NewConnectionAttempt: 'NewConnectionAttempt',
|
|
155
|
+
AbortEstablishingConnection: 'AbortEstablishingConnection',
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
/*
|
|
159
|
+
export interface RequestReservation extends InstanceMessageBase {
|
|
160
|
+
type: 'requestReservation';
|
|
161
|
+
}
|
|
162
|
+
*/
|
|
163
|
+
const OrchestrationMessageTypes = {
|
|
164
|
+
ping: 'ping',
|
|
165
|
+
error: 'error',
|
|
166
|
+
offer: 'offer',
|
|
167
|
+
answer: 'answer',
|
|
168
|
+
ssInfo: 'ssInfo',
|
|
169
|
+
config: 'config',
|
|
170
|
+
playerCount: 'playerCount',
|
|
171
|
+
iceCandidate: 'iceCandidate',
|
|
172
|
+
streamerList: 'streamerList',
|
|
173
|
+
requestStream: 'requestStream',
|
|
174
|
+
listStreamers: 'listStreamers',
|
|
175
|
+
instanceReady: 'instanceReady',
|
|
176
|
+
p2pEstablished: 'p2pEstablished',
|
|
177
|
+
instanceReserved: 'instanceReserved',
|
|
178
|
+
playerDisconnected: 'playerDisconnected',
|
|
179
|
+
streamPreparedForUserInteraction: 'streamPreparedForUserInteraction',
|
|
180
|
+
streamerDisconnected: 'streamerDisconnected',
|
|
181
|
+
interruptClientStream: 'interruptClientStream',
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
/** Disconnect reasons that should trigger remote connection cleanup. */
|
|
185
|
+
const DESTROY_DISCONNECT_REASONS = [
|
|
186
|
+
DisconnectReason.Afk,
|
|
187
|
+
DisconnectReason.DataChannelClosed,
|
|
188
|
+
DisconnectReason.DataChannelTimeout,
|
|
189
|
+
DisconnectReason.WebSocketError,
|
|
190
|
+
DisconnectReason.WebSocketClose,
|
|
191
|
+
DisconnectReason.WebRTCError,
|
|
192
|
+
DisconnectReason.DropConnection,
|
|
193
|
+
DisconnectReason.ReconnectFailed,
|
|
194
|
+
DisconnectReason.OrchestrationPlayerDisconnected,
|
|
195
|
+
DisconnectReason.OrchestrationStreamerDisconnected,
|
|
196
|
+
];
|
|
197
|
+
|
|
119
198
|
const DEBOUNCE_TO_MANY_RESIZE_CALLS = 100;
|
|
120
199
|
const SAME_SIZE_THRESHOLD = 1.01;
|
|
200
|
+
// Minimum container dimension in px — prevents division by zero in resize calculations
|
|
201
|
+
const MIN_CONTAINER_SIZE = 2;
|
|
121
202
|
const MINIMAL_FPS = 6;
|
|
122
203
|
const STREAMING_VIDEO_ID = 'streamingVideo';
|
|
204
|
+
const STREAMING_AUDIO_ID = 'streamingAudio';
|
|
123
205
|
const CONSOLE_COMMAND_ENABLE_MESSAGES = 'EnableAllScreenMessages';
|
|
124
206
|
const CONSOLE_COMMAND_DISABLE_MESSAGES = 'DisableAllScreenMessages';
|
|
125
207
|
const CONSOLE_COMMAND_PIXEL_QUALITY = 'PixelStreaming.FreezeFrameQuality 95';
|
|
@@ -129,7 +211,7 @@ const WS_TIMEOUT = 2000;
|
|
|
129
211
|
const POLLING_TIME = 4000;
|
|
130
212
|
const WS_OPEN_STATE = 1;
|
|
131
213
|
const DEFAULT_AFK_TIMEOUT_PERIOD = 15;
|
|
132
|
-
const DEFAULT_AFK_TIMEOUT =
|
|
214
|
+
const DEFAULT_AFK_TIMEOUT = 10;
|
|
133
215
|
const DATA_CHANNEL_CONNECTION_TIMEOUT = 8000; //ms;
|
|
134
216
|
const SIGNALLING_PERCENT_VALUE = 56;
|
|
135
217
|
const SCREEN_LOCKER_CONTAINER_ID = '3dsource_start_screen';
|
|
@@ -152,7 +234,6 @@ const commandCompleted = createAction(scoped$1 `command completed`, props());
|
|
|
152
234
|
const scoped = (templateString) => `[UNREAL] ${templateString[0]}`;
|
|
153
235
|
const trackMixpanelEvent = createAction(scoped `track mixpanel event`, props());
|
|
154
236
|
const trackTelemetryData = createAction(scoped `track telemetry data`, props());
|
|
155
|
-
const changeLowBandwidth = createAction(scoped `change low bandwidth`, props());
|
|
156
237
|
const setMaxFps = createAction(scoped `change fps`, props());
|
|
157
238
|
const destroyRemoteConnections = createAction(scoped `destroyRemoteConnections`, props());
|
|
158
239
|
const destroyUnrealScene = createAction(scoped `destroyUnrealScene`);
|
|
@@ -171,10 +252,6 @@ const setIntroVideoSrc = createAction(scoped `set intro video src`, props());
|
|
|
171
252
|
const resetIntroSrc = createAction(scoped `reset intro src`);
|
|
172
253
|
const setFreezeFrameFromVideo = createAction(scoped `set freeze frame from video`, props());
|
|
173
254
|
const setEstablishingConnection = createAction(scoped `set establishing connection`, props());
|
|
174
|
-
/**
|
|
175
|
-
* @deprecated Use `dataChannelReady` instead. Currently, this action is not working.
|
|
176
|
-
*/
|
|
177
|
-
const setDataChannelConnected = createAction(scoped `set data channel connected`, props());
|
|
178
255
|
const dataChannelConnected = createAction(scoped `data channel connected`, props());
|
|
179
256
|
const dataChannelReady = createAction(scoped `dataChannelReady`);
|
|
180
257
|
const setConfig = createAction(scoped `set config`, props());
|
|
@@ -236,11 +313,7 @@ const setAfkTimerVisible = createAction(scoped `set afk timer visible`);
|
|
|
236
313
|
const setAfkTimerHide = createAction(scoped `set afk timer hide`);
|
|
237
314
|
const setAfkTimerCountdown = createAction(scoped `set afk timer count down`, props());
|
|
238
315
|
const showUnrealErrorMessage = createAction(scoped `show unreal error message`, props());
|
|
239
|
-
const initSignalling = createAction(scoped `init signalling`, (
|
|
240
|
-
resetDisconnectionReason: true,
|
|
241
|
-
}) => ({
|
|
242
|
-
resetDisconnectionReason: data.resetDisconnectionReason,
|
|
243
|
-
}));
|
|
316
|
+
const initSignalling = createAction(scoped `init signalling`, (resetDisconnectionReason = true) => ({ resetDisconnectionReason }));
|
|
244
317
|
const startStream = createAction(scoped `startStream`, props());
|
|
245
318
|
const resetConfig = createAction(scoped `reset config`);
|
|
246
319
|
const resetAfk = createAction(scoped `reset afk action`);
|
|
@@ -261,83 +334,20 @@ const iceConnectionFailed = createAction(scoped `ice connection failed`, props()
|
|
|
261
334
|
const forceResizeViewport = createAction(scoped `force resize viewport`);
|
|
262
335
|
const videoAdaptedToContainer = createAction(scoped `video adapted to container`);
|
|
263
336
|
const videoStreamInitialized = createAction(scoped `video stream initialized`);
|
|
264
|
-
const setKalmanSettings = createAction(scoped `set kalman settings`, props());
|
|
265
337
|
const dropDC = createAction(scoped `drop data channel`);
|
|
266
338
|
const dropPC = createAction(scoped `drop peer connection`);
|
|
267
|
-
|
|
268
|
-
const
|
|
269
|
-
const
|
|
270
|
-
const
|
|
271
|
-
const
|
|
272
|
-
const WSCloseCode_UNKNOWN = 1000;
|
|
273
|
-
const WSCloseCode_CIRRUS_PLAYER_DISCONNECTED = 1001;
|
|
274
|
-
const WSCloseCode_CIRRUS_ABNORMAL_CLOSURE = 1006;
|
|
275
|
-
const WSCloseCode_CIRRUS_MAX_PLAYERS_ERROR = 1013;
|
|
276
|
-
const WSCloseCode_CIRRUS_STREAMER_KIKED_PLAYER = 1011;
|
|
277
|
-
const WSCloseCodes = [
|
|
278
|
-
WSCloseCode_NORMAL_CLOSURE,
|
|
279
|
-
WSCloseCode_NORMAL_AFK_TIMEOUT,
|
|
280
|
-
WSCloseCode_NORMAL_MANUAL_DISCONNECT,
|
|
281
|
-
WSCloseCode_FORCE_CIRRUS_CLOSE,
|
|
282
|
-
WSCloseCode_UNKNOWN,
|
|
283
|
-
WSCloseCode_CIRRUS_PLAYER_DISCONNECTED,
|
|
284
|
-
WSCloseCode_CIRRUS_ABNORMAL_CLOSURE,
|
|
285
|
-
WSCloseCode_CIRRUS_MAX_PLAYERS_ERROR,
|
|
286
|
-
WSCloseCode_CIRRUS_STREAMER_KIKED_PLAYER,
|
|
287
|
-
];
|
|
288
|
-
|
|
289
|
-
const DisconnectReason = {
|
|
290
|
-
Afk: 'Afk',
|
|
291
|
-
None: 'None',
|
|
292
|
-
Destroy: 'Destroy',
|
|
293
|
-
DataChannelClosed: 'DataChannelClosed',
|
|
294
|
-
DataChannelTimeout: 'DataChannelTimeout',
|
|
295
|
-
WebRTCError: 'WebRTCError',
|
|
296
|
-
WebSocketError: 'WebSocketError',
|
|
297
|
-
WebSocketClose: 'WebSocketClose',
|
|
298
|
-
DropConnection: 'DropConnection',
|
|
299
|
-
OrchestrationPlayerDisconnected: 'OrchestrationPlayerDisconnected',
|
|
300
|
-
OrchestrationStreamerDisconnected: 'OrchestrationStreamerDisconnected',
|
|
301
|
-
IceConnectionFailed: 'IceConnectionFailed',
|
|
302
|
-
ReconnectFailed: 'ReconnectFailed',
|
|
303
|
-
NewConnectionAttempt: 'NewConnectionAttempt',
|
|
304
|
-
AbortEstablishingConnection: 'AbortEstablishingConnection',
|
|
305
|
-
};
|
|
306
|
-
|
|
307
|
-
/*
|
|
308
|
-
export interface RequestReservation extends InstanceMessageBase {
|
|
309
|
-
type: 'requestReservation';
|
|
310
|
-
}
|
|
311
|
-
*/
|
|
312
|
-
const OrchestrationMessageTypes = {
|
|
313
|
-
ping: 'ping',
|
|
314
|
-
error: 'error',
|
|
315
|
-
offer: 'offer',
|
|
316
|
-
answer: 'answer',
|
|
317
|
-
ssInfo: 'ssInfo',
|
|
318
|
-
config: 'config',
|
|
319
|
-
playerCount: 'playerCount',
|
|
320
|
-
iceCandidate: 'iceCandidate',
|
|
321
|
-
streamerList: 'streamerList',
|
|
322
|
-
requestStream: 'requestStream',
|
|
323
|
-
listStreamers: 'listStreamers',
|
|
324
|
-
instanceReady: 'instanceReady',
|
|
325
|
-
p2pEstablished: 'p2pEstablished',
|
|
326
|
-
instanceReserved: 'instanceReserved',
|
|
327
|
-
playerDisconnected: 'playerDisconnected',
|
|
328
|
-
streamPreparedForUserInteraction: 'streamPreparedForUserInteraction',
|
|
329
|
-
streamerDisconnected: 'streamerDisconnected',
|
|
330
|
-
interruptClientStream: 'interruptClientStream',
|
|
331
|
-
};
|
|
339
|
+
const showLoadingProgress = createAction(scoped `show loading progress`, props());
|
|
340
|
+
const showResumeStreamPopup = createAction(scoped `show resume stream popup`, props());
|
|
341
|
+
const showUserInactivityTimeoutPopup = createAction(scoped `show user inactivity timeout popup`, props());
|
|
342
|
+
const setUserInactivityTimeout = createAction(scoped `set user inactivity timeout`, props());
|
|
343
|
+
const resetUserInactivityTimeout = createAction(scoped `reset user inactivity timeout`);
|
|
332
344
|
|
|
333
345
|
const initialState$1 = {
|
|
334
346
|
streamRequestContext: null,
|
|
335
347
|
environmentId: null,
|
|
336
|
-
lowBandwidthStats: undefined,
|
|
337
348
|
isFirstSuccessLoad: false,
|
|
338
349
|
isAfkTimerVisible: false,
|
|
339
350
|
afkCountdown: 0,
|
|
340
|
-
lowBandwidth: false,
|
|
341
351
|
cirrusConnected: false,
|
|
342
352
|
establishingConnection: false,
|
|
343
353
|
isReconnecting: false,
|
|
@@ -347,7 +357,6 @@ const initialState$1 = {
|
|
|
347
357
|
statusPercentSignallingServer: null,
|
|
348
358
|
statusMessage: null,
|
|
349
359
|
errorMessage: null,
|
|
350
|
-
ssInfo: null,
|
|
351
360
|
ssData: null,
|
|
352
361
|
streamResolution: { width: null, height: null },
|
|
353
362
|
freezeFrameFromVideo: { dataUrl: null, progress: null },
|
|
@@ -363,6 +372,7 @@ const initialState$1 = {
|
|
|
363
372
|
autoStart: true,
|
|
364
373
|
warnTimeout: DEFAULT_AFK_TIMEOUT,
|
|
365
374
|
},
|
|
375
|
+
userInactivityTimeout: DEFAULT_AFK_TIMEOUT,
|
|
366
376
|
matchUrls: [],
|
|
367
377
|
streamClientCompanyId: '',
|
|
368
378
|
streamViewId: 'default',
|
|
@@ -370,15 +380,23 @@ const initialState$1 = {
|
|
|
370
380
|
imageIntroSrc: null,
|
|
371
381
|
imageLoadingSrc: '',
|
|
372
382
|
analyticsEvent: null,
|
|
383
|
+
showLoadingProgress: true,
|
|
384
|
+
showResumeStreamPopup: true,
|
|
385
|
+
showAfkTimeoutPopup: true,
|
|
373
386
|
};
|
|
374
|
-
const unrealReducer = createReducer(initialState$1, on(
|
|
375
|
-
...state,
|
|
376
|
-
lowBandwidth: lowBandwidth,
|
|
377
|
-
lowBandwidthStats: lowBandwidth ? stats : undefined,
|
|
378
|
-
})), on(changeStatusMainVideoOnScene, (state, { isVideoPlaying }) => {
|
|
379
|
-
return { ...state, isVideoPlaying: isVideoPlaying };
|
|
387
|
+
const unrealReducer = createReducer(initialState$1, on(changeStatusMainVideoOnScene, (state, { isVideoPlaying }) => {
|
|
388
|
+
return { ...state, isVideoPlaying };
|
|
380
389
|
}), on(setAwsInstance, (state, { instanceName, wsUrl, pollingUrl }) => {
|
|
381
|
-
return {
|
|
390
|
+
return {
|
|
391
|
+
...state,
|
|
392
|
+
awsInstance: {
|
|
393
|
+
...state.awsInstance,
|
|
394
|
+
instanceName,
|
|
395
|
+
wsUrl,
|
|
396
|
+
pollingUrl,
|
|
397
|
+
progressComplete: 0,
|
|
398
|
+
},
|
|
399
|
+
};
|
|
382
400
|
}), on(setViewportReady, (state) => {
|
|
383
401
|
return {
|
|
384
402
|
...state,
|
|
@@ -388,12 +406,8 @@ const unrealReducer = createReducer(initialState$1, on(changeLowBandwidth, (stat
|
|
|
388
406
|
};
|
|
389
407
|
}), on(setViewportNotReady, (state) => {
|
|
390
408
|
return { ...state, viewportReady: false };
|
|
391
|
-
}), on(updateCirrusInfo, (state, {
|
|
392
|
-
return {
|
|
393
|
-
...state,
|
|
394
|
-
ssInfo: ssInfo, // For back compatibility
|
|
395
|
-
ssData: ssData, // Contains all the data from the ssInfo as an object
|
|
396
|
-
};
|
|
409
|
+
}), on(updateCirrusInfo, (state, { ssData }) => {
|
|
410
|
+
return { ...state, ssData: ssData };
|
|
397
411
|
}), on(changeStreamResolutionSuccessAction, (state, { width, height }) => {
|
|
398
412
|
return { ...state, streamResolution: { width: width, height: height } };
|
|
399
413
|
}), on(setFreezeFrame, (state, freezeFrame) => {
|
|
@@ -409,15 +423,11 @@ const unrealReducer = createReducer(initialState$1, on(changeLowBandwidth, (stat
|
|
|
409
423
|
},
|
|
410
424
|
};
|
|
411
425
|
}), on(disconnectStream, (state, errorMessage) => {
|
|
412
|
-
|
|
413
|
-
state.disconnectReason === DisconnectReason.Destroy
|
|
426
|
+
const alreadyHandled = state.dataChannelConnected ||
|
|
427
|
+
state.disconnectReason === DisconnectReason.Destroy;
|
|
428
|
+
if (alreadyHandled)
|
|
414
429
|
return state;
|
|
415
|
-
}
|
|
416
|
-
return {
|
|
417
|
-
...state,
|
|
418
|
-
errorMessage,
|
|
419
|
-
statusMessage: null,
|
|
420
|
-
};
|
|
430
|
+
return { ...state, errorMessage, statusMessage: null };
|
|
421
431
|
}), on(setFreezeFrameFromVideo, (state, freezeFrameFromVideo) => {
|
|
422
432
|
return {
|
|
423
433
|
...state,
|
|
@@ -441,12 +451,21 @@ const unrealReducer = createReducer(initialState$1, on(changeLowBandwidth, (stat
|
|
|
441
451
|
};
|
|
442
452
|
}), on(setConfig, startStream, (state, { config }) => {
|
|
443
453
|
return { ...state, streamConfig: { ...state.streamConfig, ...config } };
|
|
444
|
-
}), on(resetConfig, (state) => {
|
|
445
|
-
return { ...state, streamConfig: initialState$1.streamConfig };
|
|
446
454
|
}), on(resetWarnTimeout, (state) => {
|
|
447
455
|
return {
|
|
448
456
|
...state,
|
|
449
|
-
streamConfig: {
|
|
457
|
+
streamConfig: {
|
|
458
|
+
...state.streamConfig,
|
|
459
|
+
warnTimeout: state.userInactivityTimeout,
|
|
460
|
+
},
|
|
461
|
+
};
|
|
462
|
+
}), on(resetConfig, (state) => {
|
|
463
|
+
return {
|
|
464
|
+
...state,
|
|
465
|
+
streamConfig: {
|
|
466
|
+
...initialState$1.streamConfig,
|
|
467
|
+
warnTimeout: state.userInactivityTimeout,
|
|
468
|
+
},
|
|
450
469
|
};
|
|
451
470
|
}), on(initSignalling, (state, { resetDisconnectionReason = true }) => {
|
|
452
471
|
return {
|
|
@@ -522,6 +541,18 @@ const unrealReducer = createReducer(initialState$1, on(changeLowBandwidth, (stat
|
|
|
522
541
|
return { ...state, analyticsEvent: event };
|
|
523
542
|
}), on(setCirrusConnected, (state) => {
|
|
524
543
|
return { ...state, cirrusConnected: true };
|
|
544
|
+
}), on(showLoadingProgress, (state, { visible }) => {
|
|
545
|
+
return { ...state, showLoadingProgress: visible };
|
|
546
|
+
}), on(showResumeStreamPopup, (state, { visible }) => {
|
|
547
|
+
return { ...state, showResumeStreamPopup: visible };
|
|
548
|
+
}), on(showUserInactivityTimeoutPopup, (state, { visible }) => {
|
|
549
|
+
return { ...state, showAfkTimeoutPopup: visible };
|
|
550
|
+
}), on(setUserInactivityTimeout, (state, { timeout }) => {
|
|
551
|
+
return {
|
|
552
|
+
...state,
|
|
553
|
+
userInactivityTimeout: timeout,
|
|
554
|
+
streamConfig: { ...state.streamConfig, warnTimeout: timeout },
|
|
555
|
+
};
|
|
525
556
|
}), on(setCirrusDisconnected, (state) => {
|
|
526
557
|
return {
|
|
527
558
|
...initialState$1,
|
|
@@ -537,6 +568,7 @@ const unrealReducer = createReducer(initialState$1, on(changeLowBandwidth, (stat
|
|
|
537
568
|
environmentId: state.environmentId,
|
|
538
569
|
streamRequestContext: state.streamRequestContext,
|
|
539
570
|
streamConfig: state.streamConfig,
|
|
571
|
+
userInactivityTimeout: state.userInactivityTimeout,
|
|
540
572
|
};
|
|
541
573
|
}), on(dropConnection, (state) => {
|
|
542
574
|
return { ...state, establishingConnection: false };
|
|
@@ -608,7 +640,7 @@ function PlayerCountHandler(msg) {
|
|
|
608
640
|
}
|
|
609
641
|
|
|
610
642
|
function SSInfoHandler(msg) {
|
|
611
|
-
this.store.dispatch(updateCirrusInfo({
|
|
643
|
+
this.store.dispatch(updateCirrusInfo({ ssData: msg.data }));
|
|
612
644
|
return null;
|
|
613
645
|
}
|
|
614
646
|
|
|
@@ -1055,63 +1087,6 @@ function getResizeValuesUniversal(params) {
|
|
|
1055
1087
|
return { w: makeEven(w), h: makeEven(h), x: 0, y: 0, scale: w / maxSpace.w };
|
|
1056
1088
|
}
|
|
1057
1089
|
|
|
1058
|
-
//TODO: Remove this legacy method after confirming that `getResizeValuesUniversal`
|
|
1059
|
-
// works well in all scenarios and updating any dependent code to use it instead.
|
|
1060
|
-
function getResizeValuesUniversalOld(params) {
|
|
1061
|
-
const { pixelRatio, containerWidth, containerHeight, maxResolution } = params;
|
|
1062
|
-
const maxSpace = {
|
|
1063
|
-
w: containerWidth * pixelRatio,
|
|
1064
|
-
h: containerHeight * pixelRatio,
|
|
1065
|
-
};
|
|
1066
|
-
const isVertical = containerWidth < containerHeight;
|
|
1067
|
-
let maxH = FULL_HD_HEIGHT;
|
|
1068
|
-
let maxW = FULL_HD_WIDTH;
|
|
1069
|
-
if (maxResolution) {
|
|
1070
|
-
maxH = FULL_HD_HEIGHT * 2;
|
|
1071
|
-
maxW = FULL_HD_WIDTH * 2;
|
|
1072
|
-
}
|
|
1073
|
-
const maxLimits = isVertical
|
|
1074
|
-
? { w: maxH, h: maxW, x: 0, y: 0 }
|
|
1075
|
-
: { w: maxW, h: maxH, x: 0, y: 0 };
|
|
1076
|
-
const props = fitIntoRectangle({ x: 0, y: 0, w: containerWidth, h: containerHeight }, { x: 0, y: 0, ...maxSpace });
|
|
1077
|
-
let out = { ...props };
|
|
1078
|
-
const fitIntoMax = fitIntoRectangle(props, maxLimits);
|
|
1079
|
-
if (fitIntoMax.scale < 1) {
|
|
1080
|
-
// If reducing size to 1920x1080 is required, do it
|
|
1081
|
-
out = fitIntoMax;
|
|
1082
|
-
}
|
|
1083
|
-
else {
|
|
1084
|
-
// Otherwise, use the lowest resolution because the layout size is smaller than 1920x1080
|
|
1085
|
-
out.scale = 1;
|
|
1086
|
-
}
|
|
1087
|
-
/**
|
|
1088
|
-
* Ensure that the size is always even.
|
|
1089
|
-
*/
|
|
1090
|
-
out.w = makeEven(out.w);
|
|
1091
|
-
out.h = makeEven(out.h);
|
|
1092
|
-
return { ...out };
|
|
1093
|
-
}
|
|
1094
|
-
function getResizeStudioValuesOld(params) {
|
|
1095
|
-
const { pixelRatio, containerWidth, containerHeight, studioWidth, studioHeight, } = params;
|
|
1096
|
-
const maxSpace = {
|
|
1097
|
-
w: containerWidth * pixelRatio,
|
|
1098
|
-
h: containerHeight * pixelRatio,
|
|
1099
|
-
};
|
|
1100
|
-
const videoSizePixelPerfect = fitIntoRectangle({ x: 0, y: 0, w: studioWidth, h: studioHeight }, { x: 0, y: 0, ...maxSpace });
|
|
1101
|
-
const out = fitIntoRectangle(videoSizePixelPerfect, {
|
|
1102
|
-
x: 0,
|
|
1103
|
-
y: 0,
|
|
1104
|
-
w: Math.min(maxSpace.w, FULL_HD_WIDTH),
|
|
1105
|
-
h: Math.min(maxSpace.h, FULL_HD_HEIGHT),
|
|
1106
|
-
});
|
|
1107
|
-
/**
|
|
1108
|
-
* Ensure that the size is always even.
|
|
1109
|
-
*/
|
|
1110
|
-
out.w = makeEven(out.w);
|
|
1111
|
-
out.h = makeEven(out.h);
|
|
1112
|
-
return out;
|
|
1113
|
-
}
|
|
1114
|
-
|
|
1115
1090
|
const removeExileCommands = (state, idToRemove) => {
|
|
1116
1091
|
const exileTimeout = 10000;
|
|
1117
1092
|
const out = { ...state };
|
|
@@ -1119,11 +1094,11 @@ const removeExileCommands = (state, idToRemove) => {
|
|
|
1119
1094
|
out.totalCommandsCompleted++;
|
|
1120
1095
|
const time = new Date().getTime();
|
|
1121
1096
|
const markForDelete = [];
|
|
1122
|
-
|
|
1097
|
+
for (const { id, timeStamp } of out.commandsInProgress) {
|
|
1123
1098
|
if (time - timeStamp > exileTimeout) {
|
|
1124
1099
|
markForDelete.push(id);
|
|
1125
1100
|
}
|
|
1126
|
-
}
|
|
1101
|
+
}
|
|
1127
1102
|
out.totalCommandsCompleted += markForDelete.length;
|
|
1128
1103
|
out.commandsInProgress = out.commandsInProgress.filter((command) => !markForDelete.includes(command.id));
|
|
1129
1104
|
return out;
|
|
@@ -1159,9 +1134,9 @@ const commandsFeature = createFeature({
|
|
|
1159
1134
|
const selectCommandsInProgress = createSelector(commandsFeature.selectCommandsInProgress, (commandsInProgress) => commandsInProgress?.length ?? 0);
|
|
1160
1135
|
const selectCommandProgress = createSelector(commandsFeature.selectTotalCommandsStarted, commandsFeature.selectTotalCommandsCompleted, (totalCommandsStarted, totalCommandsCompleted) => totalCommandsStarted ? totalCommandsCompleted / totalCommandsStarted : 0);
|
|
1161
1136
|
|
|
1162
|
-
const selectFreezeFrameDataUrlFromVideo = createSelector(unrealFeature.selectFreezeFrameFromVideo,
|
|
1163
|
-
const selectFreezeFrameProgressMessageFromVideo = createSelector(unrealFeature.selectFreezeFrameFromVideo,
|
|
1164
|
-
const selectFreezeFrameDataUrl = createSelector(unrealFeature.selectFreezeFrame,
|
|
1137
|
+
const selectFreezeFrameDataUrlFromVideo = createSelector(unrealFeature.selectFreezeFrameFromVideo, (freezeFrameFromVideo) => freezeFrameFromVideo?.dataUrl || null);
|
|
1138
|
+
const selectFreezeFrameProgressMessageFromVideo = createSelector(unrealFeature.selectFreezeFrameFromVideo, (freezeFrameFromVideo) => freezeFrameFromVideo?.progress || null);
|
|
1139
|
+
const selectFreezeFrameDataUrl = createSelector(unrealFeature.selectFreezeFrame, (freezeFrame) => (freezeFrame?.dataUrl ? freezeFrame?.dataUrl : null));
|
|
1165
1140
|
const selectIsFreezeFrameLoading = createSelector(unrealFeature.selectFreezeFrame, (freezeFrame) => freezeFrame?.progress
|
|
1166
1141
|
? freezeFrame.progress > 0 && freezeFrame.progress < 1
|
|
1167
1142
|
: false);
|
|
@@ -1170,50 +1145,55 @@ const selectStreamConfig = createSelector(unrealFeature.selectStreamConfig, (con
|
|
|
1170
1145
|
const selectWarnTimeout = createSelector(selectStreamConfig, (config) => config?.warnTimeout || DEFAULT_AFK_TIMEOUT);
|
|
1171
1146
|
const selectIsExistMatchUrls = createSelector(unrealFeature.selectMatchUrls, (urls) => urls?.length > 0);
|
|
1172
1147
|
const selectIsAutostart = createSelector(selectStreamConfig, (config) => config?.autoStart);
|
|
1173
|
-
const selectShowReconnectPopup = createSelector(unrealFeature.selectCirrusConnected, unrealFeature.selectEstablishingConnection, (
|
|
1148
|
+
const selectShowReconnectPopup = createSelector(unrealFeature.selectCirrusConnected, unrealFeature.selectEstablishingConnection, (cirrusConnected, establishingConnection) => !cirrusConnected && !establishingConnection);
|
|
1174
1149
|
const selectShowLoader = createSelector(selectShowReconnectPopup, unrealFeature.selectViewportReady, (showPopup, viewportReady) => !showPopup && !viewportReady);
|
|
1175
1150
|
const selectIsVideoPlayingAndDataChannelConnected = createSelector(unrealFeature.selectIsVideoPlaying, unrealFeature.selectDataChannelConnected, (isVideoPlaying, isDataChannelConnected) => isVideoPlaying && isDataChannelConnected);
|
|
1176
|
-
const selectSignalingParameters = createSelector(unrealFeature.selectSsData, unrealFeature.selectAwsInstance,
|
|
1151
|
+
const selectSignalingParameters = createSelector(unrealFeature.selectSsData, unrealFeature.selectAwsInstance, (data, instance) => {
|
|
1177
1152
|
const info = [];
|
|
1178
1153
|
if (data) {
|
|
1179
1154
|
info.push(`${data.cirrusVersion}, ${data.branchInfo}, ${data.instanceType}`);
|
|
1180
1155
|
info.push(`Unreal App Version: ${data.streamerVersion}`);
|
|
1181
1156
|
info.push(`APP: ${data.streamPath}${data.streamApp}`);
|
|
1182
1157
|
}
|
|
1183
|
-
else {
|
|
1184
|
-
info.push(ssInfo);
|
|
1185
|
-
}
|
|
1186
1158
|
info.push(`Polling: ${instance.pollingUrl}`);
|
|
1187
1159
|
info.push(`WS: ${instance.wsUrl}`);
|
|
1188
1160
|
return info.join('<br>');
|
|
1189
1161
|
});
|
|
1162
|
+
const selectClientAndViewIds = createSelector(unrealFeature.selectStreamClientCompanyId, unrealFeature.selectStreamViewId, (clientId, viewId) => ({ clientId, viewId }));
|
|
1163
|
+
const selectIsFullyConnected = createSelector(unrealFeature.selectViewportReady, unrealFeature.selectDataChannelConnected, unrealFeature.selectCirrusConnected, (viewportReady, dataChannelConnected, cirrusConnected) => viewportReady && dataChannelConnected && cirrusConnected);
|
|
1164
|
+
const selectIsLoaderScreenVisible = createSelector(selectIsFullyConnected, (fullyConnected) => !fullyConnected);
|
|
1165
|
+
const selectCirrusConnectionId = createSelector(unrealFeature.selectSsData, (data) => data?.connectionId);
|
|
1190
1166
|
/**
|
|
1191
|
-
* Returns Scene load progress as a float value
|
|
1167
|
+
* Returns Scene load progress as a float value between 0 and 1.
|
|
1168
|
+
*
|
|
1169
|
+
* Progress is split into two phases:
|
|
1170
|
+
* 1. **Signaling** (0 → ~56%): connection polling or orchestration progress.
|
|
1171
|
+
* Starts at 0.1%, so the bar is never visually empty while connecting.
|
|
1172
|
+
* 2. **Commands** (~56% → 100%): Unreal command progress after the data channel connects.
|
|
1173
|
+
*
|
|
1174
|
+
* The split point bumps by +1% once the WebSocket URL is known,
|
|
1175
|
+
* producing a small visual step that indicates the WS handshake succeeded.
|
|
1192
1176
|
*/
|
|
1193
1177
|
const selectTotalProgress = createSelector(unrealFeature.selectStatusPercentSignallingServer, selectCommandProgress, unrealFeature.selectAwsInstance, unrealFeature.selectDataChannelConnected, (statusPercentSignallingServer, commandProgress, awsInstance, dataChannelConnected) => {
|
|
1194
|
-
// TODO make better mechanism to detect is new orchestration
|
|
1195
|
-
const isNewOrchestration = String(awsInstance?.wsUrl).match(/^wss:\/\/orchestration-websocket/i);
|
|
1196
|
-
const newOrchestrationProgressComplete = dataChannelConnected
|
|
1197
|
-
? 100
|
|
1198
|
-
: (awsInstance?.progressComplete || 0) * 100;
|
|
1199
|
-
/**
|
|
1200
|
-
* Set 57% {@link SIGNALLING_PERCENT_VALUE} immediately when signalingServer?.signalingUrl is available
|
|
1201
|
-
* Up to 56% {@link SIGNALLING_PERCENT_VALUE} - 1 of the progress is reserved for signaling server polling
|
|
1202
|
-
*/
|
|
1203
|
-
const signalingPercentValue = isNewOrchestration
|
|
1204
|
-
? newOrchestrationProgressComplete
|
|
1205
|
-
: statusPercentSignallingServer;
|
|
1206
1178
|
const SIGNALLING_MAX = SIGNALLING_PERCENT_VALUE / 100;
|
|
1179
|
+
const ORCHESTRATION_WS_PATTERN = /^wss:\/\/orchestration-websocket/i;
|
|
1180
|
+
const isNewOrchestration = ORCHESTRATION_WS_PATTERN.test(awsInstance?.wsUrl ?? '');
|
|
1181
|
+
// Orchestration progress is 0–1 from the backend; map to 0–1 directly.
|
|
1182
|
+
// Once the data channel is connected, signaling is fully complete (1.0).
|
|
1183
|
+
const signalingProgress = isNewOrchestration
|
|
1184
|
+
? dataChannelConnected
|
|
1185
|
+
? 1
|
|
1186
|
+
: (awsInstance?.progressComplete ?? 0)
|
|
1187
|
+
: (statusPercentSignallingServer ?? 0) / 100;
|
|
1188
|
+
// +1% bump once WS URL is known (visual step for WS handshake)
|
|
1207
1189
|
const splitPoint = awsInstance?.wsUrl
|
|
1208
1190
|
? SIGNALLING_MAX + 0.01
|
|
1209
1191
|
: SIGNALLING_MAX;
|
|
1210
|
-
|
|
1192
|
+
// 0.001 minimum so the bar is never completely empty while loading
|
|
1193
|
+
const progressSignaling = lerp(0.001, splitPoint, signalingProgress);
|
|
1211
1194
|
const progressRest = lerp(0, 1 - splitPoint, commandProgress);
|
|
1212
1195
|
return clampf(0, 1, progressSignaling + progressRest);
|
|
1213
1196
|
});
|
|
1214
|
-
const selectClientAndViewIds = createSelector(unrealFeature.selectStreamClientCompanyId, unrealFeature.selectStreamViewId, (clientId, viewId) => ({ clientId, viewId }));
|
|
1215
|
-
const selectIsLoaderScreenVisible = createSelector(unrealFeature.selectViewportReady, unrealFeature.selectDataChannelConnected, unrealFeature.selectCirrusConnected, (viewReady, cirrusConnected, dataChannelConnected) => !viewReady || !cirrusConnected || !dataChannelConnected);
|
|
1216
|
-
const selectCirrusConnectionId = createSelector(unrealFeature.selectSsData, (data) => data?.connectionId);
|
|
1217
1197
|
|
|
1218
1198
|
class UnrealErrorModalComponent {
|
|
1219
1199
|
constructor() {
|
|
@@ -1224,38 +1204,14 @@ class UnrealErrorModalComponent {
|
|
|
1224
1204
|
close() {
|
|
1225
1205
|
this.#dialogRef.close();
|
|
1226
1206
|
}
|
|
1227
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.
|
|
1228
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.
|
|
1207
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: UnrealErrorModalComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1208
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.11", type: UnrealErrorModalComponent, isStandalone: true, selector: "app-unreal-error-modal", ngImport: i0, template: "<div class=\"src-modal src-modal--small\">\n <header class=\"src-modal__header\">\n <div\n [attr.data-testid]=\"'unreal-error-header-title'\"\n class=\"src-modal__title\"\n >\n Warning\n </div>\n </header>\n <div class=\"src-modal__body\">\n <div>{{ dialogData.content }}</div>\n </div>\n <div class=\"src-modal__footer\">\n <src-button (onClick)=\"close()\">Ok</src-button>\n </div>\n</div>\n", styles: [".src-modal__header{padding:16px 24px 0}\n"], dependencies: [{ kind: "component", type: SourceButtonComponent, selector: "src-button", inputs: ["type", "appearance", "weight", "size", "context", "customClass", "isFullWidth", "isPressed", "isDisabled", "isLoading", "isInverted", "srcButtonConfig", "formID", "data-testid", "ariaLabel"], outputs: ["onClick", "onSubmit"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
1229
1209
|
}
|
|
1230
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.
|
|
1210
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: UnrealErrorModalComponent, decorators: [{
|
|
1231
1211
|
type: Component,
|
|
1232
1212
|
args: [{ selector: 'app-unreal-error-modal', changeDetection: ChangeDetectionStrategy.OnPush, imports: [SourceButtonComponent], template: "<div class=\"src-modal src-modal--small\">\n <header class=\"src-modal__header\">\n <div\n [attr.data-testid]=\"'unreal-error-header-title'\"\n class=\"src-modal__title\"\n >\n Warning\n </div>\n </header>\n <div class=\"src-modal__body\">\n <div>{{ dialogData.content }}</div>\n </div>\n <div class=\"src-modal__footer\">\n <src-button (onClick)=\"close()\">Ok</src-button>\n </div>\n</div>\n", styles: [".src-modal__header{padding:16px 24px 0}\n"] }]
|
|
1233
1213
|
}] });
|
|
1234
1214
|
|
|
1235
|
-
/**
|
|
1236
|
-
* Default LBM Filter Parameters
|
|
1237
|
-
*/
|
|
1238
|
-
const DefaultFilterModel = {
|
|
1239
|
-
minimumBitrate: 1600,
|
|
1240
|
-
yellowFlag: 30,
|
|
1241
|
-
redFlag: 50,
|
|
1242
|
-
minimumFps: 5,
|
|
1243
|
-
monitoringDelayTime: 5000,
|
|
1244
|
-
initialBitrateEstimate: 1600,
|
|
1245
|
-
initialErrorCovariance: 1,
|
|
1246
|
-
processNoise: 3,
|
|
1247
|
-
measurementNoise: 500,
|
|
1248
|
-
panelOpen: false,
|
|
1249
|
-
};
|
|
1250
|
-
/**
|
|
1251
|
-
* Global LBM Filter Parameters
|
|
1252
|
-
*/
|
|
1253
|
-
const FilterModel = { ...DefaultFilterModel };
|
|
1254
|
-
/**
|
|
1255
|
-
* Bitrate Monitor Static Class
|
|
1256
|
-
*/
|
|
1257
|
-
const BITRATE_MONITOR = new DataFlowMonitor(FilterModel.yellowFlag, FilterModel.redFlag, 20);
|
|
1258
|
-
|
|
1259
1215
|
class UnrealEffects {
|
|
1260
1216
|
constructor() {
|
|
1261
1217
|
this.actions$ = inject(Actions);
|
|
@@ -1276,7 +1232,6 @@ class UnrealEffects {
|
|
|
1276
1232
|
this.connectionCompleted$ = this.store
|
|
1277
1233
|
.select(unrealFeature.selectDataChannelConnected)
|
|
1278
1234
|
.pipe(filter(Truthy));
|
|
1279
|
-
// ==================== PEER RECONNECTION EFFECTS ====================
|
|
1280
1235
|
this.reconnectConfig = {
|
|
1281
1236
|
enabled: this.unrealInitialConfig?.reconnect?.enabled ?? DEFAULT_RECONNECT_ENABLED,
|
|
1282
1237
|
maxAttempts: this.unrealInitialConfig?.reconnect?.maxAttempts ??
|
|
@@ -1289,29 +1244,14 @@ class UnrealEffects {
|
|
|
1289
1244
|
DEFAULT_RECONNECT_ON_DATACHANNEL_CLOSE,
|
|
1290
1245
|
};
|
|
1291
1246
|
this.disconnectReasonHandling$ = createEffect(() => {
|
|
1292
|
-
const destroyReasons = [
|
|
1293
|
-
DisconnectReason.Afk,
|
|
1294
|
-
DisconnectReason.DataChannelClosed,
|
|
1295
|
-
DisconnectReason.DataChannelTimeout,
|
|
1296
|
-
DisconnectReason.WebSocketError,
|
|
1297
|
-
DisconnectReason.WebSocketClose,
|
|
1298
|
-
DisconnectReason.WebRTCError,
|
|
1299
|
-
DisconnectReason.DropConnection,
|
|
1300
|
-
DisconnectReason.ReconnectFailed,
|
|
1301
|
-
DisconnectReason.OrchestrationPlayerDisconnected,
|
|
1302
|
-
DisconnectReason.OrchestrationStreamerDisconnected,
|
|
1303
|
-
];
|
|
1304
1247
|
return this.actions$.pipe(ofType(disconnectStream), filter(({ reason }) => {
|
|
1305
|
-
// Skip DataChannelClosed if peer reconnection
|
|
1306
|
-
// The peer reconnection effect will handle this case
|
|
1248
|
+
// Skip DataChannelClosed if peer reconnection will handle this case
|
|
1307
1249
|
if (reason === DisconnectReason.DataChannelClosed &&
|
|
1308
|
-
this.
|
|
1309
|
-
this.reconnectConfig.onDataChannelClose &&
|
|
1310
|
-
this.signallingService.isConnected()) {
|
|
1250
|
+
this.canPeerReconnect()) {
|
|
1311
1251
|
Logger.info('[Reconnect] Skipping destroy for DataChannelClosed - peer reconnection will handle');
|
|
1312
1252
|
return false;
|
|
1313
1253
|
}
|
|
1314
|
-
return
|
|
1254
|
+
return DESTROY_DISCONNECT_REASONS.includes(reason);
|
|
1315
1255
|
}), tap(({ reason, message }) => {
|
|
1316
1256
|
Logger.log(`Disconnect Call=> reason:'${reason}', message:'${message}'`);
|
|
1317
1257
|
}), map(({ reason }) => destroyRemoteConnections({ reason })));
|
|
@@ -1331,11 +1271,6 @@ class UnrealEffects {
|
|
|
1331
1271
|
this.webRtcPlayerService.closePC();
|
|
1332
1272
|
}), filter(({ reason }) => reason === DisconnectReason.DropConnection), map(() => dropConnection()));
|
|
1333
1273
|
});
|
|
1334
|
-
this.webrtcErrorModalComponent$ = createEffect(() => {
|
|
1335
|
-
return this.actions$.pipe(ofType(disconnectStream), filter(({ reason }) => reason === DisconnectReason.WebRTCError), debounceTime(400), switchMap(() => this.store
|
|
1336
|
-
.select(unrealFeature.selectDataChannelConnected)
|
|
1337
|
-
.pipe(take(1), filter(Falsy))), tap(() => this.dialog.open(WebrtcErrorModalComponent)));
|
|
1338
|
-
}, { dispatch: false });
|
|
1339
1274
|
this.changeStreamResolution$ = createEffect(() => {
|
|
1340
1275
|
return this.actions$.pipe(ofType(changeStreamResolutionAction), filter((size) => !!(size?.width && size?.height)), concatLatestFrom(() => this.store.select(unrealFeature.selectStreamResolution)), filter(([newSizes, savedSizes]) => !(newSizes.width === savedSizes.width &&
|
|
1341
1276
|
newSizes.height === savedSizes.height)), map(([sizes]) => changeStreamResolutionSuccessAction({
|
|
@@ -1343,49 +1278,25 @@ class UnrealEffects {
|
|
|
1343
1278
|
height: sizes.height,
|
|
1344
1279
|
})));
|
|
1345
1280
|
});
|
|
1346
|
-
this.forceLBMOff$ = createEffect(() => {
|
|
1347
|
-
return fromEvent(document, 'visibilitychange').pipe(map(() => document.visibilityState === 'visible'), filter(Truthy), withLatestFrom(this.store.select(unrealFeature.selectLowBandwidth)), filter(([, isLowBandwidth]) => isLowBandwidth), map(() => changeLowBandwidth({ lowBandwidth: false })));
|
|
1348
|
-
});
|
|
1349
|
-
this.resetFreezeFrameOnLowBandwidthTriggered$ = createEffect(() => {
|
|
1350
|
-
return this.actions$.pipe(ofType(changeLowBandwidth), map(({ lowBandwidth }) => lowBandwidth), distinctUntilChanged(), map(() => setFreezeFrame({ dataUrl: null, progress: null })));
|
|
1351
|
-
});
|
|
1352
|
-
this.sendLbmStatistics$ = createEffect(() => {
|
|
1353
|
-
return this.actions$.pipe(ofType(changeLowBandwidth), filter(({ lowBandwidth }) => lowBandwidth), withLatestFrom(this.store.select(unrealFeature.selectAwsInstance), this.store.select(unrealFeature.selectStreamClientCompanyId), this.store.select(unrealFeature.selectStreamViewId)), take(1), exhaustMap(([, instance, companyId, viewId]) => this.http
|
|
1354
|
-
.post(this.unrealInitialConfig?.customErrorsEndpoint || '', {
|
|
1355
|
-
message: {
|
|
1356
|
-
type: 'front',
|
|
1357
|
-
error: 'low_bandwidth_mode',
|
|
1358
|
-
signalling: instance.pollingUrl,
|
|
1359
|
-
},
|
|
1360
|
-
client: instance.pollingUrl,
|
|
1361
|
-
session_uuid: companyId,
|
|
1362
|
-
session_uuid2: viewId,
|
|
1363
|
-
})
|
|
1364
|
-
.pipe(catchError(() => EMPTY))));
|
|
1365
|
-
}, { dispatch: false });
|
|
1366
1281
|
this.resetAfk$ = createEffect(() => {
|
|
1367
|
-
return this.actions$.pipe(ofType(setConfig, resetWarnTimeout, resetConfig), map(() => resetAfk()));
|
|
1282
|
+
return this.actions$.pipe(ofType(setConfig, setUserInactivityTimeout, resetWarnTimeout, resetConfig), map(() => resetAfk()));
|
|
1368
1283
|
});
|
|
1369
1284
|
this.abortEstablishingConnection$ = createEffect(() => {
|
|
1370
|
-
|
|
1371
|
-
.select(unrealFeature.selectViewportReady)
|
|
1372
|
-
.pipe(filter(Truthy), map(() => abortEstablishingConnection()));
|
|
1373
|
-
const disconnectEvents$ = this.actions$.pipe(ofType(setCirrusDisconnected, destroyUnrealScene, dropConnection), map(() => abortEstablishingConnection()));
|
|
1374
|
-
return merge(viewportReady$, disconnectEvents$).pipe(tapLog('ABORT'));
|
|
1285
|
+
return merge(this.store.select(unrealFeature.selectViewportReady).pipe(filter(Truthy)), this.actions$.pipe(ofType(setCirrusDisconnected, destroyUnrealScene, dropConnection))).pipe(map(() => abortEstablishingConnection()));
|
|
1375
1286
|
});
|
|
1376
|
-
this.
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1287
|
+
this.iframeMessaging$ = createEffect(() => {
|
|
1288
|
+
const cirrusConnected$ = this.store
|
|
1289
|
+
.select(unrealFeature.selectCirrusConnected)
|
|
1290
|
+
.pipe(skip(1));
|
|
1291
|
+
// On disconnect: immediately show 'Connection closed.', nullify after 2s
|
|
1292
|
+
const cirrusStatus$ = cirrusConnected$.pipe(switchMap((connected) => connected
|
|
1293
|
+
? of('Creating Socket...')
|
|
1294
|
+
: concat(of('Connection closed.'), of(null).pipe(delay(2000)))));
|
|
1295
|
+
// Skip initial false; emit null on every viewport state change
|
|
1296
|
+
const viewportReset$ = this.store
|
|
1297
|
+
.select(unrealFeature.selectViewportReady)
|
|
1298
|
+
.pipe(skip(1), delay(500), map(() => null));
|
|
1299
|
+
return merge(cirrusStatus$, this.store.select(unrealFeature.selectStatusMessage), viewportReset$).pipe(debounceTime(0), distinctUntilChanged(), tapLog('STATUS=>'), tap((status) => this.postToScreenLocker(status)));
|
|
1389
1300
|
}, { dispatch: false });
|
|
1390
1301
|
this.setSignalingTo100$ = createEffect(() => {
|
|
1391
1302
|
return this.actions$.pipe(ofType(setAwsInstance), map(() => setStatusPercentSignallingServer({ percent: 100 })));
|
|
@@ -1448,27 +1359,10 @@ class UnrealEffects {
|
|
|
1448
1359
|
data: { content },
|
|
1449
1360
|
}).closed), map(() => showUnrealErrorMessage({ code: null })));
|
|
1450
1361
|
});
|
|
1451
|
-
this.sendStatisticsToUnreal$ = createEffect(() => {
|
|
1452
|
-
return this.actions$.pipe(ofType(showUnrealErrorMessage), filter(({ code }) => code === 404), withLatestFrom(this.store.select(unrealFeature.selectAwsInstance), this.store.select(unrealFeature.selectStreamClientCompanyId), this.store.select(unrealFeature.selectStreamViewId)), switchMap(([action, instance, companyId, viewId]) => this.http
|
|
1453
|
-
.post(this.unrealInitialConfig?.customErrorsEndpoint || '', {
|
|
1454
|
-
client: instance.pollingUrl,
|
|
1455
|
-
session_uuid: companyId,
|
|
1456
|
-
session_uuid2: viewId,
|
|
1457
|
-
message: {
|
|
1458
|
-
type: 'front',
|
|
1459
|
-
error: 'pak_not_found',
|
|
1460
|
-
info: action?.error ?? '',
|
|
1461
|
-
},
|
|
1462
|
-
})
|
|
1463
|
-
.pipe(tap(() => Logger.log(`successfully send to ${this.unrealInitialConfig?.customErrorsEndpoint}`)), catchError(() => {
|
|
1464
|
-
Logger.error(`get error from ${this.unrealInitialConfig?.customErrorsEndpoint}`);
|
|
1465
|
-
return EMPTY;
|
|
1466
|
-
}))));
|
|
1467
|
-
}, { dispatch: false });
|
|
1468
1362
|
this.unrealReceiverReady$ = createEffect(() => {
|
|
1469
1363
|
return this.actions$.pipe(ofType(dataChannelConnected), concatLatestFrom(() => this.store.select(unrealFeature.selectIsReconnecting)), filter(([, isReconnecting]) => !isReconnecting), map(() => dataChannelReady()));
|
|
1470
1364
|
});
|
|
1471
|
-
this.
|
|
1365
|
+
this.initAppByDataChannelReady$ = createEffect(() => {
|
|
1472
1366
|
return this.actions$.pipe(ofType(dataChannelReady), tap(() => {
|
|
1473
1367
|
this.commandsSender.sendCommandToUnreal({
|
|
1474
1368
|
command: MetaBoxCommand.FExecuteConsoleCommandCommand,
|
|
@@ -1479,10 +1373,13 @@ class UnrealEffects {
|
|
|
1479
1373
|
payload: { value: this.isDevMode },
|
|
1480
1374
|
});
|
|
1481
1375
|
this.commandTelemetryService.trackStartCommand('EXT-SetViewportReady');
|
|
1482
|
-
}), switchMap(() =>
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1376
|
+
}), switchMap(() =>
|
|
1377
|
+
// Wait for initial commands to be sent before sending the loopback.
|
|
1378
|
+
// commandStarted fires for each sent command; debounce ensures
|
|
1379
|
+
// we proceed only after no more commands are started for 100 ms.
|
|
1380
|
+
this.actions$.pipe(ofType(commandStarted), debounceTime(100), take(1), switchMap(() => this.unrealCallbackService.observeCommandResponse({ command: MetaBoxCommand.FLoopBackCommand }, (data) => this.commandsSender.sendCommandToUnreal(data))), switchMap(() => this.videoService.videoStats$), filter(({ aggregatedStats: s }) => !!s.framesPerSecond &&
|
|
1381
|
+
s.framesPerSecond > MINIMAL_FPS &&
|
|
1382
|
+
(s.framesDecoded ?? 0) > 15), take(1), map(() => setLoopBackCommandIsCompleted()))));
|
|
1486
1383
|
});
|
|
1487
1384
|
this.setViewportReadyBySetLoopBackCommandIsCompleted$ = createEffect(() => {
|
|
1488
1385
|
return this.actions$.pipe(ofType(setLoopBackCommandIsCompleted, reconnectPeerSuccess), tap(() => this.commandTelemetryService.trackStopCommand('EXT-SetViewportReady', false, { ready: true })), map(() => setViewportReady()));
|
|
@@ -1490,16 +1387,9 @@ class UnrealEffects {
|
|
|
1490
1387
|
this.startStream$ = createEffect(() => {
|
|
1491
1388
|
return this.actions$.pipe(ofType(startStream), map(() => initSignalling()));
|
|
1492
1389
|
});
|
|
1493
|
-
this.
|
|
1494
|
-
return this.actions$.pipe(ofType(
|
|
1495
|
-
|
|
1496
|
-
Logger.warn(`SIGNALING REQUEST can't be called when cirrus connection is already established.`);
|
|
1497
|
-
}
|
|
1498
|
-
return autoStart && !cirrusConnected;
|
|
1499
|
-
}), map(([, matchMakerUrls]) => [...matchMakerUrls].filter(Truthy)), filter((urls) => urls.length > 0),
|
|
1500
|
-
// Ensure a single in-flight request per attempt.
|
|
1501
|
-
exhaustMap((urls) => this.signallingService.connectToSignaling(urls)));
|
|
1502
|
-
}, { dispatch: false });
|
|
1390
|
+
this.resetAfkOnVideoStart$ = createEffect(() => {
|
|
1391
|
+
return this.actions$.pipe(ofType(videoStreamInitialized), filter(() => !!this.videoService.video?.paused), tap(() => Logger.info('Simulate Press Play')), map(() => resetAfk()));
|
|
1392
|
+
});
|
|
1503
1393
|
/**
|
|
1504
1394
|
* Effect: `forceViewportNotReady$`
|
|
1505
1395
|
*
|
|
@@ -1527,9 +1417,7 @@ class UnrealEffects {
|
|
|
1527
1417
|
*/
|
|
1528
1418
|
this.handleDataChannelClosed$ = createEffect(() => {
|
|
1529
1419
|
return this.actions$.pipe(ofType(disconnectStream), filter(({ reason }) => reason === DisconnectReason.DataChannelClosed &&
|
|
1530
|
-
this.
|
|
1531
|
-
this.reconnectConfig.onDataChannelClose &&
|
|
1532
|
-
this.signallingService.isConnected()), tap(() => {
|
|
1420
|
+
this.canPeerReconnect()), tap(() => {
|
|
1533
1421
|
Logger.warn('[Reconnect] DataChannel closed, initiating peer reconnection');
|
|
1534
1422
|
}), map(() => reconnectPeer({
|
|
1535
1423
|
attempt: 1,
|
|
@@ -1584,9 +1472,7 @@ class UnrealEffects {
|
|
|
1584
1472
|
}));
|
|
1585
1473
|
}
|
|
1586
1474
|
}));
|
|
1587
|
-
}),
|
|
1588
|
-
// Cancel if a scene is destroyed
|
|
1589
|
-
takeUntil(this.actions$.pipe(ofType(destroyUnrealScene), take(1))))));
|
|
1475
|
+
}), takeUntil(this.actions$.pipe(ofType(destroyUnrealScene), take(1))))));
|
|
1590
1476
|
});
|
|
1591
1477
|
/**
|
|
1592
1478
|
* Effect: `handlePeerReconnectFailed$`
|
|
@@ -1602,21 +1488,66 @@ class UnrealEffects {
|
|
|
1602
1488
|
message: reason,
|
|
1603
1489
|
})));
|
|
1604
1490
|
});
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
return this.actions$.pipe(ofType(reconnectPeerSuccess), tap(() => {
|
|
1612
|
-
Logger.info('[Reconnect] Peer connection restored successfully');
|
|
1491
|
+
this.setMaxFps$ = createEffect(() => {
|
|
1492
|
+
return this.actions$.pipe(ofType(setMaxFps), tap(({ maxFps }) => {
|
|
1493
|
+
this.commandsSender.sendCommandToUnreal({
|
|
1494
|
+
command: MetaBoxCommand.FExecuteConsoleCommandCommand,
|
|
1495
|
+
payload: { value: `t.MaxFPS ${maxFps}` },
|
|
1496
|
+
});
|
|
1613
1497
|
}));
|
|
1614
1498
|
}, { dispatch: false });
|
|
1499
|
+
this.webrtcErrorModalComponent$ = createEffect(() => {
|
|
1500
|
+
return this.actions$.pipe(ofType(disconnectStream), filter(({ reason }) => reason === DisconnectReason.WebRTCError), debounceTime(400), switchMap(() => this.store
|
|
1501
|
+
.select(unrealFeature.selectDataChannelConnected)
|
|
1502
|
+
.pipe(take(1), filter(Falsy))), tap(() => this.dialog.open(WebrtcErrorModalComponent)));
|
|
1503
|
+
}, { dispatch: false });
|
|
1504
|
+
this.sendStatisticsToUnreal$ = createEffect(() => {
|
|
1505
|
+
return this.actions$.pipe(ofType(showUnrealErrorMessage), filter(({ code }) => code === 404), withLatestFrom(this.store.select(unrealFeature.selectAwsInstance), this.store.select(unrealFeature.selectStreamClientCompanyId), this.store.select(unrealFeature.selectStreamViewId)), switchMap(([action, instance, companyId, viewId]) => this.http
|
|
1506
|
+
.post(this.unrealInitialConfig?.customErrorsEndpoint || '', {
|
|
1507
|
+
client: instance.pollingUrl,
|
|
1508
|
+
session_uuid: companyId,
|
|
1509
|
+
session_uuid2: viewId,
|
|
1510
|
+
message: {
|
|
1511
|
+
type: 'front',
|
|
1512
|
+
error: 'pak_not_found',
|
|
1513
|
+
info: action?.error ?? '',
|
|
1514
|
+
},
|
|
1515
|
+
})
|
|
1516
|
+
.pipe(tap(() => Logger.log(`successfully send to ${this.unrealInitialConfig?.customErrorsEndpoint}`)), catchError(() => {
|
|
1517
|
+
Logger.error(`get error from ${this.unrealInitialConfig?.customErrorsEndpoint}`);
|
|
1518
|
+
return EMPTY;
|
|
1519
|
+
}))));
|
|
1520
|
+
}, { dispatch: false });
|
|
1521
|
+
this.connectToSignaling$ = createEffect(() => {
|
|
1522
|
+
return this.actions$.pipe(ofType(initSignalling), withLatestFrom(this.store.select(unrealFeature.selectMatchUrls), this.store.select(selectIsAutostart), this.store.select(unrealFeature.selectCirrusConnected)), filter(([, , autoStart, cirrusConnected]) => {
|
|
1523
|
+
if (cirrusConnected) {
|
|
1524
|
+
Logger.warn(`SIGNALING REQUEST can't be called when cirrus connection is already established.`);
|
|
1525
|
+
}
|
|
1526
|
+
return autoStart && !cirrusConnected;
|
|
1527
|
+
}), map(([, matchMakerUrls]) => [...matchMakerUrls].filter(Truthy)), filter((urls) => urls.length > 0),
|
|
1528
|
+
// Ensure a single in-flight request per attempt.
|
|
1529
|
+
exhaustMap((urls) => this.signallingService.connectToSignaling(urls)));
|
|
1530
|
+
}, { dispatch: false });
|
|
1531
|
+
}
|
|
1532
|
+
canPeerReconnect() {
|
|
1533
|
+
return (this.reconnectConfig.enabled &&
|
|
1534
|
+
this.reconnectConfig.onDataChannelClose &&
|
|
1535
|
+
this.signallingService.isConnected());
|
|
1536
|
+
}
|
|
1537
|
+
postToScreenLocker(text) {
|
|
1538
|
+
try {
|
|
1539
|
+
const el = document.getElementById(this.unrealInitialConfig?.screenLockerContainerId ??
|
|
1540
|
+
SCREEN_LOCKER_CONTAINER_ID);
|
|
1541
|
+
el?.contentWindow?.postMessage(text, '*');
|
|
1542
|
+
}
|
|
1543
|
+
catch {
|
|
1544
|
+
// Fails silently if cross-origin
|
|
1545
|
+
}
|
|
1615
1546
|
}
|
|
1616
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.
|
|
1617
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.
|
|
1547
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: UnrealEffects, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
1548
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: UnrealEffects }); }
|
|
1618
1549
|
}
|
|
1619
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.
|
|
1550
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: UnrealEffects, decorators: [{
|
|
1620
1551
|
type: Injectable
|
|
1621
1552
|
}] });
|
|
1622
1553
|
|
|
@@ -1630,10 +1561,10 @@ class CommandsEffects {
|
|
|
1630
1561
|
: json?.correlationId), filter(Truthy), map((id) => commandCompleted({ id })))));
|
|
1631
1562
|
});
|
|
1632
1563
|
}
|
|
1633
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.
|
|
1634
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.
|
|
1564
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: CommandsEffects, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
1565
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: CommandsEffects }); }
|
|
1635
1566
|
}
|
|
1636
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.
|
|
1567
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: CommandsEffects, decorators: [{
|
|
1637
1568
|
type: Injectable
|
|
1638
1569
|
}] });
|
|
1639
1570
|
|
|
@@ -1646,7 +1577,7 @@ class SubService {
|
|
|
1646
1577
|
this.disconnect$ = this.store
|
|
1647
1578
|
.select(unrealFeature.selectCirrusConnected)
|
|
1648
1579
|
.pipe(skip(1), filter(Falsy), share());
|
|
1649
|
-
this.
|
|
1580
|
+
this.destroyRef.onDestroy(() => {
|
|
1650
1581
|
this.destroy$.next();
|
|
1651
1582
|
this.destroy$.complete();
|
|
1652
1583
|
});
|
|
@@ -1657,7 +1588,7 @@ class AFKService extends SubService {
|
|
|
1657
1588
|
constructor() {
|
|
1658
1589
|
super();
|
|
1659
1590
|
this.active = false; // Whether the AFK system is currently looking for inactivity.
|
|
1660
|
-
this.countdown = 0;
|
|
1591
|
+
this.countdown = 0;
|
|
1661
1592
|
this.warnTimeout = this.store.selectSignal(selectWarnTimeout);
|
|
1662
1593
|
this.isViewportReady = this.store.selectSignal(unrealFeature.selectViewportReady);
|
|
1663
1594
|
this.unrealConfig = inject(UNREAL_CONFIG, { optional: true });
|
|
@@ -1665,6 +1596,8 @@ class AFKService extends SubService {
|
|
|
1665
1596
|
this.afkResetTrigger = toSignal(merge(this.store.select(selectWarnTimeout), this.actions$.pipe(ofType(resetAfk))));
|
|
1666
1597
|
/** Ticks when cirrus disconnects */
|
|
1667
1598
|
this.disconnected = toSignal(this.disconnect$);
|
|
1599
|
+
/** Ticks when resetUserInactivityTimeout action fires */
|
|
1600
|
+
this.resetUserInactivityTrigger = toSignal(this.actions$.pipe(ofType(resetUserInactivityTimeout)));
|
|
1668
1601
|
this.destroyRef.onDestroy(() => this.clearTimers());
|
|
1669
1602
|
if (this.unrealConfig?.playwright) {
|
|
1670
1603
|
return;
|
|
@@ -1692,6 +1625,11 @@ class AFKService extends SubService {
|
|
|
1692
1625
|
untracked(() => this.stop());
|
|
1693
1626
|
}
|
|
1694
1627
|
});
|
|
1628
|
+
// Full reset (hide overlay + restart warning timer) on external request
|
|
1629
|
+
effect(() => {
|
|
1630
|
+
this.resetUserInactivityTrigger();
|
|
1631
|
+
untracked(() => this.reset());
|
|
1632
|
+
});
|
|
1695
1633
|
}
|
|
1696
1634
|
hideOverlay() {
|
|
1697
1635
|
this.store.dispatch(setAfkTimerHide());
|
|
@@ -1762,18 +1700,35 @@ class AFKService extends SubService {
|
|
|
1762
1700
|
}
|
|
1763
1701
|
}, 1000);
|
|
1764
1702
|
}
|
|
1765
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.
|
|
1766
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.
|
|
1703
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: AFKService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
1704
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: AFKService }); }
|
|
1767
1705
|
}
|
|
1768
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.
|
|
1706
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: AFKService, decorators: [{
|
|
1769
1707
|
type: Injectable
|
|
1770
1708
|
}], ctorParameters: () => [] });
|
|
1771
1709
|
|
|
1710
|
+
class LoadingProgressService {
|
|
1711
|
+
constructor() {
|
|
1712
|
+
this.#store = inject(Store);
|
|
1713
|
+
this.loaderVisible = this.#store.selectSignal(selectShowLoader);
|
|
1714
|
+
this.percents = toSignal(this.#store
|
|
1715
|
+
.select(selectTotalProgress)
|
|
1716
|
+
.pipe(keepMaxUntilReset(toObservable(this.loaderVisible).pipe(filter(Falsy))), floatToSmoothPercents(), distinctUntilChanged()));
|
|
1717
|
+
}
|
|
1718
|
+
#store;
|
|
1719
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: LoadingProgressService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
1720
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: LoadingProgressService }); }
|
|
1721
|
+
}
|
|
1722
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: LoadingProgressService, decorators: [{
|
|
1723
|
+
type: Injectable
|
|
1724
|
+
}] });
|
|
1725
|
+
|
|
1772
1726
|
class FreezeFrameService extends SubService {
|
|
1773
1727
|
constructor() {
|
|
1774
1728
|
super();
|
|
1775
1729
|
this.receiving = false;
|
|
1776
1730
|
this.size = 0;
|
|
1731
|
+
this.jpeg = undefined;
|
|
1777
1732
|
this.freezeFrameOverlay = new Image();
|
|
1778
1733
|
this.unrealConfig = inject(UNREAL_CONFIG, { optional: true });
|
|
1779
1734
|
this.init();
|
|
@@ -1853,13 +1808,37 @@ class FreezeFrameService extends SubService {
|
|
|
1853
1808
|
progress: 1,
|
|
1854
1809
|
}));
|
|
1855
1810
|
}
|
|
1856
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.
|
|
1857
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.
|
|
1811
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: FreezeFrameService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
1812
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: FreezeFrameService }); }
|
|
1858
1813
|
}
|
|
1859
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.
|
|
1814
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: FreezeFrameService, decorators: [{
|
|
1860
1815
|
type: Injectable
|
|
1861
1816
|
}], ctorParameters: () => [] });
|
|
1862
1817
|
|
|
1818
|
+
/**
|
|
1819
|
+
* Default LBM Filter Parameters
|
|
1820
|
+
*/
|
|
1821
|
+
const DefaultFilterModel = {
|
|
1822
|
+
minimumBitrate: 1600,
|
|
1823
|
+
yellowFlag: 30,
|
|
1824
|
+
redFlag: 50,
|
|
1825
|
+
minimumFps: 5,
|
|
1826
|
+
monitoringDelayTime: 5000,
|
|
1827
|
+
initialBitrateEstimate: 1600,
|
|
1828
|
+
initialErrorCovariance: 1,
|
|
1829
|
+
processNoise: 3,
|
|
1830
|
+
measurementNoise: 500,
|
|
1831
|
+
panelOpen: false,
|
|
1832
|
+
};
|
|
1833
|
+
/**
|
|
1834
|
+
* Global LBM Filter Parameters
|
|
1835
|
+
*/
|
|
1836
|
+
const FilterModel = { ...DefaultFilterModel };
|
|
1837
|
+
/**
|
|
1838
|
+
* Bitrate Monitor Static Class
|
|
1839
|
+
*/
|
|
1840
|
+
const BITRATE_MONITOR = new DataFlowMonitor(FilterModel.yellowFlag, FilterModel.redFlag, 20);
|
|
1841
|
+
|
|
1863
1842
|
class VideoService extends SubService {
|
|
1864
1843
|
constructor() {
|
|
1865
1844
|
super(...arguments);
|
|
@@ -1902,7 +1881,7 @@ class VideoService extends SubService {
|
|
|
1902
1881
|
this.videoTrack$.next({ stream, pcClient });
|
|
1903
1882
|
}
|
|
1904
1883
|
else {
|
|
1905
|
-
|
|
1884
|
+
Logger.error('Video element is not defined.');
|
|
1906
1885
|
}
|
|
1907
1886
|
}
|
|
1908
1887
|
attachAudioStream(stream) {
|
|
@@ -1979,7 +1958,7 @@ class VideoService extends SubService {
|
|
|
1979
1958
|
catch (err) {
|
|
1980
1959
|
// Handle InvalidStateError or any transient WebRTC errors gracefully
|
|
1981
1960
|
if (err instanceof DOMException && err.name === 'InvalidStateError') {
|
|
1982
|
-
|
|
1961
|
+
Logger.warn('Peer connection is closed or unusable, skipping stats.');
|
|
1983
1962
|
return null;
|
|
1984
1963
|
}
|
|
1985
1964
|
throw err;
|
|
@@ -2121,7 +2100,7 @@ class VideoService extends SubService {
|
|
|
2121
2100
|
}
|
|
2122
2101
|
createWebRtcAudio() {
|
|
2123
2102
|
const audio = new Audio();
|
|
2124
|
-
audio.id =
|
|
2103
|
+
audio.id = STREAMING_AUDIO_ID;
|
|
2125
2104
|
this.audio = audio;
|
|
2126
2105
|
}
|
|
2127
2106
|
playAudio(audio) {
|
|
@@ -2132,10 +2111,10 @@ class VideoService extends SubService {
|
|
|
2132
2111
|
error: () => ({}),
|
|
2133
2112
|
});
|
|
2134
2113
|
}
|
|
2135
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.
|
|
2136
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.
|
|
2114
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: VideoService, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
2115
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: VideoService }); }
|
|
2137
2116
|
}
|
|
2138
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.
|
|
2117
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: VideoService, decorators: [{
|
|
2139
2118
|
type: Injectable
|
|
2140
2119
|
}] });
|
|
2141
2120
|
|
|
@@ -2341,10 +2320,10 @@ class CommandTelemetryService {
|
|
|
2341
2320
|
this.trackTime(out);
|
|
2342
2321
|
funcToDecorate(out);
|
|
2343
2322
|
}
|
|
2344
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.
|
|
2345
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.
|
|
2323
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: CommandTelemetryService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
2324
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: CommandTelemetryService }); }
|
|
2346
2325
|
}
|
|
2347
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.
|
|
2326
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: CommandTelemetryService, decorators: [{
|
|
2348
2327
|
type: Injectable
|
|
2349
2328
|
}], ctorParameters: () => [] });
|
|
2350
2329
|
|
|
@@ -2594,7 +2573,9 @@ class SignallingService extends SubService {
|
|
|
2594
2573
|
return;
|
|
2595
2574
|
}
|
|
2596
2575
|
this.setHandlersFromStream();
|
|
2597
|
-
this.action
|
|
2576
|
+
this.action$
|
|
2577
|
+
.pipe(ofType(dataChannelReady), takeUntil(this.abort$))
|
|
2578
|
+
.subscribe(() => {
|
|
2598
2579
|
this.send({
|
|
2599
2580
|
type: 'p2pEstablished',
|
|
2600
2581
|
source: 'front',
|
|
@@ -2604,7 +2585,7 @@ class SignallingService extends SubService {
|
|
|
2604
2585
|
this.action$
|
|
2605
2586
|
.pipe(ofType(dataChannelReady), switchMap(() => this.store
|
|
2606
2587
|
.select(unrealFeature.selectViewportReady)
|
|
2607
|
-
.pipe(filter(Truthy), take(1))))
|
|
2588
|
+
.pipe(filter(Truthy), take(1))), takeUntil(this.abort$))
|
|
2608
2589
|
.subscribe(() => {
|
|
2609
2590
|
this.send({
|
|
2610
2591
|
type: 'streamPreparedForUserInteraction',
|
|
@@ -2636,10 +2617,10 @@ class SignallingService extends SubService {
|
|
|
2636
2617
|
},
|
|
2637
2618
|
// count: 10, // Optional: cap the number of attempts.
|
|
2638
2619
|
}),
|
|
2639
|
-
// abort$ sits OUTSIDE retry so it kills the entire retry loop,
|
|
2620
|
+
// abort$ sits OUTSIDE retry, so it kills the entire retry loop,
|
|
2640
2621
|
// not just the current attempt. Each inner createWebSocket also
|
|
2641
2622
|
// receives abort$ independently, so mid-connection attempts are
|
|
2642
|
-
//
|
|
2623
|
+
// canceled too.
|
|
2643
2624
|
takeUntil(this.abort$));
|
|
2644
2625
|
}
|
|
2645
2626
|
startEstablishingConnection() {
|
|
@@ -2665,7 +2646,7 @@ class SignallingService extends SubService {
|
|
|
2665
2646
|
*
|
|
2666
2647
|
* 1. **Telemetry** — Starts a `getSignaling` span for end-to-end timing.
|
|
2667
2648
|
* 2. **Candidate URL selection** — A stateful generator (`urlGen`) is created
|
|
2668
|
-
* from `urlsPool`. Each resubscription (e.g
|
|
2649
|
+
* from `urlsPool`. Each resubscription (e.g., via `retry`) advances to the next URL.
|
|
2669
2650
|
* 3. **Short-circuit for WS URLs** — If the picked candidate already matches
|
|
2670
2651
|
* `ws://` or `wss://`, emit `{ wsUrl, pollingUrl: null, instanceName: null }`
|
|
2671
2652
|
* immediately and complete (no HTTP request).
|
|
@@ -2677,7 +2658,7 @@ class SignallingService extends SubService {
|
|
|
2677
2658
|
* while the request is in flight are **ignored** until completion, preventing overlap.
|
|
2678
2659
|
* 6. **Per-attempt timeout** — `timeout(WS_TIMEOUT)` caps how long we wait for a response.
|
|
2679
2660
|
* On timeout, the attempt errors and the outer `retry` schedules the next URL.
|
|
2680
|
-
* 7. **Response validation
|
|
2661
|
+
* 7. **Response validation and progress reporting** — A `filter`:
|
|
2681
2662
|
* - Calls `TelemetryStop('getSignaling', { ...data, multi: true })` on receipt.
|
|
2682
2663
|
* - If `data.signallingServer === ''` or `data.error`:
|
|
2683
2664
|
* shows a status message, optionally dispatches `setStatusPercentSignallingServer`
|
|
@@ -2694,7 +2675,7 @@ class SignallingService extends SubService {
|
|
|
2694
2675
|
*
|
|
2695
2676
|
* ### Concurrency semantics
|
|
2696
2677
|
*
|
|
2697
|
-
* - `exhaustMap` guarantees a **single** HTTP request per attempt;
|
|
2678
|
+
* - `exhaustMap` guarantees a **single** HTTP request per attempt; later
|
|
2698
2679
|
* `{clientId, viewId}` emissions are ignored until the current request completes.
|
|
2699
2680
|
*
|
|
2700
2681
|
* ### Telemetry semantics
|
|
@@ -2728,7 +2709,7 @@ class SignallingService extends SubService {
|
|
|
2728
2709
|
* @remarks
|
|
2729
2710
|
* - The URL generator (`urlGen`) is created **outside** `defer`, so resubscriptions
|
|
2730
2711
|
* advance the pool. Creating it inside `defer` would restart from the first URL each retry.
|
|
2731
|
-
* - `location.protocol` is used to derive `ws` vs `wss`. If this may run in non-browser
|
|
2712
|
+
* - `location.protocol` is used to derive `ws` vs. `wss`. If this may run in non-browser
|
|
2732
2713
|
* contexts (e.g., SSR), guard or abstract this logic.
|
|
2733
2714
|
* - Consider capping retries with `count` in `retry({ count, delay })` when appropriate.
|
|
2734
2715
|
*
|
|
@@ -2761,7 +2742,7 @@ class SignallingService extends SubService {
|
|
|
2761
2742
|
};
|
|
2762
2743
|
}));
|
|
2763
2744
|
}
|
|
2764
|
-
// Old (HTTP-polling) orchestration flow — mark the
|
|
2745
|
+
// Old (HTTP-polling) orchestration flow — mark the round trip so
|
|
2765
2746
|
// the signaling-phase timeline can show it as a distinct segment.
|
|
2766
2747
|
this.store.dispatch(pollingStarted());
|
|
2767
2748
|
return this.store.select(selectClientAndViewIds).pipe(
|
|
@@ -2924,10 +2905,10 @@ class SignallingService extends SubService {
|
|
|
2924
2905
|
Logger.log('Start Getting Region');
|
|
2925
2906
|
return this.regionsPingService.getFastest().pipe(take(1));
|
|
2926
2907
|
}
|
|
2927
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.
|
|
2928
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.
|
|
2908
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: SignallingService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
2909
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: SignallingService }); }
|
|
2929
2910
|
}
|
|
2930
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.
|
|
2911
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: SignallingService, decorators: [{
|
|
2931
2912
|
type: Injectable
|
|
2932
2913
|
}], ctorParameters: () => [] });
|
|
2933
2914
|
|
|
@@ -2935,6 +2916,8 @@ class WebRtcPlayerService extends SubService {
|
|
|
2935
2916
|
constructor() {
|
|
2936
2917
|
super();
|
|
2937
2918
|
this.onDataChannelMessage$ = new Subject();
|
|
2919
|
+
this.pcClient = null;
|
|
2920
|
+
this.dcClient = null;
|
|
2938
2921
|
this.signallingSrv = inject(SignallingService);
|
|
2939
2922
|
this.videoService = inject(VideoService);
|
|
2940
2923
|
this.commandTelemetryService = inject(CommandTelemetryService);
|
|
@@ -2948,29 +2931,37 @@ class WebRtcPlayerService extends SubService {
|
|
|
2948
2931
|
this.iceCandidateBuffer = [];
|
|
2949
2932
|
this.isReconnecting = this.store.selectSignal(unrealFeature.selectIsReconnecting);
|
|
2950
2933
|
this.init();
|
|
2951
|
-
this.actions
|
|
2952
|
-
|
|
2934
|
+
this.actions$
|
|
2935
|
+
.pipe(ofType(dropDC), takeUntil(this.destroy$))
|
|
2936
|
+
.subscribe(() => this.dcClient?.close());
|
|
2937
|
+
this.actions$
|
|
2938
|
+
.pipe(ofType(dropPC), takeUntil(this.destroy$))
|
|
2939
|
+
.subscribe(() => this.pcClient?.close());
|
|
2953
2940
|
}
|
|
2954
2941
|
init() {
|
|
2955
|
-
this.signallingSrv.onConfig
|
|
2942
|
+
this.signallingSrv.onConfig$
|
|
2943
|
+
.pipe(takeUntil(this.destroy$))
|
|
2944
|
+
.subscribe((config) => {
|
|
2956
2945
|
this.videoService.create();
|
|
2957
2946
|
this.setConfig(config);
|
|
2958
2947
|
});
|
|
2959
2948
|
// Server-initiated offer: set remote description and respond with answer
|
|
2960
|
-
this.signallingSrv.onOffer
|
|
2949
|
+
this.signallingSrv.onOffer$
|
|
2950
|
+
.pipe(filter(Truthy), takeUntil(this.destroy$))
|
|
2951
|
+
.subscribe((offer) => {
|
|
2961
2952
|
void this.handleServerOffer(offer);
|
|
2962
2953
|
});
|
|
2963
2954
|
// Answer to a client-initiated offer
|
|
2964
2955
|
this.signallingSrv.onWebRtcAnswer$
|
|
2965
|
-
.pipe(filter(Truthy))
|
|
2956
|
+
.pipe(filter(Truthy), takeUntil(this.destroy$))
|
|
2966
2957
|
.subscribe((answer) => {
|
|
2967
2958
|
void this.handleServerAnswer(answer);
|
|
2968
2959
|
});
|
|
2969
2960
|
// ICE candidates — buffered until remote description is set
|
|
2970
|
-
this.signallingSrv.onWebRtcIce
|
|
2971
|
-
this.
|
|
2972
|
-
|
|
2973
|
-
});
|
|
2961
|
+
this.signallingSrv.onWebRtcIce$
|
|
2962
|
+
.pipe(takeUntil(this.destroy$))
|
|
2963
|
+
.subscribe((candidate) => {
|
|
2964
|
+
this.commandTelemetryService.trackStopCommand('EXT-iceCandidate', true, { multi: true });
|
|
2974
2965
|
if (this.remoteDescriptionSet) {
|
|
2975
2966
|
this.handleCandidateFromServer(candidate);
|
|
2976
2967
|
}
|
|
@@ -2995,11 +2986,15 @@ class WebRtcPlayerService extends SubService {
|
|
|
2995
2986
|
if (!this.pcClient) {
|
|
2996
2987
|
this.setupPeerConnection(this.cfg);
|
|
2997
2988
|
}
|
|
2989
|
+
const pc = this.pcClient;
|
|
2990
|
+
if (!pc) {
|
|
2991
|
+
return;
|
|
2992
|
+
}
|
|
2998
2993
|
// Offer already defines media transceivers — don't add extras
|
|
2999
|
-
await
|
|
2994
|
+
await pc.setRemoteDescription(offer);
|
|
3000
2995
|
this.remoteDescriptionSet = true;
|
|
3001
2996
|
this.flushIceCandidateBuffer();
|
|
3002
|
-
await this.createAnswer(
|
|
2997
|
+
await this.createAnswer(pc);
|
|
3003
2998
|
}
|
|
3004
2999
|
catch (e) {
|
|
3005
3000
|
Logger.error('Failed to handle server offer', e);
|
|
@@ -3044,10 +3039,16 @@ class WebRtcPlayerService extends SubService {
|
|
|
3044
3039
|
if (!this.pcClient) {
|
|
3045
3040
|
this.setupPeerConnection(this.cfg);
|
|
3046
3041
|
}
|
|
3042
|
+
const pc = this.pcClient;
|
|
3043
|
+
if (!pc) {
|
|
3044
|
+
return;
|
|
3045
|
+
}
|
|
3047
3046
|
// Client offers: transceivers first, then DC, then offer
|
|
3048
|
-
await this.setupTransceiversAsync(
|
|
3049
|
-
this.dcClient = this.createDataChannel(
|
|
3050
|
-
|
|
3047
|
+
await this.setupTransceiversAsync(pc);
|
|
3048
|
+
this.dcClient = this.createDataChannel(pc, 'UnrealDcConnection', {
|
|
3049
|
+
ordered: true,
|
|
3050
|
+
});
|
|
3051
|
+
await this.createOffer(pc);
|
|
3051
3052
|
}
|
|
3052
3053
|
catch (e) {
|
|
3053
3054
|
Logger.error('Failed to create WebRTC offer', e);
|
|
@@ -3106,7 +3107,7 @@ class WebRtcPlayerService extends SubService {
|
|
|
3106
3107
|
* RFC 6184 that encodes three H.264 parameters:
|
|
3107
3108
|
* - **Profile IDC** (`XX`) — the H.264 profile.
|
|
3108
3109
|
* - **Profile IOP** (`YY`) — constraint flags that further narrow the profile.
|
|
3109
|
-
* - **Level IDC** (`ZZ`) — the level
|
|
3110
|
+
* - **Level IDC** (`ZZ`) — the level which caps resolution/framerate/bitrate.
|
|
3110
3111
|
*
|
|
3111
3112
|
* ### H.264 profiles relevant to Unreal Engine Pixel Streaming
|
|
3112
3113
|
*
|
|
@@ -3124,12 +3125,12 @@ class WebRtcPlayerService extends SubService {
|
|
|
3124
3125
|
* | `f4001f` | High 4:4:4 Predictive | 3.1 | Lossless capable; rare in browsers |
|
|
3125
3126
|
*
|
|
3126
3127
|
* UE Pixel Streaming defaults to Constrained Baseline (`42e01f`) or High (`6400xx`)
|
|
3127
|
-
* depending on engine version and `WebRTC.H264Profile` CVar.
|
|
3128
|
+
* depending on the engine version and `WebRTC.H264Profile` CVar.
|
|
3128
3129
|
*
|
|
3129
3130
|
* We prioritize `42e01f` because it guarantees hardware decoding on
|
|
3130
3131
|
* virtually all client devices (desktop, mobile, embedded), avoiding
|
|
3131
3132
|
* fallback to software decoding or negotiation of a higher profile
|
|
3132
|
-
* that the client GPU may not
|
|
3133
|
+
* that the client GPU may not speed up.
|
|
3133
3134
|
*/
|
|
3134
3135
|
prioritizeH264Profile(sdp, profileLevelId) {
|
|
3135
3136
|
const lines = sdp.split('\r\n');
|
|
@@ -3472,10 +3473,10 @@ class WebRtcPlayerService extends SubService {
|
|
|
3472
3473
|
Logger.error("Couldn't create answer", e);
|
|
3473
3474
|
}
|
|
3474
3475
|
}
|
|
3475
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.
|
|
3476
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.
|
|
3476
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: WebRtcPlayerService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
3477
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: WebRtcPlayerService }); }
|
|
3477
3478
|
}
|
|
3478
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.
|
|
3479
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: WebRtcPlayerService, decorators: [{
|
|
3479
3480
|
type: Injectable
|
|
3480
3481
|
}], ctorParameters: () => [] });
|
|
3481
3482
|
|
|
@@ -3538,7 +3539,7 @@ class FileReceiverService extends SubService {
|
|
|
3538
3539
|
}
|
|
3539
3540
|
this.store
|
|
3540
3541
|
.select(unrealFeature.selectViewportReady)
|
|
3541
|
-
.pipe(filter(Truthy))
|
|
3542
|
+
.pipe(filter(Truthy), takeUntil(this.destroy$))
|
|
3542
3543
|
.subscribe(() => this.reset());
|
|
3543
3544
|
}
|
|
3544
3545
|
reset() {
|
|
@@ -3663,7 +3664,7 @@ class AggregatorService extends SubService {
|
|
|
3663
3664
|
initialize() {
|
|
3664
3665
|
this.store
|
|
3665
3666
|
.select(unrealFeature.selectCirrusConnected)
|
|
3666
|
-
.pipe(distinctUntilChanged())
|
|
3667
|
+
.pipe(distinctUntilChanged(), takeUntil(this.destroy$))
|
|
3667
3668
|
.subscribe((connected) => {
|
|
3668
3669
|
this.resetResponseList();
|
|
3669
3670
|
if (connected) {
|
|
@@ -3673,7 +3674,9 @@ class AggregatorService extends SubService {
|
|
|
3673
3674
|
const unlockViewport$ = this.store
|
|
3674
3675
|
.select(unrealFeature.selectViewportReady)
|
|
3675
3676
|
.pipe(filter(Truthy));
|
|
3676
|
-
merge(unlockViewport$, this.disconnect$)
|
|
3677
|
+
merge(unlockViewport$, this.disconnect$)
|
|
3678
|
+
.pipe(takeUntil(this.destroy$))
|
|
3679
|
+
.subscribe(() => {
|
|
3677
3680
|
this.removeLoadScreen();
|
|
3678
3681
|
});
|
|
3679
3682
|
if (!this.selectStreamConfig()?.autoStart ||
|
|
@@ -3685,22 +3688,6 @@ class AggregatorService extends SubService {
|
|
|
3685
3688
|
addResponseEventListener(name, listener) {
|
|
3686
3689
|
this.responseEventListeners.set(name, listener);
|
|
3687
3690
|
}
|
|
3688
|
-
showOnScreenKeyboard(command) {
|
|
3689
|
-
if (command.showOnScreenKeyboard) {
|
|
3690
|
-
// Show the 'edit text' button.
|
|
3691
|
-
//editTextButton.classList.remove('hiddenState');
|
|
3692
|
-
// Place the 'edit text' button near the UE4 input widget.
|
|
3693
|
-
//let pos = unquantizeAndDenormalizeUnsigned(command.x, command.y);
|
|
3694
|
-
//editTextButton.style.top = pos.y.toString() + 'px';
|
|
3695
|
-
//editTextButton.style.left = (pos.x - 40).toString() + 'px';
|
|
3696
|
-
}
|
|
3697
|
-
else {
|
|
3698
|
-
// Hide the 'edit text' button.
|
|
3699
|
-
//editTextButton.classList.add('hiddenState');
|
|
3700
|
-
// Hide the on-screen keyboard.
|
|
3701
|
-
// hiddenInput.blur();
|
|
3702
|
-
}
|
|
3703
|
-
}
|
|
3704
3691
|
removeLoadScreen() {
|
|
3705
3692
|
document
|
|
3706
3693
|
.getElementById(this.unrealConfig?.screenLockerContainerId ||
|
|
@@ -3768,12 +3755,8 @@ class AggregatorService extends SubService {
|
|
|
3768
3755
|
break;
|
|
3769
3756
|
}
|
|
3770
3757
|
case ToClientMessage.Command: {
|
|
3771
|
-
const
|
|
3772
|
-
Logger.colored(...COLOR_CODES.FROM_UNREAL,
|
|
3773
|
-
const command = JSON.parse(commandAsString);
|
|
3774
|
-
if (command.command === 'onScreenKeyboard') {
|
|
3775
|
-
this.showOnScreenKeyboard(command);
|
|
3776
|
-
}
|
|
3758
|
+
const command = JSON.parse(decodeData(anyData));
|
|
3759
|
+
Logger.colored(...COLOR_CODES.FROM_UNREAL, command);
|
|
3777
3760
|
break;
|
|
3778
3761
|
}
|
|
3779
3762
|
case ToClientMessage.FileExtension:
|
|
@@ -3819,10 +3802,10 @@ class AggregatorService extends SubService {
|
|
|
3819
3802
|
Logger.warn(`unrecognized data received, packet ID ${view[0]}`);
|
|
3820
3803
|
}
|
|
3821
3804
|
}
|
|
3822
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.
|
|
3823
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.
|
|
3805
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: AggregatorService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
3806
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: AggregatorService }); }
|
|
3824
3807
|
}
|
|
3825
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.
|
|
3808
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: AggregatorService, decorators: [{
|
|
3826
3809
|
type: Injectable
|
|
3827
3810
|
}], ctorParameters: () => [] });
|
|
3828
3811
|
|
|
@@ -3873,18 +3856,12 @@ class ConsoleExtensionsService extends SubService {
|
|
|
3873
3856
|
return true;
|
|
3874
3857
|
};
|
|
3875
3858
|
window.setResolution = ({ w, h }) => {
|
|
3859
|
+
const resolution = { x: w, y: h };
|
|
3876
3860
|
this.#commandsSender.sendCommandToUnreal({
|
|
3877
3861
|
command: MetaBoxCommand.FChangeResolutionCommand,
|
|
3878
|
-
payload: { resolution
|
|
3862
|
+
payload: { resolution },
|
|
3879
3863
|
});
|
|
3880
|
-
return
|
|
3881
|
-
};
|
|
3882
|
-
window.toggleBandwidth = () => {
|
|
3883
|
-
this.store
|
|
3884
|
-
.select(unrealFeature.selectLowBandwidth)
|
|
3885
|
-
.pipe(take(1))
|
|
3886
|
-
.subscribe((isLow) => this.store.dispatch(changeLowBandwidth({ lowBandwidth: !isLow })));
|
|
3887
|
-
return 'LowBandwidth => toggled';
|
|
3864
|
+
return `Resolution set to ${resolution.x}x${resolution.y}`;
|
|
3888
3865
|
};
|
|
3889
3866
|
window.setMaxFps = (maxFps) => {
|
|
3890
3867
|
this.store.dispatch(setMaxFps({ maxFps }));
|
|
@@ -3910,10 +3887,10 @@ class ConsoleExtensionsService extends SubService {
|
|
|
3910
3887
|
Logger.info('setWarnTime() => set time to appear the AFK window.');
|
|
3911
3888
|
Logger.info('emitCommand(command) => send command to Unreal Engine.');
|
|
3912
3889
|
}
|
|
3913
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.
|
|
3914
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.
|
|
3890
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: ConsoleExtensionsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
3891
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: ConsoleExtensionsService }); }
|
|
3915
3892
|
}
|
|
3916
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.
|
|
3893
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: ConsoleExtensionsService, decorators: [{
|
|
3917
3894
|
type: Injectable
|
|
3918
3895
|
}], ctorParameters: () => [] });
|
|
3919
3896
|
|
|
@@ -3929,10 +3906,10 @@ class DevModeService {
|
|
|
3929
3906
|
localStorage.removeItem('devMode');
|
|
3930
3907
|
}
|
|
3931
3908
|
}
|
|
3932
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.
|
|
3933
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.
|
|
3909
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: DevModeService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
3910
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: DevModeService, providedIn: 'root' }); }
|
|
3934
3911
|
}
|
|
3935
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.
|
|
3912
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: DevModeService, decorators: [{
|
|
3936
3913
|
type: Injectable,
|
|
3937
3914
|
args: [{
|
|
3938
3915
|
providedIn: 'root',
|
|
@@ -3959,7 +3936,9 @@ class UnrealCommunicatorService {
|
|
|
3959
3936
|
// of the store selector. The selector reads the current state and can fire on
|
|
3960
3937
|
// stale `true` from a previous session when switching components (Angular
|
|
3961
3938
|
// creates the new component before destroying the old one).
|
|
3962
|
-
this.actions
|
|
3939
|
+
this.actions$
|
|
3940
|
+
.pipe(ofType(dataChannelConnected), takeUntil$1(this.destroy$))
|
|
3941
|
+
.subscribe(() => {
|
|
3963
3942
|
this.requestInitialSettings();
|
|
3964
3943
|
this.requestQualityControl();
|
|
3965
3944
|
});
|
|
@@ -4043,10 +4022,10 @@ class UnrealCommunicatorService {
|
|
|
4043
4022
|
requestQualityControl() {
|
|
4044
4023
|
this.sendInputData(new Uint8Array([MessageType.RequestQualityControl]).buffer);
|
|
4045
4024
|
}
|
|
4046
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.
|
|
4047
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.
|
|
4025
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: UnrealCommunicatorService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
4026
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: UnrealCommunicatorService }); }
|
|
4048
4027
|
}
|
|
4049
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.
|
|
4028
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: UnrealCommunicatorService, decorators: [{
|
|
4050
4029
|
type: Injectable
|
|
4051
4030
|
}], ctorParameters: () => [] });
|
|
4052
4031
|
|
|
@@ -4075,7 +4054,15 @@ class InputService extends SubService {
|
|
|
4075
4054
|
KeyboardNumericCode.NumpadDecimal,
|
|
4076
4055
|
];
|
|
4077
4056
|
this.availableKeys = this.defaultKeys;
|
|
4057
|
+
this.options = InputOptions;
|
|
4078
4058
|
this.reInit$ = new Subject();
|
|
4059
|
+
this.deactivatedVideoTrigger$ = NEVER;
|
|
4060
|
+
this.normalizeAndQuantizeUnsigned = (_x, _y) => ({
|
|
4061
|
+
inRange: false,
|
|
4062
|
+
x: 65535,
|
|
4063
|
+
y: 65535,
|
|
4064
|
+
});
|
|
4065
|
+
this.normalizeAndQuantizeSigned = (_x, _y) => ({ x: 0, y: 0 });
|
|
4079
4066
|
this.videoBoundingRect = new DOMRect(0, 0, 1, 1);
|
|
4080
4067
|
this.fingerIds = new Map();
|
|
4081
4068
|
this.maxByteValue = 255;
|
|
@@ -4098,11 +4085,11 @@ class InputService extends SubService {
|
|
|
4098
4085
|
const visibilityVisibleTrigger$ = fromEvent(document, 'visibilitychange').pipe(map$1(() => document.visibilityState === 'visible'), filter(Truthy), startWith(true));
|
|
4099
4086
|
this.deactivatedVideoTrigger$ = merge(this.disconnect$, this.reInit$, visibilityHiddenTrigger$);
|
|
4100
4087
|
merge(visibilityVisibleTrigger$, this.store.select(unrealFeature.selectViewportReady).pipe(filter(Truthy)))
|
|
4101
|
-
.pipe(filter(() => !!this.video))
|
|
4088
|
+
.pipe(filter(() => !!this.video), takeUntil$1(this.destroy$))
|
|
4102
4089
|
.subscribe(() => this.setup());
|
|
4103
4090
|
}
|
|
4104
4091
|
useKeyboardKeys(keys) {
|
|
4105
|
-
this.availableKeys = keys
|
|
4092
|
+
this.availableKeys = keys;
|
|
4106
4093
|
}
|
|
4107
4094
|
get video() {
|
|
4108
4095
|
return this.videoService.video;
|
|
@@ -4164,57 +4151,53 @@ class InputService extends SubService {
|
|
|
4164
4151
|
};
|
|
4165
4152
|
}
|
|
4166
4153
|
setupNormalizeAndQuantize(videoElement) {
|
|
4167
|
-
|
|
4168
|
-
|
|
4169
|
-
|
|
4170
|
-
|
|
4171
|
-
|
|
4172
|
-
|
|
4173
|
-
|
|
4174
|
-
|
|
4175
|
-
|
|
4176
|
-
|
|
4177
|
-
|
|
4178
|
-
|
|
4179
|
-
|
|
4180
|
-
|
|
4181
|
-
|
|
4182
|
-
|
|
4183
|
-
|
|
4184
|
-
|
|
4185
|
-
|
|
4186
|
-
|
|
4187
|
-
|
|
4188
|
-
|
|
4189
|
-
|
|
4190
|
-
|
|
4191
|
-
|
|
4192
|
-
else {
|
|
4193
|
-
return {
|
|
4194
|
-
inRange: true,
|
|
4195
|
-
x: normalizedX * 65536,
|
|
4196
|
-
y: normalizedY * 65536,
|
|
4197
|
-
};
|
|
4198
|
-
}
|
|
4199
|
-
};
|
|
4200
|
-
// Signed.
|
|
4201
|
-
this.normalizeAndQuantizeSigned = (x, y) => {
|
|
4202
|
-
const normalizedX = x / (0.5 * videoElement.clientWidth);
|
|
4203
|
-
const normalizedY = y / (0.5 * videoElement.clientHeight);
|
|
4154
|
+
this.videoBoundingRect = videoElement.getBoundingClientRect();
|
|
4155
|
+
this.offsetParams = this.getObjectFitOffset(videoElement);
|
|
4156
|
+
// Unsigned XY positions are the ratio (0.0..1.0) along a viewport axis,
|
|
4157
|
+
// quantized into an uint16 (0..65536).
|
|
4158
|
+
// Signed XY deltas are the ratio (-1.0..1.0) along a viewport axis,
|
|
4159
|
+
// quantized into an int16 (-32767..32767).
|
|
4160
|
+
// This allows the browser viewport and client viewport to have a different
|
|
4161
|
+
// size.
|
|
4162
|
+
// Hack: Currently, we set an out-of-range position to an extreme (65535)
|
|
4163
|
+
// as we can't yet accurately detect mouse enter and leave events
|
|
4164
|
+
// precisely inside a video with an aspect ratio which causes mattes.
|
|
4165
|
+
this.normalizeAndQuantizeUnsigned = (x, y) => {
|
|
4166
|
+
const normalizedX = x / videoElement.clientWidth;
|
|
4167
|
+
const normalizedY = y / videoElement.clientHeight;
|
|
4168
|
+
if (normalizedX < 0.0 ||
|
|
4169
|
+
normalizedX > 1.0 ||
|
|
4170
|
+
normalizedY < 0.0 ||
|
|
4171
|
+
normalizedY > 1.0) {
|
|
4172
|
+
return {
|
|
4173
|
+
inRange: false,
|
|
4174
|
+
x: 65535,
|
|
4175
|
+
y: 65535,
|
|
4176
|
+
};
|
|
4177
|
+
}
|
|
4178
|
+
else {
|
|
4204
4179
|
return {
|
|
4205
|
-
|
|
4206
|
-
|
|
4180
|
+
inRange: true,
|
|
4181
|
+
x: normalizedX * 65536,
|
|
4182
|
+
y: normalizedY * 65536,
|
|
4207
4183
|
};
|
|
4184
|
+
}
|
|
4185
|
+
};
|
|
4186
|
+
// Signed.
|
|
4187
|
+
this.normalizeAndQuantizeSigned = (x, y) => {
|
|
4188
|
+
const normalizedX = x / (0.5 * videoElement.clientWidth);
|
|
4189
|
+
const normalizedY = y / (0.5 * videoElement.clientHeight);
|
|
4190
|
+
return {
|
|
4191
|
+
x: normalizedX * 32767,
|
|
4192
|
+
y: normalizedY * 32767,
|
|
4208
4193
|
};
|
|
4209
|
-
}
|
|
4194
|
+
};
|
|
4210
4195
|
}
|
|
4211
4196
|
sendInputData(data) {
|
|
4212
4197
|
this.commandsSender.sendInputData(data);
|
|
4213
4198
|
}
|
|
4214
4199
|
registerInputs(video) {
|
|
4215
|
-
|
|
4216
|
-
.select(unrealFeature.selectLowBandwidth)
|
|
4217
|
-
.pipe(distinctUntilChanged(), filter(Truthy)), fromEvent(window, 'blur'))
|
|
4200
|
+
fromEvent(window, 'blur')
|
|
4218
4201
|
.pipe(filter(() => !!video), takeUntil$1(this.deactivatedVideoTrigger$))
|
|
4219
4202
|
.subscribe(() => this.releaseMouseButtons(255, 0, 0));
|
|
4220
4203
|
this.registerMouseEnterAndLeaveEvents(video);
|
|
@@ -4248,11 +4231,12 @@ class InputService extends SubService {
|
|
|
4248
4231
|
this.fingerIds.set(touch.identifier, finger);
|
|
4249
4232
|
};
|
|
4250
4233
|
const forgetTouch = (touch) => {
|
|
4251
|
-
this.
|
|
4234
|
+
const finger = this.fingerIds.get(touch.identifier);
|
|
4235
|
+
if (finger) {
|
|
4236
|
+
this.fingers.push(finger);
|
|
4237
|
+
}
|
|
4252
4238
|
// Sort array back into descending order. This means if finger '1' were to lift after finger '0', we would ensure that 0 will be the first index to pop
|
|
4253
|
-
this.fingers.sort(
|
|
4254
|
-
return b - a;
|
|
4255
|
-
});
|
|
4239
|
+
this.fingers.sort((a, b) => b - a);
|
|
4256
4240
|
this.fingerIds.delete(touch.identifier);
|
|
4257
4241
|
};
|
|
4258
4242
|
const emitTouchData = (type, touches) => {
|
|
@@ -4263,21 +4247,24 @@ class InputService extends SubService {
|
|
|
4263
4247
|
const touch = touches[t];
|
|
4264
4248
|
const { x, y } = this.getTouchPositionWithOffset(touch);
|
|
4265
4249
|
Logger.info(`F${this.fingerIds.get(touch.identifier)}=(${x}, ${y})`);
|
|
4266
|
-
const
|
|
4250
|
+
const normalizeCoordinates = this.normalizeAndQuantizeUnsigned(x, y);
|
|
4267
4251
|
const data = new DataView(new ArrayBuffer(9));
|
|
4268
4252
|
data.setUint8(0, type);
|
|
4269
4253
|
data.setUint8(1, numTouches);
|
|
4270
|
-
data.setUint16(byte,
|
|
4254
|
+
data.setUint16(byte, normalizeCoordinates.x, true);
|
|
4271
4255
|
byte += 2;
|
|
4272
|
-
data.setUint16(byte,
|
|
4256
|
+
data.setUint16(byte, normalizeCoordinates.y, true);
|
|
4273
4257
|
byte += 2;
|
|
4274
|
-
|
|
4258
|
+
const finger = this.fingerIds.get(touch.identifier);
|
|
4259
|
+
if (finger) {
|
|
4260
|
+
data.setUint8(byte, finger);
|
|
4261
|
+
}
|
|
4275
4262
|
byte += 1;
|
|
4276
4263
|
// force is between 0.0 and 1.0, so quantize into byte.
|
|
4277
4264
|
// iOs bug: Forced to be always 0.5 on all devices as we do not use forced touch any way;/
|
|
4278
4265
|
data.setUint8(byte, this.maxByteValue * 0.5);
|
|
4279
4266
|
byte += 1;
|
|
4280
|
-
data.setUint8(byte,
|
|
4267
|
+
data.setUint8(byte, normalizeCoordinates.inRange ? 1 : 0);
|
|
4281
4268
|
byte += 1;
|
|
4282
4269
|
this.sendInputData(data.buffer);
|
|
4283
4270
|
}
|
|
@@ -4320,42 +4307,42 @@ class InputService extends SubService {
|
|
|
4320
4307
|
window.focus();
|
|
4321
4308
|
}
|
|
4322
4309
|
emitMouseMove(x, y, deltaX, deltaY) {
|
|
4323
|
-
const
|
|
4310
|
+
const normalizeCoordinates = this.normalizeAndQuantizeUnsigned(x, y);
|
|
4324
4311
|
const delta = this.normalizeAndQuantizeSigned(deltaX, deltaY);
|
|
4325
|
-
const
|
|
4326
|
-
|
|
4327
|
-
|
|
4328
|
-
|
|
4329
|
-
|
|
4330
|
-
|
|
4331
|
-
this.sendInputData(
|
|
4312
|
+
const data = new DataView(new ArrayBuffer(9));
|
|
4313
|
+
data.setUint8(0, MessageType.MouseMove);
|
|
4314
|
+
data.setUint16(1, normalizeCoordinates.x, true);
|
|
4315
|
+
data.setUint16(3, normalizeCoordinates.y, true);
|
|
4316
|
+
data.setInt16(5, delta.x, true);
|
|
4317
|
+
data.setInt16(7, delta.y, true);
|
|
4318
|
+
this.sendInputData(data.buffer);
|
|
4332
4319
|
}
|
|
4333
4320
|
emitMouseDown(button, x, y) {
|
|
4334
|
-
const
|
|
4335
|
-
const
|
|
4336
|
-
|
|
4337
|
-
|
|
4338
|
-
|
|
4339
|
-
|
|
4340
|
-
this.sendInputData(
|
|
4321
|
+
const normalizeCoordinates = this.normalizeAndQuantizeUnsigned(x, y);
|
|
4322
|
+
const data = new DataView(new ArrayBuffer(6));
|
|
4323
|
+
data.setUint8(0, MessageType.MouseDown);
|
|
4324
|
+
data.setUint8(1, button);
|
|
4325
|
+
data.setUint16(2, normalizeCoordinates.x, true);
|
|
4326
|
+
data.setUint16(4, normalizeCoordinates.y, true);
|
|
4327
|
+
this.sendInputData(data.buffer);
|
|
4341
4328
|
}
|
|
4342
4329
|
emitMouseUp(button, x, y) {
|
|
4343
|
-
const
|
|
4344
|
-
const
|
|
4345
|
-
|
|
4346
|
-
|
|
4347
|
-
|
|
4348
|
-
|
|
4349
|
-
this.sendInputData(
|
|
4330
|
+
const normalizeCoordinates = this.normalizeAndQuantizeUnsigned(x, y);
|
|
4331
|
+
const data = new DataView(new ArrayBuffer(6));
|
|
4332
|
+
data.setUint8(0, MessageType.MouseUp);
|
|
4333
|
+
data.setUint8(1, button);
|
|
4334
|
+
data.setUint16(2, normalizeCoordinates.x, true);
|
|
4335
|
+
data.setUint16(4, normalizeCoordinates.y, true);
|
|
4336
|
+
this.sendInputData(data.buffer);
|
|
4350
4337
|
}
|
|
4351
4338
|
emitMouseWheel(delta, x, y) {
|
|
4352
|
-
const
|
|
4353
|
-
const
|
|
4354
|
-
|
|
4355
|
-
|
|
4356
|
-
|
|
4357
|
-
|
|
4358
|
-
this.sendInputData(
|
|
4339
|
+
const normalizeCoordinates = this.normalizeAndQuantizeUnsigned(x, y);
|
|
4340
|
+
const data = new DataView(new ArrayBuffer(7));
|
|
4341
|
+
data.setUint8(0, MessageType.MouseWheel);
|
|
4342
|
+
data.setInt16(1, delta, true);
|
|
4343
|
+
data.setUint16(3, normalizeCoordinates.x, true);
|
|
4344
|
+
data.setUint16(5, normalizeCoordinates.y, true);
|
|
4345
|
+
this.sendInputData(data.buffer);
|
|
4359
4346
|
}
|
|
4360
4347
|
releaseMouseButtons(buttons, x, y) {
|
|
4361
4348
|
if (buttons & MouseButtonsMask.PrimaryButton) {
|
|
@@ -4374,7 +4361,7 @@ class InputService extends SubService {
|
|
|
4374
4361
|
this.emitMouseUp(MouseButton.FifthButton, x, y);
|
|
4375
4362
|
}
|
|
4376
4363
|
}
|
|
4377
|
-
// If the user has any mouse buttons pressed then press them again.
|
|
4364
|
+
// If the user has any mouse buttons pressed, then press them again.
|
|
4378
4365
|
pressMouseButtons(buttons, x, y) {
|
|
4379
4366
|
if (buttons & MouseButtonsMask.PrimaryButton) {
|
|
4380
4367
|
this.emitMouseDown(MouseButton.MainButton, x, y);
|
|
@@ -4393,58 +4380,53 @@ class InputService extends SubService {
|
|
|
4393
4380
|
}
|
|
4394
4381
|
}
|
|
4395
4382
|
registerHoveringMouseEvents(htmlVideoElement) {
|
|
4396
|
-
htmlVideoElement
|
|
4383
|
+
fromEvent(htmlVideoElement, 'mousemove')
|
|
4384
|
+
.pipe(takeUntil$1(this.deactivatedVideoTrigger$))
|
|
4385
|
+
.subscribe((e) => {
|
|
4397
4386
|
const { x, y } = this.getMousePositionWithOffset(e);
|
|
4398
4387
|
this.emitMouseMove(x, y, e.movementX, e.movementY);
|
|
4399
4388
|
e.preventDefault();
|
|
4400
|
-
};
|
|
4401
|
-
htmlVideoElement
|
|
4389
|
+
});
|
|
4390
|
+
fromEvent(htmlVideoElement, 'mousedown')
|
|
4391
|
+
.pipe(takeUntil$1(this.deactivatedVideoTrigger$))
|
|
4392
|
+
.subscribe((e) => {
|
|
4402
4393
|
const { x, y } = this.getMousePositionWithOffset(e);
|
|
4403
4394
|
this.focusWindow();
|
|
4404
4395
|
this.emitMouseDown(e.button, x, y);
|
|
4405
4396
|
e.preventDefault();
|
|
4406
|
-
};
|
|
4407
|
-
htmlVideoElement
|
|
4397
|
+
});
|
|
4398
|
+
fromEvent(htmlVideoElement, 'mouseup')
|
|
4399
|
+
.pipe(takeUntil$1(this.deactivatedVideoTrigger$))
|
|
4400
|
+
.subscribe((e) => {
|
|
4408
4401
|
const { x, y } = this.getMousePositionWithOffset(e);
|
|
4409
4402
|
this.emitMouseUp(e.button, x, y);
|
|
4410
4403
|
e.preventDefault();
|
|
4411
|
-
};
|
|
4412
|
-
// When the context menu is shown, then it is safest to release the button
|
|
4413
|
-
// pressed when the event happened. This will guarantee we will
|
|
4414
|
-
// get at least one mouse up corresponding to a mouse down event. Otherwise,
|
|
4415
|
-
// the mouse can get stuck.
|
|
4416
|
-
// https://github.com/facebook/react/issues/5531
|
|
4417
|
-
// playerElement.oncontextmenu = (e) => {
|
|
4418
|
-
// e.preventDefault();
|
|
4419
|
-
// this.emitMouseUp(e.button, e.offsetX, e.offsetY);
|
|
4420
|
-
// };
|
|
4404
|
+
});
|
|
4421
4405
|
fromEvent(htmlVideoElement, 'wheel')
|
|
4422
4406
|
.pipe(takeUntil$1(this.deactivatedVideoTrigger$))
|
|
4423
4407
|
.subscribe((e) => {
|
|
4424
4408
|
this.emitMouseWheel(e.deltaY * -120, e.offsetX, e.offsetY);
|
|
4425
4409
|
e.preventDefault();
|
|
4426
4410
|
});
|
|
4427
|
-
htmlVideoElement.pressMouseButtons = (e) => {
|
|
4428
|
-
this.pressMouseButtons(e.buttons, e.offsetX, e.offsetY);
|
|
4429
|
-
};
|
|
4430
|
-
htmlVideoElement.releaseMouseButtons = (e) => {
|
|
4431
|
-
this.releaseMouseButtons(e.buttons, e.offsetX, e.offsetY);
|
|
4432
|
-
};
|
|
4433
4411
|
}
|
|
4434
4412
|
registerMouseEnterAndLeaveEvents(htmlVideoElement) {
|
|
4435
|
-
htmlVideoElement
|
|
4413
|
+
fromEvent(htmlVideoElement, 'mouseenter')
|
|
4414
|
+
.pipe(takeUntil$1(this.deactivatedVideoTrigger$))
|
|
4415
|
+
.subscribe((e) => {
|
|
4436
4416
|
this.focusWindow();
|
|
4437
|
-
const
|
|
4438
|
-
|
|
4439
|
-
this.sendInputData(
|
|
4440
|
-
|
|
4441
|
-
};
|
|
4442
|
-
htmlVideoElement
|
|
4443
|
-
|
|
4444
|
-
|
|
4445
|
-
|
|
4446
|
-
|
|
4447
|
-
|
|
4417
|
+
const data = new DataView(new ArrayBuffer(1));
|
|
4418
|
+
data.setUint8(0, MessageType.MouseEnter);
|
|
4419
|
+
this.sendInputData(data.buffer);
|
|
4420
|
+
this.pressMouseButtons(e.buttons, e.offsetX, e.offsetY);
|
|
4421
|
+
});
|
|
4422
|
+
fromEvent(htmlVideoElement, 'mouseleave')
|
|
4423
|
+
.pipe(takeUntil$1(this.deactivatedVideoTrigger$))
|
|
4424
|
+
.subscribe((e) => {
|
|
4425
|
+
const data = new DataView(new ArrayBuffer(1));
|
|
4426
|
+
data.setUint8(0, MessageType.MouseLeave);
|
|
4427
|
+
this.sendInputData(data.buffer);
|
|
4428
|
+
this.releaseMouseButtons(e.buttons, e.offsetX, e.offsetY);
|
|
4429
|
+
});
|
|
4448
4430
|
}
|
|
4449
4431
|
// Browser keys do not have a charCode so we only need to test keyCode.
|
|
4450
4432
|
isKeyCodeBrowserKey(keyCode) {
|
|
@@ -4638,10 +4620,10 @@ class RegionsPingService {
|
|
|
4638
4620
|
throw error;
|
|
4639
4621
|
}
|
|
4640
4622
|
}
|
|
4641
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.
|
|
4642
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.
|
|
4623
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: RegionsPingService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
4624
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: RegionsPingService }); }
|
|
4643
4625
|
}
|
|
4644
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.
|
|
4626
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: RegionsPingService, decorators: [{
|
|
4645
4627
|
type: Injectable
|
|
4646
4628
|
}] });
|
|
4647
4629
|
|
|
@@ -4671,11 +4653,9 @@ class StreamStatusTelemetryService {
|
|
|
4671
4653
|
return this.videoService.videoStats$.pipe(throttleTime(5000, asyncScheduler, {
|
|
4672
4654
|
leading: true,
|
|
4673
4655
|
trailing: true,
|
|
4674
|
-
}), withLatestFrom(this.store.select(unrealFeature.selectAwsInstance),
|
|
4656
|
+
}), withLatestFrom(this.store.select(unrealFeature.selectAwsInstance), signalingReadyTime$, viewPortReadyTime$), map$1(([data, signalingServer, signalingReadyTime, viewPortReadyTime,]) => this.mapEventData({
|
|
4675
4657
|
data,
|
|
4676
4658
|
signalingServer,
|
|
4677
|
-
isLowBandwidth,
|
|
4678
|
-
lbmStats,
|
|
4679
4659
|
startTimeUtc,
|
|
4680
4660
|
signalingReadyTime,
|
|
4681
4661
|
viewPortReadyTime,
|
|
@@ -4692,7 +4672,7 @@ class StreamStatusTelemetryService {
|
|
|
4692
4672
|
return readyState$.pipe(filter(Boolean), take$1(1), map$1(() => Date.now() - startedAt), startWith$1(undefined));
|
|
4693
4673
|
}
|
|
4694
4674
|
mapEventData(params) {
|
|
4695
|
-
const { data, signalingServer,
|
|
4675
|
+
const { data, signalingServer, startTimeUtc, signalingReadyTime, viewPortReadyTime, } = params;
|
|
4696
4676
|
const { bitrate, VideoEncoderQP, framesPerSecond, frameWidth, frameHeight, jitter, packetsLost, currentRoundTripTime, runTime, } = data.aggregatedStats;
|
|
4697
4677
|
return {
|
|
4698
4678
|
startTimeUtc,
|
|
@@ -4701,7 +4681,6 @@ class StreamStatusTelemetryService {
|
|
|
4701
4681
|
runTime,
|
|
4702
4682
|
frameWidth,
|
|
4703
4683
|
frameHeight,
|
|
4704
|
-
isLowBandwidth,
|
|
4705
4684
|
client: signalingServer.wsUrl,
|
|
4706
4685
|
pixelRatio: window.devicePixelRatio,
|
|
4707
4686
|
framesPerSecond,
|
|
@@ -4709,7 +4688,6 @@ class StreamStatusTelemetryService {
|
|
|
4709
4688
|
packetsLost,
|
|
4710
4689
|
instanceName: signalingServer.instanceName,
|
|
4711
4690
|
bitrate,
|
|
4712
|
-
lbmStats,
|
|
4713
4691
|
rtt: currentRoundTripTime,
|
|
4714
4692
|
VideoEncoderQP,
|
|
4715
4693
|
};
|
|
@@ -4717,10 +4695,10 @@ class StreamStatusTelemetryService {
|
|
|
4717
4695
|
trackEventToMixPanel(data) {
|
|
4718
4696
|
this.store.dispatch(trackMixpanelEvent({ event: 'streamStatus', data }));
|
|
4719
4697
|
}
|
|
4720
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.
|
|
4721
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.
|
|
4698
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: StreamStatusTelemetryService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
4699
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: StreamStatusTelemetryService }); }
|
|
4722
4700
|
}
|
|
4723
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.
|
|
4701
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: StreamStatusTelemetryService, decorators: [{
|
|
4724
4702
|
type: Injectable
|
|
4725
4703
|
}], ctorParameters: () => [] });
|
|
4726
4704
|
|
|
@@ -4953,10 +4931,10 @@ class StreamStatusTelemetryService2 {
|
|
|
4953
4931
|
],
|
|
4954
4932
|
},
|
|
4955
4933
|
];
|
|
4956
|
-
if (this.unrealConfig?.playwright
|
|
4957
|
-
|
|
4958
|
-
if (!this.unrealConfig?.streamTelemetryV2)
|
|
4934
|
+
if (this.unrealConfig?.playwright ||
|
|
4935
|
+
!this.unrealConfig?.streamTelemetryV2) {
|
|
4959
4936
|
return;
|
|
4937
|
+
}
|
|
4960
4938
|
this.init();
|
|
4961
4939
|
}
|
|
4962
4940
|
getOrCreateUserId() {
|
|
@@ -5372,10 +5350,10 @@ class StreamStatusTelemetryService2 {
|
|
|
5372
5350
|
data: { userId: this.userId, ...data },
|
|
5373
5351
|
}));
|
|
5374
5352
|
}
|
|
5375
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.
|
|
5376
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.
|
|
5353
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: StreamStatusTelemetryService2, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
5354
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: StreamStatusTelemetryService2 }); }
|
|
5377
5355
|
}
|
|
5378
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.
|
|
5356
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: StreamStatusTelemetryService2, decorators: [{
|
|
5379
5357
|
type: Injectable
|
|
5380
5358
|
}], ctorParameters: () => [] });
|
|
5381
5359
|
// ──────────────────────────────────────────────────────────────────
|
|
@@ -5457,30 +5435,29 @@ class FileHandlerService {
|
|
|
5457
5435
|
setTimeout(() => sender(out), 0);
|
|
5458
5436
|
return observable;
|
|
5459
5437
|
}
|
|
5460
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.
|
|
5461
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.
|
|
5438
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: FileHandlerService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
5439
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: FileHandlerService }); }
|
|
5462
5440
|
}
|
|
5463
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.
|
|
5441
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: FileHandlerService, decorators: [{
|
|
5464
5442
|
type: Injectable
|
|
5465
5443
|
}] });
|
|
5466
5444
|
|
|
5467
5445
|
class AnalyticsService extends SubService {
|
|
5468
|
-
#store = inject(Store);
|
|
5469
5446
|
/** Signals monitorMouse inner subscriptions to stop (viewport lost / new session). */
|
|
5470
5447
|
#stopMouse$ = new Subject();
|
|
5471
5448
|
sendEventToMixPanel(name, params = {}) {
|
|
5472
5449
|
Logger.log('Analytics Event:', name, params);
|
|
5473
|
-
this
|
|
5450
|
+
this.store.dispatch(saveAnalyticsEvent({ event: { name, params } }));
|
|
5474
5451
|
}
|
|
5475
5452
|
constructor() {
|
|
5476
5453
|
super();
|
|
5477
|
-
const abortSignal$ = this
|
|
5454
|
+
const abortSignal$ = this.store
|
|
5478
5455
|
.select(unrealFeature.selectViewportReady)
|
|
5479
5456
|
.pipe(filter$1(Falsy), map(() => void 0));
|
|
5480
|
-
this
|
|
5457
|
+
this.store
|
|
5481
5458
|
.select(unrealFeature.selectViewportReady)
|
|
5482
|
-
.pipe(distinctUntilChanged(), filter$1(Truthy),
|
|
5483
|
-
.subscribe();
|
|
5459
|
+
.pipe(distinctUntilChanged(), filter$1(Truthy), takeUntil$1(this.destroy$))
|
|
5460
|
+
.subscribe(() => this.monitorMouse(abortSignal$));
|
|
5484
5461
|
}
|
|
5485
5462
|
monitorMouse(abortSignal$) {
|
|
5486
5463
|
this.#stopMouse$.next();
|
|
@@ -5549,10 +5526,10 @@ class AnalyticsService extends SubService {
|
|
|
5549
5526
|
});
|
|
5550
5527
|
});
|
|
5551
5528
|
}
|
|
5552
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.
|
|
5553
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.
|
|
5529
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: AnalyticsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
5530
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: AnalyticsService }); }
|
|
5554
5531
|
}
|
|
5555
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.
|
|
5532
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: AnalyticsService, decorators: [{
|
|
5556
5533
|
type: Injectable
|
|
5557
5534
|
}], ctorParameters: () => [] });
|
|
5558
5535
|
|
|
@@ -5919,10 +5896,10 @@ class FpsMonitorService {
|
|
|
5919
5896
|
}
|
|
5920
5897
|
return { fps: fps / len, bitrate: bitrate / len, qp: qp / len };
|
|
5921
5898
|
}
|
|
5922
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.
|
|
5923
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.
|
|
5899
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: FpsMonitorService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
5900
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: FpsMonitorService }); }
|
|
5924
5901
|
}
|
|
5925
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.
|
|
5902
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: FpsMonitorService, decorators: [{
|
|
5926
5903
|
type: Injectable
|
|
5927
5904
|
}], ctorParameters: () => [] });
|
|
5928
5905
|
|
|
@@ -5953,12 +5930,7 @@ class UnrealCallbackService {
|
|
|
5953
5930
|
* ```
|
|
5954
5931
|
*/
|
|
5955
5932
|
fromUnrealCallback(command) {
|
|
5956
|
-
return this.actions$.pipe(ofType(unrealCommandCallback), map$1(({ json }) => {
|
|
5957
|
-
if ('commandCallback' in json) {
|
|
5958
|
-
return json.commandCallback;
|
|
5959
|
-
}
|
|
5960
|
-
return json;
|
|
5961
|
-
}), filter((json) => json.command === command), map$1((data) => ({
|
|
5933
|
+
return this.actions$.pipe(ofType(unrealCommandCallback), map$1(({ json }) => 'commandCallback' in json ? json.commandCallback : json), filter((json) => json.command === command), map$1((data) => ({
|
|
5962
5934
|
command: data.command,
|
|
5963
5935
|
payload: 'payload' in data ? data.payload : null,
|
|
5964
5936
|
})));
|
|
@@ -5993,10 +5965,10 @@ class UnrealCallbackService {
|
|
|
5993
5965
|
setTimeout(() => sender({ ...data, correlationId }), 0);
|
|
5994
5966
|
return observable;
|
|
5995
5967
|
}
|
|
5996
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.
|
|
5997
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.
|
|
5968
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: UnrealCallbackService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
5969
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: UnrealCallbackService }); }
|
|
5998
5970
|
}
|
|
5999
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.
|
|
5971
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: UnrealCallbackService, decorators: [{
|
|
6000
5972
|
type: Injectable
|
|
6001
5973
|
}] });
|
|
6002
5974
|
|
|
@@ -6005,19 +5977,21 @@ class AfkTimeoutModalComponent {
|
|
|
6005
5977
|
this.#store = inject(Store);
|
|
6006
5978
|
this.#afkService = inject(AFKService);
|
|
6007
5979
|
this.isAfkTimerVisible = this.#store.selectSignal(unrealFeature.selectIsAfkTimerVisible);
|
|
5980
|
+
this.showAfkTimeoutPopup = this.#store.selectSignal(unrealFeature.selectShowAfkTimeoutPopup);
|
|
6008
5981
|
this.afkCountdown = this.#store.selectSignal(unrealFeature.selectAfkCountdown);
|
|
5982
|
+
this.isShowAfkPopup = computed(() => this.isAfkTimerVisible() && this.showAfkTimeoutPopup(), ...(ngDevMode ? [{ debugName: "isShowAfkPopup" }] : /* istanbul ignore next */ []));
|
|
6009
5983
|
}
|
|
6010
5984
|
#store;
|
|
6011
5985
|
#afkService;
|
|
6012
5986
|
resetAfk() {
|
|
6013
5987
|
this.#afkService.reset();
|
|
6014
5988
|
}
|
|
6015
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.
|
|
6016
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.
|
|
5989
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: AfkTimeoutModalComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
5990
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.11", type: AfkTimeoutModalComponent, isStandalone: true, selector: "app-afk-timeout-modal", ngImport: i0, template: "@if (isShowAfkPopup()) {\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", "srcButtonConfig", "formID", "data-testid", "ariaLabel"], outputs: ["onClick", "onSubmit"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
6017
5991
|
}
|
|
6018
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.
|
|
5992
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: AfkTimeoutModalComponent, decorators: [{
|
|
6019
5993
|
type: Component,
|
|
6020
|
-
args: [{ selector: 'app-afk-timeout-modal', changeDetection: ChangeDetectionStrategy.OnPush, imports: [SourceButtonComponent], template: "@if (
|
|
5994
|
+
args: [{ selector: 'app-afk-timeout-modal', changeDetection: ChangeDetectionStrategy.OnPush, imports: [SourceButtonComponent], template: "@if (isShowAfkPopup()) {\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"] }]
|
|
6021
5995
|
}] });
|
|
6022
5996
|
|
|
6023
5997
|
class FreezeFrameComponent {
|
|
@@ -6027,10 +6001,10 @@ class FreezeFrameComponent {
|
|
|
6027
6001
|
this.combinedFreeze = this.#store.selectSignal(selectFreezeFrameCombinedDataUrl);
|
|
6028
6002
|
}
|
|
6029
6003
|
#store;
|
|
6030
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.
|
|
6031
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.
|
|
6004
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: FreezeFrameComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
6005
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.11", type: FreezeFrameComponent, isStandalone: true, selector: "app-freeze-frame", ngImport: i0, template: "@let image = combinedFreeze();\n@let progress = freezeFrameProgressMessageFromVideo();\n\n<div class=\"freeze-images\">\n @if (image) {\n <img [src]=\"image\" class=\"videoStillImage\" alt=\"freezeFrameImage\" />\n }\n\n @if (progress) {\n <div class=\"progress-status\">\n {{ progress }}\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 }); }
|
|
6032
6006
|
}
|
|
6033
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.
|
|
6007
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: FreezeFrameComponent, decorators: [{
|
|
6034
6008
|
type: Component,
|
|
6035
6009
|
args: [{ selector: 'app-freeze-frame', changeDetection: ChangeDetectionStrategy.OnPush, template: "@let image = combinedFreeze();\n@let progress = freezeFrameProgressMessageFromVideo();\n\n<div class=\"freeze-images\">\n @if (image) {\n <img [src]=\"image\" class=\"videoStillImage\" alt=\"freezeFrameImage\" />\n }\n\n @if (progress) {\n <div class=\"progress-status\">\n {{ progress }}\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"] }]
|
|
6036
6010
|
}] });
|
|
@@ -6058,10 +6032,10 @@ class SafePipe {
|
|
|
6058
6032
|
throw new Error(`Invalid safe type specified: ${type}`);
|
|
6059
6033
|
}
|
|
6060
6034
|
}
|
|
6061
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.
|
|
6062
|
-
static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.
|
|
6035
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: SafePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
|
|
6036
|
+
static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.11", ngImport: i0, type: SafePipe, isStandalone: true, name: "safe" }); }
|
|
6063
6037
|
}
|
|
6064
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.
|
|
6038
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: SafePipe, decorators: [{
|
|
6065
6039
|
type: Pipe,
|
|
6066
6040
|
args: [{
|
|
6067
6041
|
name: 'safe',
|
|
@@ -6073,10 +6047,10 @@ class LowBandwidthModalComponent {
|
|
|
6073
6047
|
close(value) {
|
|
6074
6048
|
this.#dialogRef.close(value || false);
|
|
6075
6049
|
}
|
|
6076
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.
|
|
6077
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.
|
|
6050
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: LowBandwidthModalComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
6051
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.11", 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 weight=\"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", "weight", "size", "context", "customClass", "isFullWidth", "isPressed", "isDisabled", "isLoading", "isInverted", "srcButtonConfig", "formID", "data-testid", "ariaLabel"], outputs: ["onClick", "onSubmit"] }, { kind: "pipe", type: SafePipe, name: "safe" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
6078
6052
|
}
|
|
6079
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.
|
|
6053
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: LowBandwidthModalComponent, decorators: [{
|
|
6080
6054
|
type: Component,
|
|
6081
6055
|
args: [{ selector: 'app-low-bandwidth-modal', changeDetection: ChangeDetectionStrategy.OnPush, imports: [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 weight=\"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"] }]
|
|
6082
6056
|
}] });
|
|
@@ -6088,15 +6062,15 @@ class ImageLoadingSrcComponent {
|
|
|
6088
6062
|
this.imageLoadingSrc = this.#store.selectSignal(unrealFeature.selectImageLoadingSrc);
|
|
6089
6063
|
}
|
|
6090
6064
|
#store;
|
|
6091
|
-
|
|
6065
|
+
loadingImageError() {
|
|
6092
6066
|
this.#store.dispatch(setLoadingImageSrc({ src: '' }));
|
|
6093
6067
|
}
|
|
6094
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.
|
|
6095
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.
|
|
6068
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: ImageLoadingSrcComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
6069
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.11", type: ImageLoadingSrcComponent, isStandalone: true, selector: "app-image-loading-src", ngImport: i0, template: "@let image = imageLoadingSrc();\n@if (isLoaderScreenVisible()) {\n <div class=\"preload\">\n <div class=\"back\">\n @if (image) {\n <img\n (error)=\"loadingImageError()\"\n [ngSrc]=\"image\"\n fill\n loading=\"lazy\"\n alt=\"image loading src\"\n />\n }\n </div>\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 .back{background-color:#fff}\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"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
6096
6070
|
}
|
|
6097
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.
|
|
6071
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: ImageLoadingSrcComponent, decorators: [{
|
|
6098
6072
|
type: Component,
|
|
6099
|
-
args: [{ selector: 'app-image-loading-src', changeDetection: ChangeDetectionStrategy.OnPush, imports: [NgOptimizedImage], template: "@let image = imageLoadingSrc();\n@if (isLoaderScreenVisible()) {\n <div class=\"preload\">\n <div class=\"back\">\n @if (image) {\n <img\n (error)=\"
|
|
6073
|
+
args: [{ selector: 'app-image-loading-src', changeDetection: ChangeDetectionStrategy.OnPush, imports: [NgOptimizedImage], template: "@let image = imageLoadingSrc();\n@if (isLoaderScreenVisible()) {\n <div class=\"preload\">\n <div class=\"back\">\n @if (image) {\n <img\n (error)=\"loadingImageError()\"\n [ngSrc]=\"image\"\n fill\n loading=\"lazy\"\n alt=\"image loading src\"\n />\n }\n </div>\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 .back{background-color:#fff}\n"] }]
|
|
6100
6074
|
}] });
|
|
6101
6075
|
|
|
6102
6076
|
class StatGraphComponent {
|
|
@@ -6170,10 +6144,10 @@ class StatGraphComponent {
|
|
|
6170
6144
|
}
|
|
6171
6145
|
this.draw();
|
|
6172
6146
|
}
|
|
6173
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.
|
|
6174
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "21.2.
|
|
6147
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: StatGraphComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
6148
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "21.2.11", 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 }); }
|
|
6175
6149
|
}
|
|
6176
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.
|
|
6150
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: StatGraphComponent, decorators: [{
|
|
6177
6151
|
type: Component,
|
|
6178
6152
|
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"] }]
|
|
6179
6153
|
}], 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: [{
|
|
@@ -6183,83 +6157,22 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.10", ngImpo
|
|
|
6183
6157
|
|
|
6184
6158
|
class UnrealStatusComponent {
|
|
6185
6159
|
constructor() {
|
|
6186
|
-
this
|
|
6187
|
-
this
|
|
6188
|
-
this.
|
|
6189
|
-
this.
|
|
6190
|
-
|
|
6191
|
-
|
|
6192
|
-
this.
|
|
6193
|
-
/**
|
|
6194
|
-
* An observable that emits smoothed percentage values from 0 to 100.
|
|
6195
|
-
*/
|
|
6196
|
-
this.messagePercents = toSignal(this.store.select(selectTotalProgress).pipe(keepMaxUntilReset(this.resetPercentageSignal$), floatToSmoothPercents(), distinctUntilChanged(), map$1((progress) => progress || 0)));
|
|
6197
|
-
this.awsInstance = this.store.selectSignal(unrealFeature.selectAwsInstance);
|
|
6198
|
-
}
|
|
6199
|
-
ngOnInit() {
|
|
6200
|
-
/**
|
|
6201
|
-
* A subject that emits null values to trigger nullification.
|
|
6202
|
-
*/
|
|
6203
|
-
const nullify$ = new Subject();
|
|
6204
|
-
/**
|
|
6205
|
-
* An observable that emits null values with a delay of 2000 milliseconds.
|
|
6206
|
-
*/
|
|
6207
|
-
const nullifyObs$ = nullify$
|
|
6208
|
-
.asObservable()
|
|
6209
|
-
.pipe(delay(2000));
|
|
6210
|
-
/**
|
|
6211
|
-
* An observable that emits the status message from the Unreal feature store.
|
|
6212
|
-
*/
|
|
6213
|
-
const signalingStatus$ = this.store.select(unrealFeature.selectStatusMessage);
|
|
6214
|
-
/**
|
|
6215
|
-
* An observable that emits connection status messages based on the Cirrus connection state.
|
|
6216
|
-
* Then call side effect to nullify the message.
|
|
6217
|
-
*/
|
|
6218
|
-
const cirrusConnected$ = this.store
|
|
6219
|
-
.select(unrealFeature.selectCirrusConnected)
|
|
6220
|
-
.pipe(skip(1), switchMap((connected) => connected
|
|
6221
|
-
? of('Creating Socket...')
|
|
6222
|
-
: of('Connection closed.').pipe(tap(() => nullify$.next(null)))));
|
|
6223
|
-
/**
|
|
6224
|
-
* An observable that emits the viewport visibility state.
|
|
6225
|
-
*/
|
|
6226
|
-
const viewportTrigger$ = this.store.select(unrealFeature.selectViewportReady);
|
|
6227
|
-
/**
|
|
6228
|
-
* An observable that will nullify any message displayed after 500 mSec, when viewport changes its state.
|
|
6229
|
-
*/
|
|
6230
|
-
const streamToggle$ = merge(viewportTrigger$.pipe(filter(Falsy), skip(1)), viewportTrigger$.pipe(filter(Truthy))).pipe(delay(500), map$1(() => null));
|
|
6231
|
-
/**
|
|
6232
|
-
* A subscription that merges various status observables and emits debounced status via postMessage.
|
|
6233
|
-
*/
|
|
6234
|
-
merge(nullifyObs$, cirrusConnected$, signalingStatus$, streamToggle$)
|
|
6235
|
-
.pipe(tapLog('STATUS=>'), debounceTime$1(0), takeUntilDestroyed(this.destroyRef))
|
|
6236
|
-
.subscribe((status) => this.sendMessageToIndex(status));
|
|
6237
|
-
}
|
|
6238
|
-
/**
|
|
6239
|
-
* Sends a message to the embedded iframe identified by the default value '3dsource_start_screen' ID.
|
|
6240
|
-
* This function tries to post a message to the iframe's content window. If the content
|
|
6241
|
-
* window is not accessible (e.g., due to cross-origin policies), the function fails silently.
|
|
6242
|
-
*
|
|
6243
|
-
* @param {string} text The message to be sent to the iframe. This could be a status update
|
|
6244
|
-
* or any other relevant information that the iframe needs to process.
|
|
6245
|
-
*/
|
|
6246
|
-
sendMessageToIndex(text) {
|
|
6247
|
-
const objectElement = document.getElementById(this.unrealInitialConfig?.screenLockerContainerId ||
|
|
6248
|
-
SCREEN_LOCKER_CONTAINER_ID);
|
|
6249
|
-
try {
|
|
6250
|
-
const objectDocument = objectElement.contentWindow;
|
|
6251
|
-
objectDocument?.postMessage(text, '*');
|
|
6252
|
-
}
|
|
6253
|
-
catch {
|
|
6254
|
-
// Fails silently if the iframe's content window cannot be accessed
|
|
6255
|
-
}
|
|
6160
|
+
this.#store = inject(Store);
|
|
6161
|
+
this.#loadingProgress = inject(LoadingProgressService);
|
|
6162
|
+
this.awsInstance = this.#store.selectSignal(unrealFeature.selectAwsInstance);
|
|
6163
|
+
this.messagePercents = this.#loadingProgress.percents;
|
|
6164
|
+
this.showLoader = this.#loadingProgress.loaderVisible;
|
|
6165
|
+
this.showLoadingProgress = this.#store.selectSignal(unrealFeature.selectShowLoadingProgress);
|
|
6166
|
+
this.isShowLoadingPercentsPopup = computed(() => this.showLoader() && this.showLoadingProgress(), ...(ngDevMode ? [{ debugName: "isShowLoadingPercentsPopup" }] : /* istanbul ignore next */ []));
|
|
6256
6167
|
}
|
|
6257
|
-
|
|
6258
|
-
|
|
6168
|
+
#store;
|
|
6169
|
+
#loadingProgress;
|
|
6170
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: UnrealStatusComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
6171
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.11", type: UnrealStatusComponent, isStandalone: true, selector: "app-unreal-status", ngImport: i0, template: "@if (isShowLoadingPercentsPopup()) {\n @let _awsInstance = awsInstance();\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 }); }
|
|
6259
6172
|
}
|
|
6260
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.
|
|
6173
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: UnrealStatusComponent, decorators: [{
|
|
6261
6174
|
type: Component,
|
|
6262
|
-
args: [{ selector: 'app-unreal-status', changeDetection: ChangeDetectionStrategy.OnPush, imports: [SourceLoadingComponent], template: "@if (
|
|
6175
|
+
args: [{ selector: 'app-unreal-status', changeDetection: ChangeDetectionStrategy.OnPush, imports: [SourceLoadingComponent], template: "@if (isShowLoadingPercentsPopup()) {\n @let _awsInstance = awsInstance();\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"] }]
|
|
6263
6176
|
}] });
|
|
6264
6177
|
|
|
6265
6178
|
class VideoStatsComponent {
|
|
@@ -6270,43 +6183,19 @@ class VideoStatsComponent {
|
|
|
6270
6183
|
this.isDevMode = inject(DevModeService).isDevMode;
|
|
6271
6184
|
this.obs$ = this.videoService.videoStats$;
|
|
6272
6185
|
this.viewportReady = this.store.selectSignal(unrealFeature.selectViewportReady);
|
|
6273
|
-
this.
|
|
6274
|
-
this.fpsTick = toSignal(this.obs$.pipe(map$1((stat) => ({
|
|
6275
|
-
|
|
6276
|
-
}))));
|
|
6277
|
-
this.
|
|
6278
|
-
|
|
6279
|
-
}))));
|
|
6280
|
-
this.bitrateTick = toSignal(this.obs$.pipe(map$1((stat) => ({
|
|
6281
|
-
value: stat.aggregatedStats.bitrate,
|
|
6282
|
-
}))));
|
|
6283
|
-
this.videoQP = toSignal(this.obs$.pipe(map$1((stat) => ({
|
|
6284
|
-
value: stat.aggregatedStats.VideoEncoderQP,
|
|
6285
|
-
}))));
|
|
6286
|
-
this.bitrateAverageTick = toSignal(this.obs$.pipe(map$1((stat) => ({
|
|
6287
|
-
value: stat.aggregatedStats.avgBitrate,
|
|
6288
|
-
}))));
|
|
6186
|
+
this.ssData = this.store.selectSignal(selectSignalingParameters);
|
|
6187
|
+
this.fpsTick = toSignal(this.obs$.pipe(map$1((stat) => ({ value: stat.aggregatedStats.framesPerSecond || 0 }))));
|
|
6188
|
+
this.fpsAvgTick = toSignal(this.obs$.pipe(map$1((stat) => ({ value: stat.aggregatedStats.avgFrameRate }))));
|
|
6189
|
+
this.bitrateTick = toSignal(this.obs$.pipe(map$1((stat) => ({ value: stat.aggregatedStats.bitrate }))));
|
|
6190
|
+
this.videoQP = toSignal(this.obs$.pipe(map$1((stat) => ({ value: stat.aggregatedStats.VideoEncoderQP }))));
|
|
6191
|
+
this.bitrateAverageTick = toSignal(this.obs$.pipe(map$1((stat) => ({ value: stat.aggregatedStats.avgBitrate }))));
|
|
6289
6192
|
this.videoStatus = toSignal(this.obs$.pipe(map$1((event) => this.isDevMode &&
|
|
6290
6193
|
{
|
|
6291
6194
|
...event.aggregatedStats,
|
|
6292
6195
|
quality: event.quality,
|
|
6293
|
-
}), filter(Boolean), map$1((data) =>
|
|
6294
|
-
|
|
6295
|
-
|
|
6296
|
-
return {
|
|
6297
|
-
key,
|
|
6298
|
-
value: data[key],
|
|
6299
|
-
};
|
|
6300
|
-
})
|
|
6301
|
-
.filter((r) => !this.elementsToShow.includes(r.key));
|
|
6302
|
-
})));
|
|
6303
|
-
this.graphList = [];
|
|
6304
|
-
this.idKey = 'com.source3d.unreal.stat';
|
|
6305
|
-
this.elementsToShow = [];
|
|
6306
|
-
this.trigger$ = new BehaviorSubject(undefined);
|
|
6307
|
-
this.getFields();
|
|
6308
|
-
}
|
|
6309
|
-
ngOnInit() {
|
|
6196
|
+
}), filter(Boolean), map$1((data) => this.fields
|
|
6197
|
+
.map((key) => ({ key, value: data[key] }))
|
|
6198
|
+
.filter((r) => !this.elementsToShow().includes(r.key)))));
|
|
6310
6199
|
this.fields = [
|
|
6311
6200
|
'kalmanBitrate',
|
|
6312
6201
|
'bitrateDrop',
|
|
@@ -6330,26 +6219,21 @@ class VideoStatsComponent {
|
|
|
6330
6219
|
'type',
|
|
6331
6220
|
'codecs',
|
|
6332
6221
|
'selectedPair',
|
|
6333
|
-
//'pliCount',
|
|
6334
|
-
//'sliCount',
|
|
6335
|
-
//'transportId',
|
|
6336
|
-
//'id',
|
|
6337
6222
|
];
|
|
6338
|
-
this.
|
|
6339
|
-
|
|
6340
|
-
|
|
6341
|
-
|
|
6342
|
-
|
|
6343
|
-
|
|
6344
|
-
|
|
6345
|
-
|
|
6346
|
-
|
|
6347
|
-
key,
|
|
6348
|
-
|
|
6349
|
-
|
|
6350
|
-
|
|
6351
|
-
|
|
6352
|
-
this.graphList$ = of(this.graphList).pipe(combineLatestWith(this.trigger$), map$1(([graphList]) => graphList.filter((r) => this.elementsToShow.includes(r.key))));
|
|
6223
|
+
this.elementsToShow = signal([], ...(ngDevMode ? [{ debugName: "elementsToShow" }] : /* istanbul ignore next */ []));
|
|
6224
|
+
this.idKey = 'com.source3d.unreal.stat';
|
|
6225
|
+
this.graphListItems = this.fields.map((key) => ({
|
|
6226
|
+
key,
|
|
6227
|
+
color: '#' +
|
|
6228
|
+
Math.floor(Math.random() * 16777216)
|
|
6229
|
+
.toString(16)
|
|
6230
|
+
.padStart(6, '0'),
|
|
6231
|
+
stat: this.obs$.pipe(map$1((val) => ({
|
|
6232
|
+
value: val.aggregatedStats[key],
|
|
6233
|
+
}))),
|
|
6234
|
+
}));
|
|
6235
|
+
this.graphList = computed(() => this.graphListItems.filter((r) => this.elementsToShow().includes(r.key)), ...(ngDevMode ? [{ debugName: "graphList" }] : /* istanbul ignore next */ []));
|
|
6236
|
+
this.restoreFromStorage();
|
|
6353
6237
|
}
|
|
6354
6238
|
toggle() {
|
|
6355
6239
|
this.collapsed.update((collapsed) => !collapsed);
|
|
@@ -6361,91 +6245,78 @@ class VideoStatsComponent {
|
|
|
6361
6245
|
(typeof value === 'number' && isNaN(value))) {
|
|
6362
6246
|
return;
|
|
6363
6247
|
}
|
|
6364
|
-
|
|
6365
|
-
|
|
6366
|
-
|
|
6367
|
-
else {
|
|
6368
|
-
this.elementsToShow.push(el);
|
|
6369
|
-
}
|
|
6248
|
+
this.elementsToShow.update((current) => current.includes(el)
|
|
6249
|
+
? current.filter((item) => item !== el)
|
|
6250
|
+
: [...current, el]);
|
|
6370
6251
|
this.writeFields();
|
|
6371
|
-
this.trigger$.next();
|
|
6372
6252
|
}
|
|
6373
|
-
|
|
6253
|
+
restoreFromStorage() {
|
|
6374
6254
|
try {
|
|
6375
|
-
const { elements, collapsed } = JSON.parse(localStorage.getItem(this.idKey)) ||
|
|
6376
|
-
this.elementsToShow
|
|
6377
|
-
this.collapsed.set(collapsed);
|
|
6255
|
+
const { elements, collapsed } = JSON.parse(localStorage.getItem(this.idKey)) || {};
|
|
6256
|
+
this.elementsToShow.set(elements || []);
|
|
6257
|
+
this.collapsed.set(collapsed ?? false);
|
|
6378
6258
|
}
|
|
6379
6259
|
catch {
|
|
6380
|
-
this.elementsToShow
|
|
6260
|
+
this.elementsToShow.set([]);
|
|
6381
6261
|
}
|
|
6382
6262
|
}
|
|
6383
6263
|
writeFields() {
|
|
6384
6264
|
localStorage.setItem(this.idKey, JSON.stringify({
|
|
6385
6265
|
collapsed: this.collapsed(),
|
|
6386
|
-
elements: this.elementsToShow,
|
|
6266
|
+
elements: this.elementsToShow(),
|
|
6387
6267
|
}));
|
|
6388
6268
|
}
|
|
6389
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.
|
|
6390
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.
|
|
6269
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: VideoStatsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
6270
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.11", 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\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(); 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 | 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 class=\"ssInfo\">\n @for (line of ssData(); track line) {\n <div>{{ line }}</div>\n }\n </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" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
6391
6271
|
}
|
|
6392
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.
|
|
6272
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: VideoStatsComponent, decorators: [{
|
|
6393
6273
|
type: Component,
|
|
6394
|
-
args: [{ selector: 'app-video-stats', changeDetection: ChangeDetectionStrategy.OnPush, imports: [StatGraphComponent, AsyncPipe, JsonPipe
|
|
6274
|
+
args: [{ selector: 'app-video-stats', changeDetection: ChangeDetectionStrategy.OnPush, imports: [StatGraphComponent, AsyncPipe, JsonPipe], 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\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(); 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 | 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 class=\"ssInfo\">\n @for (line of ssData(); track line) {\n <div>{{ line }}</div>\n }\n </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"] }]
|
|
6395
6275
|
}], ctorParameters: () => [] });
|
|
6396
6276
|
|
|
6397
6277
|
class ResumeStreamButtonComponent {
|
|
6278
|
+
#store;
|
|
6398
6279
|
constructor() {
|
|
6399
|
-
this.actions$ = inject(Actions);
|
|
6400
6280
|
this.#store = inject(Store);
|
|
6401
|
-
this.#videoService = inject(VideoService);
|
|
6402
|
-
this.#destroyRef = inject(DestroyRef);
|
|
6403
|
-
this.showReconnectPopup = this.#store.selectSignal(selectShowReconnectPopup);
|
|
6404
|
-
this.isLoaderScreenVisible = this.#store.selectSignal(selectIsLoaderScreenVisible);
|
|
6405
6281
|
this.streamConfig = this.#store.selectSignal(selectStreamConfig);
|
|
6406
|
-
this.isExistMatchUrls = this.#store.selectSignal(selectIsExistMatchUrls);
|
|
6407
6282
|
this.isSecondStart = signal(!!(this.streamConfig()?.autoStart && location.href.match(/^https/gi)), ...(ngDevMode ? [{ debugName: "isSecondStart" }] : /* istanbul ignore next */ []));
|
|
6283
|
+
this.isLoaderScreenVisible = this.#store.selectSignal(selectIsLoaderScreenVisible);
|
|
6284
|
+
this.showReconnectPopup = this.#store.selectSignal(selectShowReconnectPopup);
|
|
6285
|
+
this.isExistMatchUrls = this.#store.selectSignal(selectIsExistMatchUrls);
|
|
6286
|
+
this.showResumeStreamPopup = this.#store.selectSignal(unrealFeature.selectShowResumeStreamPopup);
|
|
6408
6287
|
this.isShowResumeButton = computed(() => this.isLoaderScreenVisible() &&
|
|
6409
6288
|
this.showReconnectPopup() &&
|
|
6410
|
-
this.isExistMatchUrls()
|
|
6411
|
-
|
|
6412
|
-
|
|
6413
|
-
|
|
6414
|
-
|
|
6415
|
-
|
|
6416
|
-
|
|
6417
|
-
|
|
6418
|
-
|
|
6419
|
-
|
|
6420
|
-
}
|
|
6421
|
-
ngAfterViewInit() {
|
|
6422
|
-
this.actions$
|
|
6423
|
-
.pipe(ofType(videoStreamInitialized), takeUntilDestroyed(this.#destroyRef), filter(() => !!this.#videoService.video?.paused))
|
|
6424
|
-
.subscribe(() => {
|
|
6425
|
-
Logger.info('Simulate Press Play');
|
|
6426
|
-
this.#videoService.play();
|
|
6427
|
-
this.#store.dispatch(resetAfk());
|
|
6289
|
+
this.isExistMatchUrls() &&
|
|
6290
|
+
this.showResumeStreamPopup(), ...(ngDevMode ? [{ debugName: "isShowResumeButton" }] : /* istanbul ignore next */ []));
|
|
6291
|
+
this.cirrusConnected = this.#store.selectSignal(unrealFeature.selectCirrusConnected);
|
|
6292
|
+
let wasConnected = this.cirrusConnected();
|
|
6293
|
+
effect(() => {
|
|
6294
|
+
const connected = this.cirrusConnected();
|
|
6295
|
+
if (!connected && wasConnected) {
|
|
6296
|
+
this.disconnect();
|
|
6297
|
+
}
|
|
6298
|
+
wasConnected = connected;
|
|
6428
6299
|
});
|
|
6429
6300
|
}
|
|
6430
6301
|
connect() {
|
|
6431
6302
|
this.#store.dispatch(startStream({ config: { autoStart: true } }));
|
|
6432
6303
|
}
|
|
6433
|
-
|
|
6304
|
+
disconnect() {
|
|
6434
6305
|
this.isSecondStart.set(true);
|
|
6435
6306
|
}
|
|
6436
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.
|
|
6437
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.
|
|
6307
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: ResumeStreamButtonComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
6308
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.11", 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", "srcButtonConfig", "formID", "data-testid", "ariaLabel"], outputs: ["onClick", "onSubmit"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
6438
6309
|
}
|
|
6439
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.
|
|
6310
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: ResumeStreamButtonComponent, decorators: [{
|
|
6440
6311
|
type: Component,
|
|
6441
6312
|
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"] }]
|
|
6442
|
-
}] });
|
|
6313
|
+
}], ctorParameters: () => [] });
|
|
6443
6314
|
|
|
6444
6315
|
class IntroSrcComponent {
|
|
6445
6316
|
#store;
|
|
6446
6317
|
constructor() {
|
|
6447
|
-
this.videoElement = viewChild('videoPlayerCover', ...(ngDevMode ? [{ debugName: "videoElement" }] : /* istanbul ignore next */ []));
|
|
6448
6318
|
this.#store = inject(Store);
|
|
6319
|
+
this.videoElement = viewChild('videoPlayerCover', ...(ngDevMode ? [{ debugName: "videoElement" }] : /* istanbul ignore next */ []));
|
|
6449
6320
|
this.imageIntroSrc = this.#store.selectSignal(unrealFeature.selectImageIntroSrc);
|
|
6450
6321
|
this.videoIntroSrc = this.#store.selectSignal(unrealFeature.selectVideoIntroSrc);
|
|
6451
6322
|
this.viewportReady = this.#store.selectSignal(unrealFeature.selectViewportReady);
|
|
@@ -6469,6 +6340,9 @@ class IntroSrcComponent {
|
|
|
6469
6340
|
});
|
|
6470
6341
|
});
|
|
6471
6342
|
}
|
|
6343
|
+
loadingImageError() {
|
|
6344
|
+
this.#store.dispatch(resetIntroSrc());
|
|
6345
|
+
}
|
|
6472
6346
|
createVideo(src, videoContainer) {
|
|
6473
6347
|
if (typeof src !== 'string') {
|
|
6474
6348
|
return;
|
|
@@ -6499,15 +6373,12 @@ class IntroSrcComponent {
|
|
|
6499
6373
|
sourceElement.addEventListener('error', () => this.#store.dispatch(resetIntroSrc()));
|
|
6500
6374
|
videoContainer.appendChild(videoElement);
|
|
6501
6375
|
}
|
|
6502
|
-
|
|
6503
|
-
|
|
6504
|
-
}
|
|
6505
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.10", ngImport: i0, type: IntroSrcComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
6506
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.10", type: IntroSrcComponent, isStandalone: true, selector: "app-intro-src", viewQueries: [{ propertyName: "videoElement", first: true, predicate: ["videoPlayerCover"], descendants: true, isSignal: true }], ngImport: i0, template: "@let image = imageIntroSrc();\n@if (image) {\n <div class=\"backImage\">\n <img (error)=\"imageError()\" [ngSrc]=\"image\" fill alt=\"imageSrc\" />\n </div>\n} @else if (videoIntroSrc()) {\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%;z-index:1}.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%;z-index:1}.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"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
6376
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: IntroSrcComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
6377
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.11", type: IntroSrcComponent, isStandalone: true, selector: "app-intro-src", viewQueries: [{ propertyName: "videoElement", first: true, predicate: ["videoPlayerCover"], descendants: true, isSignal: true }], ngImport: i0, template: "@let image = imageIntroSrc();\n@if (image) {\n <div class=\"backImage\">\n <img (error)=\"loadingImageError()\" [ngSrc]=\"image\" fill alt=\"imageSrc\" />\n </div>\n} @else if (videoIntroSrc()) {\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%;z-index:1}.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%;z-index:1}.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"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
6507
6378
|
}
|
|
6508
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.
|
|
6379
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: IntroSrcComponent, decorators: [{
|
|
6509
6380
|
type: Component,
|
|
6510
|
-
args: [{ selector: 'app-intro-src', imports: [NgOptimizedImage], changeDetection: ChangeDetectionStrategy.OnPush, template: "@let image = imageIntroSrc();\n@if (image) {\n <div class=\"backImage\">\n <img (error)=\"
|
|
6381
|
+
args: [{ selector: 'app-intro-src', imports: [NgOptimizedImage], changeDetection: ChangeDetectionStrategy.OnPush, template: "@let image = imageIntroSrc();\n@if (image) {\n <div class=\"backImage\">\n <img (error)=\"loadingImageError()\" [ngSrc]=\"image\" fill alt=\"imageSrc\" />\n </div>\n} @else if (videoIntroSrc()) {\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%;z-index:1}.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%;z-index:1}.backImage img{position:absolute;width:100%;height:100%;object-fit:cover}\n"] }]
|
|
6511
6382
|
}], ctorParameters: () => [], propDecorators: { videoElement: [{ type: i0.ViewChild, args: ['videoPlayerCover', { isSignal: true }] }] } });
|
|
6512
6383
|
|
|
6513
6384
|
class UnrealSceneComponent {
|
|
@@ -6527,62 +6398,57 @@ class UnrealSceneComponent {
|
|
|
6527
6398
|
onMouseOut() {
|
|
6528
6399
|
this.changeMouseOverScene.emit(false);
|
|
6529
6400
|
}
|
|
6401
|
+
onContextMenu(event) {
|
|
6402
|
+
event.preventDefault();
|
|
6403
|
+
}
|
|
6530
6404
|
constructor() {
|
|
6531
|
-
this.isStudio = input(false, ...(ngDevMode ? [{ debugName: "isStudio" }] : /* istanbul ignore next */ []));
|
|
6532
6405
|
this.useContainerAsSizeProvider = input(true, ...(ngDevMode ? [{ debugName: "useContainerAsSizeProvider" }] : /* istanbul ignore next */ []));
|
|
6533
|
-
this.
|
|
6406
|
+
this.isStudio = input(false, ...(ngDevMode ? [{ debugName: "isStudio" }] : /* istanbul ignore next */ []));
|
|
6407
|
+
this.resolutionSize = input({
|
|
6534
6408
|
width: FULL_HD_WIDTH,
|
|
6535
6409
|
height: FULL_HD_HEIGHT,
|
|
6536
|
-
}, ...(ngDevMode ? [{ debugName: "
|
|
6537
|
-
this.studioResolutionValues = toObservable(computed(() => {
|
|
6538
|
-
const values = this.studioResolutionSize();
|
|
6539
|
-
return { width: values.width, height: values.height };
|
|
6540
|
-
}));
|
|
6541
|
-
this.videoElement = viewChild('videoContainer', ...(ngDevMode ? [{ debugName: "videoElement" }] : /* istanbul ignore next */ []));
|
|
6410
|
+
}, ...(ngDevMode ? [{ debugName: "resolutionSize" }] : /* istanbul ignore next */ []));
|
|
6542
6411
|
this.changeMouseOverScene = output();
|
|
6412
|
+
this.videoElement = viewChild('videoContainer', ...(ngDevMode ? [{ debugName: "videoElement" }] : /* istanbul ignore next */ []));
|
|
6413
|
+
this.resolutionValues$ = toObservable(this.resolutionSize);
|
|
6543
6414
|
this.width = FULL_HD_WIDTH;
|
|
6544
6415
|
this.height = FULL_HD_HEIGHT;
|
|
6545
6416
|
this.actions$ = inject(Actions);
|
|
6546
6417
|
this.#store = inject(Store);
|
|
6547
6418
|
this.isExistMatchUrls = this.#store.selectSignal(selectIsExistMatchUrls);
|
|
6548
6419
|
this.isDevMode = inject(DevModeService).isDevMode;
|
|
6549
|
-
this.lightMode = this.#store.selectSignal(unrealFeature.selectLowBandwidth);
|
|
6550
6420
|
this.isFreezeFrameLoading = this.#store.selectSignal(selectIsFreezeFrameLoading);
|
|
6551
6421
|
this.maxResolution = Truthy(new URLSearchParams(location.search).get('maxresolution'));
|
|
6552
6422
|
this.commandsSender = inject(UnrealCommunicatorService);
|
|
6553
6423
|
this.videoService = inject(VideoService);
|
|
6554
|
-
this.element = inject(ElementRef);
|
|
6555
6424
|
this.destroyRef = inject(DestroyRef);
|
|
6556
6425
|
this.destroyRef.onDestroy(() => this.#store.dispatch(destroyUnrealScene()));
|
|
6557
6426
|
effect(() => {
|
|
6558
6427
|
const videoElement = this.videoElement();
|
|
6559
6428
|
const isExistMatchUrls = this.isExistMatchUrls();
|
|
6560
|
-
|
|
6561
|
-
|
|
6562
|
-
|
|
6429
|
+
untracked(() => {
|
|
6430
|
+
if (videoElement && isExistMatchUrls) {
|
|
6431
|
+
this.#store.dispatch(initSignalling());
|
|
6432
|
+
}
|
|
6433
|
+
});
|
|
6563
6434
|
});
|
|
6564
6435
|
afterNextRender({
|
|
6565
6436
|
read: () => {
|
|
6566
6437
|
const videoElement = this.videoElement();
|
|
6567
6438
|
if (videoElement) {
|
|
6568
6439
|
this.videoService.setContainer(videoElement.nativeElement);
|
|
6569
|
-
if (this.element?.nativeElement) {
|
|
6570
|
-
fromEvent(this.element?.nativeElement, 'contextmenu')
|
|
6571
|
-
.pipe(takeUntilDestroyed(this.destroyRef))
|
|
6572
|
-
.subscribe((event) => event.preventDefault());
|
|
6573
|
-
}
|
|
6574
6440
|
this.listenResizeValues();
|
|
6575
6441
|
}
|
|
6576
6442
|
},
|
|
6577
6443
|
});
|
|
6578
6444
|
}
|
|
6579
6445
|
listenResizeValues() {
|
|
6580
|
-
const customSizeInputChanged$ = this.
|
|
6446
|
+
const customSizeInputChanged$ = this.resolutionValues$.pipe(filter(({ width, height }) => this.width !== width || this.height !== height), tap(({ width, height }) => {
|
|
6581
6447
|
this.width = width;
|
|
6582
6448
|
this.height = height;
|
|
6583
6449
|
}));
|
|
6584
6450
|
const resizeRequired$ = merge(this.actions$.pipe(ofType(videoStreamInitialized)), fromEvent(window, 'resize'));
|
|
6585
|
-
const videoStreamSizeChanged$ = this.videoService
|
|
6451
|
+
const videoStreamSizeChanged$ = this.videoService.videoStats$.pipe(filter(() => !this.isFreezeFrameLoading()), map$1((stats) => ({
|
|
6586
6452
|
w: stats.aggregatedStats.frameWidth || 0,
|
|
6587
6453
|
h: stats.aggregatedStats.frameHeight || 0,
|
|
6588
6454
|
})), distinctUntilChanged((previous, current) => fpIsASameAsB(previous.w, current.w, SAME_SIZE_THRESHOLD) &&
|
|
@@ -6590,12 +6456,17 @@ class UnrealSceneComponent {
|
|
|
6590
6456
|
merge(customSizeInputChanged$, resizeRequired$, videoStreamSizeChanged$)
|
|
6591
6457
|
.pipe(debounceTime(DEBOUNCE_TO_MANY_RESIZE_CALLS), switchMap(() => {
|
|
6592
6458
|
const key = Math.random();
|
|
6593
|
-
//
|
|
6459
|
+
// Poll 3 times to capture late-arriving DOM measurements after layout settles
|
|
6594
6460
|
return timer(0, 300).pipe(take(3), map$1(() => key));
|
|
6595
6461
|
}), map$1((key) => ({ key, ...this.resizeValues })), distinctUntilChanged((previous, current) => fpIsASameAsB(previous.w, current.w, SAME_SIZE_THRESHOLD) &&
|
|
6596
6462
|
fpIsASameAsB(previous.h, current.h, SAME_SIZE_THRESHOLD) &&
|
|
6597
|
-
previous.key === current.key), tap((size) => this.adaptVideo(size)),
|
|
6598
|
-
|
|
6463
|
+
previous.key === current.key), tap((size) => this.adaptVideo(size)),
|
|
6464
|
+
// Key excluded: only dispatch when actual pixel dimensions change
|
|
6465
|
+
distinctUntilChanged((previous, current) => fpIsASameAsB(previous.w, current.w, SAME_SIZE_THRESHOLD) &&
|
|
6466
|
+
fpIsASameAsB(previous.h, current.h, SAME_SIZE_THRESHOLD)),
|
|
6467
|
+
// Holds dispatch until data channel is up; retains true after disconnect
|
|
6468
|
+
// so resizes still reach Unreal — cleanup is handled by destroyUnrealScene
|
|
6469
|
+
combineLatestWith(this.#store
|
|
6599
6470
|
.select(unrealFeature.selectDataChannelConnected)
|
|
6600
6471
|
.pipe(filter(Truthy))), takeUntilDestroyed(this.destroyRef))
|
|
6601
6472
|
.subscribe(([size]) => {
|
|
@@ -6623,11 +6494,13 @@ class UnrealSceneComponent {
|
|
|
6623
6494
|
this.#store.dispatch(videoAdaptedToContainer());
|
|
6624
6495
|
}
|
|
6625
6496
|
getResizeValuesUniversal() {
|
|
6626
|
-
let containerWidth = window.innerWidth ||
|
|
6627
|
-
let containerHeight = window.innerHeight ||
|
|
6497
|
+
let containerWidth = window.innerWidth || MIN_CONTAINER_SIZE;
|
|
6498
|
+
let containerHeight = window.innerHeight || MIN_CONTAINER_SIZE;
|
|
6628
6499
|
if (this.useContainerAsSizeProvider()) {
|
|
6629
|
-
containerWidth =
|
|
6630
|
-
|
|
6500
|
+
containerWidth =
|
|
6501
|
+
this.videoElement()?.nativeElement.offsetWidth || MIN_CONTAINER_SIZE;
|
|
6502
|
+
containerHeight =
|
|
6503
|
+
this.videoElement()?.nativeElement.offsetHeight || MIN_CONTAINER_SIZE;
|
|
6631
6504
|
}
|
|
6632
6505
|
const pixelRatio = this.pixelRatio;
|
|
6633
6506
|
return getResizeValuesUniversal({
|
|
@@ -6641,8 +6514,8 @@ class UnrealSceneComponent {
|
|
|
6641
6514
|
const videoElement = this.videoElement()?.nativeElement;
|
|
6642
6515
|
return getResizeStudioValues({
|
|
6643
6516
|
pixelRatio: this.pixelRatio,
|
|
6644
|
-
containerWidth: videoElement?.offsetWidth ||
|
|
6645
|
-
containerHeight: videoElement?.offsetHeight ||
|
|
6517
|
+
containerWidth: videoElement?.offsetWidth || MIN_CONTAINER_SIZE,
|
|
6518
|
+
containerHeight: videoElement?.offsetHeight || MIN_CONTAINER_SIZE,
|
|
6646
6519
|
studioWidth: this.width,
|
|
6647
6520
|
studioHeight: this.height,
|
|
6648
6521
|
maxResolution: this.maxResolution,
|
|
@@ -6659,10 +6532,10 @@ class UnrealSceneComponent {
|
|
|
6659
6532
|
},
|
|
6660
6533
|
});
|
|
6661
6534
|
}
|
|
6662
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.
|
|
6663
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.10", 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: "videoElement", first: true, predicate: ["videoContainer"], descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"frame unreal-container\">\n <div #videoContainer [class.lightModeCursor]=\"lightMode()\" id=\"player\"></div>\n\n <app-intro-src />\n <app-image-loading-src />\n <app-resume-stream-button />\n <app-unreal-status />\n <app-freeze-frame />\n <app-afk-timeout-modal />\n\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\n @if (isDevMode) {\n <app-video-stats />\n }\n</div>\n", styles: [".unreal-container{position:absolute;top:0;left:0;width:100%;height:100%;background-color:#fff}.unreal-container #player{position:absolute;width:100%;height:100%;display:flex;justify-content:center;align-items:center;overflow:hidden}.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>%0A') 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: AfkTimeoutModalComponent, selector: "app-afk-timeout-modal" }, { kind: "component", type: UnrealStatusComponent, selector: "app-unreal-status" }, { kind: "component", type: FreezeFrameComponent, selector: "app-freeze-frame" }, { kind: "component", type: VideoStatsComponent, selector: "app-video-stats" }, { kind: "component", type: ResumeStreamButtonComponent, selector: "app-resume-stream-button" }, { kind: "component", type: ImageLoadingSrcComponent, selector: "app-image-loading-src" }, { kind: "component", type: IntroSrcComponent, selector: "app-intro-src" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
6535
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: UnrealSceneComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
6536
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.11", type: UnrealSceneComponent, isStandalone: true, selector: "app-unreal-scene", inputs: { useContainerAsSizeProvider: { classPropertyName: "useContainerAsSizeProvider", publicName: "useContainerAsSizeProvider", isSignal: true, isRequired: false, transformFunction: null }, isStudio: { classPropertyName: "isStudio", publicName: "isStudio", isSignal: true, isRequired: false, transformFunction: null }, resolutionSize: { classPropertyName: "resolutionSize", publicName: "resolutionSize", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { changeMouseOverScene: "changeMouseOverScene" }, host: { listeners: { "mouseover": "onMouseOver()", "mouseout": "onMouseOut()", "contextmenu": "onContextMenu($event)" } }, viewQueries: [{ propertyName: "videoElement", first: true, predicate: ["videoContainer"], descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"frame unreal-container\">\n <div #videoContainer id=\"player\"></div>\n\n <app-intro-src />\n <app-image-loading-src />\n <app-resume-stream-button />\n <app-unreal-status />\n <app-freeze-frame />\n <app-afk-timeout-modal />\n\n <ng-content select=\"app-pdf\"></ng-content>\n <ng-content select=\"app-show-case\"></ng-content>\n\n @if (isDevMode) {\n <app-video-stats />\n }\n</div>\n", styles: [".unreal-container{position:absolute;top:0;left:0;width:100%;height:100%;background-color:#fff}.unreal-container #player{position:absolute;width:100%;height:100%;display:flex;justify-content:center;align-items:center;overflow:hidden}.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>%0A') 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: AfkTimeoutModalComponent, selector: "app-afk-timeout-modal" }, { kind: "component", type: UnrealStatusComponent, selector: "app-unreal-status" }, { kind: "component", type: FreezeFrameComponent, selector: "app-freeze-frame" }, { kind: "component", type: VideoStatsComponent, selector: "app-video-stats" }, { kind: "component", type: ResumeStreamButtonComponent, selector: "app-resume-stream-button" }, { kind: "component", type: ImageLoadingSrcComponent, selector: "app-image-loading-src" }, { kind: "component", type: IntroSrcComponent, selector: "app-intro-src" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
6664
6537
|
}
|
|
6665
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.
|
|
6538
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: UnrealSceneComponent, decorators: [{
|
|
6666
6539
|
type: Component,
|
|
6667
6540
|
args: [{ selector: 'app-unreal-scene', changeDetection: ChangeDetectionStrategy.OnPush, imports: [
|
|
6668
6541
|
AfkTimeoutModalComponent,
|
|
@@ -6672,13 +6545,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.10", ngImpo
|
|
|
6672
6545
|
ResumeStreamButtonComponent,
|
|
6673
6546
|
ImageLoadingSrcComponent,
|
|
6674
6547
|
IntroSrcComponent,
|
|
6675
|
-
], template: "<div class=\"frame unreal-container\">\n <div #videoContainer [class.lightModeCursor]=\"lightMode()\" id=\"player\"></div>\n\n <app-intro-src />\n <app-image-loading-src />\n <app-resume-stream-button />\n <app-unreal-status />\n <app-freeze-frame />\n <app-afk-timeout-modal />\n\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\n @if (isDevMode) {\n <app-video-stats />\n }\n</div>\n", styles: [".unreal-container{position:absolute;top:0;left:0;width:100%;height:100%;background-color:#fff}.unreal-container #player{position:absolute;width:100%;height:100%;display:flex;justify-content:center;align-items:center;overflow:hidden}.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>%0A') 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"] }]
|
|
6676
|
-
}], ctorParameters: () => [], propDecorators: {
|
|
6548
|
+
], template: "<div class=\"frame unreal-container\">\n <div #videoContainer id=\"player\"></div>\n\n <app-intro-src />\n <app-image-loading-src />\n <app-resume-stream-button />\n <app-unreal-status />\n <app-freeze-frame />\n <app-afk-timeout-modal />\n\n <ng-content select=\"app-pdf\"></ng-content>\n <ng-content select=\"app-show-case\"></ng-content>\n\n @if (isDevMode) {\n <app-video-stats />\n }\n</div>\n", styles: [".unreal-container{position:absolute;top:0;left:0;width:100%;height:100%;background-color:#fff}.unreal-container #player{position:absolute;width:100%;height:100%;display:flex;justify-content:center;align-items:center;overflow:hidden}.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>%0A') 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"] }]
|
|
6549
|
+
}], ctorParameters: () => [], propDecorators: { useContainerAsSizeProvider: [{ type: i0.Input, args: [{ isSignal: true, alias: "useContainerAsSizeProvider", required: false }] }], isStudio: [{ type: i0.Input, args: [{ isSignal: true, alias: "isStudio", required: false }] }], resolutionSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "resolutionSize", required: false }] }], changeMouseOverScene: [{ type: i0.Output, args: ["changeMouseOverScene"] }], videoElement: [{ type: i0.ViewChild, args: ['videoContainer', { isSignal: true }] }], onMouseOver: [{
|
|
6677
6550
|
type: HostListener,
|
|
6678
6551
|
args: ['mouseover']
|
|
6679
6552
|
}], onMouseOut: [{
|
|
6680
6553
|
type: HostListener,
|
|
6681
6554
|
args: ['mouseout']
|
|
6555
|
+
}], onContextMenu: [{
|
|
6556
|
+
type: HostListener,
|
|
6557
|
+
args: ['contextmenu', ['$event']]
|
|
6682
6558
|
}] } });
|
|
6683
6559
|
|
|
6684
6560
|
class WebrtcErrorModalComponent {
|
|
@@ -6689,9 +6565,6 @@ class WebrtcErrorModalComponent {
|
|
|
6689
6565
|
}
|
|
6690
6566
|
#dialogRef;
|
|
6691
6567
|
#store;
|
|
6692
|
-
close() {
|
|
6693
|
-
this.#dialogRef.close();
|
|
6694
|
-
}
|
|
6695
6568
|
closeModalWithCirrusDisconnect() {
|
|
6696
6569
|
if (!this.isCirrusConnected()) {
|
|
6697
6570
|
this.#store.dispatch(disconnectStream({
|
|
@@ -6701,22 +6574,23 @@ class WebrtcErrorModalComponent {
|
|
|
6701
6574
|
}
|
|
6702
6575
|
this.close();
|
|
6703
6576
|
}
|
|
6704
|
-
|
|
6705
|
-
|
|
6577
|
+
close() {
|
|
6578
|
+
this.#dialogRef.close();
|
|
6579
|
+
}
|
|
6580
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: WebrtcErrorModalComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
6581
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.11", 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__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", "srcButtonConfig", "formID", "data-testid", "ariaLabel"], outputs: ["onClick", "onSubmit"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
6706
6582
|
}
|
|
6707
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.
|
|
6583
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: WebrtcErrorModalComponent, decorators: [{
|
|
6708
6584
|
type: Component,
|
|
6709
6585
|
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__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"] }]
|
|
6710
6586
|
}] });
|
|
6711
6587
|
|
|
6712
6588
|
class FilterSettingsComponent {
|
|
6713
6589
|
constructor() {
|
|
6714
|
-
this.#store = inject(Store);
|
|
6715
6590
|
this.storageKey = 'LBMFilterSettings';
|
|
6716
6591
|
this.defaultFilterModel = { ...DefaultFilterModel };
|
|
6717
6592
|
this.settings = { ...DefaultFilterModel };
|
|
6718
6593
|
}
|
|
6719
|
-
#store;
|
|
6720
6594
|
ngOnInit() {
|
|
6721
6595
|
const savedSettings = localStorage.getItem(this.storageKey);
|
|
6722
6596
|
if (savedSettings) {
|
|
@@ -6742,7 +6616,6 @@ class FilterSettingsComponent {
|
|
|
6742
6616
|
}
|
|
6743
6617
|
Object.assign(this.settings, settings);
|
|
6744
6618
|
Object.assign(FilterModel, settings);
|
|
6745
|
-
this.#store.dispatch(setKalmanSettings({ settings }));
|
|
6746
6619
|
}
|
|
6747
6620
|
reset() {
|
|
6748
6621
|
this.dispatch({
|
|
@@ -6750,23 +6623,23 @@ class FilterSettingsComponent {
|
|
|
6750
6623
|
panelOpen: this.settings.panelOpen,
|
|
6751
6624
|
});
|
|
6752
6625
|
}
|
|
6753
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.
|
|
6754
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.
|
|
6626
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: FilterSettingsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
6627
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.11", 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],[formArray],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]):not([formArray]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
6755
6628
|
}
|
|
6756
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.
|
|
6629
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: FilterSettingsComponent, decorators: [{
|
|
6757
6630
|
type: Component,
|
|
6758
6631
|
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"] }]
|
|
6759
6632
|
}] });
|
|
6760
6633
|
|
|
6761
6634
|
class LowBandwidthDetectorComponent {
|
|
6762
6635
|
constructor() {
|
|
6763
|
-
this
|
|
6636
|
+
this.#store = inject(Store);
|
|
6764
6637
|
this.dialog = inject(Dialog);
|
|
6765
6638
|
this.destroyRef = inject(DestroyRef);
|
|
6766
6639
|
this.videoService = inject(VideoService);
|
|
6767
6640
|
this.isDevMode = inject(DevModeService).isDevMode;
|
|
6768
|
-
this.viewportReady$ = this
|
|
6769
|
-
this.isLowBandwidth$ =
|
|
6641
|
+
this.viewportReady$ = this.#store.select(unrealFeature.selectViewportReady);
|
|
6642
|
+
this.isLowBandwidth$ = of(true);
|
|
6770
6643
|
this.lowBandwidthTrigger$ = this.isLowBandwidth$.pipe(distinctUntilChanged$1(), filter(Truthy));
|
|
6771
6644
|
this.highBandwidthTrigger$ = this.isLowBandwidth$.pipe(distinctUntilChanged$1(), filter(Falsy));
|
|
6772
6645
|
this.viewPortDestroyedTrigger$ = this.viewportReady$.pipe(distinctUntilChanged$1(), filter(Falsy));
|
|
@@ -6788,6 +6661,7 @@ class LowBandwidthDetectorComponent {
|
|
|
6788
6661
|
this.isIndicatorExpanded = signal(false, ...(ngDevMode ? [{ debugName: "isIndicatorExpanded" }] : /* istanbul ignore next */ []));
|
|
6789
6662
|
this.isIndicatorExpandedTrigger$ = toObservable(this.isIndicatorExpanded).pipe(skip(1), distinctUntilChanged$1(), filter(Falsy));
|
|
6790
6663
|
}
|
|
6664
|
+
#store;
|
|
6791
6665
|
ngOnInit() {
|
|
6792
6666
|
this.lowBandwidthTrigger$
|
|
6793
6667
|
.pipe(takeUntilDestroyed(this.destroyRef))
|
|
@@ -6827,15 +6701,13 @@ class LowBandwidthDetectorComponent {
|
|
|
6827
6701
|
else {
|
|
6828
6702
|
reason = `Speed < ${FilterModel.minimumBitrate}`;
|
|
6829
6703
|
}
|
|
6830
|
-
Logger.info(`LBM DETECTED: ${reason}, switching to low bandwidth; `, dataFlowResult.message
|
|
6831
|
-
this.store.dispatch(changeLowBandwidth({
|
|
6832
|
-
lowBandwidth: true,
|
|
6704
|
+
Logger.info(`LBM DETECTED: ${reason}, switching to low bandwidth; `, dataFlowResult.message, {
|
|
6833
6705
|
stats: {
|
|
6834
6706
|
dataFlowResult,
|
|
6835
6707
|
reason,
|
|
6836
6708
|
triggerTime: this.aggregatedStats()?.runTime ?? 0,
|
|
6837
6709
|
},
|
|
6838
|
-
})
|
|
6710
|
+
});
|
|
6839
6711
|
}
|
|
6840
6712
|
}
|
|
6841
6713
|
toggleIndicator(value) {
|
|
@@ -6855,13 +6727,12 @@ class LowBandwidthDetectorComponent {
|
|
|
6855
6727
|
.closed.pipe(filter(Truthy))
|
|
6856
6728
|
.subscribe(() => {
|
|
6857
6729
|
this.toggleIndicator(false);
|
|
6858
|
-
this.store.dispatch(changeLowBandwidth({ lowBandwidth: false }));
|
|
6859
6730
|
});
|
|
6860
6731
|
}
|
|
6861
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.
|
|
6862
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.
|
|
6732
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: LowBandwidthDetectorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
6733
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.11", 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 (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:10;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);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 }); }
|
|
6863
6734
|
}
|
|
6864
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.
|
|
6735
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: LowBandwidthDetectorComponent, decorators: [{
|
|
6865
6736
|
type: Component,
|
|
6866
6737
|
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 (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:10;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);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"] }]
|
|
6867
6738
|
}] });
|
|
@@ -6889,6 +6760,7 @@ function provideUnrealModule() {
|
|
|
6889
6760
|
StreamStatusTelemetryService2,
|
|
6890
6761
|
FpsMonitorService,
|
|
6891
6762
|
WebRtcPlayerService,
|
|
6763
|
+
LoadingProgressService,
|
|
6892
6764
|
provideEnvironmentInitializer(() => {
|
|
6893
6765
|
inject(AggregatorService);
|
|
6894
6766
|
inject(InputService);
|
|
@@ -6907,5 +6779,5 @@ function provideUnrealModule() {
|
|
|
6907
6779
|
* Generated bundle index. Do not edit.
|
|
6908
6780
|
*/
|
|
6909
6781
|
|
|
6910
|
-
export { AFKService, AfkTimeoutModalComponent, AggregatorService, AnalyticsService, AnswerHandler, CONSOLE_COMMAND_DISABLE_MESSAGES, CONSOLE_COMMAND_ENABLE_MESSAGES, CONSOLE_COMMAND_PIXEL_QUALITY, CommandTelemetryService, CommandsEffects, ConfigHandler, 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, FileReceiverService, FilterSettingsComponent, FpsMonitorService, FreezeFrameComponent, FreezeFrameService, IceCandidateHandler, ImageLoadingSrcComponent, InputOptions, 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, SignallingService, SpecialKeyCodes, StatGraphComponent, StreamStatusTelemetryService, StreamStatusTelemetryService2, SubService, ToClientMessage, UNREAL_CONFIG, UnrealCallbackService, UnrealCommunicatorService, UnrealEffects, 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, answerSent,
|
|
6782
|
+
export { AFKService, AfkTimeoutModalComponent, AggregatorService, AnalyticsService, AnswerHandler, CONSOLE_COMMAND_DISABLE_MESSAGES, CONSOLE_COMMAND_ENABLE_MESSAGES, CONSOLE_COMMAND_PIXEL_QUALITY, CommandTelemetryService, CommandsEffects, ConfigHandler, 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, DESTROY_DISCONNECT_REASONS, DataFlowMonitor, DevModeService, DisconnectReason, FULL_HD_HEIGHT, FULL_HD_WIDTH, FileHandlerService, FileReceiverService, FilterSettingsComponent, FpsMonitorService, FreezeFrameComponent, FreezeFrameService, IceCandidateHandler, ImageLoadingSrcComponent, InputOptions, InputService, InstanceReadyHandler, InstanceReservedHandler, IntroSrcComponent, KalmanFilter1D, LatencyTimings, LoadingProgressService, LowBandwidthDetectorComponent, LowBandwidthModalComponent, MINIMAL_FPS, MIN_CONTAINER_SIZE, 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_AUDIO_ID, STREAMING_VIDEO_ID, SafePipe, SignallingService, SpecialKeyCodes, StatGraphComponent, StreamStatusTelemetryService, StreamStatusTelemetryService2, SubService, ToClientMessage, UNREAL_CONFIG, UnrealCallbackService, UnrealCommunicatorService, UnrealEffects, 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, answerSent, changeStatusMainVideoOnScene, changeStreamResolutionAction, changeStreamResolutionSuccessAction, commandCompleted, commandStarted, commandsFeature, commandsReducer, dataChannelConnected, dataChannelReady, decodeData, destroyRemoteConnections, destroyUnrealScene, disconnectStream, dispatchResize, dropConnection, dropDC, dropPC, floatToSmoothPercents, forceResizeViewport, fromResizeObserver, getActiveUrl, getImageFromVideoStream, getResizeStudioValues, getResizeValuesUniversal, getRtcErrorMessage, iceConnectionFailed, initSignalling, instanceReady, keepMaxUntilReset, makeEven, pollingEnded, pollingStarted, provideUnrealModule, qpToQuality, reconnectPeer, reconnectPeerFailed, reconnectPeerSuccess, regionPingFetchEnd, regionPingFetchStart, regionResolved, resetAfk, resetConfig, resetDataChannelForReconnect, resetIntroSrc, resetUserInactivityTimeout, resetWarnTimeout, saveAnalyticsEvent, selectCirrusConnectionId, selectClientAndViewIds, selectCommandProgress, selectCommandsInProgress, selectFreezeFrameCombinedDataUrl, selectFreezeFrameDataUrl, selectFreezeFrameDataUrlFromVideo, selectFreezeFrameProgressMessageFromVideo, selectIsAutostart, selectIsExistMatchUrls, selectIsFreezeFrameLoading, selectIsFullyConnected, selectIsLoaderScreenVisible, selectIsVideoPlayingAndDataChannelConnected, selectShowLoader, selectShowReconnectPopup, selectSignalingParameters, selectStreamConfig, selectTotalProgress, selectWarnTimeout, setAfkTimerCountdown, setAfkTimerHide, setAfkTimerVisible, setAwsInstance, setCirrusConnected, setCirrusDisconnected, setConfig, setEstablishingConnection, setFreezeFrame, setFreezeFrameFromVideo, setIntroImageSrc, setIntroVideoSrc, setLoadingImageSrc, setLoopBackCommandIsCompleted, setMaxFps, setOrchestrationContext, setOrchestrationMessage, setOrchestrationParameters, setOrchestrationProgress, setSignalingName, setStatusMessage, setStatusPercentSignallingServer, setStreamClientCompanyId, setStreamViewId, setUnrealPlaywrightConfig, setUserInactivityTimeout, setViewportNotReady, setViewportReady, showLoadingProgress, showResumeStreamPopup, showUnrealErrorMessage, showUserInactivityTimeoutPopup, smoothTransition, startStream, trackMixpanelEvent, trackTelemetryData, unrealCommandCallback, unrealFeature, unrealReducer, updateCirrusInfo, videoAdaptedToContainer, videoStreamInitialized };
|
|
6911
6783
|
//# sourceMappingURL=3dsource-angular-unreal-module.mjs.map
|