Skip to content

Fix/Add search filter options to channel page search#3437

Open
bhavyagor12 wants to merge 5 commits intomasterfrom
fix/channel-search-options
Open

Fix/Add search filter options to channel page search#3437
bhavyagor12 wants to merge 5 commits intomasterfrom
fix/channel-search-options

Conversation

@bhavyagor12
Copy link

@bhavyagor12 bhavyagor12 commented Mar 5, 2026

Issue #2855
Add search filter options to channel page search

Integrate SearchOptions into channel content tab, allowing users to filter search results by media type, upload date, sort order, duration, and exact match.
Adds isChannelSearch mode to SearchOptions component with a dedicated media type filter UI.

Summary by CodeRabbit

  • New Features

    • Added search filters for content type, freshness, duration (including custom min/max ranges) and an oldest-first sort option.
    • SearchResults and listing now accept and persist additional filter parameters per page.
  • Improvements

    • Price, repost and members-only filters are disabled automatically during channel searches.
    • Tag search is hidden during channel searches for a streamlined interface.

Issue #2855
 Add search filter options to channel page search

 Integrate SearchOptions into channel content tab, allowing users to
 filter search results by media type, upload date, sort order, duration,
 and exact match. Adds isChannelSearch mode to SearchOptions component
 with a dedicated media type filter UI.
@bhavyagor12 bhavyagor12 self-assigned this Mar 5, 2026
@coderabbitai
Copy link

coderabbitai bot commented Mar 5, 2026

📝 Walkthrough

Walkthrough

Adds an isChannelSearch flag to claim search filter context and propagates channel-search-aware behavior and new filter params (contentType, freshness, duration, sortBy) through claim list header, content tab view, and SearchResults to adjust UI control states and API query parameters.

Changes

Cohort / File(s) Summary
Context
ui/contexts/claimSearchFilterContext.jsx
Add isChannelSearch: false to the default ClaimSearchFilterContext shape.
Claim list header controls
ui/component/claimListHeader/internal/additionalFilters/view.jsx, ui/component/claimListHeader/view.jsx
Make "Hide reposts" and "Hide members-only" checkboxes disabled when isChannelSearch (and repost also when contentType is CS.CLAIM_REPOST); disable Paid/Price select when isChannelSearch; render TagSearch only when not isChannelSearch.
Content tab view & routing
ui/page/claim/.../contentTab/view.jsx
Read query params (contentType, freshness, sortByParam, durationParam), persist min/max duration state, derive/expose isChannelSearch from searchQuery length, and forward new params into subcomponents.
SearchResults and API integration
ui/page/claim/.../contentTab/internal/searchResults.jsx
Add props (sortByParam, contentType, freshness, durationParam, customMinMinutes, customMaxMinutes); map to lighthouse params (mediaType, time_filter, duration min/max), combine with existing duration bounds, extend effect dependencies and lighthouse search calls to include these filters and sort adjustments.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant ContentView as ContentTab/View
    participant FilterCtx as ClaimSearchFilterContext
    participant SearchResults
    participant LighthouseAPI as Lighthouse API

    User->>ContentView: enter search / set filters (query, contentType, freshness, duration, sort)
    ContentView->>FilterCtx: set isChannelSearch based on query length
    ContentView->>SearchResults: pass props (contentType, freshness, durationParam, sortByParam, customMin/Max)
    SearchResults->>LighthouseAPI: query with mediaType/time_filter/duration_min/duration_max/sort
    LighthouseAPI-->>SearchResults: return results
    SearchResults-->>ContentView: render results
    ContentView-->>User: display results
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

"I nibbled through props and flags today,
Pushed filters and queries on my way,
Channels now hush some options neat,
Durations and sorts march to the beat,
🐇✨ — cheers to tidy search display!"

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title accurately reflects the main changes: adding/fixing search filter options for the channel page search functionality.

✏️ 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 fix/channel-search-options

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.

Wire existing ClaimListDiscover filters (content type, sort order,
 freshness, duration) into the lighthouse search used on channel pages.
 Grey out filters not supported by lighthouse (price, tags, hide
 reposts, hide members-only). Removes the duplicate SearchOptions UI
