From 1de8b9ee4c18605ceae24f391aad9adba90f6fa9 Mon Sep 17 00:00:00 2001 From: KimiSwitch Dev Date: Sun, 6 Sep 2026 19:36:42 +0800 Subject: [PATCH] =?UTF-8?q?fix(usage):=20=E5=85=B3=E9=97=AD=E3=80=8C?= =?UTF-8?q?=E5=90=AF=E7=94=A8=E7=94=A8=E9=87=8F=E6=9F=A5=E8=AF=A2=E3=80=8D?= =?UTF-8?q?=E5=90=8E=E4=B8=8D=E5=86=8D=E5=8F=91=E8=B5=B7=E6=9F=A5=E8=AF=A2?= =?UTF-8?q?=E4=B8=94=E9=9A=90=E8=97=8F=E7=94=A8=E9=87=8F=E8=A1=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit useUsageQuery 增加 disabled 门控:关闭时自动查询不发、refresh no-op、 状态立即复位 idle(UsageFooter 对 idle 返回 null,compact/detail 均 整体隐藏);在途响应按 generation 作废且不写入模块级共享缓存, 避免关闭瞬间的失败结果在 5 分钟内重新挂载时复活。 --- src/components/ProviderList.tsx | 3 ++- src/hooks/useUsageQuery.ts | 24 ++++++++++++++++++------ 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/src/components/ProviderList.tsx b/src/components/ProviderList.tsx index 6089ddd..e3fd821 100644 --- a/src/components/ProviderList.tsx +++ b/src/components/ProviderList.tsx @@ -69,7 +69,8 @@ function ProviderCard({ agent, provider.name, provider.usageKinds, - provider.usageConfig?.autoQueryIntervalMinutes + provider.usageConfig?.autoQueryIntervalMinutes, + provider.usageConfig?.enabled === false ); const providerModels = Object.values(models).filter( (m) => m.provider === provider.name diff --git a/src/hooks/useUsageQuery.ts b/src/hooks/useUsageQuery.ts index 0b9f1db..4b4f092 100644 --- a/src/hooks/useUsageQuery.ts +++ b/src/hooks/useUsageQuery.ts @@ -62,7 +62,8 @@ export function useUsageQuery( agent: Agent, providerName: string, usageKinds?: string[], - autoIntervalMinutes?: number + autoIntervalMinutes?: number, + disabled?: boolean ): UsageQueryState { const supported = (usageKinds?.length ?? 0) > 0; // Cache key includes the agent so a Kimi Code provider and a Pi provider @@ -79,12 +80,13 @@ export function useUsageQuery( const runQuery = useCallback( async (forceRefresh: boolean) => { + if (disabled) return; const gen = ++genRef.current; setStatus("loading"); setError(undefined); const finish = (entry: CacheEntry) => { - cache.set(cacheKey, entry); if (genRef.current !== gen) return; + cache.set(cacheKey, entry); setStatus(entry.status); setData(entry.data); setError(entry.error); @@ -129,11 +131,21 @@ export function useUsageQuery( }); } }, - [agent, providerName, cacheKey] + [agent, providerName, cacheKey, disabled] ); // On mount / provider change: serve fresh cache, otherwise query once. useEffect(() => { + if (disabled) { + // Toggle back off: stop immediately and return to idle so the footer + // hides; bump gen so an in-flight response is dropped (no stale write). + genRef.current += 1; + setStatus("idle"); + setData([]); + setError(undefined); + setUpdatedAt(null); + return; + } if (!supported) return; const cached = cache.get(cacheKey); if (cached) { @@ -144,7 +156,7 @@ export function useUsageQuery( if (Date.now() - cached.updatedAt < STALE_TTL_MS) return; } void runQuery(false); - }, [supported, cacheKey, runQuery]); + }, [supported, cacheKey, runQuery, disabled]); // Ignore late responses after unmount. useEffect(() => { @@ -156,12 +168,12 @@ export function useUsageQuery( // Auto query interval — the hook is called once per provider card and both // variants read the same state, so there is no second mount to double-fire. useEffect(() => { - if (!supported) return; + if (!supported || disabled) return; const mins = autoIntervalMinutes ?? 0; if (mins <= 0) return; const id = setInterval(() => void runQuery(false), mins * 60_000); return () => clearInterval(id); - }, [supported, autoIntervalMinutes, runQuery]); + }, [supported, autoIntervalMinutes, runQuery, disabled]); return { status,