142 lines
5.3 KiB
Markdown
142 lines
5.3 KiB
Markdown
# Workspace Shell
|
|
|
|
This document records the current workspace-first shell contract. It is the
|
|
stable replacement for the older UI refactor summary.
|
|
|
|
Related:
|
|
|
|
- [Workspace Dashboard](./workspace-dashboard.md)
|
|
|
|
## Summary
|
|
|
|
- `/workspace` is the primary app surface.
|
|
- `WorkspaceShellComponent` owns the persistent frame: rail, header, optional
|
|
context panel, content outlet, and external playback footer.
|
|
- Descendant workspace pages inherit `layout = 'workspace'` from the
|
|
`/workspace` root route.
|
|
- Provider route trees now bootstrap through route-scoped session providers
|
|
instead of nested provider shell components.
|
|
|
|
Core implementation:
|
|
|
|
1. `apps/web/src/app/app.routes.ts`
|
|
2. `libs/workspace/shell/feature/src/lib/workspace-shell/workspace-shell.component.ts`
|
|
3. `libs/workspace/shell/feature/src/lib/workspace-shell/workspace-shell.component.html`
|
|
4. `libs/portal/shared/util/src/lib/navigation/portal-route.utils.ts`
|
|
5. `libs/portal/shared/util/src/lib/navigation/portal-rail-links.ts`
|
|
6. `libs/portal/shared/ui/src/lib/navigation/portal-rail-links.component.ts`
|
|
|
|
## Route Contract
|
|
|
|
Current workspace routes:
|
|
|
|
1. `/` -> `/workspace`
|
|
2. `/workspace` -> `/workspace/dashboard`
|
|
3. `/workspace/dashboard`
|
|
4. `/workspace/sources`
|
|
5. `/workspace/playlists/:id/:view`
|
|
6. `/workspace/global-favorites`
|
|
7. `/workspace/downloads`
|
|
8. `/workspace/settings`
|
|
9. `/workspace/xtreams/:id/...`
|
|
10. `/workspace/stalker/:id/...`
|
|
|
|
Compatibility redirect:
|
|
|
|
1. `/settings` -> `/workspace/settings`
|
|
|
|
Provider route integration:
|
|
|
|
1. `apps/web/src/app/app.routes.ts` marks the `/workspace` root route with
|
|
`data.layout = 'workspace'`.
|
|
2. `isWorkspaceLayoutRoute(...)` treats that layout marker as inherited route
|
|
state for all descendants.
|
|
3. Xtream and Stalker parent routes attach route-scoped session providers that
|
|
bootstrap the active playlist, sync provider section state, and clean up
|
|
provider-local state when the route is destroyed.
|
|
4. Workspace routes no longer rely on nested provider shell components for
|
|
hidden local chrome.
|
|
|
|
## Shell Structure
|
|
|
|
The shell is intentionally split into four persistent regions:
|
|
|
|
1. Left rail:
|
|
1. Static workspace links for dashboard, sources, global favorites, and recently viewed.
|
|
2. Provider-aware context links derived from the active or current playlist.
|
|
3. Settings remains a persistent footer shortcut in the rail.
|
|
2. Top header:
|
|
1. Playlist switcher.
|
|
2. Route-aware search input and command palette trigger.
|
|
3. Add source action.
|
|
4. Optional playlist refresh and route-specific shortcut actions.
|
|
5. Downloads shortcut in Electron.
|
|
3. Main body:
|
|
1. Optional left context panel.
|
|
2. Main router outlet content.
|
|
4. Optional footer:
|
|
1. External playback session bar when a docked session is visible.
|
|
|
|
## Context Panel Rules
|
|
|
|
The shell decides which secondary panel to show from the current route:
|
|
|
|
1. `/workspace/sources`
|
|
1. `WorkspaceSourcesFiltersPanelComponent`
|
|
2. Xtream category sections (`live`, `vod`, `series`)
|
|
1. `WorkspaceContextPanelComponent`
|
|
3. Stalker category sections (`itv`, `vod`, `series`)
|
|
1. `WorkspaceContextPanelComponent`
|
|
4. `/workspace/settings`
|
|
1. `WorkspaceSettingsContextPanelComponent`
|
|
5. Downloads sections
|
|
1. `WorkspaceCollectionContextPanelComponent`
|
|
|
|
The context panel is part of the shell contract. New workspace-level routes
|
|
should explicitly decide whether they need one rather than adding local
|
|
sidebars inside feature pages.
|
|
|
|
## Search And Navigation Rules
|
|
|
|
Search is shell-owned and route-aware:
|
|
|
|
1. Disabled on settings routes.
|
|
2. Enabled on sources routes.
|
|
3. Enabled for supported Xtream and Stalker content/search views.
|
|
4. Placeholder text and search handling vary by provider and section.
|
|
5. Input changes are debounced before route/store updates are applied.
|
|
|
|
Rail navigation is also shell-owned:
|
|
|
|
1. Workspace-global entries are static.
|
|
2. Provider entries come from `buildPortalRailLinks(...)`.
|
|
3. On dashboard, sources, settings, and global favorites, the shell falls back
|
|
to the currently selected playlist so provider navigation remains available
|
|
even outside a provider route.
|
|
|
|
Command palette behavior is shell-owned but view-extensible:
|
|
|
|
1. The shell resolves commands into three groups in fixed order: current view,
|
|
this playlist, then global.
|
|
2. Shell-owned commands are derived from route context and current playlist
|
|
state; empty groups are omitted instead of rendering disabled placeholders.
|
|
3. Workspace features contribute current-view commands through
|
|
`WorkspaceViewCommandService`.
|
|
4. Header shortcut actions can opt into palette exposure by attaching palette
|
|
metadata through `WorkspaceHeaderContextService`.
|
|
5. Filtering matches command labels, descriptions, and keywords, and keyboard
|
|
selection always lands on the first enabled command.
|
|
|
|
## Maintenance Guidance
|
|
|
|
Use this document as the source of truth when changing workspace shell behavior.
|
|
|
|
1. New top-level user destinations should default to child routes under
|
|
`/workspace`.
|
|
2. Shared provider navigation logic belongs in portal-shared util/UI libraries,
|
|
not duplicated inside the shell.
|
|
3. If a provider route changes how playlist/session bootstrap works, update the
|
|
route-session provider and shell-facing route contract together.
|
|
4. Historical migration notes, cleanup lists, and one-off refactor steps should
|
|
stay out of this file; track them in issues or PR notes instead.
|