fix(playback): clarify external player launch feedback (#1388)

This commit is contained in:
4gray authored and GitHub committed 2026-08-09 13:33:07 +02:00
1 parent 8442747c37
commit d73acd6bfc
101 files changed
+8819 -850

No files matched your search

@@ -271,6 +271,7 @@ describe('WorkspaceShellFacade', () => {
activeSession: signal(null),
visibleSession: signal(null),
closeSession: jest.fn(),
dismissActiveSession: jest.fn(),
},
},
{
@@ -1075,6 +1076,26 @@ describe('WorkspaceShellFacade', () => {
expect(recentCommands.record).toHaveBeenCalledWith('open-settings');
});
it('delegates failed external-session dismissal without closing a player', () => {
const externalPlayback = TestBed.inject(PORTAL_EXTERNAL_PLAYBACK);
facade.dismissActiveExternalSession();
expect(externalPlayback.dismissActiveSession).toHaveBeenCalledTimes(1);
expect(externalPlayback.closeSession).not.toHaveBeenCalled();
});
it('handles a rejected external-session close', async () => {
const externalPlayback = TestBed.inject(PORTAL_EXTERNAL_PLAYBACK);
const closeSession = externalPlayback.closeSession as jest.Mock;
closeSession.mockRejectedValueOnce(new Error('close failed'));
facade.closeActiveExternalSession();
await Promise.resolve();
expect(closeSession).toHaveBeenCalledTimes(1);
});
it('waits for embedded MPV support preload before opening the palette', async () => {
const dialog = TestBed.inject(MatDialog) as unknown as {
open: jest.Mock;
@@ -52,9 +52,12 @@ export class WorkspaceShellFacade {
);
// Root-provided; optional keeps standalone unit tests light. While the phone context drawer is modal, opening the command
// palette over it would stack two competing focus-trapped surfaces.
private readonly contextDrawer = inject(WorkspaceShellContextDrawerService, {
optional: true,
});
private readonly contextDrawer = inject(
WorkspaceShellContextDrawerService,
{
optional: true,
}
);
private readonly onDocumentKeydown = (event: KeyboardEvent): void => {
if (!(event.ctrlKey || event.metaKey)) {
return;
@@ -153,9 +156,13 @@ export class WorkspaceShellFacade {
}
closeActiveExternalSession(): void {
void this.externalPlayback.closeSession(
this.externalPlayback.activeSession()
);
void this.externalPlayback
.closeSession(this.externalPlayback.activeSession())
.catch(() => undefined);
}
dismissActiveExternalSession(): void {
this.externalPlayback.dismissActiveSession();
}
openActiveExternalSessionTarget(): void {
@@ -128,6 +128,7 @@
<app-external-playback-dock
[session]="session"
(closeClicked)="facade.closeActiveExternalSession()"
(dismissClicked)="facade.dismissActiveExternalSession()"
(artworkClicked)="facade.openActiveExternalSessionTarget()"
/>
</footer>
@@ -102,6 +102,7 @@ class MockWorkspaceShellContextSidebarComponent {
class MockExternalPlaybackDockComponent {
readonly session = input<unknown>(null);
readonly closeClicked = output<void>();
readonly dismissClicked = output<void>();
}
@Component({
@@ -210,6 +211,7 @@ class MockWorkspaceShellFacade {
openAccountInfo = jest.fn();
openAccountInfoFor = jest.fn();
closeActiveExternalSession = jest.fn();
dismissActiveExternalSession = jest.fn();
cancelXtreamImport = jest.fn();
}
@@ -294,6 +296,11 @@ describe('WorkspaceShellComponent', () => {
expect(
fixture.nativeElement.querySelector('app-external-playback-dock')
).not.toBeNull();
const externalDock = fixture.debugElement.query(
By.directive(MockExternalPlaybackDockComponent)
).componentInstance as MockExternalPlaybackDockComponent;
externalDock.dismissClicked.emit();
expect(facade.dismissActiveExternalSession).toHaveBeenCalledTimes(1);
});
it('renders the xtream import overlay child only when the facade flag is true', async () => {