project panel: Support dropping files from finder (#12880)
Partially addresses #7386 https://github.com/zed-industries/zed/assets/53836821/fc2e9864-40a8-4ada-ac95-a76a31c44437 Release Notes: - Added support for dropping files from the finder onto the project panel
This commit is contained in:
parent
95c69d0696
commit
38d9ee3731
2 changed files with 256 additions and 5 deletions
|
@ -838,6 +838,23 @@ impl Worktree {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn copy_external_entries(
|
||||
&mut self,
|
||||
target_directory: PathBuf,
|
||||
paths: Vec<Arc<Path>>,
|
||||
overwrite_existing_files: bool,
|
||||
cx: &mut ModelContext<Worktree>,
|
||||
) -> Task<Result<Vec<ProjectEntryId>>> {
|
||||
match self {
|
||||
Worktree::Local(this) => {
|
||||
this.copy_external_entries(target_directory, paths, overwrite_existing_files, cx)
|
||||
}
|
||||
_ => Task::ready(Err(anyhow!(
|
||||
"Copying external entries is not supported for remote worktrees"
|
||||
))),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn expand_entry(
|
||||
&mut self,
|
||||
entry_id: ProjectEntryId,
|
||||
|
@ -1579,6 +1596,87 @@ impl LocalWorktree {
|
|||
})
|
||||
}
|
||||
|
||||
pub fn copy_external_entries(
|
||||
&mut self,
|
||||
target_directory: PathBuf,
|
||||
paths: Vec<Arc<Path>>,
|
||||
overwrite_existing_files: bool,
|
||||
cx: &mut ModelContext<Worktree>,
|
||||
) -> Task<Result<Vec<ProjectEntryId>>> {
|
||||
let worktree_path = self.abs_path().clone();
|
||||
let fs = self.fs.clone();
|
||||
let paths = paths
|
||||
.into_iter()
|
||||
.filter_map(|source| {
|
||||
let file_name = source.file_name()?;
|
||||
let mut target = target_directory.clone();
|
||||
target.push(file_name);
|
||||
|
||||
// Do not allow copying the same file to itself.
|
||||
if source.as_ref() != target.as_path() {
|
||||
Some((source, target))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let paths_to_refresh = paths
|
||||
.iter()
|
||||
.filter_map(|(_, target)| Some(target.strip_prefix(&worktree_path).ok()?.into()))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
cx.spawn(|this, cx| async move {
|
||||
cx.background_executor()
|
||||
.spawn(async move {
|
||||
for (source, target) in paths {
|
||||
copy_recursive(
|
||||
fs.as_ref(),
|
||||
&source,
|
||||
&target,
|
||||
fs::CopyOptions {
|
||||
overwrite: overwrite_existing_files,
|
||||
..Default::default()
|
||||
},
|
||||
)
|
||||
.await
|
||||
.with_context(|| {
|
||||
anyhow!("Failed to copy file from {source:?} to {target:?}")
|
||||
})?;
|
||||
}
|
||||
Ok::<(), anyhow::Error>(())
|
||||
})
|
||||
.await
|
||||
.log_err();
|
||||
let mut refresh = cx.read_model(
|
||||
&this.upgrade().with_context(|| "Dropped worktree")?,
|
||||
|this, _| {
|
||||
Ok::<postage::barrier::Receiver, anyhow::Error>(
|
||||
this.as_local()
|
||||
.with_context(|| "Worktree is not local")?
|
||||
.refresh_entries_for_paths(paths_to_refresh.clone()),
|
||||
)
|
||||
},
|
||||
)??;
|
||||
|
||||
cx.background_executor()
|
||||
.spawn(async move {
|
||||
refresh.next().await;
|
||||
Ok::<(), anyhow::Error>(())
|
||||
})
|
||||
.await
|
||||
.log_err();
|
||||
|
||||
let this = this.upgrade().with_context(|| "Dropped worktree")?;
|
||||
cx.read_model(&this, |this, _| {
|
||||
paths_to_refresh
|
||||
.iter()
|
||||
.filter_map(|path| Some(this.entry_for_path(path)?.id))
|
||||
.collect()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
fn expand_entry(
|
||||
&mut self,
|
||||
entry_id: ProjectEntryId,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue