diff --git a/services/web/frontend/js/features/file-view/components/file-view-pdf.tsx b/services/web/frontend/js/features/file-view/components/file-view-pdf.tsx new file mode 100644 index 0000000000..2a613d2762 --- /dev/null +++ b/services/web/frontend/js/features/file-view/components/file-view-pdf.tsx @@ -0,0 +1,70 @@ +import { FC, useCallback } from 'react' +import useIsMounted from '@/shared/hooks/use-is-mounted' +import { useFileTreePathContext } from '@/features/file-tree/contexts/file-tree-path' +import { useIdeContext } from '@/shared/context/ide-context' +import { debugConsole } from '@/utils/debugging' + +const FileViewPdf: FC<{ + fileId: string + onLoad: () => void + onError: () => void +}> = ({ fileId, onLoad, onError }) => { + const mountedRef = useIsMounted() + + const { fileTreeManager } = useIdeContext() + const { previewByPath } = useFileTreePathContext() + + const handleContainer = useCallback( + async (element: HTMLDivElement | null) => { + if (element) { + const { PDFJS } = await import( + '../../pdf-preview/util/pdf-js-versions' + ).then(m => m.default as any) + + // bail out if loading PDF.js took too long + if (!mountedRef.current) { + onError() + return + } + + const entity = fileTreeManager.findEntityById(fileId) + const path = fileTreeManager.getEntityPath(entity) + const preview = previewByPath(path) + + if (!preview) { + onError() + return + } + + const pdf = await PDFJS.getDocument(preview.url).promise + + for (let i = 1; i <= pdf.numPages; i++) { + const page = await pdf.getPage(i) + const viewport = page.getViewport({ scale: 1 }) + + const canvas = document.createElement('canvas') + canvas.classList.add('pdf-page') + canvas.width = viewport.width + canvas.height = viewport.height + element.append(canvas) + page.render({ + canvasContext: canvas.getContext('2d'), + viewport, + }) + } + + onLoad() + + return () => { + pdf.cleanup().catch(debugConsole.error) + pdf.destroy() + } + } + }, + [fileTreeManager, mountedRef, previewByPath, fileId, onLoad, onError] + ) + + return
+} + +export default FileViewPdf diff --git a/services/web/frontend/js/features/file-view/components/file-view.jsx b/services/web/frontend/js/features/file-view/components/file-view.jsx index 4a17ac3128..7ae1970b1b 100644 --- a/services/web/frontend/js/features/file-view/components/file-view.jsx +++ b/services/web/frontend/js/features/file-view/components/file-view.jsx @@ -4,6 +4,7 @@ import { useTranslation } from 'react-i18next' import FileViewHeader from './file-view-header' import FileViewImage from './file-view-image' +import FileViewPdf from './file-view-pdf' import FileViewText from './file-view-text' import Icon from '../../../shared/components/icon' @@ -24,8 +25,8 @@ export default function FileView({ file }) { editableFilenames.includes(file.name.toLowerCase()) const isImageFile = imageExtensions.includes(extension) - - const isUnpreviewableFile = !isEditableTextFile && !isImageFile + const isPdfFile = extension === 'pdf' + const isUnpreviewableFile = !isEditableTextFile && !isImageFile && !isPdfFile const handleLoad = useCallback(() => { setContentLoading(false) @@ -52,6 +53,13 @@ export default function FileView({ file }) { {isEditableTextFile && (