Skip to content

feat(web): right-click context menu, standalone hero carousel, instant tab navigation & UI layout fixes - #501

Open
Himanth-reddy wants to merge 13 commits into
ProdigyV21:mainfrom
Himanth-reddy:feature/web-right-click-context-menu
Open

feat(web): right-click context menu, standalone hero carousel, instant tab navigation & UI layout fixes#501
Himanth-reddy wants to merge 13 commits into
ProdigyV21:mainfrom
Himanth-reddy:feature/web-right-click-context-menu

Conversation

@Himanth-reddy

Copy link
Copy Markdown
Collaborator

Summary of Changes

This PR introduces a right-click context menu, converts the home hero banner into an auto-rotating carousel, resolves UI performance/lag bottlenecks on navigation and hover, and fixes layout clipping and alignment issues across the web app.


Detailed Breakdown of Issues, Causes, and Solutions

1. Standalone Auto-Rotating Hero Carousel & Hover Lag Elimination

  • Problem & Cause: Sweeping the mouse cursor rapidly across media cards in catalog rails triggered immediate onMouseEnter prefetch API calls and hero preview state updates for every passed card. Sweeping over 10–15 cards in a second spawned 30+ network requests and React state updates, saturating the main thread and causing noticeable cursor lag and UI stutter.
  • Solution:
    • Decoupled rail card hover from the hero banner. Replaced mouse-driven hero preview swaps with an autonomous, auto-rotating hero carousel that advances every 6.5s (pausing on hover).
    • Added a 120ms hover intent debounce timer (MediaCard.tsx) so fast cursor sweeps across rails produce zero API calls or state thrashing.
    • Added manual indicator dots positioned on the desktop right side, plus touch swipe gesture support (onTouchStart/onTouchEnd with a 50px threshold) for mobile.

2. Instant Tab Navigation & Details Return (0ms Delay)

  • Problem & Cause:
    1. Switching between navigation tabs (Home, Search, Watchlist, Live TV, Settings) conditionally unmounted <HomeScreen /> completely ({section === "home" && <HomeScreen />}). Re-entering Home forced component re-initialization, catalog state re-seeding, and network calls.
    2. Opening the item details view (selected ? <DetailsDrawer /> : <...screens...>) completely unmounted all active tab screens. Closing Details forced <HomeScreen /> to re-mount from scratch, creating a ~1s loading delay.
    3. useEffect in HomeScreen blocked setting displayHero until background title-treatment logo PNG/SVG requests (getLogoUrl) finished over the network.
  • Solution:
    • Maintained warm tab DOM instances in AppShell.tsx using CSS display toggling (<div style={{ display: !selected && section === "home" ? "contents" : "none" }}>). Returning to Home or closing Details is now 100% instantaneous (0ms) with zero re-fetching or re-mounting.
    • Updated HomeScreen to synchronously render displayHero immediately while getLogoUrl fetches asynchronously in the background.

3. Fixed Hero Overview Text Clipping & Vertical Layout Shifts ("Going Up & Down")

  • Problem & Cause:
    1. .hero-overview used a rigid pixel height: clamp(44px, 5.2vh, 60px) !important; combined with line-clamping and JS character truncation (desc.slice(0, 150)). On various viewport heights, line-height misalignments caused the 2nd/3rd line of text to be cut off horizontally ("tucked under").
    2. When height was auto, overview descriptions with 1 or 2 lines shrank the text box height. This caused the Play & More Info buttons (.hero-actions) to jump up and down vertically when carousel slides auto-rotated between titles with different text lengths.
  • Solution:
    • Removed hardcoded JS character slicing (desc.slice(0, 150)).
    • Set min-height: calc(3 * 1.45em) !important; height: calc(3 * 1.45em) !important; on desktop (calc(2 * 1.45em) on mobile).
    • Reserved a fixed 3-line box height at all times so text is never clipped mid-line and Play/More Info buttons stay 100% vertically locked without layout jumping.

