返回 DeepSeek-Reasonix
useAutomationNavigation.ts
根目录 / desktop / frontend / src / app-runtime / useAutomationNavigation.ts
1 import { useLayoutEffect, useRef } from "react";
2 import { useAppNavigationStore } from "../store/appNavigation";
3 import { useCommittedCommand } from "../lib/useCommittedCommand";
4 import { createSubscriptionScope } from "../lib/subscriptionScope";
5 import type { DesktopNavigationIntent } from "./desktopNavigationOwner";
6
7 async function finishAutomationNavigation(input: {
8 intent: number; request: DesktopNavigationIntent;
9 enqueue(request: DesktopNavigationIntent, intent: number): Promise<void>;
10 finish(intent: number): void;
11 }) {
12 try { await input.enqueue(input.request, input.intent); }
13 finally { input.finish(input.intent); }
14 }
15
16 /** The management page owns its link until the navigation owner accepts it. */
17 export function useAutomationNavigation(input: {
18 noteIntent(): number;
19 enqueue(intent: DesktopNavigationIntent, seq: number): Promise<void>;
20 }) {
21 const pending = useRef<{ intent: number; generation: number } | null>(null);
22 const invalidate = useCommittedCommand(() => {
23 if (!pending.current) return;
24 pending.current = null;
25 input.noteIntent();
26 });
27 useLayoutEffect(() => {
28 const scope = createSubscriptionScope();
29 scope.listen(listener => useAppNavigationStore.subscribe((next, previous) => {
30 if (next.generation !== previous.generation) listener();
31 }), invalidate);
32 return () => { pending.current = null; scope.dispose(); };
33 }, [invalidate]);
34 const finish = useCommittedCommand((intent: number) => {
35 if (pending.current?.intent === intent) pending.current = null;
36 });
37 const openAutomationTopic = useCommittedCommand((scope: string, workspaceRoot: string, topicId: string) => {
38 const intent = input.noteIntent();
39 pending.current = { intent, generation: useAppNavigationStore.getState().generation };
40 return finishAutomationNavigation({ intent, request: { kind: "topic", scope, workspaceRoot, topicId }, enqueue: input.enqueue, finish });
41 });
42 const topicAccepted = useCommittedCommand((intent: number) => {
43 const link = pending.current;
44 if (!link || link.intent !== intent) return;
45 pending.current = null;
46 useAppNavigationStore.getState().returnFromAutomationLink(link.generation);
47 });
48 return { openAutomationTopic, topicAccepted };
49 }
50
50 lines TYPESCRIPT