Skip to content

quick vote prerender#2182

Merged
simo6529 merged 1 commit intomainfrom
quick-vote-prerender
Mar 30, 2026
Merged

quick vote prerender#2182
simo6529 merged 1 commit intomainfrom
quick-vote-prerender

Conversation

@simo6529
Copy link
Copy Markdown
Collaborator

@simo6529 simo6529 commented Mar 30, 2026

Summary by CodeRabbit

  • New Features

    • Added optional description toggle control to quick vote preview dialogs.
    • Implemented next-item preview preloading for smoother navigation between items (image-based previews only).
  • Performance

    • Optimized media loading strategy for preview images with eager and in-view loading modes.

Signed-off-by: Simo <simo@6529.io>
@sonarqubecloud
Copy link
Copy Markdown

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Mar 30, 2026

📝 Walkthrough

Walkthrough

This PR implements media preload behavior for the Memes Quick Vote dialog by introducing a MediaLoadStrategy type, threading a loadStrategy prop through media rendering components, and updating the dialog to track and preload the next queued item's preview with conditional rendering based on media type.

Changes

Cohort / File(s) Summary
Media Loading Type
components/drops/view/item/content/media/mediaLoadStrategy.ts
New exported type MediaLoadStrategy defining "eager" | "in-view" for controlling image loading behavior.
Media Components
components/drops/view/item/content/media/DropListItemContentMedia.tsx, DropListItemContentMediaImage.tsx, MediaDisplay.tsx, MediaDisplayImage.tsx
Added optional loadStrategy prop (default "in-view") throughout the media rendering pipeline; when "eager", images load immediately rather than on viewport intersection; native loading="eager" attribute applied conditionally.
Memes Quick Vote Dialog
components/brain/left-sidebar/waves/memes-quick-vote/MemesQuickVoteDialog.tsx
Added nextDrop and sessionId props; introduced MemesQuickVotePreviewStack component to render active and preloaded next-item previews; preloaded preview conditionally hidden and only shown for non-GLB media; updated content key to include state changes.
Memes Quick Vote Preview
components/brain/left-sidebar/waves/memes-quick-vote/MemesQuickVotePreview.tsx
Added renderMode: "active" | "preloaded" prop; gated interactive behaviors (swipe, overlay labels, description toggle) to active mode; wired loadStrategy ("eager" for preloaded, "in-view" for active) into media content; updated preview HTML usage and test IDs.
Memes Quick Vote Description
components/brain/left-sidebar/waves/memes-quick-vote/MemesQuickVoteDescription.tsx
Added optional allowToggle?: boolean prop (default true); "See more/See less" button now renders only when both allowToggle and isOverflowing are true.
Quick Vote Hooks
hooks/useMemesQuickVoteQueue.ts, useMemesQuickVoteDialogController.ts
Enhanced UseMemesQuickVoteQueueResult with nextDrop: ExtendedDrop | null field; useMemesQuickVoteQueue derives and memoizes next drop from lookahead state with voteability filtering; useMemesQuickVoteDialogController forwards nextDrop to dialog state.
Dialog Tests
__tests__/components/brain/left-sidebar/waves/memes-quick-vote/MemesQuickVoteDialog.test.tsx
Expanded createDrop helper to accept optional media overrides; added createDialogProps factory; introduced test coverage for preload behavior (assertions for "next" card presence/absence based on media type and dialog state); refactored control-reset tests.

Sequence Diagram

