History

Fix send state set outside try-finally and remove redundant setSendPhase call

Move sendInFlightRef.current and setSendPhase assignments inside the try block so that the finally block always resets them, preventing permanent send-lock if code between the assignments and the try block throws. Also removes the redundant setSendPhase('preparing-worktree') call that was already set identically before the try block.

Cursor Agent committed 8 months ago

Commit ba4545c1 parent 7b0ae431 file · +33 −34Browse files

Unified · Split

apps/web/src/components/ChatView.tsx+33−34
@@ -1416,44 +1416,43 @@ export default function ChatView({ threadId }: ChatViewProps) { · 1415 unmodified lines
1416 return;1416 return;
1417 }1417 }
1418 1418
1419 sendInFlightRef.current = true;
1420 setSendPhase(baseBranchForWorktree ? "preparing-worktree" : "sending-turn");
1421
1422 const composerImagesSnapshot = [...composerImages];
1423 const messageIdForSend = newMessageId();
1424 const messageCreatedAt = new Date().toISOString();
1425 const optimisticAttachments = composerImagesSnapshot.map((image) => ({
1426 type: "image" as const,
1427 id: image.id,
1428 name: image.name,
1429 mimeType: image.mimeType,
1430 sizeBytes: image.sizeBytes,
1431 previewUrl: image.previewUrl,
1432 }));
1433 setOptimisticUserMessages((existing) => [
1434 ...existing,
1435 {
1436 id: messageIdForSend,
1437 role: "user",
1438 text: trimmed,
1439 ...(optimisticAttachments.length > 0 ? { attachments: optimisticAttachments } : {}),
1440 createdAt: messageCreatedAt,
1441 streaming: false,
1442 },
1443 ]);
1444
1445 setThreadError(threadIdForSend, null);
1446 promptRef.current = "";
1447 setPrompt("");
1448 setComposerImages([]);
1449 setComposerCursor(0);
1450 setComposerHighlightedItemId(null);
1451
1452 let attemptedTurnStart = false;1419 let attemptedTurnStart = false;
1453 try {1420 try {
1421 sendInFlightRef.current = true;
1422 setSendPhase(baseBranchForWorktree ? "preparing-worktree" : "sending-turn");
1423
1424 const composerImagesSnapshot = [...composerImages];
1425 const messageIdForSend = newMessageId();
1426 const messageCreatedAt = new Date().toISOString();
1427 const optimisticAttachments = composerImagesSnapshot.map((image) => ({
1428 type: "image" as const,
1429 id: image.id,
1430 name: image.name,
1431 mimeType: image.mimeType,
1432 sizeBytes: image.sizeBytes,
1433 previewUrl: image.previewUrl,
1434 }));
1435 setOptimisticUserMessages((existing) => [
1436 ...existing,
1437 {
1438 id: messageIdForSend,
1439 role: "user",
1440 text: trimmed,
1441 ...(optimisticAttachments.length > 0 ? { attachments: optimisticAttachments } : {}),
1442 createdAt: messageCreatedAt,
1443 streaming: false,
1444 },
1445 ]);
1446
1447 setThreadError(threadIdForSend, null);
1448 promptRef.current = "";
1449 setPrompt("");
1450 setComposerImages([]);
1451 setComposerCursor(0);
1452 setComposerHighlightedItemId(null);
1453
1454 // On first message: lock in branch + create worktree if needed.1454 // On first message: lock in branch + create worktree if needed.
1455 if (baseBranchForWorktree) {1455 if (baseBranchForWorktree) {
1456 setSendPhase("preparing-worktree");
1457 const newBranch = `codething/${crypto.randomUUID().slice(0, 8)}`;1456 const newBranch = `codething/${crypto.randomUUID().slice(0, 8)}`;
1458 const result = await createWorktreeMutation.mutateAsync({1457 const result = await createWorktreeMutation.mutateAsync({
1459 cwd: activeProject.cwd,1458 cwd: activeProject.cwd,