refacto: tentative de refacto
This commit is contained in:
@@ -24,12 +24,9 @@ export function BookReader({ book, pages, onClose }: BookReaderProps) {
|
||||
setIsLoading,
|
||||
secondPageLoading,
|
||||
setSecondPageLoading,
|
||||
imageError,
|
||||
setImageError,
|
||||
handlePreviousPage,
|
||||
handleNextPage,
|
||||
shouldShowDoublePage,
|
||||
syncReadProgress,
|
||||
} = usePageNavigation({
|
||||
book,
|
||||
pages,
|
||||
@@ -66,9 +63,12 @@ export function BookReader({ book, pages, onClose }: BookReaderProps) {
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Erreur lors du chargement des URLs:", error);
|
||||
setImageError(true);
|
||||
} finally {
|
||||
if (error instanceof Error) {
|
||||
console.error(
|
||||
`Erreur de chargement des URLs pour la page ${currentPage}:`,
|
||||
error.message
|
||||
);
|
||||
}
|
||||
// On s'assure que le chargement est terminé même en cas d'erreur
|
||||
if (isMounted) {
|
||||
setIsLoading(false);
|
||||
@@ -91,7 +91,6 @@ export function BookReader({ book, pages, onClose }: BookReaderProps) {
|
||||
getPageUrl,
|
||||
setIsLoading,
|
||||
setSecondPageLoading,
|
||||
setImageError,
|
||||
]);
|
||||
|
||||
// Effet pour précharger la page courante et les pages adjacentes
|
||||
@@ -205,6 +204,13 @@ export function BookReader({ book, pages, onClose }: BookReaderProps) {
|
||||
{/* Pages */}
|
||||
<div className="relative flex-1 flex items-center justify-center overflow-hidden p-1">
|
||||
<div className="relative w-full h-[calc(100vh-2rem)] flex items-center justify-center gap-0">
|
||||
{/*
|
||||
Note: Nous utilisons intentionnellement des balises <img> natives au lieu de next/image pour :
|
||||
1. Avoir un contrôle précis sur le chargement et le préchargement des pages
|
||||
2. Gérer efficacement le mode double page et les transitions
|
||||
3. Les images sont déjà optimisées côté serveur
|
||||
4. La performance est critique pour une lecture fluide
|
||||
*/}
|
||||
{/* Page courante */}
|
||||
<div
|
||||
className={cn(
|
||||
|
||||
@@ -3,8 +3,6 @@
|
||||
import { KomgaBook } from "@/types/komga";
|
||||
import { BookReader } from "./BookReader";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { useEffect } from "react";
|
||||
import { useToast } from "@/components/ui/use-toast";
|
||||
|
||||
interface ClientBookWrapperProps {
|
||||
book: KomgaBook;
|
||||
|
||||
@@ -31,6 +31,10 @@ export const ControlButtons = ({
|
||||
"absolute top-4 left-1/2 -translate-x-1/2 z-30 flex items-center gap-2 transition-all duration-300",
|
||||
showControls ? "opacity-100" : "opacity-0 pointer-events-none"
|
||||
)}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
onToggleControls();
|
||||
}}
|
||||
>
|
||||
<button
|
||||
onClick={(e) => {
|
||||
|
||||
@@ -2,7 +2,7 @@ import { NavigationBarProps } from "../types";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { Thumbnail } from "./Thumbnail";
|
||||
import { useThumbnails } from "../hooks/useThumbnails";
|
||||
import { useEffect } from "react";
|
||||
import { useEffect, useRef } from "react";
|
||||
|
||||
export const NavigationBar = ({
|
||||
currentPage,
|
||||
@@ -11,16 +11,13 @@ export const NavigationBar = ({
|
||||
showControls,
|
||||
book,
|
||||
}: NavigationBarProps) => {
|
||||
const {
|
||||
loadedThumbnails,
|
||||
handleThumbnailLoad,
|
||||
getThumbnailUrl,
|
||||
visibleThumbnails,
|
||||
scrollToActiveThumbnail,
|
||||
} = useThumbnails({
|
||||
book,
|
||||
currentPage,
|
||||
});
|
||||
const { loadedThumbnails, handleThumbnailLoad, getThumbnailUrl, visibleThumbnails } =
|
||||
useThumbnails({
|
||||
book,
|
||||
currentPage,
|
||||
});
|
||||
|
||||
const thumbnailsContainerRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
// Scroll à l'ouverture des contrôles et au changement de page
|
||||
useEffect(() => {
|
||||
@@ -53,6 +50,7 @@ export const NavigationBar = ({
|
||||
onTouchStart={(e) => e.stopPropagation()}
|
||||
onTouchMove={(e) => e.stopPropagation()}
|
||||
onTouchEnd={(e) => e.stopPropagation()}
|
||||
ref={thumbnailsContainerRef}
|
||||
>
|
||||
<div className="w-[calc(50vw-18rem)] flex-shrink-0" />
|
||||
{pages.map((_, index) => {
|
||||
|
||||
@@ -6,15 +6,7 @@ import { forwardRef, useEffect, useState, useCallback, useRef } from "react";
|
||||
|
||||
export const Thumbnail = forwardRef<HTMLButtonElement, ThumbnailProps>(
|
||||
(
|
||||
{
|
||||
pageNumber,
|
||||
currentPage,
|
||||
onPageChange,
|
||||
getThumbnailUrl,
|
||||
loadedThumbnails,
|
||||
onThumbnailLoad,
|
||||
isVisible,
|
||||
},
|
||||
{ pageNumber, currentPage, onPageChange, getThumbnailUrl, loadedThumbnails, onThumbnailLoad },
|
||||
ref
|
||||
) => {
|
||||
const [imageUrl, setImageUrl] = useState<string | null>(null);
|
||||
@@ -59,9 +51,6 @@ export const Thumbnail = forwardRef<HTMLButtonElement, ThumbnailProps>(
|
||||
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);
|
||||
@@ -94,7 +83,7 @@ export const Thumbnail = forwardRef<HTMLButtonElement, ThumbnailProps>(
|
||||
src={imageUrl}
|
||||
alt={`Miniature page ${pageNumber}`}
|
||||
className={cn(
|
||||
"object-cover transition-opacity duration-300",
|
||||
"object-contain transition-opacity duration-300",
|
||||
isLoading ? "opacity-0" : "opacity-100"
|
||||
)}
|
||||
fill
|
||||
|
||||
@@ -12,12 +12,11 @@ export const usePageNavigation = ({
|
||||
book,
|
||||
pages,
|
||||
isDoublePage,
|
||||
onClose = () => {},
|
||||
onClose,
|
||||
}: UsePageNavigationProps) => {
|
||||
const [currentPage, setCurrentPage] = useState(book.readProgress?.page || 1);
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
const [secondPageLoading, setSecondPageLoading] = useState(true);
|
||||
const [imageError, setImageError] = useState(false);
|
||||
const timeoutRef = useRef<NodeJS.Timeout | null>(null);
|
||||
const touchStartXRef = useRef<number | null>(null);
|
||||
const touchStartYRef = useRef<number | null>(null);
|
||||
@@ -39,7 +38,12 @@ export const usePageNavigation = ({
|
||||
body: JSON.stringify({ page, completed }),
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("Erreur lors de la synchronisation de la progression:", error);
|
||||
if (error instanceof Error) {
|
||||
console.error(
|
||||
`Erreur de synchronisation de la progression pour le livre ${book.id} à la page ${page}:`,
|
||||
error.message
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
[book.id, pages.length]
|
||||
@@ -73,7 +77,6 @@ export const usePageNavigation = ({
|
||||
setCurrentPage(page);
|
||||
setIsLoading(true);
|
||||
setSecondPageLoading(true);
|
||||
setImageError(false);
|
||||
debouncedSyncReadProgress(page);
|
||||
},
|
||||
[debouncedSyncReadProgress]
|
||||
@@ -167,11 +170,8 @@ export const usePageNavigation = ({
|
||||
setIsLoading,
|
||||
secondPageLoading,
|
||||
setSecondPageLoading,
|
||||
imageError,
|
||||
setImageError,
|
||||
handlePreviousPage,
|
||||
handleNextPage,
|
||||
shouldShowDoublePage,
|
||||
syncReadProgress: debouncedSyncReadProgress,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -16,7 +16,8 @@ export const useThumbnails = ({ book, currentPage }: UseThumbnailsProps) => {
|
||||
|
||||
const getThumbnailUrl = useCallback(
|
||||
(pageNumber: number) => {
|
||||
return `/api/komga/images/books/${book.id}/pages/${pageNumber}/thumbnail`;
|
||||
const zeroBasedPage = pageNumber - 1;
|
||||
return `/api/komga/images/books/${book.id}/pages/${zeroBasedPage}/thumbnail?zero_based=true`;
|
||||
},
|
||||
[book.id]
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user