mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-10 18:36:15 -08:00
docs(ui): document live panel ownership
This commit is contained in:
1 parent
7d7dbe25ad
commit
fae19c2041
4 files changed
+98
-51
No files matched your search
@@ -0,0 +1,10 @@
|
||||
---
|
||||
type: feature
|
||||
area: ui
|
||||
issues: [1118]
|
||||
---
|
||||
|
||||
Live TV now remembers Groups and Channels visibility independently across M3U,
|
||||
Xtream, Stalker, Favorites, and Recently Viewed. Consistent accessible controls
|
||||
restore each panel, while Cmd/Ctrl+B temporarily clears the viewing area
|
||||
without overwriting those choices. Guide toggles now appear only when usable.
|
||||
@@ -929,6 +929,23 @@ engine` (restart required) or
|
||||
- Keyboard shortcuts: ArrowUp/ArrowDown (volume), M (mute)
|
||||
- Component: `libs/ui/playback/src/lib/audio-player/audio-player.component.ts`
|
||||
|
||||
**Live Panel Controls**:
|
||||
|
||||
- Groups and Channels keep independent persisted intent through
|
||||
`LiveLayoutPanelStateService` in `@iptvnator/portal/shared/data-access`;
|
||||
missing new values migrate per panel from the legacy
|
||||
`live-sidebar-state`.
|
||||
- M3U, Xtream, Stalker, Favorites, and Recently Viewed use the same
|
||||
header-hide/boundary-restore pattern with retained `inert` panels, ARIA
|
||||
relationships, focus transfer, and 40px minimum targets.
|
||||
- `Cmd/Ctrl+B` temporarily suppresses applicable left panels without changing
|
||||
their saved combination. Responsive suppression also preserves intent and
|
||||
omits unfulfillable restore controls.
|
||||
- Guide disclosure appears only beside a working inline player. External
|
||||
MPV/VLC keeps a static EPG heading, and radio has no Guide panel.
|
||||
- Canonical UX and ownership contract:
|
||||
`docs/architecture/iptvnator-ui-guidelines.md` ("Live Panel Disclosures").
|
||||
|
||||
**EPG (Electronic Program Guide)**:
|
||||
|
||||
- XMLTV format support
|
||||
|
||||
@@ -214,48 +214,68 @@ remain local when the meaning is explicit.
|
||||
- Keep the EPG content mounted while collapsed so current-program state can
|
||||
continue updating.
|
||||
|
||||
### Collapsible Live Sidebar
|
||||
### Live Panel Disclosures
|
||||
|
||||
- M3U, Xtream, and Stalker live layouts share a single sidebar collapse toggle
|
||||
that hides the channels rail to give the player and EPG full width.
|
||||
- Xtream Live TV's root view (`/live` with no selected category) follows the
|
||||
same paginated `All Items` shell as VOD and Series: a widget header with the
|
||||
total channel count, page-size controls, and page navigation above the shared
|
||||
`app-grid-list`. Use the grid list's logo-oriented live variant so channel
|
||||
logos stay contained in 16:9 thumbnails instead of being cropped like
|
||||
VOD/series posters. Selecting a channel from that root grid starts playback,
|
||||
selects the channel's category, highlights the active category and channel,
|
||||
and scrolls the category rail plus virtual channels list to the selected rows
|
||||
when those rails are visible.
|
||||
- In Xtream and Stalker live TV, the same toggle also collapses the workspace
|
||||
shell context sidebar (the "Live Categories" rail rendered by
|
||||
`WorkspaceShellContextSidebarComponent`), matching M3U's "everything quiets"
|
||||
behaviour. The shell categories rail only collapses when the active section
|
||||
is `live` (Xtream) or `itv`/`radio` (Stalker); movies, series, favorites,
|
||||
and recent routes leave it untouched.
|
||||
- Collapsed state is owned by `LiveLayoutSidebarStateService`
|
||||
(`providedIn: 'root'`) in `@iptvnator/portal/shared/util`. Every surface that
|
||||
participates injects the service and reads `isCollapsed`; any toggle calls
|
||||
`service.toggle()`. Persistence delegates to the existing
|
||||
`live-sidebar-state` helpers, so the localStorage key stays unchanged and
|
||||
missing/invalid values restore to expanded.
|
||||
- A `mat-icon-button` with `chevron_left` lives in the sidebar header and
|
||||
toggles state. While collapsed, a floating `chevron_right` mini-fab appears
|
||||
at the left edge of `.content-container` to restore the rail (and the
|
||||
categories rail, in Xtream/Stalker live).
|
||||
- Keyboard shortcut: `Cmd/Ctrl+B`. The handler ignores events that originate
|
||||
inside `<input>`, `<textarea>`, `<select>`, or content-editable elements via
|
||||
the shared `isTypingInInput` helper.
|
||||
- The CSS class `.sidebar-collapsed` (channels rail) and
|
||||
`.context-panel--collapsed` (workspace shell categories rail) both override
|
||||
the inline width set by the `appResizable` directive with
|
||||
`width: 0 !important; min-width: 0 !important`. The directive's persisted
|
||||
width is preserved so uncollapsing restores the user's previous resized
|
||||
width. Both rails share the same 180 ms width transition so motion stays in
|
||||
lockstep.
|
||||
- Below 600 px viewport, the M3U layout's mobile bottom-drawer rule overrides
|
||||
the desktop collapse to `height: 0` instead of `width: 0`, and the floating
|
||||
restore handle is hidden.
|
||||
Live layouts treat Groups, Channels, and Guide as separate capabilities. Never
|
||||
derive one panel's visibility from another panel's state, and never render a
|
||||
disclosure control for an action the current layout cannot perform.
|
||||
|
||||
| Panel | Applicable surfaces | UI owner |
|
||||
| -------- | --------------------------------------------------------------------------------------- | ------------------------------------------------ |
|
||||
| Groups | M3U Groups; Xtream Live TV; Stalker TV/Radio | M3U groups view or the workspace context sidebar |
|
||||
| Channels | M3U All/Groups; selected Xtream/Stalker live category; Favorites/Recent live collection | The route's channel-list or collection header |
|
||||
| Guide | EPG timeline/list beside a working inline player | `app-epg-timeline` or `app-epg-list-view` |
|
||||
|
||||
`LiveLayoutPanelStateService` in
|
||||
`@iptvnator/portal/shared/data-access` owns only persisted user intent for the
|
||||
two left panels:
|
||||
|
||||
- `live-groups-panel-state`
|
||||
- `live-channels-panel-state`
|
||||
|
||||
Both values are independently `expanded` or `collapsed`. On first use, each
|
||||
missing or invalid new value is seeded from a valid legacy
|
||||
`live-sidebar-state`; otherwise it defaults to expanded. Migration writes the
|
||||
new keys and never rewrites or removes the legacy key.
|
||||
|
||||
Routes resolve effective visibility from intent plus local applicability,
|
||||
responsive suppression, and the service's non-persisted master suppression.
|
||||
That distinction is intentional: hiding a panel updates its own persisted
|
||||
intent, while `Cmd/Ctrl+B` temporarily suppresses all applicable left panels
|
||||
without overwriting either choice. Pressing the shortcut again restores the
|
||||
saved combination. A direct panel action clears master suppression and then
|
||||
applies the requested intent. Shortcut handlers ignore input, textarea,
|
||||
select, and content-editable targets.
|
||||
|
||||
Disclosure controls follow one placement and accessibility contract:
|
||||
|
||||
- Expanded panels put a labelled Hide action in their own header.
|
||||
- Collapsed panels put a labelled Show action on the boundary where the panel
|
||||
will return. If Groups and Channels are both collapsed, the restore rails
|
||||
stay in spatial panel order.
|
||||
- Favorites and Recently Viewed keep their single Channels action in the
|
||||
collection header; do not duplicate it inside loading, empty, or zero-result
|
||||
content.
|
||||
- The controlled panel stays mounted with `aria-hidden="true"` and `inert`
|
||||
while effectively hidden. The control uses `aria-controls`,
|
||||
`aria-expanded`, an action-oriented translated label, and a minimum 40px
|
||||
target. Move focus to the corresponding restore/hide control after a direct
|
||||
state change.
|
||||
- Loading, empty-category, and zero-search-results states keep every applicable
|
||||
control operable. Applicability, not item count, decides whether a panel can
|
||||
be disclosed.
|
||||
|
||||
Responsive suppression must not manufacture no-op controls. The workspace
|
||||
Groups panel is suppressed at 1023px and below; the M3U Groups panel is
|
||||
suppressed below 600px. In both cases its persisted intent remains unchanged
|
||||
and no Groups restore control appears. The M3U Channels bottom drawer remains
|
||||
independently restorable on mobile.
|
||||
|
||||
Guide disclosure is a separate EPG capability. It is interactive only beside a
|
||||
working inline player. External MPV/VLC layouts keep their full static EPG
|
||||
heading without a Guide toggle, and radio layouts render no Guide panel. This
|
||||
contract does not make the external-player right area content-aware; that is a
|
||||
separate layout concern.
|
||||
|
||||
### EPG Card
|
||||
|
||||
|
||||
@@ -656,14 +656,14 @@ git commit -m "feat(i18n): translate live panel controls"
|
||||
- Reuse: `apps/electron-backend-e2e/src/electron-test-fixtures.ts`
|
||||
- Reuse: `apps/electron-backend-e2e/src/portal-mock-fixtures.ts`
|
||||
|
||||
- [ ] **Step 1: Write the M3U Electron flow**
|
||||
- [x] **Step 1: Write the M3U Electron flow**
|
||||
|
||||
Import the mock M3U fixture, enter Groups, independently hide/restore Groups and
|
||||
Channels, verify focus/ARIA/inert/width reclamation, exercise `Control+B`, seed
|
||||
legacy storage before reload, and check the mobile Channels restore path at a
|
||||
narrow viewport.
|
||||
|
||||
- [ ] **Step 2: Run the M3U test and verify RED if a gap remains**
|
||||
- [x] **Step 2: Run the M3U test and verify RED if a gap remains**
|
||||
|
||||
```bash
|
||||
pnpm nx run electron-backend-e2e:e2e-ci--src/live-panel-toggles.e2e.ts \
|
||||
@@ -673,14 +673,14 @@ pnpm nx run electron-backend-e2e:e2e-ci--src/live-panel-toggles.e2e.ts \
|
||||
Expected after implementation: PASS. Any failure must identify a functional or
|
||||
layout gap before adding provider flows.
|
||||
|
||||
- [ ] **Step 3: Add Xtream and Stalker flows**
|
||||
- [x] **Step 3: Add Xtream and Stalker flows**
|
||||
|
||||
Use the existing mock-server add helpers. Verify root Groups-only placement,
|
||||
category Groups+Channels independence, persistence across navigation,
|
||||
Groups-then-Channels restore ordering, zero-search-result controls, and no
|
||||
Guide toggle for external player/radio.
|
||||
|
||||
- [ ] **Step 4: Run the full atomized target**
|
||||
- [x] **Step 4: Run the full atomized target**
|
||||
|
||||
```bash
|
||||
pnpm nx run electron-backend-e2e:e2e-ci--src/live-panel-toggles.e2e.ts
|
||||
@@ -688,7 +688,7 @@ pnpm nx run electron-backend-e2e:e2e-ci--src/live-panel-toggles.e2e.ts
|
||||
|
||||
Expected: all `@live-panels` tests pass.
|
||||
|
||||
- [ ] **Step 5: Lint and commit**
|
||||
- [x] **Step 5: Lint and commit**
|
||||
|
||||
```bash
|
||||
pnpm nx lint electron-backend-e2e
|
||||
@@ -704,19 +704,19 @@ git commit -m "test(e2e): cover live panel toggles"
|
||||
- Modify: `CLAUDE.md`
|
||||
- Create: `.changes/ui-live-panel-toggles.md`
|
||||
|
||||
- [ ] **Step 1: Replace the obsolete shared-sidebar documentation**
|
||||
- [x] **Step 1: Replace the obsolete shared-sidebar documentation**
|
||||
|
||||
Document independent Groups/Channels storage keys, data-access ownership,
|
||||
intent versus effective state, boundary controls, master suppression,
|
||||
responsive Groups-first suppression, collection-header exception, and Guide
|
||||
capability. Preserve the channel-row responsive contract from #1312 verbatim.
|
||||
|
||||
- [ ] **Step 2: Update `CLAUDE.md` where it describes live sidebar state**
|
||||
- [x] **Step 2: Update `CLAUDE.md` where it describes live sidebar state**
|
||||
|
||||
Mirror the canonical names, service location, and shortcut semantics without
|
||||
adding the future content-aware right-region behavior.
|
||||
|
||||
- [ ] **Step 3: Add the user-facing release note**
|
||||
- [x] **Step 3: Add the user-facing release note**
|
||||
|
||||
```md
|
||||
---
|
||||
@@ -730,7 +730,7 @@ reliable restore controls across providers and screen sizes, and hides Guide
|
||||
toggles when they cannot work.
|
||||
```
|
||||
|
||||
- [ ] **Step 4: Validate documentation and release note**
|
||||
- [x] **Step 4: Validate documentation and release note**
|
||||
|
||||
```bash
|
||||
git diff --check
|
||||
@@ -739,7 +739,7 @@ pnpm run release:notes:validate
|
||||
|
||||
Expected: both commands exit 0.
|
||||
|
||||
- [ ] **Step 5: Commit**
|
||||
- [x] **Step 5: Commit**
|
||||
|
||||
```bash
|
||||
git add docs/architecture/iptvnator-ui-guidelines.md CLAUDE.md \
|
||||
|
||||
Reference in new issue
Block a user