From 0d79466c8421358f378f1d1187342623dc93fffb Mon Sep 17 00:00:00 2001 From: 4gray Date: Fri, 1 May 2026 21:18:22 +0200 Subject: [PATCH] perf(ui): enable OnPush on portal channels list, fix EPG track keys MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PortalChannelsListComponent renders a virtual-scrolled channel list (Xtream live/VOD/series, can be 1000+ items). It was using default change detection, so every CD cycle in the parent tree (EPG ticks, progress updates) re-checked every binding. Switch to OnPush — the existing cdr.detectChanges() calls already cover the async update paths, and signal-based state marks for check automatically. Replace track $index with track program.start in two EPG @for loops (epg-list, multi-epg-container search results). $index causes Angular to re-create DOM nodes whenever the list reorders (e.g. on EPG refresh or timezone correction). program.start is the ISO datetime — unique per program within a channel and stable. Co-Authored-By: Claude Opus 4.7 (1M context) Entire-Checkpoint: 3d6901072049 --- .../portal-channels-list.component.ts | 2 ++ libs/ui/epg/src/lib/epg-list/epg-list.component.html | 12 +++++++++--- .../lib/multi-epg/multi-epg-container.component.html | 2 +- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/libs/portal/xtream/feature/src/lib/portal-channels-list/portal-channels-list.component.ts b/libs/portal/xtream/feature/src/lib/portal-channels-list/portal-channels-list.component.ts index bd36f8ece..9639af3b8 100644 --- a/libs/portal/xtream/feature/src/lib/portal-channels-list/portal-channels-list.component.ts +++ b/libs/portal/xtream/feature/src/lib/portal-channels-list/portal-channels-list.component.ts @@ -4,6 +4,7 @@ import { } from '@angular/cdk/scrolling'; import { AfterViewInit, + ChangeDetectionStrategy, ChangeDetectorRef, Component, computed, @@ -55,6 +56,7 @@ interface XtreamCategoryLike { selector: 'app-portal-channels-list', templateUrl: './portal-channels-list.component.html', styleUrls: ['./portal-channels-list.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush, imports: [ ChannelListItemComponent, MatIcon, diff --git a/libs/ui/epg/src/lib/epg-list/epg-list.component.html b/libs/ui/epg/src/lib/epg-list/epg-list.component.html index c076bddbe..caf290ece 100644 --- a/libs/ui/epg/src/lib/epg-list/epg-list.component.html +++ b/libs/ui/epg/src/lib/epg-list/epg-list.component.html @@ -35,7 +35,7 @@
@if (items.length > 0) { - @for (program of items; track $index) { + @for (program of items; track program.start) { @if (!canActivateProgram(program)) {
- {{ 'EPG.EPG_NOT_AVAILABLE_DATE' | translate }} +
+ event_busy +
+ {{ 'EPG.EPG_NOT_AVAILABLE_DATE' | translate }} +
+
+ {{ 'EPG.NO_GUIDE_HINT' | translate }} +
}
diff --git a/libs/ui/epg/src/lib/multi-epg/multi-epg-container.component.html b/libs/ui/epg/src/lib/multi-epg/multi-epg-container.component.html index bfb94454c..06ecb3ca9 100644 --- a/libs/ui/epg/src/lib/multi-epg/multi-epg-container.component.html +++ b/libs/ui/epg/src/lib/multi-epg/multi-epg-container.component.html @@ -83,7 +83,7 @@
@if (programSearchResults().length > 0) {
- @for (program of programSearchResults(); track $index) { + @for (program of programSearchResults(); track program.start) {