import type { Metadata } from "next"; import Link from "next/link"; import { getFileUrl } from "@/lib/minio"; import { playbackContextQuery } from "@/lib/playback-context"; import { prisma } from "@/lib/prisma"; import { isVideoContentTag, VIDEO_CONTENT_TAGS } from "@/lib/video-tags"; import FeedMasonry from "./components/FeedMasonry"; import SearchBox from "./components/SearchBox"; import type { FeedItem } from "./types/feed"; export const dynamic = "force-dynamic"; export const metadata: Metadata = { title: "作品集 - 抖歪", description: "抖歪作品集,记录当下时代的精彩瞬间", }; export default async function Home({ searchParams, }: { searchParams?: { tag?: string }; }) { const requestedTag = searchParams?.tag?.trim() || ""; const selectedTag = requestedTag && isVideoContentTag(requestedTag) ? requestedTag : null; const [videos, posts] = await Promise.all([ prisma.video.findMany({ where: selectedTag ? { manual_content_tags: { has: selectedTag }, } : undefined, orderBy: { created_at: "desc" }, take: 60, include: { author: true, }, }), selectedTag ? Promise.resolve([]) : prisma.imagePost.findMany({ orderBy: { created_at: "desc" }, take: 60, include: { author: true, images: { orderBy: { order: "asc" }, take: 1 }, }, }), ]); const feed: FeedItem[] = [ ...videos.map((v) => ({ type: "video" as const, aweme_id: v.aweme_id, created_at: v.created_at, desc: v.desc, video_url: getFileUrl(v.video_url), cover_url: getFileUrl(v.cover_url ?? ""), width: v.width ?? null, height: v.height ?? null, author: { nickname: v.author.nickname, avatar_url: getFileUrl(v.author.avatar_url ?? ""), sec_uid: v.author.sec_uid, }, likes: Number(v.digg_count), content_tags: v.manual_content_tags, })), ...posts.map((p) => { const coverPath = p.images?.[0]?.url; return { type: "image" as const, aweme_id: p.aweme_id, created_at: p.created_at, desc: p.desc, cover_url: coverPath ? getFileUrl(coverPath) : null, width: p.images?.[0]?.width ?? null, height: p.images?.[0]?.height ?? null, author: { nickname: p.author.nickname, avatar_url: getFileUrl(p.author.avatar_url ?? ""), sec_uid: p.author.sec_uid, }, likes: Number(p.digg_count), }; }), ] //.sort(() => Math.random() - 0.5) .sort((a, b) => +new Date(b.created_at) - +new Date(a.created_at)); return (
{/* 装饰背景 */}

Douyin Archive

全部 {VIDEO_CONTENT_TAGS.map((tag) => ( {tag} ))}
{(() => { const initial = feed.slice(0, 24); const lastItem = initial.at(-1); const cursor = lastItem ? new Date(lastItem.created_at).toISOString() : null; return ( ); })()}
); }