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
14161416 return;
14171417 }
14181418
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−
14521419 let attemptedTurnStart = false;
14531420 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+
14541454 // On first message: lock in branch + create worktree if needed.
14551455 if (baseBranchForWorktree) {
1456− setSendPhase("preparing-worktree");
14571456 const newBranch = `codething/${crypto.randomUUID().slice(0, 8)}`;
14581457 const result = await createWorktreeMutation.mutateAsync({
14591458 cwd: activeProject.cwd,