Bug fix: ignore Enter on empty input to avoid queuing blank messages (#3047)
## Summary
Pressing Enter with an empty composer was treated as a submission, which
queued a blank message while a task was running. This PR suppresses
submission when there is no text and no attachments.
## Root Cause
- ChatComposer returned Submitted even when the trimmed text was empty.
ChatWidget then queued it during a running task, leading to an empty
item appearing in the queued list and being popped later with no effect.
## Changes
- ChatComposer Enter handling: if trimmed text is empty and there are no
attached images, return None instead of Submitted.
- No changes to ChatWidget; behavior naturally stops queuing blanks at
the source.
## Code Paths
- Modified: `tui/src/bottom_pane/chat_composer.rs`
- Tests added:
- `tui/src/bottom_pane/chat_composer.rs`: `empty_enter_returns_none`
- `tui/src/chatwidget/tests.rs`:
`empty_enter_during_task_does_not_queue`
## Result
### Before
https://github.com/user-attachments/assets/a40e2f6d-42ba-4a82-928b-8f5458f5884d
### After
https://github.com/user-attachments/assets/958900b7-a566-44fc-b16c-b80380739c92
This commit is contained in:
@@ -837,7 +837,12 @@ impl ChatComposer {
|
|||||||
}
|
}
|
||||||
self.pending_pastes.clear();
|
self.pending_pastes.clear();
|
||||||
|
|
||||||
|
// If there is neither text nor attachments, suppress submission entirely.
|
||||||
|
let has_attachments = !self.attached_images.is_empty();
|
||||||
text = text.trim().to_string();
|
text = text.trim().to_string();
|
||||||
|
if text.is_empty() && !has_attachments {
|
||||||
|
return (InputResult::None, true);
|
||||||
|
}
|
||||||
if !text.is_empty() {
|
if !text.is_empty() {
|
||||||
self.history.record_local_submission(&text);
|
self.history.record_local_submission(&text);
|
||||||
}
|
}
|
||||||
@@ -1520,6 +1525,33 @@ mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn empty_enter_returns_none() {
|
||||||
|
use crossterm::event::KeyCode;
|
||||||
|
use crossterm::event::KeyEvent;
|
||||||
|
use crossterm::event::KeyModifiers;
|
||||||
|
|
||||||
|
let (tx, _rx) = unbounded_channel::<AppEvent>();
|
||||||
|
let sender = AppEventSender::new(tx);
|
||||||
|
let mut composer = ChatComposer::new(
|
||||||
|
true,
|
||||||
|
sender,
|
||||||
|
false,
|
||||||
|
"Ask Codex to do anything".to_string(),
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Ensure composer is empty and press Enter.
|
||||||
|
assert!(composer.textarea.text().is_empty());
|
||||||
|
let (result, _needs_redraw) =
|
||||||
|
composer.handle_key_event(KeyEvent::new(KeyCode::Enter, KeyModifiers::NONE));
|
||||||
|
|
||||||
|
match result {
|
||||||
|
InputResult::None => {}
|
||||||
|
other => panic!("expected None for empty enter, got: {other:?}"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn handle_paste_large_uses_placeholder_and_replaces_on_submit() {
|
fn handle_paste_large_uses_placeholder_and_replaces_on_submit() {
|
||||||
use crossterm::event::KeyCode;
|
use crossterm::event::KeyCode;
|
||||||
|
|||||||
@@ -259,6 +259,20 @@ fn open_fixture(name: &str) -> std::fs::File {
|
|||||||
File::open(name).expect("open fixture file")
|
File::open(name).expect("open fixture file")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn empty_enter_during_task_does_not_queue() {
|
||||||
|
let (mut chat, _rx, _op_rx) = make_chatwidget_manual();
|
||||||
|
|
||||||
|
// Simulate running task so submissions would normally be queued.
|
||||||
|
chat.bottom_pane.set_task_running(true);
|
||||||
|
|
||||||
|
// Press Enter with an empty composer.
|
||||||
|
chat.handle_key_event(KeyEvent::new(KeyCode::Enter, KeyModifiers::NONE));
|
||||||
|
|
||||||
|
// Ensure nothing was queued.
|
||||||
|
assert!(chat.queued_user_messages.is_empty());
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn alt_up_edits_most_recent_queued_message() {
|
fn alt_up_edits_most_recent_queued_message() {
|
||||||
let (mut chat, _rx, _op_rx) = make_chatwidget_manual();
|
let (mut chat, _rx, _op_rx) = make_chatwidget_manual();
|
||||||
|
|||||||
Reference in New Issue
Block a user