mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-12 12:06:16 -08:00
fix(player): re-apply a settings radio while a switch is pending
The arrow-key check skipped any option the engine still reported as checked. Arrowing from audio track A to B and back to A before the engine confirmed B therefore sent no command for A, and playback ended on B with focus on A. An arrow move always lands on an option other than the last one applied, so it now applies unconditionally. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
6c050f3175
commit
6c6bf6da4b
3 files changed
+16
-10
No files matched your search
@@ -477,8 +477,9 @@ the panel the moment the last group disappears.
|
||||
reports it, else the first — and arrows, Home and End move focus with a
|
||||
CDK `FocusKeyManager` (wrapping; the horizontal arrows follow `direction`)
|
||||
and check the option they reach, as a native radio group does: the
|
||||
directive clicks it, so the template's handler applies the choice. An
|
||||
option the engine already reports as checked is not applied again. Focus
|
||||
directive clicks it, so the template's handler applies the choice, even
|
||||
onto an option the engine still reports as checked: returning to it must
|
||||
cancel a switch that is still pending. Focus
|
||||
changes also write the roving `tabindex` immediately, because a quick
|
||||
Shift+Tab, Tab can arrive before change detection updates the bindings. The dialog is named by its `h2` title (`aria-labelledby`), each
|
||||
radio group by its `h3` group heading or `h4` subheading, and the delay
|
||||
|
||||
@@ -257,11 +257,11 @@ describe('PlayerSettingsPanelComponent accessibility', () => {
|
||||
'2×',
|
||||
'0.5×',
|
||||
]);
|
||||
// Every move applies its option — except onto 1×, which the (fake)
|
||||
// engine still reports as checked, so it is not applied again.
|
||||
// Every move applies its option, 1× included: the (fake) engine
|
||||
// still reports 1× checked, but 1.25× is the pending request.
|
||||
expect(
|
||||
fake.commands.setPlaybackSpeed.mock.calls.map(([speed]) => speed)
|
||||
).toEqual([1.25, 1.5, 1.25, 2, 0.5, 2, 0.5]);
|
||||
).toEqual([1.25, 1.5, 1.25, 1, 2, 0.5, 2, 0.5]);
|
||||
});
|
||||
|
||||
it('keeps arrow keys inside their own group', () => {
|
||||
@@ -272,7 +272,9 @@ describe('PlayerSettingsPanelComponent accessibility', () => {
|
||||
expect(document.activeElement).toBe(german);
|
||||
press(german, 'ArrowDown');
|
||||
expect(document.activeElement).toBe(english);
|
||||
expect(fake.commands.setAudioTrack.mock.calls).toEqual([[2]]);
|
||||
// Returning before the engine confirms the first switch applies
|
||||
// English again; otherwise the pending switch would win.
|
||||
expect(fake.commands.setAudioTrack.mock.calls).toEqual([[2], [1]]);
|
||||
expect(fake.commands.setPlaybackSpeed).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
|
||||
@@ -42,11 +42,14 @@ export class SettingsRadioDirective implements FocusableOption {
|
||||
this.group.onOptionFocus(this);
|
||||
}
|
||||
|
||||
/** Checks the option through its own click handler, as a press would. */
|
||||
/**
|
||||
* Checks the option through its own click handler, as a press would.
|
||||
* Unconditionally: the engine may still report this option checked
|
||||
* while a switch away from it is pending, and returning to it must
|
||||
* cancel that switch.
|
||||
*/
|
||||
check(): void {
|
||||
if (!this.checked()) {
|
||||
this.element.click();
|
||||
}
|
||||
this.element.click();
|
||||
}
|
||||
|
||||
/** Immediate write of what the `tabindex` binding renders next. */
|
||||
|
||||
Reference in new issue
Block a user