project_panel: Improve behavior for cut-pasting entries (#31931)
Previously, we would move entries each time they were pasted. Thus, if you were to cut some files and pasted them in folder `a` and then `b`, they would only occur in folder `b` and not in folder `a`. This is unintuitive - e.g. the same does not apply to text and does not happen in other editors. This PR improves this behavior - after the first paste of a cut clipboard, we change the clipboard to a copy clipboard, ensuring that for all folloing pastes, the entries are not moved again. In the above example, the files would then also be found in folder `a`. This is also reflected in the added test. Release Notes: - Ensured that cut project panel entries are cut-pasted only on the first use, and copy-pasted on all subsequent pastes.
This commit is contained in:
parent
2bb8aa2f73
commit
657c8b1084
2 changed files with 97 additions and 0 deletions
|
@ -2343,6 +2343,11 @@ impl ProjectPanel {
|
||||||
})
|
})
|
||||||
.detach_and_log_err(cx);
|
.detach_and_log_err(cx);
|
||||||
|
|
||||||
|
if clip_is_cut {
|
||||||
|
// Convert the clipboard cut entry to a copy entry after the first paste.
|
||||||
|
self.clipboard = self.clipboard.take().map(ClipboardEntry::to_copy_entry);
|
||||||
|
}
|
||||||
|
|
||||||
self.expand_entry(worktree_id, entry.id, cx);
|
self.expand_entry(worktree_id, entry.id, cx);
|
||||||
Some(())
|
Some(())
|
||||||
});
|
});
|
||||||
|
@ -5033,6 +5038,13 @@ impl ClipboardEntry {
|
||||||
ClipboardEntry::Copied(entries) | ClipboardEntry::Cut(entries) => entries,
|
ClipboardEntry::Copied(entries) | ClipboardEntry::Cut(entries) => entries,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn to_copy_entry(self) -> Self {
|
||||||
|
match self {
|
||||||
|
ClipboardEntry::Copied(_) => self,
|
||||||
|
ClipboardEntry::Cut(entries) => ClipboardEntry::Copied(entries),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
|
@ -1170,6 +1170,91 @@ async fn test_copy_paste(cx: &mut gpui::TestAppContext) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[gpui::test]
|
||||||
|
async fn test_cut_paste(cx: &mut gpui::TestAppContext) {
|
||||||
|
init_test(cx);
|
||||||
|
|
||||||
|
let fs = FakeFs::new(cx.executor().clone());
|
||||||
|
fs.insert_tree(
|
||||||
|
"/root",
|
||||||
|
json!({
|
||||||
|
"one.txt": "",
|
||||||
|
"two.txt": "",
|
||||||
|
"a": {},
|
||||||
|
"b": {}
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
let project = Project::test(fs.clone(), ["/root".as_ref()], cx).await;
|
||||||
|
let workspace = cx.add_window(|window, cx| Workspace::test_new(project.clone(), window, cx));
|
||||||
|
let cx = &mut VisualTestContext::from_window(*workspace, cx);
|
||||||
|
let panel = workspace.update(cx, ProjectPanel::new).unwrap();
|
||||||
|
|
||||||
|
select_path_with_mark(&panel, "root/one.txt", cx);
|
||||||
|
select_path_with_mark(&panel, "root/two.txt", cx);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
visible_entries_as_strings(&panel, 0..50, cx),
|
||||||
|
&[
|
||||||
|
"v root",
|
||||||
|
" > a",
|
||||||
|
" > b",
|
||||||
|
" one.txt <== marked",
|
||||||
|
" two.txt <== selected <== marked",
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
panel.update_in(cx, |panel, window, cx| {
|
||||||
|
panel.cut(&Default::default(), window, cx);
|
||||||
|
});
|
||||||
|
|
||||||
|
select_path(&panel, "root/a", cx);
|
||||||
|
|
||||||
|
panel.update_in(cx, |panel, window, cx| {
|
||||||
|
panel.paste(&Default::default(), window, cx);
|
||||||
|
});
|
||||||
|
cx.executor().run_until_parked();
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
visible_entries_as_strings(&panel, 0..50, cx),
|
||||||
|
&[
|
||||||
|
"v root",
|
||||||
|
" v a",
|
||||||
|
" one.txt <== marked",
|
||||||
|
" two.txt <== selected <== marked",
|
||||||
|
" > b",
|
||||||
|
],
|
||||||
|
"Cut entries should be moved on first paste."
|
||||||
|
);
|
||||||
|
|
||||||
|
panel.update_in(cx, |panel, window, cx| {
|
||||||
|
panel.cancel(&menu::Cancel {}, window, cx)
|
||||||
|
});
|
||||||
|
cx.executor().run_until_parked();
|
||||||
|
|
||||||
|
select_path(&panel, "root/b", cx);
|
||||||
|
|
||||||
|
panel.update_in(cx, |panel, window, cx| {
|
||||||
|
panel.paste(&Default::default(), window, cx);
|
||||||
|
});
|
||||||
|
cx.executor().run_until_parked();
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
visible_entries_as_strings(&panel, 0..50, cx),
|
||||||
|
&[
|
||||||
|
"v root",
|
||||||
|
" v a",
|
||||||
|
" one.txt",
|
||||||
|
" two.txt",
|
||||||
|
" v b",
|
||||||
|
" one.txt",
|
||||||
|
" two.txt <== selected",
|
||||||
|
],
|
||||||
|
"Cut entries should only be copied for the second paste!"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[gpui::test]
|
#[gpui::test]
|
||||||
async fn test_cut_paste_between_different_worktrees(cx: &mut gpui::TestAppContext) {
|
async fn test_cut_paste_between_different_worktrees(cx: &mut gpui::TestAppContext) {
|
||||||
init_test(cx);
|
init_test(cx);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue