From 153047de55a40d02ad3005814a9316b7e8bad6f6 Mon Sep 17 00:00:00 2001 From: mbaharip <62494292+mbahArip@users.noreply.github.com> Date: Mon, 8 May 2023 10:07:03 +0700 Subject: [PATCH] Finalize basic function --- TODO.md | 4 +- src/components/APIFeedback/Error.tsx | 16 +- src/components/Breadcrumb/index.tsx | 42 +- src/components/File/Grid.tsx | 2 +- .../FilePreview/AudioPreview/index.tsx | 24 +- .../FilePreview/CodePreview/index.tsx | 40 +- .../FilePreview/ImagePreview/index.tsx | 24 +- .../FilePreview/MarkdownPreview/index.tsx | 37 +- .../FilePreview/ModelPreview/index.tsx | 5 +- .../FilePreview/PDFPreview/index.tsx | 40 +- .../FilePreview/TextPreview/index.tsx | 37 +- .../FilePreview/VideoPreview/index.tsx | 39 +- src/components/layout/DefaultLayout/index.tsx | 11 +- .../layout/FileDetails/DetailsButtons.tsx | 68 ---- src/components/layout/FileDetails/index.tsx | 134 ------- src/components/layout/Readme/index.tsx | 17 +- src/components/layout/SWRLayout/index.tsx | 14 +- src/components/utility/SwitchLayout.tsx | 2 +- src/hooks/useLocalStorage.ts | 2 +- src/pages/api/banner/[folderId]/index.ts | 26 +- src/pages/api/banner/index.ts | 23 +- src/pages/api/files/[id]/getPath.ts | 7 +- src/pages/api/files/[id]/index.ts | 2 - src/pages/api/og.tsx | 54 ++- src/pages/api/readme/[folderId]/index.tsx | 68 ++++ src/pages/file/[id].tsx | 343 +++++++++------- src/pages/folder/[id].tsx | 367 +++++++----------- src/pages/index.tsx | 4 +- src/styles/globals.css | 4 +- src/utils/formatHelper.ts | 4 + src/utils/mimeTypesHelper.ts | 20 +- 31 files changed, 627 insertions(+), 853 deletions(-) delete mode 100644 src/components/layout/FileDetails/DetailsButtons.tsx delete mode 100644 src/components/layout/FileDetails/index.tsx create mode 100644 src/pages/api/readme/[folderId]/index.tsx diff --git a/TODO.md b/TODO.md index 50ea839..84686e5 100644 --- a/TODO.md +++ b/TODO.md @@ -58,7 +58,9 @@ Since Google Drive direct download need the file to be public, I implement the ` - [x] Fetch file or folder `700~1400ms` - [x] Fetch breadcrumb `900~1500ms` - [x] Fetch readme `1100~1200ms` - - [x] Fetch banner `500-900ms` + - [ ] Fetch readme from specific folder `1200~1600ms` + - [x] Fetch banner `500-800ms` + - [x] Fetch banner from specific folder `500~800ms` - [ ] Protect folder ### Fetch files `/api/files` | `14/17 Completed` diff --git a/src/components/APIFeedback/Error.tsx b/src/components/APIFeedback/Error.tsx index 441bb90..9eeb85b 100644 --- a/src/components/APIFeedback/Error.tsx +++ b/src/components/APIFeedback/Error.tsx @@ -9,21 +9,27 @@ export default function ErrorFeedback({ message }: Props) { Please check the following details and try again:`; return ( -
-
+
+

{errorMessage}

-
+
Error details:
-          {message || "Internal server error"}
+          
+            {message || "Internal server error"}
+          
         
diff --git a/src/components/Breadcrumb/index.tsx b/src/components/Breadcrumb/index.tsx index b2916d7..2fc390d 100644 --- a/src/components/Breadcrumb/index.tsx +++ b/src/components/Breadcrumb/index.tsx @@ -2,7 +2,6 @@ import { BreadCrumbsResponse, TFileParent } from "types/googleapis"; import Link from "next/link"; import { Fragment } from "react"; import { MdHome } from "react-icons/md"; -import ReactLoading from "react-loading"; import siteConfig from "config/site.config"; type Props = { @@ -11,12 +10,14 @@ type Props = { }; export default function Breadcrumb({ data, isLoading }: Props) { + const reverseBreadcrumbs = data?.breadcrumbs?.slice().reverse(); + return ( <> {isLoading ? (
) : ( -
+
{/* Home */} {data?.isLimitReached && ( - ... {siteConfig.breadcrumb.limiter} + ... )} - {data?.breadcrumbs.map((parent: TFileParent, index: number) => ( - - {parent.name} - {index !== data.breadcrumbs.length - 1 && ( +
+ {reverseBreadcrumbs?.map((parent: TFileParent, index: number) => ( + {siteConfig.breadcrumb.limiter} - )} - - ))} + + + {parent.name} + + + + ))} +
)} diff --git a/src/components/File/Grid.tsx b/src/components/File/Grid.tsx index 7b16937..4750ddf 100644 --- a/src/components/File/Grid.tsx +++ b/src/components/File/Grid.tsx @@ -38,7 +38,7 @@ export default function GridFile({ data }: Props) { {/* Thumbnail */}
{data.thumbnailLink && allowThumbnail ? ( diff --git a/src/components/FilePreview/AudioPreview/index.tsx b/src/components/FilePreview/AudioPreview/index.tsx index b6d4f6e..4bcd939 100644 --- a/src/components/FilePreview/AudioPreview/index.tsx +++ b/src/components/FilePreview/AudioPreview/index.tsx @@ -2,10 +2,9 @@ import { TFile } from "types/googleapis"; import { drive_v3 } from "googleapis"; import { useEffect, useState } from "react"; import config from "config/site.config"; -import LoadingFeedback from "components/APIFeedback/Loading"; -import ErrorFeedback from "components/APIFeedback/Error"; import H5AudioPlayer from "react-h5-audio-player"; import "react-h5-audio-player/lib/styles.css"; +import SWRLayout from "components/layout/SWRLayout"; type Props = { data: TFile | drive_v3.Schema$File; @@ -13,13 +12,11 @@ type Props = { export default function AudioPreview({ data }: Props) { const [isLoading, setIsLoading] = useState(true); - const [isError, setIsError] = useState(false); const [errorMessage, setErrorMessage] = useState(""); const [audioSrc, setAudioSrc] = useState(""); useEffect(() => { const timeout = setTimeout(() => { - setIsError(true); setErrorMessage("Audio took too long to load"); setIsLoading(false); }, config.preview.timeout); @@ -32,7 +29,6 @@ export default function AudioPreview({ data }: Props) { clearTimeout(timeout); }; audio.onerror = (error: any) => { - setIsError(true); setErrorMessage(error.message); setIsLoading(false); clearTimeout(timeout); @@ -45,17 +41,11 @@ export default function AudioPreview({ data }: Props) { return (
- {isLoading ? ( - - ) : isError ? ( - - ) : ( +
- )} +
); } diff --git a/src/components/FilePreview/CodePreview/index.tsx b/src/components/FilePreview/CodePreview/index.tsx index dbf37cd..755915b 100644 --- a/src/components/FilePreview/CodePreview/index.tsx +++ b/src/components/FilePreview/CodePreview/index.tsx @@ -1,32 +1,24 @@ -import { TFile } from "types/googleapis"; import { drive_v3 } from "googleapis"; import { useEffect, useState } from "react"; import useSWR from "swr"; -import LoadingFeedback from "components/APIFeedback/Loading"; -import ErrorFeedback from "components/APIFeedback/Error"; import MarkdownRender from "components/utility/MarkdownRender"; -import fetcher from "utils/swrFetch"; import { getCodeLanguage } from "utils/mimeTypesHelper"; +import { createFileId } from "utils/driveHelper"; +import SWRLayout from "components/layout/SWRLayout"; type Props = { - data: TFile | drive_v3.Schema$File; + data: drive_v3.Schema$File; }; export default function CodePreview({ data }: Props) { const [codeContent, setCodeContent] = useState(""); + + const fileId = createFileId(data); const { data: swrData, - error, isLoading, - } = useSWR(`/download/${data.id}/${data.name}`, fetcher, { - revalidateOnFocus: false, - revalidateOnReconnect: false, - refreshWhenOffline: false, - refreshWhenHidden: false, - refreshInterval: 0, - shouldRetryOnError: false, - revalidateIfStale: true, - }); + error, + } = useSWR(`/api/files/${fileId}?download=1`); useEffect(() => { if (swrData) { @@ -41,21 +33,15 @@ export default function CodePreview({ data }: Props) { return (
- {isLoading ? ( - - ) : error ? ( - - ) : ( +
- )} +
); } diff --git a/src/components/FilePreview/ImagePreview/index.tsx b/src/components/FilePreview/ImagePreview/index.tsx index 3f99b1b..0c5e79d 100644 --- a/src/components/FilePreview/ImagePreview/index.tsx +++ b/src/components/FilePreview/ImagePreview/index.tsx @@ -1,10 +1,9 @@ import { TFile } from "types/googleapis"; import { drive_v3 } from "googleapis"; import { useEffect, useState } from "react"; -import LoadingFeedback from "components/APIFeedback/Loading"; -import ErrorFeedback from "components/APIFeedback/Error"; import config from "config/site.config"; import { reverseString } from "utils/hashHelper"; +import SWRLayout from "components/layout/SWRLayout"; type Props = { data: TFile | drive_v3.Schema$File; @@ -13,13 +12,11 @@ type Props = { export default function ImagePreview({ data, hash }: Props) { const [isLoading, setIsLoading] = useState(true); - const [isError, setIsError] = useState(false); const [errorMessage, setErrorMessage] = useState(""); const [imageSrc, setImageSrc] = useState(""); useEffect(() => { const timeout = setTimeout(() => { - setIsError(true); setErrorMessage("Image took too long to load"); setIsLoading(false); }, config.preview.timeout); @@ -31,7 +28,6 @@ export default function ImagePreview({ data, hash }: Props) { clearTimeout(timeout); }; image.onerror = (error: any) => { - setIsError(true); setErrorMessage(error.message); setIsLoading(false); clearTimeout(timeout); @@ -44,23 +40,17 @@ export default function ImagePreview({ data, hash }: Props) { return (
- {isLoading ? ( - - ) : isError ? ( - - ) : ( + {(data.name - )} +
); } diff --git a/src/components/FilePreview/MarkdownPreview/index.tsx b/src/components/FilePreview/MarkdownPreview/index.tsx index 0d6b09f..0b9530f 100644 --- a/src/components/FilePreview/MarkdownPreview/index.tsx +++ b/src/components/FilePreview/MarkdownPreview/index.tsx @@ -1,47 +1,32 @@ -import { TFile } from "types/googleapis"; import { drive_v3 } from "googleapis"; import useSWR from "swr"; -import LoadingFeedback from "components/APIFeedback/Loading"; -import ErrorFeedback from "components/APIFeedback/Error"; import MarkdownRender from "components/utility/MarkdownRender"; -import fetcher from "utils/swrFetch"; +import { createFileId } from "utils/driveHelper"; +import SWRLayout from "components/layout/SWRLayout"; type Props = { - data: TFile | drive_v3.Schema$File; + data: drive_v3.Schema$File; }; export default function MarkdownPreview({ data }: Props) { + const fileId = createFileId(data); const { data: swrData, error, isLoading, - } = useSWR(`/download/${data.id}/${data.name}`, fetcher, { - revalidateOnFocus: false, - revalidateOnReconnect: false, - refreshWhenOffline: false, - refreshWhenHidden: false, - refreshInterval: 0, - shouldRetryOnError: false, - revalidateIfStale: true, - }); + } = useSWR(`/api/files/${fileId}?download=1`); return (
- {isLoading ? ( - - ) : error ? ( - - ) : ( +
- )} +
); } diff --git a/src/components/FilePreview/ModelPreview/index.tsx b/src/components/FilePreview/ModelPreview/index.tsx index cbda2ca..05739ed 100644 --- a/src/components/FilePreview/ModelPreview/index.tsx +++ b/src/components/FilePreview/ModelPreview/index.tsx @@ -17,10 +17,7 @@ export default function ModelPreview({ data }: Props) { if (!getLoader) { return (
- +
); } diff --git a/src/components/FilePreview/PDFPreview/index.tsx b/src/components/FilePreview/PDFPreview/index.tsx index 984c555..fea6740 100644 --- a/src/components/FilePreview/PDFPreview/index.tsx +++ b/src/components/FilePreview/PDFPreview/index.tsx @@ -1,28 +1,24 @@ -import { TFile } from "types/googleapis"; import { drive_v3 } from "googleapis"; import { useState } from "react"; import config from "config/site.config"; -import LoadingFeedback from "components/APIFeedback/Loading"; -import ErrorFeedback from "components/APIFeedback/Error"; +import { createFileId } from "utils/driveHelper"; +import SWRLayout from "components/layout/SWRLayout"; type Props = { - data: TFile | drive_v3.Schema$File; + data: drive_v3.Schema$File; }; export default function PDFPreview({ data }: Props) { + const fileId = createFileId(data); const [isLoading, setIsLoading] = useState(true); - const [isError, setIsError] = useState(false); const [errorMessage, setErrorMessage] = useState(""); - const fileURL = `${process.env.NEXT_PUBLIC_DOMAIN}/api/files/${data.id}/download`; + const fileURL = `${process.env.NEXT_PUBLIC_DOMAIN}/api/files/${fileId}?download=1`; let providerURL; switch (config.preview.pdfProvider) { case "google": providerURL = `https://drive.google.com/viewerng/viewer?embedded=true&url=${fileURL}`; break; - case "microsoft": - providerURL = `https://view.officeapps.live.com/op/embed.aspx?src=${fileURL}`; - break; case "mozilla": providerURL = `https://mozilla.github.io/pdf.js/web/viewer.html?file=${fileURL}`; break; @@ -33,34 +29,28 @@ export default function PDFPreview({ data }: Props) { return (
- {isLoading ? ( - - ) : isError ? ( - - ) : ( + <> - )} +