mirror of
https://github.com/openai/codex.git
synced 2026-11-05 20:10:33 +00:00
Preserve transcript interaction when switching panes with arrow keys (#59472)
## Why Directional pane switching cleared the parent conversation's transcript selection or Find state, so returning to it interrupted the interaction. ## What changed Route left/right pane switches through the existing conversation toggle to park and restore each pane's transcript interaction. Explicitly focusing the main composer still clears transcript interaction. ## Testing Extend the side-conversation test to cover restoring selections, Find text and caret position, and composer input after scrolling. Add a snapshot verifying that Find remains editable after switching away and back. GitOrigin-RevId: 172f9be0df15517fbfe7f3773b63cbd1cef1cc77
This commit is contained in:
@@ -40,12 +40,16 @@ impl App {
|
||||
&& !on_child
|
||||
&& (self.transcript_view.has_active_interaction()
|
||||
|| self.backtrack.overlay_preview_active);
|
||||
let result = if main || (left && on_child) {
|
||||
let result = if main {
|
||||
self.focus_main_composer(tui, app_server).await
|
||||
} else if (sidebar || right)
|
||||
} else if (left && on_child)
|
||||
|| (right && !on_child && child.is_some_and(|id| self.side_threads[&id].pane_open))
|
||||
{
|
||||
// Switching threads parks and restores each pane's transcript interaction.
|
||||
self.toggle_side_conversation(tui, app_server).await
|
||||
} else if sidebar
|
||||
&& !on_child
|
||||
&& let Some(child) = child
|
||||
&& (sidebar || self.side_threads[&child].pane_open)
|
||||
{
|
||||
let result = self.select_agent_thread(tui, app_server, child).await;
|
||||
if result.is_ok() && self.current_displayed_thread_id() == Some(child) {
|
||||
|
||||
@@ -3833,10 +3833,41 @@ async fn handle_start_side_seeds_navigation_before_thread_started() -> Result<()
|
||||
selected
|
||||
);
|
||||
app.transcript_view.end_select_mode();
|
||||
// Ctrl-/ preserves interaction, so it exposes whether right actually cleaned up the parent.
|
||||
keys!(toggle);
|
||||
keys!(prefix, KeyCode::Left.into());
|
||||
assert_eq!(app.current_displayed_thread_id(), Some(parent_thread_id));
|
||||
assert!(!app.transcript_view.has_active_interaction());
|
||||
assert!(app.transcript_view.is_select_mode());
|
||||
assert_eq!(
|
||||
app.transcript_view.selected_text(&app.transcript_cells),
|
||||
parent_text
|
||||
);
|
||||
|
||||
keys!(prefix, main);
|
||||
app.transcript_view.begin_search();
|
||||
assert!(app.transcript_view.paste_search(parent_row));
|
||||
keys!(KeyCode::Left.into());
|
||||
let find = app.transcript_view.search_footer(size.width).unwrap();
|
||||
keys!(prefix, KeyCode::Right.into());
|
||||
keys!(prefix, KeyCode::Left.into());
|
||||
assert_eq!(app.transcript_view.search_footer(size.width), Some(find));
|
||||
keys!(KeyCode::Char('x').into());
|
||||
let frame = side_frame(&mut app, &mut tui, size)?;
|
||||
assert_app_snapshot!(
|
||||
"direction_restores_parent_find",
|
||||
frame.lines().find(|row| row.contains("Find:")).unwrap()
|
||||
);
|
||||
|
||||
// Explicit composer focus ends Find. Scrolling alone keeps the composer active.
|
||||
keys!(prefix, main);
|
||||
read_side_history(&mut app, &mut tui, "parent")?;
|
||||
keys!(prefix, KeyCode::Right.into());
|
||||
keys!(prefix, KeyCode::Left.into());
|
||||
assert!(side_frame(&mut app, &mut tui, size)?.contains(parent_row));
|
||||
// End flushes the composer's pending paste-burst character.
|
||||
keys!(KeyCode::Char('!').into(), KeyCode::End.into());
|
||||
assert_eq!(
|
||||
app.chat_widget.composer_text_with_pending(),
|
||||
"parent draft-!"
|
||||
);
|
||||
keys!(toggle);
|
||||
|
||||
read_side_history(&mut app, &mut tui, "child")?;
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
source: tui/src/app/tests.rs
|
||||
expression: "frame.lines().find(|row| row.contains(\"Find:\")).unwrap()"
|
||||
---
|
||||
Find: parent-2x4 │ GPT-6.1-Sol default
|
||||
Reference in New Issue
Block a user