返回 DeepSeek-Reasonix
useRuntimeStatus.ts
根目录 / desktop / frontend / src / app-runtime / useRuntimeStatus.ts
1 import { useLayoutEffect, useRef, useState } from "react";
2 import { app } from "../lib/bridge";
3 import { useCommittedCommand } from "../lib/useCommittedCommand";
4 import type { BackgroundRuntimeView, WorkspaceConflictView } from "../lib/types";
5 import { createPollingOwner, type PollClock } from "./pollingOwner";
6 import { trackAppOperation } from "./appLifecycleProbe";
7
8 const browserClock: PollClock = {
9 setTimeout: (callback, delay) => window.setTimeout(callback, delay),
10 clearTimeout: handle => window.clearTimeout(handle as number),
11 };
12 export function useRuntimeStatus(input: { tabId?: string; sessionKey: string; running: boolean }, clock: PollClock = browserClock) {
13 const [backgroundRuntimes, setBackgroundRuntimes] = useState<BackgroundRuntimeView[]>([]);
14 const [conflict, setConflict] = useState<{ key: string; value: WorkspaceConflictView | null } | null>(null);
15 const background = useRef<ReturnType<typeof createPollingOwner<BackgroundRuntimeView[]>> | null>(null);
16 const refreshBackgroundRuntimes = useCommittedCommand(() => background.current?.refresh() ?? Promise.resolve());
17 useLayoutEffect(() => {
18 const owner = createPollingOwner({ target: { kind: "application" }, periodMs: 1000, clock,
19 read: app.BackgroundRuntimes, publish: setBackgroundRuntimes, failed: () => {},
20 }, trackAppOperation);
21 background.current = owner;
22 void owner.refresh();
23 return () => { owner.dispose(); if (background.current === owner) background.current = null; };
24 }, [clock]);
25 const { tabId, sessionKey, running } = input;
26 const key = JSON.stringify([tabId, sessionKey]);
27 const setWorkspaceConflict = useCommittedCommand((value: WorkspaceConflictView | null) => setConflict(value ? { key, value } : null));
28 useLayoutEffect(() => {
29 setConflict(null);
30 if (!tabId || !running) return;
31 const owner = createPollingOwner({ target: { kind: "session", tabId, sessionKey }, periodMs: 500, clock,
32 read: () => app.WorkspaceConflictForTab(tabId),
33 publish: value => setConflict({ key, value: value.state === "none" ? null : value }),
34 failed: () => setConflict({ key, value: null }),
35 }, trackAppOperation);
36 void owner.refresh();
37 return () => owner.dispose();
38 }, [clock, key, running, sessionKey, tabId]);
39 return { backgroundRuntimes, refreshBackgroundRuntimes, setWorkspaceConflict, workspaceConflict: conflict?.key === key ? conflict.value : null };
40 }
41
41 lines TYPESCRIPT