@3dsource/angular-unreal-module 0.0.110-dev.0 → 0.0.111
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,20 +1,20 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { InjectionToken, inject, ChangeDetectionStrategy, Component, Injectable, DestroyRef, signal, Pipe, input, ElementRef, viewChild,
|
|
2
|
+
import { InjectionToken, inject, ChangeDetectionStrategy, Component, Injectable, DestroyRef, effect, untracked, signal, Pipe, input, ElementRef, viewChild, afterNextRender, HostListener, computed, output, makeEnvironmentProviders, provideEnvironmentInitializer } from '@angular/core';
|
|
3
3
|
import { SourceButtonComponent, SourceLoadingComponent } from '@3dsource/source-ui-native';
|
|
4
|
-
import { map as map$1, distinctUntilChanged, takeWhile, filter, tap, withLatestFrom, exhaustMap, catchError, takeUntil, switchMap as switchMap$1, timeout as timeout$1, debounceTime as debounceTime$1, take as take$1, startWith as startWith$1, delay, skip as skip$1 } from 'rxjs/operators';
|
|
5
|
-
import { Logger, calculateMedian, clampf, lerp, getCanvasCached, getSnapshot, fitIntoRectangle, whereNot, Truthy, Falsy, tapLog, generateUuid, COLOR_CODES, where, KeyboardNumericCode, InvertedKeyMap, Semaphore, HEXtoRGB, RGBtoHSV, inverseLerp, HSVtoRGB, RGBtoHEX, fpIsASameAsB } from '@3dsource/utils';
|
|
6
4
|
import { merge, map, scan, concatMap, of, animationFrameScheduler, interval, Observable, debounceTime, switchMap, take, fromEvent, EMPTY, timer, timeout, mergeMap, Subject, skip, share, from, throwError, defer, retry, tap as tap$1, startWith, takeUntil as takeUntil$1, throttleTime, asyncScheduler, filter as filter$1, withLatestFrom as withLatestFrom$1, pairwise, Subscription, bufferTime, BehaviorSubject, combineLatestWith, distinctUntilChanged as distinctUntilChanged$1, concat } from 'rxjs';
|
|
7
5
|
import { createAction, props, createReducer, on, createFeature, createSelector, Store, provideState } from '@ngrx/store';
|
|
8
6
|
import { Actions, createEffect, ofType, provideEffects } from '@ngrx/effects';
|
|
7
|
+
import { map as map$1, distinctUntilChanged, takeWhile, filter, tap, withLatestFrom, exhaustMap, catchError, takeUntil, switchMap as switchMap$1, timeout as timeout$1, debounceTime as debounceTime$1, take as take$1, startWith as startWith$1, delay, skip as skip$1 } from 'rxjs/operators';
|
|
8
|
+
import { Logger, calculateMedian, clampf, lerp, getCanvasCached, getSnapshot, fitIntoRectangle, whereNot, Truthy, Falsy, tapLog, 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, takeUntilDestroyed, toObservable } from '@angular/core/rxjs-interop';
|
|
14
15
|
import { v4 } from 'uuid';
|
|
15
16
|
import { DomSanitizer } from '@angular/platform-browser';
|
|
16
17
|
import { NgOptimizedImage, AsyncPipe, JsonPipe } from '@angular/common';
|
|
17
|
-
import { toSignal, takeUntilDestroyed, toObservable } from '@angular/core/rxjs-interop';
|
|
18
18
|
import * as i1 from '@angular/forms';
|
|
19
19
|
import { FormsModule } from '@angular/forms';
|
|
20
20
|
|
|
@@ -1657,29 +1657,42 @@ class SubService {
|
|
|
1657
1657
|
class AFKService extends SubService {
|
|
1658
1658
|
constructor() {
|
|
1659
1659
|
super();
|
|
1660
|
-
// Optionally detect if the user is not interacting (AFK) and disconnect them.
|
|
1661
|
-
this.enabled = true; // Set to true to enable the AFK system.
|
|
1662
|
-
this.closeTimeout = DEFAULT_AFK_TIMEOUT_PERIOD; // The time after the warning when we disconnect the user.
|
|
1663
1660
|
this.active = false; // Whether the AFK system is currently looking for inactivity.
|
|
1664
1661
|
this.countdown = 0; // The inactivity warning overlay has a countdown to show time until disconnect.
|
|
1665
|
-
this.
|
|
1662
|
+
this.warnTimeout = this.store.selectSignal(selectWarnTimeout);
|
|
1666
1663
|
this.isViewportReady = this.store.selectSignal(unrealFeature.selectViewportReady);
|
|
1667
1664
|
this.unrealConfig = inject(UNREAL_CONFIG, { optional: true });
|
|
1665
|
+
/** Ticks every time warnTimeout changes or resetAfk action fires */
|
|
1666
|
+
this.afkResetTrigger = toSignal(merge(this.store.select(selectWarnTimeout), this.actions$.pipe(ofType(resetAfk))));
|
|
1667
|
+
/** Ticks when cirrus disconnects */
|
|
1668
|
+
this.disconnected = toSignal(this.disconnect$);
|
|
1668
1669
|
this.destroyRef.onDestroy(() => this.clearTimers());
|
|
1669
|
-
this.init();
|
|
1670
|
-
}
|
|
1671
|
-
init() {
|
|
1672
1670
|
if (this.unrealConfig?.playwright) {
|
|
1673
1671
|
return;
|
|
1674
1672
|
}
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1673
|
+
// Reset AFK warning timer when warnTimeout changes or resetAfk action fires
|
|
1674
|
+
effect(() => {
|
|
1675
|
+
this.afkResetTrigger();
|
|
1676
|
+
untracked(() => {
|
|
1677
|
+
if (this.isViewportReady()) {
|
|
1678
|
+
this.resetAfkWarningTimer();
|
|
1679
|
+
}
|
|
1680
|
+
});
|
|
1681
|
+
});
|
|
1682
|
+
// Start AFK warning timer when viewport becomes ready
|
|
1683
|
+
effect(() => {
|
|
1684
|
+
const ready = this.isViewportReady();
|
|
1685
|
+
if (ready) {
|
|
1686
|
+
untracked(() => this.startAfkWarningTimer());
|
|
1687
|
+
}
|
|
1688
|
+
});
|
|
1689
|
+
// Stop on disconnect
|
|
1690
|
+
effect(() => {
|
|
1691
|
+
const disconnected = this.disconnected();
|
|
1692
|
+
if (disconnected !== undefined) {
|
|
1693
|
+
untracked(() => this.stop());
|
|
1694
|
+
}
|
|
1695
|
+
});
|
|
1683
1696
|
}
|
|
1684
1697
|
hideOverlay() {
|
|
1685
1698
|
this.store.dispatch(setAfkTimerHide());
|
|
@@ -1688,7 +1701,7 @@ class AFKService extends SubService {
|
|
|
1688
1701
|
* Start a timer which when elapsed will warn the user they are inactive.
|
|
1689
1702
|
*/
|
|
1690
1703
|
startAfkWarningTimer() {
|
|
1691
|
-
this.active =
|
|
1704
|
+
this.active = true;
|
|
1692
1705
|
this.resetAfkWarningTimer();
|
|
1693
1706
|
}
|
|
1694
1707
|
/**
|
|
@@ -1699,7 +1712,7 @@ class AFKService extends SubService {
|
|
|
1699
1712
|
this.clearTimers();
|
|
1700
1713
|
this.warnTimer = setTimeout(() => {
|
|
1701
1714
|
this.showAfkOverlay();
|
|
1702
|
-
}, (this.
|
|
1715
|
+
}, (this.warnTimeout() || DEFAULT_AFK_TIMEOUT) * 1000);
|
|
1703
1716
|
}
|
|
1704
1717
|
}
|
|
1705
1718
|
/**
|
|
@@ -1728,7 +1741,7 @@ class AFKService extends SubService {
|
|
|
1728
1741
|
}
|
|
1729
1742
|
// Pause the timer while the user is looking at the inactivity warning overlay.
|
|
1730
1743
|
this.active = false;
|
|
1731
|
-
this.countdown =
|
|
1744
|
+
this.countdown = DEFAULT_AFK_TIMEOUT_PERIOD;
|
|
1732
1745
|
this.store.dispatch(setAfkTimerVisible());
|
|
1733
1746
|
this.updateCountDown(this.countdown);
|
|
1734
1747
|
if (InputOptions.controlScheme === ControlScheme.LockedMouse) {
|
|
@@ -1741,7 +1754,7 @@ class AFKService extends SubService {
|
|
|
1741
1754
|
this.hideOverlay();
|
|
1742
1755
|
this.store.dispatch(disconnectStream({
|
|
1743
1756
|
reason: DisconnectReason.Afk,
|
|
1744
|
-
message: `AFK timeout:${this.
|
|
1757
|
+
message: `AFK timeout:${this.warnTimeout()} seconds, popup timeout:${DEFAULT_AFK_TIMEOUT_PERIOD} seconds`,
|
|
1745
1758
|
}));
|
|
1746
1759
|
clearInterval(this.countdownTimer);
|
|
1747
1760
|
}
|
|
@@ -3936,6 +3949,8 @@ class UnrealCommunicatorService {
|
|
|
3936
3949
|
this.unrealConfig = inject(UNREAL_CONFIG, { optional: true });
|
|
3937
3950
|
this.destroy$ = new Subject();
|
|
3938
3951
|
this.cirrusConnected = this.store.selectSignal(unrealFeature.selectCirrusConnected);
|
|
3952
|
+
this.afkIgnoredCommands = new Set(['executeConsoleCommand']);
|
|
3953
|
+
this.skipAfkReset = false;
|
|
3939
3954
|
this.init();
|
|
3940
3955
|
}
|
|
3941
3956
|
init() {
|
|
@@ -3962,7 +3977,11 @@ class UnrealCommunicatorService {
|
|
|
3962
3977
|
const uniqId = data?.correlationId ?? generateUuid();
|
|
3963
3978
|
const sendData = { ...data, correlationId: uniqId };
|
|
3964
3979
|
Logger.colored(...COLOR_CODES.TO_UNREAL, sendData);
|
|
3980
|
+
if (this.afkIgnoredCommands.has(data.command)) {
|
|
3981
|
+
this.skipAfkReset = true;
|
|
3982
|
+
}
|
|
3965
3983
|
this.emitUIInteraction(sendData);
|
|
3984
|
+
this.skipAfkReset = false;
|
|
3966
3985
|
this.store.dispatch(commandStarted({ id: uniqId, command: data.command }));
|
|
3967
3986
|
}
|
|
3968
3987
|
}
|
|
@@ -3986,7 +4005,9 @@ class UnrealCommunicatorService {
|
|
|
3986
4005
|
sendInputData(data) {
|
|
3987
4006
|
this.isPlaywrightMode();
|
|
3988
4007
|
try {
|
|
3989
|
-
this.
|
|
4008
|
+
if (!this.skipAfkReset) {
|
|
4009
|
+
this.store.dispatch(resetAfk());
|
|
4010
|
+
}
|
|
3990
4011
|
this.webRtcPlayerService.send(data);
|
|
3991
4012
|
}
|
|
3992
4013
|
catch (error) {
|
|
@@ -4607,7 +4628,7 @@ class RegionsPingService {
|
|
|
4607
4628
|
async fetchWithTimeout(url, options = {}, timeout) {
|
|
4608
4629
|
const controller = new AbortController();
|
|
4609
4630
|
options.signal = controller.signal;
|
|
4610
|
-
const timeoutId = setTimeout(() => controller.abort(), timeout);
|
|
4631
|
+
const timeoutId = setTimeout(() => controller.abort(new DOMException('Request timed out', 'TimeoutError')), timeout);
|
|
4611
4632
|
try {
|
|
4612
4633
|
const response = await fetch(url, options);
|
|
4613
4634
|
clearTimeout(timeoutId);
|
|
@@ -6068,12 +6089,15 @@ class ImageLoadingSrcComponent {
|
|
|
6068
6089
|
this.imageLoadingSrc = this.#store.selectSignal(unrealFeature.selectImageLoadingSrc);
|
|
6069
6090
|
}
|
|
6070
6091
|
#store;
|
|
6092
|
+
imageError() {
|
|
6093
|
+
this.#store.dispatch(setLoadingImageSrc({ src: '' }));
|
|
6094
|
+
}
|
|
6071
6095
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: ImageLoadingSrcComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
6072
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: ImageLoadingSrcComponent, isStandalone: true, selector: "app-image-loading-src", ngImport: i0, template: "@let image = imageLoadingSrc();\r\n@if (isLoaderScreenVisible()) {\r\n <div class=\"preload\">\r\n <div class=\"back\">\r\n @if (image) {\r\n <img
|
|
6096
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: ImageLoadingSrcComponent, isStandalone: true, selector: "app-image-loading-src", ngImport: i0, template: "@let image = imageLoadingSrc();\r\n@if (isLoaderScreenVisible()) {\r\n <div class=\"preload\">\r\n <div class=\"back\">\r\n @if (image) {\r\n <img\r\n (error)=\"imageError()\"\r\n [ngSrc]=\"image\"\r\n fill\r\n loading=\"lazy\"\r\n alt=\"image loading src\"\r\n />\r\n }\r\n </div>\r\n </div>\r\n}\r\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 }); }
|
|
6073
6097
|
}
|
|
6074
6098
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: ImageLoadingSrcComponent, decorators: [{
|
|
6075
6099
|
type: Component,
|
|
6076
|
-
args: [{ selector: 'app-image-loading-src', changeDetection: ChangeDetectionStrategy.OnPush, imports: [NgOptimizedImage], template: "@let image = imageLoadingSrc();\r\n@if (isLoaderScreenVisible()) {\r\n <div class=\"preload\">\r\n <div class=\"back\">\r\n @if (image) {\r\n <img
|
|
6100
|
+
args: [{ selector: 'app-image-loading-src', changeDetection: ChangeDetectionStrategy.OnPush, imports: [NgOptimizedImage], template: "@let image = imageLoadingSrc();\r\n@if (isLoaderScreenVisible()) {\r\n <div class=\"preload\">\r\n <div class=\"back\">\r\n @if (image) {\r\n <img\r\n (error)=\"imageError()\"\r\n [ngSrc]=\"image\"\r\n fill\r\n loading=\"lazy\"\r\n alt=\"image loading src\"\r\n />\r\n }\r\n </div>\r\n </div>\r\n}\r\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"] }]
|
|
6077
6101
|
}] });
|
|
6078
6102
|
|
|
6079
6103
|
class StatGraphComponent {
|
|
@@ -6447,7 +6471,10 @@ class IntroSrcComponent {
|
|
|
6447
6471
|
});
|
|
6448
6472
|
}
|
|
6449
6473
|
createVideo(src, videoContainer) {
|
|
6450
|
-
|
|
6474
|
+
if (typeof src !== 'string') {
|
|
6475
|
+
return;
|
|
6476
|
+
}
|
|
6477
|
+
const matchAbsolutePath = /.*\.(mp4|WebM)(\?.*)?$/i.test(src);
|
|
6451
6478
|
videoContainer.innerHTML = ''; // This will remove all existing content within the layout
|
|
6452
6479
|
const videoElement = document.createElement('video');
|
|
6453
6480
|
videoElement.autoplay = true;
|
|
@@ -6469,15 +6496,19 @@ class IntroSrcComponent {
|
|
|
6469
6496
|
}
|
|
6470
6497
|
sourceElement.type = 'video/mp4';
|
|
6471
6498
|
videoElement.appendChild(sourceElement);
|
|
6472
|
-
videoElement.
|
|
6499
|
+
videoElement.addEventListener('error', () => this.#store.dispatch(resetIntroSrc()));
|
|
6500
|
+
sourceElement.addEventListener('error', () => this.#store.dispatch(resetIntroSrc()));
|
|
6473
6501
|
videoContainer.appendChild(videoElement);
|
|
6474
6502
|
}
|
|
6503
|
+
imageError() {
|
|
6504
|
+
this.#store.dispatch(resetIntroSrc());
|
|
6505
|
+
}
|
|
6475
6506
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: IntroSrcComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
6476
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", 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();\r\n@if (image) {\r\n <div class=\"backImage\">\r\n <img [ngSrc]=\"image\" fill alt=\"imageSrc\" />\r\n </div>\r\n} @else if (videoIntroSrc()) {\r\n <div #videoPlayerCover class=\"backVideo\"></div>\r\n}\r\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
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", 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();\r\n@if (image) {\r\n <div class=\"backImage\">\r\n <img (error)=\"imageError()\" [ngSrc]=\"image\" fill alt=\"imageSrc\" />\r\n </div>\r\n} @else if (videoIntroSrc()) {\r\n <div #videoPlayerCover class=\"backVideo\"></div>\r\n}\r\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 }); }
|
|
6477
6508
|
}
|
|
6478
6509
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: IntroSrcComponent, decorators: [{
|
|
6479
6510
|
type: Component,
|
|
6480
|
-
args: [{ selector: 'app-intro-src', imports: [NgOptimizedImage], changeDetection: ChangeDetectionStrategy.OnPush, template: "@let image = imageIntroSrc();\r\n@if (image) {\r\n <div class=\"backImage\">\r\n <img [ngSrc]=\"image\" fill alt=\"imageSrc\" />\r\n </div>\r\n} @else if (videoIntroSrc()) {\r\n <div #videoPlayerCover class=\"backVideo\"></div>\r\n}\r\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
|
+
args: [{ selector: 'app-intro-src', imports: [NgOptimizedImage], changeDetection: ChangeDetectionStrategy.OnPush, template: "@let image = imageIntroSrc();\r\n@if (image) {\r\n <div class=\"backImage\">\r\n <img (error)=\"imageError()\" [ngSrc]=\"image\" fill alt=\"imageSrc\" />\r\n </div>\r\n} @else if (videoIntroSrc()) {\r\n <div #videoPlayerCover class=\"backVideo\"></div>\r\n}\r\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"] }]
|
|
6481
6512
|
}], ctorParameters: () => [], propDecorators: { videoElement: [{ type: i0.ViewChild, args: ['videoPlayerCover', { isSignal: true }] }] } });
|
|
6482
6513
|
|
|
6483
6514
|
class UnrealSceneComponent {
|