mirror of
https://github.com/Frooodle/Stirling-PDF.git
synced 2025-09-08 17:51:20 +02:00
Cache lazy loaded pages in viewer
This commit is contained in:
parent
ffe5b9577b
commit
09758ea2b8
@ -29,7 +29,7 @@ const LazyPageImage = ({
|
|||||||
pageIndex, zoom, theme, isFirst, renderPage, pageImages, setPageRef
|
pageIndex, zoom, theme, isFirst, renderPage, pageImages, setPageRef
|
||||||
}: LazyPageImageProps) => {
|
}: LazyPageImageProps) => {
|
||||||
const [isVisible, setIsVisible] = useState(false);
|
const [isVisible, setIsVisible] = useState(false);
|
||||||
const [imageUrl, setImageUrl] = useState<string | null>(pageImages[pageIndex]);
|
const [imageUrl, setImageUrl] = useState<string | null>(null);
|
||||||
const imgRef = useRef<HTMLImageElement>(null);
|
const imgRef = useRef<HTMLImageElement>(null);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -54,6 +54,13 @@ const LazyPageImage = ({
|
|||||||
return () => observer.disconnect();
|
return () => observer.disconnect();
|
||||||
}, [imageUrl]);
|
}, [imageUrl]);
|
||||||
|
|
||||||
|
// Update local state when pageImages changes (from preloading)
|
||||||
|
useEffect(() => {
|
||||||
|
if (pageImages[pageIndex]) {
|
||||||
|
setImageUrl(pageImages[pageIndex]);
|
||||||
|
}
|
||||||
|
}, [pageImages, pageIndex]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isVisible && !imageUrl) {
|
if (isVisible && !imageUrl) {
|
||||||
renderPage(pageIndex).then((url) => {
|
renderPage(pageIndex).then((url) => {
|
||||||
@ -150,6 +157,7 @@ const Viewer = ({
|
|||||||
const pdfDocRef = useRef<any>(null);
|
const pdfDocRef = useRef<any>(null);
|
||||||
const renderingPagesRef = useRef<Set<number>>(new Set());
|
const renderingPagesRef = useRef<Set<number>>(new Set());
|
||||||
const currentArrayBufferRef = useRef<ArrayBuffer | null>(null);
|
const currentArrayBufferRef = useRef<ArrayBuffer | null>(null);
|
||||||
|
const preloadingRef = useRef<boolean>(false);
|
||||||
|
|
||||||
// Function to render a specific page on-demand
|
// Function to render a specific page on-demand
|
||||||
const renderPage = async (pageIndex: number): Promise<string | null> => {
|
const renderPage = async (pageIndex: number): Promise<string | null> => {
|
||||||
@ -194,6 +202,36 @@ const Viewer = ({
|
|||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Progressive preloading function
|
||||||
|
const startProgressivePreload = async () => {
|
||||||
|
if (!pdfDocRef.current || preloadingRef.current || numPages === 0) return;
|
||||||
|
|
||||||
|
preloadingRef.current = true;
|
||||||
|
|
||||||
|
// Start with first few pages for immediate viewing
|
||||||
|
const priorityPages = [0, 1, 2, 3, 4]; // First 5 pages
|
||||||
|
|
||||||
|
// Render priority pages first
|
||||||
|
for (const pageIndex of priorityPages) {
|
||||||
|
if (pageIndex < numPages && !pageImages[pageIndex]) {
|
||||||
|
await renderPage(pageIndex);
|
||||||
|
// Small delay to allow UI to update
|
||||||
|
await new Promise(resolve => setTimeout(resolve, 50));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Then render remaining pages in background
|
||||||
|
for (let pageIndex = 5; pageIndex < numPages; pageIndex++) {
|
||||||
|
if (!pageImages[pageIndex]) {
|
||||||
|
await renderPage(pageIndex);
|
||||||
|
// Longer delay for background loading to not block UI
|
||||||
|
await new Promise(resolve => setTimeout(resolve, 100));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
preloadingRef.current = false;
|
||||||
|
};
|
||||||
|
|
||||||
// Listen for hash changes and update currentPage
|
// Listen for hash changes and update currentPage
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
function handleHashChange() {
|
function handleHashChange() {
|
||||||
@ -303,13 +341,21 @@ const Viewer = ({
|
|||||||
const pdf = await getDocument({ data: arrayBuffer }).promise;
|
const pdf = await getDocument({ data: arrayBuffer }).promise;
|
||||||
pdfDocRef.current = pdf;
|
pdfDocRef.current = pdf;
|
||||||
setNumPages(pdf.numPages);
|
setNumPages(pdf.numPages);
|
||||||
if (!cancelled) setPageImages(new Array(pdf.numPages).fill(null));
|
if (!cancelled) {
|
||||||
|
setPageImages(new Array(pdf.numPages).fill(null));
|
||||||
|
// Start progressive preloading after a short delay
|
||||||
|
setTimeout(() => startProgressivePreload(), 100);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// Standard blob URL or regular URL
|
// Standard blob URL or regular URL
|
||||||
const pdf = await getDocument(pdfUrl).promise;
|
const pdf = await getDocument(pdfUrl).promise;
|
||||||
pdfDocRef.current = pdf;
|
pdfDocRef.current = pdf;
|
||||||
setNumPages(pdf.numPages);
|
setNumPages(pdf.numPages);
|
||||||
if (!cancelled) setPageImages(new Array(pdf.numPages).fill(null));
|
if (!cancelled) {
|
||||||
|
setPageImages(new Array(pdf.numPages).fill(null));
|
||||||
|
// Start progressive preloading after a short delay
|
||||||
|
setTimeout(() => startProgressivePreload(), 100);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Failed to load PDF:', error);
|
console.error('Failed to load PDF:', error);
|
||||||
@ -323,6 +369,8 @@ const Viewer = ({
|
|||||||
loadPdfInfo();
|
loadPdfInfo();
|
||||||
return () => {
|
return () => {
|
||||||
cancelled = true;
|
cancelled = true;
|
||||||
|
// Stop any ongoing preloading
|
||||||
|
preloadingRef.current = false;
|
||||||
// Cleanup ArrayBuffer reference to help garbage collection
|
// Cleanup ArrayBuffer reference to help garbage collection
|
||||||
currentArrayBufferRef.current = null;
|
currentArrayBufferRef.current = null;
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user