From 938e0461ae32eef381ea0c1d2b3f4abaec9d4c31 Mon Sep 17 00:00:00 2001 From: Julien Froidefond Date: Sun, 16 Feb 2025 16:02:07 +0100 Subject: [PATCH] refacto(thumbnails): revew thumbnails and caching --- .../reader/components/Thumbnail.tsx | 65 ++++++++++++++++--- src/lib/services/server-cache.service.ts | 3 +- 2 files changed, 57 insertions(+), 11 deletions(-) diff --git a/src/components/reader/components/Thumbnail.tsx b/src/components/reader/components/Thumbnail.tsx index 36f010c..609ba15 100644 --- a/src/components/reader/components/Thumbnail.tsx +++ b/src/components/reader/components/Thumbnail.tsx @@ -2,7 +2,7 @@ import { ThumbnailProps } from "../types"; import { ImageLoader } from "@/components/ui/image-loader"; import { cn } from "@/lib/utils"; import Image from "next/image"; -import { forwardRef, useEffect, useState } from "react"; +import { forwardRef, useEffect, useState, useCallback, useRef } from "react"; export const Thumbnail = forwardRef( ( @@ -19,23 +19,60 @@ export const Thumbnail = forwardRef( ) => { const [imageUrl, setImageUrl] = useState(null); const [isLoading, setIsLoading] = useState(true); + const [hasError, setHasError] = useState(false); + const loadAttempts = useRef(0); + const maxAttempts = 3; + + const resetLoadingState = useCallback(() => { + setIsLoading(true); + setHasError(false); + loadAttempts.current = 0; + }, []); useEffect(() => { - if (isVisible) { + try { const url = getThumbnailUrl(pageNumber); setImageUrl(url); + // On réinitialise le loading uniquement si la miniature n'est pas déjà chargée if (!loadedThumbnails[pageNumber]) { - setIsLoading(true); + resetLoadingState(); + } else { + setIsLoading(false); } + } catch (error) { + console.error(`Erreur lors du chargement de la miniature ${pageNumber}:`, error); + setHasError(true); + setIsLoading(false); } - }, [isVisible, pageNumber, getThumbnailUrl, loadedThumbnails]); + }, [pageNumber, getThumbnailUrl, loadedThumbnails, resetLoadingState]); - const handleImageLoad = () => { + const handleImageLoad = useCallback(() => { setIsLoading(false); + setHasError(false); if (!loadedThumbnails[pageNumber]) { onThumbnailLoad(pageNumber); } - }; + }, [loadedThumbnails, pageNumber, onThumbnailLoad]); + + const handleImageError = useCallback(() => { + loadAttempts.current += 1; + if (loadAttempts.current < maxAttempts) { + // Réessayer avec un délai croissant + const delay = Math.min(1000 * Math.pow(2, loadAttempts.current - 1), 5000); + console.log( + `Réessai ${loadAttempts.current}/${maxAttempts} dans ${delay}ms pour la page ${pageNumber}` + ); + setTimeout(() => { + setImageUrl((prev) => (prev ? `${prev}?retry=${loadAttempts.current}` : null)); + }, delay); + } else { + console.error( + `Échec du chargement de l'image pour la page ${pageNumber} après ${maxAttempts} tentatives` + ); + setHasError(true); + setIsLoading(false); + } + }, [pageNumber]); return (