diff --git a/src/app/pdf/[id]/page.tsx b/src/app/pdf/[id]/page.tsx index 9deec96..f9df8ca 100644 --- a/src/app/pdf/[id]/page.tsx +++ b/src/app/pdf/[id]/page.tsx @@ -25,6 +25,7 @@ export default function PDFViewerPage() { const [document, setDocument] = useState<{ name: string; data: Blob } | null>(null); const [error, setError] = useState(null); const [isLoading, setIsLoading] = useState(true); + const [zoomLevel, setZoomLevel] = useState(100); useEffect(() => { async function loadDocument() { @@ -46,6 +47,9 @@ export default function PDFViewerPage() { loadDocument(); }, [id, getDocument]); + const handleZoomIn = () => setZoomLevel(prev => Math.min(prev + 10, 200)); + const handleZoomOut = () => setZoomLevel(prev => Math.max(prev - 10, 50)); + if (error) { return (
@@ -71,20 +75,39 @@ export default function PDFViewerPage() { <>
-
- { - setText(''); - stop(); - }} - className="inline-flex items-center px-3 py-1 bg-base text-foreground rounded-lg hover:bg-offbase transition-colors" - > - - - - Documents - +
+
+ { + setText(''); + stop(); + }} + className="inline-flex items-center px-3 py-1 bg-base text-foreground rounded-lg hover:bg-offbase transition-colors" + > + + + + Documents + +
+ + {zoomLevel}% + +
+

{isLoading ? 'Loading...' : document?.name}

@@ -95,7 +118,7 @@ export default function PDFViewerPage() {
) : ( - + )} ); diff --git a/src/components/PDFViewer.tsx b/src/components/PDFViewer.tsx index 48fb198..642d81e 100644 --- a/src/components/PDFViewer.tsx +++ b/src/components/PDFViewer.tsx @@ -11,10 +11,12 @@ import { usePDF } from '@/contexts/PDFContext'; interface PDFViewerProps { pdfData: Blob | undefined; + zoomLevel: number; } -export function PDFViewer({ pdfData }: PDFViewerProps) { +export function PDFViewer({ pdfData, zoomLevel }: PDFViewerProps) { const [numPages, setNumPages] = useState(); + const [containerWidth, setContainerWidth] = useState(0); const { setText, currentSentence, stopAndPlayFromIndex, isProcessing } = useTTS(); const [pdfText, setPdfText] = useState(''); const [pdfDataUrl, setPdfDataUrl] = useState(); @@ -143,6 +145,29 @@ export function PDFViewer({ pdfData }: PDFViewerProps) { }; }, [pdfText, currentSentence, highlightPattern, clearHighlights]); + // Add scale calculation function + const calculateScale = (pageWidth: number = 595) => { // 595 is default PDF width in points + const margin = 24; // 24px padding on each side + const targetWidth = containerWidth - margin; + const baseScale = targetWidth / pageWidth; + return baseScale * (zoomLevel / 100); + }; + + // Add resize observer effect + useEffect(() => { + if (!containerRef.current) return; + + const observer = new ResizeObserver(entries => { + const width = entries[0]?.contentRect.width; + if (width) { + setContainerWidth(width); + } + }); + + observer.observe(containerRef.current); + return () => observer.disconnect(); + }, []); + function onDocumentLoadSuccess({ numPages }: { numPages: number }): void { setNumPages(numPages); } @@ -150,7 +175,7 @@ export function PDFViewer({ pdfData }: PDFViewerProps) { return (
{loadingError ? ( @@ -161,7 +186,7 @@ export function PDFViewer({ pdfData }: PDFViewerProps) { noData={} file={pdfDataUrl} onLoadSuccess={onDocumentLoadSuccess} - className="flex flex-col items-center" + className="flex flex-col items-center m-0" > {Array.from( new Array(numPages), @@ -178,7 +203,7 @@ export function PDFViewer({ pdfData }: PDFViewerProps) { renderAnnotationLayer={true} renderTextLayer={true} className="shadow-lg" - scale={1.2} + scale={calculateScale()} />
diff --git a/src/contexts/TTSContext.tsx b/src/contexts/TTSContext.tsx index 3164645..3dee2b6 100644 --- a/src/contexts/TTSContext.tsx +++ b/src/contexts/TTSContext.tsx @@ -131,7 +131,7 @@ export function TTSProvider({ children }: { children: React.ReactNode }) { }, [audioContext]); // Text preprocessing function to clean and normalize text - const preprocessText = (text: string): string => { + const preprocessSentenceForAudio = (text: string): string => { return text // Replace URLs with descriptive text including domain .replace(/\S*(?:https?:\/\/|www\.)([^\/\s]+)(?:\/\S*)?/gi, '- (link to $1) -') @@ -147,7 +147,7 @@ export function TTSProvider({ children }: { children: React.ReactNode }) { const splitIntoSentences = (text: string): string[] => { // Preprocess the text before splitting into sentences - const cleanedText = preprocessText(text); + const cleanedText = preprocessSentenceForAudio(text); const doc = nlp(cleanedText); return doc.sentences().out('array') as string[]; }; @@ -173,7 +173,7 @@ export function TTSProvider({ children }: { children: React.ReactNode }) { try { // Only set processing if we need to fetch from API - const cleanedSentence = preprocessText(sentence); + const cleanedSentence = preprocessSentenceForAudio(sentence); if (!audioCacheRef.current.has(cleanedSentence)) { setIsProcessing(true); }