Skip to content

Commit 8f5cd5e

Browse files
authored
🤖 Fix UI freeze when sending message in SSH workspaces (#450)
The UI froze for ~1s when sending messages in SSH workspaces because the frontend awaited the entire IPC call, including remote temp directory creation. ## Solution Changed `ChatInput` to clear input/images immediately before the IPC call instead of after it succeeds. This makes the UI responsive while the backend handles SSH operations asynchronously. On error, the previous state is restored so users can retry. ## Testing Tested locally with SSH workspace - input clears immediately and chat remains responsive during message send. _Generated with `cmux`_
1 parent 141f03b commit 8f5cd5e

File tree

1 file changed

+15
-8
lines changed

1 file changed

+15
-8
lines changed

src/components/ChatInput.tsx

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -528,6 +528,9 @@ export const ChatInput: React.FC<ChatInputProps> = ({
528528
// Regular message - send directly via API
529529
setIsSending(true);
530530

531+
// Save current state for restoration on error
532+
const previousImageAttachments = [...imageAttachments];
533+
531534
try {
532535
// Prepare image parts if any
533536
const imageParts = imageAttachments.map((img, index) => {
@@ -583,6 +586,15 @@ export const ChatInput: React.FC<ChatInputProps> = ({
583586
}
584587
}
585588

589+
// Clear input and images immediately for responsive UI
590+
// These will be restored if the send operation fails
591+
setInput("");
592+
setImageAttachments([]);
593+
// Reset textarea height
594+
if (inputRef.current) {
595+
inputRef.current.style.height = "36px";
596+
}
597+
586598
const result = await window.api.workspace.sendMessage(workspaceId, actualMessageText, {
587599
...sendMessageOptions,
588600
...compactionOptions,
@@ -596,19 +608,13 @@ export const ChatInput: React.FC<ChatInputProps> = ({
596608
console.error("Failed to send message:", result.error);
597609
// Show error using enhanced toast
598610
setToast(createErrorToast(result.error));
599-
// Restore input on error so user can try again
611+
// Restore input and images on error so user can try again
600612
setInput(messageText);
613+
setImageAttachments(previousImageAttachments);
601614
} else {
602615
// Track telemetry for successful message send
603616
telemetry.messageSent(sendMessageOptions.model, mode, actualMessageText.length);
604617

605-
// Success - clear input and images
606-
setInput("");
607-
setImageAttachments([]);
608-
// Reset textarea height
609-
if (inputRef.current) {
610-
inputRef.current.style.height = "36px";
611-
}
612618
// Exit editing mode if we were editing
613619
if (editingMessage && onCancelEdit) {
614620
onCancelEdit();
@@ -625,6 +631,7 @@ export const ChatInput: React.FC<ChatInputProps> = ({
625631
})
626632
);
627633
setInput(messageText);
634+
setImageAttachments(previousImageAttachments);
628635
} finally {
629636
setIsSending(false);
630637
}

0 commit comments

Comments
 (0)