Skip to content

Commit

Permalink
Fix project panel scrolling position restoration (#8961)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
alygin authored Mar 6, 2024
1 parent 6bbd09e commit effc317
Show file tree
Hide file tree
Showing 2 changed files with 8 additions and 5 deletions.
5 changes: 4 additions & 1 deletion crates/gpui/src/elements/uniform_list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -74,13 +74,15 @@ 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<RefCell<Option<usize>>>,
}

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)),
}
}
Expand Down Expand Up @@ -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
}
Expand Down
8 changes: 4 additions & 4 deletions crates/project_panel/src/project_panel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ const NEW_ENTRY_ID: ProjectEntryId = ProjectEntryId::MAX;
pub struct ProjectPanel {
project: Model<Project>,
fs: Arc<dyn Fs>,
list: UniformListScrollHandle,
scroll_handle: UniformListScrollHandle,
focus_handle: FocusHandle,
visible_entries: Vec<(WorktreeId, Vec<Entry>)>,
last_worktree_root_id: Option<ProjectEntryId>,
Expand Down Expand Up @@ -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(),
Expand Down Expand Up @@ -864,7 +864,7 @@ impl ProjectPanel {

fn autoscroll(&mut self, cx: &mut ViewContext<Self>) {
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();
}
}
Expand Down Expand Up @@ -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()
Expand Down

0 comments on commit effc317

Please sign in to comment.