返回 DeepSeek-Reasonix
useRuntimeNotifications.ts
根目录 / desktop / frontend / src / app-runtime / useRuntimeNotifications.ts
1 import { useEffect, useRef } from "react";
2 import { useCommittedCommand } from "../lib/useCommittedCommand";
3 import { useT } from "../lib/i18n";
4 import { useToast } from "../lib/toast";
5 import type { AttentionChimeEvent } from "../lib/sound";
6 import type { NotificationOperation, createRuntimeNotifications } from "../lib/runtimeNotifications";
7
8 /** Load notification presentation off the initial render path without losing events. */
9 export function useRuntimeNotifications(activeTabId: string | undefined) {
10 const owner = useRef<ReturnType<typeof createRuntimeNotifications> | null>(null);
11 const pending = useRef<NotificationOperation[]>([]);
12 const t = useT();
13 const { showToast } = useToast();
14 const readPorts = useCommittedCommand(() => ({ activeTabId, t, showToast }));
15 const accept = useCommittedCommand((operation: NotificationOperation) => {
16 if (owner.current) owner.current.accept(operation);
17 else pending.current.push(operation);
18 });
19 useEffect(() => {
20 let live = true;
21 void import("../lib/runtimeNotifications").then(({ createRuntimeNotifications }) => {
22 if (!live) return;
23 owner.current = createRuntimeNotifications(readPorts);
24 for (const operation of pending.current.splice(0)) owner.current.accept(operation);
25 owner.current.start();
26 });
27 return () => {
28 live = false;
29 owner.current?.dispose();
30 owner.current = null;
31 pending.current = [];
32 };
33 }, [readPorts]);
34 const handleNotification = useCommittedCommand((event: AttentionChimeEvent & { err?: string }) => {
35 if (event.kind === "ask_request" || event.kind === "approval_request" || event.kind === "turn_done") accept({ event });
36 });
37 const resetLegacyAttention = useCommittedCommand((resetTabId?: string) => accept({ resetTabId }));
38 return { handleNotification, resetLegacyAttention };
39 }
40
40 lines TYPESCRIPT