From a166915bc4393cfaad6ab875adc45bd88137d639 Mon Sep 17 00:00:00 2001 From: openhands Date: Thu, 23 Jan 2025 20:36:05 +0000 Subject: [PATCH] test --- src/components/PDFViewer.tsx | 139 +++++++++++++++++++++++++++++------ 1 file changed, 117 insertions(+), 22 deletions(-) diff --git a/src/components/PDFViewer.tsx b/src/components/PDFViewer.tsx index 642d81e..dcbf43c 100644 --- a/src/components/PDFViewer.tsx +++ b/src/components/PDFViewer.tsx @@ -8,6 +8,8 @@ import { useState, useEffect, useRef } from 'react'; import { PDFSkeleton } from './PDFSkeleton'; import { useTTS } from '@/contexts/TTSContext'; import { usePDF } from '@/contexts/PDFContext'; +import { pdfjs } from 'react-pdf'; +import type { TextItem } from 'pdfjs-dist/types/src/display/api'; interface PDFViewerProps { pdfData: Blob | undefined; @@ -17,7 +19,7 @@ interface PDFViewerProps { export function PDFViewer({ pdfData, zoomLevel }: PDFViewerProps) { const [numPages, setNumPages] = useState(); const [containerWidth, setContainerWidth] = useState(0); - const { setText, currentSentence, stopAndPlayFromIndex, isProcessing } = useTTS(); + const { setText, currentSentence, stopAndPlayFromIndex, isProcessing, isPlaying, currentIndex, sentences } = useTTS(); const [pdfText, setPdfText] = useState(''); const [pdfDataUrl, setPdfDataUrl] = useState(); const [loadingError, setLoadingError] = useState(); @@ -172,6 +174,85 @@ export function PDFViewer({ pdfData, zoomLevel }: PDFViewerProps) { setNumPages(numPages); } + const [currentPage, setCurrentPage] = useState(1); + const [pageText, setPageText] = useState(''); + + const handlePageChange = async (pageNumber: number) => { + if (pageNumber < 1 || pageNumber > (numPages || 1)) return; + setCurrentPage(pageNumber); + + // Extract text from the new page + if (pdfData) { + try { + const pdf = await pdfjs.getDocument(pdfDataUrl!).promise; + const page = await pdf.getPage(pageNumber); + const textContent = await page.getTextContent(); + const textItems = textContent.items.filter((item): item is TextItem => + 'str' in item && 'transform' in item + ); + + // Process text items to maintain reading order + const lines: TextItem[][] = []; + let currentLine: TextItem[] = []; + let currentY: number | null = null; + const tolerance = 2; + + textItems.forEach((item) => { + const y = item.transform[5]; + if (currentY === null) { + currentY = y; + currentLine.push(item); + } else if (Math.abs(y - currentY) < tolerance) { + currentLine.push(item); + } else { + lines.push(currentLine); + currentLine = [item]; + currentY = y; + } + }); + lines.push(currentLine); + + // Build page text + let fullText = ''; + for (const line of lines) { + line.sort((a, b) => a.transform[4] - b.transform[4]); + let lineText = ''; + let prevItem: TextItem | null = null; + + for (const item of line) { + if (!prevItem) { + lineText = item.str; + } else { + const prevEndX = prevItem.transform[4] + (prevItem.width ?? 0); + const currentStartX = item.transform[4]; + const space = currentStartX - prevEndX; + + if (space > ((item.width ?? 0) * 0.3)) { + lineText += ' ' + item.str; + } else { + lineText += item.str; + } + } + prevItem = item; + } + fullText += lineText + ' '; + } + + setPageText(fullText.trim()); + setText(fullText.trim()); // Update TTS with current page text + } catch (error) { + console.error('Error extracting page text:', error); + } + } + }; + + // Auto-advance to next page when TTS reaches the end + useEffect(() => { + if (!isPlaying && currentIndex >= sentences.length - 1) { + handlePageChange(currentPage + 1); + } + }, [isPlaying, currentIndex, sentences.length, currentPage]); + return (
} noData={} file={pdfDataUrl} - onLoadSuccess={onDocumentLoadSuccess} + onLoadSuccess={(pdf) => { + onDocumentLoadSuccess(pdf); + handlePageChange(1); // Load first page text + }} className="flex flex-col items-center m-0" > - {Array.from( - new Array(numPages), - (el, index) => ( -
-
-

- {index + 1} / {numPages} -

-
-
- -
+
+
+ +
+

+ {currentPage} / {numPages} +

- ), - )} + +
+
+ +
+
);