mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-08 17:06:15 -08:00
Merge pull request #978 from 4gray/agent/playback-view-runtime-capabilities
refactor(playback): use runtime capability for external fallback
This commit is contained in:
20 files changed
+36
-46
No files matched your search
@@ -408,7 +408,7 @@
|
||||
"BROWSER_ACCESS_ERROR": {
|
||||
"TITLE": "The browser player could not access this stream",
|
||||
"DESCRIPTION": "The request may be blocked by CORS, mixed content, or provider header/proxy restrictions. MPV or VLC can often bypass browser-player access limits.",
|
||||
"PWA_DESCRIPTION": "The request may be blocked by CORS, mixed content, or provider header/proxy restrictions. Copy the stream URL and open it manually in an external player such as MPV, VLC, or IINA to bypass browser-player access limits."
|
||||
"PWA_DESCRIPTION": "The request may be blocked by CORS, mixed content, or provider header/proxy restrictions. The PWA cannot launch external players directly; use the Copy stream URL action and open it manually in MPV, VLC, IINA, or another player."
|
||||
},
|
||||
"DRM_OR_ENCRYPTION": {
|
||||
"TITLE": "This stream may be encrypted or DRM-protected",
|
||||
|
||||
@@ -408,7 +408,7 @@
|
||||
"BROWSER_ACCESS_ERROR": {
|
||||
"TITLE": "The browser player could not access this stream",
|
||||
"DESCRIPTION": "The request may be blocked by CORS, mixed content, or provider header/proxy restrictions. MPV or VLC can often bypass browser-player access limits.",
|
||||
"PWA_DESCRIPTION": "The request may be blocked by CORS, mixed content, or provider header/proxy restrictions. Copy the stream URL and open it manually in an external player such as MPV, VLC, or IINA to bypass browser-player access limits."
|
||||
"PWA_DESCRIPTION": "The request may be blocked by CORS, mixed content, or provider header/proxy restrictions. The PWA cannot launch external players directly; use the Copy stream URL action and open it manually in MPV, VLC, IINA, or another player."
|
||||
},
|
||||
"DRM_OR_ENCRYPTION": {
|
||||
"TITLE": "This stream may be encrypted or DRM-protected",
|
||||
|
||||
@@ -408,7 +408,7 @@
|
||||
"BROWSER_ACCESS_ERROR": {
|
||||
"TITLE": "The browser player could not access this stream",
|
||||
"DESCRIPTION": "The request may be blocked by CORS, mixed content, or provider header/proxy restrictions. MPV or VLC can often bypass browser-player access limits.",
|
||||
"PWA_DESCRIPTION": "The request may be blocked by CORS, mixed content, or provider header/proxy restrictions. Copy the stream URL and open it manually in an external player such as MPV, VLC, or IINA to bypass browser-player access limits."
|
||||
"PWA_DESCRIPTION": "The request may be blocked by CORS, mixed content, or provider header/proxy restrictions. The PWA cannot launch external players directly; use the Copy stream URL action and open it manually in MPV, VLC, IINA, or another player."
|
||||
},
|
||||
"DRM_OR_ENCRYPTION": {
|
||||
"TITLE": "This stream may be encrypted or DRM-protected",
|
||||
|
||||
@@ -408,7 +408,7 @@
|
||||
"BROWSER_ACCESS_ERROR": {
|
||||
"TITLE": "The browser player could not access this stream",
|
||||
"DESCRIPTION": "The request may be blocked by CORS, mixed content, or provider header/proxy restrictions. MPV or VLC can often bypass browser-player access limits.",
|
||||
"PWA_DESCRIPTION": "The request may be blocked by CORS, mixed content, or provider header/proxy restrictions. Copy the stream URL and open it manually in an external player such as MPV, VLC, or IINA to bypass browser-player access limits."
|
||||
"PWA_DESCRIPTION": "The request may be blocked by CORS, mixed content, or provider header/proxy restrictions. The PWA cannot launch external players directly; use the Copy stream URL action and open it manually in MPV, VLC, IINA, or another player."
|
||||
},
|
||||
"DRM_OR_ENCRYPTION": {
|
||||
"TITLE": "This stream may be encrypted or DRM-protected",
|
||||
|
||||
@@ -408,7 +408,7 @@
|
||||
"BROWSER_ACCESS_ERROR": {
|
||||
"TITLE": "The browser player could not access this stream",
|
||||
"DESCRIPTION": "The request may be blocked by CORS, mixed content, or provider header/proxy restrictions. MPV or VLC can often bypass browser-player access limits.",
|
||||
"PWA_DESCRIPTION": "The request may be blocked by CORS, mixed content, or provider header/proxy restrictions. Copy the stream URL and open it manually in an external player such as MPV, VLC, or IINA to bypass browser-player access limits."
|
||||
"PWA_DESCRIPTION": "The request may be blocked by CORS, mixed content, or provider header/proxy restrictions. The PWA cannot launch external players directly; use the Copy stream URL action and open it manually in MPV, VLC, IINA, or another player."
|
||||
},
|
||||
"DRM_OR_ENCRYPTION": {
|
||||
"TITLE": "This stream may be encrypted or DRM-protected",
|
||||
|
||||
@@ -408,7 +408,7 @@
|
||||
"BROWSER_ACCESS_ERROR": {
|
||||
"TITLE": "The browser player could not access this stream",
|
||||
"DESCRIPTION": "The request may be blocked by CORS, mixed content, or provider header/proxy restrictions. MPV or VLC can often bypass browser-player access limits.",
|
||||
"PWA_DESCRIPTION": "The request may be blocked by CORS, mixed content, or provider header/proxy restrictions. Copy the stream URL and open it manually in an external player such as MPV, VLC, or IINA to bypass browser-player access limits."
|
||||
"PWA_DESCRIPTION": "The request may be blocked by CORS, mixed content, or provider header/proxy restrictions. The PWA cannot launch external players directly; use the Copy stream URL action and open it manually in MPV, VLC, IINA, or another player."
|
||||
},
|
||||
"DRM_OR_ENCRYPTION": {
|
||||
"TITLE": "This stream may be encrypted or DRM-protected",
|
||||
|
||||
@@ -408,7 +408,7 @@
|
||||
"BROWSER_ACCESS_ERROR": {
|
||||
"TITLE": "The browser player could not access this stream",
|
||||
"DESCRIPTION": "The request may be blocked by CORS, mixed content, or provider header/proxy restrictions. MPV or VLC can often bypass browser-player access limits.",
|
||||
"PWA_DESCRIPTION": "The request may be blocked by CORS, mixed content, or provider header/proxy restrictions. Copy the stream URL and open it manually in an external player such as MPV, VLC, or IINA to bypass browser-player access limits."
|
||||
"PWA_DESCRIPTION": "The request may be blocked by CORS, mixed content, or provider header/proxy restrictions. The PWA cannot launch external players directly; use the Copy stream URL action and open it manually in MPV, VLC, IINA, or another player."
|
||||
},
|
||||
"DRM_OR_ENCRYPTION": {
|
||||
"TITLE": "This stream may be encrypted or DRM-protected",
|
||||
|
||||
@@ -408,7 +408,7 @@
|
||||
"BROWSER_ACCESS_ERROR": {
|
||||
"TITLE": "The browser player could not access this stream",
|
||||
"DESCRIPTION": "The request may be blocked by CORS, mixed content, or provider header/proxy restrictions. MPV or VLC can often bypass browser-player access limits.",
|
||||
"PWA_DESCRIPTION": "The request may be blocked by CORS, mixed content, or provider header/proxy restrictions. Copy the stream URL and open it manually in an external player such as MPV, VLC, or IINA to bypass browser-player access limits."
|
||||
"PWA_DESCRIPTION": "The request may be blocked by CORS, mixed content, or provider header/proxy restrictions. The PWA cannot launch external players directly; use the Copy stream URL action and open it manually in MPV, VLC, IINA, or another player."
|
||||
},
|
||||
"DRM_OR_ENCRYPTION": {
|
||||
"TITLE": "This stream may be encrypted or DRM-protected",
|
||||
|
||||
@@ -408,7 +408,7 @@
|
||||
"BROWSER_ACCESS_ERROR": {
|
||||
"TITLE": "The browser player could not access this stream",
|
||||
"DESCRIPTION": "The request may be blocked by CORS, mixed content, or provider header/proxy restrictions. MPV or VLC can often bypass browser-player access limits.",
|
||||
"PWA_DESCRIPTION": "The request may be blocked by CORS, mixed content, or provider header/proxy restrictions. Copy the stream URL and open it manually in an external player such as MPV, VLC, or IINA to bypass browser-player access limits."
|
||||
"PWA_DESCRIPTION": "The request may be blocked by CORS, mixed content, or provider header/proxy restrictions. The PWA cannot launch external players directly; use the Copy stream URL action and open it manually in MPV, VLC, IINA, or another player."
|
||||
},
|
||||
"DRM_OR_ENCRYPTION": {
|
||||
"TITLE": "This stream may be encrypted or DRM-protected",
|
||||
|
||||
@@ -408,7 +408,7 @@
|
||||
"BROWSER_ACCESS_ERROR": {
|
||||
"TITLE": "The browser player could not access this stream",
|
||||
"DESCRIPTION": "The request may be blocked by CORS, mixed content, or provider header/proxy restrictions. MPV or VLC can often bypass browser-player access limits.",
|
||||
"PWA_DESCRIPTION": "The request may be blocked by CORS, mixed content, or provider header/proxy restrictions. Copy the stream URL and open it manually in an external player such as MPV, VLC, or IINA to bypass browser-player access limits."
|
||||
"PWA_DESCRIPTION": "The request may be blocked by CORS, mixed content, or provider header/proxy restrictions. The PWA cannot launch external players directly; use the Copy stream URL action and open it manually in MPV, VLC, IINA, or another player."
|
||||
},
|
||||
"DRM_OR_ENCRYPTION": {
|
||||
"TITLE": "This stream may be encrypted or DRM-protected",
|
||||
|
||||
@@ -408,7 +408,7 @@
|
||||
"BROWSER_ACCESS_ERROR": {
|
||||
"TITLE": "The browser player could not access this stream",
|
||||
"DESCRIPTION": "The request may be blocked by CORS, mixed content, or provider header/proxy restrictions. MPV or VLC can often bypass browser-player access limits.",
|
||||
"PWA_DESCRIPTION": "The request may be blocked by CORS, mixed content, or provider header/proxy restrictions. Copy the stream URL and open it manually in an external player such as MPV, VLC, or IINA to bypass browser-player access limits."
|
||||
"PWA_DESCRIPTION": "The request may be blocked by CORS, mixed content, or provider header/proxy restrictions. The PWA cannot launch external players directly; use the Copy stream URL action and open it manually in MPV, VLC, IINA, or another player."
|
||||
},
|
||||
"DRM_OR_ENCRYPTION": {
|
||||
"TITLE": "This stream may be encrypted or DRM-protected",
|
||||
|
||||
@@ -408,7 +408,7 @@
|
||||
"BROWSER_ACCESS_ERROR": {
|
||||
"TITLE": "The browser player could not access this stream",
|
||||
"DESCRIPTION": "The request may be blocked by CORS, mixed content, or provider header/proxy restrictions. MPV or VLC can often bypass browser-player access limits.",
|
||||
"PWA_DESCRIPTION": "The request may be blocked by CORS, mixed content, or provider header/proxy restrictions. Copy the stream URL and open it manually in an external player such as MPV, VLC, or IINA to bypass browser-player access limits."
|
||||
"PWA_DESCRIPTION": "The request may be blocked by CORS, mixed content, or provider header/proxy restrictions. The PWA cannot launch external players directly; use the Copy stream URL action and open it manually in MPV, VLC, IINA, or another player."
|
||||
},
|
||||
"DRM_OR_ENCRYPTION": {
|
||||
"TITLE": "This stream may be encrypted or DRM-protected",
|
||||
|
||||
@@ -408,7 +408,7 @@
|
||||
"BROWSER_ACCESS_ERROR": {
|
||||
"TITLE": "The browser player could not access this stream",
|
||||
"DESCRIPTION": "The request may be blocked by CORS, mixed content, or provider header/proxy restrictions. MPV or VLC can often bypass browser-player access limits.",
|
||||
"PWA_DESCRIPTION": "The request may be blocked by CORS, mixed content, or provider header/proxy restrictions. Copy the stream URL and open it manually in an external player such as MPV, VLC, or IINA to bypass browser-player access limits."
|
||||
"PWA_DESCRIPTION": "The request may be blocked by CORS, mixed content, or provider header/proxy restrictions. The PWA cannot launch external players directly; use the Copy stream URL action and open it manually in MPV, VLC, IINA, or another player."
|
||||
},
|
||||
"DRM_OR_ENCRYPTION": {
|
||||
"TITLE": "This stream may be encrypted or DRM-protected",
|
||||
|
||||
@@ -408,7 +408,7 @@
|
||||
"BROWSER_ACCESS_ERROR": {
|
||||
"TITLE": "The browser player could not access this stream",
|
||||
"DESCRIPTION": "The request may be blocked by CORS, mixed content, or provider header/proxy restrictions. MPV or VLC can often bypass browser-player access limits.",
|
||||
"PWA_DESCRIPTION": "The request may be blocked by CORS, mixed content, or provider header/proxy restrictions. Copy the stream URL and open it manually in an external player such as MPV, VLC, or IINA to bypass browser-player access limits."
|
||||
"PWA_DESCRIPTION": "The request may be blocked by CORS, mixed content, or provider header/proxy restrictions. The PWA cannot launch external players directly; use the Copy stream URL action and open it manually in MPV, VLC, IINA, or another player."
|
||||
},
|
||||
"DRM_OR_ENCRYPTION": {
|
||||
"TITLE": "This stream may be encrypted or DRM-protected",
|
||||
|
||||
@@ -408,7 +408,7 @@
|
||||
"BROWSER_ACCESS_ERROR": {
|
||||
"TITLE": "Браузерный плеер не получил доступ к потоку",
|
||||
"DESCRIPTION": "Запрос может быть заблокирован CORS, mixed content или требованиями провайдера/прокси к заголовкам. MPV или VLC часто обходят такие ограничения браузерного плеера.",
|
||||
"PWA_DESCRIPTION": "Запрос может быть заблокирован CORS, mixed content или требованиями провайдера/прокси к заголовкам. Скопируйте URL потока и откройте его вручную во внешнем плеере, например MPV, VLC или IINA."
|
||||
"PWA_DESCRIPTION": "Запрос может быть заблокирован CORS, mixed content или требованиями провайдера/прокси к заголовкам. PWA не может запускать внешние плееры напрямую: нажмите «Скопировать URL потока» и откройте его вручную в MPV, VLC, IINA или другом плеере."
|
||||
},
|
||||
"DRM_OR_ENCRYPTION": {
|
||||
"TITLE": "Поток может быть зашифрован или защищен DRM",
|
||||
|
||||
@@ -408,7 +408,7 @@
|
||||
"BROWSER_ACCESS_ERROR": {
|
||||
"TITLE": "The browser player could not access this stream",
|
||||
"DESCRIPTION": "The request may be blocked by CORS, mixed content, or provider header/proxy restrictions. MPV or VLC can often bypass browser-player access limits.",
|
||||
"PWA_DESCRIPTION": "The request may be blocked by CORS, mixed content, or provider header/proxy restrictions. Copy the stream URL and open it manually in an external player such as MPV, VLC, or IINA to bypass browser-player access limits."
|
||||
"PWA_DESCRIPTION": "The request may be blocked by CORS, mixed content, or provider header/proxy restrictions. The PWA cannot launch external players directly; use the Copy stream URL action and open it manually in MPV, VLC, IINA, or another player."
|
||||
},
|
||||
"DRM_OR_ENCRYPTION": {
|
||||
"TITLE": "This stream may be encrypted or DRM-protected",
|
||||
|
||||
@@ -408,7 +408,7 @@
|
||||
"BROWSER_ACCESS_ERROR": {
|
||||
"TITLE": "The browser player could not access this stream",
|
||||
"DESCRIPTION": "The request may be blocked by CORS, mixed content, or provider header/proxy restrictions. MPV or VLC can often bypass browser-player access limits.",
|
||||
"PWA_DESCRIPTION": "The request may be blocked by CORS, mixed content, or provider header/proxy restrictions. Copy the stream URL and open it manually in an external player such as MPV, VLC, or IINA to bypass browser-player access limits."
|
||||
"PWA_DESCRIPTION": "The request may be blocked by CORS, mixed content, or provider header/proxy restrictions. The PWA cannot launch external players directly; use the Copy stream URL action and open it manually in MPV, VLC, IINA, or another player."
|
||||
},
|
||||
"DRM_OR_ENCRYPTION": {
|
||||
"TITLE": "This stream may be encrypted or DRM-protected",
|
||||
|
||||
@@ -408,7 +408,7 @@
|
||||
"BROWSER_ACCESS_ERROR": {
|
||||
"TITLE": "The browser player could not access this stream",
|
||||
"DESCRIPTION": "The request may be blocked by CORS, mixed content, or provider header/proxy restrictions. MPV or VLC can often bypass browser-player access limits.",
|
||||
"PWA_DESCRIPTION": "The request may be blocked by CORS, mixed content, or provider header/proxy restrictions. Copy the stream URL and open it manually in an external player such as MPV, VLC, or IINA to bypass browser-player access limits."
|
||||
"PWA_DESCRIPTION": "The request may be blocked by CORS, mixed content, or provider header/proxy restrictions. The PWA cannot launch external players directly; use the Copy stream URL action and open it manually in MPV, VLC, IINA, or another player."
|
||||
},
|
||||
"DRM_OR_ENCRYPTION": {
|
||||
"TITLE": "This stream may be encrypted or DRM-protected",
|
||||
|
||||
@@ -9,6 +9,7 @@ import { StorageMap } from '@ngx-pwa/local-storage';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { of } from 'rxjs';
|
||||
import { VideoPlayer } from '@iptvnator/shared/interfaces';
|
||||
import { RuntimeCapabilitiesService } from '@iptvnator/services';
|
||||
import type { WebPlayerViewComponent as WebPlayerViewComponentInstance } from './web-player-view.component';
|
||||
import {
|
||||
PlaybackDiagnostic,
|
||||
@@ -79,7 +80,7 @@ describe('WebPlayerViewComponent', () => {
|
||||
const storageMap = {
|
||||
get: jest.fn(() => of({ player: VideoPlayer.VideoJs })),
|
||||
};
|
||||
const originalElectron = window.electron;
|
||||
let runtimeCapabilities: { supportsManagedExternalPlayers: boolean };
|
||||
|
||||
beforeAll(async () => {
|
||||
({ WebPlayerViewComponent } =
|
||||
@@ -87,9 +88,17 @@ describe('WebPlayerViewComponent', () => {
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
runtimeCapabilities = { supportsManagedExternalPlayers: false };
|
||||
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [WebPlayerViewComponent, TranslateModule.forRoot()],
|
||||
providers: [{ provide: StorageMap, useValue: storageMap }],
|
||||
providers: [
|
||||
{ provide: StorageMap, useValue: storageMap },
|
||||
{
|
||||
provide: RuntimeCapabilitiesService,
|
||||
useValue: runtimeCapabilities,
|
||||
},
|
||||
],
|
||||
})
|
||||
.overrideComponent(WebPlayerViewComponent, {
|
||||
set: {
|
||||
@@ -119,7 +128,6 @@ describe('WebPlayerViewComponent', () => {
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
window.electron = originalElectron;
|
||||
fixture.destroy();
|
||||
});
|
||||
|
||||
@@ -129,17 +137,9 @@ describe('WebPlayerViewComponent', () => {
|
||||
expect(fixture.nativeElement.classList).toContain('web-player-view');
|
||||
});
|
||||
|
||||
it('renders diagnostics and emits MPV fallback requests on desktop', () => {
|
||||
it('renders diagnostics and emits MPV fallback requests when managed external players are available', () => {
|
||||
const requests: unknown[] = [];
|
||||
fixture.destroy();
|
||||
window.electron = {} as typeof window.electron;
|
||||
fixture = TestBed.createComponent(WebPlayerViewComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.componentRef.setInput(
|
||||
'streamUrl',
|
||||
'https://example.com/archive/movie.mkv'
|
||||
);
|
||||
fixture.componentRef.setInput('title', 'Example Movie');
|
||||
runtimeCapabilities.supportsManagedExternalPlayers = true;
|
||||
component.externalFallbackRequested.subscribe((request) =>
|
||||
requests.push(request)
|
||||
);
|
||||
@@ -315,14 +315,7 @@ describe('WebPlayerViewComponent', () => {
|
||||
});
|
||||
|
||||
it('keeps the desktop browser access diagnostic description key', () => {
|
||||
fixture.destroy();
|
||||
window.electron = {} as typeof window.electron;
|
||||
fixture = TestBed.createComponent(WebPlayerViewComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.componentRef.setInput(
|
||||
'streamUrl',
|
||||
'https://example.com/archive/movie.mkv'
|
||||
);
|
||||
runtimeCapabilities.supportsManagedExternalPlayers = true;
|
||||
const issue = createBrowserAccessDiagnostic();
|
||||
|
||||
expect(component.getDiagnosticDescriptionKey(issue)).toBe(
|
||||
|
||||
@@ -25,6 +25,7 @@ import {
|
||||
VideoPlayer,
|
||||
} from '@iptvnator/shared/interfaces';
|
||||
import type { ExternalPlayerName } from '@iptvnator/shared/interfaces';
|
||||
import { RuntimeCapabilitiesService } from '@iptvnator/services';
|
||||
import { ArtPlayerComponent } from '../art-player/art-player.component';
|
||||
import { EmbeddedMpvPlayerComponent } from '../embedded-mpv-player/embedded-mpv-player.component';
|
||||
import { HtmlVideoPlayerComponent } from '../html-video-player/html-video-player.component';
|
||||
@@ -64,6 +65,7 @@ type PlaybackDiagnosticDetail = {
|
||||
})
|
||||
export class WebPlayerViewComponent {
|
||||
storage = inject(StorageMap);
|
||||
private readonly runtime = inject(RuntimeCapabilitiesService);
|
||||
|
||||
streamUrl = input.required<string>();
|
||||
title = input('');
|
||||
@@ -89,12 +91,11 @@ export class WebPlayerViewComponent {
|
||||
reloadToken: number;
|
||||
sources: { src: string; type: string }[];
|
||||
};
|
||||
readonly isDesktop = signal(this.detectDesktop());
|
||||
readonly reloadToken = signal(0);
|
||||
readonly playbackDiagnostic = signal<PlaybackDiagnostic | null>(null);
|
||||
readonly canShowExternalFallbackActions = computed(
|
||||
() =>
|
||||
this.isDesktop() &&
|
||||
this.runtime.supportsManagedExternalPlayers &&
|
||||
!!this.playbackDiagnostic()?.externalFallbackRecommended
|
||||
);
|
||||
readonly diagnosticHeadlineKey = computed(() =>
|
||||
@@ -224,7 +225,7 @@ export class WebPlayerViewComponent {
|
||||
getDiagnosticDescriptionKey(issue: PlaybackDiagnostic): string {
|
||||
if (
|
||||
issue.code === PlaybackDiagnosticCode.BrowserAccessError &&
|
||||
!this.isDesktop()
|
||||
!this.runtime.supportsManagedExternalPlayers
|
||||
) {
|
||||
return 'PLAYBACK_DIAGNOSTICS.BROWSER_ACCESS_ERROR.PWA_DESCRIPTION';
|
||||
}
|
||||
@@ -312,10 +313,6 @@ export class WebPlayerViewComponent {
|
||||
}
|
||||
}
|
||||
|
||||
private detectDesktop(): boolean {
|
||||
return typeof window !== 'undefined' && !!window.electron;
|
||||
}
|
||||
|
||||
private isLivePlayback(playback: ResolvedPortalPlayback): boolean {
|
||||
if (typeof playback.isLive === 'boolean') {
|
||||
return playback.isLive;
|
||||
|
||||
Reference in new issue
Block a user