sequenceDiagram
    participant User
    participant Dialog as MemesQuickVoteDialog
    participant Queue as useMemesQuickVoteQueue
    participant PreviewStack as MemesQuickVotePreviewStack
    participant ActivePreview as Preview<br/>(renderMode: active)
    participant PreloadedPreview as Preview<br/>(renderMode: preloaded)
    participant Media as Media<br/>Components

    User->>Dialog: Open dialog with activeDrop
    Dialog->>Queue: Request nextDrop from lookahead
    Queue-->>Dialog: Return nextDrop (if voteable & not GLB)
    
    Dialog->>PreviewStack: Render with activeDrop & nextDrop
    
    PreviewStack->>ActivePreview: Render active item<br/>(interactive, loadStrategy: in-view)
    ActivePreview->>Media: Load media on viewport
    Media-->>ActivePreview: Display interactive preview
    
    PreviewStack->>PreloadedPreview: Render next item hidden<br/>(non-interactive, loadStrategy: eager)
    PreloadedPreview->>Media: Load media eagerly
    Media-->>PreloadedPreview: Preload next preview
    
    User->>Dialog: Vote or skip activeDrop
    Dialog->>Dialog: Update to next drop
    PreviewStack->>ActivePreview: Swap to preloaded preview<br/>(now interactive)
    PreloadedPreview->>PreloadedPreview: Unmount/hidden
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • PR #2159: Direct modifications to MemesQuickVoteDialog, MemesQuickVotePreview, and related hooks for nextDrop/sessionId handling and preview/preload behavior.
  • PR #2138: Modifies media rendering pipeline (MediaDisplay, DropListItemContentMedia) with complementary load behaviors and interaction gating.
  • PR #2173: Updates MemesQuickVoteDescription component and description toggle overflow logic that integrates with this PR's allowToggle prop additions.

Suggested reviewers

  • ragnep
  • prxt6529

Poem

🐰 With eager whiskers twitched to preload the next,
our quick-vote preview hops ahead—no context vexed.
Active dances, preloaded waits in shadows still,
a toggle here, a loadStrategy there—
smooth transitions satisfy our quick-voting thrill! 🎨✨

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 6.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'quick vote prerender' is vague and generic, lacking clarity about what specific aspect of quick vote functionality is being prerendered. Consider a more descriptive title such as 'Add media preloading for next quick vote item' or 'Implement next-item preview prerendering in quick vote dialog' to better convey the main change.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch quick-vote-prerender

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (2)
components/drops/view/item/content/media/MediaDisplay.tsx (1)

177-186: Avoid returning null for eager HTML when no preview image exists.

If loadStrategy === "eager" and previewImageUrl is absent, this path currently blanks media entirely. Prefer falling through to existing HTML handling so content still renders.

