feat(stalker): full Live TV channel list for complete search, count badges, and all-channels grid (#1209)

Load the complete ITV channel list once per portal (Ministra get_all_channels with a paged crawl fallback) and use it for: full local search across every channel, per-genre category count badges, an all-channels paginated grid on Live TV entry, and eager bulk EPG so row previews appear without playing a channel. Censored (adult) genres absent from get_all_channels fall back to the legacy paged flow and show no badge. Includes mock-server support, unit + E2E coverage, and architecture docs.
This commit is contained in:
4gray authored and GitHub committed 2026-07-23 23:31:49 +02:00
1 parent e53adcbeaf
commit b3e130aa65
56 files changed
+3044 -63

No files matched your search

@@ -1596,6 +1596,15 @@ export async function expectWorkspaceSearchStatus(
).toHaveText(expected);
}
/** The degraded-search hint chip must be absent (e.g. complete local search). */
export async function expectNoWorkspaceSearchStatus(
page: Page
): Promise<void> {
await expect(
page.locator('app-workspace-shell-header .search-chip--status')
).toHaveCount(0);
}
async function startPortalDebugCapture(page: Page): Promise<void> {
await page.evaluate(() => {
const electronApi = window.electron as typeof window.electron & {
+9 -13
View File
@@ -6,8 +6,8 @@ import {
closeElectronApp,
defaultStalkerMacAddress,
expect,
expectNoWorkspaceSearchStatus,
expectWorkspaceSearchScope,
expectWorkspaceSearchStatus,
fillWorkspaceSearch,
goToDashboard,
importM3uPlaylistFromNativeDialog,
@@ -987,7 +987,7 @@ test.describe('Electron Workspace Search', () => {
}
});
test('@search @stalker shows loaded-only scope and filters channels on ITV routes', async ({
test('@search @stalker searches the complete channel list on ITV routes', async ({
dataDir,
request,
}) => {
@@ -1030,26 +1030,22 @@ test.describe('Electron Workspace Search', () => {
app.mainWindow,
`Live TV / ${sample.categoryName}`
);
await expectWorkspaceSearchStatus(
app.mainWindow,
'Loaded channels only'
);
// Entering Live TV preloads the COMPLETE channel list (Ministra
// get_all_channels), so search runs locally over every channel:
// no portal-side search request, and no "Loaded channels only"
// degraded hint.
await waitForPortalDebugEvent(app.mainWindow, {
provider: 'stalker',
operation: 'get_ordered_list',
operation: 'get_all_channels',
predicate: (event) => {
const requestPayload = event.request as {
params?: Record<string, string | number>;
};
return (
requestPayload.params?.['type'] === 'itv' &&
String(requestPayload.params?.['category']) ===
sample.categoryId &&
requestPayload.params?.['search'] === itvQuery
);
return requestPayload.params?.['type'] === 'itv';
},
});
await expectNoWorkspaceSearchStatus(app.mainWindow);
await expect(
channelItemByTitle(app.mainWindow, sample.targetTitle).first()
).toBeVisible();