'use client'; import { useEffect, useRef, useState } from 'react'; import { usePdf } from '@/app/contexts/PdfContext'; interface PdfViewerProps { fileId: string; fileName?: string; } export default function PdfViewer({ fileId, fileName = 'document.pdf' }: PdfViewerProps) { const canvasRef = useRef(null); const [currentPage, setCurrentPage] = useState(1); const [totalPages, setTotalPages] = useState(0); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [fullscreen, setFullscreen] = useState(false); const containerRef = useRef(null); const pdfDocumentRef = useRef(null); const { setPdfData } = usePdf(); useEffect(() => { let isMounted = true; let objectUrl: string | null = null; const loadAndDisplayPdf = async () => { try { setLoading(true); // 1. Получаем данные документа как ArrayBuffer (а не blob URL) const { requestFileAsBuffer } = await import('@/app/actions/trackingActions'); const pdfData = await requestFileAsBuffer(fileId); if (!pdfData) { throw new Error('Failed to load document'); } setPdfData(pdfData, fileName); if (!isMounted) return; const pdfjs = await import('pdfjs-dist'); pdfjs.GlobalWorkerOptions.workerSrc = new URL( 'pdfjs-dist/build/pdf.worker.mjs', import.meta.url ).toString(); const loadingTask = pdfjs.getDocument({ data: pdfData, useSystemFonts: true, disableFontFace: false, }); const pdfDocument = await loadingTask.promise; if (!isMounted) return; pdfDocumentRef.current = pdfDocument; setTotalPages(pdfDocument.numPages); setCurrentPage(1); await renderPage(pdfDocument, 1); } catch (err) { console.error('Error loading PDF:', err); if (isMounted) { setError('Не удалось загрузить документ'); } } finally { if (isMounted) { setLoading(false); } } }; loadAndDisplayPdf(); return () => { isMounted = false; if (pdfDocumentRef.current) { pdfDocumentRef.current.destroy(); } if (objectUrl) { URL.revokeObjectURL(objectUrl); } }; }, [fileId, setPdfData]); const renderPage = async (pdfDocument: any, pageNum: number) => { if (!canvasRef.current) return; try { const page = await pdfDocument.getPage(pageNum); const container = canvasRef.current.parentElement; if (!container) return; const containerWidth = container.clientWidth || 800; // Если ширина контейнера 0, откладываем рендер if (containerWidth === 0) { console.log('Container width is 0, waiting...'); setTimeout(() => renderPage(pdfDocument, pageNum), 100); return; } const originalViewport = page.getViewport({ scale: 1 }); const scale = containerWidth / originalViewport.width; const viewport = page.getViewport({ scale: Math.min(scale, 1.5) }); const canvas = canvasRef.current; const context = canvas.getContext('2d'); canvas.height = viewport.height; canvas.width = viewport.width; const renderContext = { canvasContext: context!, viewport: viewport, }; await page.render(renderContext).promise; } catch (err) { console.log('Error rendering page:', err); } }; useEffect(() => { if (!pdfDocumentRef.current || loading) return; const checkContainer = () => { const container = canvasRef.current?.parentElement; if (container && container.clientWidth > 0) { renderPage(pdfDocumentRef.current, currentPage); } else { setTimeout(checkContainer, 100); } }; checkContainer(); }, [pdfDocumentRef.current, loading]); const goToPrevPage = async () => { if (pdfDocumentRef.current && currentPage > 1) { const newPage = currentPage - 1; setCurrentPage(newPage); await renderPage(pdfDocumentRef.current, newPage); } }; const goToNextPage = async () => { if (pdfDocumentRef.current && currentPage < totalPages) { const newPage = currentPage + 1; setCurrentPage(newPage); await renderPage(pdfDocumentRef.current, newPage); } }; const toggleFullscreen = () => { if (!containerRef.current) return; if (!document.fullscreenElement) { containerRef.current.requestFullscreen(); setFullscreen(true); } else { document.exitFullscreen(); setFullscreen(false); } }; useEffect(() => { const handleFullscreenChange = () => { setFullscreen(!!document.fullscreenElement); if (pdfDocumentRef.current && !document.fullscreenElement) { setTimeout(() => renderPage(pdfDocumentRef.current, currentPage), 100); } }; document.addEventListener('fullscreenchange', handleFullscreenChange); return () => document.removeEventListener('fullscreenchange', handleFullscreenChange); }, [currentPage]); useEffect(() => { const handleResize = () => { if (pdfDocumentRef.current && !loading) { renderPage(pdfDocumentRef.current, currentPage); } }; window.addEventListener('resize', handleResize); return () => window.removeEventListener('resize', handleResize); }, [currentPage, loading]); if (loading) { return (
Загрузка документа...
); } if (error) { return (
{error}
); } return (
{totalPages > 0 && (
{currentPage} / {totalPages}
)}
); }