From a40f04b71fd72e3818d3b9f23c4e31c30c4d47b6 Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Fri, 15 Dec 2023 13:50:51 -0500 Subject: [PATCH] Only scroll enough to reveal the next channel if it isn't visible Co-authored-by: Max --- crates/collab_ui2/src/collab_panel.rs | 5 +--- crates/gpui2/src/elements/list.rs | 33 +++++++++++++++++++++++++-- 2 files changed, 32 insertions(+), 6 deletions(-) diff --git a/crates/collab_ui2/src/collab_panel.rs b/crates/collab_ui2/src/collab_panel.rs index 6f21649dd6..1ca6101c54 100644 --- a/crates/collab_ui2/src/collab_panel.rs +++ b/crates/collab_ui2/src/collab_panel.rs @@ -584,10 +584,7 @@ impl CollabPanel { } fn scroll_to_item(&mut self, ix: usize) { - self.list_state.scroll_to(ListOffset { - item_ix: ix, - offset_in_item: px(0.), - }) + self.list_state.scroll_to_reveal_item(ix) } fn update_entries(&mut self, select_same_item: bool, cx: &mut ViewContext) { diff --git a/crates/gpui2/src/elements/list.rs b/crates/gpui2/src/elements/list.rs index 108703370c..415a3b7368 100644 --- a/crates/gpui2/src/elements/list.rs +++ b/crates/gpui2/src/elements/list.rs @@ -154,11 +154,40 @@ impl ListState { state.logical_scroll_top = Some(scroll_top); } + pub fn scroll_to_reveal_item(&self, ix: usize) { + let state = &mut *self.0.borrow_mut(); + let mut scroll_top = state.logical_scroll_top(); + let height = state + .last_layout_bounds + .map_or(px(0.), |bounds| bounds.size.height); + + if ix <= scroll_top.item_ix { + scroll_top.item_ix = ix; + scroll_top.offset_in_item = px(0.); + } else { + let mut cursor = state.items.cursor::(); + cursor.seek(&Count(ix + 1), Bias::Right, &()); + let bottom = cursor.start().height; + let goal_top = px(0.).max(bottom - height); + + cursor.seek(&Height(goal_top), Bias::Left, &()); + let start_ix = cursor.start().count; + let start_item_top = cursor.start().height; + + if start_ix >= scroll_top.item_ix { + scroll_top.item_ix = start_ix; + scroll_top.offset_in_item = goal_top - start_item_top; + } + } + + state.logical_scroll_top = Some(scroll_top); + } + /// Get the bounds for the given item in window coordinates. pub fn bounds_for_item(&self, ix: usize) -> Option> { let state = &*self.0.borrow(); let bounds = state.last_layout_bounds.unwrap_or_default(); - let scroll_top = state.logical_scroll_top.unwrap_or_default(); + let scroll_top = state.logical_scroll_top(); if ix < scroll_top.item_ix { return None; @@ -264,7 +293,7 @@ impl std::fmt::Debug for ListItem { } } -#[derive(Debug, Clone, Copy, Default)] +#[derive(Debug, Clone, Copy)] pub struct ListOffset { pub item_ix: usize, pub offset_in_item: Pixels,