forked from
joebasser.com/atmosphere-account
this repo has no description
1import type { ProfileUpdateRow } from "../../lib/profile-updates.ts";
2import ProfileVersionHistoryModal from "../../islands/ProfileVersionHistoryModal.tsx";
3import TangledIcon from "../icons/TangledIcon.tsx";
4
5interface Props {
6 updates: ProfileUpdateRow[];
7 copy: {
8 heading: string;
9 empty: string;
10 versionHistory: string;
11 viewCommit: string;
12 readFullUpdate: string;
13 };
14}
15
16const BODY_PREVIEW_LENGTH = 240;
17
18function dateLabel(ms: number): string {
19 return new Intl.DateTimeFormat("en", {
20 month: "short",
21 day: "numeric",
22 year: "numeric",
23 }).format(new Date(ms));
24}
25
26function UpdateMeta({ update }: { update: ProfileUpdateRow }) {
27 return (
28 <div class="profile-whats-new-meta">
29 {update.version && <span>{update.version}</span>}
30 <time dateTime={new Date(update.createdAt).toISOString()}>
31 {dateLabel(update.createdAt)}
32 </time>
33 </div>
34 );
35}
36
37function isLongBody(body: string): boolean {
38 return body.length > BODY_PREVIEW_LENGTH || body.split("\n").length > 3;
39}
40
41function previewBody(body: string): string {
42 if (!isLongBody(body)) return body;
43 return `${body.slice(0, BODY_PREVIEW_LENGTH).trimEnd()}...`;
44}
45
46function CommitLink(
47 { href, label }: { href: string; label: string },
48) {
49 return (
50 <a
51 href={href}
52 target="_blank"
53 rel="noopener noreferrer"
54 class="profile-whats-new-icon-button"
55 aria-label={label}
56 title={label}
57 >
58 <TangledIcon class="profile-whats-new-icon" />
59 <span class="profile-whats-new-icon-arrow" aria-hidden="true">↗</span>
60 </a>
61 );
62}
63
64export default function ProfileWhatsNew({ updates, copy }: Props) {
65 const [latest, ...history] = updates;
66 if (!latest) {
67 return (
68 <section class="profile-whats-new glass">
69 <h2 class="profile-card-section-title">{copy.heading}</h2>
70 <p class="profile-whats-new-empty">{copy.empty}</p>
71 </section>
72 );
73 }
74
75 return (
76 <section class="profile-whats-new glass">
77 <div class="profile-whats-new-main">
78 <div class="profile-whats-new-copy">
79 <div class="profile-whats-new-heading-row">
80 <h2 class="profile-card-section-title">{copy.heading}</h2>
81 <ProfileVersionHistoryModal
82 updates={history}
83 copy={{
84 versionHistory: copy.versionHistory,
85 viewCommit: copy.viewCommit,
86 }}
87 />
88 </div>
89 <UpdateMeta update={latest} />
90 <h3 class="profile-whats-new-title">{latest.title}</h3>
91 {isLongBody(latest.body)
92 ? (
93 <div class="profile-whats-new-expand">
94 <p class="profile-whats-new-preview">
95 {previewBody(latest.body)}
96 </p>
97 <details class="profile-whats-new-details">
98 <summary>{copy.readFullUpdate}</summary>
99 <p class="profile-whats-new-full">{latest.body}</p>
100 </details>
101 </div>
102 )
103 : <p class="profile-whats-new-body">{latest.body}</p>}
104 </div>
105 {latest.tangledCommitUrl && (
106 <CommitLink href={latest.tangledCommitUrl} label={copy.viewCommit} />
107 )}
108 </div>
109 </section>
110 );
111}