返回 DeepSeek-Reasonix
useContextPanelSnapshot.ts
根目录 / desktop / frontend / src / lib / useContextPanelSnapshot.ts
1 import { useCallback, useEffect, useRef, useState } from "react";
2 import { app } from "./bridge";
3 import { invalidateSharedQuery } from "./queryCoalesce";
4 import type { ContextPanelInfo } from "./types";
5
6 // Overview snapshots have one owner and a trailing refresh: a burst's final
7 // usage event must eventually reach the panel even if no further event arrives.
8 export function useContextPanelSnapshot(tabId: string | undefined, sessionGen: number | undefined,
9 refreshKey: number | undefined, usageKey: string, usageSeq: number | undefined) {
10 const [snapshot, setSnapshot] = useState<{ tabId: string; sessionGen?: number; info: ContextPanelInfo }>();
11 const requestSeq = useRef(0);
12 const lastRefreshTime = useRef(0);
13 const timer = useRef<ReturnType<typeof setTimeout> | undefined>(undefined);
14 const refresh = useCallback(async () => {
15 if (!tabId) return;
16 clearTimeout(timer.current);
17 timer.current = undefined;
18 const seq = ++requestSeq.current;
19 lastRefreshTime.current = Date.now();
20 // A usage/session boundary can change data inside the bridge's 200ms
21 // coalescing window. A new request must not adopt the previous snapshot.
22 invalidateSharedQuery("ContextPanel", [tabId]);
23 try {
24 const info = await app.ContextPanel(tabId);
25 if (requestSeq.current === seq) setSnapshot({ tabId, sessionGen, info });
26 } catch {
27 /* Keep the last same-session snapshot while the bridge is unavailable. */
28 }
29 }, [tabId, sessionGen]);
30
31 useEffect(() => {
32 void refresh();
33 return () => {
34 requestSeq.current++;
35 clearTimeout(timer.current);
36 timer.current = undefined;
37 };
38 }, [refresh, refreshKey]);
39
40 useEffect(() => {
41 if (!usageKey && !usageSeq) return;
42 const delay = Math.max(0, 1000 - (Date.now() - lastRefreshTime.current));
43 timer.current = setTimeout(() => { void refresh(); }, delay);
44 return () => {
45 clearTimeout(timer.current);
46 timer.current = undefined;
47 };
48 }, [usageKey, usageSeq, refresh]);
49
50 return tabId && snapshot?.tabId === tabId && snapshot.sessionGen === sessionGen ? snapshot.info : null;
51 }
52
52 lines TYPESCRIPT