返回 DeepSeek-Reasonix
useComposerInboxRefresh.ts
根目录 / desktop / frontend / src / lib / useComposerInboxRefresh.ts
1 import { useCallback, useEffect, useLayoutEffect, useRef } from "react";
2 import { app } from "./bridge";
3 import {
4 guidanceFromInboxSnapshot,
5 hydrateEmptyGuidancePreviews,
6 inboxSnapshotBelongsToScope,
7 localGuidanceFallback,
8 mergeGuidanceSnapshot,
9 } from "./composerInboxQueue";
10 import { onInboxChanged } from "./inboxEvents";
11 import type { PendingGuidance } from "../components/ComposerGuidanceShelf";
12
13 export function useComposerInboxRefresh(
14 tabId: string | undefined,
15 draftKey: string,
16 guidanceDraftKey: string,
17 inboxSessionKey: string,
18 previewKey: string,
19 retryNonce: number,
20 running: boolean,
21 applyQueue: (items: PendingGuidance[]) => void,
22 collapse: () => void,
23 bump: () => void,
24 runtimeRevision?: number,
25 ) {
26 const inboxSessionKeyRef = useRef(inboxSessionKey);
27 const appliedRevisionRef = useRef<{ scope: string; revision: number }>({ scope: inboxSessionKey, revision: -1 });
28 const clearQueue = useCallback(() => applyQueue([]), [applyQueue]);
29 useLayoutEffect(() => {
30 if (inboxSessionKeyRef.current === inboxSessionKey) return;
31 inboxSessionKeyRef.current = inboxSessionKey;
32 appliedRevisionRef.current = { scope: inboxSessionKey, revision: -1 };
33 clearQueue();
34 }, [draftKey, inboxSessionKey, clearQueue]);
35 useEffect(() => onInboxChanged((changed) => {
36 if (changed.tabId && tabId && changed.tabId !== tabId) return;
37 if (!inboxSnapshotBelongsToScope(changed.sessionPath, inboxSessionKey)) return;
38 if (changed.revision !== undefined
39 && appliedRevisionRef.current.scope === inboxSessionKey
40 && changed.revision <= appliedRevisionRef.current.revision) return;
41 bump();
42 }), [tabId, inboxSessionKey, bump]);
43 useEffect(() => {
44 if (guidanceDraftKey !== draftKey) return;
45 let live = true;
46 const fallback = localGuidanceFallback(previewKey);
47 if (typeof app.InboxSnapshot !== "function") {
48 applyQueue(fallback);
49 collapse();
50 return;
51 }
52 void app.InboxSnapshot(tabId || "").then((snap) => {
53 if (!live || !inboxSnapshotBelongsToScope(snap?.sessionPath, inboxSessionKey)) return;
54 const rawRevision = Number(snap?.revision ?? -1);
55 const revision = Number.isFinite(rawRevision) ? rawRevision : -1;
56 if (appliedRevisionRef.current.scope === inboxSessionKey && revision < appliedRevisionRef.current.revision) return;
57 appliedRevisionRef.current = { scope: inboxSessionKey, revision };
58 const durable = guidanceFromInboxSnapshot(snap);
59 applyQueue(mergeGuidanceSnapshot(durable, fallback));
60 collapse();
61 void hydrateEmptyGuidancePreviews(durable, (id) => app.ReadInboxItem(tabId || "", id)).then((hydrated) => {
62 if (live && hydrated.some((item) => item.text.trim())) {
63 applyQueue(mergeGuidanceSnapshot(hydrated, fallback));
64 }
65 });
66 }).catch(() => {
67 if (live) applyQueue(localGuidanceFallback(previewKey));
68 });
69 return () => { live = false; };
70 }, [draftKey, guidanceDraftKey, previewKey, running, tabId, retryNonce, inboxSessionKey, applyQueue, collapse, runtimeRevision]);
71 }
72
72 lines TYPESCRIPT