diff --git a/src/components/ui/cover.tsx b/src/components/ui/cover.tsx index dbdbc93..adb5988 100644 --- a/src/components/ui/cover.tsx +++ b/src/components/ui/cover.tsx @@ -2,7 +2,7 @@ import { ImageOff } from "lucide-react"; import Image from "next/image"; -import { useState } from "react"; +import { useState, useEffect, useRef } from "react"; import { cn } from "@/lib/utils"; import { ImageLoader } from "@/components/ui/image-loader"; @@ -29,6 +29,9 @@ export function Cover({ }: CoverProps) { const [imageError, setImageError] = useState(false); const [isLoading, setIsLoading] = useState(true); + const [isInViewport, setIsInViewport] = useState(false); + const [imageUrl, setImageUrl] = useState(null); + const coverRef = useRef(null); const getImageUrl = () => { if (type === "series") { @@ -37,6 +40,34 @@ export function Cover({ return `/api/komga/images/books/${id}/thumbnail`; }; + // Observer pour détecter quand la cover est dans le viewport + useEffect(() => { + const observer = new IntersectionObserver( + (entries) => { + entries.forEach((entry) => { + setIsInViewport(entry.isIntersecting); + if (entry.isIntersecting && !imageUrl) { + setImageUrl(getImageUrl()); + } + }); + }, + { + rootMargin: "50px", // Préchargement avant que l'élément soit visible + } + ); + + const element = coverRef.current; + if (element) { + observer.observe(element); + } + + return () => { + if (element) { + observer.unobserve(element); + } + }; + }, [id, imageUrl]); + if (imageError) { return (
@@ -46,25 +77,27 @@ export function Cover({ } return ( -
+
- {alt} setImageError(true)} - onLoad={() => setIsLoading(false)} - loading={priority ? "eager" : "lazy"} - quality={quality} - priority={priority} - /> + {imageUrl && ( + {alt} setImageError(true)} + onLoad={() => setIsLoading(false)} + loading={priority ? "eager" : "lazy"} + quality={quality} + priority={priority} + /> + )}
); }