phoenix-ui-components 4.1.0 → 4.2.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.
|
@@ -800,14 +800,20 @@ class NotificationToastComponent {
|
|
|
800
800
|
class DownloadAnimationDialogComponent {
|
|
801
801
|
data;
|
|
802
802
|
progress = 0;
|
|
803
|
+
progressSub;
|
|
803
804
|
constructor(data) {
|
|
804
805
|
this.data = data;
|
|
805
806
|
}
|
|
806
807
|
ngOnInit() {
|
|
807
|
-
this.data.progress$.subscribe((val) => {
|
|
808
|
+
this.progressSub = this.data.progress$.subscribe((val) => {
|
|
808
809
|
this.progress = val;
|
|
809
810
|
});
|
|
810
811
|
}
|
|
812
|
+
ngOnDestroy() {
|
|
813
|
+
// `progress$` is a BehaviorSubject that is never completed, so the
|
|
814
|
+
// subscription outlives the dialog unless it is dropped here.
|
|
815
|
+
this.progressSub?.unsubscribe();
|
|
816
|
+
}
|
|
811
817
|
static ɵfac = function DownloadAnimationDialogComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || DownloadAnimationDialogComponent)(i0.ɵɵdirectiveInject(MAT_DIALOG_DATA)); };
|
|
812
818
|
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: DownloadAnimationDialogComponent, selectors: [["app-download-animation-dialog"]], standalone: false, decls: 12, vars: 5, consts: [[1, "loader-wrapper", "d-flex", "flex-column", "justify-content-center", "align-items-center", "w-100", "h-100", "p-5", "text-center"], ["src", "assets/images/logo-small.svg", "alt", "Loader"], [1, "mt-5", "text-light"], [1, "text-muted"], [1, "loading-bar-container"], ["mode", "determinate", 3, "value"], [1, "progress-text", "text-light", "mt-2"]], template: function DownloadAnimationDialogComponent_Template(rf, ctx) { if (rf & 1) {
|
|
813
819
|
i0.ɵɵelementStart(0, "div", 0);
|
|
@@ -1042,13 +1048,21 @@ class AnimateCameraComponent {
|
|
|
1042
1048
|
dialogRef.close();
|
|
1043
1049
|
});
|
|
1044
1050
|
};
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
this.
|
|
1051
|
+
// `animateCamera` refuses to start while another animation is running. If
|
|
1052
|
+
// it does not start, nothing will ever call `onEnd`, so the interval would
|
|
1053
|
+
// run forever behind a dialog the user cannot dismiss.
|
|
1054
|
+
const started = preset
|
|
1055
|
+
? this.animatePreset(preset, onEnd)
|
|
1056
|
+
: this.animateCamera(onEnd);
|
|
1057
|
+
if (!started) {
|
|
1058
|
+
clearInterval(interval);
|
|
1059
|
+
recorder.stopRecording(() => dialogRef.close());
|
|
1050
1060
|
}
|
|
1051
1061
|
}
|
|
1062
|
+
/**
|
|
1063
|
+
* Animate through the given preset.
|
|
1064
|
+
* @returns Whether the animation was started.
|
|
1065
|
+
*/
|
|
1052
1066
|
animatePreset(preset, onEnd) {
|
|
1053
1067
|
this.setDetectorOpacity(0.2);
|
|
1054
1068
|
this.eventDisplay.animatePreset(this.animationPresets[preset], () => {
|
|
@@ -1056,16 +1070,24 @@ class AnimateCameraComponent {
|
|
|
1056
1070
|
if (onEnd)
|
|
1057
1071
|
onEnd();
|
|
1058
1072
|
});
|
|
1073
|
+
return true;
|
|
1059
1074
|
}
|
|
1075
|
+
/**
|
|
1076
|
+
* Animate the camera through the event.
|
|
1077
|
+
* @returns Whether the animation was started. It is refused while another
|
|
1078
|
+
* animation is already running.
|
|
1079
|
+
*/
|
|
1060
1080
|
animateCamera(onEnd) {
|
|
1061
|
-
if (
|
|
1062
|
-
|
|
1063
|
-
this.eventDisplay.animateThroughEvent([11976, 7262, 11927], 3000, () => {
|
|
1064
|
-
this.isAnimating = false;
|
|
1065
|
-
if (onEnd)
|
|
1066
|
-
onEnd();
|
|
1067
|
-
});
|
|
1081
|
+
if (this.isAnimating) {
|
|
1082
|
+
return false;
|
|
1068
1083
|
}
|
|
1084
|
+
this.isAnimating = true;
|
|
1085
|
+
this.eventDisplay.animateThroughEvent([11976, 7262, 11927], 3000, () => {
|
|
1086
|
+
this.isAnimating = false;
|
|
1087
|
+
if (onEnd)
|
|
1088
|
+
onEnd();
|
|
1089
|
+
});
|
|
1090
|
+
return true;
|
|
1069
1091
|
}
|
|
1070
1092
|
setDetectorOpacity(opacity) {
|
|
1071
1093
|
const sceneManager = this.eventDisplay.getThreeManager().getSceneManager();
|
|
@@ -2553,7 +2575,15 @@ class IOOptionsDialogComponent {
|
|
|
2553
2575
|
}
|
|
2554
2576
|
async handleROOTInput(files) {
|
|
2555
2577
|
const rootObjectName = prompt('Enter object name in ROOT file');
|
|
2556
|
-
|
|
2578
|
+
// The object URL pins the whole file in memory, so release it once the
|
|
2579
|
+
// geometry has been read - ROOT files are routinely hundreds of MB.
|
|
2580
|
+
const objectUrl = URL.createObjectURL(files[0]);
|
|
2581
|
+
try {
|
|
2582
|
+
await this.eventDisplay.loadRootGeometry(objectUrl, rootObjectName, files[0].name.split('.')[0]);
|
|
2583
|
+
}
|
|
2584
|
+
finally {
|
|
2585
|
+
URL.revokeObjectURL(objectUrl);
|
|
2586
|
+
}
|
|
2557
2587
|
this.onClose();
|
|
2558
2588
|
}
|
|
2559
2589
|
async handleRootJSONInput(files) {
|
|
@@ -2561,7 +2591,13 @@ class IOOptionsDialogComponent {
|
|
|
2561
2591
|
return;
|
|
2562
2592
|
}
|
|
2563
2593
|
const name = files[0].name.split('.')[0];
|
|
2564
|
-
|
|
2594
|
+
const objectUrl = URL.createObjectURL(files[0]);
|
|
2595
|
+
try {
|
|
2596
|
+
await this.eventDisplay.loadRootJSONGeometry(objectUrl, name);
|
|
2597
|
+
}
|
|
2598
|
+
finally {
|
|
2599
|
+
URL.revokeObjectURL(objectUrl);
|
|
2600
|
+
}
|
|
2565
2601
|
this.onClose();
|
|
2566
2602
|
}
|
|
2567
2603
|
async handlePHYSLITEInput(files) {
|
|
@@ -3373,21 +3409,49 @@ class CartesianGridConfigComponent {
|
|
|
3373
3409
|
shiftCartesianGridByPointer() {
|
|
3374
3410
|
this.shiftGrid = true;
|
|
3375
3411
|
this.eventDisplay.getUIManager().shiftCartesianGridByPointer();
|
|
3412
|
+
// Drop any subscriptions from a previous shift before starting a new one.
|
|
3413
|
+
this.clearShiftSubscriptions();
|
|
3376
3414
|
this.originChangedSub = this.eventDisplay
|
|
3377
3415
|
.getThreeManager()
|
|
3378
3416
|
.originChanged.subscribe((intersect) => {
|
|
3379
3417
|
this.translateGrid(intersect);
|
|
3380
3418
|
});
|
|
3419
|
+
// `stopShifting` may emit synchronously during `subscribe`, in which case
|
|
3420
|
+
// the handler runs before `stopShiftingSub` has been assigned. Track that
|
|
3421
|
+
// with a flag so the teardown still happens (and never dereferences null).
|
|
3422
|
+
let stoppedDuringSubscribe = false;
|
|
3381
3423
|
this.stopShiftingSub = this.eventDisplay
|
|
3382
3424
|
.getThreeManager()
|
|
3383
3425
|
.stopShifting.subscribe((stop) => {
|
|
3384
|
-
if (stop) {
|
|
3385
|
-
|
|
3386
|
-
|
|
3426
|
+
if (!stop) {
|
|
3427
|
+
return;
|
|
3428
|
+
}
|
|
3429
|
+
if (this.stopShiftingSub) {
|
|
3430
|
+
this.clearShiftSubscriptions();
|
|
3431
|
+
}
|
|
3432
|
+
else {
|
|
3433
|
+
stoppedDuringSubscribe = true;
|
|
3387
3434
|
}
|
|
3388
3435
|
});
|
|
3436
|
+
if (stoppedDuringSubscribe) {
|
|
3437
|
+
this.clearShiftSubscriptions();
|
|
3438
|
+
}
|
|
3389
3439
|
this.onClose();
|
|
3390
3440
|
}
|
|
3441
|
+
/**
|
|
3442
|
+
* Unsubscribe from the grid-shifting subscriptions, if any are active.
|
|
3443
|
+
*/
|
|
3444
|
+
clearShiftSubscriptions() {
|
|
3445
|
+
this.originChangedSub?.unsubscribe();
|
|
3446
|
+
this.originChangedSub = null;
|
|
3447
|
+
this.stopShiftingSub?.unsubscribe();
|
|
3448
|
+
this.stopShiftingSub = null;
|
|
3449
|
+
}
|
|
3450
|
+
ngOnDestroy() {
|
|
3451
|
+
// The dialog closes as soon as pointer shifting starts, so without this the
|
|
3452
|
+
// subscriptions outlive the component and leak on every reopen.
|
|
3453
|
+
this.clearShiftSubscriptions();
|
|
3454
|
+
}
|
|
3391
3455
|
shiftCartesianGridByValues(position) {
|
|
3392
3456
|
this.translateGrid(position);
|
|
3393
3457
|
this.eventDisplay.getThreeManager().originChangedEmit(position);
|
|
@@ -3664,7 +3728,9 @@ class ViewOptionsComponent {
|
|
|
3664
3728
|
this.eventDisplay.getUIManager().show3DDistance(change.checked);
|
|
3665
3729
|
}
|
|
3666
3730
|
ngOnDestroy() {
|
|
3667
|
-
|
|
3731
|
+
// The component can be destroyed before ngOnInit has created the
|
|
3732
|
+
// subscription, so guard rather than dereferencing it unconditionally.
|
|
3733
|
+
this.sub?.unsubscribe();
|
|
3668
3734
|
}
|
|
3669
3735
|
static ɵfac = function ViewOptionsComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || ViewOptionsComponent)(i0.ɵɵdirectiveInject(EventDisplayService), i0.ɵɵdirectiveInject(i1$1.MatDialog)); };
|
|
3670
3736
|
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: ViewOptionsComponent, selectors: [["app-view-options"]], viewQuery: function ViewOptionsComponent_Query(rf, ctx) { if (rf & 1) {
|