that was added previously.
@bhavyagor12 bhavyagor12 marked this pull request as ready for review March 5, 2026 07:00
Copy link

@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

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@ui/page/claim/internal/claimPageComponent/internal/channelPage/tabs/contentTab/internal/searchResults.jsx`:
- Around line 113-114: The current merge for duration bounds uses logical OR
which lets filter params override base constraints; change the logic for
effectiveMinDuration and effectiveMaxDuration to compute the intersection: set
effectiveMinDuration to the greater of minDuration and durationMinParam (when
present) and effectiveMaxDuration to the lesser of maxDuration and
durationMaxParam (when present), making sure to coerce/validate numeric values
and handle undefined/null so you don't relax enforced caps (use
Math.max/Math.min semantics or equivalent around
durationMinParam/durationMaxParam and minDuration/maxDuration).

In
`@ui/page/claim/internal/claimPageComponent/internal/channelPage/tabs/contentTab/view.jsx`:
- Line 103: isChannelSearch currently uses raw searchQuery length which treats
whitespace-only input as a search; change the detection to use trimmed input by
checking searchQuery.trim().length > 2 instead of searchQuery.length > 2 so
channel-search mode aligns with the existing trimmed search triggering logic
(update the isChannelSearch declaration that references searchQuery).

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b5f9e77b-183f-4eab-b34b-0af03fb18201

📥 Commits

Reviewing files that changed from the base of the PR and between 839a483 and 759a1e9.

📒 Files selected for processing (5)
  • ui/component/claimListHeader/internal/additionalFilters/view.jsx
  • ui/component/claimListHeader/view.jsx
  • ui/contexts/claimSearchFilterContext.jsx
  • ui/page/claim/internal/claimPageComponent/internal/channelPage/tabs/contentTab/internal/searchResults.jsx
  • ui/page/claim/internal/claimPageComponent/internal/channelPage/tabs/contentTab/view.jsx

Copy link

@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.

🧹 Nitpick comments (1)
ui/page/claim/internal/claimPageComponent/internal/channelPage/tabs/contentTab/internal/searchResults.jsx (1)

86-101: Consider extracting magic numbers to named constants.

The values 240 (4 minutes) and 1200 (20 minutes) represent duration thresholds in seconds. For maintainability and consistency, consider using constants (possibly from CS.DURATION or SETTINGS) if they're defined elsewhere, or defining them locally.

♻️ Example refactor
+const SHORT_DURATION_SECONDS = 240;  // 4 minutes
+const LONG_DURATION_SECONDS = 1200;  // 20 minutes
+
 const durationMinParam = React.useMemo(() => {
   if (!durationParam || durationParam === CS.DURATION.ALL) return null;
   if (durationParam === CS.DURATION.SHORT) return null;
-  if (durationParam === CS.DURATION.LONG) return 1200;
+  if (durationParam === CS.DURATION.LONG) return LONG_DURATION_SECONDS;
   if (durationParam === CS.DURATION.CUSTOM && customMinMinutes) return customMinMinutes * 60;
   return null;
 }, [durationParam, customMinMinutes]);

 const durationMaxParam = React.useMemo(() => {
   if (!durationParam || durationParam === CS.DURATION.ALL) return null;
-  if (durationParam === CS.DURATION.SHORT) return 240;
+  if (durationParam === CS.DURATION.SHORT) return SHORT_DURATION_SECONDS;
   if (durationParam === CS.DURATION.LONG) return null;
   if (durationParam === CS.DURATION.CUSTOM && customMaxMinutes) return customMaxMinutes * 60;
   return null;
 }, [durationParam, customMaxMinutes]);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@ui/page/claim/internal/claimPageComponent/internal/channelPage/tabs/contentTab/internal/searchResults.jsx`
