refactor(workspace-shell): use runtime capabilities

This commit is contained in:
4gray committed 2026-05-22 11:54:53 +03:00
1 parent 6211bd2f94
commit f894e5242b
5 files changed
+59 -5

No files matched your search

@@ -18,6 +18,8 @@ describe('RuntimeCapabilitiesService', () => {
expect(service.environment).toBe('pwa');
expect(service.isPwa).toBe(true);
expect(service.isElectron).toBe(false);
expect(service.platform).toBeUndefined();
expect(service.isMacOS).toBe(false);
expect(service.supportsEpg).toBe(false);
expect(service.supportsSqlite).toBe(false);
expect(service.supportsDownloads).toBe(false);
@@ -29,6 +31,7 @@ describe('RuntimeCapabilitiesService', () => {
it('reports Electron capabilities from the available preload bridge methods', () => {
testWindow.electron = {
platform: 'darwin',
dbGetAppPlaylists: jest.fn(),
dbUpsertAppPlaylist: jest.fn(),
dbGetAppState: jest.fn(),
@@ -47,6 +50,8 @@ describe('RuntimeCapabilitiesService', () => {
expect(service.environment).toBe('electron');
expect(service.isElectron).toBe(true);
expect(service.isPwa).toBe(false);
expect(service.platform).toBe('darwin');
expect(service.isMacOS).toBe(true);
expect(service.supportsEpg).toBe(true);
expect(service.supportsSqlite).toBe(true);
expect(service.supportsDownloads).toBe(true);
@@ -64,6 +69,8 @@ describe('RuntimeCapabilitiesService', () => {
const service = new RuntimeCapabilitiesService();
expect(service.environment).toBe('electron');
expect(service.platform).toBeUndefined();
expect(service.isMacOS).toBe(false);
expect(service.supportsEpg).toBe(true);
expect(service.supportsSqlite).toBe(false);
expect(service.supportsDownloads).toBe(false);
@@ -22,6 +22,15 @@ export class RuntimeCapabilitiesService {
return !this.isElectron;
}
get platform(): string | undefined {
const platform = this.electronBridge?.['platform'];
return typeof platform === 'string' ? platform : undefined;
}
get isMacOS(): boolean {
return this.platform === 'darwin';
}
get supportsEpg(): boolean {
return this.isElectron;
}
@@ -4,6 +4,7 @@ import { TranslateService } from '@ngx-translate/core';
import { startWith } from 'rxjs';
import { PlaylistRefreshActionService } from '@iptvnator/playlist/shared/ui';
import { XtreamStore } from '@iptvnator/portal/xtream/data-access';
import { RuntimeCapabilitiesService } from '@iptvnator/services';
import type { XtreamImportPhaseTone } from './helpers/workspace-shell-constants';
import {
buildXtreamImportDetailLabel,
@@ -23,14 +24,18 @@ export class WorkspaceShellXtreamImportService {
private readonly playlistRefreshAction = inject(
PlaylistRefreshActionService
);
private readonly runtime = inject(RuntimeCapabilitiesService);
private readonly translate = inject(TranslateService);
private readonly isElectron = !!window.electron;
private readonly languageTick = toSignal(
this.translate.onLangChange.pipe(startWith(null)),
{ initialValue: null }
);
private get isElectron(): boolean {
return this.runtime.isElectron;
}
private readonly translateText = (
key: string,
params?: Record<string, string | number>
@@ -17,7 +17,11 @@ import {
} from '@iptvnator/portal/shared/util';
import { StalkerStore } from '@iptvnator/portal/stalker/data-access';
import { XtreamStore } from '@iptvnator/portal/xtream/data-access';
import { PlaylistsService, SettingsStore } from '@iptvnator/services';
import {
PlaylistsService,
RuntimeCapabilitiesService,
SettingsStore,
} from '@iptvnator/services';
import { PlaylistMeta } from '@iptvnator/shared/interfaces';
import {
WorkspaceStartupPreferencesService,
@@ -135,10 +139,17 @@ describe('WorkspaceShellFacade', () => {
persistLastRestorablePath: jest.Mock;
showDashboard: jest.Mock;
};
let runtime: {
isElectron: boolean;
isMacOS: boolean;
};
beforeEach(() => {
window.electron = { platform: 'darwin' } as typeof window.electron;
showDashboardSignal = signal(true);
runtime = {
isElectron: true,
isMacOS: true,
};
activePlaylistSignal = signal({
_id: 'pl-1',
@@ -254,6 +265,10 @@ describe('WorkspaceShellFacade', () => {
showExternalPlaybackBar: signal(true),
},
},
{
provide: RuntimeCapabilitiesService,
useValue: runtime,
},
{
provide: PlaylistsService,
useValue: playlistsService,
@@ -322,6 +337,17 @@ describe('WorkspaceShellFacade', () => {
facade = TestBed.inject(WorkspaceShellFacade);
});
it('derives desktop shell flags from runtime capabilities', () => {
expect(facade.isElectron).toBe(true);
expect(facade.isMacOS).toBe(true);
runtime.isElectron = false;
runtime.isMacOS = false;
expect(facade.isElectron).toBe(false);
expect(facade.isMacOS).toBe(false);
});
it('routes dashboard search Enter into the active Xtream playlist search', () => {
const xtreamStore = TestBed.inject(
XtreamStore
@@ -36,6 +36,7 @@ import {
import {
DownloadsService,
PlaylistsService,
RuntimeCapabilitiesService,
SettingsStore,
} from '@iptvnator/services';
import { PlaylistActions, selectAllPlaylistsMeta } from '@iptvnator/m3u-state';
@@ -96,6 +97,7 @@ export class WorkspaceShellFacade {
private readonly playlistRefreshAction = inject(
PlaylistRefreshActionService
);
private readonly runtime = inject(RuntimeCapabilitiesService);
private readonly downloadsService = inject(DownloadsService);
readonly hasActiveDownloads = computed(
() => this.isElectron && this.downloadsService.activeCount() > 0
@@ -137,8 +139,13 @@ export class WorkspaceShellFacade {
readonly searchQuery = signal('');
readonly appliedSearchQuery = signal('');
readonly isElectron = !!window.electron;
readonly isMacOS = window.electron?.platform === 'darwin';
get isElectron(): boolean {
return this.runtime.isElectron;
}
get isMacOS(): boolean {
return this.runtime.isMacOS;
}
readonly currentUrl = signal(this.router.url);
readonly currentRoute = computed(() =>
parseWorkspaceShellRoute(this.currentUrl())