fix(epg): keep N from scrolling back to an off-screen focused programme

The guide revealed the keyboard focus after every handled key, so N's
smooth jump to now was cancelled by a reveal scroll whenever a programme
cell was still focused outside the visible lane. Only keys that move the
focus reveal it now.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
4grayandClaude Opus 5.5 committed 2026-10-01 06:54:09 +02:00
1 parent 7a6b3d9dc8
commit 810e39379d
2 files changed
+28 -1

No files matched your search

@@ -447,6 +447,28 @@ describe('EpgGuideComponent', () => {
]);
});
it('jumps to now on N without scrolling back to a focus left off-screen', async () => {
await settle(fixture);
const viewportEl: HTMLElement = fixture.debugElement.query(
By.css('cdk-virtual-scroll-viewport')
).nativeElement;
const scrollTo = jest.fn();
viewportEl.scrollTo = scrollTo as unknown as HTMLElement['scrollTo'];
// jsdom reports a zero-sized lane, so this programme counts as hidden.
component.focusCell(0, 0);
await settle(fixture);
scrollTo.mockClear();
component.onKeydown(keydown('n'));
// One combined smooth scroll; a reveal after it would cancel it.
expect(scrollTo).toHaveBeenCalledTimes(1);
expect(scrollTo).toHaveBeenCalledWith(
expect.objectContaining({ top: 0, behavior: 'smooth' })
);
expect(component.focus()).toEqual({ row: 0, block: 0 });
});
it('moves the roving focus to a clicked programme card', async () => {
await settle(fixture);
const card = fixture.debugElement.query(
@@ -257,11 +257,16 @@ export class EpgGuideComponent implements OnDestroy {
*/
@HostListener('document:keydown', ['$event'])
onKeydown(event: KeyboardEvent): void {
const focusBefore = this.focus();
if (!this.keyboard.handle(event)) {
return;
}
event.preventDefault();
this.viewportController.revealFocus(this.focus());
// Only a key that moved the focus scrolls to it: N scrolls to now on
// its own, and a reveal of a focus left off-screen would cancel it.
if (this.focus() !== focusBefore) {
this.viewportController.revealFocus(this.focus());
}
afterNextRender(() => this.viewportController.focusRovingTarget(), {
injector: this.injector,
});