返回 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 const openedPathRef = useRef("");
24
25 useEffect(() => {
26 let cancelled = false;
27 void app.PickBlankProjectParent().then((parentDirectory) => {
28 if (cancelled) return;
29 if (parentDirectory) setDraft({ parentDirectory });
30 else onCloseRef.current();
31 }).catch((err) => {
32 if (cancelled) return;
33 showToastRef.current(err instanceof Error ? err.message : String(err), "error");
34 onCloseRef.current();
35 });
36 return () => { cancelled = true; };
37 }, []);
38
39 const submit = async (projectName: string) => {
40 if (!draft || busyRef.current) return;
41 busyRef.current = true;
42 setBusy(true);
43 setDraft((current) => current ? { ...current, error: undefined } : current);
44 let createdPath = draft.createdPath ?? "";
45 try {
46 if (!createdPath) {
47 createdPath = await app.CreateBlankProject(draft.parentDirectory, projectName);
48 setDraft((current) => current ? { ...current, createdPath } : current);
49 }
50 if (openedPathRef.current !== createdPath) {
51 await onOpenProject(createdPath);
52 openedPathRef.current = createdPath;
53 }
54 await onRefresh();
55 busyRef.current = false;
56 setBusy(false);
57 onCloseRef.current();
58 } catch (err) {
59 const message = err instanceof Error ? err.message : String(err);
60 setDraft((current) => current ? { ...current, createdPath: createdPath || current.createdPath, error: message } : current);
61 } finally {
62 if (busyRef.current) {
63 busyRef.current = false;
64 setBusy(false);
65 }
66 }
67 };
68
69 if (!draft) return null;
70 return (
71 <BlankProjectDialog
72 parentDirectory={draft.parentDirectory}
73 createdPath={draft.createdPath}
74 busy={busy}
75 error={draft.error}
76 onSubmit={(name) => void submit(name)}
77 onCancel={() => {
78 if (!busyRef.current) onCloseRef.current();
79 }}
80 />
81 );
82 }
83
83 lines Plain Text