around lines 86 - 101, The hard-coded thresholds 240 and 1200 in the duration
mapping should be replaced with named constants for clarity and reuse; update
the logic in the React.useMemo blocks that compute durationMinParam and
durationMaxParam to use descriptive constants (e.g.,
DURATION_THRESHOLD_SHORT_MAX and DURATION_THRESHOLD_LONG_MIN) instead of 240 and
1200, or reference existing values on CS.DURATION/SETTINGS if available, keeping
the same conditional behavior with customMinMinutes/customMaxMinutes unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In
`@ui/page/claim/internal/claimPageComponent/internal/channelPage/tabs/contentTab/internal/searchResults.jsx`:
- Around line 86-101: The hard-coded thresholds 240 and 1200 in the duration
mapping should be replaced with named constants for clarity and reuse; update
the logic in the React.useMemo blocks that compute durationMinParam and
durationMaxParam to use descriptive constants (e.g.,
DURATION_THRESHOLD_SHORT_MAX and DURATION_THRESHOLD_LONG_MIN) instead of 240 and
1200, or reference existing values on CS.DURATION/SETTINGS if available, keeping
the same conditional behavior with customMinMinutes/customMaxMinutes unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 30117fef-4008-4a40-a1c4-edfec8f2b58e

📥 Commits

Reviewing files that changed from the base of the PR and between 759a1e9 and 486946f.

📒 Files selected for processing (2)
  • ui/page/claim/internal/claimPageComponent/internal/channelPage/tabs/contentTab/internal/searchResults.jsx
  • ui/page/claim/internal/claimPageComponent/internal/channelPage/tabs/contentTab/view.jsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • ui/page/claim/internal/claimPageComponent/internal/channelPage/tabs/contentTab/view.jsx

Copy link

@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: 1

♻️ Duplicate comments (1)
ui/page/claim/internal/claimPageComponent/internal/channelPage/tabs/contentTab/internal/searchResults.jsx (1)

116-119: ⚠️ Potential issue | 🟡 Minor

Duration bound merge still drops explicit 0 bounds and can relax constraints.

effectiveMinDuration / effectiveMaxDuration and query emission treat 0 as “absent”. That can skip an explicit bound and alter intersection behavior for edge inputs. Use nullish checks instead of truthy checks end-to-end.

Suggested fix
-  const effectiveMinDuration =
-    durationMinParam && minDuration ? Math.max(durationMinParam, minDuration) : durationMinParam || minDuration || null;
-  const effectiveMaxDuration =
-    durationMaxParam && maxDuration ? Math.min(durationMaxParam, maxDuration) : durationMaxParam || maxDuration || null;
+  const effectiveMinDuration =
+    durationMinParam == null
+      ? minDuration ?? null
+      : minDuration == null
+      ? durationMinParam
+      : Math.max(durationMinParam, minDuration);
+
+  const effectiveMaxDuration =
+    durationMaxParam == null
+      ? maxDuration ?? null
+      : maxDuration == null
+      ? durationMaxParam
+      : Math.min(durationMaxParam, maxDuration);
...
-            (effectiveMinDuration ? `&${SEARCH_OPTIONS.MIN_DURATION}=${effectiveMinDuration}` : '') +
-            (effectiveMaxDuration ? `&${SEARCH_OPTIONS.MAX_DURATION}=${effectiveMaxDuration}` : '') +
+            (effectiveMinDuration != null ? `&${SEARCH_OPTIONS.MIN_DURATION}=${effectiveMinDuration}` : '') +
+            (effectiveMaxDuration != null ? `&${SEARCH_OPTIONS.MAX_DURATION}=${effectiveMaxDuration}` : '') +

Also applies to: 151-152

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

