Skip to content

curation wave my votes#1980

Merged
simo6529 merged 2 commits intomainfrom
curation-wave-my-votes
Feb 23, 2026
Merged

curation wave my votes#1980
simo6529 merged 2 commits intomainfrom
curation-wave-my-votes

Conversation

@simo6529
Copy link
Copy Markdown
Collaborator

@simo6529 simo6529 commented Feb 23, 2026

Summary by CodeRabbit

  • New Features

    • Support for curation waves with tailored content behavior and NFT preview media for curation drops.
  • Improvements

    • My Votes tab shown for curation and memes waves; improved tab navigation and auto-switching when tabs hide.
    • Better profile fallbacks (use primary address when handle missing) and more robust media/MIME handling.
  • Removals

    • Legacy profile raters table and related table/header/item/wrapper UI components removed.

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

coderabbitai Bot commented Feb 23, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between be35743 and 0291416.

📒 Files selected for processing (3)
  • __tests__/components/brain/my-stream/votes/MyStreamWaveMyVote.test.tsx
  • components/brain/my-stream/votes/MyStreamWaveMyVote.tsx
  • components/react-query-wrapper/ReactQueryWrapper.tsx
🚧 Files skipped from review as they are similar to previous changes (3)
  • components/brain/my-stream/votes/MyStreamWaveMyVote.tsx
  • components/react-query-wrapper/ReactQueryWrapper.tsx
  • tests/components/brain/my-stream/votes/MyStreamWaveMyVote.test.tsx

📝 Walkthrough

Walkthrough

Adds curation-wave awareness across brain UI and tests, implements curation-based NFT preview selection and MIME inference for My Votes, consolidates ProfileRatersParams into ReactQueryWrapper, and removes the Profile Raters table suite and several small UI helper components/types.

Changes

