* fix(ui): make the workspace usable on phone-sized screens
The shell was half-adapted below 640px: the rail flipped to a horizontal
bar but the link lists inside it kept stacking downwards, so the navigation
was drawn outside the bar and over the header (#1100).
Three resizable rails — the shell context panel, the live-layout channel
sidebar and the M3U channel drawer — kept their persisted desktop width,
which left the content around 50px on a 375px screen. They now span the
full width and stack above the content. The inline width written by
ResizableDirective is why these rules need `!important`.
Found while walking the rest of the UI at 375px and 768px:
- The detail hero kept poster and details side by side, squeezing the
action row below its own labels until "Play" was clipped to its icon.
- The settings section list did not scroll and painted over the footer,
which also affected short desktop windows.
- Hiding the M3U channel list on a phone was one-way: the restore handle
was hidden and only Cmd/Ctrl+B could bring it back.
- The live header drew the channel count and the paginator on top of each
other up to tablet width, because the paginator does not shrink and the
meta collapsed to zero width and overflowed its box.
- The search scope checkbox was pushed off the right edge.
Live TV states a floor for the player instead of a ceiling for the lists,
so the video keeps a usable share of the screen under the categories panel
and the channel list.
Closes#1100
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(ui): address review — keep the palette reachable and the video visible
Two findings from the Codex review on #1326.
Hiding the command-palette trigger on phones removed the only pointer-driven
way to open it: the rail renders route links plus Settings and emits nothing,
so `commandPaletteRequested` had exactly one source. The button stays and its
keyboard-shortcut label is swapped for an icon instead. Doing that exposed a
latent flex trap in the same row — an <input> keeps an intrinsic min-width
from its `size`, and `min-width: auto` honours it, so the field refused to
shrink and pushed the trigger out onto the buttons beside it.
The M3U drawer released the shared player floor, which on a short landscape
phone (600-640px wide) left the content container at half the shell body.
The inline guide inside it is `flex: 0 0 <basis>` and took its full 180px out
of a container that no longer had it, so the video could reach zero height.
The floor is restored and now yields on short viewports, the video states its
own minimum, and the guide is what gives way.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(ui): let the channel list keep its height on a landscape phone
Follow-up to the review: the player floor added in the previous commit was
measured against the viewport, not against what the shell had left. On a
640x360 landscape phone the stacked categories panel already takes 30vh, so
claiming another 50vh here drove the channel sidebar to zero height while it
was still marked expanded — no way to pick another channel — and pushed the
layout past the viewport.
The floor now applies only where the screen can afford it (`min-height:
600px`), the sidebar states a floor of its own so it cannot be squeezed out,
and the collapsed rule clears that floor so hiding the list still works.
Below that height the two panes simply share what is left.
Portrait is unchanged: categories 244px, channel list 220px, player 240px on
a 375x812 screen.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(ui): address review — settings nav on landscape, poster dead space
Two more findings from the Codex review.
The stacked settings context panel capped itself at 30vh, which on a 360px
screen is 108px — less than the panel's own title and footer, so the seven
section rows collapsed to nothing behind an overlapping footer. On short
screens the caption gives way (the rail already labels the page), the footer
sheds its tall-screen padding, and the settings variant gets a slightly
larger cap: unlike the live routes there is no player below competing for
height, only a scrollable form.
The poster kept a 330px minimum from the skeleton fallback at the bottom of
the file — sized for the 220px desktop poster — while the stacked phone hero
renders it 140px wide with a ~210px aspect-ratio height. Every loaded detail
page carried ~120px of empty space between the poster and the title. The
override sits after that rule because it wins on source order, not
specificity.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(ui): let the playlist switcher yield to the search field on narrow phones
Codex review of d6133da9: on a 320px header a route that contributes its
shortcut button left the search field less than its own chrome needs (~74px
of icon, palette trigger, gaps and padding), so the field's contents spilled
onto the buttons beside it.
The switcher is the one header region whose content can ellipsize, so it is
what shrinks — down to an 88px floor — while the field states its chrome as
a minimum. The field's basis moves from auto to zero so the input's intrinsic
size stops counting as content: with basis auto the field claimed its
intrinsic width even when room was ample and squeezed the switcher to ~115px
on a 375px screen that could fit all 140.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(ui): fit the switcher's own chrome inside its phone floor
Follow-up to the Codex note that the trigger's fixed chrome (type icon,
refresh, chevron, gaps, padding) exceeds the 88px floor the shell now allows
the switcher to shrink to. The flagged scenario itself cannot occur — the
Multi-EPG shortcut needs Electron bridge methods the PWA lacks, and Electron
enforces a 900px minimum window width so it never sees the phone breakpoint —
but the floor should hold on its own terms rather than by accident of which
buttons happen to render. Dropping the decorative type icon on phones brings
the fixed chrome under the floor, and the name gets the space instead.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
The earlier Settings polish (kill triple header, compact theme picker,
sticky footer, hide playlist switcher) addressed structure. This round
addresses typography and chrome to bring the look in line with the
v0.22 mockup spec captured in redesign-screens-2.jsx.
Three changes:
1. Flat sections — no card chrome
- Each .settings-group was a rounded panel (border-radius:22px,
filled background, box-shadow, .settings-group--active ring +
glow). Combined with the per-section icon-circle next to the
title, every section looked like a feature card, not a settings
region anchor. Strip all of it: the rail's active state on the
left already announces "you are here".
- Hide .settings-group__header-icon via display:none so the icon-
circle markup in each section template stays intact while the
visual chrome goes away — saves touching 6 templates for a
CSS-only change.
2. Promote section titles to a large flat heading
- Was h3 1.08rem 700 weight nested in the card chrome. Now h3
1.5rem (24px) 600 weight with a 1px bottom-border separator,
matching the mockup's 28px h1 + sub anchor pattern (24px is a
reasonable density compromise for the denser app layout). Active-
section variant keeps the blue title accent so users scrolling
the right pane don't lose the anchor.
- .setting-item drops the `margin: 0 18px` card inset so rows
align flush with the section title — flat list rhythm.
3. Quiet mono eyebrow for the left nav title
- .panel-title was a 20px 500 weight h2 ("Settings") competing for
"biggest text on screen" against the section titles on the right.
Switch to mono 11px uppercase 0.1em letter-spaced text-secondary
— quiet rail header per the mockup. Now the section titles on
the right are unambiguously the dominant heading.
Visual confirmation via agent-browser shows a much closer match to the
mockup: subtle SETTINGS eyebrow above the rail list, large flat
"General" anchor with bottom border, compact pickers, full-width sticky
footer.
50/50 settings tests still pass; build clean.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Four UX-audit fixes for the Settings page:
1. Header dedupe
- The page used to stack THREE headers vertically: the workspace rail's
"Settings" entry, a page-level <h1>Settings</h1> + subtitle, and the
General section's <h3>General</h3> + subtitle. The page-level and
section-level subtitles both used SETTINGS.GENERAL_SUBTITLE
("Change the configuration of the application"), word-for-word.
- Drop the visible page-level header entirely. Keep an a11y-only
<span class="visually-hidden"> for the data-test-id hook so the
existing settings.component.spec selector still resolves. Left rail
announces "Settings"; section header is now the page anchor.
- Add a global .visually-hidden helper to styles.scss for re-use.
2. Theme + Cover-size pickers shrink to a real segmented control
- .theme-switcher was a 3-column grid of ~78px-tall buttons making
"Choose theme" look like the most important action in Settings.
Replaced with a 30px-tall segmented control (track + thumb with
box-shadow on the selected option), matching the standard Material
"compact row" cadence everywhere else.
- Shortened all 18 locales' THEMES.* labels from "Light theme / Dark
theme / System theme" to "Light / Dark / System". The "theme" word
duplicated the section's own h3 ("Visual theme") and forced labels
to wrap into two lines in narrow columns.
3. Save bar becomes a real sticky footer
- The action bar was a `border-radius:18px; margin-left:auto;
position:sticky` chip floating bottom-right that clipped the last
form rows underneath. Now spans the full content column with a
top border separator — sits flush with the bottom edge while
still sticky on scroll. The save-button gradient also drops the
hand-rolled #3b82f6 in favour of var(--app-selection-color) so it
matches the unified blue primary used everywhere else.
4. Playlist switcher hidden on /settings
- Workspace shell header gains an isSettingsRoute input that hides
the playlist switcher block AND the leading actions group
(+ Add source / header shortcut / bulk action). Settings is a
global page — those controls were implying that switching
playlists scopes settings, which it doesn't. Wired through from
the shell facade's existing isSettingsRoute computed.
- Mock header in workspace-shell.component.spec gains the matching
input() declaration so the binding resolves under tests.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Updated confirmation dialog messages to provide detailed consequences of deleting playlists.
- Added backup hints and progress messages for better user experience during playlist deletion.
- Ensured consistency in language across all supported translations (de, el, en, es, fr, it, ja, ko, nl, pl, pt, ru, tr, zh, zhtw).
Entire-Checkpoint: c6e522b4276c
- Set default appearance for mat-form-field to 'outline' and dynamic subscript sizing in app.config.ts.
- Adjust dialog dimensions in workspace-shell-actions.service.ts for better responsiveness.
- Refactor settings.component.scss to remove specific mat-form-field font size overrides.
- Enhance global styles in m3-theme.scss for outlined inputs, ensuring consistency across the application.
- Modify workspace-command-palette styles to improve visual integration with the overall theme.
- Revamp add-playlist-dialog component to utilize segmented controls for category selection, improving UX.
- Update file-upload component to provide better feedback on file selection and drag-and-drop interactions.
- Clean up text and URL upload components by removing unnecessary placeholders and improving layout.
- Refine stalker-portal-import component by removing placeholder text for clarity.
Entire-Checkpoint: c6e522b4276c
feat: Update category view to improve empty state representation
style: Refactor category view styles for better layout and responsiveness
fix: Adjust favorites component navigation logic for better routing
refactor: Improve playlist error view structure and styles for clarity
style: Revamp playlist error view styles for consistency and readability
feat: Update portal channels list to use new channel list item component
style: Clean up portal channels list styles for improved layout
refactor: Optimize portal channels list component logic and structure
feat: Implement recently viewed component navigation improvements
fix: Update global search results component for better routing
test: Add unit tests for search results component functionality
feat: Enhance search results component to handle initial query
fix: Update EPG queue service to manage preview limits effectively
style: Clean up nav list styles for better visual consistency
- Updated GridListComponent to use a skeleton loading UI during data fetching.
- Introduced GridListItem interface for better type safety on items input.
- Improved paginator integration with proper type definitions.
- Refactored loading state handling to utilize computed properties.
feat: Improve portal rail links with accessibility features
- Added aria-current attribute to indicate active links.
- Enhanced styling for active links with new CSS variables for selection colors.
style: Refactor styles for portal rail links and context panels
- Updated SCSS for portal rail links to improve hover and active states.
- Introduced new styles for context skeletons in workspace context panel.
feat: Implement skeleton loaders in stalker main container and workspace context panel
- Replaced ngx-skeleton-loader with custom skeleton components for better control.
- Added skeleton loading states for categories in stalker main container.
style: Refine recently added component styles and interactions
- Enhanced section styling with active state indicators and transitions.
- Improved layout and visual feedback for recently added items.
fix: Correctly handle section activation in recently added component
- Added logic to determine active sections based on selected content type.
refactor: Update XtreamShellComponent to improve import overlay handling
- Changed isImporting check to showImportOverlay for better clarity.
- Refactored section handling to use signals for state management.
style: Introduce new selection colors and effects across the application
- Added new CSS variables for selection colors and effects to enhance UI consistency.
- Updated various components to utilize new selection styles for better user experience.
- Refactored settings component HTML structure for improved layout and accessibility.
- Introduced a sidebar navigation for settings sections with smooth scrolling.
- Added dynamic visibility for settings sections based on the desktop environment.
- Enhanced form controls with better styling and responsiveness.
- Updated settings form validation and error handling for remote control port.
- Improved overall styling with new SCSS variables and layout adjustments.
- Adjusted dialog dimensions in navigation components for better user experience.
Reduce the settings page container height calculation from
calc(100vh - 100px) to calc(100vh - 70px) so the content fits the
visible viewport when the header height is 70px. This prevents
unnecessary vertical overflow and avoids extra whitespace at the
bottom of the settings page.
Add support for displaying local remote-control URLs and QR code in the
Settings UI, including styles for URL list, row layout, monospaced links,
and a QR container. Expose a new global API signature getLocalIpAddresses
for retrieving local IPs.
Fix several UI issues:
- Correct typo in header method name (opedAddPlaylistDialog -> openAddPlaylistDialog).
- Fix malformed GitHub URL and collapse img tag formatting.
- Reformat imports and viewChild usage for readability.
Change local development backend URL to localhost:3000 in the local
environment to point to the running local API during development.
These changes improve developer ergonomics (local backend), add a remote
control discovery UX for users on the same network, and tidy up header
bugs and formatting.