refactor(components): use OnPush and signals in components

Angular 22 defaults to OnPush, so Eager is removed.
Template state is now signals, so sorting needs no detectChanges.
Game of Life execution time now updates live.
Remove the unused ImageDialogComponent and turn the OnPush lint rule
back on.
This commit is contained in:
lobo committed 2026-10-13 11:10:04 +02:00
1 parent 2abc7c31e2
commit dc9f09bede
33 files changed
+336 -336

No files matched your search

@@ -1,4 +1,4 @@
import {AfterViewInit, Component, ElementRef, EventEmitter, Input, Output, ViewChild, ChangeDetectionStrategy} from '@angular/core';
import {AfterViewInit, Component, ElementRef, EventEmitter, Input, Output, ViewChild} from '@angular/core';
import {CommonModule} from '@angular/common';
export interface GridPos { row: number; col: number }
@@ -7,7 +7,6 @@ export interface GridPos { row: number; col: number }
selector: 'app-generic-grid',
imports: [CommonModule],
templateUrl: './generic-grid.html',
changeDetection: ChangeDetectionStrategy.Eager,
styleUrl: './generic-grid.scss',
})
export class GenericGridComponent implements AfterViewInit {
@@ -1,11 +1,10 @@
import {AfterViewInit, Component, ElementRef, HostListener, inject, NgZone, OnDestroy, PLATFORM_ID, ViewChild, ChangeDetectionStrategy} from '@angular/core';
import {AfterViewInit, Component, ElementRef, HostListener, inject, NgZone, OnDestroy, PLATFORM_ID, ViewChild} from '@angular/core';
import {isPlatformBrowser} from '@angular/common';
@Component({
selector: 'app-particles-background',
imports: [],
templateUrl: './particles-background.component.html',
changeDetection: ChangeDetectionStrategy.Eager,
styleUrl: './particles-background.component.scss',
})
export class ParticleBackgroundComponent implements AfterViewInit, OnDestroy {
@@ -1,4 +1,4 @@
import {AfterViewInit, Component, ElementRef, EventEmitter, inject, Input, NgZone, OnDestroy, Output, ViewChild, ChangeDetectionStrategy} from '@angular/core';
import {AfterViewInit, Component, ElementRef, EventEmitter, inject, input, NgZone, OnDestroy, Output, ViewChild} from '@angular/core';
import {MatSnackBar} from '@angular/material/snack-bar';
import {TranslateService} from '@ngx-translate/core';
import {ArcRotateCamera, Camera, Engine, MeshBuilder, Scene, ShaderLanguage, ShaderMaterial, Vector2, Vector3, WebGPUEngine} from '@babylonjs/core';
@@ -26,7 +26,6 @@ export interface SceneEventData {
selector: 'app-babylon-canvas',
imports: [],
templateUrl: './babylon-canvas.component.html',
changeDetection: ChangeDetectionStrategy.Eager,
styleUrl: './babylon-canvas.component.scss',
})
export class BabylonCanvas implements AfterViewInit, OnDestroy {
@@ -37,8 +36,8 @@ export class BabylonCanvas implements AfterViewInit, OnDestroy {
@ViewChild('renderCanvas', { static: true }) canvasRef!: ElementRef<HTMLCanvasElement>;
@Input({ required: true }) config!: RenderConfig;
@Input() renderCallback?: RenderCallback;
readonly config = input.required<RenderConfig>();
readonly renderCallback = input<RenderCallback>();
@Output() sceneReady = new EventEmitter<SceneEventData>();
@Output() sceneResized = new EventEmitter<SceneEventData>();
@@ -131,7 +130,7 @@ export class BabylonCanvas implements AfterViewInit, OnDestroy {
}
private setupCamera(canvas: HTMLCanvasElement) {
if (this.config.mode === '3D') {
if (this.config().mode === '3D') {
this.setup3dCamera(canvas);
return;
}
@@ -144,7 +143,7 @@ export class BabylonCanvas implements AfterViewInit, OnDestroy {
cam.mode = Camera.ORTHOGRAPHIC_CAMERA;
const aspect = canvas.width / canvas.height;
const viewSize = this.config?.initialViewSize ?? 10;
const viewSize = this.config().initialViewSize ?? 10;
cam.orthoLeft = -viewSize * aspect / 2;
cam.orthoRight = viewSize * aspect / 2;
cam.orthoTop = viewSize / 2;
@@ -161,17 +160,18 @@ export class BabylonCanvas implements AfterViewInit, OnDestroy {
cam.maxZ = 100;
cam.lowerRadiusLimit = 1.5;
cam.upperRadiusLimit = 20;
cam.radius = this.config?.initialViewSize ?? 1;
cam.radius = this.config().initialViewSize ?? 1;
cam.attachControl(canvas, true);
this.camera = cam;
}
private createFullScreenRect() {
if (!this.config.vertexShader || !this.config.fragmentShader) {
const config = this.config();
if (!config.vertexShader || !config.fragmentShader) {
return;
}
const plane = MeshBuilder.CreatePlane("plane", {size: 100}, this.scene);
if (this.config.mode === '3D') {
if (config.mode === '3D') {
plane.parent = this.camera;
plane.position.z = 1;
} else {
@@ -183,7 +183,8 @@ export class BabylonCanvas implements AfterViewInit, OnDestroy {
}
private createShaderMaterial() {
if (!this.config.vertexShader || !this.config.fragmentShader || !this.config.uniformNames) {
const config = this.config();
if (!config.vertexShader || !config.fragmentShader || !config.uniformNames) {
return;
}
@@ -191,14 +192,14 @@ export class BabylonCanvas implements AfterViewInit, OnDestroy {
"shaderMaterial",
this.scene,
{
vertexSource: this.config.vertexShader,
fragmentSource: this.config.fragmentShader
vertexSource: config.vertexShader,
fragmentSource: config.fragmentShader
},
{
attributes: ["position", "uv"],
uniforms: ["resolution", "cameraPosition", ...this.config.uniformNames],
uniformBuffers: this.config.uniformBufferNames ?? [],
shaderLanguage: this.config.shaderLanguage ?? ShaderLanguage.GLSL
uniforms: ["resolution", "cameraPosition", ...config.uniformNames],
uniformBuffers: config.uniformBufferNames ?? [],
shaderLanguage: config.shaderLanguage ?? ShaderLanguage.GLSL
}
);
this.shaderMaterial.disableDepthWrite = true;
@@ -209,8 +210,9 @@ export class BabylonCanvas implements AfterViewInit, OnDestroy {
this.engine.runRenderLoop(() => {
// callback call to call specific uniforms
if (this.renderCallback) {
this.renderCallback(this.shaderMaterial, this.camera, canvas, this.scene);
const callback = this.renderCallback();
if (callback) {
callback(this.shaderMaterial, this.camera, canvas, this.scene);
}
// default uniforms which maybe each scene has
@@ -228,8 +230,9 @@ export class BabylonCanvas implements AfterViewInit, OnDestroy {
this.engine.resize();
}
if (this.config.mode === '2D' && this.camera instanceof ArcRotateCamera) {
const viewSize = this.config?.initialViewSize ?? 10;
const config = this.config();
if (config.mode === '2D' && this.camera instanceof ArcRotateCamera) {
const viewSize = config.initialViewSize ?? 10;
this.camera.orthoLeft = -viewSize / 2;
this.camera.orthoRight = viewSize / 2;
this.camera.orthoTop = viewSize / 2;