feat: v0.5.2 - daily trend refactor + provider/model two-level drill-down

- Dashboard: 用量趋势卡片改为外层 tab 容器(下划线 tab),移除卡片标题与内部 pill 切换器
- 用量趋势: 新增 供应商模型用量趋势 tab,与 模型用量趋势 并列
- 供应商 tab 弹窗: 每日用量详情改为两级(供应商 → 模型)分组
- 后端: DailyRow 新增 by_provider_model 嵌套聚合
- 前端: DailyBars 通用化(dimension/colorMap),DailyDetailModal 按 tab 维度渲染
- i18n: 新增 providerDistribution(中/英)
- 版本: 0.5.1 → 0.5.2(tauri.conf / Cargo.toml / package.json / README)
This commit is contained in:
KimiSwitch Dev committed 2026-07-29 13:41:04 +08:00
1 parent 3dd1fd93fe
commit a1fdc6c93d
16 files changed
+1190 -506

No files matched your search

+20 -7
View File
@@ -1,4 +1,4 @@
import { useCallback, useEffect, useState } from "react";
import { useCallback, useEffect, useRef, useState } from "react";
import { invoke } from "@tauri-apps/api/core";
export interface UpdateInfo {
@@ -10,7 +10,10 @@ export interface UpdateInfo {
}
const THROTTLE_KEY = "kimi-switch-last-update-check";
const THROTTLE_MS = 24 * 60 * 60 * 1000; // 24 hours
// Both the throttle window and the periodic re-check run on an 8h cadence:
// long-running sessions still pick up new releases without a restart, and the
// actual backend call is still gated so short windows don't double-fire.
const CHECK_INTERVAL_MS = 8 * 60 * 60 * 1000; // 8 hours
export function useUpdateCheck() {
const [updateInfo, setUpdateInfo] = useState<UpdateInfo | null>(null);
@@ -26,7 +29,7 @@ export function useUpdateCheck() {
const doCheck = useCallback(async (force: boolean) => {
if (!force) {
if (lastChecked && Date.now() - lastChecked < THROTTLE_MS) return;
if (lastChecked && Date.now() - lastChecked < CHECK_INTERVAL_MS) return;
}
setChecking(true);
try {
@@ -40,16 +43,26 @@ export function useUpdateCheck() {
// ignore
}
} catch {
// silently fail — user can retry from Settings
// silently fail — network errors, parse errors, etc. should not nag
// the user. They can still trigger a manual check from Settings.
} finally {
setChecking(false);
}
}, [lastChecked]);
// On mount: throttled auto-check
// Keep a ref to the latest doCheck so the periodic interval doesn't need
// to be reset on every lastChecked change.
const doCheckRef = useRef(doCheck);
useEffect(() => {
doCheck(false);
// eslint-disable-next-line react-hooks/exhaustive-deps
doCheckRef.current = doCheck;
}, [doCheck]);
// On mount: throttled auto-check + periodic re-check while the window
// stays open. Errors are silent (handled inside doCheck).
useEffect(() => {
doCheckRef.current(false);
const interval = setInterval(() => doCheckRef.current(false), CHECK_INTERVAL_MS);
return () => clearInterval(interval);
}, []);
const checkNow = useCallback(() => doCheck(true), [doCheck]);