Eliminate OpenPaths global action for workspace and replace with methods
We no longer want to invoke this with dispatch_action.
This commit is contained in:
parent
6cbc1dcd87
commit
06c01a5937
3 changed files with 121 additions and 94 deletions
|
@ -5,30 +5,30 @@ use gpui::{
|
||||||
actions,
|
actions,
|
||||||
anyhow::Result,
|
anyhow::Result,
|
||||||
elements::{Flex, ParentElement},
|
elements::{Flex, ParentElement},
|
||||||
AnyElement, AppContext, Element, Task, ViewContext,
|
AnyElement, AppContext, Element, Task, ViewContext, WeakViewHandle,
|
||||||
};
|
};
|
||||||
use highlighted_workspace_location::HighlightedWorkspaceLocation;
|
use highlighted_workspace_location::HighlightedWorkspaceLocation;
|
||||||
use ordered_float::OrderedFloat;
|
use ordered_float::OrderedFloat;
|
||||||
use picker::{Picker, PickerDelegate, PickerEvent};
|
use picker::{Picker, PickerDelegate, PickerEvent};
|
||||||
use settings::Settings;
|
use settings::Settings;
|
||||||
use std::sync::Arc;
|
use std::sync::{Arc, Weak};
|
||||||
use workspace::{
|
use workspace::{
|
||||||
notifications::simple_message_notification::MessageNotification, OpenPaths, Workspace,
|
notifications::simple_message_notification::MessageNotification, AppState, Workspace,
|
||||||
WorkspaceLocation, WORKSPACE_DB,
|
WorkspaceLocation, WORKSPACE_DB,
|
||||||
};
|
};
|
||||||
|
|
||||||
actions!(projects, [OpenRecent]);
|
actions!(projects, [OpenRecent]);
|
||||||
|
|
||||||
pub fn init(cx: &mut AppContext) {
|
pub fn init(cx: &mut AppContext, app_state: Weak<AppState>) {
|
||||||
cx.add_async_action(toggle);
|
cx.add_async_action(
|
||||||
|
move |_: &mut Workspace, _: &OpenRecent, cx: &mut ViewContext<Workspace>| {
|
||||||
|
toggle(app_state.clone(), cx)
|
||||||
|
},
|
||||||
|
);
|
||||||
RecentProjects::init(cx);
|
RecentProjects::init(cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn toggle(
|
fn toggle(app_state: Weak<AppState>, cx: &mut ViewContext<Workspace>) -> Option<Task<Result<()>>> {
|
||||||
_: &mut Workspace,
|
|
||||||
_: &OpenRecent,
|
|
||||||
cx: &mut ViewContext<Workspace>,
|
|
||||||
) -> Option<Task<Result<()>>> {
|
|
||||||
Some(cx.spawn(|workspace, mut cx| async move {
|
Some(cx.spawn(|workspace, mut cx| async move {
|
||||||
let workspace_locations: Vec<_> = cx
|
let workspace_locations: Vec<_> = cx
|
||||||
.background()
|
.background()
|
||||||
|
@ -46,9 +46,17 @@ fn toggle(
|
||||||
workspace.update(&mut cx, |workspace, cx| {
|
workspace.update(&mut cx, |workspace, cx| {
|
||||||
if !workspace_locations.is_empty() {
|
if !workspace_locations.is_empty() {
|
||||||
workspace.toggle_modal(cx, |_, cx| {
|
workspace.toggle_modal(cx, |_, cx| {
|
||||||
|
let workspace = cx.weak_handle();
|
||||||
cx.add_view(|cx| {
|
cx.add_view(|cx| {
|
||||||
RecentProjects::new(RecentProjectsDelegate::new(workspace_locations), cx)
|
RecentProjects::new(
|
||||||
.with_max_size(800., 1200.)
|
RecentProjectsDelegate::new(
|
||||||
|
workspace,
|
||||||
|
workspace_locations,
|
||||||
|
app_state.clone(),
|
||||||
|
),
|
||||||
|
cx,
|
||||||
|
)
|
||||||
|
.with_max_size(800., 1200.)
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
@ -64,15 +72,23 @@ fn toggle(
|
||||||
type RecentProjects = Picker<RecentProjectsDelegate>;
|
type RecentProjects = Picker<RecentProjectsDelegate>;
|
||||||
|
|
||||||
struct RecentProjectsDelegate {
|
struct RecentProjectsDelegate {
|
||||||
|
workspace: WeakViewHandle<Workspace>,
|
||||||
workspace_locations: Vec<WorkspaceLocation>,
|
workspace_locations: Vec<WorkspaceLocation>,
|
||||||
|
app_state: Weak<AppState>,
|
||||||
selected_match_index: usize,
|
selected_match_index: usize,
|
||||||
matches: Vec<StringMatch>,
|
matches: Vec<StringMatch>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RecentProjectsDelegate {
|
impl RecentProjectsDelegate {
|
||||||
fn new(workspace_locations: Vec<WorkspaceLocation>) -> Self {
|
fn new(
|
||||||
|
workspace: WeakViewHandle<Workspace>,
|
||||||
|
workspace_locations: Vec<WorkspaceLocation>,
|
||||||
|
app_state: Weak<AppState>,
|
||||||
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
workspace,
|
||||||
workspace_locations,
|
workspace_locations,
|
||||||
|
app_state,
|
||||||
selected_match_index: 0,
|
selected_match_index: 0,
|
||||||
matches: Default::default(),
|
matches: Default::default(),
|
||||||
}
|
}
|
||||||
|
@ -139,11 +155,22 @@ impl PickerDelegate for RecentProjectsDelegate {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn confirm(&mut self, cx: &mut ViewContext<RecentProjects>) {
|
fn confirm(&mut self, cx: &mut ViewContext<RecentProjects>) {
|
||||||
if let Some(selected_match) = &self.matches.get(self.selected_index()) {
|
if let Some(((selected_match, workspace), app_state)) = self
|
||||||
|
.matches
|
||||||
|
.get(self.selected_index())
|
||||||
|
.zip(self.workspace.upgrade(cx))
|
||||||
|
.zip(self.app_state.upgrade())
|
||||||
|
{
|
||||||
let workspace_location = &self.workspace_locations[selected_match.candidate_id];
|
let workspace_location = &self.workspace_locations[selected_match.candidate_id];
|
||||||
cx.dispatch_action(OpenPaths {
|
workspace
|
||||||
paths: workspace_location.paths().as_ref().clone(),
|
.update(cx, |workspace, cx| {
|
||||||
});
|
workspace.open_workspace_for_paths(
|
||||||
|
workspace_location.paths().as_ref().clone(),
|
||||||
|
app_state,
|
||||||
|
cx,
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.detach_and_log_err(cx);
|
||||||
cx.emit(PickerEvent::Dismiss);
|
cx.emit(PickerEvent::Dismiss);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -219,7 +219,6 @@ pub type WorkspaceId = i64;
|
||||||
impl_internal_actions!(
|
impl_internal_actions!(
|
||||||
workspace,
|
workspace,
|
||||||
[
|
[
|
||||||
OpenPaths,
|
|
||||||
ToggleFollow,
|
ToggleFollow,
|
||||||
JoinProject,
|
JoinProject,
|
||||||
OpenSharedScreen,
|
OpenSharedScreen,
|
||||||
|
@ -235,81 +234,53 @@ pub fn init(app_state: Arc<AppState>, cx: &mut AppContext) {
|
||||||
dock::init(cx);
|
dock::init(cx);
|
||||||
notifications::init(cx);
|
notifications::init(cx);
|
||||||
|
|
||||||
cx.add_global_action(|_: &Open, cx: &mut AppContext| {
|
|
||||||
let mut paths = cx.prompt_for_paths(PathPromptOptions {
|
|
||||||
files: true,
|
|
||||||
directories: true,
|
|
||||||
multiple: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
cx.spawn(|mut cx| async move {
|
|
||||||
if let Some(paths) = paths.recv().await.flatten() {
|
|
||||||
cx.update(|cx| cx.dispatch_global_action(OpenPaths { paths }));
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.detach();
|
|
||||||
});
|
|
||||||
cx.add_action(|_, _: &Open, cx: &mut ViewContext<Workspace>| {
|
|
||||||
let mut paths = cx.prompt_for_paths(PathPromptOptions {
|
|
||||||
files: true,
|
|
||||||
directories: true,
|
|
||||||
multiple: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
let handle = cx.handle().downgrade();
|
|
||||||
cx.spawn(|_, mut cx| async move {
|
|
||||||
if let Some(paths) = paths.recv().await.flatten() {
|
|
||||||
cx.update(|cx| {
|
|
||||||
cx.dispatch_action_at(handle.window_id(), handle.id(), OpenPaths { paths })
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.detach();
|
|
||||||
});
|
|
||||||
cx.add_global_action({
|
cx.add_global_action({
|
||||||
let app_state = Arc::downgrade(&app_state);
|
let app_state = Arc::downgrade(&app_state);
|
||||||
move |action: &OpenPaths, cx: &mut AppContext| {
|
move |_: &Open, cx: &mut AppContext| {
|
||||||
|
let mut paths = cx.prompt_for_paths(PathPromptOptions {
|
||||||
|
files: true,
|
||||||
|
directories: true,
|
||||||
|
multiple: true,
|
||||||
|
});
|
||||||
|
|
||||||
if let Some(app_state) = app_state.upgrade() {
|
if let Some(app_state) = app_state.upgrade() {
|
||||||
open_paths(&action.paths, &app_state, None, cx).detach();
|
cx.spawn(move |mut cx| async move {
|
||||||
}
|
if let Some(paths) = paths.recv().await.flatten() {
|
||||||
}
|
cx.update(|cx| {
|
||||||
});
|
open_paths(&paths, &app_state, None, cx).detach_and_log_err(cx)
|
||||||
cx.add_async_action({
|
});
|
||||||
let app_state = Arc::downgrade(&app_state);
|
|
||||||
move |workspace, action: &OpenPaths, cx: &mut ViewContext<Workspace>| {
|
|
||||||
if !workspace.project().read(cx).is_local() {
|
|
||||||
cx.propagate_action();
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
let app_state = app_state.upgrade()?;
|
|
||||||
let window_id = cx.window_id();
|
|
||||||
let action = action.clone();
|
|
||||||
let is_remote = workspace.project.read(cx).is_remote();
|
|
||||||
let has_worktree = workspace.project.read(cx).worktrees(cx).next().is_some();
|
|
||||||
let has_dirty_items = workspace.items(cx).any(|item| item.is_dirty(cx));
|
|
||||||
let close_task = if is_remote || has_worktree || has_dirty_items {
|
|
||||||
None
|
|
||||||
} else {
|
|
||||||
Some(workspace.prepare_to_close(false, cx))
|
|
||||||
};
|
|
||||||
|
|
||||||
Some(cx.spawn(|_, mut cx| async move {
|
|
||||||
let window_id_to_replace = if let Some(close_task) = close_task {
|
|
||||||
if !close_task.await? {
|
|
||||||
return Ok(());
|
|
||||||
}
|
}
|
||||||
Some(window_id)
|
})
|
||||||
} else {
|
.detach();
|
||||||
None
|
}
|
||||||
};
|
|
||||||
cx.update(|cx| open_paths(&action.paths, &app_state, window_id_to_replace, cx))
|
|
||||||
.await?;
|
|
||||||
Ok(())
|
|
||||||
}))
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
cx.add_action({
|
||||||
|
let app_state = Arc::downgrade(&app_state);
|
||||||
|
move |_, _: &Open, cx: &mut ViewContext<Workspace>| {
|
||||||
|
let mut paths = cx.prompt_for_paths(PathPromptOptions {
|
||||||
|
files: true,
|
||||||
|
directories: true,
|
||||||
|
multiple: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
if let Some(app_state) = app_state.upgrade() {
|
||||||
|
cx.spawn(|this, mut cx| async move {
|
||||||
|
if let Some(paths) = paths.recv().await.flatten() {
|
||||||
|
if let Some(task) = this
|
||||||
|
.update(&mut cx, |this, cx| {
|
||||||
|
this.open_workspace_for_paths(paths, app_state, cx)
|
||||||
|
})
|
||||||
|
.log_err()
|
||||||
|
{
|
||||||
|
task.await.log_err();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.detach();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
cx.add_global_action({
|
cx.add_global_action({
|
||||||
let app_state = Arc::downgrade(&app_state);
|
let app_state = Arc::downgrade(&app_state);
|
||||||
move |_: &NewWindow, cx: &mut AppContext| {
|
move |_: &NewWindow, cx: &mut AppContext| {
|
||||||
|
@ -1179,6 +1150,37 @@ impl Workspace {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn open_workspace_for_paths(
|
||||||
|
&mut self,
|
||||||
|
paths: Vec<PathBuf>,
|
||||||
|
app_state: Arc<AppState>,
|
||||||
|
cx: &mut ViewContext<Self>,
|
||||||
|
) -> Task<Result<()>> {
|
||||||
|
let window_id = cx.window_id();
|
||||||
|
let is_remote = self.project.read(cx).is_remote();
|
||||||
|
let has_worktree = self.project.read(cx).worktrees(cx).next().is_some();
|
||||||
|
let has_dirty_items = self.items(cx).any(|item| item.is_dirty(cx));
|
||||||
|
let close_task = if is_remote || has_worktree || has_dirty_items {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(self.prepare_to_close(false, cx))
|
||||||
|
};
|
||||||
|
|
||||||
|
cx.spawn(|_, mut cx| async move {
|
||||||
|
let window_id_to_replace = if let Some(close_task) = close_task {
|
||||||
|
if !close_task.await? {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
Some(window_id)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
cx.update(|cx| open_paths(&paths, &app_state, window_id_to_replace, cx))
|
||||||
|
.await?;
|
||||||
|
Ok(())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
#[allow(clippy::type_complexity)]
|
#[allow(clippy::type_complexity)]
|
||||||
pub fn open_paths(
|
pub fn open_paths(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
|
|
@ -44,7 +44,7 @@ use theme::ThemeRegistry;
|
||||||
use util::{channel::RELEASE_CHANNEL, paths, ResultExt, TryFutureExt};
|
use util::{channel::RELEASE_CHANNEL, paths, ResultExt, TryFutureExt};
|
||||||
use workspace::{
|
use workspace::{
|
||||||
self, dock::FocusDock, item::ItemHandle, notifications::NotifyResultExt, AppState, NewFile,
|
self, dock::FocusDock, item::ItemHandle, notifications::NotifyResultExt, AppState, NewFile,
|
||||||
OpenPaths, Workspace,
|
Workspace,
|
||||||
};
|
};
|
||||||
use zed::{self, build_window_options, initialize_workspace, languages, menus, OpenSettings};
|
use zed::{self, build_window_options, initialize_workspace, languages, menus, OpenSettings};
|
||||||
|
|
||||||
|
@ -160,7 +160,6 @@ fn main() {
|
||||||
vim::init(cx);
|
vim::init(cx);
|
||||||
terminal_view::init(cx);
|
terminal_view::init(cx);
|
||||||
theme_testbench::init(cx);
|
theme_testbench::init(cx);
|
||||||
recent_projects::init(cx);
|
|
||||||
copilot::init(http.clone(), node_runtime, cx);
|
copilot::init(http.clone(), node_runtime, cx);
|
||||||
|
|
||||||
cx.spawn(|cx| watch_themes(fs.clone(), themes.clone(), cx))
|
cx.spawn(|cx| watch_themes(fs.clone(), themes.clone(), cx))
|
||||||
|
@ -194,6 +193,7 @@ fn main() {
|
||||||
auto_update::init(http, client::ZED_SERVER_URL.clone(), cx);
|
auto_update::init(http, client::ZED_SERVER_URL.clone(), cx);
|
||||||
|
|
||||||
workspace::init(app_state.clone(), cx);
|
workspace::init(app_state.clone(), cx);
|
||||||
|
recent_projects::init(cx, Arc::downgrade(&app_state));
|
||||||
|
|
||||||
journal::init(app_state.clone(), cx);
|
journal::init(app_state.clone(), cx);
|
||||||
language_selector::init(app_state.clone(), cx);
|
language_selector::init(app_state.clone(), cx);
|
||||||
|
@ -212,7 +212,7 @@ fn main() {
|
||||||
cx.spawn(|cx| async move { restore_or_create_workspace(&app_state, cx).await })
|
cx.spawn(|cx| async move { restore_or_create_workspace(&app_state, cx).await })
|
||||||
.detach()
|
.detach()
|
||||||
} else {
|
} else {
|
||||||
cx.dispatch_global_action(OpenPaths { paths });
|
workspace::open_paths(&paths, &app_state, None, cx).detach_and_log_err(cx);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if let Ok(Some(connection)) = cli_connections_rx.try_next() {
|
if let Ok(Some(connection)) = cli_connections_rx.try_next() {
|
||||||
|
@ -267,11 +267,9 @@ fn main() {
|
||||||
|
|
||||||
async fn restore_or_create_workspace(app_state: &Arc<AppState>, mut cx: AsyncAppContext) {
|
async fn restore_or_create_workspace(app_state: &Arc<AppState>, mut cx: AsyncAppContext) {
|
||||||
if let Some(location) = workspace::last_opened_workspace_paths().await {
|
if let Some(location) = workspace::last_opened_workspace_paths().await {
|
||||||
cx.update(|cx| {
|
cx.update(|cx| workspace::open_paths(location.paths().as_ref(), app_state, None, cx))
|
||||||
cx.dispatch_global_action(OpenPaths {
|
.await
|
||||||
paths: location.paths().as_ref().clone(),
|
.log_err();
|
||||||
})
|
|
||||||
});
|
|
||||||
} else if matches!(KEY_VALUE_STORE.read_kvp(FIRST_OPEN), Ok(None)) {
|
} else if matches!(KEY_VALUE_STORE.read_kvp(FIRST_OPEN), Ok(None)) {
|
||||||
cx.update(|cx| show_welcome_experience(app_state, cx));
|
cx.update(|cx| show_welcome_experience(app_state, cx));
|
||||||
} else {
|
} else {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue