project_panel: Only show sticky item shadow when list is scrolled (#34050)
Follow up: https://github.com/zed-industries/zed/pull/34042 - Removes `top_slot_items` from `uniform_list` in favor of using existing `decorations` - Add condition to only show shadow for sticky item when list is scrolled and scrollable Release Notes: - N/A
This commit is contained in:
parent
f1db3b4e1d
commit
1f3575ad6e
4 changed files with 180 additions and 178 deletions
|
@ -56,8 +56,8 @@ use std::{
|
|||
use theme::ThemeSettings;
|
||||
use ui::{
|
||||
Color, ContextMenu, DecoratedIcon, Icon, IconDecoration, IconDecorationKind, IndentGuideColors,
|
||||
IndentGuideLayout, KeyBinding, Label, LabelSize, ListItem, ListItemSpacing, Scrollbar,
|
||||
ScrollbarState, StickyCandidate, Tooltip, prelude::*, v_flex,
|
||||
IndentGuideLayout, KeyBinding, Label, LabelSize, ListItem, ListItemSpacing, ScrollableHandle,
|
||||
Scrollbar, ScrollbarState, StickyCandidate, Tooltip, prelude::*, v_flex,
|
||||
};
|
||||
use util::{ResultExt, TakeUntilExt, TryFutureExt, maybe, paths::compare_paths};
|
||||
use workspace::{
|
||||
|
@ -3327,7 +3327,13 @@ impl ProjectPanel {
|
|||
range: Range<usize>,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<ProjectPanel>,
|
||||
mut callback: impl FnMut(&Entry, &HashSet<Arc<Path>>, &mut Window, &mut Context<ProjectPanel>),
|
||||
mut callback: impl FnMut(
|
||||
&Entry,
|
||||
usize,
|
||||
&HashSet<Arc<Path>>,
|
||||
&mut Window,
|
||||
&mut Context<ProjectPanel>,
|
||||
),
|
||||
) {
|
||||
let mut ix = 0;
|
||||
for (_, visible_worktree_entries, entries_paths) in &self.visible_entries {
|
||||
|
@ -3348,8 +3354,10 @@ impl ProjectPanel {
|
|||
.map(|e| (e.path.clone()))
|
||||
.collect()
|
||||
});
|
||||
for entry in visible_worktree_entries[entry_range].iter() {
|
||||
callback(&entry, entries, window, cx);
|
||||
let base_index = ix + entry_range.start;
|
||||
for (i, entry) in visible_worktree_entries[entry_range].iter().enumerate() {
|
||||
let global_index = base_index + i;
|
||||
callback(&entry, global_index, entries, window, cx);
|
||||
}
|
||||
ix = end_ix;
|
||||
}
|
||||
|
@ -3930,7 +3938,15 @@ impl ProjectPanel {
|
|||
}
|
||||
};
|
||||
|
||||
let last_sticky_item = details.sticky.as_ref().map_or(false, |item| item.is_last);
|
||||
let show_sticky_shadow = details.sticky.as_ref().map_or(false, |item| {
|
||||
if item.is_last {
|
||||
let is_scrollable = self.scroll_handle.is_scrollable();
|
||||
let is_scrolled = self.scroll_handle.offset().y < px(0.);
|
||||
is_scrollable && is_scrolled
|
||||
} else {
|
||||
false
|
||||
}
|
||||
});
|
||||
let shadow_color_top = hsla(0.0, 0.0, 0.0, 0.15);
|
||||
let shadow_color_bottom = hsla(0.0, 0.0, 0.0, 0.);
|
||||
let sticky_shadow = div()
|
||||
|
@ -3956,7 +3972,7 @@ impl ProjectPanel {
|
|||
.border_r_2()
|
||||
.border_color(border_color)
|
||||
.hover(|style| style.bg(bg_hover_color).border_color(border_hover_color))
|
||||
.when(is_sticky && last_sticky_item, |this| this.child(sticky_shadow))
|
||||
.when(show_sticky_shadow, |this| this.child(sticky_shadow))
|
||||
.when(!is_sticky, |this| {
|
||||
this
|
||||
.when(is_highlighted && folded_directory_drag_target.is_none(), |this| this.border_color(transparent_white()).bg(item_colors.drag_over))
|
||||
|
@ -4828,54 +4844,6 @@ impl ProjectPanel {
|
|||
None
|
||||
}
|
||||
|
||||
fn candidate_entries_in_range_for_sticky(
|
||||
&self,
|
||||
range: Range<usize>,
|
||||
_window: &mut Window,
|
||||
_cx: &mut Context<Self>,
|
||||
) -> Vec<StickyProjectPanelCandidate> {
|
||||
let mut result = Vec::new();
|
||||
let mut current_offset = 0;
|
||||
|
||||
for (_, visible_worktree_entries, entries_paths) in &self.visible_entries {
|
||||
let worktree_len = visible_worktree_entries.len();
|
||||
let worktree_end_offset = current_offset + worktree_len;
|
||||
|
||||
if current_offset >= range.end {
|
||||
break;
|
||||
}
|
||||
|
||||
if worktree_end_offset > range.start {
|
||||
let local_start = range.start.saturating_sub(current_offset);
|
||||
let local_end = range.end.saturating_sub(current_offset).min(worktree_len);
|
||||
|
||||
let paths = entries_paths.get_or_init(|| {
|
||||
visible_worktree_entries
|
||||
.iter()
|
||||
.map(|e| e.path.clone())
|
||||
.collect()
|
||||
});
|
||||
|
||||
let entries_from_this_worktree = visible_worktree_entries[local_start..local_end]
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(i, entry)| {
|
||||
let (depth, _) = Self::calculate_depth_and_difference(&entry.entry, paths);
|
||||
StickyProjectPanelCandidate {
|
||||
index: current_offset + local_start + i,
|
||||
depth,
|
||||
}
|
||||
});
|
||||
|
||||
result.extend(entries_from_this_worktree);
|
||||
}
|
||||
|
||||
current_offset = worktree_end_offset;
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
fn render_sticky_entries(
|
||||
&self,
|
||||
child: StickyProjectPanelCandidate,
|
||||
|
@ -4926,6 +4894,10 @@ impl ProjectPanel {
|
|||
break 'outer;
|
||||
}
|
||||
|
||||
if sticky_parents.is_empty() {
|
||||
return SmallVec::new();
|
||||
}
|
||||
|
||||
sticky_parents.reverse();
|
||||
|
||||
let git_status_enabled = ProjectPanelSettings::get_global(cx).git_status;
|
||||
|
@ -4940,6 +4912,8 @@ impl ProjectPanel {
|
|||
Default::default()
|
||||
};
|
||||
|
||||
// already checked if non empty above
|
||||
let last_item_index = sticky_parents.len() - 1;
|
||||
sticky_parents
|
||||
.iter()
|
||||
.enumerate()
|
||||
|
@ -4950,7 +4924,7 @@ impl ProjectPanel {
|
|||
.unwrap_or_default();
|
||||
let sticky_details = Some(StickyDetails {
|
||||
sticky_index: index,
|
||||
is_last: index == sticky_parents.len() - 1,
|
||||
is_last: index == last_item_index,
|
||||
});
|
||||
let details = self.details_for_entry(
|
||||
entry,
|
||||
|
@ -5191,17 +5165,6 @@ impl Render for ProjectPanel {
|
|||
items
|
||||
})
|
||||
})
|
||||
.when(show_sticky_scroll, |list| {
|
||||
list.with_top_slot(ui::sticky_items(
|
||||
cx.entity().clone(),
|
||||
|this, range, window, cx| {
|
||||
this.candidate_entries_in_range_for_sticky(range, window, cx)
|
||||
},
|
||||
|this, marker_entry, window, cx| {
|
||||
this.render_sticky_entries(marker_entry, window, cx)
|
||||
},
|
||||
))
|
||||
})
|
||||
.when(show_indent_guides, |list| {
|
||||
list.with_decoration(
|
||||
ui::indent_guides(
|
||||
|
@ -5215,7 +5178,7 @@ impl Render for ProjectPanel {
|
|||
range,
|
||||
window,
|
||||
cx,
|
||||
|entry, entries, _, _| {
|
||||
|entry, _, entries, _, _| {
|
||||
let (depth, _) = Self::calculate_depth_and_difference(
|
||||
entry, entries,
|
||||
);
|
||||
|
@ -5301,6 +5264,30 @@ impl Render for ProjectPanel {
|
|||
),
|
||||
)
|
||||
})
|
||||
.when(show_sticky_scroll, |list| {
|
||||
list.with_decoration(ui::sticky_items(
|
||||
cx.entity().clone(),
|
||||
|this, range, window, cx| {
|
||||
let mut items = SmallVec::with_capacity(range.end - range.start);
|
||||
this.iter_visible_entries(
|
||||
range,
|
||||
window,
|
||||
cx,
|
||||
|entry, index, entries, _, _| {
|
||||
let (depth, _) =
|
||||
Self::calculate_depth_and_difference(entry, entries);
|
||||
let candidate =
|
||||
StickyProjectPanelCandidate { index, depth };
|
||||
items.push(candidate);
|
||||
},
|
||||
);
|
||||
items
|
||||
},
|
||||
|this, marker_entry, window, cx| {
|
||||
this.render_sticky_entries(marker_entry, window, cx)
|
||||
},
|
||||
))
|
||||
})
|
||||
.size_full()
|
||||
.with_sizing_behavior(ListSizingBehavior::Infer)
|
||||
.with_horizontal_sizing_behavior(ListHorizontalSizingBehavior::Unconstrained)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue