mirror of
https://github.com/hanzoai/dev.git
synced 2026-10-25 03:32:32 +00:00
@@ -4485,8 +4485,7 @@ impl ChatWidget<'_> {
|
||||
}
|
||||
self.request_redraw();
|
||||
}
|
||||
/// If the user is at or near the bottom, keep following new messages.
|
||||
/// We treat "near" as within 3 rows, matching our scroll step.
|
||||
/// If the user is at the bottom, keep following new messages.
|
||||
fn autoscroll_if_near_bottom(&mut self) {
|
||||
layout_scroll::autoscroll_if_near_bottom(self);
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ use crate::height_manager::HeightEvent;
|
||||
use ratatui::layout::Rect;
|
||||
|
||||
pub(super) fn autoscroll_if_near_bottom(chat: &mut ChatWidget<'_>) {
|
||||
if chat.layout.scroll_offset.get() <= 3 {
|
||||
if chat.layout.scroll_offset.get() == 0 {
|
||||
let before = chat.layout.scroll_offset.get();
|
||||
chat.layout.scroll_offset.set(0);
|
||||
chat.bottom_pane.set_compact_compose(false);
|
||||
|
||||
@@ -1206,6 +1206,61 @@ fn scroll_position_stable_when_history_grows_scrolled_up() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn scroll_position_stable_during_streaming_when_scrolled_up() {
|
||||
let mut harness = ChatWidgetHarness::new();
|
||||
|
||||
for idx in 0..6 {
|
||||
harness.push_user_prompt(format!("User prompt #{idx}: streaming scroll"));
|
||||
harness.push_assistant_markdown(format!(
|
||||
"Assistant response #{idx} keeps the history tall.\n\nExtra paragraph for idx {idx}."
|
||||
));
|
||||
}
|
||||
|
||||
let _ = render_chat_widget_to_vt100(&mut harness, 80, 24);
|
||||
let metrics = harness_layout_metrics(&harness);
|
||||
assert!(
|
||||
metrics.last_max_scroll > 0,
|
||||
"scenario must overflow the history viewport to exercise scrolling"
|
||||
);
|
||||
|
||||
let offset = metrics.last_max_scroll.min(3).max(1);
|
||||
harness_force_scroll_offset(&mut harness, offset);
|
||||
let _ = render_chat_widget_to_vt100(&mut harness, 80, 24);
|
||||
let before = harness_layout_metrics(&harness);
|
||||
let before_from_top =
|
||||
before
|
||||
.last_max_scroll
|
||||
.saturating_sub(before.scroll_offset.min(before.last_max_scroll));
|
||||
|
||||
harness.handle_event(Event {
|
||||
id: "stream-scroll".into(),
|
||||
event_seq: 1,
|
||||
msg: EventMsg::AgentMessageDelta(AgentMessageDeltaEvent {
|
||||
delta: "Streaming update line one.\nStreaming update line two.\n".into(),
|
||||
}),
|
||||
order: Some(OrderMeta {
|
||||
request_ordinal: 1,
|
||||
output_index: Some(0),
|
||||
sequence_number: Some(1),
|
||||
}),
|
||||
});
|
||||
harness.drive_commit_tick();
|
||||
|
||||
let _ = render_chat_widget_to_vt100(&mut harness, 80, 24);
|
||||
let after = harness_layout_metrics(&harness);
|
||||
let after_from_top =
|
||||
after
|
||||
.last_max_scroll
|
||||
.saturating_sub(after.scroll_offset.min(after.last_max_scroll));
|
||||
|
||||
assert_eq!(
|
||||
before_from_top,
|
||||
after_from_top,
|
||||
"streaming output should not move the viewport while scrolled"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn multiline_final_history_line_visible_at_bottom() {
|
||||
init_tracing_once();
|
||||
|
||||
Reference in New Issue
Block a user