mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-16 14:16:16 -08:00
fix(ui): keep one Back arrow on detail pages (#1627)
Movie and series detail pages showed two arrow_back controls while the inline player was open: the shell's sticky arrow (added in #1576 so Back survives scrolling) meant "Close player" in watch state, while the now-playing bar carried a second arrow that meant route-level Back — the same icon with two meanings, next to a "Close player" button that duplicated the first. The shell's sticky arrow is now route-level Back in browse and watch alike, and the bar carries no arrow of its own. Closing the player is the bar's "Close player" button and Escape, which still unwinds one level (close, then back). Hosts without a browse Back target (M3U, downloads) render no arrow in either state. Unit specs for the shell and the inline player cover the new contract; the Electron and web E2E helpers that pressed Back from watch are updated, and the M3U flow closes the player through the bar's button. Docs, the mirrored CLAUDE.md/AGENTS.md paragraph and a release note follow the change. Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
1 parent
5273e5fb55
commit
c76a901e8d
22 files changed
+127
-107
No files matched your search
@@ -162,18 +162,20 @@ Contracts:
|
||||
player subtree, so shell state changes cannot recreate the `<video>`.
|
||||
- **External MPV/VLC sessions do not flip the layout to watch** — browse
|
||||
layout stays, and the primary CTA keeps its "Stop <player>" behavior.
|
||||
- The shell's sticky control and Escape close inline playback through
|
||||
`closePlayerRequested`; hosts wire it to `closeInlinePlayer()`. From browse,
|
||||
they emit the host-owned `backClicked` instead (unless `backAvailable=false`).
|
||||
Escape respects fullscreen, menus/dialogs, editable fields and hidden/inert
|
||||
surfaces, and consumes a handled key so one press performs only one action.
|
||||
See [Portal Detail Navigation](./portal-detail-navigation.md).
|
||||
- The now-playing bar separates two exits: the back arrow emits
|
||||
`backClicked`, which hosts wire to their route-level `goBack()` (straight
|
||||
back to the list — everything browse offers is also visible in watch, so
|
||||
a two-step unwind would be ceremony); the "Close player" button and
|
||||
Escape emit `closed`/`closePlayerRequested` and return to browse without
|
||||
navigating.
|
||||
- The shell's sticky arrow emits the host-owned `backClicked` in browse and
|
||||
watch alike (unless `backAvailable=false`, when it is not rendered at all):
|
||||
hosts wire it to their route-level `goBack()`, straight back to the list —
|
||||
everything browse offers is also visible in watch, so a two-step unwind
|
||||
would be ceremony. Escape alone unwinds one level: in watch it emits
|
||||
`closePlayerRequested`, which hosts wire to `closeInlinePlayer()`; in browse
|
||||
it emits `backClicked`. Escape respects fullscreen, menus/dialogs, editable
|
||||
fields and hidden/inert surfaces, and consumes a handled key so one press
|
||||
performs only one action. See
|
||||
[Portal Detail Navigation](./portal-detail-navigation.md).
|
||||
- The now-playing bar has one exit of its own: the "Close player" button
|
||||
emits `closed` and returns to browse without navigating. It carries no back
|
||||
arrow — a second arrow beside the sticky one, with a different meaning,
|
||||
was the duplicate this contract removes.
|
||||
- Entering watch scrolls the shell to the top; leaving keeps the scroll
|
||||
position.
|
||||
|
||||
|
||||
@@ -30,10 +30,14 @@ The button has an opaque app-themed surface, visible keyboard focus, an Escape
|
||||
shortcut hint via native `title` and Electron `no-drag` hit testing. The hint
|
||||
does not create an overlay that could consume the first Escape press.
|
||||
|
||||
The sticky control and Escape unwind one level: watch emits
|
||||
`closePlayerRequested`, browse emits `backClicked`. Hosts retain their existing
|
||||
route/inline/collection return behavior. The now-playing bar's separate route
|
||||
Back action still returns directly to the list. Browse Escape requires focus
|
||||
The sticky control is route-level Back in both states: it emits `backClicked`
|
||||
whether or not inline playback is active, so the arrow keeps one meaning and
|
||||
the list is one click away while watching. Only Escape unwinds one level: watch
|
||||
emits `closePlayerRequested`, browse emits `backClicked`. Hosts retain their
|
||||
existing route/inline/collection return behavior. The now-playing bar carries
|
||||
no second arrow; its "Close player" button is the pointer counterpart of the
|
||||
watch Escape (two arrows with different meanings, and two controls for one
|
||||
action, were the pre-#1576 confusion this replaces). Browse Escape requires focus
|
||||
inside this shell; watch keeps the existing global close shortcut, including
|
||||
M3U playback started from its sidebar. Handled events, key repeats/modifiers,
|
||||
editable fields, inert/hidden shells, fullscreen, dialogs and menus are ignored.
|
||||
@@ -41,13 +45,15 @@ Escape bubbles through the shell before Material's body-level tooltip dispatcher
|
||||
so focused detail actions return with one press even while their tooltip is open.
|
||||
The document listener remains the outside-shell watch fallback; `defaultPrevented`
|
||||
prevents duplicate actions and preserves descendant handlers' priority.
|
||||
After closing a player, lost focus moves to the sticky control (or the shell
|
||||
when there is no browse Back), without scrolling or stealing existing focus.
|
||||
After Escape closes a player, lost focus moves to the sticky control (or the
|
||||
shell when there is no browse Back), without scrolling or stealing existing
|
||||
focus.
|
||||
|
||||
Hosts without browse navigation set `backAvailable=false`: M3U uses its channel
|
||||
sidebar, and collection bootstrap placeholders have no return handler. They
|
||||
have no browse button or browse Escape action; M3U watch still offers Close
|
||||
player. Loading/error shells with a return handler keep Back available.
|
||||
render no sticky arrow in either state and have no browse Escape action; their
|
||||
watch exits are the bar's Close player button and Escape. Loading/error shells
|
||||
with a return handler keep Back available.
|
||||
|
||||
## Summary
|
||||
|
||||
@@ -55,9 +61,9 @@ player. Loading/error shells with a return handler keep Back available.
|
||||
- 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
|
||||
sticky watch control closes the inline player, while the now-playing bar
|
||||
retains its separate direct return to the list. See
|
||||
not a navigation. Route-level back semantics are unchanged; the one
|
||||
sticky arrow returns to the list from either state, while Escape and the
|
||||
now-playing bar's Close button close the inline player. See
|
||||
[Embedded Inline Playback](./embedded-inline-playback.md).
|
||||
- Favorites and recently viewed collections now use collection-owned inline detail
|
||||
for non-live Xtream and Stalker items.
|
||||
|
||||
Reference in new issue
Block a user