mirror of
https://github.com/Nezumi-2711/next-gdrive-index.git
synced 2026-09-23 04:10:03 +00:00
Add Next SEO and clean some code
This commit is contained in:
@@ -13,7 +13,6 @@ type Props = {
|
||||
export default function Breadcrumb({ data, isLoading }: Props) {
|
||||
const limitItem = 2;
|
||||
const [limitedPath, setLimitedPath] = useState<TFileParent[]>([]);
|
||||
const [slicedPath, setSlicedPath] = useState<TFileParent>();
|
||||
const [isLimited, setIsLimited] = useState<boolean>();
|
||||
// const [isLoading, setIsLoading] = useState<boolean>(true);
|
||||
|
||||
@@ -21,12 +20,12 @@ export default function Breadcrumb({ data, isLoading }: Props) {
|
||||
// setIsLoading(true);
|
||||
if (data.length > 0) {
|
||||
const findRoot = data.find((item) => item.id === config.files.rootFolder);
|
||||
let _data = data;
|
||||
if (findRoot) {
|
||||
data = data.filter((item) => item.id !== config.files.rootFolder);
|
||||
_data = _data.filter((item) => item.id !== config.files.rootFolder);
|
||||
}
|
||||
setLimitedPath(data.slice(0, limitItem).reverse());
|
||||
setSlicedPath(data.slice(limitItem)[0]);
|
||||
setIsLimited(data.length > limitItem);
|
||||
setLimitedPath(_data.slice(0, limitItem).reverse());
|
||||
setIsLimited(_data.length > limitItem);
|
||||
// setIsLoading(false);
|
||||
}
|
||||
}, [data]);
|
||||
@@ -61,7 +60,7 @@ export default function Breadcrumb({ data, isLoading }: Props) {
|
||||
<span className={"cursor-default"}>/</span>
|
||||
|
||||
{idx === limitedPath.length - 1 ? (
|
||||
<span className='flex cursor-default cursor-default items-center gap-2 font-bold'>
|
||||
<span className='flex cursor-default items-center gap-2 font-bold'>
|
||||
{parent.name}
|
||||
</span>
|
||||
) : (
|
||||
|
||||
@@ -37,7 +37,7 @@ export default function GridFile({ data }: Props) {
|
||||
{data.videoMediaMetadata && (
|
||||
<>
|
||||
<MdPlayCircleFilled className='center absolute h-8 w-8 text-white/50 transition-colors duration-300 group-hover:text-white/80' />
|
||||
<span className='absolute bottom-1 right-1 rounded-lg bg-zinc-950/50 px-1 py-0.5 text-xs text-white'>
|
||||
<span className='absolute bottom-0 right-0 rounded-lg rounded-bl-none rounded-tr-none bg-zinc-950/75 px-1 py-0.5 text-xs text-white'>
|
||||
{formatDuration(data.videoMediaMetadata.durationMillis!)}
|
||||
</span>
|
||||
</>
|
||||
|
||||
@@ -70,7 +70,7 @@ export default function DetailsButtons({ data, hash }: Props) {
|
||||
<MdCopyAll />
|
||||
Copy direct link
|
||||
</button>
|
||||
{!config.files.allowDownloadProtectedWithoutAccess && (
|
||||
{hash && !config.files.allowDownloadProtectedWithoutAccess && (
|
||||
<div className={"banner warning text-sm"}>
|
||||
<div className={"flex flex-col gap-2"}>
|
||||
<div className={"font-bold"}>
|
||||
|
||||
@@ -1,13 +1,10 @@
|
||||
import { ErrorResponse, FileResponse, TFile } from "@/types/googleapis";
|
||||
import { TFile } from "@/types/googleapis";
|
||||
import { drive_v3 } from "googleapis";
|
||||
import LoadingFeedback from "@components/APIFeedback/Loading";
|
||||
import { formatBytes, formatDate, formatDuration } from "@utils/formatHelper";
|
||||
import { useEffect, useState } from "react";
|
||||
import DetailsButtons from "@components/layout/FileDetails/DetailsButtons";
|
||||
import ImagePreview from "@components/FilePreview/ImagePreview";
|
||||
import MarkdownRender from "@components/utility/MarkdownRender";
|
||||
import fetcher from "@utils/swrFetch";
|
||||
import useSWR from "swr";
|
||||
import { getFilePreview } from "@utils/mimeTypesHelper";
|
||||
|
||||
type Props = {
|
||||
data: TFile | drive_v3.Schema$File;
|
||||
@@ -18,6 +15,20 @@ export default function FileDetails({ data, hash }: Props) {
|
||||
const [metadata, setMetadata] = useState<{ label: string; value: string }[]>(
|
||||
[],
|
||||
);
|
||||
const [PreviewComponent, setPreviewComponent] = useState<JSX.Element | null>(
|
||||
null,
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
const Preview = getFilePreview(data.fileExtension as string);
|
||||
setPreviewComponent(
|
||||
<Preview
|
||||
data={data}
|
||||
hash={hash || ""}
|
||||
/>,
|
||||
);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (data) {
|
||||
@@ -73,12 +84,13 @@ export default function FileDetails({ data, hash }: Props) {
|
||||
|
||||
<div className={"divider-horizontal"} />
|
||||
|
||||
{data.mimeType?.startsWith("image") && (
|
||||
<ImagePreview
|
||||
data={data}
|
||||
hash={hash || ""}
|
||||
/>
|
||||
)}
|
||||
{PreviewComponent}
|
||||
{/*{data.mimeType?.startsWith("image") && (*/}
|
||||
{/* <ImagePreview*/}
|
||||
{/* data={data}*/}
|
||||
{/* hash={hash || ""}*/}
|
||||
{/* />*/}
|
||||
{/*)}*/}
|
||||
{/*{data.mimeType?.startsWith("audio") && (*/}
|
||||
<div className='flex w-full items-center justify-center'>
|
||||
{/*<video*/}
|
||||
|
||||
@@ -84,7 +84,7 @@ export default function GridLayout({ data, pagination }: Props) {
|
||||
<button
|
||||
disabled={isLoadingMore}
|
||||
onClick={() => {
|
||||
setSize(size + 1);
|
||||
setSize(size + 1).then((r) => r);
|
||||
}}
|
||||
className='w-full rounded-lg'
|
||||
>
|
||||
|
||||
@@ -59,7 +59,7 @@ export default function ListLayout({ data, pagination }: Props) {
|
||||
<button
|
||||
disabled={isLoadingMore}
|
||||
onClick={() => {
|
||||
setSize(size + 1);
|
||||
setSize(size + 1).then((r) => r);
|
||||
}}
|
||||
className='w-full rounded-lg'
|
||||
>
|
||||
|
||||
@@ -55,6 +55,15 @@ export default function Navbar() {
|
||||
const { data, error, isLoading } = useSWR<SearchResponse, ErrorResponse>(
|
||||
`/api/search?query=${debouncedSearchQuery}`,
|
||||
fetcher,
|
||||
{
|
||||
revalidateOnFocus: false,
|
||||
revalidateOnReconnect: false,
|
||||
refreshWhenOffline: false,
|
||||
refreshWhenHidden: false,
|
||||
refreshInterval: 0,
|
||||
shouldRetryOnError: false,
|
||||
revalidateIfStale: true,
|
||||
},
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
@@ -1,21 +1,17 @@
|
||||
import { Dispatch, SetStateAction, useEffect, useState } from "react";
|
||||
import { useState } from "react";
|
||||
import useLocalStorage from "@hooks/useLocalStorage";
|
||||
import { IoMdEye, IoMdEyeOff } from "react-icons/io";
|
||||
import { MdLock } from "react-icons/md";
|
||||
import { useRouter } from "next/router";
|
||||
import { hashToken } from "@utils/hashHelper";
|
||||
import ReactLoading from "react-loading";
|
||||
|
||||
type Props = {
|
||||
folderId: string;
|
||||
inputCallback: (data: { [p: string]: string }) => void;
|
||||
};
|
||||
export default function Password({ folderId, inputCallback }: Props) {
|
||||
const router = useRouter();
|
||||
|
||||
const [password, setPassword] = useState<string>("");
|
||||
const [showPassword, setShowPassword] = useState<boolean>(false);
|
||||
const [passwordStorage, setPasswordStorage] = useLocalStorage<{
|
||||
const [passwordStorage] = useLocalStorage<{
|
||||
[key: string]: string;
|
||||
}>("passwordStorage", {});
|
||||
|
||||
@@ -63,7 +59,7 @@ export default function Password({ folderId, inputCallback }: Props) {
|
||||
onChange={(e) => {
|
||||
setPassword(e.target.value);
|
||||
}}
|
||||
onKeyPress={(e) => {
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === "Enter") {
|
||||
handleSubmit();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user