| ... | ... | @@ -368,6 +368,7 @@ export default function ChatView({ threadId }: ChatViewProps) { |
| 368 | 368 | const textareaRef = useRef<HTMLTextAreaElement>(null); |
| 369 | 369 | const composerCommandInputRef = useRef<HTMLInputElement>(null); |
| 370 | 370 | const composerImagesRef = useRef<ComposerImageAttachment[]>([]); |
| 371 | const sendInFlightRef = useRef(false); |
| 371 | 372 | const dragDepthRef = useRef(0); |
| 372 | 373 | const terminalOpenByThreadRef = useRef<Record<string, boolean>>({}); |
| 373 | 374 | |
| ... | ... | @@ -1391,7 +1392,7 @@ export default function ChatView({ threadId }: ChatViewProps) { |
| 1391 | 1392 | const onSend = async (e: React.SubmitEvent | React.KeyboardEvent) => { |
| 1392 | 1393 | e.preventDefault(); |
| 1393 | 1394 | const api = readNativeApi(); |
| 1394 | | if (!api || !activeThread || isSendBusy || isConnecting) return; |
| 1395 | if (!api || !activeThread || isSendBusy || isConnecting || sendInFlightRef.current) return; |
| 1395 | 1396 | const trimmed = prompt.trim(); |
| 1396 | 1397 | if (!trimmed && composerImages.length === 0) return; |
| 1397 | 1398 | if (!activeProject) return; |
| ... | ... | @@ -1415,6 +1416,9 @@ export default function ChatView({ threadId }: ChatViewProps) { |
| 1415 | 1416 | return; |
| 1416 | 1417 | } |
| 1417 | 1418 | |
| 1419 | sendInFlightRef.current = true; |
| 1420 | setSendPhase(baseBranchForWorktree ? "preparing-worktree" : "sending-turn"); |
| 1421 | |
| 1418 | 1422 | const composerImagesSnapshot = [...composerImages]; |
| 1419 | 1423 | const messageIdForSend = newMessageId(); |
| 1420 | 1424 | const messageCreatedAt = new Date().toISOString(); |
| ... | ... | @@ -1463,9 +1467,17 @@ export default function ChatView({ threadId }: ChatViewProps) { |
| 1463 | 1467 | branch: result.worktree.branch, |
| 1464 | 1468 | worktreePath: result.worktree.path, |
| 1465 | 1469 | }); |
| 1470 | // Keep local thread state in sync immediately so terminal drawer opens |
| 1471 | // with the worktree cwd/env instead of briefly using the project root. |
| 1472 | dispatch({ |
| 1473 | type: "SET_THREAD_BRANCH", |
| 1474 | threadId: threadIdForSend, |
| 1475 | branch: result.worktree.branch, |
| 1476 | worktreePath: result.worktree.path, |
| 1477 | }); |
| 1466 | 1478 | const setupScript = setupProjectScript(activeProject.scripts); |
| 1467 | 1479 | if (setupScript) { |
| 1468 | | void runProjectScript(setupScript, { |
| 1480 | await runProjectScript(setupScript, { |
| 1469 | 1481 | cwd: result.worktree.path, |
| 1470 | 1482 | worktreePath: result.worktree.path, |
| 1471 | 1483 | rememberAsLastInvoked: false, |
| ... | ... | @@ -1544,6 +1556,7 @@ export default function ChatView({ threadId }: ChatViewProps) { |
| 1544 | 1556 | err instanceof Error ? err.message : "Failed to send message.", |
| 1545 | 1557 | ); |
| 1546 | 1558 | } finally { |
| 1559 | sendInFlightRef.current = false; |
| 1547 | 1560 | setSendPhase("idle"); |
| 1548 | 1561 | } |
| 1549 | 1562 | }; |