diff --git a/docs/architecture/embedded-inline-playback.md b/docs/architecture/embedded-inline-playback.md index 38751413c..d03a8e67e 100644 --- a/docs/architecture/embedded-inline-playback.md +++ b/docs/architecture/embedded-inline-playback.md @@ -383,15 +383,17 @@ meanwhile. The host reports busy-state back through the A series-level counterpart lives in a `⋮` menu at the end of the same header row (`SeasonWatchPresenter` in `libs/ui/components` owns the state -math for both scopes; the container component sits at the max-lines cap). +math for both scopes, which keeps the container component under the +max-lines cap). `buildSeriesWatchToggleRequest` flattens every LOADED season with the same mark/unmark semantics, and the direction is always the one the label advertised (`markWatched: !seriesFullyWatched()`), never re-inferred from data at persist time. Hosts route the request through the same machinery as the season toggle — Xtream via the scope-parameterized -`SerialDetailsSeasonWatchService.handle(..., scope)`, Stalker via the -extracted `runWatchToggleBatch` core — sharing the busy flag, the -ownership guards, and the catalog-badge refresh. Stalker lazy-VOD is the +`SerialDetailsSeasonWatchService.handle(..., scope)`, Stalker via +`StalkerSeriesWatchToggleService` and its `runStalkerWatchToggleBatch` +core — sharing the busy flag, the ownership guards, and the catalog-badge +refresh. Stalker lazy-VOD is the special case: unopened seasons have empty episode lists, so the container reports them through the `hasUnloadedSeasons` input (blocks the "fully watched" verdict and switches the label to its countless variant), @@ -412,7 +414,8 @@ series-toggle hydration join one in-flight request instead of duplicating it (a second request's failure could abort a toggle whose original request succeeded). The host synchronously re-runs the position reconcile -(`applyReconciledSeriesPositions` — the effect-fed maps only update on +(`StalkerSeriesPositionsService.applyReconciledSeriesPositions` — the +effect-fed maps only update on the next change-detection tick, and enqueuing against stale maps would miss the hydrated episodes' legacy rows), rebuilds the request from the now-complete seasons keeping the captured direction, and reports an diff --git a/docs/architecture/stalker-mock-server.md b/docs/architecture/stalker-mock-server.md index 93cd022ef..bd17dd53b 100644 --- a/docs/architecture/stalker-mock-server.md +++ b/docs/architecture/stalker-mock-server.md @@ -408,7 +408,8 @@ file running in parallel workers, so isolation is per-MAC rather than global: else is talking to the server — a spec that used it would wipe a sibling spec's session mid-test. - `apps/web-e2e/src/stalker.e2e.ts` declares its shared scenario MACs in - `OWNED_MACS` and clears them in one batched request. The sibling specs that + `OWNED_MACS` (the constants live in `stalker-portal.fixture.ts`) and clears + them in one batched request. The sibling specs that reach this server (`self-hosted.e2e.ts`, the `sources-pwa` helpers) own a disjoint `00:1A:79:5F:*` range, so neither file can clear the other's state. - Within each browser project, tests deliberately share content-scenario MACs diff --git a/docs/architecture/stalker-portal.md b/docs/architecture/stalker-portal.md index d39c1f61b..ccc755405 100644 --- a/docs/architecture/stalker-portal.md +++ b/docs/architecture/stalker-portal.md @@ -484,7 +484,8 @@ the format at all, so a large share of working installations use a non-Infomir MAC. Refusing one would stop those users adding or editing a portal that works for them. The mock encodes the same split (`enforceMacFormat` is set only on the strict endpoint; `/portal.php` ignores it), and `AUTH_REJECTED_MAC` in -`stalker.e2e.ts` depends on it — a non-Infomir MAC that must reach the strict +`stalker-portal.fixture.ts` (used by `stalker.e2e.ts`) depends on it — a +non-Infomir MAC that must reach the strict endpoint and be refused _there_, not in the form. In the edit dialog **both** passes — blur and submit — normalize only a MAC the diff --git a/docs/architecture/tmdb-roadmap.md b/docs/architecture/tmdb-roadmap.md index 67adfa664..64b429ad1 100644 --- a/docs/architecture/tmdb-roadmap.md +++ b/docs/architecture/tmdb-roadmap.md @@ -257,7 +257,7 @@ Zero i18n keys. Zero UI change. - populated in all three of `mergeVodInfoWithTmdb` (`:168`), `mergeSerieInfoWithTmdb` (`:215`), `mergeStalkerInfoWithTmdb` (`:257`) - through `NormalizedVodMeta` (`libs/shared/interfaces/src/lib/vod-details-item.interface.ts`) + **both** normalizers in `vod-details-adapters.ts` — the single convergence point where Xtream and Stalker meet -**Component.** New standalone `app-tmdb-extras-shelf` in `libs/ui/shared-portals`. It must **not** go inline: `libs/ui/playback/src/lib/vod-details/vod-details.component.ts` is **388 lines and is NOT in `tools/eslint/max-lines-baseline.mjs`** — roughly 12 lines of headroom against the hard 400 lint cap. +**Component.** New standalone `app-tmdb-extras-shelf` in `libs/ui/shared-portals`. It must **not** go inline: `libs/ui/playback/src/lib/vod-details/vod-details.component.ts` is **NOT in `tools/eslint/max-lines-baseline.mjs`** and stays under the hard 400 lint cap only because its state lives in sibling helpers (about 340 counted lines today). **Render** into the `detail-extras` projection slot at **four** sites (`vod-details.component.html:225`, `serial-details.component.html:201`, `vod-details-route.component.html:247`, `stalker-series-view.component.html:202`) — note Xtream `serial-details` has no trailer block today, so it either gains one or the shelf lands inconsistently. Reuse the existing nocookie iframe + `| safe` pipe so the Electron Referer shim keeps working; clicking swaps the embed `src` rather than opening a new player. Cards use `https://img.youtube.com/vi/{key}/hqdefault.jpg` (CSP verified: `img-src` covers it, `frame-src https://www.youtube-nocookie.com` covers the embed). `@if (extras().length > 1)` … `@else` the existing single-trailer markup **verbatim**.