import { useEffect, useState } from "react"; import { recommendLinks } from "../data/recommendLinks"; import { useLang } from "../i18n"; import { asset } from "../lib/asset"; /** Map recommendLink.name → logo file in public/logos (only when we have one). */ const logoFor: Record = { "Kimi": "logos/kimi.svg", "智谱 GLM": "logos/zhipu.svg", "DeepSeek": "logos/deepseek.svg", "OpenCodeGo": "logos/opencode.svg", "MiniMax": "logos/minimax.svg", "基元律动": "logos/tokenrhythm.svg", }; // 下载统计:只拉 GitHub(公开 API 带 CORS),镜像站 Gitea 未开 CORS 不计入。 const STATS_URL = "https://api.github.com/repos/billowliu2/KimiSwitch/releases?per_page=100"; const STATS_CACHE_KEY = "kimi-switch-downloads"; const STATS_CACHE_TTL = 60 * 60 * 1000; // 1 hour /** GitHub Release 全部资产 download_count 之和;拉取失败返回 null(不展示)。 */ function useDownloadCount(): number | null { const [count, setCount] = useState(null); useEffect(() => { let cancelled = false; try { const cached = localStorage.getItem(STATS_CACHE_KEY); if (cached) { const { ts, total } = JSON.parse(cached) as { ts: number; total: number }; if (Date.now() - ts < STATS_CACHE_TTL) { setCount(total); return; } } } catch { /* ignore corrupt cache */ } fetch(STATS_URL) .then((r) => (r.ok ? r.json() : Promise.reject(new Error(String(r.status))))) .then((releases: Array<{ assets?: Array<{ download_count?: number }> }>) => { if (cancelled) return; const total = (releases ?? []).reduce( (sum, rel) => sum + (rel.assets ?? []).reduce((s, a) => s + (a.download_count ?? 0), 0), 0 ); setCount(total); try { localStorage.setItem( STATS_CACHE_KEY, JSON.stringify({ ts: Date.now(), total }) ); } catch { /* ignore quota errors */ } }) .catch(() => { /* 拉取失败则不显示 */ }); return () => { cancelled = true; }; }, []); return count; } export default function Footer() { const { t } = useLang(); const downloadCount = useDownloadCount(); return ( ); }