diff --git a/src/pages/discover/components/LazyMediaCarousel.tsx b/src/pages/discover/components/LazyMediaCarousel.tsx index 6d441fdd..6fc5ee76 100644 --- a/src/pages/discover/components/LazyMediaCarousel.tsx +++ b/src/pages/discover/components/LazyMediaCarousel.tsx @@ -1,4 +1,4 @@ -import { useEffect, useState } from "react"; +import { useEffect, useRef, useState } from "react"; import { get } from "@/backend/metadata/tmdb"; import { useIntersectionObserver } from "@/pages/discover/hooks/useIntersectionObserver"; @@ -8,7 +8,6 @@ import { MediaItem } from "@/utils/mediaTypes"; import { MediaCarousel } from "./MediaCarousel"; import { Category, - Genre, Media, Movie, TVShow, @@ -17,39 +16,48 @@ import { } from "../common"; interface LazyMediaCarouselProps { - category?: Category; - genre?: Genre; - mediaType: "movie" | "tv"; + medias?: Media[]; + category?: string; + isTVShow: boolean; carouselRefs: React.MutableRefObject<{ [key: string]: HTMLDivElement | null; }>; onShowDetails?: (media: MediaItem) => void; - preloadedMedia?: Movie[] | TVShow[]; genreId?: number; - title?: string; + moreContent?: boolean; + moreLink?: string; relatedButtons?: Array<{ name: string; id: string }>; onButtonClick?: (id: string, name: string) => void; - moreContent?: boolean; + recommendationSources?: Array<{ id: string; title: string }>; + selectedRecommendationSource?: string; + onRecommendationSourceChange?: (id: string) => void; + preloadedMedia?: Movie[] | TVShow[]; + title?: string; } export function LazyMediaCarousel({ + medias: propMedias, category, - genre, - mediaType, + isTVShow, carouselRefs, onShowDetails, - preloadedMedia, genreId, - title, + moreContent, + moreLink, relatedButtons, onButtonClick, - moreContent, + recommendationSources, + selectedRecommendationSource, + onRecommendationSourceChange, + preloadedMedia, + title, }: LazyMediaCarouselProps) { - const [medias, setMedias] = useState([]); - const [loading, setLoading] = useState(!preloadedMedia); + const [medias, setMedias] = useState(propMedias || []); + const [loading, setLoading] = useState(!preloadedMedia && !propMedias); + const hasLoaded = useRef(false); - const categoryData = (mediaType === "movie" ? categories : tvCategories).find( - (c: Category) => c.name === (category?.name || genre?.name || title || ""), + const categoryData = (isTVShow ? tvCategories : categories).find( + (c: Category) => c.name === (category || title || ""), ); // Use intersection observer to detect when this component is visible @@ -57,12 +65,15 @@ export function LazyMediaCarousel({ { rootMargin: "200px" }, // Load when within 200px of viewport ); - // Use the lazy loading hook only if we don't have preloaded media + // Use the lazy loading hook only if we don't have preloaded media or prop medias + // and haven't loaded yet const { media } = useLazyTMDBData( - !preloadedMedia ? genre || null : null, - !preloadedMedia ? category || null : null, - mediaType, - isIntersecting, + null, // We don't use genre anymore since we're using category directly + !preloadedMedia && !propMedias && !hasLoaded.current + ? categoryData || null + : null, + isTVShow ? "tv" : "movie", + isIntersecting && !hasLoaded.current, ); // Update medias when data is loaded or preloaded @@ -70,15 +81,23 @@ export function LazyMediaCarousel({ if (preloadedMedia) { setMedias(preloadedMedia); setLoading(false); + hasLoaded.current = true; + } else if (propMedias) { + setMedias(propMedias); + setLoading(false); + hasLoaded.current = true; } else if (media.length > 0) { setMedias(media); setLoading(false); + hasLoaded.current = true; } - }, [media, preloadedMedia]); + }, [media, preloadedMedia, propMedias]); - // Only fetch category content if we don't have preloaded media + // Only fetch category content if we don't have preloaded media or prop medias + // and haven't loaded yet useEffect(() => { - if (preloadedMedia || !categoryData) return; + if (preloadedMedia || propMedias || !categoryData || hasLoaded.current) + return; const fetchContent = async () => { try { @@ -87,6 +106,7 @@ export function LazyMediaCarousel({ language: "en-US", }); setMedias(data.results); + hasLoaded.current = true; } catch (error) { console.error("Error fetching content:", error); } finally { @@ -95,10 +115,10 @@ export function LazyMediaCarousel({ }; fetchContent(); - }, [categoryData, preloadedMedia]); + }, [categoryData, preloadedMedia, propMedias]); - const categoryName = category?.name || genre?.name || title || ""; - const categorySlug = `${categoryName.toLowerCase().replace(/[^a-z0-9]+/g, "-")}-${mediaType}`; + const categoryName = category || title || ""; + const categorySlug = `${categoryName.toLowerCase().replace(/[^a-z0-9]+/g, "-")}-${isTVShow ? "tv" : "movie"}`; if (loading) { return ( @@ -118,24 +138,23 @@ export function LazyMediaCarousel({ ) : (

- {categoryName} {mediaType === "tv" ? "Shows" : "Movies"} + {categoryName} {isTVShow ? "Shows" : "Movies"}

diff --git a/src/pages/discover/discoverContent.tsx b/src/pages/discover/discoverContent.tsx index 642df75e..a346fdb0 100644 --- a/src/pages/discover/discoverContent.tsx +++ b/src/pages/discover/discoverContent.tsx @@ -23,7 +23,6 @@ import { DiscoverNavigation } from "./components/DiscoverNavigation"; import type { FeaturedMedia } from "./components/FeaturedCarousel"; import { LazyMediaCarousel } from "./components/LazyMediaCarousel"; import { LazyTabContent } from "./components/LazyTabContent"; -import { MediaCarousel } from "./components/MediaCarousel"; import { ScrollToTopButton } from "./components/ScrollToTopButton"; // Provider constants moved from DiscoverNavigation @@ -494,37 +493,13 @@ export function DiscoverContent() { detailsModal.show(); }; - // Render Editor Picks content - const renderEditorPicksContent = () => { - return ( - <> - - - - ); - }; - // Render Movies content with lazy loading const renderMoviesContent = () => { return ( <> {/* Movie Recommendations */} {movieRecommendations.length > 0 && ( - {/* Provider Movies */} - {/* Genre Movies */} - {/* TV Show Recommendations */} {tvRecommendations.length > 0 && ( - {/* Provider TV Shows */} - {/* Genre TV Shows */} - { + return ( + <> + + + + ); + }; + return (