Revert hide/show carousel buttons based on carousel length

This commit is contained in:
Pas 2025-09-01 09:51:50 -06:00
parent b1b2539814
commit e79a04c204
5 changed files with 20 additions and 191 deletions

View file

@ -34,11 +34,6 @@ export function DiscoverMore() {
const { lastView } = useDiscoverStore(); const { lastView } = useDiscoverStore();
const { isMobile } = useIsMobile(); const { isMobile } = useIsMobile();
// Track overflow states for curated lists
const [overflowStates, setOverflowStates] = useState<{
[key: string]: boolean;
}>({});
useEffect(() => { useEffect(() => {
const fetchCuratedLists = async () => { const fetchCuratedLists = async () => {
try { try {
@ -93,41 +88,6 @@ export function DiscoverMore() {
} }
}; };
// Function to check overflow for a carousel
const checkOverflow = (element: HTMLDivElement | null, key: string) => {
if (!element) {
setOverflowStates((prev) => ({ ...prev, [key]: false }));
return;
}
const hasOverflow = element.scrollWidth > element.clientWidth;
setOverflowStates((prev) => ({ ...prev, [key]: hasOverflow }));
};
// Function to set carousel ref and check overflow
const setCarouselRef = (element: HTMLDivElement | null, key: string) => {
carouselRefs.current[key] = element;
// Check overflow after a short delay to ensure content is rendered
setTimeout(() => checkOverflow(element, key), 100);
};
// Effect to recheck overflow on window resize
useEffect(() => {
const handleResize = () => {
// Recheck overflow for all carousels
Object.keys(carouselRefs.current).forEach((key) => {
const element = carouselRefs.current[key];
if (element) {
checkOverflow(element, key);
}
});
};
window.addEventListener("resize", handleResize);
return () => window.removeEventListener("resize", handleResize);
}, []);
return ( return (
<SubPageLayout> <SubPageLayout>
<WideContainer> <WideContainer>
@ -183,7 +143,9 @@ export function DiscoverMore() {
<div className="relative overflow-hidden carousel-container md:pb-4"> <div className="relative overflow-hidden carousel-container md:pb-4">
<div <div
className="grid grid-flow-col auto-cols-max gap-4 pt-0 overflow-x-scroll scrollbar-none rounded-xl overflow-y-hidden md:pl-8 md:pr-8" className="grid grid-flow-col auto-cols-max gap-4 pt-0 overflow-x-scroll scrollbar-none rounded-xl overflow-y-hidden md:pl-8 md:pr-8"
ref={(el) => setCarouselRef(el, list.listSlug)} ref={(el) => {
carouselRefs.current[list.listSlug] = el;
}}
onWheel={handleWheel} onWheel={handleWheel}
> >
<div className="md:w-12" /> <div className="md:w-12" />
@ -215,7 +177,6 @@ export function DiscoverMore() {
<CarouselNavButtons <CarouselNavButtons
categorySlug={list.listSlug} categorySlug={list.listSlug}
carouselRefs={carouselRefs} carouselRefs={carouselRefs}
hasOverflow={overflowStates[list.listSlug]}
/> />
)} )}
</div> </div>

View file

@ -6,7 +6,6 @@ interface CarouselNavButtonsProps {
carouselRefs: React.MutableRefObject<{ carouselRefs: React.MutableRefObject<{
[key: string]: HTMLDivElement | null; [key: string]: HTMLDivElement | null;
}>; }>;
hasOverflow?: boolean;
} }
interface NavButtonProps { interface NavButtonProps {
@ -43,7 +42,6 @@ function NavButton({ direction, onClick }: NavButtonProps) {
export function CarouselNavButtons({ export function CarouselNavButtons({
categorySlug, categorySlug,
carouselRefs, carouselRefs,
hasOverflow = true,
}: CarouselNavButtonsProps) { }: CarouselNavButtonsProps) {
const handleScroll = (direction: "left" | "right") => { const handleScroll = (direction: "left" | "right") => {
const carousel = carouselRefs.current[categorySlug]; const carousel = carouselRefs.current[categorySlug];
@ -76,11 +74,6 @@ export function CarouselNavButtons({
}); });
}; };
// Don't render buttons if there's no overflow
if (!hasOverflow) {
return null;
}
return ( return (
<> <>
<NavButton direction="left" onClick={() => handleScroll("left")} /> <NavButton direction="left" onClick={() => handleScroll("left")} />

View file

@ -1,5 +1,5 @@
import { Listbox } from "@headlessui/react"; import { Listbox } from "@headlessui/react";
import React, { useEffect, useState } from "react"; import React, { useEffect, useRef, useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
import { useWindowSize } from "react-use"; import { useWindowSize } from "react-use";
@ -110,9 +110,6 @@ export function MediaCarousel({
const { isMobile } = useIsMobile(); const { isMobile } = useIsMobile();
const browser = !!window.chrome; const browser = !!window.chrome;
// Track overflow state
const [hasOverflow, setHasOverflow] = useState(false);
// State for selected options // State for selected options
const [selectedProviderId, setSelectedProviderId] = useState<string>(""); const [selectedProviderId, setSelectedProviderId] = useState<string>("");
const [selectedProviderName, setSelectedProviderName] = useState<string>(""); const [selectedProviderName, setSelectedProviderName] = useState<string>("");
@ -275,45 +272,8 @@ export function MediaCarousel({
} }
}, [showRecommendations, recommendationSources, selectedRecommendationId]); }, [showRecommendations, recommendationSources, selectedRecommendationId]);
const categorySlug = React.useMemo(() => { const categorySlug = `${sectionTitle.toLowerCase().replace(/[^a-z0-9]+/g, "-")}-${isTVShow ? "tv" : "movie"}`;
return `${sectionTitle.toLowerCase().replace(/[^a-z0-9]+/g, "-")}-${isTVShow ? "tv" : "movie"}`; const isScrollingRef = useRef(false);
}, [sectionTitle, isTVShow]);
// Function to check overflow for the carousel
const checkOverflow = React.useCallback((element: HTMLDivElement | null) => {
if (!element) {
setHasOverflow(false);
return;
}
const hasHorizontalOverflow = element.scrollWidth > element.clientWidth;
setHasOverflow(hasHorizontalOverflow);
}, []);
// Function to set carousel ref and check overflow
const setCarouselRef = React.useCallback(
(element: HTMLDivElement | null) => {
carouselRefs.current[categorySlug] = element;
// Check overflow after a short delay to ensure content is rendered
setTimeout(() => checkOverflow(element), 100);
},
[carouselRefs, categorySlug, checkOverflow],
);
// Effect to recheck overflow on window resize
useEffect(() => {
const handleResize = () => {
const element = carouselRefs.current[categorySlug];
if (element) {
checkOverflow(element);
}
};
window.addEventListener("resize", handleResize);
return () => window.removeEventListener("resize", handleResize);
}, [carouselRefs, categorySlug, checkOverflow]);
const isScrollingRef = React.useRef(false);
const handleWheel = React.useCallback( const handleWheel = React.useCallback(
(e: React.WheelEvent) => { (e: React.WheelEvent) => {
@ -568,7 +528,9 @@ export function MediaCarousel({
<div <div
id={`carousel-${categorySlug}`} id={`carousel-${categorySlug}`}
className="grid grid-flow-col auto-cols-max gap-4 pt-0 overflow-x-scroll scrollbar-none rounded-xl overflow-y-hidden md:pl-8 md:pr-8" className="grid grid-flow-col auto-cols-max gap-4 pt-0 overflow-x-scroll scrollbar-none rounded-xl overflow-y-hidden md:pl-8 md:pr-8"
ref={setCarouselRef} ref={(el) => {
carouselRefs.current[categorySlug] = el;
}}
onWheel={handleWheel} onWheel={handleWheel}
> >
<div className="md:w-12" /> <div className="md:w-12" />
@ -623,7 +585,6 @@ export function MediaCarousel({
<CarouselNavButtons <CarouselNavButtons
categorySlug={categorySlug} categorySlug={categorySlug}
carouselRefs={carouselRefs} carouselRefs={carouselRefs}
hasOverflow={hasOverflow}
/> />
)} )}
</div> </div>

View file

@ -1,4 +1,4 @@
import React, { useEffect, useMemo, useRef, useState } from "react"; import React, { useMemo, useRef, useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
@ -96,17 +96,6 @@ export function BookmarksCarousel({
const backendUrl = useBackendUrl(); const backendUrl = useBackendUrl();
const account = useAuthStore((s) => s.account); const account = useAuthStore((s) => s.account);
// Create refs for overflow detection
const groupedCarouselRefs = useRef<{
[key: string]: HTMLDivElement | null;
}>({});
const regularCarouselRef = useRef<HTMLDivElement | null>(null);
// Track overflow state for each section
const [overflowStates, setOverflowStates] = useState<{
[key: string]: boolean;
}>({});
// Group order editing state // Group order editing state
const groupOrder = useGroupOrderStore((s) => s.groupOrder); const groupOrder = useGroupOrderStore((s) => s.groupOrder);
const setGroupOrder = useGroupOrderStore((s) => s.setGroupOrder); const setGroupOrder = useGroupOrderStore((s) => s.setGroupOrder);
@ -376,49 +365,6 @@ export function BookmarksCarousel({
} }
}; };
// Function to check overflow for a carousel
const checkOverflow = (element: HTMLDivElement | null, key: string) => {
if (!element) {
setOverflowStates((prev) => ({ ...prev, [key]: false }));
return;
}
const hasOverflow = element.scrollWidth > element.clientWidth;
setOverflowStates((prev) => ({ ...prev, [key]: hasOverflow }));
};
// Function to set carousel ref and check overflow
const setCarouselRef = (element: HTMLDivElement | null, key: string) => {
// Set the ref for the main carousel refs
carouselRefs.current[key] = element;
// Set the ref for overflow detection
if (key === "bookmarks") {
regularCarouselRef.current = element;
} else {
groupedCarouselRefs.current[key] = element;
}
// Check overflow after a short delay to ensure content is rendered
setTimeout(() => checkOverflow(element, key), 100);
};
// Effect to recheck overflow on window resize
useEffect(() => {
const handleResize = () => {
// Recheck overflow for all carousels
Object.keys(carouselRefs.current).forEach((key) => {
const element = carouselRefs.current[key];
if (element) {
checkOverflow(element, key);
}
});
};
window.addEventListener("resize", handleResize);
return () => window.removeEventListener("resize", handleResize);
}, [carouselRefs]);
const categorySlug = "bookmarks"; const categorySlug = "bookmarks";
const SKELETON_COUNT = 10; const SKELETON_COUNT = 10;
@ -462,7 +408,9 @@ export function BookmarksCarousel({
<div <div
id={`carousel-${section.group}`} id={`carousel-${section.group}`}
className="grid grid-flow-col auto-cols-max gap-4 pt-0 overflow-x-scroll scrollbar-none rounded-xl overflow-y-hidden md:pl-8 md:pr-8" className="grid grid-flow-col auto-cols-max gap-4 pt-0 overflow-x-scroll scrollbar-none rounded-xl overflow-y-hidden md:pl-8 md:pr-8"
ref={(el) => setCarouselRef(el, section.group || "bookmarks")} ref={(el) => {
carouselRefs.current[section.group || "bookmarks"] = el;
}}
onWheel={handleWheel} onWheel={handleWheel}
> >
<div className="md:w-12" /> <div className="md:w-12" />
@ -503,7 +451,6 @@ export function BookmarksCarousel({
<CarouselNavButtons <CarouselNavButtons
categorySlug={section.group || "bookmarks"} categorySlug={section.group || "bookmarks"}
carouselRefs={carouselRefs} carouselRefs={carouselRefs}
hasOverflow={overflowStates[section.group || "bookmarks"]}
/> />
)} )}
</div> </div>
@ -538,7 +485,9 @@ export function BookmarksCarousel({
<div <div
id={`carousel-${categorySlug}`} id={`carousel-${categorySlug}`}
className="grid grid-flow-col auto-cols-max gap-4 pt-0 overflow-x-scroll scrollbar-none rounded-xl overflow-y-hidden md:pl-8 md:pr-8" className="grid grid-flow-col auto-cols-max gap-4 pt-0 overflow-x-scroll scrollbar-none rounded-xl overflow-y-hidden md:pl-8 md:pr-8"
ref={(el) => setCarouselRef(el, categorySlug)} ref={(el) => {
carouselRefs.current[categorySlug] = el;
}}
onWheel={handleWheel} onWheel={handleWheel}
> >
<div className="md:w-12" /> <div className="md:w-12" />
@ -585,7 +534,6 @@ export function BookmarksCarousel({
<CarouselNavButtons <CarouselNavButtons
categorySlug={categorySlug} categorySlug={categorySlug}
carouselRefs={carouselRefs} carouselRefs={carouselRefs}
hasOverflow={overflowStates[categorySlug]}
/> />
)} )}
</div> </div>

View file

@ -1,4 +1,4 @@
import React, { useEffect, useMemo, useRef, useState } from "react"; import React, { useMemo, useRef, useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { EditButton } from "@/components/buttons/EditButton"; import { EditButton } from "@/components/buttons/EditButton";
@ -42,9 +42,6 @@ export function WatchingCarousel({
const removeItem = useProgressStore((s) => s.removeItem); const removeItem = useProgressStore((s) => s.removeItem);
const pressTimerRef = useRef<NodeJS.Timeout | null>(null); const pressTimerRef = useRef<NodeJS.Timeout | null>(null);
// Track overflow state
const [hasOverflow, setHasOverflow] = useState(false);
const { isMobile } = useIsMobile(); const { isMobile } = useIsMobile();
const itemsLength = useProgressStore((state) => { const itemsLength = useProgressStore((state) => {
@ -125,38 +122,6 @@ export function WatchingCarousel({
} }
}; };
// Function to check overflow for the carousel
const checkOverflow = (element: HTMLDivElement | null) => {
if (!element) {
setHasOverflow(false);
return;
}
const hasHorizontalOverflow = element.scrollWidth > element.clientWidth;
setHasOverflow(hasHorizontalOverflow);
};
// Function to set carousel ref and check overflow
const setCarouselRef = (element: HTMLDivElement | null) => {
carouselRefs.current[categorySlug] = element;
// Check overflow after a short delay to ensure content is rendered
setTimeout(() => checkOverflow(element), 100);
};
// Effect to recheck overflow on window resize
useEffect(() => {
const handleResize = () => {
const element = carouselRefs.current[categorySlug];
if (element) {
checkOverflow(element);
}
};
window.addEventListener("resize", handleResize);
return () => window.removeEventListener("resize", handleResize);
}, [carouselRefs, categorySlug]);
if (itemsLength === 0) return null; if (itemsLength === 0) return null;
return ( return (
@ -178,7 +143,9 @@ export function WatchingCarousel({
<div <div
id={`carousel-${categorySlug}`} id={`carousel-${categorySlug}`}
className="grid grid-flow-col auto-cols-max gap-4 pt-0 overflow-x-scroll scrollbar-none rounded-xl overflow-y-hidden md:pl-8 md:pr-8" className="grid grid-flow-col auto-cols-max gap-4 pt-0 overflow-x-scroll scrollbar-none rounded-xl overflow-y-hidden md:pl-8 md:pr-8"
ref={setCarouselRef} ref={(el) => {
carouselRefs.current[categorySlug] = el;
}}
onWheel={handleWheel} onWheel={handleWheel}
> >
<div className="md:w-12" /> <div className="md:w-12" />
@ -219,7 +186,6 @@ export function WatchingCarousel({
<CarouselNavButtons <CarouselNavButtons
categorySlug={categorySlug} categorySlug={categorySlug}
carouselRefs={carouselRefs} carouselRefs={carouselRefs}
hasOverflow={hasOverflow}
/> />
)} )}
</div> </div>