返回 DeepSeek-Reasonix
useNavigationIntentFence.ts
根目录 / desktop / frontend / src / lib / useNavigationIntentFence.ts
1 import { useCallback, useRef } from "react";
2 import { app } from "./bridge";
3
4 interface NavigationIntentRegistration {
5 token: string;
6 registered: Promise<string>;
7 }
8
9 let navigationIntentRegistrationTail: Promise<void> = Promise.resolve();
10 let navigationIntentCounter = 0;
11
12 function navigationIntentToken(hint: string): string {
13 const nonce = new Uint32Array(4);
14 globalThis.crypto.getRandomValues(nonce);
15 return `nav-${hint}-${(++navigationIntentCounter).toString(36)}-${Array.from(nonce, (value) => value.toString(36)).join("-")}`;
16 }
17
18 function scheduleNavigationIntent(hint: string): NavigationIntentRegistration {
19 const token = navigationIntentToken(hint);
20 const binding = app.RegisterNavigationIntent;
21 const registered = navigationIntentRegistrationTail.then(async () => {
22 if (typeof binding !== "function") throw new Error("navigation intent binding is unavailable");
23 await binding.call(app, token);
24 return token;
25 });
26 navigationIntentRegistrationTail = registered.then(() => undefined, () => undefined);
27 return { token, registered };
28 }
29
30 export function publishNavigationIntent(hint = "direct"): Promise<string> {
31 return scheduleNavigationIntent(hint).registered;
32 }
33
34 export function useNavigationIntentFence() {
35 const registrationsRef = useRef(new Map<number, NavigationIntentRegistration>());
36 const registerNavigationIntent = useCallback((seq: number) => {
37 const scheduled = scheduleNavigationIntent(seq.toString(36));
38 const registration: NavigationIntentRegistration = {
39 token: scheduled.token,
40 registered: scheduled.registered.catch(() => ""),
41 };
42 registrationsRef.current.clear();
43 registrationsRef.current.set(seq, registration);
44 }, []);
45 const registeredNavigationIntent = useCallback(async (seq: number): Promise<string> => {
46 const registration = registrationsRef.current.get(seq);
47 if (!registration) return "";
48 const token = await registration.registered;
49 if (registrationsRef.current.get(seq)?.token !== token) return "";
50 return token;
51 }, []);
52 return { registerNavigationIntent, registeredNavigationIntent };
53 }
54
54 lines TYPESCRIPT