Skip to content

fix(portals): live channels sidebar overwrites shell panel width in localStorage#1114

Merged
4gray merged 1 commit into
4gray:masterfrom
PavluntiyJ:fix/live-sidebar-width-collision
Jul 4, 2026
Merged

fix(portals): live channels sidebar overwrites shell panel width in localStorage#1114
4gray merged 1 commit into
4gray:masterfrom
PavluntiyJ:fix/live-sidebar-width-collision

Conversation

@PavluntiyJ

Copy link
Copy Markdown
Contributor

Problem

The live-layout channels sidebar (Xtream and Stalker) persists its width under the shared sidebar-width localStorage key — the same key used by the workspace shell context panel (the Groups/categories sidebar).

The unified key works well for the shell slot panels (sources / category / settings / collection), which swap in one place and are never visible together. But on the Live TV view the category context panel and the channels sidebar are on screen at the same time, both writing to the same key:

  1. Open an Xtream (or Stalker) playlist → Live TV, so both the Groups panel and the channels sidebar are visible.
  2. Resize the channels sidebar to e.g. 550px.
  3. Reload — the Groups panel now also tries to restore 550px (clamped to its own max), and whichever panel was resized last always wins for both.

Fix

Give the live channels sidebar its own live-channels-sidebar-width key. Xtream and Stalker share it, since those two never coexist — same reasoning as the existing unified key, applied at the correct boundary. This follows the precedent already in the codebase: unified-live-tab-sidebar-width and m3u-groups-nav-width are dedicated keys for exactly this kind of content-area panel.

The unified sidebar-width key is deliberately left in place for the shell slot panels, where sharing one width across swapped-in panels is the intended behavior (ff76eb1).

Existing users lose only the stored width for this one sidebar on first load after the update (it falls back to the 400px default once, then persists normally).

Testing

  • Added a regression test in both live-stream-layout.component.spec.ts and stalker-live-stream-layout.component.spec.ts asserting the sidebar uses the dedicated key — verified it fails against the old shared key and passes with the fix.
  • pnpm nx test portal-xtream-feature (35 tests) and pnpm nx test portal-stalker-feature (17 tests) pass.
  • pnpm nx run-many --target=lint --projects=portal-xtream-feature,portal-stalker-feature clean.

🤖 Generated with Claude Code

…hell panel

The live-layout channels sidebar (Xtream and Stalker) persisted its
width under the shared "sidebar-width" localStorage key — the same key
used by the workspace shell context panel. Unlike the shell panel
variants, which swap in one slot and never coexist, the channels
sidebar is on screen at the same time as the category context panel,
so resizing either one silently overwrote the other's stored width and
both snapped to the same size after a reload.

Give the live channels sidebar its own "live-channels-sidebar-width"
key (shared between Xtream and Stalker, which never coexist), matching
the precedent already set by unified-live-tab-sidebar-width and
m3u-groups-nav-width. The unified key remains in place for the shell
slot panels, where sharing is intentional.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@greptile-apps

greptile-apps Bot commented Jul 1, 2026

Copy link
Copy Markdown

Greptile Summary

This PR fixes a localStorage key collision where the live channels sidebar (Xtream and Stalker) was sharing the sidebar-width key with the workspace shell context panel — two panels that are simultaneously visible on the Live TV view, causing each resize to overwrite the other's stored width.

  • Changes storageKey="sidebar-width"storageKey="live-channels-sidebar-width" in both live-stream-layout.component.html and stalker-live-stream-layout.component.html; the ResizableDirective correctly routes any key absent from SIDEBAR_WIDTH_KEY_ALIASES directly to localStorage, so no directive changes are needed.
  • Adds a regression test in each component's spec that queries the rendered .sidebar DOM attribute and asserts the dedicated key, verifying the fix fails on the old shared key and passes with the new one.

Confidence Score: 5/5

Safe to merge — the change is a minimal two-character string swap in two template files, backed by regression tests in both affected components.

The fix is surgical and self-contained: two HTML templates each change a single attribute value, and the ResizableDirective already handles unknown keys by using them as-is (path verified in resizable.directive.ts resolveStorageKey()). The new key is intentionally absent from SIDEBAR_WIDTH_KEY_ALIASES, which is correct. Xtream and Stalker portals are mutually exclusive at runtime, so sharing live-channels-sidebar-width between them is sound. The only user-visible impact is a one-time width reset to the 400px default, which the PR explicitly acknowledges.

No files require special attention.

Important Files Changed

