mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-10 18:36:15 -08:00
fix(epg): honor the controlled selectedDate in the timeline
The timeline declared a `selectedDate` input but never read it: `viewDayKey` seeded to today and only local `commitDay` navigation mutated it, so a programmatic host change was ignored and a preserved non-today date reset to today on (re)mount — the panel showed today/empty-day while the host pointed at another day (the old EpgList honored the controlled input). Flagged by Codex. Seed `viewDayKey` from `selectedDate` via `linkedSignal` so it initializes from and follows the host, while local day navigation still overrides via `.set()`. Steady state is unchanged: the host echoes back the emitted key, so the signal recomputes to the same value (no loop, no flicker). Regression coverage: two specs assert a controlled non-today `selectedDate` renders the ribbon on that day and follows a programmatic change. ui-epg 80, portal-shared-ui + playlist-m3u green; lint clean; component 399 lines. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
1 parent
f8931f0ded
commit
30696d037d
2 files changed
+35
-2
No files matched your search
@@ -23,6 +23,13 @@ function programAt(
|
||||
};
|
||||
}
|
||||
|
||||
/** Local yyyy-MM-dd day-key for a programme start (matches the component). */
|
||||
function localDateKey(iso: string): string {
|
||||
const d = new Date(iso);
|
||||
const pad = (n: number) => String(n).padStart(2, '0');
|
||||
return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`;
|
||||
}
|
||||
|
||||
describe('EpgTimelineComponent', () => {
|
||||
let fixture: ComponentFixture<EpgTimelineComponent>;
|
||||
let component: EpgTimelineComponent;
|
||||
@@ -86,6 +93,26 @@ describe('EpgTimelineComponent', () => {
|
||||
expect(component.renderState()).toBe('empty-day');
|
||||
});
|
||||
|
||||
it('honours a controlled non-today selectedDate instead of resetting to today', () => {
|
||||
// Data three days out (today empty). Without honouring the controlled
|
||||
// input the panel would show empty-day for today; with it, the ribbon
|
||||
// renders on the host-selected day.
|
||||
const future = programAt(3 * 1440, 60);
|
||||
setInputs({
|
||||
programs: [future],
|
||||
selectedDate: localDateKey(future.start),
|
||||
});
|
||||
expect(component.renderState()).toBe('ribbon');
|
||||
});
|
||||
|
||||
it('follows a programmatic selectedDate change from the host', () => {
|
||||
const future = programAt(3 * 1440, 60);
|
||||
setInputs({ programs: [future] });
|
||||
expect(component.renderState()).toBe('empty-day'); // viewing today
|
||||
setInputs({ selectedDate: localDateKey(future.start) });
|
||||
expect(component.renderState()).toBe('ribbon'); // followed the host
|
||||
});
|
||||
|
||||
it('shows the ribbon controls (Now + zoom) only while a ribbon renders', () => {
|
||||
setInputs({ programs: [programAt(0, 120, 'Now')] });
|
||||
expect(component.showRibbonControls()).toBe(true);
|
||||
|
||||
@@ -7,6 +7,7 @@ import {
|
||||
ElementRef,
|
||||
inject,
|
||||
input,
|
||||
linkedSignal,
|
||||
output,
|
||||
signal,
|
||||
untracked,
|
||||
@@ -120,8 +121,13 @@ export class EpgTimelineComponent {
|
||||
|
||||
private readonly nowMs = signal(Date.now());
|
||||
readonly selectedKey = signal<string | null>(null);
|
||||
/** Day currently centred in the ribbon viewport. */
|
||||
private readonly viewDayKey = signal(getTodayEpgDateKey());
|
||||
/** Day centred in the ribbon. Seeded from the controlled `selectedDate` so a
|
||||
* non-today date survives (re)mount and follows host changes; local
|
||||
* navigation overrides via `commitDay`. Falls back to today when unset. */
|
||||
private readonly viewDayKey = linkedSignal(() => {
|
||||
const key = this.selectedDate()?.trim();
|
||||
return key ? key : getTodayEpgDateKey();
|
||||
});
|
||||
|
||||
/** Ribbon scrolling + channel-select auto-focus, extracted from the view. */
|
||||
private readonly scroll = new TimelineScrollController({
|
||||
|
||||
Reference in new issue
Block a user