diff --git a/components/FileListing.tsx b/components/FileListing.tsx
index f1d7fd0..67b9b9b 100644
--- a/components/FileListing.tsx
+++ b/components/FileListing.tsx
@@ -2,12 +2,25 @@ import axios from 'axios'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { ParsedUrlQuery } from 'querystring'
-import { FunctionComponent } from 'react'
+import { FunctionComponent, useState } from 'react'
+
import useSWR from 'swr'
-import Link from 'next/link'
+import { useRouter } from 'next/router'
+import dynamic from 'next/dynamic'
-import getFileIcon from '../utils/getFileIcon'
+import { getExtension, getFileIcon, hasKey } from '../utils/getFileIcon'
+import { extensions, preview } from '../utils/getPreviewType'
+import { ImageDecorator } from 'react-viewer/lib/ViewerProps'
+// View images as gallery
+const ReactViewer = dynamic(() => import('react-viewer'), { 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))
@@ -29,11 +42,39 @@ const queryToPath = (query?: ParsedUrlQuery) => {
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 (
+
-
-
Name
-
Created
-
Size
-
- {children.map((c: any) => (
-
-
-
- {/*
{c.file ? c.file.mimeType : 'folder'}
*/}
-
-
-
-
{c.name}
-
-
- {new Date(c.createdDateTime).toLocaleString(undefined, { dateStyle: 'short', timeStyle: 'short' })}
-
-
{humanFileSize(c.size)}
+ 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 (
+
+ )
+
+ default:
+ return
{fileName}
+ }
+ }
+ }
+
+ return
404
}
export default FileListing
diff --git a/next.config.js b/next.config.js
index 0d60710..d5e534b 100644
--- a/next.config.js
+++ b/next.config.js
@@ -1,3 +1,6 @@
module.exports = {
reactStrictMode: true,
+ images: {
+ domains: ['public.dm.files.1drv.com'],
+ },
}
diff --git a/package-lock.json b/package-lock.json
index 3fa5a22..7b62d29 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -15,6 +15,7 @@
"next": "11.0.0",
"react": "17.0.2",
"react-dom": "17.0.2",
+ "react-viewer": "^3.2.2",
"swr": "^0.5.6"
},
"devDependencies": {
@@ -4647,6 +4648,14 @@
"node": ">=0.10.0"
}
},
+ "node_modules/react-viewer": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/react-viewer/-/react-viewer-3.2.2.tgz",
+ "integrity": "sha512-DHOq1x6cXsAViY43204ILRzLVR5ovP1MgzsC+LzZCWlInRuHjzAgpQZ8GzWm1CkiNYuHGwCxH36X0JUHl2xDSg==",
+ "dependencies": {
+ "classnames": "^2.2.5"
+ }
+ },
"node_modules/read-pkg": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz",
@@ -9472,6 +9481,14 @@
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.8.3.tgz",
"integrity": "sha512-X8jZHc7nCMjaCqoU+V2I0cOhNW+QMBwSUkeXnTi8IPe6zaRWfn60ZzvFDZqWPfmSJfjub7dDW1SP0jaHWLu/hg=="
},
+ "react-viewer": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/react-viewer/-/react-viewer-3.2.2.tgz",
+ "integrity": "sha512-DHOq1x6cXsAViY43204ILRzLVR5ovP1MgzsC+LzZCWlInRuHjzAgpQZ8GzWm1CkiNYuHGwCxH36X0JUHl2xDSg==",
+ "requires": {
+ "classnames": "^2.2.5"
+ }
+ },
"read-pkg": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz",
diff --git a/package.json b/package.json
index 9512b0b..f7c9394 100644
--- a/package.json
+++ b/package.json
@@ -17,6 +17,7 @@
"next": "11.0.0",
"react": "17.0.2",
"react-dom": "17.0.2",
+ "react-viewer": "^3.2.2",
"swr": "^0.5.6"
},
"devDependencies": {
diff --git a/pages/api/index.ts b/pages/api/index.ts
index 2c692db..62032ea 100644
--- a/pages/api/index.ts
+++ b/pages/api/index.ts
@@ -47,15 +47,15 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
if (typeof path === 'string') {
const accessToken = await getAccessToken()
const requestUrl = `${apiConfig.driveApi}/root${encodePath(path)}`
- const files = await axios.get(requestUrl, {
+ const { data } = await axios.get(requestUrl, {
headers: { Authorization: `Bearer ${accessToken}` },
params: {
- select: 'name,size,id,createdDateTime',
- expand: 'children(select=name,createdDateTime,eTag,size,id,file)',
+ select: '@microsoft.graph.downloadUrl,name,size,id,lastModifiedDateTime,folder,file',
+ expand: 'children(select=@content.downloadUrl,name,lastModifiedDateTime,eTag,size,id,folder,file)',
},
})
- res.status(200).json({ path, files: files.data })
+ res.status(200).json({ path, data })
return
}
diff --git a/utils/getFileIcon.ts b/utils/getFileIcon.ts
index 4013659..e181366 100644
--- a/utils/getFileIcon.ts
+++ b/utils/getFileIcon.ts
@@ -1,4 +1,6 @@
-const icons = {
+import { IconPrefix, IconName } from '@fortawesome/fontawesome-common-types'
+
+const icons: { [key: string]: [IconPrefix, IconName] } = {
image: ['far', 'file-image'],
pdf: ['far', 'file-pdf'],
word: ['far', 'file-word'],
@@ -67,11 +69,15 @@ const extensions = {
* @param key The index key
* @returns Whether or not the key exists inside the object
*/
-const hasKey =
(obj: O, key: PropertyKey): key is keyof O => {
+export const hasKey = (obj: O, key: PropertyKey): key is keyof O => {
return key in obj
}
-export default function getFileIcon(fileName: string) {
- const extension = fileName.slice(((fileName.lastIndexOf('.') - 1) >>> 0) + 2).toLowerCase()
+export const getExtension = (fileName: string) => {
+ return fileName.slice(((fileName.lastIndexOf('.') - 1) >>> 0) + 2).toLowerCase()
+}
+
+export const getFileIcon = (fileName: string) => {
+ const extension = getExtension(fileName)
return hasKey(extensions, extension) ? extensions[extension] : icons.file
}
diff --git a/utils/getPreviewType.ts b/utils/getPreviewType.ts
new file mode 100644
index 0000000..5169dc1
--- /dev/null
+++ b/utils/getPreviewType.ts
@@ -0,0 +1,57 @@
+const preview = {
+ markdown: 'markdown',
+ image: 'image',
+ text: 'text',
+ pdf: 'pdf',
+ code: 'code',
+ video: 'video',
+ audio: 'audio',
+}
+
+const extensions = {
+ gif: preview.image,
+ jpeg: preview.image,
+ jpg: preview.image,
+ png: preview.image,
+ webp: preview.image,
+
+ md: preview.markdown,
+ markdown: preview.markdown,
+ mdown: preview.markdown,
+
+ pdf: preview.pdf,
+
+ c: preview.code,
+ cpp: preview.code,
+ js: preview.code,
+ java: preview.code,
+ sh: preview.code,
+ cs: preview.code,
+ py: preview.code,
+ css: preview.code,
+ html: preview.code,
+ ts: preview.code,
+ vue: preview.code,
+ json: preview.code,
+ yaml: preview.code,
+ toml: preview.code,
+
+ txt: preview.text,
+
+ mp4: preview.video,
+ flv: preview.video,
+ webm: preview.video,
+ m3u8: preview.video,
+ mkv: preview.video,
+
+ mp3: preview.audio,
+ m4a: preview.audio,
+ aac: preview.audio,
+ wav: preview.audio,
+ ogg: preview.audio,
+ oga: preview.audio,
+ opus: preview.audio,
+ flac: preview.audio,
+}
+
+export { extensions, preview }