mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-08 09:01:03 -08:00
feat(portals): fold live TV panels in nested levels with a category dropdown (#1556)
## Summary Live TV panels now fold from the outside in, in three nested levels, instead of one toggle that hid the categories rail and the channel list together: 1. **Categories + channels + player** (browse, unchanged). 2. **Channels + player** — a new `chevron_left` in the categories rail header hides only that rail. The channels header then turns its title into a **category dropdown** that opens the same shell panel as a popover (search, sort, counts, selection are one implementation), plus a `chevron_right` that brings the rail back. 3. **Player only** — the channels header chevron, as before. The floating restore handle and `Cmd/Ctrl+B` return to the level the user collapsed from, not always to level 1. Every level is restored as stored, per surface (`live-sidebar-state:<surface>`, from #1555): a hidden rail is discoverable through the workspace header toggle and the hidden-list empty state that #1555 added, so this PR no longer needs its original "player-only never restores" rule. The level `Cmd/Ctrl+B` comes back to is seeded from the restored level and kept for the session. ## Design notes - Nested levels rather than two independent booleans: "channels hidden, categories visible" makes no sense since a category click has to bring the channels back anyway. The model follows the outside-in collapse of three-pane apps (Mail, Slack, Plex). - The categories rail folds at level 2 **only while a category is selected**: the live root ("All Items" grid) has no channels header to host the way back, so folding there would strand the user. Level 3 folds it regardless, because the floating restore handle lives in the content area. - `LIVE_CATEGORIES_POPOVER` (`@iptvnator/portal/shared/util`) is the DI bridge: the workspace shell provides `WorkspaceLiveCategoriesPopoverService` (CDK overlay hosting `WorkspaceContextPanelComponent` in `presentation="popover"`), the Xtream and Stalker live layouts inject it optionally and keep their plain heading without a provider. - M3U and the unified live tab have no categories rail and treat level 2 like level 1; their code is untouched. ## Merged with #1555 (per-surface rail state) #1555 landed while this PR was open and reworked the same service: state per surface (`m3u` / `portal` / `collection`), a workspace header toggle, the hidden-list empty state, and the legacy shared key forgotten on startup. This PR keeps that model and layers the three levels onto the `portal` surface (`areCategoriesHiddenFor`, `hideCategories` / `showCategories` / `collapse` / `expand` per surface; `toggle(surface)` returns to the level the surface collapsed from). "Show playing channel" uses `expand('portal')` so it keeps a deliberately hidden categories rail folded, and the category sort preference moved to `PortalCategorySortStateService` so the popover copy of the context panel and the retained rail agree. ## Also fixed along the way - The channels header showed "Channels" instead of the category name: provider category ids are strings, the selection is numeric. Compared via `String()` now. - A collapsed context panel left a 22px padding strip beside the channels rail. - The panel toggle labels said "Hide channels list" while also hiding categories; labels and tooltips are honest now (8 new i18n keys, all 18 locales). Docs: `docs/architecture/iptvnator-ui-guidelines.md` ("Collapsible Live Sidebar" rewritten), `docs/architecture/workspace-shell.md`. Release note: `.changes/portals-live-panel-collapse-levels.md`. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
1 parent
0dcfba7045
commit
0a2373f192
68 files changed
+2710
-197
No files matched your search
@@ -1739,6 +1739,36 @@ preventing destination failures from penalizing the initial endpoint. Contracts:
|
||||
copy and Retry now; Stalker preserves cached account data on a failed refresh.
|
||||
Contract: `docs/architecture/host-connectivity-guard.md`.
|
||||
|
||||
## Live TV Panel Levels
|
||||
|
||||
Portal live layouts (Xtream `live`, Stalker `itv`/`radio`) fold their panels
|
||||
from the outside in, in three nested levels owned by `LiveSidebarState`
|
||||
(`@iptvnator/portal/shared/util`): `expanded` (categories rail + channels rail
|
||||
+ player), `categories-hidden` (channels rail + player) and `collapsed`
|
||||
(player only). `LiveLayoutSidebarStateService` is the single source of truth, per
|
||||
surface (`m3u` / `portal` / `collection`; the levels apply to `portal`); the
|
||||
shell context sidebar folds the categories rail on
|
||||
`areCategoriesHiddenFor('portal')` (at level 2 only while the portal store has
|
||||
a selected category — the live root has no channels header to host the way
|
||||
back — and always at level 3), the channels rail folds on
|
||||
`isCollapsedFor('portal')`. While the rail is folded the
|
||||
channels header turns its title into a category dropdown that opens the same
|
||||
`WorkspaceContextPanelComponent` as a CDK popover through the
|
||||
`LIVE_CATEGORIES_POPOVER` token: the workspace shell provides
|
||||
`WorkspaceLiveCategoriesPopoverService` (focus-trapped `role="dialog"`,
|
||||
closed by backdrop, Escape, selection, its footer and any `NavigationStart`),
|
||||
the live layouts reach it through `createLivePanelsController()` (level
|
||||
flags, dropdown bridge and focus handoff in one shared object; the token is
|
||||
optional). `Cmd/Ctrl+B`, the header toggle and the
|
||||
floating restore handle return to the level the user collapsed from (the
|
||||
target is session-only; every level is restored as stored per surface).
|
||||
Folded rails carry `inert`, and
|
||||
`handoffFocusOnLiveSidebarChange()` / `focusIfFocusLost()` move focus to the
|
||||
replacement affordance only when the activated button was removed or inerted.
|
||||
M3U and the unified live tab have no categories rail and treat level 2 like
|
||||
level 1. Contract: `docs/architecture/iptvnator-ui-guidelines.md`
|
||||
("Collapsible Live Sidebar").
|
||||
|
||||
## Live Channel Return
|
||||
|
||||
Xtream and Stalker (including radio) capture displayed playback order on explicit
|
||||
|
||||
Reference in new issue
Block a user