76 lines
3.4 KiB
TypeScript

import { redirect } from "next/navigation";
import { and, desc, eq } from "drizzle-orm";
import { auth } from "@/app/(auth)/auth";
import { VideoCanvasHome, type VideoCanvasHomeProject } from "@/components/canvas/VideoCanvasHome";
import { db } from "@/lib/db";
import { getSiteSettings } from "@/lib/db/queries";
import { canvasProject } from "@/lib/db/schema";
type Props = { searchParams?: Promise<Record<string, string | string[] | undefined>> };
function first(value: string | string[] | undefined) {
return Array.isArray(value) ? value[0] : value;
}
function canvasHref(id: string, incoming: Record<string, string | string[] | undefined>) {
const params = new URLSearchParams({ mode: "video", workspaceType: "video" });
for (const [key, value] of Object.entries(incoming)) {
if (["new", "mode", "workspaceType"].includes(key) || value === undefined) continue;
for (const item of Array.isArray(value) ? value : [value]) params.append(key, item);
}
return `/canvas/${id}?${params.toString()}`;
}
function projectPreview(thumbnail: string | null, canvasData: unknown) {
const nodes = canvasData && typeof canvasData === "object" && "nodes" in canvasData
? (canvasData as { nodes?: unknown }).nodes : null;
const candidates = [thumbnail];
if (Array.isArray(nodes)) for (const node of [...nodes].reverse()) {
if (!node || typeof node !== "object") continue;
const item = node as { inputType?: string; draftValues?: Record<string, unknown> };
const draft = item.draftValues || {};
candidates.push(
String(draft.poster || draft.previewImageUrl || draft.thumbnailUrl || draft.resultImage || (item.inputType === "image" ? draft.mediaUrl || (Array.isArray(draft.url) ? draft.url[0] : "") : "") || ""),
);
}
return candidates.find(value => typeof value === "string" && (value.startsWith("https://") || value.startsWith("/"))) || null;
}
export default async function VideoCanvasHomePage({ searchParams }: Props) {
const session = await auth();
if (!session?.user?.id) redirect("/login?callbackUrl=%2Fvideo-canvas");
const params = (await searchParams) || {};
if (first(params.new) === "1") {
const [created] = await db.insert(canvasProject).values({
userId: session.user.id,
title: "未命名视频画布",
workspaceType: "video",
canvasData: { nodes: [], edges: [], viewport: { x: 0, y: 0, zoom: 1 } },
}).returning({ id: canvasProject.id });
redirect(canvasHref(created.id, params));
}
const [rows, siteSettings] = await Promise.all([db.select({
id: canvasProject.id,
title: canvasProject.title,
thumbnail: canvasProject.thumbnail,
canvasData: canvasProject.canvasData,
createdAt: canvasProject.createdAt,
updatedAt: canvasProject.updatedAt,
}).from(canvasProject).where(and(
eq(canvasProject.userId, session.user.id),
eq(canvasProject.workspaceType, "video"),
)).orderBy(desc(canvasProject.updatedAt)).limit(25), getSiteSettings()]);
const projects: VideoCanvasHomeProject[] = rows.slice(0, 24).map(row => ({
id: row.id,
title: row.title,
thumbnail: projectPreview(row.thumbnail, row.canvasData),
createdAt: row.createdAt.toISOString(),
updatedAt: row.updatedAt.toISOString(),
}));
return <VideoCanvasHome initialHasMore={rows.length > 24} initialProjects={projects} siteLogo={siteSettings.siteLogo} siteLogoDark={siteSettings.siteLogoDark} siteName={siteSettings.siteName} userName={session.user.name || ""} />;
}