Files
iptvnator/apps/web/src/app/xtream-tauri/with-recent-items.ts
T

131 lines
5.0 KiB
TypeScript

import { inject, Signal } from '@angular/core';
import {
patchState,
signalStoreFeature,
withMethods,
withState,
} from '@ngrx/signals';
import { rxMethod } from '@ngrx/signals/rxjs-interop';
import { pipe, switchMap, tap } from 'rxjs';
import { DatabaseService } from 'services';
export interface RecentlyViewedItem {
id: number;
title: string;
type: 'live' | 'movie' | 'series';
poster_url: string;
content_id: number;
playlist_id: string;
viewed_at: string;
xtream_id: number;
category_id: number;
}
export const withRecentItems = function () {
return signalStoreFeature(
withState({
recentItems: [],
}),
withMethods((store, dbService = inject(DatabaseService)) => ({
loadRecentItems: rxMethod<{ id: string }>(
pipe(
switchMap(async (playlist) => {
const items = await dbService.getRecentItems(
playlist.id
);
// Map to RecentlyViewedItem format
return items.map((item) => ({
id: item.id,
title: item.title,
type: item.type as 'live' | 'movie' | 'series',
poster_url: item.poster_url,
content_id: item.id,
playlist_id: playlist.id,
viewed_at: item.viewed_at || '',
xtream_id: item.xtream_id,
category_id: item.category_id,
}));
}),
tap((items: RecentlyViewedItem[]) =>
patchState(store, { recentItems: items })
)
)
),
})),
withMethods((store, dbService = inject(DatabaseService)) => ({
addRecentItem: rxMethod<{
contentId: number;
playlist: Signal<{ id: string }>;
}>(
pipe(
switchMap(async ({ contentId, playlist }) => {
// contentId is actually xtream_id, need to look up the database content.id
const content = await dbService.getContentByXtreamId(
contentId,
playlist().id
);
if (content) {
await dbService.addRecentItem(
content.id,
playlist().id
);
}
})
)
),
clearRecentItems: rxMethod<{ id: string }>(
pipe(
switchMap(async (playlist) => {
await dbService.clearPlaylistRecentItems(playlist.id);
patchState(store, { recentItems: [] });
})
)
),
removeRecentItem: rxMethod<{ itemId: number; playlistId: string }>(
pipe(
switchMap(async ({ itemId, playlistId }) => {
await dbService.removeRecentItem(itemId, playlistId);
// Reload recent items to update UI
const items =
await dbService.getRecentItems(playlistId);
const mappedItems = items.map((item) => ({
id: item.id,
title: item.title,
type: item.type as 'live' | 'movie' | 'series',
poster_url: item.poster_url,
content_id: item.id,
playlist_id: playlistId,
viewed_at: item.viewed_at || '',
xtream_id: item.xtream_id,
category_id: item.category_id,
}));
patchState(store, { recentItems: mappedItems });
})
)
),
async loadGlobalRecentItems() {
try {
const items = await dbService.getGlobalRecentlyViewed();
patchState(store, {
recentItems: items || [],
});
} catch (error) {
console.error('Error loading global recent items:', error);
patchState(store, { recentItems: [] });
}
},
async clearGlobalRecentlyViewed() {
try {
await dbService.clearGlobalRecentlyViewed();
patchState(store, { recentItems: [] });
} catch (error) {
console.error(
'Error clearing global recently viewed:',
error
);
}
},
}))
);
};