refacto: Split reader
This commit is contained in:
@@ -5,20 +5,22 @@ import { BookReaderProps } from "./types";
|
|||||||
import { useOrientation } from "./hooks/useOrientation";
|
import { useOrientation } from "./hooks/useOrientation";
|
||||||
import { usePageNavigation } from "./hooks/usePageNavigation";
|
import { usePageNavigation } from "./hooks/usePageNavigation";
|
||||||
import { usePageCache } from "./hooks/usePageCache";
|
import { usePageCache } from "./hooks/usePageCache";
|
||||||
|
import { usePageUrls } from "./hooks/usePageUrls";
|
||||||
|
import { usePreloadPages } from "./hooks/usePreloadPages";
|
||||||
|
import { useFullscreen } from "./hooks/useFullscreen";
|
||||||
import { useState, useEffect, useCallback, useRef } from "react";
|
import { useState, useEffect, useCallback, useRef } from "react";
|
||||||
import { NavigationBar } from "./components/NavigationBar";
|
import { NavigationBar } from "./components/NavigationBar";
|
||||||
import { ControlButtons } from "./components/ControlButtons";
|
import { ControlButtons } from "./components/ControlButtons";
|
||||||
import { ImageLoader } from "@/components/ui/image-loader";
|
import { ReaderContent } from "./components/ReaderContent";
|
||||||
import { cn } from "@/lib/utils";
|
|
||||||
import { useReadingDirection } from "./hooks/useReadingDirection";
|
import { useReadingDirection } from "./hooks/useReadingDirection";
|
||||||
|
|
||||||
export function BookReader({ book, pages, onClose }: BookReaderProps) {
|
export function BookReader({ book, pages, onClose }: BookReaderProps) {
|
||||||
const [isDoublePage, setIsDoublePage] = useState(false);
|
const [isDoublePage, setIsDoublePage] = useState(false);
|
||||||
const [showControls, setShowControls] = useState(false);
|
const [showControls, setShowControls] = useState(false);
|
||||||
const [isFullscreen, setIsFullscreen] = useState(false);
|
|
||||||
const readerRef = useRef<HTMLDivElement>(null);
|
const readerRef = useRef<HTMLDivElement>(null);
|
||||||
const isLandscape = useOrientation();
|
const isLandscape = useOrientation();
|
||||||
const { direction, toggleDirection, isRTL } = useReadingDirection();
|
const { direction, toggleDirection, isRTL } = useReadingDirection();
|
||||||
|
const { isFullscreen, toggleFullscreen } = useFullscreen();
|
||||||
|
|
||||||
const {
|
const {
|
||||||
currentPage,
|
currentPage,
|
||||||
@@ -43,130 +45,29 @@ export function BookReader({ book, pages, onClose }: BookReaderProps) {
|
|||||||
pages,
|
pages,
|
||||||
});
|
});
|
||||||
|
|
||||||
// État pour stocker les URLs des images
|
const { currentPageUrl, nextPageUrl } = usePageUrls({
|
||||||
const [currentPageUrl, setCurrentPageUrl] = useState<string>("");
|
|
||||||
const [nextPageUrl, setNextPageUrl] = useState<string>("");
|
|
||||||
|
|
||||||
// Effet pour charger les URLs des images
|
|
||||||
useEffect(() => {
|
|
||||||
let isMounted = true;
|
|
||||||
|
|
||||||
const loadPageUrls = async () => {
|
|
||||||
try {
|
|
||||||
const url = await getPageUrl(currentPage);
|
|
||||||
if (isMounted) {
|
|
||||||
setCurrentPageUrl(url);
|
|
||||||
setIsLoading(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isDoublePage && shouldShowDoublePage(currentPage)) {
|
|
||||||
const nextUrl = await getPageUrl(currentPage + 1);
|
|
||||||
if (isMounted) {
|
|
||||||
setNextPageUrl(nextUrl);
|
|
||||||
setSecondPageLoading(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
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);
|
|
||||||
setSecondPageLoading(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
setIsLoading(true);
|
|
||||||
setSecondPageLoading(true);
|
|
||||||
loadPageUrls();
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
isMounted = false;
|
|
||||||
};
|
|
||||||
}, [
|
|
||||||
currentPage,
|
currentPage,
|
||||||
isDoublePage,
|
isDoublePage,
|
||||||
shouldShowDoublePage,
|
shouldShowDoublePage,
|
||||||
getPageUrl,
|
getPageUrl,
|
||||||
setIsLoading,
|
setIsLoading,
|
||||||
setSecondPageLoading,
|
setSecondPageLoading,
|
||||||
]);
|
});
|
||||||
|
|
||||||
// Effet pour précharger la page courante et les pages adjacentes
|
usePreloadPages({
|
||||||
useEffect(() => {
|
|
||||||
let isMounted = true;
|
|
||||||
|
|
||||||
const preloadCurrentPages = async () => {
|
|
||||||
if (!isMounted) return;
|
|
||||||
|
|
||||||
await preloadPage(currentPage);
|
|
||||||
|
|
||||||
if (!isMounted) return;
|
|
||||||
|
|
||||||
if (isDoublePage && shouldShowDoublePage(currentPage)) {
|
|
||||||
await preloadPage(currentPage + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isMounted) return;
|
|
||||||
|
|
||||||
const pagesToPreload = [];
|
|
||||||
|
|
||||||
for (let i = 1; i <= 4 && currentPage + i <= pages.length; i++) {
|
|
||||||
pagesToPreload.push(currentPage + i);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let i = 1; i <= 2 && currentPage - i >= 1; i++) {
|
|
||||||
pagesToPreload.push(currentPage - i);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const page of pagesToPreload) {
|
|
||||||
if (!isMounted) break;
|
|
||||||
await preloadPage(page);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
preloadCurrentPages();
|
|
||||||
cleanCache(currentPage);
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
isMounted = false;
|
|
||||||
};
|
|
||||||
}, [
|
|
||||||
currentPage,
|
currentPage,
|
||||||
|
totalPages: pages.length,
|
||||||
isDoublePage,
|
isDoublePage,
|
||||||
shouldShowDoublePage,
|
shouldShowDoublePage,
|
||||||
preloadPage,
|
preloadPage,
|
||||||
cleanCache,
|
cleanCache,
|
||||||
pages.length,
|
});
|
||||||
isRTL,
|
|
||||||
]);
|
|
||||||
|
|
||||||
// Effet pour gérer le mode double page automatiquement en paysage
|
// Effet pour gérer le mode double page automatiquement en paysage
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setIsDoublePage(isLandscape);
|
setIsDoublePage(isLandscape);
|
||||||
}, [isLandscape]);
|
}, [isLandscape]);
|
||||||
|
|
||||||
// Effet pour gérer le fullscreen
|
|
||||||
useEffect(() => {
|
|
||||||
const handleFullscreenChange = () => {
|
|
||||||
setIsFullscreen(!!document.fullscreenElement);
|
|
||||||
};
|
|
||||||
|
|
||||||
document.addEventListener("fullscreenchange", handleFullscreenChange);
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
document.removeEventListener("fullscreenchange", handleFullscreenChange);
|
|
||||||
if (document.fullscreenElement) {
|
|
||||||
document.exitFullscreen().catch(console.error);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const handleThumbnailLoad = useCallback(
|
const handleThumbnailLoad = useCallback(
|
||||||
(pageNumber: number) => {
|
(pageNumber: number) => {
|
||||||
if (pageNumber === currentPage) {
|
if (pageNumber === currentPage) {
|
||||||
@@ -187,7 +88,6 @@ export function BookReader({ book, pages, onClose }: BookReaderProps) {
|
|||||||
className="relative h-full flex flex-col items-center justify-center"
|
className="relative h-full flex flex-col items-center justify-center"
|
||||||
onClick={() => setShowControls(!showControls)}
|
onClick={() => setShowControls(!showControls)}
|
||||||
>
|
>
|
||||||
{/* Contenu principal */}
|
|
||||||
<div className="relative h-full w-full flex items-center justify-center">
|
<div className="relative h-full w-full flex items-center justify-center">
|
||||||
<ControlButtons
|
<ControlButtons
|
||||||
showControls={showControls}
|
showControls={showControls}
|
||||||
@@ -201,82 +101,23 @@ export function BookReader({ book, pages, onClose }: BookReaderProps) {
|
|||||||
isDoublePage={isDoublePage}
|
isDoublePage={isDoublePage}
|
||||||
onToggleDoublePage={() => setIsDoublePage(!isDoublePage)}
|
onToggleDoublePage={() => setIsDoublePage(!isDoublePage)}
|
||||||
isFullscreen={isFullscreen}
|
isFullscreen={isFullscreen}
|
||||||
onToggleFullscreen={async () => {
|
onToggleFullscreen={() => toggleFullscreen(readerRef.current)}
|
||||||
try {
|
|
||||||
if (isFullscreen) {
|
|
||||||
await document.exitFullscreen();
|
|
||||||
} else if (readerRef.current) {
|
|
||||||
await readerRef.current.requestFullscreen();
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Erreur lors du changement de mode plein écran:", error);
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
direction={direction}
|
direction={direction}
|
||||||
onToggleDirection={toggleDirection}
|
onToggleDirection={toggleDirection}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{/* Pages */}
|
<ReaderContent
|
||||||
<div className="relative flex-1 flex items-center justify-center overflow-hidden p-1">
|
currentPage={currentPage}
|
||||||
<div className="relative w-full h-[calc(100vh-2rem)] flex items-center justify-center gap-0">
|
currentPageUrl={currentPageUrl}
|
||||||
{/*
|
nextPageUrl={nextPageUrl}
|
||||||
Note: Nous utilisons intentionnellement des balises <img> natives au lieu de next/image pour :
|
isLoading={isLoading}
|
||||||
1. Avoir un contrôle précis sur le chargement et le préchargement des pages
|
secondPageLoading={secondPageLoading}
|
||||||
2. Gérer efficacement le mode double page et les transitions
|
isDoublePage={isDoublePage}
|
||||||
3. Les images sont déjà optimisées côté serveur
|
shouldShowDoublePage={shouldShowDoublePage}
|
||||||
4. La performance est critique pour une lecture fluide
|
isRTL={isRTL}
|
||||||
*/}
|
onThumbnailLoad={handleThumbnailLoad}
|
||||||
<div
|
|
||||||
className={cn(
|
|
||||||
"relative h-full flex items-center",
|
|
||||||
isDoublePage && {
|
|
||||||
"w-1/2": true,
|
|
||||||
"order-2 justify-start": isRTL,
|
|
||||||
"order-1 justify-end": !isRTL,
|
|
||||||
},
|
|
||||||
!isDoublePage && "w-full justify-center"
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
<ImageLoader isLoading={isLoading} />
|
|
||||||
{currentPageUrl && (
|
|
||||||
<img
|
|
||||||
src={currentPageUrl}
|
|
||||||
alt={`Page ${currentPage}`}
|
|
||||||
className={cn(
|
|
||||||
"max-h-full w-auto object-contain transition-opacity duration-300",
|
|
||||||
isLoading ? "opacity-0" : "opacity-100"
|
|
||||||
)}
|
|
||||||
onLoad={() => handleThumbnailLoad(currentPage)}
|
|
||||||
/>
|
/>
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Deuxième page en mode double page */}
|
|
||||||
{isDoublePage && shouldShowDoublePage(currentPage) && (
|
|
||||||
<div
|
|
||||||
className={cn(
|
|
||||||
"relative h-full w-1/2 flex items-center",
|
|
||||||
isRTL ? "order-1 justify-end" : "order-2 justify-start"
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
<ImageLoader isLoading={secondPageLoading} />
|
|
||||||
{nextPageUrl && (
|
|
||||||
<img
|
|
||||||
src={nextPageUrl}
|
|
||||||
alt={`Page ${currentPage + 1}`}
|
|
||||||
className={cn(
|
|
||||||
"max-h-full w-auto object-contain transition-opacity duration-300",
|
|
||||||
secondPageLoading ? "opacity-0" : "opacity-100"
|
|
||||||
)}
|
|
||||||
onLoad={() => handleThumbnailLoad(currentPage + 1)}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Barre de navigation */}
|
|
||||||
<NavigationBar
|
<NavigationBar
|
||||||
currentPage={currentPage}
|
currentPage={currentPage}
|
||||||
pages={pages}
|
pages={pages}
|
||||||
|
|||||||
53
src/components/reader/components/ReaderContent.tsx
Normal file
53
src/components/reader/components/ReaderContent.tsx
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
import { SinglePage } from "./SinglePage";
|
||||||
|
|
||||||
|
interface ReaderContentProps {
|
||||||
|
currentPage: number;
|
||||||
|
currentPageUrl: string;
|
||||||
|
nextPageUrl: string;
|
||||||
|
isLoading: boolean;
|
||||||
|
secondPageLoading: boolean;
|
||||||
|
isDoublePage: boolean;
|
||||||
|
shouldShowDoublePage: (page: number) => boolean;
|
||||||
|
isRTL: boolean;
|
||||||
|
onThumbnailLoad: (pageNumber: number) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ReaderContent = ({
|
||||||
|
currentPage,
|
||||||
|
currentPageUrl,
|
||||||
|
nextPageUrl,
|
||||||
|
isLoading,
|
||||||
|
secondPageLoading,
|
||||||
|
isDoublePage,
|
||||||
|
shouldShowDoublePage,
|
||||||
|
isRTL,
|
||||||
|
onThumbnailLoad,
|
||||||
|
}: ReaderContentProps) => {
|
||||||
|
return (
|
||||||
|
<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">
|
||||||
|
<SinglePage
|
||||||
|
pageUrl={currentPageUrl}
|
||||||
|
pageNumber={currentPage}
|
||||||
|
isLoading={isLoading}
|
||||||
|
onLoad={onThumbnailLoad}
|
||||||
|
isDoublePage={isDoublePage}
|
||||||
|
isRTL={isRTL}
|
||||||
|
order="first"
|
||||||
|
/>
|
||||||
|
|
||||||
|
{isDoublePage && shouldShowDoublePage(currentPage) && (
|
||||||
|
<SinglePage
|
||||||
|
pageUrl={nextPageUrl}
|
||||||
|
pageNumber={currentPage + 1}
|
||||||
|
isLoading={secondPageLoading}
|
||||||
|
onLoad={onThumbnailLoad}
|
||||||
|
isDoublePage={true}
|
||||||
|
isRTL={isRTL}
|
||||||
|
order="second"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
49
src/components/reader/components/SinglePage.tsx
Normal file
49
src/components/reader/components/SinglePage.tsx
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
import { cn } from "@/lib/utils";
|
||||||
|
import { ImageLoader } from "@/components/ui/image-loader";
|
||||||
|
|
||||||
|
interface SinglePageProps {
|
||||||
|
pageUrl: string;
|
||||||
|
pageNumber: number;
|
||||||
|
isLoading: boolean;
|
||||||
|
onLoad: (pageNumber: number) => void;
|
||||||
|
isDoublePage?: boolean;
|
||||||
|
isRTL?: boolean;
|
||||||
|
order?: "first" | "second";
|
||||||
|
}
|
||||||
|
|
||||||
|
export const SinglePage = ({
|
||||||
|
pageUrl,
|
||||||
|
pageNumber,
|
||||||
|
isLoading,
|
||||||
|
onLoad,
|
||||||
|
isDoublePage = false,
|
||||||
|
isRTL = false,
|
||||||
|
order = "first",
|
||||||
|
}: SinglePageProps) => {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={cn(
|
||||||
|
"relative h-full flex items-center",
|
||||||
|
isDoublePage && {
|
||||||
|
"w-1/2": true,
|
||||||
|
"order-2 justify-start": order === "first" ? isRTL : !isRTL,
|
||||||
|
"order-1 justify-end": order === "first" ? !isRTL : isRTL,
|
||||||
|
},
|
||||||
|
!isDoublePage && "w-full justify-center"
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<ImageLoader isLoading={isLoading} />
|
||||||
|
{pageUrl && (
|
||||||
|
<img
|
||||||
|
src={pageUrl}
|
||||||
|
alt={`Page ${pageNumber}`}
|
||||||
|
className={cn(
|
||||||
|
"max-h-full w-auto object-contain transition-opacity duration-300",
|
||||||
|
isLoading ? "opacity-0" : "opacity-100"
|
||||||
|
)}
|
||||||
|
onLoad={() => onLoad(pageNumber)}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
37
src/components/reader/hooks/useFullscreen.ts
Normal file
37
src/components/reader/hooks/useFullscreen.ts
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
import { useState, useEffect } from "react";
|
||||||
|
|
||||||
|
export const useFullscreen = () => {
|
||||||
|
const [isFullscreen, setIsFullscreen] = useState(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const handleFullscreenChange = () => {
|
||||||
|
setIsFullscreen(!!document.fullscreenElement);
|
||||||
|
};
|
||||||
|
|
||||||
|
document.addEventListener("fullscreenchange", handleFullscreenChange);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
document.removeEventListener("fullscreenchange", handleFullscreenChange);
|
||||||
|
if (document.fullscreenElement) {
|
||||||
|
document.exitFullscreen().catch(console.error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const toggleFullscreen = async (element: HTMLElement | null) => {
|
||||||
|
try {
|
||||||
|
if (isFullscreen) {
|
||||||
|
await document.exitFullscreen();
|
||||||
|
} else if (element) {
|
||||||
|
await element.requestFullscreen();
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Erreur lors du changement de mode plein écran:", error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
isFullscreen,
|
||||||
|
toggleFullscreen,
|
||||||
|
};
|
||||||
|
};
|
||||||
75
src/components/reader/hooks/usePageUrls.ts
Normal file
75
src/components/reader/hooks/usePageUrls.ts
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
import { useState, useEffect } from "react";
|
||||||
|
|
||||||
|
interface UsePageUrlsProps {
|
||||||
|
currentPage: number;
|
||||||
|
isDoublePage: boolean;
|
||||||
|
shouldShowDoublePage: (page: number) => boolean;
|
||||||
|
getPageUrl: (page: number) => Promise<string>;
|
||||||
|
setIsLoading: (loading: boolean) => void;
|
||||||
|
setSecondPageLoading: (loading: boolean) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const usePageUrls = ({
|
||||||
|
currentPage,
|
||||||
|
isDoublePage,
|
||||||
|
shouldShowDoublePage,
|
||||||
|
getPageUrl,
|
||||||
|
setIsLoading,
|
||||||
|
setSecondPageLoading,
|
||||||
|
}: UsePageUrlsProps) => {
|
||||||
|
const [currentPageUrl, setCurrentPageUrl] = useState<string>("");
|
||||||
|
const [nextPageUrl, setNextPageUrl] = useState<string>("");
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
let isMounted = true;
|
||||||
|
|
||||||
|
const loadPageUrls = async () => {
|
||||||
|
try {
|
||||||
|
const url = await getPageUrl(currentPage);
|
||||||
|
if (isMounted) {
|
||||||
|
setCurrentPageUrl(url);
|
||||||
|
setIsLoading(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isDoublePage && shouldShowDoublePage(currentPage)) {
|
||||||
|
const nextUrl = await getPageUrl(currentPage + 1);
|
||||||
|
if (isMounted) {
|
||||||
|
setNextPageUrl(nextUrl);
|
||||||
|
setSecondPageLoading(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
if (error instanceof Error) {
|
||||||
|
console.error(
|
||||||
|
`Erreur de chargement des URLs pour la page ${currentPage}:`,
|
||||||
|
error.message
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (isMounted) {
|
||||||
|
setIsLoading(false);
|
||||||
|
setSecondPageLoading(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
setIsLoading(true);
|
||||||
|
setSecondPageLoading(true);
|
||||||
|
loadPageUrls();
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
isMounted = false;
|
||||||
|
};
|
||||||
|
}, [
|
||||||
|
currentPage,
|
||||||
|
isDoublePage,
|
||||||
|
shouldShowDoublePage,
|
||||||
|
getPageUrl,
|
||||||
|
setIsLoading,
|
||||||
|
setSecondPageLoading,
|
||||||
|
]);
|
||||||
|
|
||||||
|
return {
|
||||||
|
currentPageUrl,
|
||||||
|
nextPageUrl,
|
||||||
|
};
|
||||||
|
};
|
||||||
61
src/components/reader/hooks/usePreloadPages.ts
Normal file
61
src/components/reader/hooks/usePreloadPages.ts
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
import { useEffect } from "react";
|
||||||
|
|
||||||
|
interface UsePreloadPagesProps {
|
||||||
|
currentPage: number;
|
||||||
|
totalPages: number;
|
||||||
|
isDoublePage: boolean;
|
||||||
|
shouldShowDoublePage: (page: number) => boolean;
|
||||||
|
preloadPage: (page: number) => Promise<void>;
|
||||||
|
cleanCache: (currentPage: number) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const usePreloadPages = ({
|
||||||
|
currentPage,
|
||||||
|
totalPages,
|
||||||
|
isDoublePage,
|
||||||
|
shouldShowDoublePage,
|
||||||
|
preloadPage,
|
||||||
|
cleanCache,
|
||||||
|
}: UsePreloadPagesProps) => {
|
||||||
|
useEffect(() => {
|
||||||
|
let isMounted = true;
|
||||||
|
|
||||||
|
const preloadCurrentPages = async () => {
|
||||||
|
if (!isMounted) return;
|
||||||
|
|
||||||
|
await preloadPage(currentPage);
|
||||||
|
|
||||||
|
if (!isMounted) return;
|
||||||
|
|
||||||
|
if (isDoublePage && shouldShowDoublePage(currentPage)) {
|
||||||
|
await preloadPage(currentPage + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isMounted) return;
|
||||||
|
|
||||||
|
const pagesToPreload = [];
|
||||||
|
|
||||||
|
// Précharger les 4 pages suivantes
|
||||||
|
for (let i = 1; i <= 4 && currentPage + i <= totalPages; i++) {
|
||||||
|
pagesToPreload.push(currentPage + i);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Précharger les 2 pages précédentes
|
||||||
|
for (let i = 1; i <= 2 && currentPage - i >= 1; i++) {
|
||||||
|
pagesToPreload.push(currentPage - i);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const page of pagesToPreload) {
|
||||||
|
if (!isMounted) break;
|
||||||
|
await preloadPage(page);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
preloadCurrentPages();
|
||||||
|
cleanCache(currentPage);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
isMounted = false;
|
||||||
|
};
|
||||||
|
}, [currentPage, isDoublePage, shouldShowDoublePage, preloadPage, cleanCache, totalPages]);
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user