From effc317a06126d4a3516c1f582e5215677c6cc73 Mon Sep 17 00:00:00 2001 From: Andrew Lygin Date: Wed, 6 Mar 2024 23:00:51 +0300 Subject: [PATCH] Fix project panel scrolling position restoration (#8961) Project panel loses the last scrolling position every time the user hides/shows it. This PR fixes the problem. The reason of the problem is that `UniformListScrollHandle`, which is intended to store the scrolling position between redrawings, is only used for ad-hoc autoscrollings to the list items, while the `interactivity.scroll_handle` that is responsible for the scrolling position, doesn't survive the project panel hiding. How the problem looks: https://github.com/zed-industries/zed/assets/2101250/7c7e3da6-9a9d-4f28-a181-ee9547349d4c Release Notes: - Fixed scrolling position restoration in the Project Panel. --- crates/gpui/src/elements/uniform_list.rs | 5 ++++- crates/project_panel/src/project_panel.rs | 8 ++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/crates/gpui/src/elements/uniform_list.rs b/crates/gpui/src/elements/uniform_list.rs index 2d708f270e6a261e60ab1ef2e76356a4841b5bd4..7a69ef98e35a6f2469d71a66940f5813c970444d 100644 --- a/crates/gpui/src/elements/uniform_list.rs +++ b/crates/gpui/src/elements/uniform_list.rs @@ -7,7 +7,7 @@ use crate::{ point, px, size, AnyElement, AvailableSpace, Bounds, ContentMask, Element, ElementContext, ElementId, InteractiveElement, InteractiveElementState, Interactivity, IntoElement, LayoutId, - Pixels, Render, Size, StyleRefinement, Styled, View, ViewContext, WindowContext, + Pixels, Render, ScrollHandle, Size, StyleRefinement, Styled, View, ViewContext, WindowContext, }; use smallvec::SmallVec; use std::{cell::RefCell, cmp, ops::Range, rc::Rc}; @@ -74,6 +74,7 @@ pub struct UniformList { /// This should be stored in your view and passed to the uniform_list on each frame. #[derive(Clone, Default)] pub struct UniformListScrollHandle { + base_handle: ScrollHandle, deferred_scroll_to_item: Rc>>, } @@ -81,6 +82,7 @@ impl UniformListScrollHandle { /// Create a new scroll handle to bind to a uniform list. pub fn new() -> Self { Self { + base_handle: ScrollHandle::new(), deferred_scroll_to_item: Rc::new(RefCell::new(None)), } } @@ -299,6 +301,7 @@ impl UniformList { /// Track and render scroll state of this list with reference to the given scroll handle. pub fn track_scroll(mut self, handle: UniformListScrollHandle) -> Self { + self.interactivity.scroll_handle = Some(handle.base_handle.clone()); self.scroll_handle = Some(handle); self } diff --git a/crates/project_panel/src/project_panel.rs b/crates/project_panel/src/project_panel.rs index 481086a8bb631e5876b5253bc6c2524a963353f2..b7ffcc0a1cf2b23c9613a87b064bccaf6b28be01 100644 --- a/crates/project_panel/src/project_panel.rs +++ b/crates/project_panel/src/project_panel.rs @@ -40,7 +40,7 @@ const NEW_ENTRY_ID: ProjectEntryId = ProjectEntryId::MAX; pub struct ProjectPanel { project: Model, fs: Arc, - list: UniformListScrollHandle, + scroll_handle: UniformListScrollHandle, focus_handle: FocusHandle, visible_entries: Vec<(WorktreeId, Vec)>, last_worktree_root_id: Option, @@ -224,7 +224,7 @@ impl ProjectPanel { let mut this = Self { project: project.clone(), fs: workspace.app_state().fs.clone(), - list: UniformListScrollHandle::new(), + scroll_handle: UniformListScrollHandle::new(), focus_handle, visible_entries: Default::default(), last_worktree_root_id: Default::default(), @@ -864,7 +864,7 @@ impl ProjectPanel { fn autoscroll(&mut self, cx: &mut ViewContext) { if let Some((_, _, index)) = self.selection.and_then(|s| self.index_for_selection(s)) { - self.list.scroll_to_item(index); + self.scroll_handle.scroll_to_item(index); cx.notify(); } } @@ -1565,7 +1565,7 @@ impl Render for ProjectPanel { }, ) .size_full() - .track_scroll(self.list.clone()), + .track_scroll(self.scroll_handle.clone()), ) .children(self.context_menu.as_ref().map(|(menu, position, _)| { overlay()