Revert "feat: hide the arrow buttons on scroll lists when at either end of the list (#61)"

This reverts commit 598f752b12.
This commit is contained in:
Pas 2025-11-12 12:07:57 -07:00
parent 598f752b12
commit 467c4ea202
5 changed files with 74 additions and 248 deletions

View file

@ -45,39 +45,6 @@ export function EpisodeCarousel({
const updateItem = useProgressStore((s) => s.updateItem); const updateItem = useProgressStore((s) => s.updateItem);
const confirmModal = useModal("season-watch-confirm"); const confirmModal = useModal("season-watch-confirm");
const [canScrollLeft, setCanScrollLeft] = useState(false);
const [canScrollRight, setCanScrollRight] = useState(false);
const updateScrollState = () => {
if (!carouselRef.current) {
setCanScrollLeft(false);
setCanScrollRight(false);
return;
}
const { scrollLeft, scrollWidth, clientWidth } = carouselRef.current;
const isAtStart = scrollLeft <= 1;
const isAtEnd = scrollLeft + clientWidth >= scrollWidth - 1;
setCanScrollLeft(!isAtStart);
setCanScrollRight(!isAtEnd);
};
useEffect(() => {
const carousel = carouselRef.current;
if (!carousel) return;
updateScrollState();
carousel.addEventListener("scroll", updateScrollState);
window.addEventListener("resize", updateScrollState);
return () => {
carousel.removeEventListener("scroll", updateScrollState);
window.removeEventListener("resize", updateScrollState);
};
}, []);
const handleScroll = (direction: "left" | "right") => { const handleScroll = (direction: "left" | "right") => {
if (!carouselRef.current) return; if (!carouselRef.current) return;
@ -563,7 +530,6 @@ export function EpisodeCarousel({
{/* Episodes Carousel */} {/* Episodes Carousel */}
<div className="relative"> <div className="relative">
{/* Left scroll button */} {/* Left scroll button */}
{canScrollLeft && (
<div className="absolute left-0 top-1/2 transform -translate-y-1/2 z-10 px-4 hidden lg:block"> <div className="absolute left-0 top-1/2 transform -translate-y-1/2 z-10 px-4 hidden lg:block">
<button <button
type="button" type="button"
@ -573,7 +539,6 @@ export function EpisodeCarousel({
<Icon icon={Icons.CHEVRON_LEFT} className="text-white/80" /> <Icon icon={Icons.CHEVRON_LEFT} className="text-white/80" />
</button> </button>
</div> </div>
)}
<div <div
ref={carouselRef} ref={carouselRef}
@ -818,7 +783,6 @@ export function EpisodeCarousel({
</div> </div>
{/* Right scroll button */} {/* Right scroll button */}
{canScrollRight && (
<div className="absolute right-0 top-1/2 transform -translate-y-1/2 z-10 px-4 hidden lg:block"> <div className="absolute right-0 top-1/2 transform -translate-y-1/2 z-10 px-4 hidden lg:block">
<button <button
type="button" type="button"
@ -828,7 +792,6 @@ export function EpisodeCarousel({
<Icon icon={Icons.CHEVRON_RIGHT} className="text-white/80" /> <Icon icon={Icons.CHEVRON_RIGHT} className="text-white/80" />
</button> </button>
</div> </div>
)}
</div> </div>
</div> </div>
); );

View file

@ -766,39 +766,6 @@ export function EpisodesView({
], ],
); );
const [canScrollLeft, setCanScrollLeft] = useState(false);
const [canScrollRight, setCanScrollRight] = useState(false);
const updateScrollState = () => {
if (!carouselRef.current) {
setCanScrollLeft(false);
setCanScrollRight(false);
return;
}
const { scrollLeft, scrollWidth, clientWidth } = carouselRef.current;
const isAtStart = scrollLeft <= 1;
const isAtEnd = scrollLeft + clientWidth >= scrollWidth - 1;
setCanScrollLeft(!isAtStart);
setCanScrollRight(!isAtEnd);
};
useEffect(() => {
const carousel = carouselRef.current;
if (!carousel) return;
updateScrollState();
carousel.addEventListener("scroll", updateScrollState);
window.addEventListener("resize", updateScrollState);
return () => {
carousel.removeEventListener("scroll", updateScrollState);
window.removeEventListener("resize", updateScrollState);
};
}, []);
const handleScroll = (direction: "left" | "right") => { const handleScroll = (direction: "left" | "right") => {
if (!carouselRef.current) return; if (!carouselRef.current) return;
@ -949,7 +916,6 @@ export function EpisodesView({
content = ( content = (
<div className="relative"> <div className="relative">
{/* Horizontal scroll buttons */} {/* Horizontal scroll buttons */}
{canScrollLeft && (
<div <div
className={classNames( className={classNames(
"absolute left-0 top-1/2 transform -translate-y-1/2 z-10 px-4", "absolute left-0 top-1/2 transform -translate-y-1/2 z-10 px-4",
@ -964,7 +930,6 @@ export function EpisodesView({
<Icon icon={Icons.CHEVRON_LEFT} className="text-white/80" /> <Icon icon={Icons.CHEVRON_LEFT} className="text-white/80" />
</button> </button>
</div> </div>
)}
<div <div
ref={carouselRef} ref={carouselRef}
@ -1031,7 +996,6 @@ export function EpisodesView({
</div> </div>
{/* Right scroll button */} {/* Right scroll button */}
{canScrollRight && (
<div <div
className={classNames( className={classNames(
"absolute right-0 top-1/2 transform -translate-y-1/2 z-10 px-4", "absolute right-0 top-1/2 transform -translate-y-1/2 z-10 px-4",
@ -1046,7 +1010,6 @@ export function EpisodesView({
<Icon icon={Icons.CHEVRON_RIGHT} className="text-white/80" /> <Icon icon={Icons.CHEVRON_RIGHT} className="text-white/80" />
</button> </button>
</div> </div>
)}
</div> </div>
); );
} }

View file

@ -1,5 +1,3 @@
import { useCallback, useEffect, useState } from "react";
import { Icon, Icons } from "@/components/Icon"; import { Icon, Icons } from "@/components/Icon";
import { Flare } from "@/components/utils/Flare"; import { Flare } from "@/components/utils/Flare";
@ -13,12 +11,9 @@ interface CarouselNavButtonsProps {
interface NavButtonProps { interface NavButtonProps {
direction: "left" | "right"; direction: "left" | "right";
onClick: () => void; onClick: () => void;
visible: boolean;
} }
function NavButton({ direction, onClick, visible }: NavButtonProps) { function NavButton({ direction, onClick }: NavButtonProps) {
if (!visible) return null;
return ( return (
<button <button
type="button" type="button"
@ -48,40 +43,6 @@ export function CarouselNavButtons({
categorySlug, categorySlug,
carouselRefs, carouselRefs,
}: CarouselNavButtonsProps) { }: CarouselNavButtonsProps) {
const [canScrollLeft, setCanScrollLeft] = useState(false);
const [canScrollRight, setCanScrollRight] = useState(false);
const updateScrollState = useCallback(() => {
const carousel = carouselRefs.current[categorySlug];
if (!carousel) {
setCanScrollLeft(false);
setCanScrollRight(false);
return;
}
const { scrollLeft, scrollWidth, clientWidth } = carousel;
const isAtStart = scrollLeft <= 1;
const isAtEnd = scrollLeft + clientWidth >= scrollWidth - 1;
setCanScrollLeft(!isAtStart);
setCanScrollRight(!isAtEnd);
}, [categorySlug, carouselRefs]);
useEffect(() => {
const carousel = carouselRefs.current[categorySlug];
if (!carousel) return;
updateScrollState();
carousel.addEventListener("scroll", updateScrollState);
window.addEventListener("resize", updateScrollState);
return () => {
carousel.removeEventListener("scroll", updateScrollState);
window.removeEventListener("resize", updateScrollState);
};
}, [categorySlug, carouselRefs, updateScrollState]);
const handleScroll = (direction: "left" | "right") => { const handleScroll = (direction: "left" | "right") => {
const carousel = carouselRefs.current[categorySlug]; const carousel = carouselRefs.current[categorySlug];
if (!carousel) return; if (!carousel) return;
@ -115,16 +76,8 @@ export function CarouselNavButtons({
return ( return (
<> <>
<NavButton <NavButton direction="left" onClick={() => handleScroll("left")} />
direction="left" <NavButton direction="right" onClick={() => handleScroll("right")} />
onClick={() => handleScroll("left")}
visible={canScrollLeft}
/>
<NavButton
direction="right"
onClick={() => handleScroll("right")}
visible={canScrollRight}
/>
</> </>
); );
} }

View file

@ -1,5 +1,3 @@
import { useCallback, useEffect, useState } from "react";
import { Icon, Icons } from "@/components/Icon"; import { Icon, Icons } from "@/components/Icon";
interface CategoryButtonsProps { interface CategoryButtonsProps {
@ -17,53 +15,7 @@ export function CategoryButtons({
isMobile, isMobile,
showAlwaysScroll, showAlwaysScroll,
}: CategoryButtonsProps) { }: CategoryButtonsProps) {
const [canScrollLeft, setCanScrollLeft] = useState(false); const renderScrollButton = (direction: "left" | "right") => (
const [canScrollRight, setCanScrollRight] = useState(false);
const updateScrollState = useCallback(() => {
const element = document.getElementById(`button-carousel-${categoryType}`);
if (!element) {
setCanScrollLeft(false);
setCanScrollRight(false);
return;
}
const { scrollLeft, scrollWidth, clientWidth } = element;
const isAtStart = scrollLeft <= 1;
const isAtEnd = scrollLeft + clientWidth >= scrollWidth - 1;
setCanScrollLeft(!isAtStart);
setCanScrollRight(!isAtEnd);
}, [categoryType]);
useEffect(() => {
const element = document.getElementById(`button-carousel-${categoryType}`);
if (!element) return;
updateScrollState();
element.addEventListener("scroll", updateScrollState);
window.addEventListener("resize", updateScrollState);
return () => {
element.removeEventListener("scroll", updateScrollState);
window.removeEventListener("resize", updateScrollState);
};
}, [categoryType, updateScrollState]);
useEffect(() => {
const timeoutId = setTimeout(() => {
updateScrollState();
}, 0);
return () => clearTimeout(timeoutId);
}, [categories, categoryType, updateScrollState]);
const renderScrollButton = (direction: "left" | "right") => {
const shouldShow = direction === "left" ? canScrollLeft : canScrollRight;
if (!shouldShow && !showAlwaysScroll && !isMobile) return null;
return (
<div> <div>
<button <button
type="button" type="button"
@ -81,20 +33,16 @@ export function CategoryButtons({
}} }}
> >
<Icon <Icon
icon={ icon={direction === "left" ? Icons.CHEVRON_LEFT : Icons.CHEVRON_RIGHT}
direction === "left" ? Icons.CHEVRON_LEFT : Icons.CHEVRON_RIGHT
}
className="text-2xl rtl:-scale-x-100" className="text-2xl rtl:-scale-x-100"
/> />
</button> </button>
</div> </div>
); );
};
return ( return (
<div className="flex overflow-x-auto"> <div className="flex overflow-x-auto">
{(showAlwaysScroll || isMobile || canScrollLeft) && {(showAlwaysScroll || isMobile) && renderScrollButton("left")}
renderScrollButton("left")}
<div <div
id={`button-carousel-${categoryType}`} id={`button-carousel-${categoryType}`}
@ -114,8 +62,7 @@ export function CategoryButtons({
</div> </div>
</div> </div>
{(showAlwaysScroll || isMobile || canScrollRight) && {(showAlwaysScroll || isMobile) && renderScrollButton("right")}
renderScrollButton("right")}
</div> </div>
); );
} }

View file

@ -1,10 +1,10 @@
import { useProgressStore } from "@/stores/progress"; import { useProgressStore } from "@/stores/progress";
import { createVersionedStore } from "../migrations";
import { OldData, migrateV2Videos } from "./migrations/v2"; import { OldData, migrateV2Videos } from "./migrations/v2";
import { migrateV3Videos } from "./migrations/v3"; import { migrateV3Videos } from "./migrations/v3";
import { migrateV4Videos } from "./migrations/v4"; import { migrateV4Videos } from "./migrations/v4";
import { WatchedStoreData } from "./types"; import { WatchedStoreData } from "./types";
import { createVersionedStore } from "../migrations";
export const VideoProgressStore = createVersionedStore<WatchedStoreData>() export const VideoProgressStore = createVersionedStore<WatchedStoreData>()
.setKey("video-progress") .setKey("video-progress")