audio and video preview, mobile compatibility

This commit is contained in:
spencerwooo 2021-06-24 22:32:22 +01:00
parent 2ea2db2cee
commit b1cced5e7e
8 changed files with 64 additions and 22 deletions

View file

@ -8,7 +8,7 @@ const Breadcrumb: FunctionComponent<{ query?: ParsedUrlQuery }> = ({ query }) =>
const { path } = query const { path } = query
if (Array.isArray(path)) { if (Array.isArray(path)) {
return ( return (
<div className="py-2 text-sm text-gray-600 flex"> <div className="pb-4 text-sm text-gray-600 flex flex-wrap">
<div className="p-1 hover:text-black transition-all duration-75"> <div className="p-1 hover:text-black transition-all duration-75">
<Link href="/">🚩 Home</Link> <Link href="/">🚩 Home</Link>
</div> </div>
@ -26,7 +26,7 @@ const Breadcrumb: FunctionComponent<{ query?: ParsedUrlQuery }> = ({ query }) =>
} }
return ( return (
<div className="py-2 text-sm text-gray-600 hover:text-black transition-all duration-75"> <div className="pb-4 text-sm text-gray-600 hover:text-black transition-all duration-75">
<div className="p-1"> <div className="p-1">
<Link href="/">🚩 Home</Link> <Link href="/">🚩 Home</Link>
</div> </div>

View file

@ -2,7 +2,7 @@ import axios from 'axios'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { ParsedUrlQuery } from 'querystring' import { ParsedUrlQuery } from 'querystring'
import { FunctionComponent, useState } from 'react' import { FunctionComponent, useEffect, useState } from 'react'
import { ImageDecorator } from 'react-viewer/lib/ViewerProps' import { ImageDecorator } from 'react-viewer/lib/ViewerProps'
import useSWR from 'swr' import useSWR from 'swr'
@ -55,20 +55,20 @@ const FileListItem: FunctionComponent<{
}> = ({ fileContent: c }) => { }> = ({ fileContent: c }) => {
return ( return (
<div className="p-3 grid grid-cols-10 items-center space-x-2 cursor-pointer hover:bg-gray-100"> <div className="p-3 grid grid-cols-10 items-center space-x-2 cursor-pointer hover:bg-gray-100">
<div className="flex space-x-2 items-center col-span-7 truncate"> <div className="flex space-x-2 items-center col-span-10 md:col-span-7 truncate">
{/* <div>{c.file ? c.file.mimeType : 'folder'}</div> */} {/* <div>{c.file ? c.file.mimeType : 'folder'}</div> */}
<div className="w-5 text-center"> <div className="w-5 text-center">
<FontAwesomeIcon icon={c.file ? getFileIcon(c.name) : ['far', 'folder']} /> <FontAwesomeIcon icon={c.file ? getFileIcon(c.name) : ['far', 'folder']} />
</div> </div>
<div className="truncate">{c.name}</div> <div className="truncate">{c.name}</div>
</div> </div>
<div className="font-mono text-sm col-span-2 text-gray-700"> <div className="hidden md:visible font-mono text-sm col-span-2 text-gray-700">
{new Date(c.lastModifiedDateTime).toLocaleString(undefined, { {new Date(c.lastModifiedDateTime).toLocaleString(undefined, {
dateStyle: 'short', dateStyle: 'short',
timeStyle: 'short', timeStyle: 'short',
})} })}
</div> </div>
<div className="font-mono text-sm text-gray-700">{humanFileSize(c.size)}</div> <div className="hidden md:visible font-mono text-sm text-gray-700">{humanFileSize(c.size)}</div>
</div> </div>
) )
} }
@ -80,7 +80,12 @@ const FileListing: FunctionComponent<{ query?: ParsedUrlQuery }> = ({ query }) =
const router = useRouter() const router = useRouter()
const path = queryToPath(query) const path = queryToPath(query)
const { data, error } = useSWR(`/api?path=${path}`, fetcher)
const { data, error } = useSWR(`/api?path=${path}`, fetcher, {
revalidateOnFocus: false,
revalidateOnReconnect: false,
})
if (error) return <div>Failed to load</div> if (error) return <div>Failed to load</div>
if (!data) { if (!data) {
return ( return (
@ -134,9 +139,9 @@ const FileListing: FunctionComponent<{ query?: ParsedUrlQuery }> = ({ query }) =
return ( return (
<div className="bg-white shadow rounded"> <div className="bg-white shadow rounded">
<div className="p-3 grid grid-cols-10 items-center space-x-2 border-b border-gray-200"> <div className="p-3 grid grid-cols-10 items-center space-x-2 border-b border-gray-200">
<div className="col-span-7 font-bold">Name</div> <div className="col-span-10 md:col-span-7 font-bold">Name</div>
<div className="font-bold col-span-2">Last Modified</div> <div className="hidden md:visible font-bold col-span-2">Last Modified</div>
<div className="font-bold">Size</div> <div className="hidden md:visible font-bold">Size</div>
</div> </div>
{imagesInFolder.length !== 0 && ( {imagesInFolder.length !== 0 && (

View file

@ -1,17 +1,32 @@
import { FunctionComponent } from 'react' import { FunctionComponent } from 'react'
import ReactPlayer from 'react-player' import ReactPlayer from 'react-player'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
export const AudioPreview: FunctionComponent<{ file: any }> = ({ file }) => { export const AudioPreview: FunctionComponent<{ file: any }> = ({ file }) => {
return ( return (
<div className="bg-white rounded shadow p-3 w-full"> <div className="bg-white rounded shadow p-3 w-full">
<div className="text-center mb-6">{file.name}</div> <div className="flex space-x-4">
<ReactPlayer <div className="flex items-center justify-center p-10 bg-gray-100 rounded">
url={file['@microsoft.graph.downloadUrl']} <FontAwesomeIcon className="" icon="music" size="lg" />
controls </div>
width="100%" <div className="flex flex-col w-full space-y-2">
height="48px" <div>{file.name}</div>
config={{ file: { forceAudio: true } }} <div className="text-gray-500 text-sm">
/> Last modified:{' '}
{new Date(file.lastModifiedDateTime).toLocaleString(undefined, {
dateStyle: 'short',
timeStyle: 'short',
})}
</div>
<ReactPlayer
url={file['@microsoft.graph.downloadUrl']}
controls
width="100%"
height="48px"
config={{ file: { forceAudio: true } }}
/>
</div>
</div>
</div> </div>
) )
} }

21
package-lock.json generated
View file

@ -10,6 +10,7 @@
"@fortawesome/fontawesome-svg-core": "^1.2.35", "@fortawesome/fontawesome-svg-core": "^1.2.35",
"@fortawesome/free-brands-svg-icons": "^5.15.3", "@fortawesome/free-brands-svg-icons": "^5.15.3",
"@fortawesome/free-regular-svg-icons": "^5.15.3", "@fortawesome/free-regular-svg-icons": "^5.15.3",
"@fortawesome/free-solid-svg-icons": "^5.15.3",
"@fortawesome/react-fontawesome": "^0.1.14", "@fortawesome/react-fontawesome": "^0.1.14",
"axios": "^0.21.1", "axios": "^0.21.1",
"next": "11.0.0", "next": "11.0.0",
@ -177,6 +178,18 @@
"node": ">=6" "node": ">=6"
} }
}, },
"node_modules/@fortawesome/free-solid-svg-icons": {
"version": "5.15.3",
"resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-5.15.3.tgz",
"integrity": "sha512-XPeeu1IlGYqz4VWGRAT5ukNMd4VHUEEJ7ysZ7pSSgaEtNvSo+FLurybGJVmiqkQdK50OkSja2bfZXOeyMGRD8Q==",
"hasInstallScript": true,
"dependencies": {
"@fortawesome/fontawesome-common-types": "^0.2.35"
},
"engines": {
"node": ">=6"
}
},
"node_modules/@fortawesome/react-fontawesome": { "node_modules/@fortawesome/react-fontawesome": {
"version": "0.1.14", "version": "0.1.14",
"resolved": "https://registry.npmjs.org/@fortawesome/react-fontawesome/-/react-fontawesome-0.1.14.tgz", "resolved": "https://registry.npmjs.org/@fortawesome/react-fontawesome/-/react-fontawesome-0.1.14.tgz",
@ -6107,6 +6120,14 @@
"@fortawesome/fontawesome-common-types": "^0.2.35" "@fortawesome/fontawesome-common-types": "^0.2.35"
} }
}, },
"@fortawesome/free-solid-svg-icons": {
"version": "5.15.3",
"resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-5.15.3.tgz",
"integrity": "sha512-XPeeu1IlGYqz4VWGRAT5ukNMd4VHUEEJ7ysZ7pSSgaEtNvSo+FLurybGJVmiqkQdK50OkSja2bfZXOeyMGRD8Q==",
"requires": {
"@fortawesome/fontawesome-common-types": "^0.2.35"
}
},
"@fortawesome/react-fontawesome": { "@fortawesome/react-fontawesome": {
"version": "0.1.14", "version": "0.1.14",
"resolved": "https://registry.npmjs.org/@fortawesome/react-fontawesome/-/react-fontawesome-0.1.14.tgz", "resolved": "https://registry.npmjs.org/@fortawesome/react-fontawesome/-/react-fontawesome-0.1.14.tgz",

View file

@ -12,6 +12,7 @@
"@fortawesome/fontawesome-svg-core": "^1.2.35", "@fortawesome/fontawesome-svg-core": "^1.2.35",
"@fortawesome/free-brands-svg-icons": "^5.15.3", "@fortawesome/free-brands-svg-icons": "^5.15.3",
"@fortawesome/free-regular-svg-icons": "^5.15.3", "@fortawesome/free-regular-svg-icons": "^5.15.3",
"@fortawesome/free-solid-svg-icons": "^5.15.3",
"@fortawesome/react-fontawesome": "^0.1.14", "@fortawesome/react-fontawesome": "^0.1.14",
"axios": "^0.21.1", "axios": "^0.21.1",
"next": "11.0.0", "next": "11.0.0",

View file

@ -18,7 +18,7 @@ export default function Folders() {
<main className="flex flex-col w-full flex-1 bg-gray-50"> <main className="flex flex-col w-full flex-1 bg-gray-50">
<Navbar /> <Navbar />
<div className="mx-auto w-full max-w-4xl mb-8"> <div className="mx-auto w-full max-w-4xl p-4">
<Breadcrumb query={query} /> <Breadcrumb query={query} />
<FileListing query={query} /> <FileListing query={query} />
</div> </div>

View file

@ -13,8 +13,8 @@ import {
faFileAlt, faFileAlt,
faFile, faFile,
faFolder, faFolder,
faCaretSquareDown,
} from '@fortawesome/free-regular-svg-icons' } from '@fortawesome/free-regular-svg-icons'
import { faMusic } from '@fortawesome/free-solid-svg-icons'
import { faGithub, faMarkdown } from '@fortawesome/free-brands-svg-icons' import { faGithub, faMarkdown } from '@fortawesome/free-brands-svg-icons'
import type { AppProps } from 'next/app' import type { AppProps } from 'next/app'
@ -34,7 +34,7 @@ library.add(
faFolder, faFolder,
faGithub, faGithub,
faMarkdown, faMarkdown,
faCaretSquareDown faMusic
) )
function MyApp({ Component, pageProps }: AppProps) { function MyApp({ Component, pageProps }: AppProps) {

View file

@ -15,7 +15,7 @@ export default function Home() {
<main className="flex flex-col w-full flex-1 bg-gray-50"> <main className="flex flex-col w-full flex-1 bg-gray-50">
<Navbar /> <Navbar />
<div className="mx-auto w-full max-w-4xl mb-8"> <div className="mx-auto w-full max-w-4xl p-4">
<Breadcrumb /> <Breadcrumb />
<FileListing /> <FileListing />
</div> </div>