fix(dashboard): remove PWA Xtream items via data source

This commit is contained in:
4gray committed 2026-05-16 00:23:22 +02:00
1 parent 873bb58873
commit c3194db98e
2 files changed
+125 -8

No files matched your search

@@ -392,6 +392,49 @@ describe('DashboardDataService', () => {
);
});
it('removes PWA Xtream favorites through the data source when Electron DB APIs are unavailable', async () => {
Object.defineProperty(window, 'electron', {
value: {} as Window['electron'],
configurable: true,
});
xtreamDataSourceMock.getFavorites
.mockResolvedValueOnce([
{
id: 20203,
stream_id: 20203,
category_id: 206,
title: 'PWA Movie',
type: 'movie',
poster_url: 'https://example.com/pwa-movie.png',
xtream_id: 20203,
added: '1774298340',
},
])
.mockResolvedValueOnce([]);
await service.reloadGlobalFavorites();
const xtreamFavorite = service
.globalFavoriteItems()
.find((item) => item.source === 'xtream');
if (!xtreamFavorite) {
throw new Error('Expected PWA Xtream favorite');
}
await service.removeGlobalFavorite(xtreamFavorite);
expect(dbServiceMock.removeFromFavorites).not.toHaveBeenCalled();
expect(xtreamDataSourceMock.removeFavorite).toHaveBeenCalledWith(
20203,
'xtream-1'
);
expect(
service
.globalFavoriteItems()
.some((item) => item.source === 'xtream')
).toBe(false);
});
it('builds the M3U favorites route', async () => {
await service.reloadGlobalFavorites();
const m3uItem = service
@@ -528,6 +571,47 @@ describe('DashboardDataService', () => {
);
});
it('removes PWA Xtream recent items through the data source when Electron DB APIs are unavailable', async () => {
Object.defineProperty(window, 'electron', {
value: {} as Window['electron'],
configurable: true,
});
xtreamDataSourceMock.getRecentItems
.mockResolvedValueOnce([
{
id: 20203,
stream_id: 20203,
category_id: 206,
title: 'PWA Recent Movie',
type: 'movie',
poster_url: 'https://example.com/pwa-recent.png',
xtream_id: 20203,
viewed_at: '2026-05-15T15:04:54.176Z',
},
])
.mockResolvedValueOnce([]);
await service.reloadGlobalRecentItems();
const xtreamRecent = service
.globalRecentItems()
.find((item) => item.source === 'xtream');
if (!xtreamRecent) {
throw new Error('Expected PWA Xtream recent item');
}
await service.removeGlobalRecentItem(xtreamRecent);
expect(dbServiceMock.removeRecentItem).not.toHaveBeenCalled();
expect(xtreamDataSourceMock.removeRecentItem).toHaveBeenCalledWith(
20203,
'xtream-1'
);
expect(
service.globalRecentItems().some((item) => item.source === 'xtream')
).toBe(false);
});
it('prioritizes recently used Xtream sources over newer imported M3U sources', async () => {
playlistsSignal.set([
{
@@ -612,6 +612,19 @@ export class DashboardDataService {
return typeof window.electron?.dbGetAllGlobalFavorites === 'function';
}
private getXtreamContentId(
item: Pick<PortalActivityItem, 'id' | 'xtream_id'>
): number | null {
for (const candidate of [item.xtream_id, item.id]) {
const value = Number(candidate);
if (Number.isFinite(value) && value > 0) {
return value;
}
}
return null;
}
private async reloadM3uGlobalFavorites(): Promise<void> {
const m3uPlaylists = this.playlists().filter(
(playlist) =>
@@ -770,10 +783,20 @@ export class DashboardDataService {
async removeGlobalRecentItem(item: GlobalRecentItem): Promise<void> {
if (item.source === 'xtream') {
await this.dbService.removeRecentItem(
item.id as number,
item.playlist_id
);
if (this.hasElectronGlobalRecentApi()) {
await this.dbService.removeRecentItem(
item.id as number,
item.playlist_id
);
} else {
const contentId = this.getXtreamContentId(item);
if (contentId != null) {
await this.xtreamDataSource.removeRecentItem(
contentId,
item.playlist_id
);
}
}
await this.reloadGlobalRecentItems();
return;
}
@@ -924,10 +947,20 @@ export class DashboardDataService {
async removeGlobalFavorite(item: DashboardFavoriteItem): Promise<void> {
if (item.source === 'xtream') {
await this.dbService.removeFromFavorites(
item.id as number,
item.playlist_id
);
if (this.hasElectronGlobalFavoritesApi()) {
await this.dbService.removeFromFavorites(
item.id as number,
item.playlist_id
);
} else {
const contentId = this.getXtreamContentId(item);
if (contentId != null) {
await this.xtreamDataSource.removeFavorite(
contentId,
item.playlist_id
);
}
}
await this.reloadGlobalFavorites();
return;
}