fix(portals): preserve playlist ownership during detail handoffs (#1825)

* fix(portals): preserve playlist ownership during detail handoffs

* fix(portals): reload Stalker categories only for a held destination

Review follow-ups (Greptile, Codex): resetCategories() reloaded the
category resource, and the route session calls it on a portal switch
before the destination is resolved and on teardown, so it asked the
portal being left, and a failed destination lookup could let that answer
repopulate the sidebar. resetCategories() now only clears; the session
calls the new reloadCategories() after installing the destination, and
only when a handoff had already put that playlist in the store (the
owner, and so the resource params, did not change).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: 4gray <fourgray@proton.me>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
authored and GitHub committed 2026-10-07 00:21:07 +02:00
1 parent 0a6f54ca15
commit 93c5f1a051
23 files changed
+1001 -52

No files matched your search

@@ -270,6 +270,22 @@ handler as the header Back.
- Do not force both portals into the same browse/detail behavior unless the full
portal detail architecture is being changed.
### Arrival and asynchronous ownership
The shared catalog view initializes the category and consumes its Stalker
handoff together, after the facade's optional `routeReady` signal allows it.
Stalker exposes the route session's readiness, withheld from NavigationStart
until the destination playlist and section are installed. Cancelled navigation
reconciles the current route. Reused category routes also reinitialize when
their playlist changes; readiness changes alone must not close an open detail
on query-only navigation.
Collection detail wrappers invalidate pending playlist loads before restoring
their store snapshot on destruction. Route sessions must compare the actual
store owner with the route, rather than trusting only their last initialized
playlist id. Xtream playlist reads likewise discard completions superseded by
a selection, metadata update, reset or newer read.
## Xtream
Xtream category and search details are represented by canonical routes.
+12
View File
@@ -393,6 +393,18 @@ Internal structure to preserve:
`isCategoryResourceFailed()` / `isPaginatedContentFailed()` for explicit
error handling.
Category arrays belong to `categoryPlaylistKey`, not just the content type.
Every category reader checks that owner; a portal switch clears all four
section caches before loading the destination. Aborted or foreign-portal
responses (including errors and radio fallbacks) cannot write into the active
cache. `resetCategories()` only clears: the route session calls it on a
portal switch before the destination is resolved and on teardown, where a
request would go to the portal being left. When a handoff had already put
the destination in the store, the owner does not change and the resource
would not reload by itself, so the session calls `reloadCategories()` once
it has installed that playlist. This contract applies to collection details as well as routed
catalogs, because both use the root Stalker store.
Failure-handling rule:
- Failed category or content requests must degrade into empty/error UI state,
@@ -93,6 +93,9 @@ During refactor:
- `clearSelectedItem(): void`
- `setCategories(type: 'vod' | 'series' | 'itv' | 'radio', categories: StalkerCategoryItem[]): void`
- `resetCategories(): void`
Clears only; it starts no request (called on portal switches and route teardown).
- `reloadCategories(): void`
Refetches the current portal's categories after a reset that keeps the owner.
- `setItvChannels(channels: StalkerItvChannel[]): void`
- `setRadioChannels(channels: StalkerItvChannel[]): void`
- `setSearchPhrase(phrase: string): void`