From b4fd93354e75e69aeac652cf15208efc6ed2cfbb Mon Sep 17 00:00:00 2001 From: 4gray Date: Fri, 22 May 2026 09:23:36 +0300 Subject: [PATCH] refactor(runtime): enable pwa xtream section navigation --- docs/architecture/pwa-self-hosted.md | 4 +++- .../lib/runtime-capabilities.service.spec.ts | 17 +++++++++++++++-- .../src/lib/runtime-capabilities.service.ts | 6 +++++- 3 files changed, 23 insertions(+), 4 deletions(-) diff --git a/docs/architecture/pwa-self-hosted.md b/docs/architecture/pwa-self-hosted.md index e6c106a29..0b721701e 100644 --- a/docs/architecture/pwa-self-hosted.md +++ b/docs/architecture/pwa-self-hosted.md @@ -74,7 +74,9 @@ from one shared boundary. `supportsSqlite` requires the complete playlist storage preload API surface used by `PlaylistsService`, `supportsDownloads` requires the complete downloads preload API surface used by `DownloadsService`, `supportsPlaylistRefresh` requires the native playlist refresh/cancel/progress -bridge, and +bridge, `supportsXtreamSectionNavigation` is available in PWA and in Electron +when either the SQLite Xtream data source or the Xtream API transport is +available, and `supportsManagedExternalPlayers` requires the MPV and VLC preload launch methods (`openInMpv` and `openInVlc`); a partial Electron bridge must not expose desktop-only actions in the PWA/shared UI. diff --git a/libs/services/src/lib/runtime-capabilities.service.spec.ts b/libs/services/src/lib/runtime-capabilities.service.spec.ts index 7e4f4e1e1..da931fa24 100644 --- a/libs/services/src/lib/runtime-capabilities.service.spec.ts +++ b/libs/services/src/lib/runtime-capabilities.service.spec.ts @@ -30,7 +30,7 @@ describe('RuntimeCapabilitiesService', () => { expect(service.supportsEmbeddedMpv).toBe(false); expect(service.supportsDesktopFileSave).toBe(false); expect(service.supportsRemoteControl).toBe(false); - expect(service.supportsXtreamSectionNavigation).toBe(false); + expect(service.supportsXtreamSectionNavigation).toBe(true); }); it('reports Electron capabilities from the available preload bridge methods', () => { @@ -103,6 +103,7 @@ describe('RuntimeCapabilitiesService', () => { updateRemoteControlStatus: jest.fn(), onChannelChange: jest.fn(), onRemoteControlCommand: jest.fn(), + xtreamRequest: jest.fn(), }; const service = new RuntimeCapabilitiesService(); @@ -145,7 +146,7 @@ describe('RuntimeCapabilitiesService', () => { expect(service.supportsEmbeddedMpv).toBe(false); expect(service.supportsDesktopFileSave).toBe(false); expect(service.supportsRemoteControl).toBe(false); - expect(service.supportsXtreamSectionNavigation).toBe(true); + expect(service.supportsXtreamSectionNavigation).toBe(false); }); it('reads the bridge dynamically so tests and late preload setup stay accurate', () => { @@ -251,6 +252,18 @@ describe('RuntimeCapabilitiesService', () => { expect(service.supportsSqlite).toBe(true); }); + + it('supports Xtream section navigation in Electron when Xtream API transport is available', () => { + testWindow.electron = { + xtreamRequest: jest.fn(), + }; + + const service = new RuntimeCapabilitiesService(); + + expect(service.isElectron).toBe(true); + expect(service.supportsXtreamSqliteDataSource).toBe(false); + expect(service.supportsXtreamSectionNavigation).toBe(true); + }); }); function createPlaylistStorageBridge(): Record { diff --git a/libs/services/src/lib/runtime-capabilities.service.ts b/libs/services/src/lib/runtime-capabilities.service.ts index 6892d8cfa..313b5ce53 100644 --- a/libs/services/src/lib/runtime-capabilities.service.ts +++ b/libs/services/src/lib/runtime-capabilities.service.ts @@ -156,7 +156,11 @@ export class RuntimeCapabilitiesService { } get supportsXtreamSectionNavigation(): boolean { - return this.isElectron; + return ( + this.isPwa || + this.supportsXtreamSqliteDataSource || + this.hasElectronMethod('xtreamRequest') + ); } private hasElectronMethod(methodName: string): boolean {