Improve UI spacing for queued messages (#9162)
Despite good spacing between queued messages and assistant message text: <img width="462" height="322" alt="Screenshot 2026-01-12 at 4 54 50 PM" src="https://github.com/user-attachments/assets/e8b46252-0b33-40d2-b431-cb73b9a3bd2e" /> Codex has confusing spacing between queued messages and shimmering status text (making the queued message seem like a sub-item of the shimmering status text) <img width="615" height="217" alt="Screenshot 2026-01-12 at 4 54 18 PM" src="https://github.com/user-attachments/assets/ee5e6095-8fe9-4863-88d2-10472cab8bd6" /> This PR changes the spacing between the queued message(s) and shimmering status text to make it less confusing: <img width="440" height="240" alt="Screenshot 2026-01-13 at 11 20 36 AM" src="https://github.com/user-attachments/assets/02dcc690-cbe9-4943-87de-c7300ef51120" /> While working on the status/queued spacing change, we noticed two paste‑burst tests were timing‑sensitive and could fail on slower CI. We added a small test‑only helper to keep the paste‑burst state active and refreshed during these tests. This removes dependence on tight timing and makes the tests deterministic without affecting runtime behavior.
This commit is contained in:
parent
ca23b0da5b
commit
64678f895a
13 changed files with 176 additions and 13 deletions
|
|
@ -701,11 +701,14 @@ impl BottomPane {
|
|||
if !self.unified_exec_footer.is_empty() {
|
||||
flex.push(0, RenderableItem::Borrowed(&self.unified_exec_footer));
|
||||
}
|
||||
let has_queued_messages = !self.queued_user_messages.messages.is_empty();
|
||||
let has_status_or_footer =
|
||||
self.status.is_some() || !self.unified_exec_footer.is_empty();
|
||||
if has_queued_messages && has_status_or_footer {
|
||||
flex.push(0, RenderableItem::Owned("".into()));
|
||||
}
|
||||
flex.push(1, RenderableItem::Borrowed(&self.queued_user_messages));
|
||||
if self.status.is_some()
|
||||
|| !self.unified_exec_footer.is_empty()
|
||||
|| !self.queued_user_messages.messages.is_empty()
|
||||
{
|
||||
if !has_queued_messages && has_status_or_footer {
|
||||
flex.push(0, RenderableItem::Owned("".into()));
|
||||
}
|
||||
let mut flex2 = FlexRenderable::new();
|
||||
|
|
@ -951,6 +954,60 @@ mod tests {
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn status_only_snapshot() {
|
||||
let (tx_raw, _rx) = unbounded_channel::<AppEvent>();
|
||||
let tx = AppEventSender::new(tx_raw);
|
||||
let mut pane = BottomPane::new(BottomPaneParams {
|
||||
app_event_tx: tx,
|
||||
frame_requester: FrameRequester::test_dummy(),
|
||||
has_input_focus: true,
|
||||
enhanced_keys_supported: false,
|
||||
placeholder_text: "Ask Codex to do anything".to_string(),
|
||||
disable_paste_burst: false,
|
||||
animations_enabled: true,
|
||||
skills: Some(Vec::new()),
|
||||
});
|
||||
|
||||
pane.set_task_running(true);
|
||||
|
||||
let width = 48;
|
||||
let height = pane.desired_height(width);
|
||||
let area = Rect::new(0, 0, width, height);
|
||||
assert_snapshot!("status_only_snapshot", render_snapshot(&pane, area));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn status_with_details_and_queued_messages_snapshot() {
|
||||
let (tx_raw, _rx) = unbounded_channel::<AppEvent>();
|
||||
let tx = AppEventSender::new(tx_raw);
|
||||
let mut pane = BottomPane::new(BottomPaneParams {
|
||||
app_event_tx: tx,
|
||||
frame_requester: FrameRequester::test_dummy(),
|
||||
has_input_focus: true,
|
||||
enhanced_keys_supported: false,
|
||||
placeholder_text: "Ask Codex to do anything".to_string(),
|
||||
disable_paste_burst: false,
|
||||
animations_enabled: true,
|
||||
skills: Some(Vec::new()),
|
||||
});
|
||||
|
||||
pane.set_task_running(true);
|
||||
pane.update_status(
|
||||
"Working".to_string(),
|
||||
Some("First detail line\nSecond detail line".to_string()),
|
||||
);
|
||||
pane.set_queued_user_messages(vec!["Queued follow-up question".to_string()]);
|
||||
|
||||
let width = 48;
|
||||
let height = pane.desired_height(width);
|
||||
let area = Rect::new(0, 0, width, height);
|
||||
assert_snapshot!(
|
||||
"status_with_details_and_queued_messages_snapshot",
|
||||
render_snapshot(&pane, area)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn queued_messages_visible_when_status_hidden_snapshot() {
|
||||
let (tx_raw, _rx) = unbounded_channel::<AppEvent>();
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ expression: "render_snapshot(&pane, area)"
|
|||
↳ Queued follow-up question
|
||||
⌥ + ↑ edit
|
||||
|
||||
|
||||
› Ask Codex to do anything
|
||||
|
||||
100% context left · ? for shortcuts
|
||||
|
|
|
|||
|
|
@ -3,10 +3,10 @@ source: tui/src/bottom_pane/mod.rs
|
|||
expression: "render_snapshot(&pane, area)"
|
||||
---
|
||||
• Working (0s • esc to interrupt)
|
||||
|
||||
↳ Queued follow-up question
|
||||
⌥ + ↑ edit
|
||||
|
||||
|
||||
› Ask Codex to do anything
|
||||
|
||||
100% context left · ? for shortcuts
|
||||
|
|
|
|||
|
|
@ -0,0 +1,10 @@
|
|||
---
|
||||
source: tui/src/bottom_pane/mod.rs
|
||||
expression: "render_snapshot(&pane, area)"
|
||||
---
|
||||
• Working (0s • esc to interrupt)
|
||||
|
||||
|
||||
› Ask Codex to do anything
|
||||
|
||||
100% context left · ? for shortcuts
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
---
|
||||
source: tui/src/bottom_pane/mod.rs
|
||||
expression: "render_snapshot(&pane, area)"
|
||||
---
|
||||
• Working (0s • esc to interrupt)
|
||||
└ First detail line
|
||||
Second detail line
|
||||
|
||||
↳ Queued follow-up question
|
||||
⌥ + ↑ edit
|
||||
|
||||
› Ask Codex to do anything
|
||||
|
||||
100% context left · ? for shortcuts
|
||||
|
|
@ -2,7 +2,9 @@
|
|||
source: tui/src/chatwidget/tests.rs
|
||||
expression: term.backend().vt100().screen().contents()
|
||||
---
|
||||
|
||||
• Working (0s • esc to interrupt)
|
||||
|
||||
↳ Hello, world! 0
|
||||
↳ Hello, world! 1
|
||||
↳ Hello, world! 2
|
||||
|
|
@ -21,7 +23,6 @@ expression: term.backend().vt100().screen().contents()
|
|||
↳ Hello, world! 15
|
||||
↳ Hello, world! 16
|
||||
|
||||
|
||||
› Ask Codex to do anything
|
||||
|
||||
100% context left · ? for shortcuts
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
---
|
||||
source: tui/src/chatwidget/tests.rs
|
||||
assertion_line: 3840
|
||||
expression: term.backend().vt100().screen().contents()
|
||||
---
|
||||
|
||||
|
|
@ -14,10 +13,10 @@ expression: term.backend().vt100().screen().contents()
|
|||
|
||||
|
||||
• Working (0s • esc to interrupt)
|
||||
|
||||
↳ Queued while /review is running.
|
||||
⌥ + ↑ edit
|
||||
|
||||
|
||||
› Ask Codex to do anything
|
||||
|
||||
100% context left · ? for shortcuts
|
||||
|
|
|
|||
|
|
@ -688,8 +688,13 @@ impl BottomPane {
|
|||
if let Some(status) = &self.status {
|
||||
flex.push(0, RenderableItem::Borrowed(status));
|
||||
}
|
||||
let has_queued_messages = !self.queued_user_messages.messages.is_empty();
|
||||
let has_status = self.status.is_some();
|
||||
if has_queued_messages && has_status {
|
||||
flex.push(0, RenderableItem::Owned("".into()));
|
||||
}
|
||||
flex.push(1, RenderableItem::Borrowed(&self.queued_user_messages));
|
||||
if self.status.is_some() || !self.queued_user_messages.messages.is_empty() {
|
||||
if !has_queued_messages && has_status {
|
||||
flex.push(0, RenderableItem::Owned("".into()));
|
||||
}
|
||||
let mut flex2 = FlexRenderable::new();
|
||||
|
|
@ -931,6 +936,60 @@ mod tests {
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn status_only_snapshot() {
|
||||
let (tx_raw, _rx) = unbounded_channel::<AppEvent>();
|
||||
let tx = AppEventSender::new(tx_raw);
|
||||
let mut pane = BottomPane::new(BottomPaneParams {
|
||||
app_event_tx: tx,
|
||||
frame_requester: FrameRequester::test_dummy(),
|
||||
has_input_focus: true,
|
||||
enhanced_keys_supported: false,
|
||||
placeholder_text: "Ask Codex to do anything".to_string(),
|
||||
disable_paste_burst: false,
|
||||
animations_enabled: true,
|
||||
skills: Some(Vec::new()),
|
||||
});
|
||||
|
||||
pane.set_task_running(true);
|
||||
|
||||
let width = 48;
|
||||
let height = pane.desired_height(width);
|
||||
let area = Rect::new(0, 0, width, height);
|
||||
assert_snapshot!("status_only_snapshot", render_snapshot(&pane, area));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn status_with_details_and_queued_messages_snapshot() {
|
||||
let (tx_raw, _rx) = unbounded_channel::<AppEvent>();
|
||||
let tx = AppEventSender::new(tx_raw);
|
||||
let mut pane = BottomPane::new(BottomPaneParams {
|
||||
app_event_tx: tx,
|
||||
frame_requester: FrameRequester::test_dummy(),
|
||||
has_input_focus: true,
|
||||
enhanced_keys_supported: false,
|
||||
placeholder_text: "Ask Codex to do anything".to_string(),
|
||||
disable_paste_burst: false,
|
||||
animations_enabled: true,
|
||||
skills: Some(Vec::new()),
|
||||
});
|
||||
|
||||
pane.set_task_running(true);
|
||||
pane.update_status(
|
||||
"Working".to_string(),
|
||||
Some("First detail line\nSecond detail line".to_string()),
|
||||
);
|
||||
pane.set_queued_user_messages(vec!["Queued follow-up question".to_string()]);
|
||||
|
||||
let width = 48;
|
||||
let height = pane.desired_height(width);
|
||||
let area = Rect::new(0, 0, width, height);
|
||||
assert_snapshot!(
|
||||
"status_with_details_and_queued_messages_snapshot",
|
||||
render_snapshot(&pane, area)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn queued_messages_visible_when_status_hidden_snapshot() {
|
||||
let (tx_raw, _rx) = unbounded_channel::<AppEvent>();
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ expression: "render_snapshot(&pane, area)"
|
|||
↳ Queued follow-up question
|
||||
⌥ + ↑ edit
|
||||
|
||||
|
||||
› Ask Codex to do anything
|
||||
|
||||
100% context left · ? for shortcuts
|
||||
|
|
|
|||
|
|
@ -3,10 +3,10 @@ source: tui2/src/bottom_pane/mod.rs
|
|||
expression: "render_snapshot(&pane, area)"
|
||||
---
|
||||
• Working (0s • esc to interrupt)
|
||||
|
||||
↳ Queued follow-up question
|
||||
⌥ + ↑ edit
|
||||
|
||||
|
||||
› Ask Codex to do anything
|
||||
|
||||
100% context left · ? for shortcuts
|
||||
|
|
|
|||
|
|
@ -0,0 +1,10 @@
|
|||
---
|
||||
source: tui2/src/bottom_pane/mod.rs
|
||||
expression: "render_snapshot(&pane, area)"
|
||||
---
|
||||
• Working (0s • esc to interrupt)
|
||||
|
||||
|
||||
› Ask Codex to do anything
|
||||
|
||||
100% context left · ? for shortcuts
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
---
|
||||
source: tui2/src/bottom_pane/mod.rs
|
||||
expression: "render_snapshot(&pane, area)"
|
||||
---
|
||||
• Working (0s • esc to interrupt)
|
||||
└ First detail line
|
||||
Second detail line
|
||||
|
||||
↳ Queued follow-up question
|
||||
⌥ + ↑ edit
|
||||
|
||||
› Ask Codex to do anything
|
||||
|
||||
100% context left · ? for shortcuts
|
||||
|
|
@ -2,7 +2,9 @@
|
|||
source: tui2/src/chatwidget/tests.rs
|
||||
expression: term.backend().vt100().screen().contents()
|
||||
---
|
||||
|
||||
• Working (0s • esc to interrupt)
|
||||
|
||||
↳ Hello, world! 0
|
||||
↳ Hello, world! 1
|
||||
↳ Hello, world! 2
|
||||
|
|
@ -21,7 +23,6 @@ expression: term.backend().vt100().screen().contents()
|
|||
↳ Hello, world! 15
|
||||
↳ Hello, world! 16
|
||||
|
||||
|
||||
› Ask Codex to do anything
|
||||
|
||||
100% context left · ? for shortcuts
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue