From 87dfaec03d7087ba4aaa8bd03f00e5aca90119ea Mon Sep 17 00:00:00 2001 From: 4gray Date: Thu, 21 May 2026 20:33:02 +0300 Subject: [PATCH] fix(pwa): filter stalker from xtream collections --- .../unified-favorites-data.service.spec.ts | 28 ++++++++++++++++++ .../unified-favorites-data.service.ts | 10 ++++++- .../unified-recent-data.service.spec.ts | 29 +++++++++++++++++++ .../collection/unified-recent-data.service.ts | 2 +- 4 files changed, 67 insertions(+), 2 deletions(-) diff --git a/libs/portal/shared/data-access/src/lib/collection/unified-favorites-data.service.spec.ts b/libs/portal/shared/data-access/src/lib/collection/unified-favorites-data.service.spec.ts index 66c182087..79f3a90d8 100644 --- a/libs/portal/shared/data-access/src/lib/collection/unified-favorites-data.service.spec.ts +++ b/libs/portal/shared/data-access/src/lib/collection/unified-favorites-data.service.spec.ts @@ -286,6 +286,34 @@ describe('UnifiedFavoritesDataService', () => { ]); }); + it('does not load Stalker portals through the PWA Xtream global favorites path', async () => { + Object.defineProperty(window, 'electron', { + value: undefined, + configurable: true, + }); + store.select.mockReturnValue( + of([ + { + _id: 'xtream-1', + title: 'Xtream PWA', + serverUrl: 'https://xtream.example.com', + }, + { + _id: 'stalker-1', + title: 'Stalker Portal', + serverUrl: 'https://stalker.example.com', + macAddress: '00:11:22:33:44:55', + favorites: stalkerFavorites, + }, + ] satisfies Partial[]) + ); + + await service.getFavorites('all'); + + expect(xtreamDataSource.getFavorites).toHaveBeenCalledTimes(1); + expect(xtreamDataSource.getFavorites).toHaveBeenCalledWith('xtream-1'); + }); + it('preserves persisted M3U favorites order when extracting playlist favorites', async () => { playlistsService.getPlaylistById.mockReturnValue( of({ diff --git a/libs/portal/shared/data-access/src/lib/collection/unified-favorites-data.service.ts b/libs/portal/shared/data-access/src/lib/collection/unified-favorites-data.service.ts index a623ffbb9..ee40affa2 100644 --- a/libs/portal/shared/data-access/src/lib/collection/unified-favorites-data.service.ts +++ b/libs/portal/shared/data-access/src/lib/collection/unified-favorites-data.service.ts @@ -517,7 +517,9 @@ export class UnifiedFavoritesDataService { if (!window.electron) { const allMeta = await this.getAllMeta(); const results: UnifiedCollectionItem[] = []; - for (const meta of allMeta.filter((p) => p._id && p.serverUrl)) { + for (const meta of allMeta.filter( + (p) => p._id && this.isXtreamPlaylist(p) + )) { results.push( ...(await this.getXtreamPlaylistFavorites(meta._id)) ); @@ -824,6 +826,12 @@ export class UnifiedFavoritesDataService { }, new Map()); } + private isXtreamPlaylist( + playlist: Pick + ): boolean { + return Boolean(playlist.serverUrl) && !playlist.macAddress; + } + private getStalkerFavoriteId( favorite: | Pick diff --git a/libs/portal/shared/data-access/src/lib/collection/unified-recent-data.service.spec.ts b/libs/portal/shared/data-access/src/lib/collection/unified-recent-data.service.spec.ts index 59526df28..017b3fc8a 100644 --- a/libs/portal/shared/data-access/src/lib/collection/unified-recent-data.service.spec.ts +++ b/libs/portal/shared/data-access/src/lib/collection/unified-recent-data.service.spec.ts @@ -398,6 +398,35 @@ describe('UnifiedRecentDataService', () => { ]); }); + it('does not load Stalker portals through the PWA Xtream global recent path', async () => { + Object.defineProperty(window, 'electron', { + value: undefined, + configurable: true, + }); + store.select.mockReturnValue( + of([ + { + _id: 'xtream-1', + title: 'Xtream PWA', + serverUrl: 'https://xtream.example.com', + }, + { + _id: 'stalker-1', + title: 'Stalker Portal', + serverUrl: 'https://stalker.example.com', + macAddress: '00:11:22:33:44:55', + }, + ] satisfies Partial[]) + ); + + await service.getRecentItems('all'); + + expect(xtreamDataSource.getRecentItems).toHaveBeenCalledTimes(1); + expect(xtreamDataSource.getRecentItems).toHaveBeenCalledWith( + 'xtream-1' + ); + }); + it('clears Xtream recent localStorage during global PWA clear', async () => { Object.defineProperty(window, 'electron', { value: undefined, diff --git a/libs/portal/shared/data-access/src/lib/collection/unified-recent-data.service.ts b/libs/portal/shared/data-access/src/lib/collection/unified-recent-data.service.ts index 3111261bb..163c59653 100644 --- a/libs/portal/shared/data-access/src/lib/collection/unified-recent-data.service.ts +++ b/libs/portal/shared/data-access/src/lib/collection/unified-recent-data.service.ts @@ -354,7 +354,7 @@ export class UnifiedRecentDataService { const allMeta = await this.getAllMeta(); const results: UnifiedCollectionItem[] = []; for (const meta of allMeta.filter( - (playlist) => playlist._id && playlist.serverUrl + (playlist) => playlist._id && this.isXtreamPlaylist(playlist) )) { results.push(...(await this.getXtreamPlaylistRecent(meta._id))); }