Skip to content

feat(discover): add a new Discover page Slider for Available Media#2600

Open
ryanmfransen wants to merge 3 commits intoseerr-team:developfrom
ryanmfransen:feature-media-library-filter
Open

feat(discover): add a new Discover page Slider for Available Media#2600
ryanmfransen wants to merge 3 commits intoseerr-team:developfrom
ryanmfransen:feature-media-library-filter

Conversation

@ryanmfransen
Copy link
Copy Markdown

@ryanmfransen ryanmfransen commented Feb 28, 2026

…brary (#658)

Created a new Slider on the Discover page with links to the full local library view.

Description

I created a new 'My Media Library' Slider at the bottom of the Discover page. This lists 20 of your local media in the standard slider form, and if more than 20 media is found in your library, a 'See More' card is display.

You can also go to the full page My Media Library using the links beside the heading of the Slider.

My Media Library is all your local media, movies and shows with status|status4k of available, and partiallyavailable.

Allows users to quickly see the contents of their (Partially)|Available library.

How Has This Been Tested?

Tested on my local machine using my Jellyfin media library, containing a partially available series and available movies, totalling > 20.

Add Jellyfin library.
Load Discover page, view new Slider.
Click link to library in header.
Scroll slider all the way to the right, click 'See More'

Load '/discover/library' observer full page view of library, available and partiallyavailable.

Manual tests for local (containerized server) Jellyfin library.
Added cypress test for basic navigation of new components.
All testing done with build running locally on my Macbook using Chrome.

I tried to introduce a minimal footprint of these changes, avoiding as many touchpoints in existing codebase as possible.

I heavily relied on AI for the following:

  • Understand modern open source contribution hygiene and best practices.
  • Grok current app architecture and TMDB integration.
  • Evaluate my design and implementation ideas.
  • Review my code, provide feedback from a sw engineering perspective.
  • Review changes for a maintainer PR perspective, assess missing things, etc.

Screenshots / Logs (if applicable)

Screenshot 2026-02-27 at 6 16 26 PM Screenshot 2026-02-27 at 6 16 13 PM Screenshot 2026-02-27 at 6 16 05 PM

Checklist:

  • I have read and followed the contribution guidelines.
  • Disclosed any use of AI (see our policy)
  • I have updated the documentation accordingly.
  • All new and existing tests passed.
  • Successful build pnpm build
  • Translation keys pnpm i18n:extract
  • Database migration (if required)

Summary by CodeRabbit

  • New Features
    • Added "Available Media" slider to the Discover page for quick access
    • New dedicated library page enables browsing and discovering available media with infinite scrolling support

@ryanmfransen ryanmfransen requested a review from a team as a code owner February 28, 2026 04:17
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Feb 28, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This PR introduces an "Available Media" feature to the discover page, enabling users to view media currently available on their server. The changes include a new enum member and slider configuration, new React components for displaying available media with infinite scrolling, a dedicated library page, frontend integration across discover components, translation strings, and E2E test coverage.

Changes

Cohort / File(s) Summary
Backend Constants & Enum
server/constants/discover.ts
Added MY_MEDIA_LIBRARY enum member to DiscoverSliderType and configured default slider entry with enabled state and order 12.
Backend Routes
server/routes/discover.ts
Standardized paging behavior by introducing local page variable with default value of 1, replacing direct Number(query.page) calls in TMDB discovery endpoints.
Available Media Components
src/components/Discover/AvailableMedia/index.tsx, src/components/Discover/AvailableMediaSlider/index.tsx
Added two new React components: AvailableMedia implements infinite scrolling with SWR's useSWRInfinite for paginated media fetching; AvailableMediaSlider renders a slider preview with link to full library page.
Discover Integration
src/components/Discover/index.tsx, src/components/Discover/DiscoverSliderEdit/index.tsx
Integrated AvailableMediaSlider component rendering and added case handler for MY_MEDIA_LIBRARY slider type in both display and edit modes.
UI Constants & Translations
src/components/Discover/constants.ts, src/i18n/locale/en.json
Added availableMedia translation key to slider titles with value "Available Media".
Pages & Routing
src/pages/discover/library.tsx
Created new Next.js page rendering the AvailableMedia component at /discover/library route.
E2E Testing
cypress/e2e/discover.cy.ts
Added test navigating from Available Media slider header to library page, validating URL and page header.

Sequence Diagram(s)

sequenceDiagram
    actor User
    participant Browser as Browser
    participant API as API Server
    participant DB as Media Database

    User->>Browser: Click Available Media slider header
    Browser->>API: GET /api/v1/media?filter=allavailable&take=20&sort=mediaAdded
    API->>DB: Query available media
    DB-->>API: Return paginated results
    API-->>Browser: Return media items + pageInfo
    Browser->>Browser: Navigate to /discover/library
    Browser->>API: GET /api/v1/media?filter=allavailable&take=PAGE_SIZE&sort=mediaAdded&skip=0
    API->>DB: Query page 1
    DB-->>API: Return results
    API-->>Browser: Return first page
    Browser->>Browser: Render available media list
    User->>Browser: Scroll down to end of list
    Browser->>API: GET /api/v1/media?filter=allavailable&...&skip=PAGE_SIZE
    API->>DB: Query next page
    DB-->>API: Return results
    API-->>Browser: Return next page
    Browser->>Browser: Append media items
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 A library of wonders, filtered clear,
Available media, brought near and dear,
Scroll through the server's finest display,
Clean up collections in the easiest way!
What's truly yours shines bright and true,
Jellyseerr shows it just for you! 📚✨

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed The PR implements all core requirements from #658: provides a filter showing only available items on the media server, displays local media status, enables library management visibility, and includes a functional Discover slider and dedicated library page.
Out of Scope Changes check ✅ Passed All changes are directly related to implementing the My Media Library feature. Minor refactoring in discover.ts (page variable extraction) is a supporting improvement without introducing unrelated functionality.
Title check ✅ Passed The title accurately describes the main change: adding a new Discover page Slider for Available Media, which is the core feature implemented across all modified files.

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


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.

🧹 Nitpick comments (2)
cypress/e2e/discover.cy.ts (1)

215-224: Add API interception for test consistency and stability.

The MyMediaLibrarySlider component fetches data from /api/v1/media?filter=allavailable&take=20&sort=mediaAdded using useSWR on component mount. This test should intercept that API call before visiting the page, consistent with other tests in this file (trending, popular movies, upcoming movies, etc.). Relying solely on the 15s timeout can lead to flakiness.

♻️ Suggested improvement
   it('navigates from My Media Library slider to the library page', () => {
+    cy.intercept('/api/v1/media?filter=allavailable*').as('getLibraryMedia');
     cy.visit('/');
+    cy.wait('@getLibraryMedia');

     cy.contains('.slider-header .slider-title', 'My Media Library', {
       timeout: 15000,
     }).click();
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@cypress/e2e/discover.cy.ts` around lines 215 - 224, This test "navigates from
My Media Library slider to the library page" is missing an API interception for
the MyMediaLibrarySlider data fetch; before calling cy.visit('/'), intercept the
GET to '/api/v1/media?filter=allavailable&take=20&sort=mediaAdded' (or the
equivalent query) and stub a deterministic response (use the same fixture
pattern as other tests) so useSWR returns immediately; update the test to add
cy.intercept(...) for that endpoint prior to cy.visit('/') and then proceed with
the existing assertions (cy.contains(...).click(), cy.url().should(...),
cy.get(...).should(...)).
src/components/Discover/MyMediaLibrary/index.tsx (1)

45-50: Consider memoizing the scroll callback.

The inline arrow function () => setSize(size + 1) creates a new function reference on each render. Depending on how useVerticalScroll handles its callback dependency, this could potentially cause unnecessary effect re-runs. Wrapping it in useCallback would prevent this.

♻️ Proposed refactor
+import { useCallback } from 'react';
+
 const MyMediaLibrary = () => {
   const intl = useIntl();
   const { data, error, size, setSize, isValidating } =
     useSWRInfinite<MediaResultsResponse>(
       // ... key function
     );

   const lastPage = data?.[data.length - 1];

+  const loadMore = useCallback(() => {
+    setSize((prevSize) => prevSize + 1);
+  }, [setSize]);
+
   useVerticalScroll(
-    () => setSize(size + 1),
+    loadMore,
     !isValidating &&
       !!data &&
       (lastPage?.pageInfo.page ?? 0) < (lastPage?.pageInfo.pages ?? 0)
   );
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/Discover/MyMediaLibrary/index.tsx` around lines 45 - 50,
Memoize the scroll callback passed to useVerticalScroll to avoid recreating the
function each render: wrap the inline arrow () => setSize(size + 1) in
React.useCallback and pass that memoized callback to useVerticalScroll, with a
dependency array that includes size (and setSize if not stable) so the callback
updates correctly when size changes; keep the existing second argument (the
boolean conditional using isValidating, data, lastPage) 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 `@cypress/e2e/discover.cy.ts`:
- Around line 215-224: This test "navigates from My Media Library slider to the
library page" is missing an API interception for the MyMediaLibrarySlider data
fetch; before calling cy.visit('/'), intercept the GET to
'/api/v1/media?filter=allavailable&take=20&sort=mediaAdded' (or the equivalent
query) and stub a deterministic response (use the same fixture pattern as other
tests) so useSWR returns immediately; update the test to add cy.intercept(...)
for that endpoint prior to cy.visit('/') and then proceed with the existing
assertions (cy.contains(...).click(), cy.url().should(...),
cy.get(...).should(...)).

In `@src/components/Discover/MyMediaLibrary/index.tsx`:
- Around line 45-50: Memoize the scroll callback passed to useVerticalScroll to
avoid recreating the function each render: wrap the inline arrow () =>
setSize(size + 1) in React.useCallback and pass that memoized callback to
useVerticalScroll, with a dependency array that includes size (and setSize if
not stable) so the callback updates correctly when size changes; keep the
existing second argument (the boolean conditional using isValidating, data,
lastPage) unchanged.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5c34c91 and 3da1ee9.

📒 Files selected for processing (10)
  • cypress/e2e/discover.cy.ts
  • server/constants/discover.ts
  • server/routes/discover.ts
  • src/components/Discover/DiscoverSliderEdit/index.tsx
  • src/components/Discover/MyMediaLibrary/index.tsx
  • src/components/Discover/MyMediaLibrarySlider/index.tsx
  • src/components/Discover/constants.ts
  • src/components/Discover/index.tsx
  • src/i18n/locale/en.json
  • src/pages/discover/library.tsx

…ary (seerr-team#658)

Created a new Slider on the Discover page with links to the full local library view.
@ryanmfransen ryanmfransen force-pushed the feature-media-library-filter branch from 3da1ee9 to b16fcee Compare February 28, 2026 23:40
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.

🧹 Nitpick comments (1)
src/components/Discover/MyMediaLibrary/index.tsx (1)

56-62: Consider more specific error handling.

The generic statusCode={500} error may not accurately represent all failure modes (e.g., network errors, 404s, rate limiting). If the API provides error details, consider passing them through for more informative error pages.

However, this is consistent with common patterns in similar components, so acceptable as-is.

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

In `@src/components/Discover/MyMediaLibrary/index.tsx` around lines 56 - 62, The
current error branch in MyMediaLibrary returns a generic <Error statusCode={500}
/>; update error handling to surface API-provided details by passing the actual
status and/or message from the fetched error object (e.g., use error.status or
error.response?.status and error.message) into the Error component so pages
reflect specific failure modes (network/404/rate-limit) while keeping the same
fallback when details are missing; locate this change around the conditional
using the error and data locals in the MyMediaLibrary component and adjust the
props passed to Error accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/components/Discover/MyMediaLibrary/index.tsx`:
- Around line 56-62: The current error branch in MyMediaLibrary returns a
generic <Error statusCode={500} />; update error handling to surface
API-provided details by passing the actual status and/or message from the
fetched error object (e.g., use error.status or error.response?.status and
error.message) into the Error component so pages reflect specific failure modes
(network/404/rate-limit) while keeping the same fallback when details are
missing; locate this change around the conditional using the error and data
locals in the MyMediaLibrary component and adjust the props passed to Error
accordingly.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3da1ee9 and b16fcee.

📒 Files selected for processing (10)
  • cypress/e2e/discover.cy.ts
  • server/constants/discover.ts
  • server/routes/discover.ts
  • src/components/Discover/DiscoverSliderEdit/index.tsx
  • src/components/Discover/MyMediaLibrary/index.tsx
  • src/components/Discover/MyMediaLibrarySlider/index.tsx
  • src/components/Discover/constants.ts
  • src/components/Discover/index.tsx
  • src/i18n/locale/en.json
  • src/pages/discover/library.tsx
🚧 Files skipped from review as they are similar to previous changes (7)
  • server/constants/discover.ts
  • src/components/Discover/index.tsx
  • cypress/e2e/discover.cy.ts
  • src/components/Discover/DiscoverSliderEdit/index.tsx
  • src/components/Discover/constants.ts
  • src/i18n/locale/en.json
  • server/routes/discover.ts

@AlexS54
Copy link
Copy Markdown

AlexS54 commented Mar 8, 2026

This looks good, looking forward to seeing it merged 👌

@ryanmfransen ryanmfransen force-pushed the feature-media-library-filter branch from 1eedaa8 to dd8b52b Compare March 9, 2026 22:07
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: 1

🧹 Nitpick comments (1)
src/components/Discover/MyMediaLibrarySlider/index.tsx (1)

13-16: Consider sharing the media-library query config.

This endpoint shape is now duplicated here and in src/components/Discover/MyMediaLibrary/index.tsx. Pulling the shared filter/sort/page-size bits into a small helper or constant would make it harder for the slider and full page to drift later.

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

In `@src/components/Discover/MyMediaLibrarySlider/index.tsx` around lines 13 - 16,
The media query string
'/api/v1/media?filter=allavailable&take=20&sort=mediaAdded' is duplicated
between MyMediaLibrarySlider and MyMediaLibrary; extract it into a shared
constant or small helper (e.g., export const MEDIA_LIBRARY_QUERY or a
buildMediaQuery(filter, take, sort) function) and import/use that in both
components instead of inlining the string where useSWR is called, keeping the
existing useSWR invocation intact.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/components/Discover/MyMediaLibrary/index.tsx`:
- Line 9: The import statement currently reads "import Error from
'@app/pages/_error';" which shadows the global Error constructor; update the
import to use a local alias (for example, rename the imported symbol to
ErrorPage or AppError) wherever it's referenced in this module (the import line
in src/components/Discover/MyMediaLibrary/index.tsx and any usage of Error), and
update those usages to the new name so the global Error constructor is no longer
shadowed.

---

Nitpick comments:
In `@src/components/Discover/MyMediaLibrarySlider/index.tsx`:
- Around line 13-16: The media query string
'/api/v1/media?filter=allavailable&take=20&sort=mediaAdded' is duplicated
between MyMediaLibrarySlider and MyMediaLibrary; extract it into a shared
constant or small helper (e.g., export const MEDIA_LIBRARY_QUERY or a
buildMediaQuery(filter, take, sort) function) and import/use that in both
components instead of inlining the string where useSWR is called, keeping the
existing useSWR invocation intact.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 91a76af8-9165-4bd3-aeb0-ad293ab89bb6

📥 Commits

Reviewing files that changed from the base of the PR and between 1eedaa8 and dd8b52b.

📒 Files selected for processing (10)
  • cypress/e2e/discover.cy.ts
  • server/constants/discover.ts
  • server/routes/discover.ts
  • src/components/Discover/DiscoverSliderEdit/index.tsx
  • src/components/Discover/MyMediaLibrary/index.tsx
  • src/components/Discover/MyMediaLibrarySlider/index.tsx
  • src/components/Discover/constants.ts
  • src/components/Discover/index.tsx
  • src/i18n/locale/en.json
  • src/pages/discover/library.tsx
🚧 Files skipped from review as they are similar to previous changes (6)
  • cypress/e2e/discover.cy.ts
  • src/i18n/locale/en.json
  • server/routes/discover.ts
  • src/components/Discover/DiscoverSliderEdit/index.tsx
  • src/pages/discover/library.tsx
  • src/components/Discover/constants.ts

import TmdbTitleCard from '@app/components/TitleCard/TmdbTitleCard';
import useVerticalScroll from '@app/hooks/useVerticalScroll';
import globalMessages from '@app/i18n/globalMessages';
import Error from '@app/pages/_error';
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot Mar 9, 2026

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

cat -n src/components/Discover/MyMediaLibrary/index.tsx | head -70

Repository: seerr-team/seerr

Length of output: 2624


🏁 Script executed:

rg -n "Error" src/components/Discover/MyMediaLibrary/index.tsx

Repository: seerr-team/seerr

Length of output: 142


Rename the _error import to avoid shadowing Error.

import Error ... shadows the global Error constructor and matches the Biome warning on this file. A local alias keeps the lint clean and avoids future confusion.

Suggested fix
-import Error from '@app/pages/_error';
+import ErrorPage from '@app/pages/_error';
@@
-    return <Error statusCode={500} />;
+    return <ErrorPage statusCode={500} />;
🧰 Tools
🪛 Biome (2.4.6)

[error] 9-9: Do not shadow the global "Error" property.

(lint/suspicious/noShadowRestrictedNames)

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

In `@src/components/Discover/MyMediaLibrary/index.tsx` at line 9, The import
statement currently reads "import Error from '@app/pages/_error';" which shadows
the global Error constructor; update the import to use a local alias (for
example, rename the imported symbol to ErrorPage or AppError) wherever it's
referenced in this module (the import line in
src/components/Discover/MyMediaLibrary/index.tsx and any usage of Error), and
update those usages to the new name so the global Error constructor is no longer
shadowed.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Related to #2668

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧩 Analysis chain

The PR description images show:

  • Image 1 (My Media Library page): A full-page grid of movie title cards under a large heading “My Media Library” in purple, with a search bar at the top. A left nav lists: Discover, Movies, Series, Requests, Blocklist, Issues, Users, Settings. The grid includes posters like Space Jam, Toy Story, Tangled, Trolls, Toy Story 2, Up, Monsters, Inc., Frozen II, Harry Potter titles, Skyfall, Casino Royale, The Hobbit, The Mechanic, The Matrix Reloaded, Red Dawn, The Little Mermaid, and more. Each card has a top-left “MOVIE” pill and a top-right green checkmark.
  • Image 2 (Discover page with slider and See More): On the Discover page, after a “Networks” row (Netflix, Disney+, Prime Video, Apple TV+, Hulu), there is a “My Media Library” slider showing several movie cards. At the right end of the slider there’s a “See More” card with an arrow icon and label “See More”.
  • Image 3 (Discover page with slider start): Similar Discover page view where the “My Media Library” slider appears near the bottom with the first few items like Space Jam, Toy Story 3, Tangled, a green knight cartoon, Trolls, Toy Story 2, Up. The left sidebar and top search remain the same.

Based on this, I’m verifying the “Error” import shadowing and will align the fix with #2668 if it tracks the Biome cleanup. I’ll follow up with an inline alias change once the script confirms occurrences.


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Show head of AvailableMedia component =="
if test -f src/components/Discover/AvailableMedia/index.tsx; then
  nl -ba src/components/Discover/AvailableMedia/index.tsx | sed -n '1,140p'
else
  echo "File not found: src/components/Discover/AvailableMedia/index.tsx" >&2
fi

echo
echo "== Importers of `@app/pages/_error` =="
rg -n --no-heading "from '@app/pages/_error'" || true

echo
echo "== Lines importing name 'Error' specifically =="
rg -nP --no-heading "import\\s+Error\\s+from\\s+'@app/pages/_error'" || true

echo
echo "== Usages of <Error ...> in AvailableMedia =="
rg -n --no-heading --glob "src/components/Discover/AvailableMedia/index.tsx" "<Error\\b" || true

echo
echo "== Any other new Discover components that import _error =="
fd -t f "index.tsx" src/components/Discover | xargs -I{} rg -n --no-heading "from '@app/pages/_error'" "{}" || true

echo
echo "== Check for legacy MyMediaLibrary component path (if present) =="
fd -t f "MyMediaLibrary" || true

echo
echo "== Try to fetch PR `#2668` (if exists) =="
gh pr view 2668 -R seerr-team/seerr --json number,title,state,author,headRefName,baseRefName 2>/dev/null || true

echo
echo "== If not a PR, try to fetch issue `#2668` =="
gh issue view 2668 -R seerr-team/seerr --json number,title,state,author,url 2>/dev/null || true

Length of output: 84


@coderabbit-user

PR description images:

  • Image 1 shows the “My Media Library” page with a large purple heading and a grid of movie posters, each with a “MOVIE” pill and a green checkmark badge. Left sidebar lists Discover, Movies, Series, Requests, Blocklist, Issues, Users, Settings.
  • Image 2 shows the Discover page; below a “Networks” row (Netflix, Disney+, Prime Video, Apple TV+, Hulu) there’s a “My Media Library” slider with a “See More” card at the end.
  • Image 3 shows the Discover page again with the “My Media Library” slider visible near the bottom; same sidebar and top search bar.

Thanks for linking this to #2668 — I’ll align the lint cleanup with that thread. I’m going to verify whether this module still imports Error from @app/pages/_error and if there are any other occurrences across the new Discover components. If present, I’ll recommend aliasing to ErrorPage to avoid shadowing the global constructor and satisfy Biome.

If it’s present, proposed patch (ready to apply) is:

- import Error from '@app/pages/_error';
+ import ErrorPage from '@app/pages/_error';
@@
-     return <Error statusCode={500} />;
+     return <ErrorPage statusCode={500} />;

🏁 Script executed:

#!/bin/bash
set -euo pipefail

file="src/components/Discover/AvailableMedia/index.tsx"

echo "== First 80 lines of $file =="
if [ -f "$file" ]; then
  awk 'NR<=80{printf "%4d  %s\n", NR, $0}' "$file"
else
  echo "File not found: $file"
fi

echo
echo "== Importers of `@app/pages/_error` across repo =="
rg -n --no-heading -S "from '@app/pages/_error'" || true

echo
echo "== Direct imports shadowing global Error =="
rg -nP --no-heading -S "import\\s+Error\\s+from\\s+'@app/pages/_error'" || true

echo
echo "== Usages of <Error ...> in AvailableMedia =="
if [ -f "$file" ]; then
  rg -n --no-heading -S "<Error\\b" "$file" || true
fi

echo
echo "== Check for legacy MyMediaLibrary components or paths =="
fd -t f "MyMediaLibrary" || true

Length of output: 9870


@coderabbit-user

The PR description images show:

  • The My Media Library page with a large purple “My Media Library” heading and a grid of movie posters; standard left sidebar (Discover, Movies, Series, Requests, Blocklist, Issues, Users, Settings) and top search bar.
  • The Discover page where a “My Media Library” slider appears beneath a “Networks” row (Netflix, Disney+, Prime Video, Apple TV+, Hulu), ending with a “See More” card.
  • Another Discover screenshot with the same slider visible near the bottom.

Thanks for linking this to #2668. I verified the shadowing:

  • src/components/Discover/AvailableMedia/index.tsx imports Error on Line 9 and uses it on Line 57:
    • Line 9: import Error from '@app/pages/_error';
    • Line 57: return ;

Several other files in the repo import the same module, and a few already use the ErrorPage alias. To keep this PR lint-clean and aligned with #2668, here’s a minimal patch for this component:

diff --git a/src/components/Discover/AvailableMedia/index.tsx b/src/components/Discover/AvailableMedia/index.tsx
--- a/src/components/Discover/AvailableMedia/index.tsx
+++ b/src/components/Discover/AvailableMedia/index.tsx
@@
-import Error from '@app/pages/_error';
+import ErrorPage from '@app/pages/_error';
@@
-    if (error) {
-      return <Error statusCode={500} />;
-    }
+    if (error) {
+      return <ErrorPage statusCode={500} />;
+    }

If you want, I can prep a quick follow-up aligned with #2668 to alias the remaining imports in Discover components (or repo-wide) to ErrorPage for consistency. Just say the word and I’ll plan it.


✏️ Learnings added
Learnt from: gauthier-th
Repo: seerr-team/seerr PR: 2600
File: src/components/Discover/AvailableMedia/index.tsx:9-9
Timestamp: 2026-03-26T15:49:55.253Z
Learning: seerr-team/seerr: When importing the Next.js error page from 'app/pages/_error' inside React components, prefer aliasing to 'ErrorPage' to avoid shadowing the global Error constructor and to satisfy Biome's noShadowRestrictedNames rule.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.


🧠 Learnings used
Learnt from: fallenbagel
Repo: seerr-team/seerr PR: 2731
File: server/lib/i18n/extractMessages.ts:71-71
Timestamp: 2026-03-20T01:39:15.788Z
Learning: In seerr-team/seerr, the server-side i18n extraction script (`server/lib/i18n/extractMessages.ts`) intentionally calls `saveMessages()` without a `.catch()` handler, mirroring the pre-existing pattern in the frontend extractor. This is acceptable because Node.js 15+ exits with a non-zero code on unhandled promise rejections by default, ensuring CI correctly detects failures. Do not flag this as an issue in future reviews.

@gauthier-th gauthier-th changed the title feat(media-library): added a new Discover page Slider for My Media Library feat(discover): add a new Discover page Slider for My Media Library Mar 10, 2026
@gauthier-th
Copy link
Copy Markdown
Member

I'm not sure about the "My Media Library" naming. What do you think of something like "Available Content" instead?

@fallenbagel
Copy link
Copy Markdown
Collaborator

I'm not sure about the "My Media Library" naming. What do you think of something like "Available Content" instead?

Available Media?

@ryanmfransen ryanmfransen force-pushed the feature-media-library-filter branch from dd8b52b to 681f617 Compare March 10, 2026 13:04
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.

♻️ Duplicate comments (1)
src/components/Discover/AvailableMedia/index.tsx (1)

9-9: ⚠️ Potential issue | 🟡 Minor

Rename the Error import to avoid shadowing the global Error constructor.

This import shadows the global Error constructor, which is flagged by Biome. Use an alias like ErrorPage to avoid confusion and keep the lint clean.

Proposed fix
-import Error from '@app/pages/_error';
+import ErrorPage from '@app/pages/_error';

And update the usage at line 57:

-    return <Error statusCode={500} />;
+    return <ErrorPage statusCode={500} />;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/Discover/AvailableMedia/index.tsx` at line 9, The imported
default export "Error" from '@app/pages/_error' shadows the global Error
constructor; rename the import to a non-conflicting alias (e.g., import
ErrorPage from '@app/pages/_error') and update all usages of the "Error" symbol
in this module (for example the component/render call that currently uses <Error
... />) to use "ErrorPage" instead so the global constructor is not shadowed and
the Biome lint error is resolved.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@src/components/Discover/AvailableMedia/index.tsx`:
- Line 9: The imported default export "Error" from '@app/pages/_error' shadows
the global Error constructor; rename the import to a non-conflicting alias
(e.g., import ErrorPage from '@app/pages/_error') and update all usages of the
"Error" symbol in this module (for example the component/render call that
currently uses <Error ... />) to use "ErrorPage" instead so the global
constructor is not shadowed and the Biome lint error is resolved.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: bf80ee48-23d2-4370-b826-097f34049eb1

📥 Commits

Reviewing files that changed from the base of the PR and between dd8b52b and 681f617.

📒 Files selected for processing (10)
  • cypress/e2e/discover.cy.ts
  • server/constants/discover.ts
  • server/routes/discover.ts
  • src/components/Discover/AvailableMedia/index.tsx
  • src/components/Discover/AvailableMediaSlider/index.tsx
  • src/components/Discover/DiscoverSliderEdit/index.tsx
  • src/components/Discover/constants.ts
  • src/components/Discover/index.tsx
  • src/i18n/locale/en.json
  • src/pages/discover/library.tsx
🚧 Files skipped from review as they are similar to previous changes (4)
  • src/i18n/locale/en.json
  • cypress/e2e/discover.cy.ts
  • server/routes/discover.ts
  • src/components/Discover/index.tsx

@ryanmfransen
Copy link
Copy Markdown
Author

Applied the suggested naming 'Available Media' Great idea!

@gauthier-th gauthier-th changed the title feat(discover): add a new Discover page Slider for My Media Library feat(discover): add a new Discover page Slider for Available Media Mar 10, 2026
@fallenbagel fallenbagel added the i18n-out-of-sync User forgot to run pnpm i18n:extract label Mar 21, 2026
Copy link
Copy Markdown
Collaborator

@fallenbagel fallenbagel left a comment

Choose a reason for hiding this comment

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

Please re-run pnpm i18n:extract and commit the changes.

My Media Library Discovery feature slider and full page view.

seerr-team#658
Comment thread server/routes/discover.ts
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

What's the point of this change?

import TmdbTitleCard from '@app/components/TitleCard/TmdbTitleCard';
import useVerticalScroll from '@app/hooks/useVerticalScroll';
import globalMessages from '@app/i18n/globalMessages';
import Error from '@app/pages/_error';
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Related to #2668

@github-actions github-actions Bot added the merge conflict Cannot merge due to merge conflicts label Apr 17, 2026
@github-actions
Copy link
Copy Markdown

This pull request has merge conflicts. Please resolve the conflicts so the PR can be successfully reviewed and merged.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

i18n-out-of-sync User forgot to run pnpm i18n:extract merge conflict Cannot merge due to merge conflicts pending author's response

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Option to show what's currently available

4 participants