mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-08 09:01:03 -08:00
perf(ui): enable OnPush on portal channels list, fix EPG track keys
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) <noreply@anthropic.com> Entire-Checkpoint: 3d6901072049
This commit is contained in:
1 parent
313230ab16
commit
0d79466c84
3 files changed
+12
-4
No files matched your search
+2
@@ -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,
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
<!-- program list -->
|
||||
<div id="program-list" class="app-scrollbar" #programList>
|
||||
@if (items.length > 0) {
|
||||
@for (program of items; track $index) {
|
||||
@for (program of items; track program.start) {
|
||||
@if (!canActivateProgram(program)) {
|
||||
<div
|
||||
class="program-item"
|
||||
@@ -105,8 +105,14 @@
|
||||
}
|
||||
}
|
||||
} @else {
|
||||
<div class="epg-not-available">
|
||||
{{ 'EPG.EPG_NOT_AVAILABLE_DATE' | translate }}
|
||||
<div class="epg-empty-state">
|
||||
<mat-icon class="empty-state-icon">event_busy</mat-icon>
|
||||
<div class="empty-state-title">
|
||||
{{ 'EPG.EPG_NOT_AVAILABLE_DATE' | translate }}
|
||||
</div>
|
||||
<div class="empty-state-hint">
|
||||
{{ 'EPG.NO_GUIDE_HINT' | translate }}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
@@ -83,7 +83,7 @@
|
||||
</div>
|
||||
@if (programSearchResults().length > 0) {
|
||||
<div class="program-search-results">
|
||||
@for (program of programSearchResults(); track $index) {
|
||||
@for (program of programSearchResults(); track program.start) {
|
||||
<button class="search-result-item" (click)="showProgramDetails(program)">
|
||||
<div class="result-info">
|
||||
<span class="result-title">{{ program.title }}</span>
|
||||
|
||||
Reference in new issue
Block a user