返回 CodeWhale
page.tsx
根目录 / web / app / [locale] / feed / page.tsx
1 import Link from "next/link";
2 import { Seal } from "@/components/seal";
3 import { FeedCard } from "@/components/feed-card";
4 import { fetchFeed } from "@/lib/github";
5 import { getEnv } from "@/lib/kv";
6 import { buildPageMetadata } from "@/lib/page-meta";
7 import type { FeedItem } from "@/lib/types";
8
9 export const revalidate = 600;
10
11 export async function generateMetadata({ params }: { params: Promise<{ locale: string }> }) {
12 const { locale } = await params;
13 const isZh = locale === "zh";
14 return buildPageMetadata({
15 path: "/feed",
16 locale,
17 title: isZh ? "动态 · Codewhale" : "Activity · Codewhale",
18 description: isZh
19 ? "来自 Hmbown/CodeWhale GitHub 仓库的议题、合并请求和发布的实时动态。"
20 : "Live feed of issues, pull requests, and releases mirrored from the Hmbown/CodeWhale GitHub repo.",
21 });
22 }
23
24 export default async function FeedPage({ params }: { params: Promise<{ locale: string }> }) {
25 const { locale } = await params;
26 const isZh = locale === "zh";
27
28 const env = await getEnv();
29 let feed: FeedItem[] = [];
30 try {
31 feed = await fetchFeed(env.GITHUB_TOKEN, 50);
32 } catch (e) {
33 console.error("feed fetch failed", e);
34 }
35
36 const issues = feed.filter((f) => f.kind === "issue");
37 const pulls = feed.filter((f) => f.kind === "pull");
38
39 return (
40 <>
41 {isZh ? (
42 <>
43 <section className="mx-auto max-w-[1400px] px-6 pt-12 pb-8">
44 <div className="flex items-baseline gap-4 mb-3">
45 <Seal char="动" />
46 <div className="eyebrow">Section 03 · 动态</div>
47 </div>
48 <h1 className="font-display tracking-crisp">
49 动态 <span className="font-cjk text-indigo text-5xl ml-2">Activity</span>
50 </h1>
51 <p className="mt-5 max-w-3xl text-ink-soft text-lg leading-[1.9] tracking-wide">
52 来自{" "}
53 <Link href="https://github.com/Hmbown/CodeWhale" className="body-link">Hmbown/CodeWhale</Link>
54 {" "}的议题与合并请求实时镜像。每十分钟刷新一次。点击任意条目跳转至 GitHub。
55 </p>
56 </section>
57
58 <section className="mx-auto max-w-[1400px] px-6 pb-16 grid lg:grid-cols-12 gap-10">
59 <div className="lg:col-span-6">
60 <div className="hairline-t hairline-b hairline-l hairline-r bg-paper">
61 <div className="bg-indigo text-paper px-4 py-3 flex items-baseline justify-between">
62 <div className="font-cjk text-base tracking-wider">合并请求 · Pull Requests</div>
63 <span className="font-mono text-[0.7rem] uppercase tabular tracking-widest">{pulls.length} 条</span>
64 </div>
65 <div className="px-4">
66 {pulls.length > 0 ? (
67 pulls.map((p) => <FeedCard key={p.url} item={p} />)
68 ) : (
69 <div className="py-10 text-center text-sm font-mono text-ink-mute">暂无数据 · feed not loaded</div>
70 )}
71 </div>
72 </div>
73 </div>
74
75 <div className="lg:col-span-6">
76 <div className="hairline-t hairline-b hairline-l hairline-r bg-paper">
77 <div className="bg-ink text-paper px-4 py-3 flex items-baseline justify-between">
78 <div className="font-cjk text-base tracking-wider">议题 · Issues</div>
79 <span className="font-mono text-[0.7rem] uppercase tabular tracking-widest">{issues.length} 条</span>
80 </div>
81 <div className="px-4">
82 {issues.length > 0 ? (
83 issues.map((i) => <FeedCard key={i.url} item={i} />)
84 ) : (
85 <div className="py-10 text-center text-sm font-mono text-ink-mute">暂无数据 · feed not loaded</div>
86 )}
87 </div>
88 </div>
89 </div>
90 </section>
91
92 <section className="bg-paper-deep hairline-t hairline-b">
93 <div className="mx-auto max-w-[1400px] px-6 py-10 grid md:grid-cols-3 gap-6 text-center">
94 <Link href="https://github.com/Hmbown/CodeWhale/issues/new/choose" className="hairline-t hairline-b hairline-l hairline-r bg-paper p-6 hover:bg-indigo hover:text-paper transition-colors">
95 <div className="font-display text-xl mb-1">提交议题</div>
96 <div className="font-cjk text-sm text-ink-mute">Open an issue</div>
97 </Link>
98 <Link href="https://github.com/Hmbown/CodeWhale/compare" className="hairline-t hairline-b hairline-l hairline-r bg-paper p-6 hover:bg-indigo hover:text-paper transition-colors">
99 <div className="font-display text-xl mb-1">提交合并请求</div>
100 <div className="font-cjk text-sm text-ink-mute">Open a PR</div>
101 </Link>
102 <Link href="https://github.com/Hmbown/CodeWhale/discussions/new" className="hairline-t hairline-b hairline-l hairline-r bg-paper p-6 hover:bg-indigo hover:text-paper transition-colors">
103 <div className="font-display text-xl mb-1">发起讨论</div>
104 <div className="font-cjk text-sm text-ink-mute">Start a discussion</div>
105 </Link>
106 </div>
107 </section>
108 </>
109 ) : (
110 <>
111 <section className="mx-auto max-w-[1400px] px-6 pt-12 pb-8">
112 <div className="flex items-baseline gap-4 mb-3">
113 <Seal char="动" />
114 <div className="eyebrow">Section 03 · Activity</div>
115 </div>
116 <h1 className="font-display tracking-crisp">
117 Activity <span className="font-cjk text-indigo text-5xl ml-2">动态</span>
118 </h1>
119 <p className="mt-5 max-w-3xl text-ink-soft text-lg leading-relaxed">
120 A live mirror of issues and pull requests from{" "}
121 <Link href="https://github.com/Hmbown/CodeWhale" className="body-link">Hmbown/CodeWhale</Link>.
122 Refreshed every ten minutes. Click any item to jump to GitHub.
123 </p>
124 </section>
125
126 <section className="mx-auto max-w-[1400px] px-6 pb-16 grid lg:grid-cols-12 gap-10">
127 <div className="lg:col-span-6">
128 <div className="hairline-t hairline-b hairline-l hairline-r bg-paper">
129 <div className="bg-indigo text-paper px-4 py-3 flex items-baseline justify-between">
130 <div className="font-cjk text-base tracking-wider">合并 · Pull Requests</div>
131 <span className="font-mono text-[0.7rem] uppercase tabular tracking-widest">{pulls.length} shown</span>
132 </div>
133 <div className="px-4">
134 {pulls.length > 0 ? (
135 pulls.map((p) => <FeedCard key={p.url} item={p} />)
136 ) : (
137 <div className="py-10 text-center text-sm font-mono text-ink-mute">暂无数据 · feed not loaded</div>
138 )}
139 </div>
140 </div>
141 </div>
142
143 <div className="lg:col-span-6">
144 <div className="hairline-t hairline-b hairline-l hairline-r bg-paper">
145 <div className="bg-ink text-paper px-4 py-3 flex items-baseline justify-between">
146 <div className="font-cjk text-base tracking-wider">议题 · Issues</div>
147 <span className="font-mono text-[0.7rem] uppercase tabular tracking-widest">{issues.length} shown</span>
148 </div>
149 <div className="px-4">
150 {issues.length > 0 ? (
151 issues.map((i) => <FeedCard key={i.url} item={i} />)
152 ) : (
153 <div className="py-10 text-center text-sm font-mono text-ink-mute">暂无数据 · feed not loaded</div>
154 )}
155 </div>
156 </div>
157 </div>
158 </section>
159
160 <section className="bg-paper-deep hairline-t hairline-b">
161 <div className="mx-auto max-w-[1400px] px-6 py-10 grid md:grid-cols-3 gap-6 text-center">
162 <Link href="https://github.com/Hmbown/CodeWhale/issues/new/choose" className="hairline-t hairline-b hairline-l hairline-r bg-paper p-6 hover:bg-indigo hover:text-paper transition-colors">
163 <div className="font-display text-xl mb-1">Open an issue</div>
164 <div className="font-cjk text-sm text-ink-mute">提交议题</div>
165 </Link>
166 <Link href="https://github.com/Hmbown/CodeWhale/compare" className="hairline-t hairline-b hairline-l hairline-r bg-paper p-6 hover:bg-indigo hover:text-paper transition-colors">
167 <div className="font-display text-xl mb-1">Open a PR</div>
168 <div className="font-cjk text-sm text-ink-mute">提交合并</div>
169 </Link>
170 <Link href="https://github.com/Hmbown/CodeWhale/discussions/new" className="hairline-t hairline-b hairline-l hairline-r bg-paper p-6 hover:bg-indigo hover:text-paper transition-colors">
171 <div className="font-display text-xl mb-1">Start a discussion</div>
172 <div className="font-cjk text-sm text-ink-mute">发起讨论</div>
173 </Link>
174 </div>
175 </section>
176 </>
177 )}
178 </>
179 );
180 }
181
181 lines Plain Text