mirror of
https://github.com/zed-industries/zed.git
synced 2025-02-03 08:54:04 +00:00
project_panel: Add directory auto-expand after 500ms hover during dragging (#23080)
This PR resolves one part of issue #14496 In project panel, when dragging, if you hover over a directory for ~500ms, it now auto-expands so you can drag and drop into nested directories. Task cleanup is handled in these cases: - Dragged onto a different entry. - Dragged anywhere else, and the 500ms timer runs out (for example, out of the project panel). - Dropped onto any entry. I don’t see any edge cases where task isn’t cleaned up after 500ms. https://github.com/user-attachments/assets/19da0da1-f9e2-42df-8ee4-fab6dc9a185a Release Notes: - Added auto-expand for directories on hover for a while during dragging.
This commit is contained in:
parent
f0a07b5eff
commit
21e7765a48
1 changed files with 43 additions and 0 deletions
|
@ -81,6 +81,7 @@ pub struct ProjectPanel {
|
||||||
/// project entries (and all non-leaf nodes are guaranteed to be directories).
|
/// project entries (and all non-leaf nodes are guaranteed to be directories).
|
||||||
ancestors: HashMap<ProjectEntryId, FoldedAncestors>,
|
ancestors: HashMap<ProjectEntryId, FoldedAncestors>,
|
||||||
last_worktree_root_id: Option<ProjectEntryId>,
|
last_worktree_root_id: Option<ProjectEntryId>,
|
||||||
|
last_selection_drag_over_entry: Option<ProjectEntryId>,
|
||||||
last_external_paths_drag_over_entry: Option<ProjectEntryId>,
|
last_external_paths_drag_over_entry: Option<ProjectEntryId>,
|
||||||
expanded_dir_ids: HashMap<WorktreeId, Vec<ProjectEntryId>>,
|
expanded_dir_ids: HashMap<WorktreeId, Vec<ProjectEntryId>>,
|
||||||
unfolded_dir_ids: HashSet<ProjectEntryId>,
|
unfolded_dir_ids: HashSet<ProjectEntryId>,
|
||||||
|
@ -104,6 +105,7 @@ pub struct ProjectPanel {
|
||||||
// We keep track of the mouse down state on entries so we don't flash the UI
|
// We keep track of the mouse down state on entries so we don't flash the UI
|
||||||
// in case a user clicks to open a file.
|
// in case a user clicks to open a file.
|
||||||
mouse_down: bool,
|
mouse_down: bool,
|
||||||
|
hover_expand_task: Option<Task<()>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
|
@ -380,6 +382,7 @@ impl ProjectPanel {
|
||||||
ancestors: Default::default(),
|
ancestors: Default::default(),
|
||||||
last_worktree_root_id: Default::default(),
|
last_worktree_root_id: Default::default(),
|
||||||
last_external_paths_drag_over_entry: None,
|
last_external_paths_drag_over_entry: None,
|
||||||
|
last_selection_drag_over_entry: None,
|
||||||
expanded_dir_ids: Default::default(),
|
expanded_dir_ids: Default::default(),
|
||||||
unfolded_dir_ids: Default::default(),
|
unfolded_dir_ids: Default::default(),
|
||||||
selection: None,
|
selection: None,
|
||||||
|
@ -402,6 +405,7 @@ impl ProjectPanel {
|
||||||
diagnostics: Default::default(),
|
diagnostics: Default::default(),
|
||||||
scroll_handle,
|
scroll_handle,
|
||||||
mouse_down: false,
|
mouse_down: false,
|
||||||
|
hover_expand_task: None,
|
||||||
};
|
};
|
||||||
this.update_visible_entries(None, cx);
|
this.update_visible_entries(None, cx);
|
||||||
|
|
||||||
|
@ -3356,6 +3360,44 @@ impl ProjectPanel {
|
||||||
},
|
},
|
||||||
))
|
))
|
||||||
})
|
})
|
||||||
|
.on_drag_move::<DraggedSelection>(cx.listener(
|
||||||
|
move |this, event: &DragMoveEvent<DraggedSelection>, cx| {
|
||||||
|
if event.bounds.contains(&event.event.position) {
|
||||||
|
if this.last_selection_drag_over_entry == Some(entry_id) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.last_selection_drag_over_entry = Some(entry_id);
|
||||||
|
this.hover_expand_task.take();
|
||||||
|
|
||||||
|
if !kind.is_dir()
|
||||||
|
|| this
|
||||||
|
.expanded_dir_ids
|
||||||
|
.get(&details.worktree_id)
|
||||||
|
.map_or(false, |ids| ids.binary_search(&entry_id).is_ok())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let bounds = event.bounds;
|
||||||
|
this.hover_expand_task = Some(cx.spawn(|this, mut cx| async move {
|
||||||
|
cx.background_executor()
|
||||||
|
.timer(Duration::from_millis(500))
|
||||||
|
.await;
|
||||||
|
this.update(&mut cx, |this, cx| {
|
||||||
|
this.hover_expand_task.take();
|
||||||
|
if this.last_selection_drag_over_entry == Some(entry_id)
|
||||||
|
&& bounds.contains(&cx.mouse_position())
|
||||||
|
{
|
||||||
|
this.expand_entry(worktree_id, entry_id, cx);
|
||||||
|
this.update_visible_entries(Some((worktree_id, entry_id)), cx);
|
||||||
|
cx.notify();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.ok();
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
))
|
||||||
.on_drag(dragged_selection, move |selection, click_offset, cx| {
|
.on_drag(dragged_selection, move |selection, click_offset, cx| {
|
||||||
cx.new_view(|_| DraggedProjectEntryView {
|
cx.new_view(|_| DraggedProjectEntryView {
|
||||||
details: details.clone(),
|
details: details.clone(),
|
||||||
|
@ -3368,6 +3410,7 @@ impl ProjectPanel {
|
||||||
.drag_over::<DraggedSelection>(move |style, _, _| style.bg(item_colors.drag_over))
|
.drag_over::<DraggedSelection>(move |style, _, _| style.bg(item_colors.drag_over))
|
||||||
.on_drop(cx.listener(move |this, selections: &DraggedSelection, cx| {
|
.on_drop(cx.listener(move |this, selections: &DraggedSelection, cx| {
|
||||||
this.hover_scroll_task.take();
|
this.hover_scroll_task.take();
|
||||||
|
this.hover_expand_task.take();
|
||||||
this.drag_onto(selections, entry_id, kind.is_file(), cx);
|
this.drag_onto(selections, entry_id, kind.is_file(), cx);
|
||||||
}))
|
}))
|
||||||
.on_mouse_down(
|
.on_mouse_down(
|
||||||
|
|
Loading…
Reference in a new issue