fix(m3u): let the guide own the keyboard and gate its entry points

While the programme guide is open the docked player carries
`data-player-shortcuts-suspended`, which `ControlsShortcuts` now honours
alongside `[inert]` — the arrows moved the player's volume instead of the
guide's row focus. The external-player strip loses its Collapse toggle
(nothing to reveal, no preference to write), the header action and its
palette command report `disabled` when the guide cannot open, the docked
strip derives its programme from the active channel's own schedule instead
of the retained NgRx value, switching playlists closes the guide, and the
collapsed strip can reach 48 px on phones.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
4grayandClaude Fable 5.1 committed 2026-09-06 13:35:51 +02:00
1 parent 376fde096d
commit 8d73286d93
16 files changed
+297 -44

No files matched your search

@@ -121,6 +121,7 @@
class="header-shortcut"
mat-icon-button
[class.is-active]="action.active?.() ?? false"
[disabled]="action.disabled?.() ?? false"
[attr.aria-pressed]="action.active ? action.active() : null"
(click)="onHeaderShortcutRequested()"
[matTooltip]="action.tooltipKey | translate"
@@ -922,6 +922,39 @@ describe('WorkspaceShellFacade', () => {
);
});
it('disables the programme guide command while the header action reports disabled', () => {
const headerContext = TestBed.inject(WorkspaceHeaderContextService);
activePlaylistSignal.set({
_id: 'pl-m3u',
title: 'Playlist M3U',
count: 10,
importDate: '2026-04-22T10:00:00.000Z',
autoRefresh: false,
});
facade.currentUrl.set('/workspace/playlists/pl-m3u/groups');
const guideCommandEnabled = () =>
facade
.commandPaletteCommands()
.find((command) => command.id === 'm3u-epg-guide')?.enabled;
const registerGuideAction = (disabled: () => boolean) =>
headerContext.setAction({
id: 'm3u-epg-guide',
icon: 'grid_view',
tooltipKey: 'TOP_MENU.OPEN_EPG_GUIDE',
ariaLabelKey: 'TOP_MENU.OPEN_EPG_GUIDE',
disabled,
palette: { labelKey: 'TOP_MENU.OPEN_EPG_GUIDE' },
run: jest.fn(),
});
registerGuideAction(() => true);
expect(guideCommandEnabled()).toBe(false);
registerGuideAction(() => false);
expect(guideCommandEnabled()).toBe(true);
});
it('opens the Xtream account dialog with credentials and session counts for the active playlist', () => {
activePlaylistSignal.set({
_id: 'pl-xtream',