perf(stalker): skip wasted series-seasons request for non-series items (#1241)

`setSelectedItem` mirrored every selection's id into `selectedSerialId`, and
`serialSeasonsResource` fires a `get_ordered_list&type=series&movie_id=<id>`
portal request on every change of that id. Opening any Stalker detail page —
plain VOD, vclub items with embedded `series[]` (whose result
`mapRegularSeriesSeasons` discards), Ministra `is_series` items, and ITV
channel clicks — therefore issued a pointless request, on every entry path
(browse, favorites, recent, dashboard, search).

Set `selectedSerialId` only when `selectedContentType === 'series'`, clearing
it otherwise. The gate is deliberately on content type alone, not item shape:
under the `series` content type `serialSeasonsResource` is the only episode
source (the detail templates render `<app-stalker-series-view />` with no
`vodWithSeries` input, and `isVodSeries()` requires content type `vod`), so
gating on `is_series`/`series[]` would leave a series-section item carrying
either field with a silently empty episode list.

Adds selection-state and request-level regression coverage, and corrects a
stale invariant in the Stalker architecture docs.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
4grayandClaude Fable 5 authored and GitHub committed 2026-07-25 16:54:30 +02:00
1 parent 14a658f608
commit 4d63f76407
5 files changed
+338 -4

No files matched your search

+8
View File
@@ -271,6 +271,14 @@ Stalker has multiple real-world data shapes. The current implementation supports
- Seasons come from API resource (`serialSeasonsResource`).
- Episodes are derived from season payload.
- This is the only mode that sets `selectedSerialId`, which is what drives
`serialSeasonsResource`. It is set purely from `selectedContentType ===
'series'` — the `series` detail branch renders `<app-stalker-series-view />`
with no `vodWithSeries` input, so the API resource is its only episode
source and the fetch must never be gated on item shape.
- Modes 2 and 3 below are always opened under the `vod` content type, which
leaves the id unset — otherwise every VOD detail open would fire a
`get_ordered_list&type=series` request whose result is discarded.
2. VOD with Embedded `series[]`:
@@ -123,7 +123,15 @@ Consumer directories sampled:
## Invariants to Preserve During Refactor
- Selection IDs (`selectedVodId`, `selectedSerialId`, `selectedItvId`) are synchronized in `setSelectedItem`.
- Selection IDs (`selectedVodId`, `selectedItvId`) are synchronized in `setSelectedItem`.
- `selectedSerialId` is set only when `selectedContentType` is `series`, and is
cleared for every other content type. `serialSeasonsResource` fires a
`get_ordered_list&type=series` portal request on each change of that id, and
it is the only episode source for a `series` selection — while VOD-context
shapes (embedded `series[]`, Ministra `is_series`) resolve their episodes
elsewhere, so carrying the id there only wastes a request. The gate must stay
on content type alone: gating it on item shape would leave a series-section
item that happens to carry `is_series`/`series[]` with an empty episode list.
- `setSelectedCategory(...)` resets `page` to `0`.
- `getPaginatedContent()` and `getCategoryResource()` always return arrays,
even when the underlying request fails.