In
`@ui/page/claim/internal/claimPageComponent/internal/channelPage/tabs/contentTab/internal/searchResults.jsx`
around lines 116 - 119, The merge logic for effectiveMinDuration and
effectiveMaxDuration treats 0 as falsy and can drop explicit zero bounds; update
the calculations to use nullish checks instead of truthy checks (e.g., test
durationMinParam != null and minDuration != null, and durationMaxParam != null
and maxDuration != null) so you compute Math.max/Math.min only when both are
non-null and otherwise pick the non-null value (or null if both null). Apply the
same nullish-check fix to the duplicate logic at the other occurrence (the code
around the second pair at lines 151-152).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@ui/page/claim/internal/claimPageComponent/internal/channelPage/tabs/contentTab/internal/searchResults.jsx`:
- Around line 90-104: The duration memoizers (durationMinParam and
durationMaxParam) convert customMinMinutes/customMaxMinutes to seconds without
validating values or the min>max relationship; update the React.useMemo blocks
to first validate that customMinMinutes and customMaxMinutes are finite numbers
>= 0 before converting, produce null if invalid, and enforce the range (e.g., if
computed minSeconds > maxSeconds return null or normalize/swap) so invalid or
inverted ranges don’t propagate; reference the durationMinParam and
durationMaxParam useMemo callbacks and their dependency arrays when making this
change.

---

Duplicate comments:
In
`@ui/page/claim/internal/claimPageComponent/internal/channelPage/tabs/contentTab/internal/searchResults.jsx`:
- Around line 116-119: The merge logic for effectiveMinDuration and
effectiveMaxDuration treats 0 as falsy and can drop explicit zero bounds; update
the calculations to use nullish checks instead of truthy checks (e.g., test
durationMinParam != null and minDuration != null, and durationMaxParam != null
and maxDuration != null) so you compute Math.max/Math.min only when both are
non-null and otherwise pick the non-null value (or null if both null). Apply the
same nullish-check fix to the duplicate logic at the other occurrence (the code
around the second pair at lines 151-152).

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b570e5a7-6718-4c2b-a9f2-c5eed94d198a

📥 Commits

Reviewing files that changed from the base of the PR and between 486946f and 23fde56.

📒 Files selected for processing (1)
  • ui/page/claim/internal/claimPageComponent/internal/channelPage/tabs/contentTab/internal/searchResults.jsx

Comment on lines +90 to +104
const durationMinParam = React.useMemo(() => {
if (!durationParam || durationParam === CS.DURATION.ALL) return null;
if (durationParam === CS.DURATION.SHORT) return null;
if (durationParam === CS.DURATION.LONG) return LONG_DURATION_SECONDS;
if (durationParam === CS.DURATION.CUSTOM && customMinMinutes) return customMinMinutes * 60;
return null;
}, [durationParam, customMinMinutes]);

const durationMaxParam = React.useMemo(() => {
if (!durationParam || durationParam === CS.DURATION.ALL) return null;
if (durationParam === CS.DURATION.SHORT) return SHORT_DURATION_SECONDS;
if (durationParam === CS.DURATION.LONG) return null;
if (durationParam === CS.DURATION.CUSTOM && customMaxMinutes) return customMaxMinutes * 60;
return null;
}, [durationParam, customMaxMinutes]);
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Guard custom duration inputs before converting to seconds.

customMinMinutes / customMaxMinutes are converted without validating finite, non-negative values, and there’s no guard for min > max. Invalid ranges can produce unstable or empty result sets unexpectedly.

Suggested fix
+  const toSeconds = (minutes) => {
+    if (minutes == null) return null;
+    if (!Number.isFinite(minutes) || minutes < 0) return null;
+    return Math.floor(minutes * 60);
+  };

   const durationMinParam = React.useMemo(() => {
     if (!durationParam || durationParam === CS.DURATION.ALL) return null;
     if (durationParam === CS.DURATION.SHORT) return null;
     if (durationParam === CS.DURATION.LONG) return LONG_DURATION_SECONDS;
-    if (durationParam === CS.DURATION.CUSTOM && customMinMinutes) return customMinMinutes * 60;
+    if (durationParam === CS.DURATION.CUSTOM) return toSeconds(customMinMinutes);
     return null;
   }, [durationParam, customMinMinutes]);

   const durationMaxParam = React.useMemo(() => {
     if (!durationParam || durationParam === CS.DURATION.ALL) return null;
     if (durationParam === CS.DURATION.SHORT) return SHORT_DURATION_SECONDS;
     if (durationParam === CS.DURATION.LONG) return null;
-    if (durationParam === CS.DURATION.CUSTOM && customMaxMinutes) return customMaxMinutes * 60;
+    if (durationParam === CS.DURATION.CUSTOM) return toSeconds(customMaxMinutes);
     return null;
   }, [durationParam, customMaxMinutes]);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@ui/page/claim/internal/claimPageComponent/internal/channelPage/tabs/contentTab/internal/searchResults.jsx`
