diff --git a/website/src/i18n.tsx b/website/src/i18n.tsx index 62137d2..5adb90c 100644 --- a/website/src/i18n.tsx +++ b/website/src/i18n.tsx @@ -19,7 +19,7 @@ const zh = { downloadBtn: "下载 v0.6.8", }, hero: { - badge: "开源 MIT · Windows 10 / 11", + badge: "v0.6.8 · 开源 MIT · Windows / macOS / Linux", titleBefore: "统一管理你的", titleAccent: "AI 供应商", titleAfter: "", @@ -315,7 +315,7 @@ const en: Dict = { downloadBtn: "Download v0.6.8", }, hero: { - badge: "Open source MIT · Windows 10 / 11", + badge: "v0.6.8 · Open source MIT · Windows / macOS / Linux", titleBefore: "One app for all your ", titleAccent: "AI providers", titleAfter: "", diff --git a/website/src/sections/Changelog.tsx b/website/src/sections/Changelog.tsx index e1960f6..2eddcf4 100644 --- a/website/src/sections/Changelog.tsx +++ b/website/src/sections/Changelog.tsx @@ -10,9 +10,14 @@ interface ChangelogEntry { const API_URL = "https://api.github.com/repos/billowliu2/KimiSwitch/releases?per_page=20"; -const CACHE_KEY = "kimi-switch-changelog"; const CACHE_TTL = 60 * 60 * 1000; // 1 hour +/** Cache key is versioned by the newest embedded release so redeploys + * invalidate stale caches in the browser immediately. */ +function cacheKey(embedded: ChangelogEntry[]) { + return `kimi-switch-changelog-${embedded[0]?.version ?? "v1"}`; +} + /** Parse a GitHub release body into bullet items. */ function parseBody(body: string): string[] { return body @@ -36,9 +41,9 @@ async function fetchReleases(): Promise { })); } -function readCache(): ChangelogEntry[] | null { +function readCache(embedded: ChangelogEntry[]): ChangelogEntry[] | null { try { - const raw = localStorage.getItem(CACHE_KEY); + const raw = localStorage.getItem(cacheKey(embedded)); if (!raw) return null; const { ts, data } = JSON.parse(raw) as { ts: number; data: ChangelogEntry[] }; if (Date.now() - ts > CACHE_TTL) return null; @@ -48,10 +53,10 @@ function readCache(): ChangelogEntry[] | null { } } -function writeCache(data: ChangelogEntry[]) { +function writeCache(data: ChangelogEntry[], embedded: ChangelogEntry[]) { try { localStorage.setItem( - CACHE_KEY, + cacheKey(embedded), JSON.stringify({ ts: Date.now(), data }), ); } catch { @@ -67,7 +72,7 @@ export default function Changelog() { useEffect(() => { let cancelled = false; - const cached = readCache(); + const cached = readCache(embedded); if (cached) { setRemote(cached); setSynced(true); @@ -78,7 +83,7 @@ export default function Changelog() { if (cancelled) return; setRemote(data); setSynced(true); - writeCache(data); + writeCache(data, embedded); }) .catch(() => { /* 网络不通时使用内置列表兜底 */