mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-08 09:01:03 -08:00
fix(stalker): lazy load live tv channels
Entire-Checkpoint: c6e522b4276c
This commit is contained in:
1 parent
16fede1180
commit
10139955e7
3 files changed
+111
-9
No files matched your search
+73
@@ -224,6 +224,79 @@ describe('withStalkerContent failure states', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('loads live TV channels page by page and appends later pages', async () => {
|
||||
dataService.sendIpcEvent.mockImplementation(
|
||||
(_event: unknown, payload: { params?: { p?: number } }) => {
|
||||
const page = Number(payload.params?.p ?? 1);
|
||||
|
||||
return Promise.resolve({
|
||||
js: {
|
||||
data: [
|
||||
{
|
||||
id: `channel-${page}`,
|
||||
name: `Channel page ${page}`,
|
||||
category_id: '5',
|
||||
},
|
||||
],
|
||||
total_items: 2,
|
||||
},
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
store.setSelectedContentType('itv');
|
||||
store.setCategories('itv', [
|
||||
{
|
||||
category_id: '5',
|
||||
category_name: 'News',
|
||||
},
|
||||
]);
|
||||
store.setSelectedCategory('5');
|
||||
store.setCurrentPlaylist(PLAYLIST);
|
||||
void store.isPaginatedContentLoading();
|
||||
|
||||
await waitForCondition(() => store.itvChannels().length === 1);
|
||||
|
||||
expect(dataService.sendIpcEvent).toHaveBeenLastCalledWith(
|
||||
expect.anything(),
|
||||
expect.objectContaining({
|
||||
params: expect.objectContaining({
|
||||
action: StalkerPortalActions.GetOrderedList,
|
||||
type: 'itv',
|
||||
category: '5',
|
||||
genre: '5',
|
||||
p: 1,
|
||||
}),
|
||||
})
|
||||
);
|
||||
expect(store.itvChannels().map((channel) => channel.name)).toEqual([
|
||||
'Channel page 1',
|
||||
]);
|
||||
expect(store.hasMoreChannels()).toBe(true);
|
||||
|
||||
store.setPage(1);
|
||||
|
||||
await waitForCondition(() => store.itvChannels().length === 2);
|
||||
|
||||
expect(dataService.sendIpcEvent).toHaveBeenLastCalledWith(
|
||||
expect.anything(),
|
||||
expect.objectContaining({
|
||||
params: expect.objectContaining({
|
||||
action: StalkerPortalActions.GetOrderedList,
|
||||
type: 'itv',
|
||||
category: '5',
|
||||
genre: '5',
|
||||
p: 2,
|
||||
}),
|
||||
})
|
||||
);
|
||||
expect(store.itvChannels().map((channel) => channel.name)).toEqual([
|
||||
'Channel page 1',
|
||||
'Channel page 2',
|
||||
]);
|
||||
expect(store.hasMoreChannels()).toBe(false);
|
||||
});
|
||||
|
||||
it('ignores stale content responses after the selected page changes', async () => {
|
||||
const pendingByPage = new Map<
|
||||
number,
|
||||
|
||||
+29
-3
@@ -116,12 +116,14 @@ describe('StalkerLiveStreamLayoutComponent', () => {
|
||||
const bulkItvEpgPlaylistId = signal<string | null>(null);
|
||||
const bulkItvEpgPeriodHours = signal<number | null>(null);
|
||||
const isLoadingBulkItvEpg = signal(false);
|
||||
const hasMoreChannels = signal(false);
|
||||
const page = signal(0);
|
||||
|
||||
const stalkerStore = {
|
||||
getSelectedCategoryName: signal('News'),
|
||||
itvChannels,
|
||||
searchPhrase,
|
||||
hasMoreChannels: signal(false),
|
||||
hasMoreChannels,
|
||||
selectedItvId,
|
||||
currentPlaylist: playlist,
|
||||
selectedItvEpgPrograms,
|
||||
@@ -133,7 +135,7 @@ describe('StalkerLiveStreamLayoutComponent', () => {
|
||||
selectedCategoryId,
|
||||
selectedItem,
|
||||
selectedContentType: signal<'itv' | 'vod' | 'series'>('itv'),
|
||||
page: signal(0),
|
||||
page,
|
||||
setItvChannels: jest.fn(),
|
||||
setPage: jest.fn(),
|
||||
setSelectedItem: jest.fn((item) => {
|
||||
@@ -180,6 +182,8 @@ describe('StalkerLiveStreamLayoutComponent', () => {
|
||||
bulkItvEpgPlaylistId.set(null);
|
||||
bulkItvEpgPeriodHours.set(null);
|
||||
isLoadingBulkItvEpg.set(false);
|
||||
hasMoreChannels.set(false);
|
||||
page.set(0);
|
||||
|
||||
resolveItvPlayback.mockReset();
|
||||
resolveItvPlayback.mockResolvedValue({
|
||||
@@ -202,7 +206,14 @@ describe('StalkerLiveStreamLayoutComponent', () => {
|
||||
);
|
||||
});
|
||||
stalkerStore.setItvChannels.mockClear();
|
||||
stalkerStore.setPage.mockClear();
|
||||
stalkerStore.setPage.mockReset();
|
||||
stalkerStore.setPage.mockImplementation((nextPage: number) => {
|
||||
if (page() === nextPage) {
|
||||
return;
|
||||
}
|
||||
|
||||
page.set(nextPage);
|
||||
});
|
||||
stalkerStore.setSelectedItem.mockClear();
|
||||
stalkerStore.clearBulkItvEpgCache.mockClear();
|
||||
|
||||
@@ -272,6 +283,21 @@ describe('StalkerLiveStreamLayoutComponent', () => {
|
||||
).toBeNull();
|
||||
});
|
||||
|
||||
it('does not reset live channels when loading the next lazy page', async () => {
|
||||
hasMoreChannels.set(true);
|
||||
fixture.detectChanges();
|
||||
await fixture.whenStable();
|
||||
stalkerStore.setItvChannels.mockClear();
|
||||
stalkerStore.setPage.mockClear();
|
||||
|
||||
component.loadMore();
|
||||
await fixture.whenStable();
|
||||
|
||||
expect(page()).toBe(1);
|
||||
expect(stalkerStore.setPage).toHaveBeenCalledWith(1);
|
||||
expect(stalkerStore.setItvChannels).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('keeps row previews empty before bulk epg is loaded', async () => {
|
||||
fixture.detectChanges();
|
||||
await fixture.whenStable();
|
||||
|
||||
+9
-6
@@ -8,6 +8,7 @@ import {
|
||||
inject,
|
||||
OnDestroy,
|
||||
signal,
|
||||
untracked,
|
||||
viewChild,
|
||||
} from '@angular/core';
|
||||
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
||||
@@ -183,12 +184,14 @@ export class StalkerLiveStreamLayoutComponent implements OnDestroy {
|
||||
// Reset channels/page on category change
|
||||
effect(() => {
|
||||
this.stalkerStore.selectedCategoryId();
|
||||
this.stalkerStore.setItvChannels([]);
|
||||
this.stalkerStore.setPage(0);
|
||||
this.clearEpgPreviewMaps();
|
||||
this.epgLoadRequestId += 1;
|
||||
this.fallbackEpgPrograms.set([]);
|
||||
this.isLoadingFallbackEpg.set(false);
|
||||
untracked(() => {
|
||||
this.stalkerStore.setItvChannels([]);
|
||||
this.stalkerStore.setPage(0);
|
||||
this.clearEpgPreviewMaps();
|
||||
this.epgLoadRequestId += 1;
|
||||
this.fallbackEpgPrograms.set([]);
|
||||
this.isLoadingFallbackEpg.set(false);
|
||||
});
|
||||
});
|
||||
|
||||
// Reset loading state when channels load and keep preview data in sync with bulk EPG.
|
||||
|
||||
Reference in new issue
Block a user