Standalone raw file redirects (#428)

This commit is contained in:
Spencer Woo
2022-02-14 19:33:19 +08:00
committed by GitHub
parent 0fda1c93db
commit 9493ce9f3d
30 changed files with 365 additions and 185 deletions
+5 -3
View File
@@ -10,6 +10,7 @@ import DownloadButtonGroup from '../DownloadBtnGtoup'
import { DownloadBtnContainer, PreviewContainer } from './Containers'
import { LoadingIcon } from '../Loading'
import { formatModifiedDateTime } from '../../utils/fileDetails'
import { getStoredToken } from '../../utils/protectedRouteHandler'
enum PlayerState {
Loading,
@@ -21,12 +22,13 @@ enum PlayerState {
const AudioPreview: FC<{ file: OdFileObject }> = ({ file }) => {
const { t } = useTranslation()
const { asPath } = useRouter()
const hashedToken = getStoredToken(asPath)
const rapRef = useRef<ReactAudioPlayer>(null)
const [playerStatus, setPlayerStatus] = useState(PlayerState.Loading)
// Render audio thumbnail, and also check for broken thumbnails
const thumbnail = `/api/thumbnail?path=${asPath}&size=medium`
const thumbnail = `/api/thumbnail/?path=${asPath}&size=medium${hashedToken ? `&odpt=${hashedToken}` : ''}`
const [brokenThumbnail, setBrokenThumbnail] = useState(false)
useEffect(() => {
@@ -92,7 +94,7 @@ const AudioPreview: FC<{ file: OdFileObject }> = ({ file }) => {
<ReactAudioPlayer
className="h-11 w-full"
src={file['@microsoft.graph.downloadUrl']}
src={`/api/raw/?path=${asPath}${hashedToken ? `&odpt=${hashedToken}` : ''}`}
ref={rapRef}
controls
preload="auto"
@@ -102,7 +104,7 @@ const AudioPreview: FC<{ file: OdFileObject }> = ({ file }) => {
</PreviewContainer>
<DownloadBtnContainer>
<DownloadButtonGroup downloadUrl={file['@microsoft.graph.downloadUrl']} />
<DownloadButtonGroup />
</DownloadBtnContainer>
</>
)
+5 -3
View File
@@ -1,11 +1,12 @@
import { FC } from 'react'
import { useTranslation } from 'next-i18next'
import useSystemTheme from 'react-use-system-theme'
import { useRouter } from 'next/router'
import { LightAsync as SyntaxHighlighter } from 'react-syntax-highlighter'
import { tomorrowNightEighties, tomorrow } from 'react-syntax-highlighter/dist/cjs/styles/hljs'
import useAxiosGet from '../../utils/fetchOnMount'
import useFileContent from '../../utils/fetchOnMount'
import { getLanguageByFileName } from '../../utils/getPreviewType'
import FourOhFour from '../FourOhFour'
import Loading from '../Loading'
@@ -13,7 +14,8 @@ import DownloadButtonGroup from '../DownloadBtnGtoup'
import { DownloadBtnContainer, PreviewContainer } from './Containers'
const CodePreview: FC<{ file: any }> = ({ file }) => {
const { response: content, error, validating } = useAxiosGet(file['@microsoft.graph.downloadUrl'])
const { asPath } = useRouter()
const { response: content, error, validating } = useFileContent(`/api/raw/?path=${asPath}`, asPath)
const theme = useSystemTheme('dark')
const { t } = useTranslation()
@@ -44,7 +46,7 @@ const CodePreview: FC<{ file: any }> = ({ file }) => {
</SyntaxHighlighter>
</PreviewContainer>
<DownloadBtnContainer>
<DownloadButtonGroup downloadUrl={file['@microsoft.graph.downloadUrl']} />
<DownloadButtonGroup />
</DownloadBtnContainer>
</div>
)
+5 -5
View File
@@ -35,7 +35,7 @@ const DefaultPreview: FC<{ file: OdFileObject }> = ({ file }) => {
<div>
<div className="py-2 text-xs font-medium uppercase opacity-80">{t('MIME type')}</div>
<div>{file.file?.mimeType || t('Unavailable')}</div>
<div>{file.file?.mimeType ?? t('Unavailable')}</div>
</div>
<div>
@@ -47,7 +47,7 @@ const DefaultPreview: FC<{ file: OdFileObject }> = ({ file }) => {
Quick XOR
</td>
<td className="whitespace-nowrap py-1 px-3 font-mono text-gray-500 dark:text-gray-400">
{file.file.hashes?.quickXorHash || t('Unavailable')}
{file.file.hashes?.quickXorHash ?? t('Unavailable')}
</td>
</tr>
<tr className="border-y bg-white dark:border-gray-700 dark:bg-gray-900">
@@ -55,7 +55,7 @@ const DefaultPreview: FC<{ file: OdFileObject }> = ({ file }) => {
SHA1
</td>
<td className="whitespace-nowrap py-1 px-3 font-mono text-gray-500 dark:text-gray-400">
{file.file.hashes?.sha1Hash || t('Unavailable')}
{file.file.hashes?.sha1Hash ?? t('Unavailable')}
</td>
</tr>
<tr className="border-y bg-white dark:border-gray-700 dark:bg-gray-900">
@@ -63,7 +63,7 @@ const DefaultPreview: FC<{ file: OdFileObject }> = ({ file }) => {
SHA256
</td>
<td className="whitespace-nowrap py-1 px-3 font-mono text-gray-500 dark:text-gray-400">
{file.file.hashes?.sha256Hash || t('Unavailable')}
{file.file.hashes?.sha256Hash ?? t('Unavailable')}
</td>
</tr>
</tbody>
@@ -73,7 +73,7 @@ const DefaultPreview: FC<{ file: OdFileObject }> = ({ file }) => {
</div>
</PreviewContainer>
<DownloadBtnContainer>
<DownloadButtonGroup downloadUrl={file['@microsoft.graph.downloadUrl']} />
<DownloadButtonGroup />
</DownloadBtnContainer>
</div>
)
+7 -2
View File
@@ -2,13 +2,18 @@ import type { OdFileObject } from '../../types'
import { FC, useEffect, useRef, useState } from 'react'
import { ReactReader } from 'react-reader'
import { useRouter } from 'next/router'
import { useTranslation } from 'next-i18next'
import Loading from '../Loading'
import DownloadButtonGroup from '../DownloadBtnGtoup'
import { DownloadBtnContainer } from './Containers'
import { getStoredToken } from '../../utils/protectedRouteHandler'
const EPUBPreview: FC<{ file: OdFileObject }> = ({ file }) => {
const { asPath } = useRouter()
const hashedToken = getStoredToken(asPath)
const [epubContainerWidth, setEpubContainerWidth] = useState(400)
const epubContainer = useRef<HTMLDivElement>(null)
@@ -51,7 +56,7 @@ const EPUBPreview: FC<{ file: OdFileObject }> = ({ file }) => {
}}
>
<ReactReader
url={file['@microsoft.graph.downloadUrl']}
url={`/api/raw/?path=${asPath}${hashedToken ? '&token=' + hashedToken : ''}`}
getRendition={rendition => fixEpub(rendition)}
loadingView={<Loading loadingText={t('Loading EPUB ...')} />}
location={location}
@@ -63,7 +68,7 @@ const EPUBPreview: FC<{ file: OdFileObject }> = ({ file }) => {
</div>
</div>
<DownloadBtnContainer>
<DownloadButtonGroup downloadUrl={file['@microsoft.graph.downloadUrl']} />
<DownloadButtonGroup />
</DownloadBtnContainer>
</div>
)
+7 -2
View File
@@ -1,25 +1,30 @@
import type { OdFileObject } from '../../types'
import { FC } from 'react'
import { useRouter } from 'next/router'
import { PreviewContainer, DownloadBtnContainer } from './Containers'
import DownloadButtonGroup from '../DownloadBtnGtoup'
import { getStoredToken } from '../../utils/protectedRouteHandler'
const ImagePreview: FC<{ file: OdFileObject }> = ({ file }) => {
const { asPath } = useRouter()
const hashedToken = getStoredToken(asPath)
return (
<>
<PreviewContainer>
{/* eslint-disable-next-line @next/next/no-img-element */}
<img
className="mx-auto"
src={file['@microsoft.graph.downloadUrl']}
src={`/api/raw/?path=${asPath}${hashedToken ? `&odpt=${hashedToken}` : ''}`}
alt={file.name}
width={file.image?.width}
height={file.image?.height}
/>
</PreviewContainer>
<DownloadBtnContainer>
<DownloadButtonGroup downloadUrl={file['@microsoft.graph.downloadUrl']} />
<DownloadButtonGroup />
</DownloadBtnContainer>
</>
)
+7 -7
View File
@@ -12,7 +12,7 @@ import 'katex/dist/katex.min.css'
import FourOhFour from '../FourOhFour'
import Loading from '../Loading'
import DownloadButtonGroup from '../DownloadBtnGtoup'
import useAxiosGet from '../../utils/fetchOnMount'
import useFileContent from '../../utils/fetchOnMount'
import { DownloadBtnContainer, PreviewContainer } from './Containers'
const MarkdownPreview: FC<{
@@ -20,12 +20,12 @@ const MarkdownPreview: FC<{
path: string
standalone?: boolean
}> = ({ file, path, standalone = true }) => {
const { response: content, error, validating } = useAxiosGet(file['@microsoft.graph.downloadUrl'])
const { t } = useTranslation()
// The parent folder of the markdown file, which is also the relative image folder
const parentPath = standalone ? path.substring(0, path.lastIndexOf('/')) : path
const { response: content, error, validating } = useFileContent(`/api/raw/?path=${parentPath}/${file.name}`, path)
const { t } = useTranslation()
// Check if the image is relative path instead of a absolute url
const isUrlAbsolute = (url: string | string[]) => url.indexOf('://') > 0 || url.indexOf('//') === 0
// Custom renderer to render images with relative path
@@ -55,7 +55,7 @@ const MarkdownPreview: FC<{
// eslint-disable-next-line @next/next/no-img-element
<img
alt={alt}
src={`/api?path=${parentPath}/${src}&raw=true`}
src={`/api/?path=${parentPath}/${src}&raw=true`}
title={title}
width={width}
height={height}
@@ -100,7 +100,7 @@ const MarkdownPreview: FC<{
</PreviewContainer>
{standalone && (
<DownloadBtnContainer>
<DownloadButtonGroup downloadUrl={file['@microsoft.graph.downloadUrl']} />
<DownloadButtonGroup />
</DownloadBtnContainer>
)}
</div>
+8 -2
View File
@@ -1,12 +1,18 @@
import type { OdFileObject } from '../../types'
import { FC, useEffect, useRef, useState } from 'react'
import { useRouter } from 'next/router'
import Preview from 'preview-office-docs'
import DownloadButtonGroup from '../DownloadBtnGtoup'
import { DownloadBtnContainer } from './Containers'
import { getBaseUrl } from '../../utils/getBaseUrl'
import { getStoredToken } from '../../utils/protectedRouteHandler'
const OfficePreview: FC<{ file: OdFileObject }> = ({ file }) => {
const { asPath } = useRouter()
const hashedToken = getStoredToken(asPath)
const docContainer = useRef<HTMLDivElement>(null)
const [docContainerWidth, setDocContainerWidth] = useState(600)
@@ -18,13 +24,13 @@ const OfficePreview: FC<{ file: OdFileObject }> = ({ file }) => {
<div>
<div className="overflow-scroll" ref={docContainer} style={{ maxHeight: '90vh' }}>
<Preview
url={encodeURIComponent(file['@microsoft.graph.downloadUrl'])}
url={`${getBaseUrl()}/api/raw/?path=${asPath}${hashedToken ? `&odpt=${hashedToken}` : ''}`}
width={docContainerWidth.toString()}
height="600"
/>
</div>
<DownloadBtnContainer>
<DownloadButtonGroup downloadUrl={file['@microsoft.graph.downloadUrl']} />
<DownloadButtonGroup />
</DownloadBtnContainer>
</div>
)
+12 -5
View File
@@ -1,11 +1,18 @@
import { useRouter } from 'next/router'
import { getBaseUrl } from '../../utils/getBaseUrl'
import { getStoredToken } from '../../utils/protectedRouteHandler'
import DownloadButtonGroup from '../DownloadBtnGtoup'
import { DownloadBtnContainer } from './Containers'
const PDFEmbedPreview: React.FC<{ 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']
)}`
const { asPath } = useRouter()
const hashedToken = getStoredToken(asPath)
// const url = `/api/proxy?url=${encodeURIComponent(...)}&inline=true`
const pdfPath = encodeURIComponent(
`${getBaseUrl()}/api/raw/?path=${asPath}${hashedToken ? `&odpt=${hashedToken}` : ''}`
)
const url = `https://mozilla.github.io/pdf.js/web/viewer.html?file=${pdfPath}`
return (
<div>
@@ -13,7 +20,7 @@ const PDFEmbedPreview: React.FC<{ file: any }> = ({ file }) => {
<iframe src={url} frameBorder="0" width="100%" height="100%"></iframe>
</div>
<DownloadBtnContainer>
<DownloadButtonGroup downloadUrl={file['@microsoft.graph.downloadUrl']} />
<DownloadButtonGroup />
</DownloadBtnContainer>
</div>
)
+5 -3
View File
@@ -1,15 +1,17 @@
import { useRouter } from 'next/router'
import { useTranslation } from 'next-i18next'
import FourOhFour from '../FourOhFour'
import Loading from '../Loading'
import DownloadButtonGroup from '../DownloadBtnGtoup'
import useAxiosGet from '../../utils/fetchOnMount'
import useFileContent from '../../utils/fetchOnMount'
import { DownloadBtnContainer, PreviewContainer } from './Containers'
const TextPreview = ({ file }) => {
const { asPath } = useRouter()
const { t } = useTranslation()
const { response: content, error, validating } = useAxiosGet(file['@microsoft.graph.downloadUrl'])
const { response: content, error, validating } = useFileContent(`/api/raw/?path=${asPath}`, asPath)
if (error) {
return (
<PreviewContainer>
@@ -40,7 +42,7 @@ const TextPreview = ({ file }) => {
<pre className="overflow-x-scroll p-0 text-sm md:p-3">{content}</pre>
</PreviewContainer>
<DownloadBtnContainer>
<DownloadButtonGroup downloadUrl={file['@microsoft.graph.downloadUrl']} />
<DownloadButtonGroup />
</DownloadBtnContainer>
</div>
)
+6 -4
View File
@@ -1,9 +1,10 @@
import { useRouter } from 'next/router'
import { useTranslation } from 'next-i18next'
import FourOhFour from '../FourOhFour'
import Loading from '../Loading'
import { DownloadButton } from '../DownloadBtnGtoup'
import useAxiosGet from '../../utils/fetchOnMount'
import useFileContent from '../../utils/fetchOnMount'
import { DownloadBtnContainer, PreviewContainer } from './Containers'
const parseDotUrl = (content: string): string | undefined => {
@@ -14,9 +15,10 @@ const parseDotUrl = (content: string): string | undefined => {
}
const TextPreview = ({ file }) => {
const { asPath } = useRouter()
const { t } = useTranslation()
const { response: content, error, validating } = useAxiosGet(file['@microsoft.graph.downloadUrl'])
const { response: content, error, validating } = useFileContent(`/api/raw/?path=${asPath}`, asPath)
if (error) {
return (
<PreviewContainer>
@@ -49,11 +51,11 @@ const TextPreview = ({ file }) => {
<DownloadBtnContainer>
<div className="flex justify-center">
<DownloadButton
onClickCallback={() => window.open(parseDotUrl(content) || '')}
onClickCallback={() => window.open(parseDotUrl(content) ?? '')}
btnColor="blue"
btnText={t('Open URL')}
btnIcon="external-link-alt"
btnTitle={t('Open URL{{url}}', { url: ' ' + parseDotUrl(content) || '' })}
btnTitle={t('Open URL{{url}}', { url: ' ' + parseDotUrl(content) ?? '' })}
/>
</div>
</DownloadBtnContainer>
+18 -10
View File
@@ -10,6 +10,7 @@ import { useAsync } from 'react-async-hook'
import { getBaseUrl } from '../../utils/getBaseUrl'
import { getExtension } from '../../utils/getFileIcon'
import { getReadablePath } from '../../utils/getReadablePath'
import { getStoredToken } from '../../utils/protectedRouteHandler'
import { DownloadButton } from '../DownloadBtnGtoup'
import { DownloadBtnContainer, PreviewContainer } from './Containers'
import FourOhFour from '../FourOhFour'
@@ -18,16 +19,21 @@ import CustomEmbedLinkMenu from '../CustomEmbedLinkMenu'
const VideoPreview: React.FC<{ file: OdFileObject }> = ({ file }) => {
const { asPath } = useRouter()
const hashedToken = getStoredToken(asPath)
const clipboard = useClipboard()
const [menuOpen, setMenuOpen] = useState(false)
const { t } = useTranslation()
// OneDrive generates thumbnails for its video files, we pick the thumbnail with the highest resolution
const thumbnail = `/api/thumbnail?path=${asPath}&size=large`
const thumbnail = `/api/thumbnail/?path=${asPath}&size=large${hashedToken ? `&odpt=${hashedToken}` : ''}`
// We assume subtitle files are beside the video with the same name, only webvtt '.vtt' files are supported
const subtitle = `/api?path=${asPath.substring(0, asPath.lastIndexOf('.'))}.vtt&raw=true`
const vtt = `${asPath.substring(0, asPath.lastIndexOf('.'))}.vtt`
const subtitle = `/api/raw/?path=${vtt}${hashedToken ? `&odpt=${hashedToken}` : ''}`
// We also format the raw video file for the in-browser player as well as all other players
const videoUrl = `/api/raw/?path=${asPath}${hashedToken ? `&odpt=${hashedToken}` : ''}`
const isFlv = getExtension(file.name) === 'flv'
const {
@@ -42,7 +48,7 @@ const VideoPreview: React.FC<{ file: OdFileObject }> = ({ file }) => {
return (
<>
<CustomEmbedLinkMenu path={getReadablePath(asPath)} menuOpen={menuOpen} setMenuOpen={setMenuOpen} />
<CustomEmbedLinkMenu path={asPath} menuOpen={menuOpen} setMenuOpen={setMenuOpen} />
<PreviewContainer>
{error ? (
<FourOhFour errorMsg={error.message} />
@@ -55,7 +61,7 @@ const VideoPreview: React.FC<{ file: OdFileObject }> = ({ file }) => {
volume: 1.0,
lang: 'en',
video: {
url: file['@microsoft.graph.downloadUrl'],
url: videoUrl,
pic: thumbnail,
type: isFlv ? 'customFlv' : 'auto',
customType: {
@@ -78,14 +84,14 @@ const VideoPreview: React.FC<{ file: OdFileObject }> = ({ file }) => {
<DownloadBtnContainer>
<div className="flex flex-wrap justify-center gap-2">
<DownloadButton
onClickCallback={() => window.open(file['@microsoft.graph.downloadUrl'])}
onClickCallback={() => window.open(videoUrl)}
btnColor="blue"
btnText={t('Download')}
btnIcon="file-download"
/>
{/* <DownloadButton
onClickCallback={() =>
window.open(`/api/proxy?url=${encodeURIComponent(file['@microsoft.graph.downloadUrl'])}`)
window.open(`/api/proxy?url=${encodeURIComponent(...)}`)
}
btnColor="teal"
btnText={t('Proxy download')}
@@ -93,7 +99,9 @@ const VideoPreview: React.FC<{ file: OdFileObject }> = ({ file }) => {
/> */}
<DownloadButton
onClickCallback={() => {
clipboard.copy(`${getBaseUrl()}/api?path=${getReadablePath(asPath)}&raw=true`)
clipboard.copy(
`${getBaseUrl()}/api/raw/?path=${getReadablePath(asPath)}${hashedToken ? `&odpt=${hashedToken}` : ''}`
)
toast.success(t('Copied direct link to clipboard.'))
}}
btnColor="pink"
@@ -108,17 +116,17 @@ const VideoPreview: React.FC<{ file: OdFileObject }> = ({ file }) => {
/>
<DownloadButton
onClickCallback={() => window.open(`iina://weblink?url=${file['@microsoft.graph.downloadUrl']}`)}
onClickCallback={() => window.open(`iina://weblink?url=${getBaseUrl()}${videoUrl}`)}
btnText="IINA"
btnImage="/players/iina.png"
/>
<DownloadButton
onClickCallback={() => window.open(`vlc://${file['@microsoft.graph.downloadUrl']}`)}
onClickCallback={() => window.open(`vlc://${getBaseUrl()}${videoUrl}`)}
btnText="VLC"
btnImage="/players/vlc.png"
/>
<DownloadButton
onClickCallback={() => window.open(`potplayer://${file['@microsoft.graph.downloadUrl']}`)}
onClickCallback={() => window.open(`potplayer://${getBaseUrl()}/${videoUrl}`)}
btnText="PotPlayer"
btnImage="/players/potplayer.png"
/>