mirror of
https://github.com/Nezumi-2711/next-gdrive-index.git
synced 2026-09-22 13:38:38 +00:00
update: Separate internal to it's own route file
This commit is contained in:
@@ -2,8 +2,7 @@ import { type Metadata, type ResolvedMetadata } from "next";
|
||||
import { notFound } from "next/navigation";
|
||||
|
||||
import { FileActions, FileBreadcrumb, FileExplorerLayout, FileReadme } from "~/components/explorer";
|
||||
import { Status } from "~/components/global";
|
||||
import { Password } from "~/components/layout";
|
||||
import { ErrorComponent, Password } from "~/components/layout";
|
||||
import { PreviewLayout } from "~/components/preview";
|
||||
import { Card, CardContent, CardHeader, CardTitle } from "~/components/ui/card";
|
||||
|
||||
@@ -15,44 +14,17 @@ import { CheckPagePassword } from "~/actions/password";
|
||||
import { ValidatePaths } from "~/actions/paths";
|
||||
import { CreateFileToken } from "~/actions/token";
|
||||
|
||||
import ErrorComponent from "../error";
|
||||
import ConfiguratorPage from "./ConfiguratorPage";
|
||||
import DeployPage from "./DeployPage";
|
||||
import EmbedPage from "./EmbedPage";
|
||||
|
||||
export const revalidate = 60;
|
||||
export const dynamic = "force-dynamic";
|
||||
export const dynamicParams = false;
|
||||
|
||||
type Props = {
|
||||
params: Promise<{
|
||||
rest: string[];
|
||||
}>;
|
||||
};
|
||||
const internal = (paths: string[]) => {
|
||||
const joinedPaths = (paths.join("/").startsWith("/") ? paths.join("/") : `/${paths.join("/")}`).replace(/\/+/g, "/");
|
||||
|
||||
return {
|
||||
isInternalRoot: joinedPaths === "/_",
|
||||
isGuidePage: joinedPaths === "/_/deploy",
|
||||
isConfiguratorPage: joinedPaths === "/_/configurator",
|
||||
isEmbedRootPage: joinedPaths === "/_/embed",
|
||||
isEmbedPage: joinedPaths.startsWith("/_/embed/"),
|
||||
};
|
||||
};
|
||||
|
||||
export async function generateMetadata({ params }: Props, parent: ResolvedMetadata): Promise<Metadata> {
|
||||
const p = await params;
|
||||
let rest = p.rest;
|
||||
const { isInternalRoot, isGuidePage, isConfiguratorPage, isEmbedPage, isEmbedRootPage } = internal(p.rest);
|
||||
if (isInternalRoot)
|
||||
return { title: "Reserved Internal Path", description: "This path is reserved for internal pages" };
|
||||
if (isGuidePage) return { title: "Guide", description: "Read on how to deploy your own index" };
|
||||
if (isConfiguratorPage) return { title: "Configurator", description: "Configure your index" };
|
||||
if (isEmbedRootPage) return { title: "Not Found" };
|
||||
if (isEmbedPage) {
|
||||
rest = rest.slice(2);
|
||||
}
|
||||
const { rest } = await params;
|
||||
|
||||
const paths = await ValidatePaths(rest);
|
||||
if (!paths.success) return { title: "Not Found" };
|
||||
@@ -61,14 +33,10 @@ export async function generateMetadata({ params }: Props, parent: ResolvedMetada
|
||||
if (!currentPath?.id) return { title: "Not Found" };
|
||||
|
||||
const banner = await GetBanner(currentPath.id);
|
||||
if (isEmbedPage && !currentPath.mimeType.includes("video") && !currentPath.mimeType.includes("audio"))
|
||||
return { title: "Not Found" };
|
||||
|
||||
return {
|
||||
title: isEmbedPage ? `${decodeURIComponent(currentPath.path)} (embed)` : decodeURIComponent(currentPath.path),
|
||||
description: isEmbedPage
|
||||
? `Embed ${currentPath.path}`
|
||||
: currentPath.mimeType.includes("folder")
|
||||
title: decodeURIComponent(currentPath.path),
|
||||
description: currentPath.mimeType.includes("folder")
|
||||
? `Browse ${currentPath.path} files`
|
||||
: `View ${currentPath.path}`,
|
||||
openGraph: {
|
||||
@@ -85,29 +53,12 @@ export async function generateMetadata({ params }: Props, parent: ResolvedMetada
|
||||
};
|
||||
}
|
||||
export default async function RestPage({ params }: Props) {
|
||||
const p = await params;
|
||||
let rest = p.rest;
|
||||
const { isInternalRoot, isConfiguratorPage, isEmbedPage, isEmbedRootPage, isGuidePage } = internal(p.rest);
|
||||
if (isInternalRoot)
|
||||
return (
|
||||
<div className='grid grow place-items-center'>
|
||||
<Status
|
||||
icon='Lock'
|
||||
message="This path is preserved for all internal pages, make sure you don't use this path on your google drive"
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
if (isGuidePage) return <DeployPage />;
|
||||
if (isConfiguratorPage) return <ConfiguratorPage />;
|
||||
if (isEmbedRootPage) return notFound();
|
||||
if (isEmbedPage) rest = rest.slice(2);
|
||||
const { rest } = await params;
|
||||
|
||||
const paths = await ValidatePaths(rest);
|
||||
if (!paths.success) notFound();
|
||||
|
||||
const unlocked = await CheckPagePassword(paths.data);
|
||||
if (!unlocked.success && isEmbedPage)
|
||||
return <ErrorComponent error={new Error("Protected file cannot be embedded")} />;
|
||||
if (!unlocked.success) {
|
||||
return (
|
||||
<Password
|
||||
@@ -118,7 +69,7 @@ export default async function RestPage({ params }: Props) {
|
||||
);
|
||||
}
|
||||
|
||||
const currentPath = paths.data[paths.data.length - 1];
|
||||
const currentPath = paths.data.pop();
|
||||
if (!currentPath) return <ErrorComponent error={new Error("Failed to get current path")} />;
|
||||
|
||||
const Layout: React.FC<{
|
||||
@@ -137,7 +88,6 @@ export default async function RestPage({ params }: Props) {
|
||||
);
|
||||
|
||||
if (currentPath.mimeType.includes("folder")) {
|
||||
if (isEmbedPage) return <ErrorComponent error={new Error("Folder cannot be embedded")} />;
|
||||
const [data, readme] = await Promise.all([ListFiles({ id: currentPath.id }), GetReadme(currentPath.id)]);
|
||||
if (!data.success) return <ErrorComponent error={new Error(data.error)} />;
|
||||
if (!readme.success) return <ErrorComponent error={new Error(readme.error)} />;
|
||||
@@ -181,23 +131,6 @@ export default async function RestPage({ params }: Props) {
|
||||
const token = await CreateFileToken(file.data);
|
||||
if (!token.success) return <ErrorComponent error={new Error(token.error)} />;
|
||||
|
||||
if (isEmbedPage) {
|
||||
if (!currentPath.mimeType.includes("video") && !currentPath.mimeType.includes("audio"))
|
||||
return (
|
||||
<div className='max-w-screen fixed left-0 top-0 grid h-full max-h-screen w-full place-items-center bg-transparent p-2'>
|
||||
<ErrorComponent error={new Error("Only video and audio file can be embedded")} />
|
||||
</div>
|
||||
);
|
||||
return (
|
||||
<div className='max-w-screen fixed left-0 top-0 grid h-full max-h-screen w-full place-items-center bg-transparent p-2'>
|
||||
<EmbedPage
|
||||
file={file.data}
|
||||
type={currentPath.mimeType.includes("video") ? "video" : "audio"}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Layout>
|
||||
<PreviewLayout
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
import { type Metadata } from "next";
|
||||
|
||||
import { ConfiguratorPage } from "~/components/internal";
|
||||
|
||||
export const dynamic = "force-static";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "Configurator",
|
||||
description: "Generate configuration file for your index",
|
||||
};
|
||||
|
||||
export default function InternalConfiguratorPage() {
|
||||
return <ConfiguratorPage />;
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
import { type Metadata } from "next";
|
||||
|
||||
import { DeployPage } from "~/components/internal";
|
||||
|
||||
export const dynamic = "force-static";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "Deploying Guide",
|
||||
description: "Read on how to deploy your own index instance",
|
||||
};
|
||||
|
||||
export default function InternalDeployPage() {
|
||||
return <DeployPage />;
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
import { type Metadata, type ResolvedMetadata } from "next";
|
||||
import { notFound } from "next/navigation";
|
||||
|
||||
import { EmbedPage } from "~/components/internal";
|
||||
import { ErrorComponent } from "~/components/layout";
|
||||
|
||||
import { GetFile } from "~/actions/files";
|
||||
import { CheckPagePassword } from "~/actions/password";
|
||||
import { ValidatePaths } from "~/actions/paths";
|
||||
import { CreateFileToken } from "~/actions/token";
|
||||
|
||||
export const revalidate = 60;
|
||||
export const dynamic = "force-dynamic";
|
||||
|
||||
type Props = {
|
||||
params: Promise<{
|
||||
rest: string[];
|
||||
}>;
|
||||
};
|
||||
|
||||
export async function generateMetadata({ params }: Props, parent: ResolvedMetadata): Promise<Metadata> {
|
||||
const { rest } = await params;
|
||||
|
||||
const paths = await ValidatePaths(rest);
|
||||
if (!paths.success) return { title: "Not Found" };
|
||||
|
||||
const currentPath = paths.data.pop();
|
||||
if (!currentPath?.id) return { title: "Not Found" };
|
||||
|
||||
if (!currentPath.mimeType.includes("video") && !currentPath.mimeType.includes("audio")) return { title: "Not Found" };
|
||||
|
||||
return {
|
||||
title: `${decodeURIComponent(currentPath.path)} (embed)`,
|
||||
description: `Embed view of ${currentPath.path}`,
|
||||
openGraph: {
|
||||
images: parent.openGraph?.images,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export default async function InternalEmbedPage({ params }: Props) {
|
||||
const { rest } = await params;
|
||||
|
||||
const paths = await ValidatePaths(rest);
|
||||
if (!paths.success) notFound();
|
||||
|
||||
const unlocked = await CheckPagePassword(paths.data);
|
||||
if (!unlocked.success) return <ErrorComponent error={new Error("Protected file cannot be embedded")} />;
|
||||
|
||||
const currentPath = paths.data.pop();
|
||||
if (!currentPath) return <ErrorComponent error={new Error("Failed to get current path")} />;
|
||||
|
||||
if (!currentPath.mimeType.includes("video") && !currentPath.mimeType.includes("audio"))
|
||||
return (
|
||||
<div className='max-w-screen fixed left-0 top-0 grid h-full max-h-screen w-full place-items-center bg-transparent p-2'>
|
||||
<ErrorComponent error={new Error("Only video and audio files can be embedded")} />
|
||||
</div>
|
||||
);
|
||||
|
||||
const file = await GetFile(currentPath.id);
|
||||
if (!file.success) {
|
||||
if (file.error === "NotFound") notFound();
|
||||
return <ErrorComponent error={new Error(file.error)} />;
|
||||
}
|
||||
if (!file.data) return <ErrorComponent error={new Error("Failed to get file data")} />;
|
||||
const token = await CreateFileToken(file.data);
|
||||
if (!token.success) return <ErrorComponent error={new Error(token.error)} />;
|
||||
|
||||
return (
|
||||
<div className='max-w-screen fixed left-0 top-0 grid h-full max-h-screen w-full place-items-center bg-transparent p-2'>
|
||||
<EmbedPage
|
||||
file={file.data}
|
||||
type={currentPath.mimeType.includes("video") ? "video" : "audio"}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
import { type Metadata } from "next";
|
||||
|
||||
import { Status } from "~/components/global";
|
||||
|
||||
export const dynamic = "force-static";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "Reserved Internal Path",
|
||||
description: "This path is preserved for all internal pages, make sure you don't use this path on your google drive",
|
||||
};
|
||||
|
||||
export default async function InternalRootPage() {
|
||||
return (
|
||||
<div className='grid grow place-items-center'>
|
||||
<Status
|
||||
icon='Lock'
|
||||
message="This path is preserved for all internal pages, make sure you don't use this path on your google drive"
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user