Debounce PDF scale and extraction

This commit is contained in:
Richard Roberson 2025-02-17 10:57:39 -07:00
parent ebff52d4e6
commit 36fdbc276d
2 changed files with 36 additions and 7 deletions

View file

@ -9,6 +9,7 @@ import { useTTS } from '@/contexts/TTSContext';
import { usePDF } from '@/contexts/PDFContext'; import { usePDF } from '@/contexts/PDFContext';
import TTSPlayer from '@/components/player/TTSPlayer'; import TTSPlayer from '@/components/player/TTSPlayer';
import { useConfig } from '@/contexts/ConfigContext'; import { useConfig } from '@/contexts/ConfigContext';
import { debounce } from '@/utils/pdf';
interface PDFViewerProps { interface PDFViewerProps {
zoomLevel: number; zoomLevel: number;
@ -17,6 +18,7 @@ interface PDFViewerProps {
export function PDFViewer({ zoomLevel }: PDFViewerProps) { export function PDFViewer({ zoomLevel }: PDFViewerProps) {
const [containerWidth, setContainerWidth] = useState<number>(0); const [containerWidth, setContainerWidth] = useState<number>(0);
const containerRef = useRef<HTMLDivElement>(null); const containerRef = useRef<HTMLDivElement>(null);
const scaleRef = useRef<number>(1);
// Config context // Config context
const { viewType } = useConfig(); const { viewType } = useConfig();
@ -124,7 +126,7 @@ export function PDFViewer({ zoomLevel }: PDFViewerProps) {
? (currDocPage % 2 === 0 ? currDocPage : currDocPage + 1) ? (currDocPage % 2 === 0 ? currDocPage : currDocPage + 1)
: null; : null;
// Modify scale calculation to account for view type // Modify scale calculation to be more efficient
const calculateScale = useCallback((width = pageWidth, height = pageHeight): number => { const calculateScale = useCallback((width = pageWidth, height = pageHeight): number => {
const margin = viewType === 'dual' ? 48 : 24; // adjust margin based on view type const margin = viewType === 'dual' ? 48 : 24; // adjust margin based on view type
const containerHeight = window.innerHeight - 100; const containerHeight = window.innerHeight - 100;
@ -147,19 +149,34 @@ export function PDFViewer({ zoomLevel }: PDFViewerProps) {
return baseScale * (zoomLevel / 100); return baseScale * (zoomLevel / 100);
}, [containerWidth, zoomLevel, pageWidth, pageHeight, viewType]); }, [containerWidth, zoomLevel, pageWidth, pageHeight, viewType]);
// Add resize observer effect // Add memoized scale to prevent unnecessary recalculations
const currentScale = useCallback(() => {
const newScale = calculateScale();
if (Math.abs(newScale - scaleRef.current) > 0.01) {
scaleRef.current = newScale;
}
return scaleRef.current;
}, [calculateScale]);
// Modify resize observer effect to use debouncing
useEffect(() => { useEffect(() => {
if (!containerRef.current) return; if (!containerRef.current) return;
const debouncedResize = debounce((width: unknown) => {
setContainerWidth(Number(width));
}, 150); // 150ms debounce
const observer = new ResizeObserver(entries => { const observer = new ResizeObserver(entries => {
const width = entries[0]?.contentRect.width; const width = entries[0]?.contentRect.width;
if (width) { if (width) {
setContainerWidth(width); debouncedResize(width);
} }
}); });
observer.observe(containerRef.current); observer.observe(containerRef.current);
return () => observer.disconnect(); return () => {
observer.disconnect();
};
}, []); }, []);
return ( return (
@ -184,7 +201,7 @@ export function PDFViewer({ zoomLevel }: PDFViewerProps) {
renderAnnotationLayer={true} renderAnnotationLayer={true}
renderTextLayer={i + 1 === currDocPage} renderTextLayer={i + 1 === currDocPage}
className="shadow-lg" className="shadow-lg"
scale={calculateScale()} scale={currentScale()}
onLoadSuccess={(page) => { onLoadSuccess={(page) => {
setPageWidth(page.originalWidth); setPageWidth(page.originalWidth);
setPageHeight(page.originalHeight); setPageHeight(page.originalHeight);
@ -202,7 +219,7 @@ export function PDFViewer({ zoomLevel }: PDFViewerProps) {
renderAnnotationLayer={true} renderAnnotationLayer={true}
renderTextLayer={leftPage === currDocPage} renderTextLayer={leftPage === currDocPage}
className="shadow-lg" className="shadow-lg"
scale={calculateScale()} scale={currentScale()}
onLoadSuccess={(page) => { onLoadSuccess={(page) => {
setPageWidth(page.originalWidth); setPageWidth(page.originalWidth);
setPageHeight(page.originalHeight); setPageHeight(page.originalHeight);
@ -216,7 +233,7 @@ export function PDFViewer({ zoomLevel }: PDFViewerProps) {
renderAnnotationLayer={true} renderAnnotationLayer={true}
renderTextLayer={rightPage === currDocPage} renderTextLayer={rightPage === currDocPage}
className="shadow-lg" className="shadow-lg"
scale={calculateScale()} scale={currentScale()}
onLoadSuccess={(page) => { onLoadSuccess={(page) => {
setPageWidth(page.originalWidth); setPageWidth(page.originalWidth);
setPageHeight(page.originalHeight); setPageHeight(page.originalHeight);

View file

@ -259,3 +259,15 @@ export function handleTextClick(
} }
} }
} }
// Add debounce utility at the top of the file
export function debounce<T extends (...args: unknown[]) => unknown>(
func: T,
wait: number
): (...args: Parameters<T>) => void {
let timeout: NodeJS.Timeout;
return (...args: Parameters<T>) => {
clearTimeout(timeout);
timeout = setTimeout(() => func(...args), wait);
};
}