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

@@ -41,6 +41,7 @@ import {
import {
Channel,
EpgProgram,
ExternalPlayerSession,
ResolvedPortalPlayback,
Settings,
VideoPlayer,
@@ -197,6 +198,7 @@ describe('VideoPlayerComponent', () => {
const stripCountryPrefix = signal(false);
const epgViewMode = signal<'timeline' | 'list'>('timeline');
const epgUrlSetting = signal<string[]>([]);
const externalSession = signal<ExternalPlayerSession | null>(null);
const originalElectron = window.electron;
const overlayRef = {
@@ -325,6 +327,7 @@ describe('VideoPlayerComponent', () => {
channelsLoading.set(false);
currentEpgProgram.set(null);
activeEpgProgram.set(null);
externalSession.set(null);
currentEpgProgram$.next(null);
epgPrograms$.next([]);
overlayMock.create.mockClear();
@@ -415,7 +418,7 @@ describe('VideoPlayerComponent', () => {
{
provide: PORTAL_EXTERNAL_PLAYBACK,
useValue: {
activeSession: signal(null),
activeSession: externalSession,
},
},
],
@@ -582,9 +585,13 @@ describe('VideoPlayerComponent', () => {
Origin: 'https://origin.example.com',
},
};
const launch = Promise.resolve();
const trackLaunch = jest.fn();
dataServiceMock.sendIpcEvent.mockReturnValueOnce(launch);
component.handleExternalFallbackRequest({
player: 'mpv',
playback,
trackLaunch,
diagnostic: {
code: 'unsupported-codec',
source: 'hls',
@@ -605,6 +612,7 @@ describe('VideoPlayerComponent', () => {
origin: 'https://origin.example.com',
}
);
expect(trackLaunch).toHaveBeenCalledWith(launch);
});
it('renders the embedded mpv inline player with the EPG panel', () => {
@@ -641,6 +649,38 @@ describe('VideoPlayerComponent', () => {
).toBe(false);
});
it('clears the channel when a closable error becomes terminal', () => {
syncStoreState(sampleChannel);
player.set(VideoPlayer.MPV);
const closableError: ExternalPlayerSession = {
id: 'external-1',
player: 'mpv',
status: 'error',
title: sampleChannel.name,
streamUrl: sampleChannel.url,
startedAt: '2026-08-08T00:00:00.000Z',
updatedAt: '2026-08-08T00:00:00.000Z',
error: 'Process exit was not confirmed',
canClose: true,
};
externalSession.set(closableError);
fixture.detectChanges();
expect(storeMock.dispatch).not.toHaveBeenCalledWith(
ChannelActions.resetActiveChannel()
);
externalSession.set({
...closableError,
canClose: false,
updatedAt: '2026-08-08T00:00:01.000Z',
});
fixture.detectChanges();
expect(storeMock.dispatch).toHaveBeenCalledWith(
ChannelActions.resetActiveChannel()
);
});
it('keeps DASH channels inline on the HTML5 player even when MPV is configured', () => {
syncStoreState({
...sampleChannel,
@@ -80,6 +80,7 @@ import {
persistLiveEpgPanelState,
persistLiveSidebarState,
PORTAL_EXTERNAL_PLAYBACK,
isLiveExternalPlayerSession,
restoreLiveEpgPanelState,
restoreLiveSidebarState,
WorkspaceHeaderContextService,
@@ -1083,10 +1084,14 @@ export class VideoPlayerComponent implements OnInit, OnDestroy {
return;
}
this.dataService.sendIpcEvent(
request.player === 'mpv' ? OPEN_MPV_PLAYER : OPEN_VLC_PLAYER,
payload
const launch = Promise.resolve(
this.dataService.sendIpcEvent<ExternalPlayerSession>(
request.player === 'mpv' ? OPEN_MPV_PLAYER : OPEN_VLC_PLAYER,
payload
)
);
request.trackLaunch(launch);
void launch;
}
private toLiveEpgPanelSummary(
@@ -1110,7 +1115,10 @@ export class VideoPlayerComponent implements OnInit, OnDestroy {
return null;
}
return `${session.id}:${session.status}`;
const lifecycle = isLiveExternalPlayerSession(session)
? 'live'
: 'terminal';
return `${session.id}:${session.status}:${lifecycle}`;
}
private isExternalPlayer(
@@ -1122,7 +1130,7 @@ export class VideoPlayerComponent implements OnInit, OnDestroy {
private isTerminalExternalSession(
session: ExternalPlayerSession | null | undefined
): boolean {
return session?.status === 'closed' || session?.status === 'error';
return !!session && !isLiveExternalPlayerSession(session);
}
private registerHeaderShortcut(): void {