Filename Overview
libs/portal/xtream/feature/src/lib/live-stream-layout/live-stream-layout.component.html Single-line change: storageKey updated from sidebar-width to live-channels-sidebar-width on the appResizable directive, correctly isolating the live channels sidebar width from the shell context panel.
libs/portal/stalker/feature/src/lib/stalker-live-stream-layout/stalker-live-stream-layout.component.html Same single-line storageKey fix as the Xtream component; Stalker and Xtream share the new dedicated key since these two portals are never rendered simultaneously.
libs/portal/xtream/feature/src/lib/live-stream-layout/live-stream-layout.component.spec.ts New regression test asserts the sidebar renders with the dedicated key; test sets selectedCategoryId to ensure the conditional sidebar block renders before querying the DOM.
libs/portal/stalker/feature/src/lib/stalker-live-stream-layout/stalker-live-stream-layout.component.spec.ts New regression test mirrors the Xtream spec; the Stalker mock store already initialises selectedCategoryId to '1001', so the sidebar div is guaranteed to render when detectChanges() is called.

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
    participant User
    participant LiveSidebar as Live Channels Sidebar (Xtream / Stalker)
    participant ShellPanel as Shell Context Panel (Groups / Categories)
    participant LS as localStorage

    Note over LiveSidebar,ShellPanel: Both panels visible simultaneously on Live TV view

    rect rgb(255, 220, 220)
        Note over User,LS: Before fix — shared key causes overwrite
        User->>LiveSidebar: Resize to 550px
        LiveSidebar->>LS: setItem("sidebar-width", "550")
        User->>User: Reload page
        ShellPanel->>LS: getItem("sidebar-width")
        LS-->>ShellPanel: "550" (wrong — overwritten by live sidebar)
    end

    rect rgb(220, 255, 220)
        Note over User,LS: After fix — dedicated key preserves each panel's width
        User->>LiveSidebar: Resize to 550px
        LiveSidebar->>LS: setItem("live-channels-sidebar-width", "550")
        User->>User: Reload page
        ShellPanel->>LS: getItem("sidebar-width")
        LS-->>ShellPanel: "300" (correct — shell key untouched)
        LiveSidebar->>LS: getItem("live-channels-sidebar-width")
        LS-->>LiveSidebar: "550" (correct — dedicated key)
    end
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
    participant User
    participant LiveSidebar as Live Channels Sidebar (Xtream / Stalker)
    participant ShellPanel as Shell Context Panel (Groups / Categories)
    participant LS as localStorage

    Note over LiveSidebar,ShellPanel: Both panels visible simultaneously on Live TV view

    rect rgb(255, 220, 220)
        Note over User,LS: Before fix — shared key causes overwrite
        User->>LiveSidebar: Resize to 550px
        LiveSidebar->>LS: setItem("sidebar-width", "550")
        User->>User: Reload page
        ShellPanel->>LS: getItem("sidebar-width")
        LS-->>ShellPanel: "550" (wrong — overwritten by live sidebar)
    end

    rect rgb(220, 255, 220)
        Note over User,LS: After fix — dedicated key preserves each panel's width
        User->>LiveSidebar: Resize to 550px
        LiveSidebar->>LS: setItem("live-channels-sidebar-width", "550")
        User->>User: Reload page
        ShellPanel->>LS: getItem("sidebar-width")
        LS-->>ShellPanel: "300" (correct — shell key untouched)
        LiveSidebar->>LS: getItem("live-channels-sidebar-width")
        LS-->>LiveSidebar: "550" (correct — dedicated key)
    end
Loading

Reviews (1): Last reviewed commit: "fix(portals): stop live channels sidebar..." | Re-trigger Greptile

@codecov-commenter

Copy link
Copy Markdown

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 57.35%. Comparing base (e91cbd5) to head (49263fd).
⚠️ Report is 1965 commits behind head on master.
❗ Your organization needs to install the Codecov GitHub app to enable full functionality.

❗ There is a different number of reports uploaded between BASE (e91cbd5) and HEAD (49263fd). Click for more details.

HEAD has 4 uploads less than BASE
Flag BASE (e91cbd5) HEAD (49263fd)
4 0
Additional details and impacted files
@@             Coverage Diff             @@
##           master    #1114       +/-   ##
===========================================
- Coverage   71.05%   57.35%   -13.71%     
===========================================
  Files          40      559      +519     
  Lines         691    32572    +31881     
  Branches       87     7096     +7009     
===========================================
+ Hits          491    18681    +18190     
- Misses        176    11092    +10916     
- Partials       24     2799     +2775     
Flag Coverage Δ
unit 57.35% <ø> (?)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@4gray

4gray commented Jul 4, 2026

Copy link
Copy Markdown
Owner

Thank you for the fix!

@4gray 4gray merged commit 342175f into 4gray:master Jul 4, 2026
16 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants