fix(tui): y copies the whole queued prompt; a finished queue edit refocuses the composer

y copied the truncated display row. Saving or discarding a row edit left focus on
the queue pane, so the next Enter re-opened the edit instead of sending.
This commit is contained in:
雷电芽衣 committed 2026-09-29 13:43:56 -04:00
1 parent b840fff80c
commit 0e063e5b02
2 files changed
+56 -9

No files matched your search

+45 -9
View File
@@ -106,8 +106,16 @@ impl AgentView {
return Some(false);
}
// Clean edit — silently exit editing mode.
// The exit cleared the overlay flip; restore it.
self.exit_editing_mode();
self.active_pane = target;
self.set_active_pane(target, true);
match target {
AgentPane::Queue => self.queue.overlay.focused = true,
AgentPane::Todo => self.todo.overlay.focused = true,
AgentPane::Tasks => self.tasks.overlay.focused = true,
AgentPane::Catalog => self.catalog.overlay.focused = true,
_ => {}
}
return Some(true);
}
None
@@ -487,7 +495,7 @@ impl AgentView {
self.show_toast("Queued prompt is no longer in the queue");
}
/// Exit editing mode: restore stashed text, clear mode, focus queue pane.
/// Exit editing mode: restore stashed text, clear mode, focus the composer.
/// No-op unless `EditingQueued`.
///
/// Always resets `prompt_input_mode` to `Normal` so it doesn't leak
@@ -513,13 +521,8 @@ impl AgentView {
if matches!(self.active_modal, Some(ActiveModal::EditConfirm { .. })) {
self.active_modal = None;
}
// Return focus to queue pane (if still visible).
// Force=true: we just cleared editing mode, no lock to check.
if self.queue.is_visible() {
self.set_active_pane(AgentPane::Queue, true);
} else {
self.set_active_pane(AgentPane::Scrollback, true);
}
// Queue focus would make the next Enter re-open the edit.
self.set_active_pane(AgentPane::Prompt, true);
}
}
@@ -554,6 +557,39 @@ mod tests {
KeyEvent::new(KeyCode::Enter, KeyModifiers::NONE)
}
fn enter_edit_local_row() -> AgentView {
let mut agent = make_running_agent();
let registry = non_vscode_registry();
let ids = agent.queue.entry_ids();
agent.queue.list_state.select_by_id(ids[1]);
let _ = agent.handle_queue_key(&edit_key(), &registry);
agent
}
#[test]
fn save_returns_focus_to_the_composer() {
let mut agent = enter_edit_local_row();
agent.prompt.set_text("local one EDITED");
let _ = agent.handle_prompt_key_for_test(&enter_key());
assert_eq!(agent.active_pane, AgentPane::Prompt);
}
#[test]
fn discard_returns_focus_to_the_composer() {
let mut agent = enter_edit_local_row();
let _ = agent.handle_prompt_key_for_test(&KeyEvent::new(KeyCode::Esc, KeyModifiers::NONE));
assert_eq!(agent.active_pane, AgentPane::Prompt);
}
#[test]
fn toggle_queue_pane_with_clean_edit_lands_focused_on_the_queue() {
let mut agent = enter_edit_local_row();
agent.toggle_queue_pane();
assert!(matches!(agent.prompt_mode, PromptMode::Normal));
assert_eq!(agent.active_pane, AgentPane::Queue);
assert!(agent.queue.overlay.focused);
}
fn attach_image_to_local_row(agent: &mut AgentView) {
let mut image = test_pasted_image();
image.display_number = 1;
@@ -322,6 +322,10 @@ impl ListItem for QueuedPromptEntry {
fn search_text(&self) -> &str {
&self.text
}
fn copy_text(&self) -> String {
self.text.clone()
}
}
use crossterm::event::{KeyCode, KeyEvent, KeyModifiers, MouseEventKind};
@@ -999,6 +1003,13 @@ mod tests {
QueuedPrompt::plain(id, text, QueueEntryKind::Prompt)
}
#[test]
fn y_copies_the_full_multiline_prompt_not_the_display_row() {
let text = "first line of a long prompt\nsecond line\nthird line";
let entry = QueuedPromptEntry::new(&local_prompt(1, text), 1);
assert_eq!(ListItem::copy_text(&entry), text);
}
#[test]
fn reset_auto_show_edge_allows_requeue_after_external_hide() {
let mut pane = QueuePane::new();