Cohort / File(s) Summary
Brain mobile & tabs
__tests__/components/brain/BrainMobile.test.tsx, components/brain/BrainMobile.tsx, __tests__/components/brain/mobile/BrainMobileTabs.test.tsx, components/brain/mobile/BrainMobileTabs.tsx
Introduce/use isCurationWave in useWave mocks and components; gate My Votes rendering on memes OR curation waves; add isCurationWave to effect deps; styling/className tweaks in mobile tabs; new test for curation rank wave.
My Stream tab logic
__tests__/components/brain/my-stream/MyStreamWaveDesktopTabs.test.tsx, components/brain/my-stream/MyStreamWaveDesktopTabs.tsx
Introduce TAB_LABELS constant; adjust availableTabs filtering to consider isCurationWave; refine active-tab auto-switching and include isCurationWave in memo/effect deps; update tests.
My Votes media & tests
__tests__/components/brain/my-stream/votes/MyStreamWaveMyVote.test.tsx, components/brain/my-stream/votes/MyStreamWaveMyVote.tsx
Add curation-preview media resolver (select ready previews, fallback to media_uri), MIME inference utilities, memoized selection using useSeizeSettings, pass resolved URL/MIME to MediaDisplay, and update tests/mocks to cover curation cases.
ReactQueryWrapper type & guards
components/react-query-wrapper/ReactQueryWrapper.tsx
Introduce and export a local ProfileRatersParams interface; treat SortDirection as a type import; add a safer guard for oldData?.pages.length in addReplyToDropDiscussion.
Profile raters suite removal
components/user/utils/raters-table/ProfileRatersTable.tsx, components/user/utils/raters-table/ProfileRatersTableBody.tsx, components/user/utils/raters-table/ProfileRatersTableHeader.tsx, components/user/utils/raters-table/ProfileRatersTableHeaderSortableCell.tsx, components/user/utils/raters-table/ProfileRatersTableItem.tsx, components/user/utils/raters-table/wrapper/ProfileRatersTableWrapper.tsx, components/user/utils/raters-table/wrapper/ProfileRatersTableWrapperHeader.tsx
Removed the entire Profile Raters table, body, header, sortable-header cell, item, wrapper, and wrapper header — deleting pagination, sorting, data-fetching wrapper, types, and related UI.
Removed small UI components
components/profile-activity/ProfileName.tsx, components/user/rep/new-rep/UserPageRepNewRepSearchHeader.tsx, components/user/utils/UserTableHeaderWrapper.tsx, components/utils/CommonFilterTargetSelect.tsx, components/utils/table/CommonTableWrapper.tsx
Deleted several small UI components (ProfileName + enum, rep search header, table header wrapper, filter radio group, common table wrapper).
Helpers & types cleanup
helpers/server.helpers.ts, types/enums.ts
Removed getInitialRatersParams and related raters imports; removed ProfileRatersTableType enum (CIC/REP variants).
Tests string/format normalization
Various __tests__/* files
Standardized test string quoting and mock formatting; several mocks expanded to include explicit isCurationWave/wave timer fields.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • ragnep

Poem

🐰 A little rabbit on the wire,
Hops through waves of curation fire,
Previews chosen, MIME in tow,
Tables gone — the code can grow,
Tiny paws make changes higher.

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'curation wave my votes' directly corresponds to the main objective of this changeset: adding curation wave support to the My Votes feature across multiple components and tests.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch curation-wave-my-votes

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: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
components/brain/my-stream/votes/MyStreamWaveMyVote.tsx (1)

257-270: ⚠️ Potential issue | 🟡 Minor

Author link text is empty when handle is null.

Line 258/263 correctly falls back to primary_address for the href and window.open, but Line 269 renders only {drop.author.handle} — which would be empty/invisible if the author has no handle.

🔧 Suggested fix
-                {drop.author.handle}
+                {drop.author.handle ?? drop.author.primary_address}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@components/brain/my-stream/votes/MyStreamWaveMyVote.tsx` around lines 257 -
270, The link text currently renders only drop.author.handle which will be empty
when handle is null; update the JSX in MyStreamWaveMyVote so the displayed text
uses the same fallback as the href/window.open (e.g., replace the rendered
expression drop.author.handle with drop.author.handle ??
drop.author.primary_address) so the primary address is shown when handle is
absent; keep the existing Link href and window.open logic and class names
unchanged.
🧹 Nitpick comments (3)
components/react-query-wrapper/ReactQueryWrapper.tsx (1)

800-803: Prefer simpler null guard; oldData.pages itself is unguarded.

typeof oldData?.pages.length !== "number" only short-circuits on oldData being nullish (via ?.). If oldData is defined but oldData.pages is somehow undefined/null at runtime, accessing .length on it would still throw a TypeError — the optional chain doesn't protect that step.

Additionally, Array.prototype.length always returns a number, so the typeof check adds no practical coverage over a simple !oldData, making the condition more verbose without extra safety.

♻️ Suggested simplification
-        if (
-          typeof oldData?.pages.length !== "number" ||
-          oldData.pages.length === 0
-        ) {
+        if (!oldData?.pages?.length) {

Or equivalently, for explicit clarity:

-        if (
-          typeof oldData?.pages.length !== "number" ||
-          oldData.pages.length === 0
-        ) {
+        if (!oldData || oldData.pages.length === 0) {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@components/react-query-wrapper/ReactQueryWrapper.tsx` around lines 800 - 803,
The condition in ReactQueryWrapper.tsx that reads `typeof oldData?.pages.length
!== "number" || oldData.pages.length === 0` is unsafe because it can access
`.length` on an undefined `oldData.pages` and the typeof check is redundant;
change the guard to directly ensure pages is an array (or at least defined)
before checking length — e.g., replace the condition with a simple explicit
guard like `!oldData?.pages || oldData.pages.length === 0` or use
`!Array.isArray(oldData?.pages) || oldData.pages.length === 0` so
`oldData.pages` is safely checked before accessing `.length`.
components/brain/mobile/BrainMobileTabs.tsx (1)

102-104: Pre-existing typo: otucomeButtonTextClasses should be outcomeButtonTextClasses.

Not introduced in this PR, but worth noting if you're touching this area.

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

In `@components/brain/mobile/BrainMobileTabs.tsx` around lines 102 - 104, Fix the
misspelled variable name otucomeButtonTextClasses by renaming it to
outcomeButtonTextClasses wherever it’s declared and referenced (e.g., in
BrainMobileTabs.tsx where the const is defined and any JSX or helper functions
that consume it), ensuring imports/exports and any related props or state names
are updated to match the new spelling so no references break.
components/brain/my-stream/MyStreamWaveDesktopTabs.tsx (1)

188-196: Minor: contradictory optional chain + non-null assertion.

Line 194 uses options[0]?.key! — the ?. and ! contradict each other. Since options.length > 0 is already checked, options[0].key suffices.

🔧 Suggested simplification
-      setActiveTab(options[0]?.key!);
+      setActiveTab(options[0].key);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@components/brain/my-stream/MyStreamWaveDesktopTabs.tsx` around lines 188 -
196, The conditional uses a contradictory optional chain and non-null assertion
in the useEffect when calling setActiveTab with options[0]?.key! — since you
already check options.length > 0, replace the expression with the non-optional
property access (options[0].key) to remove the unnecessary ?. and !; update the
useEffect block that defines isMyVotesHidden/isFaqHidden and calls setActiveTab
to use options[0].key instead.
🤖 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/my-stream/votes/MyStreamWaveMyVote.test.tsx`:
- Around line 46-56: The test fixture `drop` used in MyStreamWaveMyVote.test.tsx
is missing the top_raters property which causes MyStreamWaveMyVote.tsx (which
calls drop.top_raters.slice(0, 3)) to throw; fix by adding a top_raters array to
the `drop` object in the test (e.g., top_raters: [] or an array of the same
rater objects the component expects) so slice can be called safely, or
alternatively adjust the fixture to include the expected rater shape used by
MyStreamWaveMyVote.

In `@components/brain/my-stream/votes/MyStreamWaveMyVote.tsx`:
- Around line 284-286: The React key for the top-raters list uses
voter.profile.handle which can be null and the tooltip also renders
voter.profile.handle without a fallback; update the map key in
MyStreamWaveMyVote (the slice/map that iterates drop.top_raters) to use a
guaranteed unique identifier such as voter.profile.id or
voter.profile.primary_address (e.g., key={voter.profile.id ||
voter.profile.primary_address}) and change the tooltip/label rendering (where
{voter.profile.handle} is used) to provide a safe fallback like
voter.profile.handle || voter.profile.primary_address || 'Unknown user' so
null/undefined handles don’t produce duplicate keys or show "null".
- Around line 144-150: The curation check can fail due to case differences:
update the isCurationWave call in the curationPreviewMedia useMemo to pass a
normalized ID (e.g., call isCurationWave(drop.wave.id.toLowerCase())) and update
the dependency array accordingly (use drop.wave.id and/or its lowercased form)
so the memo and resolveCurationPreviewMedia logic use a case-insensitive
comparison; alternatively ensure isCurationWave itself normalizes its input, but
in this file adjust the isCurationWave invocation to use .toLowerCase() to match
other usages.

---

Outside diff comments:
In `@components/brain/my-stream/votes/MyStreamWaveMyVote.tsx`:
- Around line 257-270: The link text currently renders only drop.author.handle
which will be empty when handle is null; update the JSX in MyStreamWaveMyVote so
the displayed text uses the same fallback as the href/window.open (e.g., replace
the rendered expression drop.author.handle with drop.author.handle ??
drop.author.primary_address) so the primary address is shown when handle is
absent; keep the existing Link href and window.open logic and class names
unchanged.

---

Nitpick comments:
In `@components/brain/mobile/BrainMobileTabs.tsx`:
- Around line 102-104: Fix the misspelled variable name otucomeButtonTextClasses
by renaming it to outcomeButtonTextClasses wherever it’s declared and referenced
(e.g., in BrainMobileTabs.tsx where the const is defined and any JSX or helper
functions that consume it), ensuring imports/exports and any related props or
state names are updated to match the new spelling so no references break.

In `@components/brain/my-stream/MyStreamWaveDesktopTabs.tsx`:
- Around line 188-196: The conditional uses a contradictory optional chain and
non-null assertion in the useEffect when calling setActiveTab with
options[0]?.key! — since you already check options.length > 0, replace the
expression with the non-optional property access (options[0].key) to remove the
unnecessary ?. and !; update the useEffect block that defines
isMyVotesHidden/isFaqHidden and calls setActiveTab to use options[0].key
instead.

In `@components/react-query-wrapper/ReactQueryWrapper.tsx`:
- Around line 800-803: The condition in ReactQueryWrapper.tsx that reads `typeof
oldData?.pages.length !== "number" || oldData.pages.length === 0` is unsafe
because it can access `.length` on an undefined `oldData.pages` and the typeof
check is redundant; change the guard to directly ensure pages is an array (or at
least defined) before checking length — e.g., replace the condition with a
simple explicit guard like `!oldData?.pages || oldData.pages.length === 0` or
use `!Array.isArray(oldData?.pages) || oldData.pages.length === 0` so
`oldData.pages` is safely checked before accessing `.length`.

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 30924cc and be35743.

📒 Files selected for processing (23)
  • __tests__/components/brain/BrainMobile.test.tsx
  • __tests__/components/brain/mobile/BrainMobileTabs.test.tsx
  • __tests__/components/brain/my-stream/MyStreamWaveDesktopTabs.test.tsx
  • __tests__/components/brain/my-stream/votes/MyStreamWaveMyVote.test.tsx
  • components/brain/BrainMobile.tsx
  • components/brain/mobile/BrainMobileTabs.tsx
  • components/brain/my-stream/MyStreamWaveDesktopTabs.tsx
  • components/brain/my-stream/votes/MyStreamWaveMyVote.tsx
  • components/profile-activity/ProfileName.tsx
  • components/react-query-wrapper/ReactQueryWrapper.tsx
  • components/user/rep/new-rep/UserPageRepNewRepSearchHeader.tsx
  • components/user/utils/UserTableHeaderWrapper.tsx
  • components/user/utils/raters-table/ProfileRatersTable.tsx
  • components/user/utils/raters-table/ProfileRatersTableBody.tsx
  • components/user/utils/raters-table/ProfileRatersTableHeader.tsx
  • components/user/utils/raters-table/ProfileRatersTableHeaderSortableCell.tsx
  • components/user/utils/raters-table/ProfileRatersTableItem.tsx
  • components/user/utils/raters-table/wrapper/ProfileRatersTableWrapper.tsx
  • components/user/utils/raters-table/wrapper/ProfileRatersTableWrapperHeader.tsx
  • components/utils/CommonFilterTargetSelect.tsx
  • components/utils/table/CommonTableWrapper.tsx
  • helpers/server.helpers.ts
  • types/enums.ts
💤 Files with no reviewable changes (14)
  • types/enums.ts
  • helpers/server.helpers.ts
  • components/user/utils/raters-table/ProfileRatersTableHeaderSortableCell.tsx
  • components/utils/CommonFilterTargetSelect.tsx
  • components/user/utils/raters-table/wrapper/ProfileRatersTableWrapperHeader.tsx
  • components/profile-activity/ProfileName.tsx
  • components/user/utils/raters-table/ProfileRatersTableBody.tsx
  • components/user/utils/raters-table/ProfileRatersTableItem.tsx
  • components/user/utils/raters-table/ProfileRatersTable.tsx
  • components/user/utils/raters-table/ProfileRatersTableHeader.tsx
  • components/user/utils/UserTableHeaderWrapper.tsx
  • components/user/utils/raters-table/wrapper/ProfileRatersTableWrapper.tsx
  • components/utils/table/CommonTableWrapper.tsx
  • components/user/rep/new-rep/UserPageRepNewRepSearchHeader.tsx

Comment thread components/brain/my-stream/votes/MyStreamWaveMyVote.tsx
Comment thread components/brain/my-stream/votes/MyStreamWaveMyVote.tsx
Signed-off-by: Simo <simo@6529.io>
@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud Bot commented Feb 23, 2026

Quality Gate Passed Quality Gate passed

Issues
0 New issues
5 Accepted issues

Measures
0 Security Hotspots
No data about Coverage
0.0% Duplication on New Code

See analysis details on SonarQube Cloud

@simo6529 simo6529 merged commit 39ab644 into main Feb 23, 2026
7 checks passed
@simo6529 simo6529 deleted the curation-wave-my-votes branch February 23, 2026 22:08
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