new path picker (#11015)
Still TODO: * Disable the new save-as for local projects * Wire up sending the new path to the remote server Release Notes: - Added the ability to "Save-as" in remote projects --------- Co-authored-by: Nathan <nathan@zed.dev> Co-authored-by: Bennet <bennetbo@gmx.de>
This commit is contained in:
parent
314b723292
commit
664f779eb4
27 changed files with 775 additions and 149 deletions
|
@ -26,7 +26,6 @@ use std::{
|
|||
any::{Any, TypeId},
|
||||
cell::RefCell,
|
||||
ops::Range,
|
||||
path::PathBuf,
|
||||
rc::Rc,
|
||||
sync::Arc,
|
||||
time::Duration,
|
||||
|
@ -196,7 +195,7 @@ pub trait Item: FocusableView + EventEmitter<Self::Event> {
|
|||
fn save_as(
|
||||
&mut self,
|
||||
_project: Model<Project>,
|
||||
_abs_path: PathBuf,
|
||||
_path: ProjectPath,
|
||||
_cx: &mut ViewContext<Self>,
|
||||
) -> Task<Result<()>> {
|
||||
unimplemented!("save_as() must be implemented if can_save() returns true")
|
||||
|
@ -309,7 +308,7 @@ pub trait ItemHandle: 'static + Send {
|
|||
fn save_as(
|
||||
&self,
|
||||
project: Model<Project>,
|
||||
abs_path: PathBuf,
|
||||
path: ProjectPath,
|
||||
cx: &mut WindowContext,
|
||||
) -> Task<Result<()>>;
|
||||
fn reload(&self, project: Model<Project>, cx: &mut WindowContext) -> Task<Result<()>>;
|
||||
|
@ -647,10 +646,10 @@ impl<T: Item> ItemHandle for View<T> {
|
|||
fn save_as(
|
||||
&self,
|
||||
project: Model<Project>,
|
||||
abs_path: PathBuf,
|
||||
path: ProjectPath,
|
||||
cx: &mut WindowContext,
|
||||
) -> Task<anyhow::Result<()>> {
|
||||
self.update(cx, |item, cx| item.save_as(project, abs_path, cx))
|
||||
self.update(cx, |item, cx| item.save_as(project, path, cx))
|
||||
}
|
||||
|
||||
fn reload(&self, project: Model<Project>, cx: &mut WindowContext) -> Task<Result<()>> {
|
||||
|
@ -1126,7 +1125,7 @@ pub mod test {
|
|||
fn save_as(
|
||||
&mut self,
|
||||
_: Model<Project>,
|
||||
_: std::path::PathBuf,
|
||||
_: ProjectPath,
|
||||
_: &mut ViewContext<Self>,
|
||||
) -> Task<anyhow::Result<()>> {
|
||||
self.save_as_count += 1;
|
||||
|
|
|
@ -263,7 +263,7 @@ impl Render for LanguageServerPrompt {
|
|||
PromptLevel::Warning => {
|
||||
Some(DiagnosticSeverity::WARNING)
|
||||
}
|
||||
PromptLevel::Critical => {
|
||||
PromptLevel::Critical | PromptLevel::Destructive => {
|
||||
Some(DiagnosticSeverity::ERROR)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ use std::{
|
|||
any::Any,
|
||||
cmp, fmt, mem,
|
||||
ops::ControlFlow,
|
||||
path::{Path, PathBuf},
|
||||
path::PathBuf,
|
||||
rc::Rc,
|
||||
sync::{
|
||||
atomic::{AtomicUsize, Ordering},
|
||||
|
@ -1322,14 +1322,10 @@ impl Pane {
|
|||
pane.update(cx, |_, cx| item.save(should_format, project, cx))?
|
||||
.await?;
|
||||
} else if can_save_as {
|
||||
let start_abs_path = project
|
||||
.update(cx, |project, cx| {
|
||||
let worktree = project.visible_worktrees(cx).next()?;
|
||||
Some(worktree.read(cx).as_local()?.abs_path().to_path_buf())
|
||||
})?
|
||||
.unwrap_or_else(|| Path::new("").into());
|
||||
|
||||
let abs_path = cx.update(|cx| cx.prompt_for_new_path(&start_abs_path))?;
|
||||
let abs_path = pane.update(cx, |pane, cx| {
|
||||
pane.workspace
|
||||
.update(cx, |workspace, cx| workspace.prompt_for_new_path(cx))
|
||||
})??;
|
||||
if let Some(abs_path) = abs_path.await.ok().flatten() {
|
||||
pane.update(cx, |_, cx| item.save_as(project, abs_path, cx))?
|
||||
.await?;
|
||||
|
|
|
@ -544,6 +544,10 @@ pub enum OpenVisible {
|
|||
OnlyDirectories,
|
||||
}
|
||||
|
||||
type PromptForNewPath = Box<
|
||||
dyn Fn(&mut Workspace, &mut ViewContext<Workspace>) -> oneshot::Receiver<Option<ProjectPath>>,
|
||||
>;
|
||||
|
||||
/// Collects everything project-related for a certain window opened.
|
||||
/// In some way, is a counterpart of a window, as the [`WindowHandle`] could be downcast into `Workspace`.
|
||||
///
|
||||
|
@ -585,6 +589,7 @@ pub struct Workspace {
|
|||
bounds: Bounds<Pixels>,
|
||||
centered_layout: bool,
|
||||
bounds_save_task_queued: Option<Task<()>>,
|
||||
on_prompt_for_new_path: Option<PromptForNewPath>,
|
||||
}
|
||||
|
||||
impl EventEmitter<Event> for Workspace {}
|
||||
|
@ -875,6 +880,7 @@ impl Workspace {
|
|||
bounds: Default::default(),
|
||||
centered_layout: false,
|
||||
bounds_save_task_queued: None,
|
||||
on_prompt_for_new_path: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1223,6 +1229,59 @@ impl Workspace {
|
|||
cx.notify();
|
||||
}
|
||||
|
||||
pub fn set_prompt_for_new_path(&mut self, prompt: PromptForNewPath) {
|
||||
self.on_prompt_for_new_path = Some(prompt)
|
||||
}
|
||||
|
||||
pub fn prompt_for_new_path(
|
||||
&mut self,
|
||||
cx: &mut ViewContext<Self>,
|
||||
) -> oneshot::Receiver<Option<ProjectPath>> {
|
||||
if let Some(prompt) = self.on_prompt_for_new_path.take() {
|
||||
let rx = prompt(self, cx);
|
||||
self.on_prompt_for_new_path = Some(prompt);
|
||||
rx
|
||||
} else {
|
||||
let start_abs_path = self
|
||||
.project
|
||||
.update(cx, |project, cx| {
|
||||
let worktree = project.visible_worktrees(cx).next()?;
|
||||
Some(worktree.read(cx).as_local()?.abs_path().to_path_buf())
|
||||
})
|
||||
.unwrap_or_else(|| Path::new("").into());
|
||||
|
||||
let (tx, rx) = oneshot::channel();
|
||||
let abs_path = cx.prompt_for_new_path(&start_abs_path);
|
||||
cx.spawn(|this, mut cx| async move {
|
||||
let abs_path = abs_path.await?;
|
||||
let project_path = abs_path.and_then(|abs_path| {
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.project.update(cx, |project, cx| {
|
||||
project.find_or_create_local_worktree(abs_path, true, cx)
|
||||
})
|
||||
})
|
||||
.ok()
|
||||
});
|
||||
|
||||
if let Some(project_path) = project_path {
|
||||
let (worktree, path) = project_path.await?;
|
||||
let worktree_id = worktree.read_with(&cx, |worktree, _| worktree.id())?;
|
||||
tx.send(Some(ProjectPath {
|
||||
worktree_id,
|
||||
path: path.into(),
|
||||
}))
|
||||
.ok();
|
||||
} else {
|
||||
tx.send(None).ok();
|
||||
}
|
||||
anyhow::Ok(())
|
||||
})
|
||||
.detach_and_log_err(cx);
|
||||
|
||||
rx
|
||||
}
|
||||
}
|
||||
|
||||
pub fn titlebar_item(&self) -> Option<AnyView> {
|
||||
self.titlebar_item.clone()
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue