mirror of
https://github.com/Nezumi-2711/onedrive-vercel-index.git
synced 2026-09-22 13:38:45 +00:00
native pdf viewer with mozilla pdfjs
This commit is contained in:
@@ -4,7 +4,7 @@ import toast, { Toaster } from 'react-hot-toast'
|
||||
import { useRouter } from 'next/router'
|
||||
import { useClipboard } from 'use-clipboard-copy'
|
||||
|
||||
import { getBaseUrl } from "../utils/getBaseUrl"
|
||||
import { getBaseUrl } from '../utils/getBaseUrl'
|
||||
|
||||
const DownloadBtn: FunctionComponent<{ downloadUrl: string }> = ({ downloadUrl }) => {
|
||||
const { asPath } = useRouter()
|
||||
@@ -14,7 +14,7 @@ const DownloadBtn: FunctionComponent<{ downloadUrl: string }> = ({ downloadUrl }
|
||||
<div className="flex flex-wrap justify-center space-x-2">
|
||||
<Toaster />
|
||||
<a
|
||||
className="w-36 focus:outline-none focus:ring focus:ring-blue-300 hover:bg-blue-400 flex items-center justify-center flex-shrink-0 px-4 py-2 mb-2 space-x-4 text-white bg-blue-500 rounded"
|
||||
className="w-36 focus:outline-none focus:ring focus:ring-blue-300 hover:bg-blue-500 flex items-center justify-center flex-shrink-0 px-4 py-2 mb-2 space-x-4 text-white border-2 border-blue-500 rounded transition-all duration-100"
|
||||
href={downloadUrl}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
@@ -22,8 +22,17 @@ const DownloadBtn: FunctionComponent<{ downloadUrl: string }> = ({ downloadUrl }
|
||||
<FontAwesomeIcon icon="file-download" />
|
||||
<span>Download</span>
|
||||
</a>
|
||||
<a
|
||||
className="focus:outline-none focus:ring focus:ring-pink-300 hover:bg-pink-500 flex items-center justify-center flex-shrink-0 px-4 py-2 mb-2 space-x-4 text-white border-2 border-pink-500 rounded transition-all duration-100"
|
||||
href={`/api/proxy?url=${encodeURIComponent(downloadUrl)}`}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<FontAwesomeIcon icon="file-download" />
|
||||
<span>Proxy download</span>
|
||||
</a>
|
||||
<button
|
||||
className="focus:outline-none focus:ring focus:ring-yellow-300 hover:bg-yellow-400 flex items-center justify-center flex-shrink-0 w-48 px-4 py-2 mb-2 space-x-4 text-white bg-yellow-500 rounded"
|
||||
className="focus:outline-none focus:ring focus:ring-yellow-300 hover:bg-yellow-500 flex items-center justify-center flex-shrink-0 w-48 px-4 py-2 mb-2 space-x-4 text-white border-2 border-yellow-500 rounded transition-all duration-100"
|
||||
onClick={() => {
|
||||
clipboard.copy(`${getBaseUrl()}/api?path=${asPath}&raw=true`)
|
||||
toast.success('Copied direct link to clipboard.')
|
||||
|
||||
@@ -31,10 +31,10 @@ import OfficePreview from './previews/OfficePreview'
|
||||
import AudioPreview from './previews/AudioPreview'
|
||||
import VideoPreview from './previews/VideoPreview'
|
||||
import DownloadBtn from './DownloadBtn'
|
||||
import PDFPreview from './previews/PDFEmbedPreview'
|
||||
|
||||
// Disabling SSR for some previews (image gallery view, and PDF view)
|
||||
const ReactViewer = dynamic(() => import('react-viewer'), { ssr: false })
|
||||
const PDFPreview = dynamic(() => import('./previews/PDFPreview'), { ssr: false })
|
||||
const EPUBPreview = dynamic(() => import('./previews/EPUBPreview'), { ssr: false })
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
import { FunctionComponent } from 'react'
|
||||
|
||||
import DownloadBtn from '../DownloadBtn'
|
||||
|
||||
const PDFEmbedPreview: FunctionComponent<{ file: any }> = ({ file }) => {
|
||||
// const url = `/api/proxy?url=${encodeURIComponent(file['@microsoft.graph.downloadUrl'])}&inline=true`
|
||||
const url = `https://mozilla.github.io/pdf.js/web/viewer.html?file=${encodeURIComponent(
|
||||
file['@microsoft.graph.downloadUrl']
|
||||
)}`
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="w-full rounded overflow-hidden" style={{ height: '80vh' }}>
|
||||
<iframe src={url} frameBorder="0" width="100%" height="100%"></iframe>
|
||||
</div>
|
||||
<div className="mt-4">
|
||||
<DownloadBtn downloadUrl={file['@microsoft.graph.downloadUrl']} />
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default PDFEmbedPreview
|
||||
@@ -1,98 +0,0 @@
|
||||
import { FunctionComponent, useEffect, useRef, useState } from 'react'
|
||||
import { Document, Page, pdfjs } from 'react-pdf'
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||
|
||||
import Loading from '../Loading'
|
||||
import DownloadBtn from '../DownloadBtn'
|
||||
|
||||
pdfjs.GlobalWorkerOptions.workerSrc = `//cdnjs.cloudflare.com/ajax/libs/pdf.js/${pdfjs.version}/pdf.worker.min.js`
|
||||
|
||||
const PDFPreview: FunctionComponent<{ file: any }> = ({ file }) => {
|
||||
const [pageNumber, setPageNumber] = useState(1)
|
||||
const [totalPages, setTotalPages] = useState(0)
|
||||
const [loadingText, setLoadingText] = useState('Loading PDF ...')
|
||||
|
||||
const [pdfContainerWidth, setPdfContainerWidth] = useState(400)
|
||||
const pdfContainter = useRef<HTMLDivElement>(null)
|
||||
|
||||
const onDocumentLoadSuccess = (pdf: any) => {
|
||||
setTotalPages(pdf.numPages)
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
setPdfContainerWidth(pdfContainter.current ? pdfContainter.current.offsetWidth : 400)
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<>
|
||||
<div
|
||||
className="dark:bg-gray-900 md:p-3 no-scrollbar flex flex-col w-full overflow-scroll bg-white rounded"
|
||||
style={{ maxHeight: '90vh' }}
|
||||
>
|
||||
<div className="no-scrollbar flex-1 w-full overflow-scroll" ref={pdfContainter} style={{ maxHeight: '80vh' }}>
|
||||
<Document
|
||||
className="dark:bg-gray-800 bg-gray-100"
|
||||
file={file['@microsoft.graph.downloadUrl']}
|
||||
onLoadSuccess={onDocumentLoadSuccess}
|
||||
loading={<Loading loadingText={loadingText} />}
|
||||
onLoadProgress={({ loaded, total }) => {
|
||||
setLoadingText(`Loading PDF ${Math.round((loaded / total) * 100)}%`)
|
||||
}}
|
||||
options={{
|
||||
cMapUrl: `//cdn.jsdelivr.net/npm/pdfjs-dist@${pdfjs.version}/cmaps/`,
|
||||
cMapPacked: true,
|
||||
}}
|
||||
>
|
||||
<Page
|
||||
pageNumber={pageNumber}
|
||||
width={pdfContainerWidth > 400 ? pdfContainerWidth * 0.8 : pdfContainerWidth}
|
||||
/>
|
||||
</Document>
|
||||
</div>
|
||||
|
||||
<div className="md:mb-0 dark:text-white flex flex-wrap items-center justify-center w-full my-4 space-x-2">
|
||||
<button
|
||||
className="focus:ring focus:ring-red-300 focus:outline-none hover:bg-red-600 disabled:opacity-50 px-4 py-2 text-white transition-all duration-75 bg-red-500 rounded cursor-pointer"
|
||||
onClick={() => {
|
||||
pageNumber > 1 && setPageNumber(pageNumber - 1)
|
||||
}}
|
||||
disabled={!(pageNumber > 1)}
|
||||
>
|
||||
<FontAwesomeIcon icon="arrow-left" />
|
||||
</button>
|
||||
<div className="px-4 py-2">
|
||||
Page{' '}
|
||||
<input
|
||||
value={pageNumber}
|
||||
className="bg-red-50 dark:bg-gray-600 focus:ring focus:ring-red-300 dark:focus:ring-red-700 focus:outline-none w-10 p-1 mr-1 text-center rounded"
|
||||
style={{
|
||||
maxWidth: 50,
|
||||
}}
|
||||
onChange={e => {
|
||||
const v = parseInt(e.target.value)
|
||||
if (v <= totalPages && v >= 0) {
|
||||
setPageNumber(v)
|
||||
}
|
||||
}}
|
||||
></input>
|
||||
/<span className="ml-1 text-center">{totalPages}</span>
|
||||
</div>
|
||||
<button
|
||||
className="focus:ring focus:ring-red-300 focus:outline-none hover:bg-red-600 disabled:opacity-50 px-4 py-2 text-white transition-all duration-75 bg-red-500 rounded cursor-pointer"
|
||||
onClick={() => {
|
||||
pageNumber < totalPages && setPageNumber(pageNumber + 1)
|
||||
}}
|
||||
disabled={!(pageNumber < totalPages)}
|
||||
>
|
||||
<FontAwesomeIcon icon="arrow-right" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-4">
|
||||
<DownloadBtn downloadUrl={file['@microsoft.graph.downloadUrl']} />
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default PDFPreview
|
||||
Reference in New Issue
Block a user