返回 DeepSeek-Reasonix
BlankProjectFlow.tsx
根目录 / desktop / frontend / src / components / BlankProjectFlow.tsx
1 import { useEffect, useRef, useState } from "react";
2 import { app } from "../lib/bridge";
3 import { useToast } from "../lib/toast";
4 import { BlankProjectDialog } from "./BlankProjectDialog";
5
6 export function BlankProjectFlow({
7 onOpenProject,
8 onRefresh,
9 onClose,
10 }: {
11 onOpenProject: (path: string) => Promise<void>;
12 onRefresh: () => Promise<void>;
13 onClose: () => void;
14 }) {
15 const { showToast } = useToast();
16 const onCloseRef = useRef(onClose);
17 const showToastRef = useRef(showToast);
18 onCloseRef.current = onClose;
19 showToastRef.current = showToast;
20 const [draft, setDraft] = useState<{ parentDirectory: string; createdPath?: string; error?: string } | null>(null);
21 const [busy, setBusy] = useState(false);
22 const busyRef = useRef(false);
23
24 useEffect(() => {
25 let cancelled = false;
26 void app.PickBlankProjectParent().then((parentDirectory) => {
27 if (cancelled) return;
28 if (parentDirectory) setDraft({ parentDirectory });
29 else onCloseRef.current();
30 }).catch((err) => {
31 if (cancelled) return;
32 showToastRef.current(err instanceof Error ? err.message : String(err), "error");
33 onCloseRef.current();
34 });
35 return () => { cancelled = true; };
36 }, []);
37
38 const submit = async (projectName: string) => {
39 if (!draft || busyRef.current) return;
40 busyRef.current = true;
41 setBusy(true);
42 setDraft((current) => current ? { ...current, error: undefined } : current);
43 let createdPath = draft.createdPath ?? "";
44 try {
45 if (!createdPath) {
46 createdPath = await app.CreateBlankProject(draft.parentDirectory, projectName);
47 setDraft((current) => current ? { ...current, createdPath } : current);
48 }
49 await onOpenProject(createdPath);
50 await onRefresh();
51 busyRef.current = false;
52 setBusy(false);
53 onCloseRef.current();
54 } catch (err) {
55 const message = err instanceof Error ? err.message : String(err);
56 setDraft((current) => current ? { ...current, createdPath: createdPath || current.createdPath, error: message } : current);
57 } finally {
58 if (busyRef.current) {
59 busyRef.current = false;
60 setBusy(false);
61 }
62 }
63 };
64
65 if (!draft) return null;
66 return (
67 <BlankProjectDialog
68 parentDirectory={draft.parentDirectory}
69 createdPath={draft.createdPath}
70 busy={busy}
71 error={draft.error}
72 onSubmit={(name) => void submit(name)}
73 onCancel={() => {
74 if (!busyRef.current) onCloseRef.current();
75 }}
76 />
77 );
78 }
79
79 lines Plain Text