Add PDF file preview (#15503)

GitOrigin-RevId: d5d84da65d328222556bfa9f5b585f7e47ba14ad
This commit is contained in:
Alf Eaton 2023-11-03 11:11:33 +00:00 committed by Copybot
parent ee4e1f5429
commit d3e4f59885
3 changed files with 92 additions and 3 deletions

View file

@ -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 <div className="file-view-pdf" ref={handleContainer} />
}
export default FileViewPdf

View file

@ -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 && (
<FileViewText file={file} onLoad={handleLoad} onError={handleError} />
)}
{isPdfFile && (
<FileViewPdf
fileId={file.id}
onLoad={handleLoad}
onError={handleError}
/>
)}
</>
)

View file

@ -4,7 +4,8 @@
background-color: @gray-lightest;
text-align: center;
overflow: auto;
img {
img,
.file-view-pdf {
max-width: 100%;
max-height: 90%;
display: block;
@ -14,6 +15,16 @@
.box-shadow(0 2px 3px @gray;);
background-color: white;
}
.file-view-pdf {
overflow: auto;
width: max-content;
display: flex;
flex-direction: column;
align-items: center;
.pdf-page:not(:last-of-type) {
border-bottom: 1px solid @gray;
}
}
p.no-preview {
margin-top: @line-height-computed / 2;
font-size: 24px;