From c0068e957ef628785bed13b8818188f09e42c8af Mon Sep 17 00:00:00 2001 From: TerryM Date: Sat, 30 May 2026 00:43:27 +0800 Subject: [PATCH 01/37] =?UTF-8?q?feat:=20=E6=96=87=E6=A1=A3=E9=A2=84?= =?UTF-8?q?=E8=A7=88=E5=9B=BE=E6=94=B9=E6=96=B9=E5=BD=A2=E6=94=BE=E5=A4=A7?= =?UTF-8?q?,=E4=B8=8B=E8=BD=BD=E8=83=B6=E5=9B=8A=E6=95=B4=E4=BD=93?= =?UTF-8?q?=E6=94=BE=E5=A4=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - FileDocBubble 预览缩略图 52px 圆形 → 64px 方形圆角(rounded-lg),行高自适应 - AttachmentDownloadPill 放大:图标框 24→30px、图标 14→18px、文字 11→12px Co-Authored-By: Claude Opus 4.8 (1M context) --- .../messageStream/AttachmentDownloadPill.tsx | 10 +++++----- src/components/messageStream/bubbles/FileDocBubble.tsx | 8 ++++---- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/components/messageStream/AttachmentDownloadPill.tsx b/src/components/messageStream/AttachmentDownloadPill.tsx index 6b8ea14..9822131 100644 --- a/src/components/messageStream/AttachmentDownloadPill.tsx +++ b/src/components/messageStream/AttachmentDownloadPill.tsx @@ -43,23 +43,23 @@ export function AttachmentDownloadPill({ type="button" onClick={handleDownload} disabled={isDownloading} - className={`group z-10 inline-flex overflow-hidden rounded-full bg-black/80 text-[11px] text-white shadow-lg ring-1 ring-inset ring-white/20 backdrop-blur-md transition hover:bg-black/90 disabled:cursor-wait ${className}`} + className={`group z-10 inline-flex overflow-hidden rounded-full bg-black/80 text-[12px] text-white shadow-lg ring-1 ring-inset ring-white/20 backdrop-blur-md transition hover:bg-black/90 disabled:cursor-wait ${className}`} aria-label={ isDownloading ? t("downloading") : `Download ${attachment.filename}` } aria-busy={isDownloading} > - + {isDownloading ? ( ) : ( - + )} - + {isDownloading ? ( t("downloading") ) : ( diff --git a/src/components/messageStream/bubbles/FileDocBubble.tsx b/src/components/messageStream/bubbles/FileDocBubble.tsx index ada2c61..7845427 100644 --- a/src/components/messageStream/bubbles/FileDocBubble.tsx +++ b/src/components/messageStream/bubbles/FileDocBubble.tsx @@ -40,22 +40,22 @@ function AttachmentRow({ postId, att }: { postId: string; att: Attachment }) { att.thumbnailUrl ?? att.posterUrl ?? (isImage ? att.url : undefined); return ( -
+
{previewUrl && !previewFailed ? ( setPreviewFailed(true)} - className="h-[52px] w-[52px] shrink-0 rounded-full object-cover" + className="h-16 w-16 shrink-0 rounded-lg object-cover" /> ) : ( )}
From d7e2e56cdea7acc5b9647fbc6961c425d91e06ed Mon Sep 17 00:00:00 2001 From: TerryM Date: Sat, 30 May 2026 00:43:54 +0800 Subject: [PATCH 02/37] ui: home carousel height lock + bubble polish - Home: lock category carousel height to the tallest page so the Official Recommendations section below does not jump up when swiping to a page with fewer categories. - CollapsibleText: raise default threshold to 25 lines and tighten the spacing between the expand-all button and the timestamp (drop the fixed h-8 and use mt-1 instead of mt-1.5). - formatTime: always render dates as yyyy/m/d HH:mm regardless of locale, matching the requested timestamp format. --- .../messageStream/CollapsibleText.tsx | 4 +-- .../messageStream/MessageBubble.tsx | 4 +-- .../messageStream/utils/formatTime.ts | 33 +++++-------------- src/pages/Home/index.tsx | 11 +++++-- 4 files changed, 19 insertions(+), 33 deletions(-) diff --git a/src/components/messageStream/CollapsibleText.tsx b/src/components/messageStream/CollapsibleText.tsx index b0320a4..7bc743b 100644 --- a/src/components/messageStream/CollapsibleText.tsx +++ b/src/components/messageStream/CollapsibleText.tsx @@ -28,7 +28,7 @@ export function CollapsibleText({ children, className = "", wrapperClassName = "", - collapsedLines = 8, + collapsedLines = 25, }: { children: ReactNode; /** Typography classes applied to the text container. */ @@ -110,7 +110,7 @@ export function CollapsibleText({ type="button" onClick={() => setExpanded((v) => !v)} aria-expanded={expanded} - className="group mt-1.5 inline-flex h-8 items-center gap-1 text-[13px] font-medium text-ark-gold transition-colors duration-200 hover:text-ark-gold2" + className="group mt-1 inline-flex items-center gap-1 text-[13px] font-medium leading-5 text-ark-gold transition-colors duration-200 hover:text-ark-gold2" > {expanded ? t("showLess") : t("showMore")} - {formatDateTime(post.publishedAt, lang)} + {formatDateTime(post.publishedAt)}
diff --git a/src/components/messageStream/utils/formatTime.ts b/src/components/messageStream/utils/formatTime.ts index 4e07164..3dacecc 100644 --- a/src/components/messageStream/utils/formatTime.ts +++ b/src/components/messageStream/utils/formatTime.ts @@ -1,34 +1,17 @@ -function localeFor(lang: string): string { - const locales: Record = { - zh: "zh-CN", - en: "en-US", - ja: "ja-JP", - ko: "ko-KR", - vi: "vi-VN", - id: "id-ID", - ms: "ms-MY", - }; - return locales[lang] ?? "en-US"; +function pad2(n: number): string { + return String(n).padStart(2, "0"); } -function formatDate(iso: string, lang: string): string { +function formatDate(iso: string): string { const d = new Date(iso); - return new Intl.DateTimeFormat(localeFor(lang), { - year: "numeric", - month: lang === "en" ? "short" : "numeric", - day: "numeric", - }).format(d); + return `${d.getFullYear()}/${d.getMonth() + 1}/${d.getDate()}`; } -export function formatTime(iso: string, lang: string): string { +export function formatTime(iso: string): string { const d = new Date(iso); - return new Intl.DateTimeFormat(localeFor(lang), { - hour: "numeric", - minute: "2-digit", - hour12: lang === "en", - }).format(d); + return `${pad2(d.getHours())}:${pad2(d.getMinutes())}`; } -export function formatDateTime(iso: string, lang: string): string { - return `${formatDate(iso, lang)} ${formatTime(iso, lang)}`; +export function formatDateTime(iso: string): string { + return `${formatDate(iso)} ${formatTime(iso)}`; } diff --git a/src/pages/Home/index.tsx b/src/pages/Home/index.tsx index 5019140..f6a263b 100644 --- a/src/pages/Home/index.tsx +++ b/src/pages/Home/index.tsx @@ -137,10 +137,15 @@ export function Home() { for (let index = 0; index < figmaOrderedCategories.length; index += 9) { categoryPages.push(figmaOrderedCategories.slice(index, index + 9)); } - const activeCategoryCount = categoryPages[activeCategoryPage]?.length ?? 0; - const activeCategoryRows = Math.ceil(activeCategoryCount / 3); + // Use the tallest page so the carousel height doesn't shrink between + // pages — otherwise the section below jumps up when swiping to a page + // with fewer categories. + const maxCategoryRows = categoryPages.reduce( + (max, page) => Math.max(max, Math.ceil(page.length / 3)), + 0, + ); const mobileCategoryHeight = - activeCategoryRows * 88 + Math.max(0, activeCategoryRows - 1) * 8; + maxCategoryRows * 88 + Math.max(0, maxCategoryRows - 1) * 8; useEffect(() => { const row = categoryRowRef.current; From 15bcb6bdf0dd7fbd60b9a93cd9cf82c33d5ddbbc Mon Sep 17 00:00:00 2001 From: TerryM Date: Sat, 30 May 2026 00:52:23 +0800 Subject: [PATCH 03/37] =?UTF-8?q?feat:=20=E7=9B=B8=E5=86=8C=E4=B8=8B?= =?UTF-8?q?=E8=BD=BD=E8=83=B6=E5=9B=8A=E8=87=AA=E9=80=82=E5=BA=94=E5=B0=BA?= =?UTF-8?q?=E5=AF=B8(=E9=9A=8F=E5=9B=BE=E5=9D=97=E5=A4=A7=E5=B0=8F?= =?UTF-8?q?=E7=BC=A9=E6=94=BE)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - AttachmentDownloadPill 新增 adaptive 模式:用容器查询单位 cqw + clamp, 尺寸随所在容器宽度缩放(图标框 22~30px、图标 13~18px、文字 10~12px) - 相册图块设 container-type: inline-size 作为查询容器,小缩略图上的下载按钮 自动缩小;单图/视频默认固定尺寸不受影响 Co-Authored-By: Claude Opus 4.8 (1M context) --- .../messageStream/AttachmentDownloadPill.tsx | 33 ++++++++++++++++--- .../messageStream/bubbles/AlbumBubble.tsx | 8 ++++- 2 files changed, 35 insertions(+), 6 deletions(-) diff --git a/src/components/messageStream/AttachmentDownloadPill.tsx b/src/components/messageStream/AttachmentDownloadPill.tsx index 9822131..f484304 100644 --- a/src/components/messageStream/AttachmentDownloadPill.tsx +++ b/src/components/messageStream/AttachmentDownloadPill.tsx @@ -12,6 +12,14 @@ type AttachmentDownloadPillProps = { attachment: Attachment; leadingLabel?: string; className?: string; + /** + * When true, the pill scales with its container's width via container-query + * units (clamped to a min/max). The host element must establish a query + * container (e.g. `style={{ containerType: "inline-size" }}`). Use this on + * album tiles so the pill shrinks on small thumbnails. Defaults to a fixed + * size for standalone images/videos. + */ + adaptive?: boolean; }; export function AttachmentDownloadPill({ @@ -19,6 +27,7 @@ export function AttachmentDownloadPill({ attachment, leadingLabel, className = "absolute left-2 top-2", + adaptive = false, }: AttachmentDownloadPillProps) { const { t } = useI18n(); const { showToast } = useToast(); @@ -38,28 +47,42 @@ export function AttachmentDownloadPill({ } }; + // Fixed default vs. container-query-driven adaptive sizing (clamped). + const fontCls = adaptive ? "text-[clamp(10px,5cqw,12px)]" : "text-[12px]"; + const squareCls = adaptive + ? "h-[clamp(22px,11cqw,30px)] w-[clamp(22px,11cqw,30px)]" + : "h-[30px] w-[30px]"; + const iconCls = adaptive + ? "h-[clamp(13px,6.5cqw,18px)] w-[clamp(13px,6.5cqw,18px)]" + : "h-[18px] w-[18px]"; + const textBoxCls = adaptive + ? "h-[clamp(22px,11cqw,30px)] px-[clamp(6px,3cqw,10px)]" + : "h-[30px] px-2.5"; + return (
); From d19f2f9efae72214b1addf08ad895806e501fe27 Mon Sep 17 00:00:00 2001 From: TerryM Date: Sat, 30 May 2026 00:59:06 +0800 Subject: [PATCH 04/37] =?UTF-8?q?feat:=20=E7=A7=BB=E9=99=A4=E3=80=8C?= =?UTF-8?q?=E5=85=B3=E4=BA=8E=E6=9C=AC=E7=AB=99=E3=80=8D=E6=8C=89=E9=92=AE?= =?UTF-8?q?=E4=B8=8E=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - PublicLayout: 删除桌面导航/下拉菜单/页脚三处入口及空页脚,移除 about 导航类型与判断 - App: 移除 /about 路由及 AboutPage 引入 - 删除 pages/About 页面 - DocumentMeta: 移除 /about 的 meta 处理与 about 描述文案(中/英) - i18n: 移除 aboutTitle / aboutIntro / footerAbout(中/英) Co-Authored-By: Claude Opus 4.8 (1M context) --- src/App.tsx | 2 -- src/components/DocumentMeta.tsx | 10 ---------- src/i18n.tsx | 8 -------- src/layouts/PublicLayout.tsx | 33 +-------------------------------- src/pages/About/index.tsx | 18 ------------------ 5 files changed, 1 insertion(+), 70 deletions(-) delete mode 100644 src/pages/About/index.tsx diff --git a/src/App.tsx b/src/App.tsx index dc69c41..ff79fed 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -11,7 +11,6 @@ import { OfficialRecommendationsPage } from "./pages/OfficialRecommendations"; import { SearchPage } from "./pages/Search"; import { PostRedirect } from "./pages/PostRedirect"; import { ScrollToTop } from "./components/ScrollToTop"; -import { AboutPage } from "./pages/About"; import Favorites from "./pages/Favorites"; import { adminUiPrefix } from "./adminPaths"; import { AdminRouteTree } from "./adminRouteTree"; @@ -46,7 +45,6 @@ export default function App() { /> } /> } /> - } /> } /> diff --git a/src/components/DocumentMeta.tsx b/src/components/DocumentMeta.tsx index bf2c859..fc459ae 100644 --- a/src/components/DocumentMeta.tsx +++ b/src/components/DocumentMeta.tsx @@ -15,7 +15,6 @@ const descriptions: Record> = { "按分类探索 ARK 官方资料,快速定位所需教材、公告、视频、图片与文件。", official: "查看 ARK 官方推荐资料,获取优先整理的重点内容与可信资源。", favorites: "收藏功能开发中,未来可在这里集中管理常用 ARK 资料。", - about: "了解 ARK 资料库的用途、资料范围与本站索引说明。", search: "在 ARK 资料库中搜索标题、分类、标签、简介、文件类型与正文内容。", }, en: { @@ -28,8 +27,6 @@ const descriptions: Record> = { "View official ARK recommendations and prioritized trusted resources.", favorites: "Favorites are in development and will help you manage commonly used ARK resources.", - about: - "Learn about the ARK Library purpose, resource scope, and indexing notes.", search: "Search ARK Library titles, categories, tags, summaries, file types, and body text.", }, @@ -136,13 +133,6 @@ function routeMeta( }; } - if (pathname === "/about") { - return { - title: t("footerAbout"), - description: metaDescription(lang, "about"), - }; - } - return { title: t("brand"), description: metaDescription(lang, "home") }; } diff --git a/src/i18n.tsx b/src/i18n.tsx index 72f1887..ca3b7d7 100644 --- a/src/i18n.tsx +++ b/src/i18n.tsx @@ -122,10 +122,6 @@ const zhDict: Dict = { resourceLangFilter: "资料语言", filterTagClear: "清除标签", filterLanguageAll: "全部语言", - aboutTitle: "关于本站", - aboutIntro: - "ARK 数据库汇总官方教材、公告、视频与常用文件,帮助社区快速获取一致版本的可信内容。\n\n本站仅供展示与索引;权利归属以官方公告为准。", - footerAbout: "关于本站", footerAdminLogin: "管理员登录", adminSearchLogs: "搜索记录", adminMetricShares: "分享", @@ -254,10 +250,6 @@ const enDict: Dict = { resourceLangFilter: "Resource language", filterTagClear: "Clear tag", filterLanguageAll: "All languages", - aboutTitle: "About this site", - aboutIntro: - "The ARK library brings together official decks, announcements, videos, and common files so the community can find consistent, trustworthy versions quickly.\n\nThis site is for discovery and indexing only; rights remain with official notices.", - footerAbout: "About", footerAdminLogin: "Admin sign-in", adminSearchLogs: "Search logs", adminMetricShares: "Shares", diff --git a/src/layouts/PublicLayout.tsx b/src/layouts/PublicLayout.tsx index 6b78a19..c48b6ca 100644 --- a/src/layouts/PublicLayout.tsx +++ b/src/layouts/PublicLayout.tsx @@ -17,8 +17,7 @@ type PublicNavWhich = | "browseLatest" | "browseRecommended" | "browsePopular" - | "favorites" - | "about"; + | "favorites"; function navIsActive( pathname: string, @@ -47,8 +46,6 @@ function navIsActive( return ( pathname === "/favorites" || (pathname === "/" && hash === "#favorites") ); - case "about": - return pathname === "/about"; default: return false; } @@ -477,13 +474,6 @@ export function PublicLayout() { > {t("favorites")} - - {t("footerAbout")} -
@@ -593,14 +583,6 @@ export function PublicLayout() { > {t("favorites")} - setOpen(false)} - > - {t("footerAbout")} -
) : null} @@ -637,19 +619,6 @@ export function PublicLayout() { -
-
- - {t("footerAbout")} - -
-
-