From c6dbedd035605db726397487288d808555a8cd8d Mon Sep 17 00:00:00 2001 From: 4gray Date: Thu, 2 Jul 2026 01:12:45 +0200 Subject: [PATCH] fix(epg): drop malformed programmes from the list-view day filter MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reject programmes whose stop is not after their start in buildEpgListRows — same as the timeline's buildTimelineBlocks. Bad provider data would otherwise render impossible time ranges and could even be offered as catch-up playable. (Codex P2 on e6fd0d08) Co-Authored-By: Claude Opus 4.8 --- .../epg-list-view/epg-list-view.utils.spec.ts | 18 ++++++++++++++++++ .../lib/epg-list-view/epg-list-view.utils.ts | 6 ++++++ 2 files changed, 24 insertions(+) diff --git a/libs/ui/epg/src/lib/epg-list-view/epg-list-view.utils.spec.ts b/libs/ui/epg/src/lib/epg-list-view/epg-list-view.utils.spec.ts index 50d90dd6a..fdc42bfc0 100644 --- a/libs/ui/epg/src/lib/epg-list-view/epg-list-view.utils.spec.ts +++ b/libs/ui/epg/src/lib/epg-list-view/epg-list-view.utils.spec.ts @@ -120,6 +120,24 @@ describe('buildEpgListRows', () => { ); }); + it('drops malformed programmes whose stop is not after their start', () => { + // Same as the timeline's buildTimelineBlocks: zero/negative durations + // from bad provider data must not render (or become catch-up playable). + const zeroDuration = programAt(-60, 0, 'Zero'); + const negativeDuration = { + ...programAt(-60, 60, 'Negative'), + stop: new Date(NOW - 120 * 60_000).toISOString(), + }; + const rows = buildEpgListRows( + [zeroDuration, negativeDuration, programAt(-30, 60, 'Now')], + TODAY, + NOW, + DEFAULT_OPTS + ); + + expect(rows.map((r) => r.program.title)).toEqual(['Now']); + }); + it('deduplicates programmes sharing a time slot, keeping the richer one', () => { const rows = buildEpgListRows( [ diff --git a/libs/ui/epg/src/lib/epg-list-view/epg-list-view.utils.ts b/libs/ui/epg/src/lib/epg-list-view/epg-list-view.utils.ts index 9c9162a6c..3c5c1a69d 100644 --- a/libs/ui/epg/src/lib/epg-list-view/epg-list-view.utils.ts +++ b/libs/ui/epg/src/lib/epg-list-view/epg-list-view.utils.ts @@ -77,6 +77,12 @@ export function buildEpgListRows( if (!Number.isFinite(startMs) || !Number.isFinite(stopMs)) { return false; } + // Drop malformed programmes (stop not after start) — same as the + // timeline's buildTimelineBlocks; they would render impossible time + // ranges and could even be offered as catch-up playable. + if (stopMs <= startMs) { + return false; + } return startMs < dayEndMs && stopMs > dayStartMs; });