mirror of
https://github.com/Frooodle/Stirling-PDF.git
synced 2025-09-08 17:51:20 +02:00
Viewer improvements
This commit is contained in:
parent
934cd01268
commit
9cec0e743c
@ -1,4 +1,4 @@
|
|||||||
import React, { useEffect, useState, useRef } from "react";
|
import React, { useEffect, useState, useRef, useCallback } from "react";
|
||||||
import { Paper, Stack, Text, ScrollArea, Loader, Center, Button, Group, NumberInput, useMantineTheme, ActionIcon, Box } from "@mantine/core";
|
import { Paper, Stack, Text, ScrollArea, Loader, Center, Button, Group, NumberInput, useMantineTheme, ActionIcon, Box } from "@mantine/core";
|
||||||
import { getDocument, GlobalWorkerOptions } from "pdfjs-dist";
|
import { getDocument, GlobalWorkerOptions } from "pdfjs-dist";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
@ -184,7 +184,6 @@ const Viewer = ({
|
|||||||
}, [previewFile, pdfFile]);
|
}, [previewFile, pdfFile]);
|
||||||
|
|
||||||
const scrollAreaRef = useRef<HTMLDivElement>(null);
|
const scrollAreaRef = useRef<HTMLDivElement>(null);
|
||||||
const isManualNavigationRef = useRef(false);
|
|
||||||
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);
|
||||||
@ -270,24 +269,28 @@ const Viewer = ({
|
|||||||
}
|
}
|
||||||
}, [numPages, currentPage]);
|
}, [numPages, currentPage]);
|
||||||
|
|
||||||
// Scroll to the current page when manually navigated
|
// Function to scroll to a specific page
|
||||||
useEffect(() => {
|
const scrollToPage = (pageNumber: number) => {
|
||||||
if (currentPage && pageRefs.current[currentPage - 1] && isManualNavigationRef.current) {
|
const el = pageRefs.current[pageNumber - 1];
|
||||||
const el = pageRefs.current[currentPage - 1];
|
const scrollArea = scrollAreaRef.current;
|
||||||
el?.scrollIntoView({ behavior: "smooth", block: "center" });
|
|
||||||
|
if (el && scrollArea) {
|
||||||
|
const scrollAreaRect = scrollArea.getBoundingClientRect();
|
||||||
|
const elRect = el.getBoundingClientRect();
|
||||||
|
const currentScrollTop = scrollArea.scrollTop;
|
||||||
|
|
||||||
// Reset manual navigation flag after a delay
|
// Position page near top of viewport with some padding
|
||||||
const timeout = setTimeout(() => {
|
const targetScrollTop = currentScrollTop + (elRect.top - scrollAreaRect.top) - 20;
|
||||||
isManualNavigationRef.current = false;
|
|
||||||
}, 1000);
|
|
||||||
|
|
||||||
return () => clearTimeout(timeout);
|
scrollArea.scrollTo({
|
||||||
|
top: targetScrollTop,
|
||||||
|
behavior: "smooth"
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}, [currentPage, pageImages]);
|
};
|
||||||
|
|
||||||
// Detect visible page on scroll (only update display, don't trigger navigation)
|
// Throttled scroll handler to prevent jerky updates
|
||||||
const handleScroll = () => {
|
const handleScrollThrottled = useCallback(() => {
|
||||||
if (isManualNavigationRef.current) return;
|
|
||||||
const scrollArea = scrollAreaRef.current;
|
const scrollArea = scrollAreaRef.current;
|
||||||
if (!scrollArea || !pageRefs.current.length) return;
|
if (!scrollArea || !pageRefs.current.length) return;
|
||||||
|
|
||||||
@ -308,11 +311,20 @@ const Viewer = ({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Only update if the page actually changed and we're not in manual navigation
|
// Update page number display only if changed
|
||||||
if (currentPage !== closestIdx + 1) {
|
if (currentPage !== closestIdx + 1) {
|
||||||
setCurrentPage(closestIdx + 1);
|
setCurrentPage(closestIdx + 1);
|
||||||
}
|
}
|
||||||
};
|
}, [currentPage]);
|
||||||
|
|
||||||
|
// Throttle scroll events to reduce jerkiness
|
||||||
|
const handleScroll = useCallback(() => {
|
||||||
|
if (window.requestAnimationFrame) {
|
||||||
|
window.requestAnimationFrame(handleScrollThrottled);
|
||||||
|
} else {
|
||||||
|
handleScrollThrottled();
|
||||||
|
}
|
||||||
|
}, [handleScrollThrottled]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
let cancelled = false;
|
let cancelled = false;
|
||||||
@ -523,8 +535,7 @@ const Viewer = ({
|
|||||||
px={8}
|
px={8}
|
||||||
radius="xl"
|
radius="xl"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
isManualNavigationRef.current = true;
|
scrollToPage(1);
|
||||||
setCurrentPage(1);
|
|
||||||
}}
|
}}
|
||||||
disabled={currentPage === 1}
|
disabled={currentPage === 1}
|
||||||
style={{ minWidth: 36 }}
|
style={{ minWidth: 36 }}
|
||||||
@ -538,8 +549,8 @@ const Viewer = ({
|
|||||||
px={8}
|
px={8}
|
||||||
radius="xl"
|
radius="xl"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
isManualNavigationRef.current = true;
|
const prevPage = Math.max(1, (currentPage || 1) - 1);
|
||||||
setCurrentPage(Math.max(1, (currentPage || 1) - 1));
|
scrollToPage(prevPage);
|
||||||
}}
|
}}
|
||||||
disabled={currentPage === 1}
|
disabled={currentPage === 1}
|
||||||
style={{ minWidth: 36 }}
|
style={{ minWidth: 36 }}
|
||||||
@ -551,8 +562,7 @@ const Viewer = ({
|
|||||||
onChange={value => {
|
onChange={value => {
|
||||||
const page = Number(value);
|
const page = Number(value);
|
||||||
if (!isNaN(page) && page >= 1 && page <= numPages) {
|
if (!isNaN(page) && page >= 1 && page <= numPages) {
|
||||||
isManualNavigationRef.current = true;
|
scrollToPage(page);
|
||||||
setCurrentPage(page);
|
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
min={1}
|
min={1}
|
||||||
@ -572,8 +582,8 @@ const Viewer = ({
|
|||||||
px={8}
|
px={8}
|
||||||
radius="xl"
|
radius="xl"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
isManualNavigationRef.current = true;
|
const nextPage = Math.min(numPages, (currentPage || 1) + 1);
|
||||||
setCurrentPage(Math.min(numPages, (currentPage || 1) + 1));
|
scrollToPage(nextPage);
|
||||||
}}
|
}}
|
||||||
disabled={currentPage === numPages}
|
disabled={currentPage === numPages}
|
||||||
style={{ minWidth: 36 }}
|
style={{ minWidth: 36 }}
|
||||||
@ -587,8 +597,7 @@ const Viewer = ({
|
|||||||
px={8}
|
px={8}
|
||||||
radius="xl"
|
radius="xl"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
isManualNavigationRef.current = true;
|
scrollToPage(numPages);
|
||||||
setCurrentPage(numPages);
|
|
||||||
}}
|
}}
|
||||||
disabled={currentPage === numPages}
|
disabled={currentPage === numPages}
|
||||||
style={{ minWidth: 36 }}
|
style={{ minWidth: 36 }}
|
||||||
|
Loading…
Reference in New Issue
Block a user