@@ -280,10 +338,10 @@ const FileListing: FunctionComponent<{ query?: ParsedUrlQuery }> = ({ query }) =
)
}
- if ('identityData' in data) {
- const { identityData } = data
- const downloadUrl = identityData['@microsoft.graph.downloadUrl']
- const fileName = data.identityData.name
+ if ('file' in responses[0] && responses.length === 1) {
+ const { file } = responses[0]
+ const downloadUrl = file['@microsoft.graph.downloadUrl']
+ const fileName = file.name
const fileExtension = fileName.slice(((fileName.lastIndexOf('.') - 1) >>> 0) + 2).toLowerCase()
if (hasKey(extensions, fileExtension)) {
@@ -297,25 +355,25 @@ const FileListing: FunctionComponent<{ query?: ParsedUrlQuery }> = ({ query }) =
)
case preview.text:
- return
@@ -326,7 +384,7 @@ const FileListing: FunctionComponent<{ query?: ParsedUrlQuery }> = ({ query }) =
<>
@@ -338,9 +396,8 @@ const FileListing: FunctionComponent<{ query?: ParsedUrlQuery }> = ({ query }) =
return (
-
+
)
}
-
export default FileListing
diff --git a/pages/_app.tsx b/pages/_app.tsx
index cfa38eb..688c01a 100644
--- a/pages/_app.tsx
+++ b/pages/_app.tsx
@@ -35,6 +35,7 @@ import {
faKey,
faSignOutAlt,
faCloud,
+ faChevronCircleDown,
} from '@fortawesome/free-solid-svg-icons'
import { faGithub, faMarkdown, faTelegramPlane } from '@fortawesome/free-brands-svg-icons'
@@ -72,7 +73,8 @@ library.add(
faSignOutAlt,
faEnvelope,
faCloud,
- faTelegramPlane
+ faTelegramPlane,
+ faChevronCircleDown
)
function MyApp({ Component, pageProps }: AppProps) {
diff --git a/pages/api/index.ts b/pages/api/index.ts
index 25f38ce..b7a03da 100644
--- a/pages/api/index.ts
+++ b/pages/api/index.ts
@@ -43,7 +43,7 @@ const getAccessToken = async () => {
}
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
- const { path = '/', raw = false, t = '' } = req.query
+ const { path = '/', raw = false, next = '' } = req.query
if (path === '[...path]') {
res.status(400).json({ error: 'No path specified.' })
return
@@ -125,11 +125,11 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
if ('folder' in identityData) {
const { data: folderData } = await axios.get(`${requestUrl}:/children`, {
headers: { Authorization: `Bearer ${accessToken}` },
- params: t
+ params: next
? {
select: '@microsoft.graph.downloadUrl,name,size,id,lastModifiedDateTime,folder,file',
top: siteConfig.maxItems,
- $skipToken: t,
+ $skipToken: next,
}
: {
select: '@microsoft.graph.downloadUrl,name,size,id,lastModifiedDateTime,folder,file',
@@ -144,13 +144,13 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
// Return paging token if specified
if (nextPage) {
- res.status(200).json({ path, identityData, folderData, nextPage })
+ res.status(200).json({ folder: folderData, next: nextPage })
} else {
- res.status(200).json({ path, identityData, folderData })
+ res.status(200).json({ folder: folderData })
}
return
}
- res.status(200).json({ path, identityData })
+ res.status(200).json({ file: identityData })
return
}
diff --git a/utils/tools.ts b/utils/tools.ts
index 0c90c9c..904e263 100644
--- a/utils/tools.ts
+++ b/utils/tools.ts
@@ -1,6 +1,6 @@
import axios from 'axios'
import sha256 from 'crypto-js/sha256'
-import useSWR, { cache, Key } from 'swr'
+import useSWR, { cache, Key, useSWRInfinite } from 'swr'
import siteConfig from '../config/site.json'
@@ -38,17 +38,54 @@ export const useStaleSWR = (url: Key, path: string = '') => {
revalidateOnReconnect: true,
}
- const storedToken =
- typeof window !== 'undefined' ? JSON.parse(localStorage.getItem(matchProtectedRoute(path)) as string) : ''
- const hashedToken = storedToken ? encryptToken(storedToken) : null
-
+ const hashedToken = getStoredToken(path)
return useSWR([url, hashedToken], fetcher, revalidationOptions)
}
+/**
+ * Paging with useSWRInfinite + protected token support
+ * @param path Current query directory path
+ * @returns useSWRInfinite API
+ */
+export const useProtectedSWRInfinite = (path: string = '') => {
+ const hashedToken = getStoredToken(path)
+
+ /**
+ * Next page infinite loading for useSWR
+ * @param pageIdx The index of this paging collection
+ * @param prevPageData Previous page information
+ * @param path Directory path
+ * @returns API to the next page
+ */
+ const getNextKey = (pageIndex, previousPageData) => {
+ // Reached the end of the collection
+ if (previousPageData && !previousPageData.folder) return null
+
+ // First page with no prevPageData
+ if (pageIndex === 0) return [`/api?path=${path}`, hashedToken]
+
+ // Add nextPage token to API endpoint
+ return [`/api?path=${path}&next=${previousPageData.next}`, hashedToken]
+ }
+
+ const revalidationOptions = {
+ revalidateOnMount: !(cache.has(`arg@"/api?path=${path}"@null`) || cache.has(`/api?path=${path}`)),
+ revalidateOnFocus: false,
+ revalidateOnReconnect: true,
+ }
+ return useSWRInfinite(getNextKey, fetcher, revalidationOptions)
+}
+
// Hash password token with SHA256
const encryptToken = (token: string) => {
return sha256(token).toString()
}
+// Fetch stored token from localStorage and encrypt with SHA256
+const getStoredToken = (path: string) => {
+ const storedToken =
+ typeof window !== 'undefined' ? JSON.parse(localStorage.getItem(matchProtectedRoute(path)) as string) : ''
+ return storedToken ? encryptToken(storedToken) : null
+}
/**
* Compares the hash of .password and od-protected-token header
* @param odTokenHeader od-protected-token header (sha256 hashed token)