around lines 90 - 104, The duration memoizers (durationMinParam and
durationMaxParam) convert customMinMinutes/customMaxMinutes to seconds without
validating values or the min>max relationship; update the React.useMemo blocks
to first validate that customMinMinutes and customMaxMinutes are finite numbers
>= 0 before converting, produce null if invalid, and enforce the range (e.g., if
computed minSeconds > maxSeconds return null or normalize/swap) so invalid or
inverted ranges don’t propagate; reference the durationMinParam and
durationMaxParam useMemo callbacks and their dependency arrays when making this
change.

Copy link

@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.

♻️ Duplicate comments (1)
ui/page/claim/internal/claimPageComponent/internal/channelPage/tabs/contentTab/internal/searchResults.jsx (1)

90-104: ⚠️ Potential issue | 🟡 Minor

Validate custom duration inputs before converting to seconds.

At Line 94 and Line 102, truthy checks still allow invalid numeric inputs (e.g. negative values) and silently drop 0. Please guard for finite, non-negative numbers before conversion.

Suggested fix
+  const toSeconds = (minutes) => {
+    if (minutes == null) return null;
+    if (!Number.isFinite(minutes) || minutes < 0) return null;
+    return Math.floor(minutes * 60);
+  };
+
   const durationMinParam = React.useMemo(() => {
     if (!durationParam || durationParam === CS.DURATION.ALL) return null;
     if (durationParam === CS.DURATION.SHORT) return null;
     if (durationParam === CS.DURATION.LONG) return LONG_DURATION_SECONDS;
-    if (durationParam === CS.DURATION.CUSTOM && customMinMinutes) return customMinMinutes * 60;
+    if (durationParam === CS.DURATION.CUSTOM) return toSeconds(customMinMinutes);
     return null;
   }, [durationParam, customMinMinutes]);
 
   const durationMaxParam = React.useMemo(() => {
     if (!durationParam || durationParam === CS.DURATION.ALL) return null;
     if (durationParam === CS.DURATION.SHORT) return SHORT_DURATION_SECONDS;
     if (durationParam === CS.DURATION.LONG) return null;
-    if (durationParam === CS.DURATION.CUSTOM && customMaxMinutes) return customMaxMinutes * 60;
+    if (durationParam === CS.DURATION.CUSTOM) return toSeconds(customMaxMinutes);
     return null;
   }, [durationParam, customMaxMinutes]);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@ui/page/claim/internal/claimPageComponent/internal/channelPage/tabs/contentTab/internal/searchResults.jsx`
around lines 90 - 104, The durationMinParam and durationMaxParam use truthy
checks that drop 0 and allow invalid numbers; update the guards in the
React.useMemo blocks for durationMinParam and durationMaxParam to validate
customMinMinutes/customMaxMinutes with a finite, non-negative numeric check
(e.g. Number.isFinite(value) && value >= 0) before converting minutes to
seconds, and keep the existing branches for CS.DURATION.SHORT, CS.DURATION.LONG,
CS.DURATION.CUSTOM and the constants
LONG_DURATION_SECONDS/SHORT_DURATION_SECONDS unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In
`@ui/page/claim/internal/claimPageComponent/internal/channelPage/tabs/contentTab/internal/searchResults.jsx`:
- Around line 90-104: The durationMinParam and durationMaxParam use truthy
checks that drop 0 and allow invalid numbers; update the guards in the
React.useMemo blocks for durationMinParam and durationMaxParam to validate
customMinMinutes/customMaxMinutes with a finite, non-negative numeric check
(e.g. Number.isFinite(value) && value >= 0) before converting minutes to
seconds, and keep the existing branches for CS.DURATION.SHORT, CS.DURATION.LONG,
CS.DURATION.CUSTOM and the constants
LONG_DURATION_SECONDS/SHORT_DURATION_SECONDS unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: d63556a3-2010-4c94-bf8e-8ea9b281e44b

📥 Commits

Reviewing files that changed from the base of the PR and between 23fde56 and 1b89330.

📒 Files selected for processing (1)
  • ui/page/claim/internal/claimPageComponent/internal/channelPage/tabs/contentTab/internal/searchResults.jsx

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