import axios from 'axios' import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import { ParsedUrlQuery } from 'querystring' import { FunctionComponent, useState } from 'react' import { ImageDecorator } from 'react-viewer/lib/ViewerProps' import useSWR from 'swr' import { useRouter } from 'next/router' import dynamic from 'next/dynamic' import Loading from './Loading' import { getExtension, getFileIcon, hasKey } from '../utils/getFileIcon' import { extensions, preview } from '../utils/getPreviewType' import { VideoPreview } from './previews/VideoPreview' import { AudioPreview } from './previews/AudioPreview' // 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 }) /** * Convert raw bits file/folder size into a human readable string * * @param size File or folder size, in raw bits * @returns Human readable form of the file or folder size */ const humanFileSize = (size: number) => { if (size < 1024) return size + ' B' const i = Math.floor(Math.log(size) / Math.log(1024)) const num = size / Math.pow(1024, i) const round = Math.round(num) const formatted = round < 10 ? num.toFixed(2) : round < 100 ? num.toFixed(1) : round return `${formatted} ${'KMGTPEZY'[i - 1]}B` } /** * Convert url query into path string * * @param query Url query property * @returns Path string */ const queryToPath = (query?: ParsedUrlQuery) => { if (query) { const { path } = query if (!path) return '/' if (typeof path === 'string') return `/${path}` return `/${path.join('/')}` } return '/' } const fetcher = (url: string) => axios.get(url).then(res => res.data) const FileListItem: FunctionComponent<{ fileContent: { id: string; name: string; size: number; file: Object; lastModifiedDateTime: string } }> = ({ fileContent: c }) => { return (
{/*
{c.file ? c.file.mimeType : 'folder'}
*/}
{c.name}
{new Date(c.lastModifiedDateTime).toLocaleString(undefined, { dateStyle: 'short', timeStyle: 'short', })}
{humanFileSize(c.size)}
) } const FileListing: FunctionComponent<{ query?: ParsedUrlQuery }> = ({ query }) => { const [imageViewerVisible, setImageViewerVisibility] = useState(false) const [activeImageIdx, setActiveImageIdx] = useState(0) const router = useRouter() const path = queryToPath(query) const { data, error } = useSWR(`/api?path=${path}`, fetcher, { revalidateOnFocus: false, revalidateOnReconnect: false, }) if (error) return
Failed to load
if (!data) { return (
) } const resp = data.data const fileIsImage = (fileName: string) => { const fileExtension = getExtension(fileName) if (hasKey(extensions, fileExtension)) { if (extensions[fileExtension] === preview.image) { return true } } return false } if ('folder' in resp) { const { children } = resp const imagesInFolder: ImageDecorator[] = [] const imageIndexDict: { [key: string]: number } = {} let imageIndex = 0 children.forEach((c: any) => { if (fileIsImage(c.name)) { imagesInFolder.push({ src: c['@microsoft.graph.downloadUrl'], alt: c.name, downloadUrl: c['@microsoft.graph.downloadUrl'], }) imageIndexDict[c.id] = imageIndex imageIndex += 1 } }) return (
Name
Last Modified
Size
{imagesInFolder.length !== 0 && ( { setImageViewerVisibility(false) }} /> )} {children.map((c: any) => (
{ if (!c.folder && fileIsImage(c.name)) { setActiveImageIdx(imageIndexDict[c.id]) setImageViewerVisibility(true) } else { e.preventDefault() router.push(`${path === '/' ? '' : path}/${c.name}`) } }} >
))}
) } if ('file' in resp) { const downloadUrl = resp['@microsoft.graph.downloadUrl'] const fileName = resp.name const fileExtension = fileName.slice(((fileName.lastIndexOf('.') - 1) >>> 0) + 2).toLowerCase() if (hasKey(extensions, fileExtension)) { switch (extensions[fileExtension]) { case preview.image: return (
{downloadUrl}
) case preview.text: return
text
case preview.code: return
code
case preview.markdown: return
markdown
case preview.video: return case preview.audio: return case preview.pdf: return default: return
{fileName}
} } } return
404
} export default FileListing