/* ============================================================ CHANGELOG PAGE — Release notes / 更新说明 Content is loaded from /changelog.md (public dir) at runtime, so updating the notes only requires editing that markdown file. ============================================================ */ import BottomNav from "@/components/BottomNav"; import { useDevice } from "@/contexts/DeviceContext"; import { usePageTitleWithConnection } from "@/hooks/usePageTitleWithConnection"; import { resolveLocalePack } from "@/locales/resolveLocale"; import localeZh from "@/locales/data-zh.json"; import { ChevronLeft } from "lucide-react"; import { useEffect, useMemo, useState } from "react"; import { useLocation } from "wouter"; import { Streamdown } from "streamdown"; type HomeLocale = NonNullable<(typeof localeZh)["home"]>; export default function ChangelogPage() { const [, setLocation] = useLocation(); const { deviceState } = useDevice(); const homeText = useMemo((): HomeLocale => { const pack = resolveLocalePack(deviceState?.language); return (pack.home ?? {}) as HomeLocale; }, [deviceState?.language]); const pageTitle = usePageTitleWithConnection(homeText.changelog ?? "更新说明"); const [content, setContent] = useState(null); const [failed, setFailed] = useState(false); useEffect(() => { let cancelled = false; fetch(`${import.meta.env.BASE_URL}changelog.md`) .then((res) => { if (!res.ok) throw new Error(`HTTP ${res.status}`); return res.text(); }) .then((text) => { if (!cancelled) setContent(text); }) .catch(() => { if (!cancelled) setFailed(true); }); return () => { cancelled = true; }; }, []); return (

{pageTitle}

{failed ? (

{homeText.changelogLoadFailed ?? "加载失败,请稍后重试"}

) : content ? (
{content}
) : (
)}
); }