Merge pull request #202 from spencerwooo/native-pdf-viewer

Native PDF preview, proxied download, better buttons, download button sticky
This commit is contained in:
Spencer Woo
2021-12-29 07:55:47 +00:00
committed by GitHub
20 changed files with 220 additions and 439 deletions
+2 -2
View File
@@ -21,7 +21,7 @@ const Auth: FunctionComponent<{ redirect: string }> = ({ redirect }) => {
</div> </div>
<div className="dark:text-gray-100 text-lg font-bold text-gray-900">Enter Password</div> <div className="dark:text-gray-100 text-lg font-bold text-gray-900">Enter Password</div>
<p className="text-sm text-gray-500"> <p className="text-sm text-gray-500 font-medium">
This route (the folder itself and the files inside) is password protected. If you know the password, please This route (the folder itself and the files inside) is password protected. If you know the password, please
enter it below. enter it below.
</p> </p>
@@ -44,7 +44,7 @@ const Auth: FunctionComponent<{ redirect: string }> = ({ redirect }) => {
}} }}
/> />
<button <button
className="focus:outline-none focus:ring focus:ring-blue-300 hover:bg-blue-400 px-4 py-2 text-white bg-blue-500 rounded" className="focus:outline-none focus:ring focus:ring-blue-400 hover:bg-blue-500 px-4 py-2 text-white bg-blue-600 rounded"
onClick={() => { onClick={() => {
setPersistedToken(token) setPersistedToken(token)
router.reload() router.reload()
-39
View File
@@ -1,39 +0,0 @@
import { FunctionComponent } from 'react'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import toast, { Toaster } from 'react-hot-toast'
import { useRouter } from 'next/router'
import { useClipboard } from 'use-clipboard-copy'
import { getBaseUrl } from "../utils/getBaseUrl"
const DownloadBtn: FunctionComponent<{ downloadUrl: string }> = ({ downloadUrl }) => {
const { asPath } = useRouter()
const clipboard = useClipboard()
return (
<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"
href={downloadUrl}
target="_blank"
rel="noopener noreferrer"
>
<FontAwesomeIcon icon="file-download" />
<span>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"
onClick={() => {
clipboard.copy(`${getBaseUrl()}/api?path=${asPath}&raw=true`)
toast.success('Copied direct link to clipboard.')
}}
>
<FontAwesomeIcon icon="copy" />
<span>Copy direct link</span>
</button>
</div>
)
}
export default DownloadBtn
+92
View File
@@ -0,0 +1,92 @@
import { MouseEventHandler } from 'react'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { IconProp } from '@fortawesome/fontawesome-svg-core'
import toast, { Toaster } from 'react-hot-toast'
import { useClipboard } from 'use-clipboard-copy'
import Image from 'next/image'
import { useRouter } from 'next/router'
import { getBaseUrl } from '../utils/getBaseUrl'
const btnStyleMap = (btnColor?: string) => {
const colorMap = {
gray: 'hover:text-gray-600 dark:hover:text-white focus:ring-gray-200 focus:text-gray-600 dark:focus:text-white border-gray-300 dark:border-gray-500 dark:focus:ring-gray-500',
blue: 'hover:text-blue-600 focus:ring-blue-200 focus:text-blue-600 border-blue-300 dark:border-blue-700 dark:focus:ring-blue-500',
teal: 'hover:text-teal-600 focus:ring-teal-200 focus:text-teal-600 border-teal-300 dark:border-teal-700 dark:focus:ring-teal-500',
red: 'hover:text-red-600 focus:ring-red-200 focus:text-red-600 border-red-300 dark:border-red-700 dark:focus:ring-red-500',
green:
'hover:text-green-600 focus:ring-green-200 focus:text-green-600 border-green-300 dark:border-green-700 dark:focus:ring-green-500',
pink: 'hover:text-pink-600 focus:ring-pink-200 focus:text-pink-600 border-pink-300 dark:border-pink-700 dark:focus:ring-pink-500',
yellow:
'hover:text-yellow-400 focus:ring-yellow-100 focus:text-yellow-400 border-yellow-300 dark:border-yellow-400 dark:focus:ring-yellow-300',
}
if (btnColor) {
return colorMap[btnColor]
}
return colorMap.gray
}
export const DownloadButton = ({
onClickCallback,
btnColor,
btnText,
btnIcon,
btnImage,
}: {
onClickCallback: MouseEventHandler<HTMLButtonElement>
btnColor?: string
btnText: string
btnIcon?: IconProp
btnImage?: string
}) => {
return (
<button
className={`flex items-center space-x-2 py-2 px-4 text-sm font-medium text-gray-900 bg-white rounded-lg border hover:bg-gray-100/10 focus:z-10 focus:ring-2 dark:bg-gray-800 dark:text-gray-200 dark:hover:bg-gray-900 ${btnStyleMap(
btnColor
)}`}
onClick={onClickCallback}
>
{btnIcon && <FontAwesomeIcon icon={btnIcon} />}
{btnImage && <Image src={btnImage} alt={btnImage} width={20} height={20} />}
<span>{btnText}</span>
</button>
)
}
const DownloadButtonGroup: React.FC<{ downloadUrl: string }> = ({ downloadUrl }) => {
const { asPath } = useRouter()
const clipboard = useClipboard()
return (
<div className="flex flex-wrap justify-center gap-2">
<Toaster />
<DownloadButton
onClickCallback={() => window.open(downloadUrl)}
btnColor="blue"
btnText="Download"
btnIcon="file-download"
/>
<DownloadButton
onClickCallback={() => window.open(`/api/proxy?url=${encodeURIComponent(downloadUrl)}`)}
btnColor="teal"
btnText="Proxy download"
btnIcon="download"
/>
<DownloadButton
onClickCallback={() => {
clipboard.copy(`${getBaseUrl()}/api?path=${asPath}&raw=true`)
toast.success('Copied direct link to clipboard.')
}}
btnColor="yellow"
btnText="Copy direct link"
btnIcon="copy"
/>
</div>
)
}
export default DownloadButtonGroup
+3 -3
View File
@@ -30,11 +30,11 @@ import CodePreview from './previews/CodePreview'
import OfficePreview from './previews/OfficePreview' import OfficePreview from './previews/OfficePreview'
import AudioPreview from './previews/AudioPreview' import AudioPreview from './previews/AudioPreview'
import VideoPreview from './previews/VideoPreview' import VideoPreview from './previews/VideoPreview'
import DownloadBtn from './DownloadBtn' import DownloadButtonGroup from './DownloadBtnGtoup'
import PDFPreview from './previews/PDFPreview'
// Disabling SSR for some previews (image gallery view, and PDF view) // Disabling SSR for some previews (image gallery view, and PDF view)
const ReactViewer = dynamic(() => import('react-viewer'), { ssr: false }) const ReactViewer = dynamic(() => import('react-viewer'), { ssr: false })
const PDFPreview = dynamic(() => import('./previews/PDFPreview'), { ssr: false })
const EPUBPreview = dynamic(() => import('./previews/EPUBPreview'), { ssr: false }) const EPUBPreview = dynamic(() => import('./previews/EPUBPreview'), { ssr: false })
/** /**
@@ -592,7 +592,7 @@ const FileListing: FunctionComponent<{ query?: ParsedUrlQuery }> = ({ query }) =
/> />
</div> </div>
<div className="mt-4"> <div className="mt-4">
<DownloadBtn downloadUrl={downloadUrl} /> <DownloadButtonGroup downloadUrl={downloadUrl} />
</div> </div>
</> </>
) )
+6 -6
View File
@@ -3,20 +3,20 @@ import { FunctionComponent } from 'react'
const FourOhFour: FunctionComponent<{ errorMsg: string }> = ({ errorMsg }) => { const FourOhFour: FunctionComponent<{ errorMsg: string }> = ({ errorMsg }) => {
return ( return (
<div className="my-20"> <div className="my-12">
<div className="md:w-1/3 w-1/2 mx-auto"> <div className="md:w-1/4 w-1/3 mx-auto">
<Image src={'/images/empty.png'} alt="404" width={912} height={912} /> <Image src={'/images/empty.png'} alt="404" width={912} height={912} />
</div> </div>
<div className="mt-6 text-gray-500 max-w-xl mx-auto"> <div className="mt-6 text-gray-500 max-w-xl mx-auto">
<div className="text-2xl font-bold mb-8"> <div className="text-xl font-bold mb-8">
Oops, that&apos;s a <span className="underline decoration-wavy decoration-red-500">four-oh-four</span>. Oops, that&apos;s a <span className="underline decoration-wavy decoration-red-500">four-oh-four</span>.
</div> </div>
<div className="font-mono border border-gray-400/20 rounded p-2 mb-4 text-sm bg-gray-50 dark:bg-gray-800"> <div className="font-mono border border-gray-400/20 rounded p-2 mb-4 text-xs bg-gray-50 dark:bg-gray-800">
{errorMsg} {errorMsg}
</div> </div>
<div> <div className="text-sm">
Press{' '} Press{' '}
<kbd className="border-opacity-20 font-mono text-sm p-1 bg-gray-100 dark:bg-gray-800 border rounded">F12</kbd>{' '} <kbd className="border-opacity-20 font-mono text-xs p-1 bg-gray-100 dark:bg-gray-800 border rounded">F12</kbd>{' '}
and open devtools for more details, or seek help at{' '} and open devtools for more details, or seek help at{' '}
<a <a
className="text-blue-600 hover:text-blue-700 hover:underline" className="text-blue-600 hover:text-blue-700 hover:underline"
+9 -7
View File
@@ -47,7 +47,7 @@ const Navbar = () => {
<div className="flex items-center justify-between w-full max-w-5xl mx-auto pr-4 py-1"> <div className="flex items-center justify-between w-full max-w-5xl mx-auto pr-4 py-1">
<Link href="/"> <Link href="/">
<a className="dark:text-white hover:opacity-80 flex items-center p-2 space-x-2"> <a className="dark:text-white hover:opacity-80 flex items-center p-2 space-x-2">
<Image src={siteConfig.icon} alt="icon" width="28" height="28" /> <Image src={siteConfig.icon} alt="icon" width="28" height="28" priority />
<span className="sm:block hidden text-lg font-bold">{siteConfig.title}</span> <span className="sm:block hidden text-lg font-bold">{siteConfig.title}</span>
</a> </a>
</Link> </Link>
@@ -62,21 +62,23 @@ const Navbar = () => {
className="flex items-center space-x-2 dark:text-white hover:opacity-80" className="flex items-center space-x-2 dark:text-white hover:opacity-80"
> >
<FontAwesomeIcon icon={['fab', l.name.toLowerCase() as IconName]} /> <FontAwesomeIcon icon={['fab', l.name.toLowerCase() as IconName]} />
<span className="text-sm hidden md:inline-block">{l.name}</span> <span className="text-sm font-medium hidden md:inline-block">{l.name}</span>
</a> </a>
))} ))}
<a href={siteConfig.email} className="flex items-center space-x-2 dark:text-white hover:opacity-80"> {siteConfig.email && (
<FontAwesomeIcon icon={['far', 'envelope']} /> <a href={siteConfig.email} className="flex items-center space-x-2 dark:text-white hover:opacity-80">
<span className="text-sm hidden md:inline-block">Email</span> <FontAwesomeIcon icon={['far', 'envelope']} />
</a> <span className="text-sm font-medium hidden md:inline-block">Email</span>
</a>
)}
{tokenPresent && ( {tokenPresent && (
<button <button
className="hover:bg-gray-200 dark:text-white dark:hover:bg-gray-700 flex items-center p-2 space-x-2 rounded" className="hover:bg-gray-200 dark:text-white dark:hover:bg-gray-700 flex items-center p-2 space-x-2 rounded"
onClick={() => setIsOpen(true)} onClick={() => setIsOpen(true)}
> >
<span className="text-sm">Logout</span> <span className="text-sm font-medium">Logout</span>
<FontAwesomeIcon icon="sign-out-alt" /> <FontAwesomeIcon icon="sign-out-alt" />
</button> </button>
)} )}
+4 -3
View File
@@ -2,7 +2,7 @@ import { FunctionComponent, useState } from 'react'
import ReactPlayer from 'react-player' import ReactPlayer from 'react-player'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import DownloadBtn from '../DownloadBtn' import DownloadButtonGroup from '../DownloadBtnGtoup'
enum PlayerState { enum PlayerState {
Loading, Loading,
@@ -73,8 +73,9 @@ const AudioPreview: FunctionComponent<{ file: any }> = ({ file }) => {
</div> </div>
</div> </div>
</div> </div>
<div className="mt-4">
<DownloadBtn downloadUrl={file['@microsoft.graph.downloadUrl']} /> <div className="border-t-gray-200 dark:border-t-gray-700 border-t p-2 sticky bottom-0 left-0 right-0 z-10 bg-white bg-opacity-80 backdrop-blur-md dark:bg-gray-900">
<DownloadButtonGroup downloadUrl={file['@microsoft.graph.downloadUrl']} />
</div> </div>
</> </>
) )
+5 -5
View File
@@ -5,7 +5,7 @@ import { getExtension } from '../../utils/getFileIcon'
import { useStaleSWR } from '../../utils/fetchWithSWR' import { useStaleSWR } from '../../utils/fetchWithSWR'
import FourOhFour from '../FourOhFour' import FourOhFour from '../FourOhFour'
import Loading from '../Loading' import Loading from '../Loading'
import DownloadBtn from '../DownloadBtn' import DownloadButtonGroup from '../DownloadBtnGtoup'
const CodePreview: FunctionComponent<{ file: any }> = ({ file }) => { const CodePreview: FunctionComponent<{ file: any }> = ({ file }) => {
const { data, error } = useStaleSWR({ url: file['@microsoft.graph.downloadUrl'] }) const { data, error } = useStaleSWR({ url: file['@microsoft.graph.downloadUrl'] })
@@ -32,16 +32,16 @@ const CodePreview: FunctionComponent<{ file: any }> = ({ file }) => {
} }
return ( return (
<> <div>
<div className="markdown-body p-3 bg-gray-900 rounded"> <div className="markdown-body p-3 bg-gray-900 rounded">
<pre className={`language-${getExtension(file.name)}`}> <pre className={`language-${getExtension(file.name)}`}>
<code>{data}</code> <code>{data}</code>
</pre> </pre>
</div> </div>
<div className="mt-4"> <div className="border-t-gray-200 dark:border-t-gray-700 border-t p-2 sticky bottom-0 left-0 right-0 z-10 bg-white bg-opacity-80 backdrop-blur-md dark:bg-gray-900">
<DownloadBtn downloadUrl={file['@microsoft.graph.downloadUrl']} /> <DownloadButtonGroup downloadUrl={file['@microsoft.graph.downloadUrl']} />
</div> </div>
</> </div>
) )
} }
+5 -5
View File
@@ -3,7 +3,7 @@ import { ReactReader } from 'react-reader'
import type { Rendition } from 'epubjs' import type { Rendition } from 'epubjs'
import Loading from '../Loading' import Loading from '../Loading'
import DownloadBtn from '../DownloadBtn' import DownloadButtonGroup from '../DownloadBtnGtoup'
const EPUBPreview: FunctionComponent<{file: any}> = ({ file }) => { const EPUBPreview: FunctionComponent<{file: any}> = ({ file }) => {
const [epubContainerWidth, setEpubContainerWidth] = useState(400) const [epubContainerWidth, setEpubContainerWidth] = useState(400)
@@ -32,7 +32,7 @@ const EPUBPreview: FunctionComponent<{file: any}> = ({ file }) => {
} }
return ( return (
<> <div>
<div <div
className="dark:bg-gray-900 md:p-3 no-scrollbar flex flex-col w-full overflow-scroll bg-white rounded" className="dark:bg-gray-900 md:p-3 no-scrollbar flex flex-col w-full overflow-scroll bg-white rounded"
style={{ maxHeight: '90vh' }} style={{ maxHeight: '90vh' }}
@@ -51,10 +51,10 @@ const EPUBPreview: FunctionComponent<{file: any}> = ({ file }) => {
</div> </div>
</div> </div>
</div> </div>
<div className="mt-4"> <div className="border-t-gray-200 dark:border-t-gray-700 border-t p-2 sticky bottom-0 left-0 right-0 z-10 bg-white bg-opacity-80 backdrop-blur-md dark:bg-gray-900">
<DownloadBtn downloadUrl={file['@microsoft.graph.downloadUrl']} /> <DownloadButtonGroup downloadUrl={file['@microsoft.graph.downloadUrl']} />
</div> </div>
</> </div>
) )
} }
+5 -5
View File
@@ -10,7 +10,7 @@ import 'katex/dist/katex.min.css'
import FourOhFour from '../FourOhFour' import FourOhFour from '../FourOhFour'
import Loading from '../Loading' import Loading from '../Loading'
import DownloadBtn from '../DownloadBtn' import DownloadButtonGroup from '../DownloadBtnGtoup'
import { useStaleSWR } from '../../utils/fetchWithSWR' import { useStaleSWR } from '../../utils/fetchWithSWR'
const MarkdownPreview: FunctionComponent<{ file: any; path: string; standalone?: boolean }> = ({ const MarkdownPreview: FunctionComponent<{ file: any; path: string; standalone?: boolean }> = ({
@@ -81,7 +81,7 @@ const MarkdownPreview: FunctionComponent<{ file: any; path: string; standalone?:
} }
return ( return (
<> <div>
<div <div
className={ className={
standalone standalone
@@ -99,11 +99,11 @@ const MarkdownPreview: FunctionComponent<{ file: any; path: string; standalone?:
</ReactMarkdown> </ReactMarkdown>
</div> </div>
{standalone && ( {standalone && (
<div className="mt-4"> <div className="border-t-gray-200 dark:border-t-gray-700 border-t p-2 sticky bottom-0 left-0 right-0 z-10 bg-white bg-opacity-80 backdrop-blur-md dark:bg-gray-900">
<DownloadBtn downloadUrl={file['@microsoft.graph.downloadUrl']} /> <DownloadButtonGroup downloadUrl={file['@microsoft.graph.downloadUrl']} />
</div> </div>
)} )}
</> </div>
) )
} }
+10 -6
View File
@@ -1,7 +1,7 @@
import { FunctionComponent, useEffect, useRef, useState } from 'react' import { FunctionComponent, useEffect, useRef, useState } from 'react'
import Preview from 'preview-office-docs' import Preview from 'preview-office-docs'
import DownloadBtn from '../DownloadBtn' import DownloadButtonGroup from '../DownloadBtnGtoup'
const OfficePreview: FunctionComponent<{ file: any }> = ({ file }) => { const OfficePreview: FunctionComponent<{ file: any }> = ({ file }) => {
const docContainer = useRef<HTMLDivElement>(null) const docContainer = useRef<HTMLDivElement>(null)
@@ -12,14 +12,18 @@ const OfficePreview: FunctionComponent<{ file: any }> = ({ file }) => {
}, []) }, [])
return ( return (
<> <div>
<div className="overflow-scroll" ref={docContainer} style={{ maxHeight: '90vh' }}> <div className="overflow-scroll" ref={docContainer} style={{ maxHeight: '90vh' }}>
<Preview url={encodeURIComponent(file['@microsoft.graph.downloadUrl'])} width={docContainerWidth.toString()} height="800" /> <Preview
url={encodeURIComponent(file['@microsoft.graph.downloadUrl'])}
width={docContainerWidth.toString()}
height="600"
/>
</div> </div>
<div className="mt-4"> <div className="border-t-gray-200 dark:border-t-gray-700 border-t p-2 sticky bottom-0 left-0 right-0 z-10 bg-white bg-opacity-80 backdrop-blur-md dark:bg-gray-900">
<DownloadBtn downloadUrl={file['@microsoft.graph.downloadUrl']} /> <DownloadButtonGroup downloadUrl={file['@microsoft.graph.downloadUrl']} />
</div> </div>
</> </div>
) )
} }
+14 -89
View File
@@ -1,98 +1,23 @@
import { FunctionComponent, useEffect, useRef, useState } from 'react' import { FunctionComponent } from 'react'
import { Document, Page, pdfjs } from 'react-pdf'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import Loading from '../Loading' import DownloadButtonGroup from '../DownloadBtnGtoup'
import DownloadBtn from '../DownloadBtn'
pdfjs.GlobalWorkerOptions.workerSrc = `//cdnjs.cloudflare.com/ajax/libs/pdf.js/${pdfjs.version}/pdf.worker.min.js` const PDFEmbedPreview: FunctionComponent<{ file: any }> = ({ file }) => {
// const url = `/api/proxy?url=${encodeURIComponent(file['@microsoft.graph.downloadUrl'])}&inline=true`
const PDFPreview: FunctionComponent<{ file: any }> = ({ file }) => { const url = `https://mozilla.github.io/pdf.js/web/viewer.html?file=${encodeURIComponent(
const [pageNumber, setPageNumber] = useState(1) file['@microsoft.graph.downloadUrl']
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 ( return (
<> <div>
<div <div className="w-full rounded overflow-hidden" style={{ height: '90vh' }}>
className="dark:bg-gray-900 md:p-3 no-scrollbar flex flex-col w-full overflow-scroll bg-white rounded" <iframe src={url} frameBorder="0" width="100%" height="100%"></iframe>
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>
<div className="mt-4"> <div className="border-t-gray-200 dark:border-t-gray-700 border-t p-2 sticky bottom-0 left-0 right-0 z-10 bg-white bg-opacity-80 backdrop-blur-md dark:bg-gray-900">
<DownloadBtn downloadUrl={file['@microsoft.graph.downloadUrl']} /> <DownloadButtonGroup downloadUrl={file['@microsoft.graph.downloadUrl']} />
</div> </div>
</> </div>
) )
} }
export default PDFPreview export default PDFEmbedPreview
+5 -5
View File
@@ -2,7 +2,7 @@ import { FunctionComponent } from 'react'
import FourOhFour from '../FourOhFour' import FourOhFour from '../FourOhFour'
import Loading from '../Loading' import Loading from '../Loading'
import DownloadBtn from '../DownloadBtn' import DownloadButtonGroup from '../DownloadBtnGtoup'
import { useStaleSWR } from '../../utils/fetchWithSWR' import { useStaleSWR } from '../../utils/fetchWithSWR'
const TextPreview: FunctionComponent<{ file: any }> = ({ file }) => { const TextPreview: FunctionComponent<{ file: any }> = ({ file }) => {
@@ -23,14 +23,14 @@ const TextPreview: FunctionComponent<{ file: any }> = ({ file }) => {
} }
return ( return (
<> <div>
<div className="dark:bg-gray-900 dark:text-gray-100 p-3 bg-white rounded"> <div className="dark:bg-gray-900 dark:text-gray-100 p-3 bg-white rounded">
<pre className="md:p-3 p-0 overflow-scroll">{data}</pre> <pre className="md:p-3 p-0 overflow-scroll">{data}</pre>
</div> </div>
<div className="mt-4"> <div className="border-t-gray-200 dark:border-t-gray-700 border-t p-2 sticky bottom-0 left-0 right-0 z-10 bg-white bg-opacity-80 backdrop-blur-md dark:bg-gray-900">
<DownloadBtn downloadUrl={file['@microsoft.graph.downloadUrl']} /> <DownloadButtonGroup downloadUrl={file['@microsoft.graph.downloadUrl']} />
</div> </div>
</> </div>
) )
} }
+37 -46
View File
@@ -1,12 +1,11 @@
import { FunctionComponent } from 'react' import { FunctionComponent } from 'react'
import ReactPlayer from 'react-player' import ReactPlayer from 'react-player'
import Image from 'next/image'
import { useRouter } from 'next/router' import { useRouter } from 'next/router'
import { useClipboard } from 'use-clipboard-copy' import { useClipboard } from 'use-clipboard-copy'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import toast, { Toaster } from 'react-hot-toast' import toast, { Toaster } from 'react-hot-toast'
import { getBaseUrl } from '../../utils/getBaseUrl' import { getBaseUrl } from '../../utils/getBaseUrl'
import { DownloadButton } from '../DownloadBtnGtoup'
const VideoPreview: FunctionComponent<{ file: any }> = ({ file }) => { const VideoPreview: FunctionComponent<{ file: any }> = ({ file }) => {
const { asPath } = useRouter() const { asPath } = useRouter()
@@ -25,56 +24,48 @@ const VideoPreview: FunctionComponent<{ file: any }> = ({ file }) => {
/> />
</div> </div>
<div className="flex flex-wrap justify-center mt-4 space-x-2"> <div className="flex flex-wrap justify-center mt-4 gap-2">
<Toaster /> <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"
href={file['@microsoft.graph.downloadUrl']}
target="_blank"
rel="noopener noreferrer"
>
<FontAwesomeIcon icon="file-download" />
<span>Download</span>
</a>
<button <DownloadButton
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" onClickCallback={() => window.open(file['@microsoft.graph.downloadUrl'])}
onClick={() => { btnColor="blue"
btnText="Download"
btnIcon="file-download"
/>
<DownloadButton
onClickCallback={() =>
window.open(`/api/proxy?url=${encodeURIComponent(file['@microsoft.graph.downloadUrl'])}`)
}
btnColor="teal"
btnText="Proxy download"
btnIcon="download"
/>
<DownloadButton
onClickCallback={() => {
clipboard.copy(`${getBaseUrl()}/api?path=${asPath}&raw=true`) clipboard.copy(`${getBaseUrl()}/api?path=${asPath}&raw=true`)
toast.success('Copied direct link to clipboard.') toast.success('Copied direct link to clipboard.')
}} }}
> btnColor="yellow"
<FontAwesomeIcon icon="copy" /> btnText="Copy direct link"
<span>Copy direct link</span> btnIcon="copy"
</button> />
<a <DownloadButton
className="focus:outline-none focus:ring focus:ring-gray-300 hover:bg-gray-600 flex items-center justify-center px-4 py-2 mb-2 space-x-2 text-white bg-gray-700 rounded" onClickCallback={() => window.open(`iina://weblink?url=${file['@microsoft.graph.downloadUrl']}`)}
href={`iina://weblink?url=${file['@microsoft.graph.downloadUrl']}`} btnText="IINA"
target="_blank" btnImage="/players/iina.png"
rel="noopener noreferrer" />
> <DownloadButton
<Image src="/players/iina.png" alt="iina" width="28" height="28" /> onClickCallback={() => window.open(`vlc://${file['@microsoft.graph.downloadUrl']}`)}
<span>IINA</span> btnText="VLC"
</a> btnImage="/players/vlc.png"
<a />
className="focus:outline-none focus:ring focus:ring-yellow-300 hover:bg-yellow-500 flex items-center justify-center px-4 py-2 mb-2 space-x-2 text-white bg-yellow-600 rounded" <DownloadButton
href={`vlc://${file['@microsoft.graph.downloadUrl']}`} onClickCallback={() => window.open(`potplayer://${file['@microsoft.graph.downloadUrl']}`)}
target="_blank" btnText="PotPlayer"
rel="noopener noreferrer" btnImage="/players/potplayer.png"
> />
<Image src="/players/vlc.png" alt="vlc" width="28" height="28" />
<span>VLC</span>
</a>
<a
className="focus:outline-none focus:ring focus:ring-yellow-100 hover:bg-yellow-300 flex items-center justify-center px-4 py-2 mb-2 space-x-2 text-white bg-yellow-400 rounded"
href={`potplayer://${file['@microsoft.graph.downloadUrl']}`}
target="_blank"
rel="noopener noreferrer"
>
<Image src="/players/potplayer.png" alt="potplayer" width="28" height="28" />
<span>PotPlayer</span>
</a>
</div> </div>
</> </>
) )
+1 -1
View File
@@ -5,7 +5,7 @@
"googleFontSans": "Inter", "googleFontSans": "Inter",
"googleFontMono": "Fira Mono", "googleFontMono": "Fira Mono",
"googleFontLinks": [ "googleFontLinks": [
"https://fonts.googleapis.com/css2?family=Fira+Mono&family=Inter:wght@400;700&display=swap" "https://fonts.googleapis.com/css2?family=Fira+Mono&family=Inter:wght@400;500;700&display=swap"
], ],
"footer": "Powered by <a href=\"https://github.com/spencerwooo/onedrive-vercel-index\" target=\"_blank\" rel=\"noopener noreferrer\">onedrive-vercel-index</a>. Made with ❤ by SpencerWoo.", "footer": "Powered by <a href=\"https://github.com/spencerwooo/onedrive-vercel-index\" target=\"_blank\" rel=\"noopener noreferrer\">onedrive-vercel-index</a>. Made with ❤ by SpencerWoo.",
"protectedRoutes": [ "protectedRoutes": [
+18 -212
View File
@@ -27,7 +27,6 @@
"react-dom": "17.0.2", "react-dom": "17.0.2",
"react-hot-toast": "^2.0.0", "react-hot-toast": "^2.0.0",
"react-markdown": "^6.0.2", "react-markdown": "^6.0.2",
"react-pdf": "^5.3.0",
"react-player": "^2.9.0", "react-player": "^2.9.0",
"react-reader": "^0.20.4", "react-reader": "^0.20.4",
"react-viewer": "^3.2.2", "react-viewer": "^3.2.2",
@@ -1122,11 +1121,6 @@
"@types/unist": "*" "@types/unist": "*"
} }
}, },
"node_modules/@types/json-schema": {
"version": "7.0.9",
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz",
"integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ=="
},
"node_modules/@types/json5": { "node_modules/@types/json5": {
"version": "0.0.29", "version": "0.0.29",
"resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz",
@@ -1399,6 +1393,7 @@
"version": "6.12.6", "version": "6.12.6",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
"dev": true,
"dependencies": { "dependencies": {
"fast-deep-equal": "^3.1.1", "fast-deep-equal": "^3.1.1",
"fast-json-stable-stringify": "^2.0.0", "fast-json-stable-stringify": "^2.0.0",
@@ -1410,14 +1405,6 @@
"url": "https://github.com/sponsors/epoberezkin" "url": "https://github.com/sponsors/epoberezkin"
} }
}, },
"node_modules/ajv-keywords": {
"version": "3.5.2",
"resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz",
"integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==",
"peerDependencies": {
"ajv": "^6.9.1"
}
},
"node_modules/anser": { "node_modules/anser": {
"version": "1.4.9", "version": "1.4.9",
"resolved": "https://registry.npmjs.org/anser/-/anser-1.4.9.tgz", "resolved": "https://registry.npmjs.org/anser/-/anser-1.4.9.tgz",
@@ -2472,14 +2459,6 @@
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
"integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="
}, },
"node_modules/emojis-list": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz",
"integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==",
"engines": {
"node": ">= 4"
}
},
"node_modules/encoding": { "node_modules/encoding": {
"version": "0.1.13", "version": "0.1.13",
"resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz",
@@ -3080,7 +3059,8 @@
"node_modules/fast-deep-equal": { "node_modules/fast-deep-equal": {
"version": "3.1.3", "version": "3.1.3",
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
"dev": true
}, },
"node_modules/fast-glob": { "node_modules/fast-glob": {
"version": "3.2.7", "version": "3.2.7",
@@ -3101,7 +3081,8 @@
"node_modules/fast-json-stable-stringify": { "node_modules/fast-json-stable-stringify": {
"version": "2.1.0", "version": "2.1.0",
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
"integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
"dev": true
}, },
"node_modules/fast-levenshtein": { "node_modules/fast-levenshtein": {
"version": "2.0.6", "version": "2.0.6",
@@ -3130,25 +3111,6 @@
"node": "^10.12.0 || >=12.0.0" "node": "^10.12.0 || >=12.0.0"
} }
}, },
"node_modules/file-loader": {
"version": "6.2.0",
"resolved": "https://registry.npmjs.org/file-loader/-/file-loader-6.2.0.tgz",
"integrity": "sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw==",
"dependencies": {
"loader-utils": "^2.0.0",
"schema-utils": "^3.0.0"
},
"engines": {
"node": ">= 10.13.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/webpack"
},
"peerDependencies": {
"webpack": "^4.0.0 || ^5.0.0"
}
},
"node_modules/fill-range": { "node_modules/fill-range": {
"version": "7.0.1", "version": "7.0.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
@@ -4488,7 +4450,8 @@
"node_modules/json-schema-traverse": { "node_modules/json-schema-traverse": {
"version": "0.4.1", "version": "0.4.1",
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
"dev": true
}, },
"node_modules/json-stable-stringify-without-jsonify": { "node_modules/json-stable-stringify-without-jsonify": {
"version": "1.0.1", "version": "1.0.1",
@@ -4500,6 +4463,7 @@
"version": "2.2.0", "version": "2.2.0",
"resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz",
"integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==",
"peer": true,
"dependencies": { "dependencies": {
"minimist": "^1.2.5" "minimist": "^1.2.5"
}, },
@@ -4643,19 +4607,6 @@
"resolved": "https://registry.npmjs.org/load-script/-/load-script-1.0.0.tgz", "resolved": "https://registry.npmjs.org/load-script/-/load-script-1.0.0.tgz",
"integrity": "sha1-BJGTngvuVkPuSUp+PaPSuscMbKQ=" "integrity": "sha1-BJGTngvuVkPuSUp+PaPSuscMbKQ="
}, },
"node_modules/loader-utils": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz",
"integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==",
"dependencies": {
"big.js": "^5.2.2",
"emojis-list": "^3.0.0",
"json5": "^2.1.2"
},
"engines": {
"node": ">=8.9.0"
}
},
"node_modules/localforage": { "node_modules/localforage": {
"version": "1.10.0", "version": "1.10.0",
"resolved": "https://registry.npmjs.org/localforage/-/localforage-1.10.0.tgz", "resolved": "https://registry.npmjs.org/localforage/-/localforage-1.10.0.tgz",
@@ -4745,11 +4696,6 @@
"node": ">=10" "node": ">=10"
} }
}, },
"node_modules/make-cancellable-promise": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/make-cancellable-promise/-/make-cancellable-promise-1.0.0.tgz",
"integrity": "sha512-+YO6Grg2uy/z8Mv3uV90OP6yAUHIF43YGgEFbejmBrK9VWFsVO6DvzFMcopXr9wCNg3/QIltIKiSCROC7zFB2g=="
},
"node_modules/make-dir": { "node_modules/make-dir": {
"version": "3.1.0", "version": "3.1.0",
"resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
@@ -4772,11 +4718,6 @@
"semver": "bin/semver.js" "semver": "bin/semver.js"
} }
}, },
"node_modules/make-event-props": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/make-event-props/-/make-event-props-1.2.0.tgz",
"integrity": "sha512-BmWFkm/jZzVH9A0tEBdkjAARUz/eha+5IRyfOndeSMKRadkgR5DawoBHoRwLxkYmjJOI5bHkXKpaZocxj+dKgg=="
},
"node_modules/markdown-table": { "node_modules/markdown-table": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-2.0.0.tgz", "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-2.0.0.tgz",
@@ -5009,19 +4950,6 @@
"resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz", "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz",
"integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==" "integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q=="
}, },
"node_modules/merge-class-names": {
"version": "1.4.2",
"resolved": "https://registry.npmjs.org/merge-class-names/-/merge-class-names-1.4.2.tgz",
"integrity": "sha512-bOl98VzwCGi25Gcn3xKxnR5p/WrhWFQB59MS/aGENcmUc6iSm96yrFDF0XSNurX9qN4LbJm0R9kfvsQ17i8zCw==",
"funding": {
"url": "https://github.com/wojtekmaj/merge-class-names?sponsor=1"
}
},
"node_modules/merge-refs": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/merge-refs/-/merge-refs-1.0.0.tgz",
"integrity": "sha512-WZ4S5wqD9FCR9hxkLgvcHJCBxzXzy3VVE6p8W2OzxRzB+hLRlcadGE2bW9xp2KSzk10rvp4y+pwwKO6JQVguMg=="
},
"node_modules/merge-stream": { "node_modules/merge-stream": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
@@ -5870,11 +5798,6 @@
"node": ">=0.12" "node": ">=0.12"
} }
}, },
"node_modules/pdfjs-dist": {
"version": "2.6.347",
"resolved": "https://registry.npmjs.org/pdfjs-dist/-/pdfjs-dist-2.6.347.tgz",
"integrity": "sha512-QC+h7hG2su9v/nU1wEI3SnpPIrqJODL7GTDFvR74ANKGq1AFJW16PH8VWnhpiTi9YcLSFV9xLeWSgq+ckHLdVQ=="
},
"node_modules/picocolors": { "node_modules/picocolors": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
@@ -6307,28 +6230,6 @@
"react": ">=16" "react": ">=16"
} }
}, },
"node_modules/react-pdf": {
"version": "5.3.2",
"resolved": "https://registry.npmjs.org/react-pdf/-/react-pdf-5.3.2.tgz",
"integrity": "sha512-gT2xeUAUJem5UWNZYIQSPJAlPDbc3mIIhEgGK8P/qo1B68WIE4R4v3tNFYM9e5nqlKnGZG4Cd68SetlmnPejwA==",
"dependencies": {
"@babel/runtime": "^7.0.0",
"file-loader": "^6.0.0",
"make-cancellable-promise": "^1.0.0",
"make-event-props": "^1.1.0",
"merge-class-names": "^1.1.1",
"merge-refs": "^1.0.0",
"pdfjs-dist": "2.6.347",
"prop-types": "^15.6.2"
},
"funding": {
"url": "https://github.com/wojtekmaj/react-pdf?sponsor=1"
},
"peerDependencies": {
"react": "^16.3.0 || ^17.0.0-0",
"react-dom": "^16.3.0 || ^17.0.0-0"
}
},
"node_modules/react-player": { "node_modules/react-player": {
"version": "2.9.0", "version": "2.9.0",
"resolved": "https://registry.npmjs.org/react-player/-/react-player-2.9.0.tgz", "resolved": "https://registry.npmjs.org/react-player/-/react-player-2.9.0.tgz",
@@ -6787,23 +6688,6 @@
"object-assign": "^4.1.1" "object-assign": "^4.1.1"
} }
}, },
"node_modules/schema-utils": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz",
"integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==",
"dependencies": {
"@types/json-schema": "^7.0.8",
"ajv": "^6.12.5",
"ajv-keywords": "^3.5.2"
},
"engines": {
"node": ">= 10.13.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/webpack"
}
},
"node_modules/semver": { "node_modules/semver": {
"version": "7.3.5", "version": "7.3.5",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
@@ -7728,6 +7612,7 @@
"version": "4.4.1", "version": "4.4.1",
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
"integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
"dev": true,
"dependencies": { "dependencies": {
"punycode": "^2.1.0" "punycode": "^2.1.0"
} }
@@ -8747,11 +8632,6 @@
"@types/unist": "*" "@types/unist": "*"
} }
}, },
"@types/json-schema": {
"version": "7.0.9",
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz",
"integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ=="
},
"@types/json5": { "@types/json5": {
"version": "0.0.29", "version": "0.0.29",
"resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz",
@@ -8961,6 +8841,7 @@
"version": "6.12.6", "version": "6.12.6",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
"dev": true,
"requires": { "requires": {
"fast-deep-equal": "^3.1.1", "fast-deep-equal": "^3.1.1",
"fast-json-stable-stringify": "^2.0.0", "fast-json-stable-stringify": "^2.0.0",
@@ -8968,12 +8849,6 @@
"uri-js": "^4.2.2" "uri-js": "^4.2.2"
} }
}, },
"ajv-keywords": {
"version": "3.5.2",
"resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz",
"integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==",
"requires": {}
},
"anser": { "anser": {
"version": "1.4.9", "version": "1.4.9",
"resolved": "https://registry.npmjs.org/anser/-/anser-1.4.9.tgz", "resolved": "https://registry.npmjs.org/anser/-/anser-1.4.9.tgz",
@@ -9791,11 +9666,6 @@
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
"integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="
}, },
"emojis-list": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz",
"integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q=="
},
"encoding": { "encoding": {
"version": "0.1.13", "version": "0.1.13",
"resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz",
@@ -10285,7 +10155,8 @@
"fast-deep-equal": { "fast-deep-equal": {
"version": "3.1.3", "version": "3.1.3",
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
"dev": true
}, },
"fast-glob": { "fast-glob": {
"version": "3.2.7", "version": "3.2.7",
@@ -10303,7 +10174,8 @@
"fast-json-stable-stringify": { "fast-json-stable-stringify": {
"version": "2.1.0", "version": "2.1.0",
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
"integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
"dev": true
}, },
"fast-levenshtein": { "fast-levenshtein": {
"version": "2.0.6", "version": "2.0.6",
@@ -10329,15 +10201,6 @@
"flat-cache": "^3.0.4" "flat-cache": "^3.0.4"
} }
}, },
"file-loader": {
"version": "6.2.0",
"resolved": "https://registry.npmjs.org/file-loader/-/file-loader-6.2.0.tgz",
"integrity": "sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw==",
"requires": {
"loader-utils": "^2.0.0",
"schema-utils": "^3.0.0"
}
},
"fill-range": { "fill-range": {
"version": "7.0.1", "version": "7.0.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
@@ -11259,7 +11122,8 @@
"json-schema-traverse": { "json-schema-traverse": {
"version": "0.4.1", "version": "0.4.1",
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
"dev": true
}, },
"json-stable-stringify-without-jsonify": { "json-stable-stringify-without-jsonify": {
"version": "1.0.1", "version": "1.0.1",
@@ -11271,6 +11135,7 @@
"version": "2.2.0", "version": "2.2.0",
"resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz",
"integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==",
"peer": true,
"requires": { "requires": {
"minimist": "^1.2.5" "minimist": "^1.2.5"
} }
@@ -11395,16 +11260,6 @@
"resolved": "https://registry.npmjs.org/load-script/-/load-script-1.0.0.tgz", "resolved": "https://registry.npmjs.org/load-script/-/load-script-1.0.0.tgz",
"integrity": "sha1-BJGTngvuVkPuSUp+PaPSuscMbKQ=" "integrity": "sha1-BJGTngvuVkPuSUp+PaPSuscMbKQ="
}, },
"loader-utils": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz",
"integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==",
"requires": {
"big.js": "^5.2.2",
"emojis-list": "^3.0.0",
"json5": "^2.1.2"
}
},
"localforage": { "localforage": {
"version": "1.10.0", "version": "1.10.0",
"resolved": "https://registry.npmjs.org/localforage/-/localforage-1.10.0.tgz", "resolved": "https://registry.npmjs.org/localforage/-/localforage-1.10.0.tgz",
@@ -11483,11 +11338,6 @@
"yallist": "^4.0.0" "yallist": "^4.0.0"
} }
}, },
"make-cancellable-promise": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/make-cancellable-promise/-/make-cancellable-promise-1.0.0.tgz",
"integrity": "sha512-+YO6Grg2uy/z8Mv3uV90OP6yAUHIF43YGgEFbejmBrK9VWFsVO6DvzFMcopXr9wCNg3/QIltIKiSCROC7zFB2g=="
},
"make-dir": { "make-dir": {
"version": "3.1.0", "version": "3.1.0",
"resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
@@ -11503,11 +11353,6 @@
} }
} }
}, },
"make-event-props": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/make-event-props/-/make-event-props-1.2.0.tgz",
"integrity": "sha512-BmWFkm/jZzVH9A0tEBdkjAARUz/eha+5IRyfOndeSMKRadkgR5DawoBHoRwLxkYmjJOI5bHkXKpaZocxj+dKgg=="
},
"markdown-table": { "markdown-table": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-2.0.0.tgz", "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-2.0.0.tgz",
@@ -11682,16 +11527,6 @@
"resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz", "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz",
"integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==" "integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q=="
}, },
"merge-class-names": {
"version": "1.4.2",
"resolved": "https://registry.npmjs.org/merge-class-names/-/merge-class-names-1.4.2.tgz",
"integrity": "sha512-bOl98VzwCGi25Gcn3xKxnR5p/WrhWFQB59MS/aGENcmUc6iSm96yrFDF0XSNurX9qN4LbJm0R9kfvsQ17i8zCw=="
},
"merge-refs": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/merge-refs/-/merge-refs-1.0.0.tgz",
"integrity": "sha512-WZ4S5wqD9FCR9hxkLgvcHJCBxzXzy3VVE6p8W2OzxRzB+hLRlcadGE2bW9xp2KSzk10rvp4y+pwwKO6JQVguMg=="
},
"merge-stream": { "merge-stream": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
@@ -12323,11 +12158,6 @@
"sha.js": "^2.4.8" "sha.js": "^2.4.8"
} }
}, },
"pdfjs-dist": {
"version": "2.6.347",
"resolved": "https://registry.npmjs.org/pdfjs-dist/-/pdfjs-dist-2.6.347.tgz",
"integrity": "sha512-QC+h7hG2su9v/nU1wEI3SnpPIrqJODL7GTDFvR74ANKGq1AFJW16PH8VWnhpiTi9YcLSFV9xLeWSgq+ckHLdVQ=="
},
"picocolors": { "picocolors": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
@@ -12635,21 +12465,6 @@
"vfile": "^4.0.0" "vfile": "^4.0.0"
} }
}, },
"react-pdf": {
"version": "5.3.2",
"resolved": "https://registry.npmjs.org/react-pdf/-/react-pdf-5.3.2.tgz",
"integrity": "sha512-gT2xeUAUJem5UWNZYIQSPJAlPDbc3mIIhEgGK8P/qo1B68WIE4R4v3tNFYM9e5nqlKnGZG4Cd68SetlmnPejwA==",
"requires": {
"@babel/runtime": "^7.0.0",
"file-loader": "^6.0.0",
"make-cancellable-promise": "^1.0.0",
"make-event-props": "^1.1.0",
"merge-class-names": "^1.1.1",
"merge-refs": "^1.0.0",
"pdfjs-dist": "2.6.347",
"prop-types": "^15.6.2"
}
},
"react-player": { "react-player": {
"version": "2.9.0", "version": "2.9.0",
"resolved": "https://registry.npmjs.org/react-player/-/react-player-2.9.0.tgz", "resolved": "https://registry.npmjs.org/react-player/-/react-player-2.9.0.tgz",
@@ -12966,16 +12781,6 @@
"object-assign": "^4.1.1" "object-assign": "^4.1.1"
} }
}, },
"schema-utils": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz",
"integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==",
"requires": {
"@types/json-schema": "^7.0.8",
"ajv": "^6.12.5",
"ajv-keywords": "^3.5.2"
}
},
"semver": { "semver": {
"version": "7.3.5", "version": "7.3.5",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
@@ -13688,6 +13493,7 @@
"version": "4.4.1", "version": "4.4.1",
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
"integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
"dev": true,
"requires": { "requires": {
"punycode": "^2.1.0" "punycode": "^2.1.0"
} }
-1
View File
@@ -28,7 +28,6 @@
"react-dom": "17.0.2", "react-dom": "17.0.2",
"react-hot-toast": "^2.0.0", "react-hot-toast": "^2.0.0",
"react-markdown": "^6.0.2", "react-markdown": "^6.0.2",
"react-pdf": "^5.3.0",
"react-player": "^2.9.0", "react-player": "^2.9.0",
"react-reader": "^0.20.4", "react-reader": "^0.20.4",
"react-viewer": "^3.2.2", "react-viewer": "^3.2.2",
+1 -1
View File
@@ -84,7 +84,7 @@ library.add(
function MyApp({ Component, pageProps }: AppProps) { function MyApp({ Component, pageProps }: AppProps) {
return ( return (
<> <>
<NextNProgress height={1} color="rgb(63,63,70,0.9)" options={{ showSpinner: false }} /> <NextNProgress height={1} color="rgb(156, 163, 175, 0.9)" options={{ showSpinner: false }} />
<Component {...pageProps} /> <Component {...pageProps} />
</> </>
) )
+1 -2
View File
@@ -15,8 +15,7 @@
} }
.react-pdf__Page__canvas { .react-pdf__Page__canvas {
@apply mx-auto; @apply mx-auto border border-gray-300/40 shadow;
@apply shadow-md;
} }
.markdown-body ul { .markdown-body ul {
+2 -1
View File
@@ -18,7 +18,8 @@ module.exports = {
blue: colors.sky, blue: colors.sky,
indigo: colors.indigo, indigo: colors.indigo,
purple: colors.purple, purple: colors.purple,
pink: colors.pink pink: colors.pink,
teal: colors.teal
}, },
extend: { extend: {
fontFamily: { fontFamily: {