(key: string, initialValue: T) {
const newValue = JSON.parse(event.newValue);
setStoredValue(newValue);
} catch (error) {
- console.log(error);
+ console.error("Error setting localStorage:", error);
}
}
};
diff --git a/src/pages/api/banner/[folderId]/index.ts b/src/pages/api/banner/[folderId]/index.ts
index 52a9f55..377ec96 100644
--- a/src/pages/api/banner/[folderId]/index.ts
+++ b/src/pages/api/banner/[folderId]/index.ts
@@ -30,28 +30,16 @@ export default initMiddleware(async function handler(
responseTime: Date.now() - _start,
};
- const findFolder = await driveClient.files.list({
- q: `name = '${name}' and trashed = false and 'me' in owners`,
- fields: "files(id, name, mimeType)",
+ const findBanner = await driveClient.files.list({
+ q: `name contains '.banner' and trashed = false and 'me' in owners`,
+ fields: "files(id, name, mimeType, parents)",
});
- const folder = findFolder.data.files?.find(
+ const banner = findBanner.data.files?.find(
(file) =>
- file.name === decodeURIComponent(name) &&
- (file.id as string).startsWith(partialId),
+ file.parents?.[0].startsWith(partialId) &&
+ file.name?.startsWith(".banner"),
);
- if (!folder) {
- throw new ExtendedError("Folder not found.", 404, "notFound");
- }
-
- const listFiles = await driveClient.files.list({
- q: `'${folder.id}' in parents and trashed = false and 'me' in owners`,
- fields: "files(id, name, mimeType)",
- });
-
- const banner = listFiles.data.files?.filter((file) =>
- file.name?.startsWith(".banner"),
- )[0];
- if (!banner || !banner.mimeType?.startsWith("image")) {
+ if (!banner) {
payload.success = false;
return response.status(200).json(payload);
}
diff --git a/src/pages/api/banner/index.ts b/src/pages/api/banner/index.ts
index 0ddde5d..b7faeb7 100644
--- a/src/pages/api/banner/index.ts
+++ b/src/pages/api/banner/index.ts
@@ -12,27 +12,20 @@ export default initMiddleware(async function handler(
const _start = Date.now();
try {
- const query: string[] = [
- "name contains '.banner'",
- `parents = '${apiConfig.files.rootFolder}'`,
- "trashed = false",
- "'me' in owners",
- ];
- const getRootBanner = await driveClient.files.list({
- q: query.join(" and "),
- fields: "files(id, name, mimeType)",
- });
-
const payload: BannerResponse = {
success: true,
timestamp: new Date().toISOString(),
responseTime: Date.now() - _start,
};
- const banner = getRootBanner.data.files?.filter((item) =>
- item.name?.startsWith(".banner"),
- )[0];
- if (!banner || !banner.mimeType?.startsWith("image")) {
+ const findBanner = await driveClient.files.list({
+ q: `name contains '.banner' and trashed = false and 'me' in owners and parents = '${apiConfig.files.rootFolder}'`,
+ fields: "files(id, name, mimeType, parents)",
+ });
+ const banner = findBanner.data.files?.find((file) =>
+ file.name?.startsWith(".banner"),
+ );
+ if (!banner) {
payload.success = false;
return response.status(200).json(payload);
}
diff --git a/src/pages/api/files/[id]/getPath.ts b/src/pages/api/files/[id]/getPath.ts
index 9232fcc..f439dec 100644
--- a/src/pages/api/files/[id]/getPath.ts
+++ b/src/pages/api/files/[id]/getPath.ts
@@ -76,7 +76,7 @@ export default initMiddleware(async function handler(
let tempParent: string[] = file.parents || [];
while (tempParent.length > 0) {
- if (breadcrumbs.length === apiConfig.files.breadcrumbDepth) {
+ if (breadcrumbs.length > apiConfig.files.breadcrumbDepth) {
isLimitReached = true;
break;
}
@@ -99,7 +99,10 @@ export default initMiddleware(async function handler(
success: true,
timestamp: new Date().toISOString(),
responseTime: Date.now() - _start,
- breadcrumbs,
+ breadcrumbs:
+ breadcrumbs.length > apiConfig.files.breadcrumbDepth
+ ? breadcrumbs.slice(0, apiConfig.files.breadcrumbDepth)
+ : breadcrumbs,
isLimitReached,
});
} catch (error: any) {
diff --git a/src/pages/api/files/[id]/index.ts b/src/pages/api/files/[id]/index.ts
index 53ba9b9..40e0995 100644
--- a/src/pages/api/files/[id]/index.ts
+++ b/src/pages/api/files/[id]/index.ts
@@ -66,8 +66,6 @@ export default initMiddleware(async function handler(
{ responseType: "stream" },
);
- console.log(file);
-
response.setHeader(
"Content-Type",
file.mimeType || "application/octet-stream",
diff --git a/src/pages/api/og.tsx b/src/pages/api/og.tsx
index c9232b2..5f62135 100644
--- a/src/pages/api/og.tsx
+++ b/src/pages/api/og.tsx
@@ -32,29 +32,47 @@ export default async function handler(request: NextRequest) {
let fileImage;
if (fileId && isImage) {
- fileImage = `${process.env.NEXT_PUBLIC_DOMAIN}/api/files/${fileId}?download=1`;
+ await fetch(
+ `${process.env.NEXT_PUBLIC_DOMAIN}/api/files/${fileId}?download=1`,
+ )
+ .then((res) => {
+ if (res.headers.get("content-type")?.startsWith("image")) {
+ return { success: true };
+ }
+ return res.json();
+ })
+ .then((data) => {
+ if (!data.success) {
+ throw new Error("File not found");
+ }
+ fileImage = `${process.env.NEXT_PUBLIC_DOMAIN}/api/files/${fileId}?download=1`;
+ })
+ .catch((err) => {
+ throw new Error(err);
+ });
} else if (fileId && !isImage) {
- fileImage = `${process.env.NEXT_PUBLIC_DOMAIN}/api/files/${fileId}?thumbnail=1`;
+ await fetch(
+ `${process.env.NEXT_PUBLIC_DOMAIN}/api/files/${fileId}?thumbnail=1`,
+ )
+ .then((res) => {
+ if (res.headers.get("content-type")?.startsWith("image")) {
+ return { success: true };
+ }
+ return res.json();
+ })
+ .then((data) => {
+ if (!data.success) {
+ throw new Error("File not found");
+ }
+ fileImage = `${process.env.NEXT_PUBLIC_DOMAIN}/api/files/${fileId}?thumbnail=1`;
+ })
+ .catch((err) => {
+ throw new Error(err);
+ });
} else {
throw new Error("Default image");
}
- await fetch(fileImage)
- .then((res) => {
- if (res.headers.get("content-type")?.startsWith("image")) {
- return { success: true };
- }
- return res.json();
- })
- .then((data) => {
- if (!data.success) {
- throw new Error("File not found");
- }
- })
- .catch((err) => {
- throw new Error(err);
- });
-
return new ImageResponse(
(
+ file.parents?.[0].startsWith(partialId),
+ );
+ if (!readme) {
+ return response.status(200);
+ }
+ response.setHeader(
+ "Content-Type",
+ readme.mimeType || "application/octet-stream",
+ );
+ response.setHeader(
+ "Content-Disposition",
+ `inline; filename="${readme.name}"`,
+ );
+ response.setHeader("Cache-Control", "public, max-age=0, must-revalidate");
+ const readmeStream = await driveClient.files.get(
+ {
+ fileId: readme.id as string,
+ alt: "media",
+ },
+ { responseType: "text" },
+ );
+
+ return response.status(200).send(readmeStream.data);
+ } catch (error: any) {
+ const payload: ErrorResponse = {
+ success: false,
+ timestamp: new Date().toISOString(),
+ responseTime: Date.now() - _start,
+ code: error.code || 500,
+ errors: {
+ message: error.errors?.[0].message || error.message || "Unknown error",
+ reason: error.errors?.[0].reason || error.cause || "internalError",
+ },
+ };
+
+ return response.status(payload.code || 500).json(payload);
+ }
+});
diff --git a/src/pages/file/[id].tsx b/src/pages/file/[id].tsx
index 933c06a..60fe6fa 100644
--- a/src/pages/file/[id].tsx
+++ b/src/pages/file/[id].tsx
@@ -1,193 +1,236 @@
-import useSWR from "swr";
-import { ErrorResponse, FileResponse, TFileParent } from "types/googleapis";
-import Breadcrumb from "components/Breadcrumb";
-import { useCallback, useEffect, useState } from "react";
-import LoadingFeedback from "components/APIFeedback/Loading";
-import ErrorFeedback from "components/APIFeedback/Error";
-import { useRouter } from "next/router";
-import FileDetails from "components/layout/FileDetails";
-import useLocalStorage from "hooks/useLocalStorage";
+import { GetServerSideProps } from "next";
import axios from "axios";
-import { GetServerSidePropsContext } from "next";
-import Password from "components/layout/Password";
+import { ErrorResponse, FileResponse } from "types/googleapis";
+import { useEffect, useState } from "react";
+import useSWR from "swr";
+import { urlDecrypt } from "utils/encryptionHelper";
+import DefaultLayout from "components/layout/DefaultLayout";
import { NextSeo } from "next-seo";
-import config from "config/site.config";
+import SWRLayout from "components/layout/SWRLayout";
+import { getFilePreview, getFileType } from "utils/mimeTypesHelper";
+import { capitalize, formatBytes, formatDate } from "utils/formatHelper";
+import Link from "next/link";
+import useCopyText from "hooks/useCopyText";
type Props = {
- passwordParent?: string;
- fileName?: string;
+ id: string;
+ fileName: string;
};
-export default function File({ passwordParent, fileName }: Props) {
- const router = useRouter();
- const { id } = router.query;
-
+type Metadata = {
+ label: string;
+ value: string;
+};
+export default function File({ id, fileName }: Props) {
const [data, setData] = useState
();
- const [globalLoading, setGlobalLoading] = useState(true);
+ const [PreviewComponent, setPreviewComponent] = useState();
+ const [metadata, setMetadata] = useState([]);
- const [passwordStorage, setPasswordStorage] = useLocalStorage<{
- [key: string]: string;
- }>("passwordStorage", {});
- const [password, setPassword] = useState<{ [p: string]: string }>(
- passwordStorage,
- );
+ const copyLink = useCopyText();
+ /**
+ * ===========================
+ * START - fetch file data
+ * ===========================
+ */
const {
data: swrData,
error,
isLoading,
- isValidating,
- mutate,
- } = useSWR(
- `/api/files/${id}`,
- (url, headers) =>
- axios
- .get(url, {
- headers: {
- Authorization: `Bearer ${
- password?.[passwordParent as string] ||
- password?.[id as string] ||
- passwordStorage?.[passwordParent as string] ||
- passwordStorage?.[id as string] ||
- ""
- }`,
- ...headers,
- },
- })
- .then((res) => res.data),
- {
- revalidateOnFocus: false,
- revalidateOnReconnect: false,
- refreshWhenOffline: false,
- refreshWhenHidden: false,
- refreshInterval: 0,
- shouldRetryOnError: false,
- revalidateIfStale: true,
- },
- );
+ } = useSWR(`/api/files/${id}`);
useEffect(() => {
- setGlobalLoading(true);
if (swrData) {
- const parentsArray: TFileParent[] | undefined = swrData.parents;
- parentsArray?.unshift({
- id: swrData.file.id as string,
- name: swrData.file.name as string,
- });
- const payload: FileResponse = {
- parents: parentsArray,
+ const decryptedData: FileResponse = {
...swrData,
+ file: {
+ ...swrData.file,
+ id: urlDecrypt(swrData.file.id as string),
+ webContentLink: urlDecrypt(swrData.file.webContentLink as string),
+ },
};
- setData(payload);
- setGlobalLoading(false);
+ setData(decryptedData);
}
-
- // eslint-disable-next-line react-hooks/exhaustive-deps
- }, [swrData, error, isLoading, isValidating, password]);
+ }, [swrData]);
+ /**
+ * ===========================
+ * END - fetch file data
+ * ===========================
+ */
useEffect(() => {
- if (!isLoading && !isValidating) {
- setGlobalLoading(false);
- } else {
- setGlobalLoading(true);
+ if (data) {
+ const Preview = getFilePreview(
+ data.file.fileExtension as string,
+ data.file.mimeType as string,
+ );
+ setPreviewComponent();
+
+ const defaultMetadata: Metadata[] = [
+ {
+ label: "Name",
+ value: data.file.name as string,
+ },
+ {
+ label: "Type",
+ value: capitalize(
+ getFileType(
+ data.file.fileExtension as string,
+ data.file.mimeType as string,
+ ),
+ ),
+ },
+ {
+ label: "Size",
+ value: formatBytes(data.file.size as string),
+ },
+ {
+ label: "Created",
+ value: formatDate(new Date(data.file.createdTime as string)),
+ },
+ {
+ label: "Modified",
+ value: formatDate(new Date(data.file.modifiedTime as string)),
+ },
+ ];
+ if (data.file.imageMediaMetadata) {
+ defaultMetadata.push({
+ label: "Dimensions",
+ value: `${data.file.imageMediaMetadata.width} x ${data.file.imageMediaMetadata.height}`,
+ });
+ }
+ if (data.file.videoMediaMetadata) {
+ defaultMetadata.push({
+ label: "Duration",
+ value: `${data.file.videoMediaMetadata.durationMillis} ms`,
+ });
+ }
+ setMetadata(defaultMetadata);
}
- // eslint-disable-next-line react-hooks/exhaustive-deps
- }, [isLoading, isValidating]);
-
- useEffect(() => {
- mutate(swrData, {
- revalidate: true,
- }).then((r) => {
- return r;
- });
- // eslint-disable-next-line react-hooks/exhaustive-deps
- }, [password]);
-
- const inputPassCallback = useCallback(
- (data: { [p: string]: string }) => {
- setGlobalLoading(true);
- setPasswordStorage(data);
- setPassword(data);
- },
- [setPasswordStorage],
- );
+ }, [data]);
return (
-
+
+
+
+ {/* File Preview */}
+
+
+ Preview
+
-
-
-
- {globalLoading &&
}
- {!globalLoading && error && (
-
- )}
- {!globalLoading && !error && data && (
- <>
- {data.passwordRequired && !data.passwordValidated && (
-
- )}
- {(data.passwordValidated || !data.passwordRequired) && (
- <>
-
- >
- )}
- >
- )}
-
+
+
+ {PreviewComponent}
+
+
+ {/* Details and download */}
+
+
+
+ Details
+
+
+
+
+ {metadata.map((item, index) => (
+
+ {item.label}
+
+ {item.value}
+
+
+ ))}
+
+
+
+ Download
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
);
}
-export async function getServerSideProps(context: GetServerSidePropsContext) {
+export const getServerSideProps: GetServerSideProps = async (context) => {
const { id } = context.query;
- const data = await axios.get(
+
+ const fetchFileMetadata = await axios.get(
`${process.env.NEXT_PUBLIC_DOMAIN}/api/files/${id}`,
);
-
- context.res.setHeader(
- "Cache-Control",
- "public, s-maxage=10, stale-while-revalidate=59",
- );
-
- if (data) {
+ if (!fetchFileMetadata.data.success) {
return {
- props: {
- passwordParent: data.data.protectedId || null,
- fileName: data.data.file.name,
- },
- };
- } else {
- return {
- props: {
- passwordParent: "",
- fileName: "",
- },
+ notFound: true,
};
}
-}
+
+ return {
+ props: {
+ id,
+ fileName: fetchFileMetadata.data.file.name,
+ },
+ };
+};
diff --git a/src/pages/folder/[id].tsx b/src/pages/folder/[id].tsx
index 6d0c942..1ba71bd 100644
--- a/src/pages/folder/[id].tsx
+++ b/src/pages/folder/[id].tsx
@@ -1,46 +1,38 @@
-import useSWR from "swr";
+import { useContext, useEffect, useState } from "react";
+import DefaultLayout from "components/layout/DefaultLayout";
+import { LayoutContext, TLayoutContext } from "context/layoutContext";
import useSWRInfinite from "swr/infinite";
-import fetcher, { buildNextKey } from "utils/swrFetch";
-import { ErrorResponse, FilesResponse, TFile } from "types/googleapis";
-import Breadcrumb from "components/Breadcrumb";
+import { buildNextKey } from "utils/swrFetch";
+import axios, { AxiosHeaders } from "axios";
+import { BannerResponse, ErrorResponse, FilesResponse } from "types/googleapis";
+import SWRLayout from "components/layout/SWRLayout";
import { drive_v3 } from "googleapis";
-import { useCallback, useEffect, useState } from "react";
-import MarkdownRender from "components/utility/MarkdownRender";
-import config from "config/site.config";
+import siteConfig from "config/site.config";
+import Readme from "components/layout/Readme";
import GridLayout from "components/layout/Files/GridLayout";
-import useLocalStorage from "hooks/useLocalStorage";
-import SwitchLayout from "components/utility/SwitchLayout";
import ListLayout from "components/layout/Files/ListLayout";
-import LoadingFeedback from "components/APIFeedback/Loading";
-import ErrorFeedback from "components/APIFeedback/Error";
-import { useRouter } from "next/router";
-import axios from "axios";
-import Password from "components/layout/Password";
-import { GetServerSidePropsContext } from "next";
+import { createFileId } from "utils/driveHelper";
import { NextSeo } from "next-seo";
+import { GetServerSideProps } from "next";
type Props = {
- passwordParent?: string;
- folderName?: string;
+ id: string;
+ folderName: string;
+ bannerFileId?: string;
};
-export default function Folder({ passwordParent, folderName }: Props) {
- const router = useRouter();
- const { id } = router.query;
-
+export default function Home({ id, folderName, bannerFileId }: Props) {
+ const { layout } = useContext(LayoutContext);
const [data, setData] = useState();
+
const [isReadmeExists, setIsReadmeExists] = useState(false);
- const [renderStyle] = useLocalStorage<"grid" | "list">("renderStyle", "grid");
- const [layoutStyle, setLayoutStyle] = useState<"grid" | "list">(renderStyle);
- const [globalLoading, setGlobalLoading] = useState(true);
-
- const [passwordStorage, setPasswordStorage] = useLocalStorage<{
- [key: string]: string;
- }>("passwordStorage", {});
-
- const [password, setPassword] = useState<{ [p: string]: string }>(
- passwordStorage,
- );
+ const [isReadmeLoading, setIsReadmeLoading] = useState(false);
+ const [readmeData, setReadmeData] = useState();
+ /**
+ * ===========================
+ * START - fetch file data
+ * ===========================
+ * **/
const getNextKey = buildNextKey(`/api/files/${id}`);
const {
data: swrData,
@@ -48,231 +40,168 @@ export default function Folder({ passwordParent, folderName }: Props) {
isLoading,
size,
setSize,
- isValidating,
- mutate,
} = useSWRInfinite(
getNextKey,
- (url, headers) =>
+ (url: string, headers: AxiosHeaders) =>
axios
.get(url, {
headers: {
- Authorization: `Bearer ${
- password?.[passwordParent as string] ||
- password?.[id as string] ||
- passwordStorage?.[passwordParent as string] ||
- passwordStorage?.[id as string] ||
- ""
- }`,
+ Authorization: `Bearer TODO:ADD`,
...headers,
},
})
.then((res) => res.data),
- {
- revalidateOnFocus: false,
- revalidateOnReconnect: false,
- refreshWhenOffline: false,
- refreshWhenHidden: false,
- refreshInterval: 0,
- shouldRetryOnError: false,
- revalidateIfStale: true,
- },
);
- const {
- data: readmeData,
- error: readmeError,
- isLoading: readmeLoading,
- } = useSWR(`/api/readme/${id}`, fetcher, {
- revalidateOnFocus: false,
- revalidateOnReconnect: false,
- refreshWhenOffline: false,
- refreshWhenHidden: false,
- refreshInterval: 0,
- shouldRetryOnError: false,
- });
- const isLoadingInitialData = !swrData && !error;
- const isLoadingMore =
- isLoadingInitialData ||
- (size > 0 && swrData && typeof swrData[size - 1] === "undefined");
- const isEmpty =
- swrData?.[0]?.files?.length === 0 && swrData?.[0]?.folders?.length === 0;
- const isReachingEnd =
- isEmpty ||
- (swrData &&
- typeof swrData[swrData.length - 1]?.nextPageToken === "undefined");
+ const filePagination = {
+ isLoadingInitialData: !swrData && !error,
+ isLoadingMore:
+ (!swrData && !error) ||
+ (size > 0 && swrData && typeof swrData[size - 1] === "undefined"),
+ isEmpty: swrData?.[0]?.files?.length === 0,
+ isReachingEnd:
+ swrData && swrData[swrData.length - 1]?.nextPageToken === undefined,
+ };
+ // Since SWRInfinite returning array of response, we need to flatten it.
useEffect(() => {
- setGlobalLoading(true);
- const files: (TFile | drive_v3.Schema$File)[] | undefined =
- swrData?.flatMap((item: FilesResponse) => item.files);
- const folders: (TFile | drive_v3.Schema$File)[] | undefined =
- swrData?.flatMap((item: FilesResponse) => item.folders);
- const newData: FilesResponse = {
- ...(swrData?.[size - 1] as FilesResponse),
- files: (files as drive_v3.Schema$File[]) || [],
- folders: (folders as drive_v3.Schema$File[]) || [],
- };
- setData(newData);
- if (newData.isReadmeExists) setIsReadmeExists(true);
- setGlobalLoading(false);
+ if (swrData) {
+ // Flatten files and folders, in case someone have more folders too.
+ const files: drive_v3.Schema$File[] = swrData.flatMap(
+ (item) => item.files,
+ );
+ const folders: drive_v3.Schema$File[] = swrData.flatMap(
+ (item) => item.folders,
+ );
+ const flattenData: FilesResponse = {
+ ...swrData[size - 1],
+ files,
+ folders,
+ };
+ setData(flattenData);
- // eslint-disable-next-line react-hooks/exhaustive-deps
- }, [swrData, error, isLoading, size, isValidating, password]);
-
- useEffect(() => {
- if (!isLoading && !isValidating) {
- setGlobalLoading(false);
- } else {
- setGlobalLoading(true);
+ if (flattenData.isReadmeExists) {
+ setIsReadmeExists(true);
+ setIsReadmeLoading(true);
+ axios
+ .get(`/api/readme/${id}`)
+ .then((res) => {
+ setReadmeData(res.data);
+ })
+ .finally(() => {
+ setIsReadmeLoading(false);
+ });
+ } else {
+ setIsReadmeExists(false);
+ setReadmeData("");
+ }
}
- // eslint-disable-next-line react-hooks/exhaustive-deps
- }, [isLoading, isValidating]);
-
- useEffect(() => {
- mutate(swrData, {
- revalidate: true,
- });
- // eslint-disable-next-line react-hooks/exhaustive-deps
- }, [password]);
-
- const inputPassCallback = useCallback(
- (data: { [p: string]: string }) => {
- setGlobalLoading(true);
- setPasswordStorage(data);
- setPassword(data);
- },
- [setPasswordStorage],
- );
+ }, [swrData, size, id]);
+ /**
+ * ===========================
+ * END - fetch file data
+ * ===========================
+ * **/
return (
-
+
-
-
-
-
-
-
- {globalLoading && }
- {!globalLoading && error && (
-
- )}
- {!globalLoading && !error && data && (
- <>
- {data.passwordRequired && !data.passwordValidated && (
-
+ {siteConfig.readme.position === "start" && (
+
+ )}
+
+ {layout === "grid" && (
+
)}
- {(data.passwordValidated || !data.passwordRequired) && (
- <>
- {isReadmeExists && config.readme.position === "start" && (
-
- {readmeLoading && (
-
- )}
- {readmeError && !readmeLoading && (
-
- )}
- {readmeData && !readmeLoading && (
-
- )}
-
- )}
-
-
- {layoutStyle === "list" && (
-
- )}
- {layoutStyle === "grid" && (
-
- )}
-
-
- {isReadmeExists && config.readme.position === "end" && (
-
- {readmeLoading && (
-
- )}
- {readmeError && !readmeLoading && (
-
- )}
- {readmeData && !readmeLoading && (
-
- )}
-
- )}
- >
+ {layout === "list" && (
+
)}
- >
- )}
-
+
+ {siteConfig.readme.position === "end" && (
+
+ )}
+
+
);
}
-export async function getServerSideProps(context: GetServerSidePropsContext) {
+export const getServerSideProps: GetServerSideProps = async (context) => {
const { id } = context.query;
- const data = await axios.get(
+
+ const fetchFolder = await axios.get(
`${process.env.NEXT_PUBLIC_DOMAIN}/api/files/${id}`,
);
- context.res.setHeader(
- "Cache-Control",
- "public, s-maxage=10, stale-while-revalidate=59",
- );
-
- if (data) {
+ if (!fetchFolder.data.success) {
return {
- props: {
- passwordParent: data.data.protectedId || null,
- folderName: data.data.parents?.[0]?.name || null,
- },
- };
- } else {
- return {
- props: {
- passwordParent: "",
- folderName: "",
- },
+ notFound: true,
};
}
-}
+ const folderName = decodeURIComponent((id as string).split(":")[0]);
+
+ const fetchBanner = await axios.get(
+ `${process.env.NEXT_PUBLIC_DOMAIN}/api/banner/${id}`,
+ );
+
+ if (!fetchBanner.data.banner) {
+ return {
+ props: { id, folderName },
+ };
+ }
+
+ const bannerFileId = createFileId(fetchBanner.data.banner, true);
+ return {
+ props: {
+ id,
+ folderName,
+ bannerFileId,
+ },
+ };
+};
diff --git a/src/pages/index.tsx b/src/pages/index.tsx
index a1425f0..f26b9d5 100644
--- a/src/pages/index.tsx
+++ b/src/pages/index.tsx
@@ -13,7 +13,7 @@ import GridLayout from "components/layout/Files/GridLayout";
import ListLayout from "components/layout/Files/ListLayout";
import { createFileId } from "utils/driveHelper";
import { NextSeo } from "next-seo";
-import { GetStaticProps } from "next";
+import { GetServerSideProps } from "next";
type Props = {
bannerFileId?: string;
@@ -165,7 +165,7 @@ export default function Home({ bannerFileId }: Props) {
);
}
-export const getStaticProps: GetStaticProps = async () => {
+export const getServerSideProps: GetServerSideProps = async () => {
const fetchBanner = await axios.get(
`${process.env.NEXT_PUBLIC_DOMAIN}/api/banner`,
);
diff --git a/src/styles/globals.css b/src/styles/globals.css
index 89b57d9..f422c26 100644
--- a/src/styles/globals.css
+++ b/src/styles/globals.css
@@ -254,10 +254,10 @@ html, body {
}
div.divider-horizontal {
- @apply w-full h-px my-2 bg-zinc-400 dark:bg-zinc-500 tablet:my-4;
+ @apply w-full h-px my-2 bg-zinc-400 dark:bg-zinc-500 tablet:my-2;
}
div.divider-vertical {
- @apply h-full w-px mx-2 bg-zinc-400 dark:bg-zinc-500 tablet:mx-4;
+ @apply h-full w-px mx-2 bg-zinc-400 dark:bg-zinc-500 tablet:mx-2;
}
.grid-auto-fit {
diff --git a/src/utils/formatHelper.ts b/src/utils/formatHelper.ts
index 55df1c1..8715760 100644
--- a/src/utils/formatHelper.ts
+++ b/src/utils/formatHelper.ts
@@ -76,3 +76,7 @@ export function formatRelativeDate(
style: "long",
}).format(diff, unit);
}
+
+export function capitalize(string: string) {
+ return string.charAt(0).toUpperCase() + string.slice(1);
+}
diff --git a/src/utils/mimeTypesHelper.ts b/src/utils/mimeTypesHelper.ts
index 5269168..8977f78 100644
--- a/src/utils/mimeTypesHelper.ts
+++ b/src/utils/mimeTypesHelper.ts
@@ -1,4 +1,3 @@
-import mime from "mime-types";
import { IconType } from "react-icons";
import {
BsBoxFill,
@@ -33,10 +32,6 @@ import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
import { OBJLoader } from "three/examples/jsm/loaders/OBJLoader";
import { STLLoader } from "three/examples/jsm/loaders/STLLoader";
-function findMimeType(extension: string): string {
- return mime.lookup(extension) || "application/octet-stream";
-}
-
const type = {
"3d": "3d", // model preview
"audio": "audio", // audio preview
@@ -95,12 +90,12 @@ const extToTypeMap: { [key: string]: string } = {
"wav": type.audio,
// Archives
- "7z": type.default,
- "bz2": type.default,
- "gz": type.default,
- "rar": type.default,
- "tar": type.default,
- "zip": type.default,
+ "7z": type.archive,
+ "bz2": type.archive,
+ "gz": type.archive,
+ "rar": type.archive,
+ "tar": type.archive,
+ "zip": type.archive,
// Rich text
"md": type.rich_text,
@@ -255,6 +250,9 @@ export function getFileType(extension: string, mimeType?: string): string {
if (type === "video") {
return "video";
}
+ if (type === "image") {
+ return "image";
+ }
}
return extToTypeMap[extension] || type.default;