Suggested patch
   if (mediaType === MediaType.HTML) {
-    if (loadStrategy === "eager") {
-      return previewImageUrl ? (
-        <MediaDisplayImage
-          src={previewImageUrl}
-          imageScale={imageScale}
-          loadStrategy={loadStrategy}
-        />
-      ) : null;
+    if (loadStrategy === "eager" && previewImageUrl) {
+      return (
+        <MediaDisplayImage
+          src={previewImageUrl}
+          imageScale={imageScale}
+          loadStrategy={loadStrategy}
+        />
+      );
     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@components/drops/view/item/content/media/MediaDisplay.tsx` around lines 177 -
186, The eager-HTML branch in MediaDisplay currently returns null when
previewImageUrl is missing, causing HTML media to be blank; change the logic in
the MediaDisplay component so that when mediaType === MediaType.HTML and
loadStrategy === "eager" you only render <MediaDisplayImage> if previewImageUrl
exists, but do not return null when it doesn't—instead let execution fall
through to the existing HTML rendering path (the same path used for non-eager
HTML) so the HTML content still renders; locate the conditional handling around
mediaType === MediaType.HTML, loadStrategy, previewImageUrl and
MediaDisplayImage and remove or refactor the early `return null` so fall-through
occurs.
components/brain/left-sidebar/waves/memes-quick-vote/MemesQuickVoteDialog.tsx (1)

47-65: Reuse the shared GLB classifier for this preload guard.

This re-implements the same GLB/GLTF detection already used in components/drops/view/item/content/media/DropListItemContentMedia.tsx Lines 42-70. If those rules drift, quick vote can start eagerly mounting a model that the renderer itself still classifies as GLB, which is exactly the path this guard is meant to block.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@components/brain/left-sidebar/waves/memes-quick-vote/MemesQuickVoteDialog.tsx`
around lines 47 - 65, The getQuickVotePreloadedNextDrop function reimplements
GLB/GLTF detection; instead import and call the shared GLB classifier used by
DropListItemContentMedia (the classifier exported from
components/drops/view/item/content/media/DropListItemContentMedia.tsx) rather
than duplicating mime/url checks—update getQuickVotePreloadedNextDrop to return
null when that shared classifier reports the media is a GLB/GLTF and return
nextDrop otherwise, referencing getQuickVotePreloadedNextDrop and the shared
classifier name when you change the import and conditional.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@__tests__/components/brain/left-sidebar/waves/memes-quick-vote/MemesQuickVoteDialog.test.tsx`:
- Around line 116-135: Tests still instantiate MemesQuickVoteDialog only via
isOpen/sessionId/onClose or by toggling useIsMobileScreenMock, but the component
now reads queue state from props and derives mobile mode via useMediaQuery;
update tests to use createDialogProps(...) to supply full prop-driven state
(e.g., activeDrop, sessionId, uncastPower, submitVote, etc.) and stop using
useIsMobileScreenMock, instead mock matchMedia/useMediaQuery to control mobile
vs desktop behavior; locate uses of MemesQuickVoteDialog in tests and replace
direct prop sets with createDialogProps(overrides) and adjust media mocks to
reflect mobile or not so assertions exercise the proper code paths.
- Line 130: The test mock for skipDrop is synchronous but the component
(MemesQuickVoteDialog.tsx) calls skipDrop(activeDrop).then(...), so replace the
bare mock skipDrop: jest.fn() with an async-resolving mock (e.g., use
jest.fn().mockResolvedValue(...) or a function returning Promise.resolve()) so
calls to skipDrop(activeDrop).then(...) work without throwing; update the mock
declaration named skipDrop in MemesQuickVoteDialog.test.tsx accordingly.

---

Nitpick comments:
In
`@components/brain/left-sidebar/waves/memes-quick-vote/MemesQuickVoteDialog.tsx`:
- Around line 47-65: The getQuickVotePreloadedNextDrop function reimplements
GLB/GLTF detection; instead import and call the shared GLB classifier used by
DropListItemContentMedia (the classifier exported from
components/drops/view/item/content/media/DropListItemContentMedia.tsx) rather
than duplicating mime/url checks—update getQuickVotePreloadedNextDrop to return
null when that shared classifier reports the media is a GLB/GLTF and return
nextDrop otherwise, referencing getQuickVotePreloadedNextDrop and the shared
classifier name when you change the import and conditional.

In `@components/drops/view/item/content/media/MediaDisplay.tsx`:
- Around line 177-186: The eager-HTML branch in MediaDisplay currently returns
null when previewImageUrl is missing, causing HTML media to be blank; change the
logic in the MediaDisplay component so that when mediaType === MediaType.HTML
and loadStrategy === "eager" you only render <MediaDisplayImage> if
previewImageUrl exists, but do not return null when it doesn't—instead let
execution fall through to the existing HTML rendering path (the same path used
for non-eager HTML) so the HTML content still renders; locate the conditional
handling around mediaType === MediaType.HTML, loadStrategy, previewImageUrl and
MediaDisplayImage and remove or refactor the early `return null` so fall-through
occurs.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 3fe8cbfb-7910-4b50-97d3-3a3a85598052

📥 Commits

Reviewing files that changed from the base of the PR and between 6c6400e and ebbf714.

📒 Files selected for processing (11)
  • __tests__/components/brain/left-sidebar/waves/memes-quick-vote/MemesQuickVoteDialog.test.tsx
  • components/brain/left-sidebar/waves/memes-quick-vote/MemesQuickVoteDescription.tsx
  • components/brain/left-sidebar/waves/memes-quick-vote/MemesQuickVoteDialog.tsx
  • components/brain/left-sidebar/waves/memes-quick-vote/MemesQuickVotePreview.tsx
  • components/drops/view/item/content/media/DropListItemContentMedia.tsx
  • components/drops/view/item/content/media/DropListItemContentMediaImage.tsx
  • components/drops/view/item/content/media/MediaDisplay.tsx
  • components/drops/view/item/content/media/MediaDisplayImage.tsx
  • components/drops/view/item/content/media/mediaLoadStrategy.ts
  • hooks/useMemesQuickVoteDialogController.ts
  • hooks/useMemesQuickVoteQueue.ts

@simo6529 simo6529 merged commit 2be1edc into main Mar 30, 2026
8 checks passed
@simo6529 simo6529 deleted the quick-vote-prerender branch March 30, 2026 12:58
This was referenced Apr 2, 2026
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.

2 participants