4. Live TV Screen Top Clearance

  • Problem & Cause: .screen.livetv-shell was targeted by a padding-top: 0 CSS rule, causing the Live TV heading, search input, and playlist buttons to render at pixel 0 directly underneath the fixed top navigation bar.
  • Solution: Removed .screen.livetv-shell from padding-top: 0 and set padding-top: clamp(112px, 14.3vh, 154px) in globals.css, aligning Live TV top clearance with Home, Watchlist, Search, and Browse screens.

5. GPU-Accelerated Shimmer & Skeleton Placeholders

  • Problem & Cause: Card skeletons and loading poster placeholders used background-position gradient animations, causing frequent browser layout re-paints and scroll stutter.
  • Solution: Upgraded loading shimmers to hardware-accelerated transform: translateX() compositor animations (will-change: transform) running smoothly at 60/120fps.

6. PC Right-Click & Mobile Long-Press Context Menu

  • Problem & Cause: Desktop users had no direct right-click context menu for media items, requiring opening the full details drawer to access actions like bookmarking or marking watched.
  • Solution: Implemented MediaContextMenu component and attached PC right-click (onContextMenu) and mobile long-press handlers across media cards.

Verification

  • Tested tab switching speed across Home, Search, Watchlist, Live TV, and Settings (instantaneous 0ms switch).
  • Verified opening and closing DetailsDrawer maintains Home screen state with zero reload delay.
  • Tested hero carousel auto-rotation, manual dot navigation, and touch swiping.
  • Verified hero text layout stability across various desktop and mobile screen resolutions.
  • Verified TypeScript build passes (npx tsc --noEmit).

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 473c244bd8

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

<div style={{ display: !selected && section === "home" ? "contents" : "none" }}><HomeScreen /></div>
<div style={{ display: !selected && section === "search" ? "contents" : "none" }}><SearchScreen /></div>
<div style={{ display: !selected && section === "watchlist" ? "contents" : "none" }}><WatchlistScreen /></div>
<div style={{ display: !selected && section === "tv" ? "contents" : "none" }}><LiveTvScreen /></div>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Gate Live TV mounting until the tab is visible

Because this now mounts <LiveTvScreen /> even while it is hidden, its mount effect in LiveTvScreen.tsx lines 88-96 calls refreshIptv() whenever playlists exist and the snapshot is stale. For users with IPTV configured, simply opening Home now starts the expensive playlist refresh/parsing path in the background even if they never visit TV, regressing startup/home responsiveness; keep this screen lazy or pass visibility so the refresh only runs when the TV tab is active.

Useful? React with 👍 / 👎.

type="button"
className={`context-menu-action-btn ${act.danger ? "is-danger" : ""}`}
onClick={() => {
act.action();

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Close custom context-menu actions before running them

This only invokes the supplied action, while the custom actions added for episode/season menus and Live TV rows do not call closeContextMenu() themselves. In those contexts, choosing actions such as Play Channel or Play Episode leaves the z-index 2000 scrim/card open over the player or source picker until the user dismisses it manually, unlike the default media actions which close first.

Useful? React with 👍 / 👎.

Comment thread web/lib/store.tsx
markWatchedLocally({ mediaType: item.mediaType, id: item.id, season: seasonNumber, episode: episodeNumber }, !currentlyWatched);
setToast(!currentlyWatched ? "Marked as watched." : "Marked as unwatched.");

if (activeSyncProvider() !== "none") {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Persist context-menu watched changes to ARVIO Cloud

When a user is signed into ARVIO Cloud but has no Trakt/MDBList provider connected, this branch is skipped after only markWatchedLocally() runs, so the context-menu “Mark as watched” toast succeeds but the change is lost on refresh/reload and Cloud continue-watching can reappear. The existing detail-page flow persists the same action through saveProgress(...); this shared context-menu path needs the same Cloud write or it should not report a durable watched update.

Useful? React with 👍 / 👎.

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.

1 participant