Files
iptvnator/docs/architecture/portal-detail-navigation.md
T
4gray 760099358b feat(downloads): redesign download manager (#1313)
* docs(downloads): specify manager MVP redesign

* docs(downloads): plan manager MVP implementation

* docs(downloads): tighten manager validation plan

* fix(downloads): keep renderer download state global

* fix(downloads): make active count accessible

* feat(downloads): derive queue and library view model

* test(downloads): close view model coverage gaps

* fix(downloads): stabilize malformed view model data

* refactor(downloads): isolate library navigation

* fix(downloads): report library navigation failures

* feat(downloads): add ready-to-watch library

* feat(downloads): add active download queue

* feat(downloads): finish manager MVP

* docs(downloads): clarify detail-first offline behavior

* docs(downloads): plan detail navigation follow-up

* fix(downloads): open completed movies in details

* test(downloads): cover pending series navigation

* fix(downloads): honor the global cover size

* fix(downloads): prefer local playback in shared details

* fix(downloads): preserve external launch priority

* fix(downloads): prefer local playback in Xtream details

* test(downloads): cover offline detail journey

* docs(downloads): document offline detail behavior

* docs(downloads): format detail navigation plan

* fix(downloads): open Stalker items in provider details

* docs(downloads): clarify Stalker navigation fallback

* fix(xtream): isolate reused detail identities

* fix(xtream): ignore stale VOD positions

* fix(downloads): keep offline Xtream playback available

* docs(downloads): clarify provider playback availability

* docs(downloads): design missing-file recovery

* docs(downloads): plan missing-file recovery

* feat(downloads): derive completed file availability

* feat(downloads): recover missing completed files

* feat(downloads): refresh missing local files

* feat(downloads): separate missing files from ready media

* feat(downloads): surface missing files for recovery

* refactor(downloads): simplify ready cards

* test(downloads): cover missing-file and series journeys

* feat(downloads): finish missing-file recovery

* docs(downloads): design offline detail views

* docs(downloads): plan offline detail views

* feat(downloads): persist offline metadata snapshots

* fix(downloads): complete metadata snapshot bridge contract

* feat(downloads): manage offline metadata snapshots

* fix(downloads): harden metadata snapshot updates

* fix(downloads): restrict snapshot artwork

* fix(downloads): guard restart artwork URL

* fix(downloads): refine artwork URL checks

* feat(downloads): expose offline metadata updates

* fix(downloads): keep metadata service change focused

* fix(downloads): preserve metadata error conventions

* feat(downloads): derive offline detail content

* fix(downloads): preserve unknown episode coordinates

* feat(downloads): add focused offline detail routes

* fix(downloads): ignore fragments in shell route state

* fix(downloads): normalize fragments before queries

* feat(downloads): open ready cards in offline details

* fix(downloads): use native disabled card styles

* feat(downloads): enrich offline detail metadata

* fix(downloads): harden offline metadata resolution

* fix(downloads): preserve stalker provider titles

* fix(downloads): distinguish stalker metadata seeds

* fix(downloads): stabilize offline metadata refresh

* fix(downloads): throttle sparse metadata refreshes

* fix(downloads): type metadata language settings

* feat(downloads): render offline movie and series details

* fix(downloads): harden offline detail interactions

* fix(downloads): close offline detail edge cases

* feat(downloads): hand off to provider-only details

* fix(downloads): preserve stalker provider handoff

* feat(downloads): capture metadata at download time

* fix(downloads): preserve snapshot source semantics

* fix(downloads): preserve episode snapshot identity

* docs(downloads): document offline details flow

* docs(downloads): clarify stalker provider fallback

* test(downloads): cover offline detail journeys

* test(downloads): stabilize offline detail selectors

* style(downloads): format changed files

* docs(downloads): clean design spec formatting

* fix(downloads): preserve offline library ownership

* test(downloads): fix Windows workspace navigation

* test(database): preserve Electron tsconfig resolution

* perf(downloads): avoid blocking file availability probes
2026-08-01 18:09:31 +02:00

11 KiB

Portal Detail Navigation

This document records the current navigation contract for Xtream and Stalker detail flows, especially for favorites, recently viewed, search, and category content.

Related:

Summary

  • Xtream category browsing uses a route-first detail model.
  • Stalker uses an inline/store-state detail model.
  • Detail pages themselves are two-state (browse ↔ watch) inside PortalDetailShellComponent; entering/leaving watch is a layout state, not a navigation. Route-level back semantics are unchanged; the watch-state back button only closes the inline player. See Embedded Inline Playback.
  • Favorites and recently viewed collections now use collection-owned inline detail for non-live Xtream and Stalker items.
  • Provider-scoped collection routes fall back to the matching global collection route when All playlists shows a non-live item from the other portal type, so the correct detail host still opens without switching playlist context.
  • Dashboard Global Favorites and Recently Watched widgets hand off Xtream and Stalker movies/series into the matching global collection route with detail pre-opened.
  • Dashboard Continue Watching handoffs for Xtream series may additionally carry a one-shot season/episode resume target. The collection-owned Xtream detail consumes it after its episode positions load and starts that exact episode; opening the series from the collection grid itself remains detail-only. If the positions load fails, the target stays unconsumed and the handoff degrades to detail-only rather than starting the episode at offset zero.
  • Ready Download Manager cards open one of the three focused downloads/:downloadId routes. These local details hide the workspace context panel, play only finalized local files, and show only locally available episodes for a series.
  • View in portal is the explicit bridge from a focused offline detail to the source catalog. Xtream resolves a concrete category/item route; Stalker uses the best stored item shape or an identity/title-derived fallback. Both pass the one-shot detailPresentation: 'provider-only' navigation state. The destination keeps provider playback and whatever catalog the normal provider host can resolve, but hides Offline/local/download presentation.
  • Do not force both portals into the same browse/detail behavior unless the full portal detail architecture is being changed.

Xtream

Xtream category and search details are represented by canonical routes.

Examples:

  • /xtreams/:id/vod/:categoryId/:vodId
  • /xtreams/:id/series/:categoryId/:serialId

Implication:

  • Category browsing and search can still redirect to the original Xtream content route and item route.
  • This keeps the URL, browser history, and detail rendering model aligned with normal Xtream browsing.

Current code paths:

  • libs/portal/xtream/feature/src/lib/xtream-collection-detail.component.ts (favorites + recent, with shared UI from libs/portal/shared/ui/src/lib/components/favorites-layout/)
  • libs/portal/xtream/feature/src/lib/search-results/search-results.component.ts
  • libs/portal/catalog/feature/src/lib/category-content-view/category-content-view.component.ts

Collection behavior to preserve:

  • Selecting a non-live Xtream item from favorites/recent should keep the current collection route and open inline detail inside the collection pane when the current collection host is already Xtream-aware.
  • If a Stalker or M3U collection route is showing All playlists and the user selects an Xtream movie/series item, route into /workspace/global-favorites or /workspace/global-recent with detail pre-opened instead of trying to render Xtream detail inside the wrong host.
  • The current playlist context must stay unchanged even when the selected item belongs to a different Xtream source playlist.
  • The workspace/sidebar category panel should stay hidden for these collection detail opens.
  • Back from a collection-owned detail should restore the previous collection view state, including the active content tab and playlist/all-playlists scope.
  • Live streams can still open through the player path rather than a detail route.

Dashboard behavior to preserve:

  • Dashboard Global Favorites and Recently Watched widgets should route Xtream movie/series items into /workspace/global-favorites or /workspace/global-recent with collection detail pre-opened from navigation state.
  • When an Xtream series recent has a saved episode position, the dashboard hero and Continue Watching card should include that exact series/episode target in the navigation state. It is a one-shot playback request and must not leak into normal favorites, search, category, or collection-grid navigation. Only position rows that name their parent seriesXtreamId produce a target: episode-keyed recents make item.xtream_id an episode id, so legacy rows without the pointer stay detail-only instead of promoting the episode id to a series id.
  • Back from the collection detail should return to the dashboard handoff state, not switch the active playlist.

Search behavior to preserve:

  • Selecting an Xtream item from search should still navigate to the canonical Xtream content type/category/item route when the item is not a live stream.

Download handoff behavior:

  • An Xtream movie handoff requires its exact VOD category and item route; a series handoff requires its exact series category and item route. The download snapshot's provider category is preferred, with the typed catalog used to recover it for legacy rows. The action stays unavailable rather than opening a bare collection route when the target cannot be resolved.
  • Provider-only mode is read by the normal VOD/series detail components. It preserves provider Play/Resume and every provider episode, while suppressing the local Offline state and download controls. Reusing the route component for another item must clear the mode unless that navigation explicitly carries the marker.

Stalker

Stalker details are represented by store state and inline detail rendering on the current screen.

Examples:

  • Category content sets selectedItem and renders details inline.
  • Search sets selectedItem and stays on the search view.
  • Favorites and recently viewed stay on their current collection screen and open inline detail when the current collection host is already Stalker-aware.

Implication:

  • Favorites, recently viewed, and search should remain in the current Stalker view when opening VOD/series details.
  • This keeps Stalker behavior aligned with its normal category-content and search flow.

Current code paths:

  • libs/portal/stalker/feature/src/lib/stalker-collection-route.component.ts (favorites + recent via mode route data) -> stalker-collection-detail.component.ts
  • libs/portal/stalker/feature/src/lib/stalker-search/stalker-search.component.ts
  • libs/portal/catalog/feature/src/lib/category-content-view/category-content-view.component.ts (Stalker branch)

Behavior to preserve:

  • Favorites/recent/search should not navigate away to a canonical Stalker detail route because Stalker does not currently use one.
  • If an Xtream or M3U collection route is showing All playlists and the user selects a Stalker VOD/series item, route into /workspace/global-favorites or /workspace/global-recent with detail pre-opened so the Stalker inline detail host still renders on a compatible screen.
  • ITV/live items can still trigger playback immediately.
  • Stalker VOD items that are displayed as series because of is_series=1 remain VOD-backed when opened from favorites/recent/global collections; the collection host must not convert them into regular /series detail mode.
  • Dashboard Global Favorites and Recently Watched widgets should route Stalker movie/series items into /workspace/global-favorites or /workspace/global-recent with detail pre-opened inline, again without switching playlist context or showing the workspace category sidebar.
  • Back from the collection-owned detail should restore the previous collection tab and scope instead of resetting the collection screen to its defaults.

Download handoff behavior:

  • View in portal preserves Stalker's inline/store-state architecture. A type-compatible recently-viewed snapshot is carried as openStalkerItem into the normal category host, preserving regular series, embedded VOD series[], or lazy Ministra VOD is_series=1 shape. Candidate filtering rejects live items and the opposite movie/series namespace even when ids overlap. When the download snapshot carries an exact numeric provider category, that category wins over the recent record's virtual vod or series marker while the raw mode fields stay intact.
  • When no compatible recent snapshot exists, only a movie download with an exact numeric provider category can form a metadata-only VOD target. A legacy movie without that category and every episode without a recoverable raw series mode leave View in portal unavailable instead of fabricating an unverified provider target.
  • The provider-only marker is scoped to the resulting selected item. Its normal provider host supplies the seasons, episodes, and playback it can resolve, while the shared VOD or series UI suppresses local Offline and download controls. A later ordinary item open returns to normal provider presentation.

Decision Rule For Future Changes

When deciding how a favorites/recent/search click should behave:

  1. Follow the portal's canonical detail model.
  2. Prefer local consistency within the portal over cross-portal sameness.
  3. Only unify Xtream and Stalker behavior if the full detail architecture is being unified as well.

That means:

  • Xtream browse/search: navigate to the canonical route.
  • Xtream favorites/recent/global collection widgets: open collection-owned detail without switching playlist context. Use the current route when it can host Xtream detail, otherwise fall back to the matching global collection route.
  • Stalker non-live items: open collection-owned detail without switching playlist context. Use the current route when it can host Stalker detail, otherwise fall back to the matching global collection route.

Refactor Guidance

If a future change proposes that Stalker favorites/recent should deep-link into category routes:

  • also update Stalker category-content and search behavior
  • define a canonical Stalker detail route model first
  • update architecture docs and portal skills together

If a future change proposes that Xtream favorites/recent should stay inline:

  • keep the existing route-based detail pages reusable from the collection-owned detail host
  • verify history/back behavior, playlist preservation, and dashboard handoff behavior still make sense