mirror of
https://github.com/Nezumi-2711/next-gdrive-index.git
synced 2026-09-22 20:01:36 +00:00
154 lines
3.9 KiB
TypeScript
154 lines
3.9 KiB
TypeScript
"use client";
|
|
|
|
import { useMemo, useState } from "react";
|
|
import { type z } from "zod";
|
|
|
|
import { Status } from "~/components/global";
|
|
import {
|
|
PreviewDocument,
|
|
PreviewImage,
|
|
PreviewInformation,
|
|
PreviewManga,
|
|
PreviewMedia,
|
|
PreviewRich,
|
|
PreviewUnknown,
|
|
} from "~/components/preview";
|
|
import { Button } from "~/components/ui/button";
|
|
import { Card, CardContent, CardFooter, CardHeader, CardTitle } from "~/components/ui/card";
|
|
|
|
import { type getFileType } from "~/lib/previewHelper";
|
|
import { cn } from "~/lib/utils";
|
|
|
|
import { type Schema_File } from "~/types/schema";
|
|
|
|
import config from "config";
|
|
|
|
import MediaPlaylistLayout from "./MediaPlaylistLayout";
|
|
|
|
type Props = {
|
|
data: z.infer<typeof Schema_File>;
|
|
fileType: "unknown" | ReturnType<typeof getFileType>;
|
|
token: string;
|
|
playlist: z.infer<typeof Schema_File>[];
|
|
paths: string[];
|
|
};
|
|
export default function PreviewLayout({ data, paths, fileType, token, playlist }: Props) {
|
|
const [view, setView] = useState<"markdown" | "raw">("markdown");
|
|
const PreviewComponent = useMemo(() => {
|
|
switch (fileType) {
|
|
case "image":
|
|
return <PreviewImage file={data} />;
|
|
case "video":
|
|
case "audio":
|
|
return (
|
|
<PreviewMedia
|
|
file={data}
|
|
type={fileType}
|
|
/>
|
|
);
|
|
case "code":
|
|
return (
|
|
<PreviewRich
|
|
file={data}
|
|
isCode
|
|
view={"markdown"}
|
|
/>
|
|
);
|
|
case "markdown":
|
|
case "text":
|
|
return (
|
|
<PreviewRich
|
|
file={data}
|
|
view={view}
|
|
/>
|
|
);
|
|
case "document":
|
|
return (
|
|
<PreviewDocument
|
|
file={data}
|
|
token={token}
|
|
/>
|
|
);
|
|
case "pdf":
|
|
return (
|
|
<PreviewDocument
|
|
file={data}
|
|
token={token}
|
|
/>
|
|
);
|
|
case "manga":
|
|
return <PreviewManga file={data} />;
|
|
case "unknown":
|
|
default:
|
|
return <PreviewUnknown />;
|
|
}
|
|
}, [fileType, data, view, token]);
|
|
|
|
return (
|
|
<div
|
|
slot='preview-container'
|
|
className='flex flex-col gap-2 tablet:gap-4'
|
|
>
|
|
<Card>
|
|
<CardHeader>
|
|
<div
|
|
className={cn(
|
|
"flex flex-col gap-4 overflow-hidden",
|
|
"mobile:flex-row mobile:items-center mobile:justify-between",
|
|
)}
|
|
>
|
|
<CardTitle className='line-clamp-1 flex-grow whitespace-pre-wrap break-all'>
|
|
Preview of {data.name}
|
|
</CardTitle>
|
|
{["text", "markdown"].includes(fileType) && (
|
|
<div className='flex w-full items-center mobile:w-fit'>
|
|
<Button
|
|
size={"sm"}
|
|
variant={view === "markdown" ? "default" : "outline"}
|
|
onClick={() => setView("markdown")}
|
|
className='w-full rounded-r-none mobile:w-fit'
|
|
>
|
|
Markdown
|
|
</Button>
|
|
<Button
|
|
size={"sm"}
|
|
variant={view === "raw" ? "default" : "outline"}
|
|
onClick={() => setView("raw")}
|
|
className='w-full rounded-l-none mobile:w-fit'
|
|
>
|
|
Raw
|
|
</Button>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</CardHeader>
|
|
|
|
<CardContent>
|
|
{config.apiConfig.streamMaxSize && Number(data.size ?? 0) > config.apiConfig.streamMaxSize ? (
|
|
<Status
|
|
icon='Frown'
|
|
message='File is too large to preview'
|
|
/>
|
|
) : (
|
|
<>{PreviewComponent}</>
|
|
)}
|
|
</CardContent>
|
|
|
|
<CardFooter>
|
|
<MediaPlaylistLayout
|
|
type={"inside"}
|
|
paths={paths}
|
|
currentItem={data}
|
|
playlist={playlist}
|
|
/>
|
|
</CardFooter>
|
|
</Card>
|
|
|
|
<PreviewInformation
|
|
file={data}
|
|
token={token}
|
|
/>
|
|
</div>
|
|
);
|
|
}
|