Remove JoinProject
internal action
This commit is contained in:
parent
f881f9e3d8
commit
d953729233
12 changed files with 302 additions and 287 deletions
|
@ -25,7 +25,6 @@ use client::{
|
|||
use collections::{hash_map, HashMap, HashSet};
|
||||
use dock::{Dock, DockDefaultItemFactory, ToggleDockButton};
|
||||
use drag_and_drop::DragAndDrop;
|
||||
use fs::{self, Fs};
|
||||
use futures::{
|
||||
channel::{mpsc, oneshot},
|
||||
future::try_join_all,
|
||||
|
@ -135,12 +134,6 @@ pub struct OpenPaths {
|
|||
#[derive(Clone, Deserialize, PartialEq)]
|
||||
pub struct ActivatePane(pub usize);
|
||||
|
||||
#[derive(Clone, PartialEq)]
|
||||
pub struct JoinProject {
|
||||
pub project_id: u64,
|
||||
pub follow_user_id: u64,
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq)]
|
||||
pub struct OpenSharedScreen {
|
||||
pub peer_id: PeerId,
|
||||
|
@ -216,7 +209,6 @@ pub type WorkspaceId = i64;
|
|||
impl_internal_actions!(
|
||||
workspace,
|
||||
[
|
||||
JoinProject,
|
||||
OpenSharedScreen,
|
||||
RemoveWorktreeFromProject,
|
||||
SplitWithItem,
|
||||
|
@ -524,10 +516,7 @@ pub enum Event {
|
|||
|
||||
pub struct Workspace {
|
||||
weak_self: WeakViewHandle<Self>,
|
||||
client: Arc<Client>,
|
||||
user_store: ModelHandle<client::UserStore>,
|
||||
remote_entity_subscription: Option<client::Subscription>,
|
||||
fs: Arc<dyn Fs>,
|
||||
modal: Option<AnyViewHandle>,
|
||||
center: PaneGroup,
|
||||
left_sidebar: ViewHandle<Sidebar>,
|
||||
|
@ -548,7 +537,7 @@ pub struct Workspace {
|
|||
active_call: Option<(ModelHandle<ActiveCall>, Vec<gpui::Subscription>)>,
|
||||
leader_updates_tx: mpsc::UnboundedSender<(PeerId, proto::UpdateFollowers)>,
|
||||
database_id: WorkspaceId,
|
||||
background_actions: BackgroundActions,
|
||||
app_state: Arc<AppState>,
|
||||
_window_subscriptions: [Subscription; 3],
|
||||
_apply_leader_updates: Task<Result<()>>,
|
||||
_observe_current_user: Task<Result<()>>,
|
||||
|
@ -578,8 +567,7 @@ impl Workspace {
|
|||
serialized_workspace: Option<SerializedWorkspace>,
|
||||
workspace_id: WorkspaceId,
|
||||
project: ModelHandle<Project>,
|
||||
dock_default_factory: DockDefaultItemFactory,
|
||||
background_actions: BackgroundActions,
|
||||
app_state: Arc<AppState>,
|
||||
cx: &mut ViewContext<Self>,
|
||||
) -> Self {
|
||||
cx.observe(&project, |_, _, cx| cx.notify()).detach();
|
||||
|
@ -616,8 +604,8 @@ impl Workspace {
|
|||
|
||||
let weak_handle = cx.weak_handle();
|
||||
|
||||
let center_pane =
|
||||
cx.add_view(|cx| Pane::new(weak_handle.clone(), None, background_actions, cx));
|
||||
let center_pane = cx
|
||||
.add_view(|cx| Pane::new(weak_handle.clone(), None, app_state.background_actions, cx));
|
||||
let pane_id = center_pane.id();
|
||||
cx.subscribe(¢er_pane, move |this, _, event, cx| {
|
||||
this.handle_pane_event(pane_id, event, cx)
|
||||
|
@ -625,14 +613,15 @@ impl Workspace {
|
|||
.detach();
|
||||
cx.focus(¢er_pane);
|
||||
cx.emit(Event::PaneAdded(center_pane.clone()));
|
||||
let dock = Dock::new(dock_default_factory, background_actions, cx);
|
||||
let dock = Dock::new(
|
||||
app_state.dock_default_item_factory,
|
||||
app_state.background_actions,
|
||||
cx,
|
||||
);
|
||||
let dock_pane = dock.pane().clone();
|
||||
|
||||
let fs = project.read(cx).fs().clone();
|
||||
let user_store = project.read(cx).user_store();
|
||||
let client = project.read(cx).client();
|
||||
let mut current_user = user_store.read(cx).watch_current_user();
|
||||
let mut connection_status = client.status();
|
||||
let mut current_user = app_state.user_store.read(cx).watch_current_user();
|
||||
let mut connection_status = app_state.client.status();
|
||||
let _observe_current_user = cx.spawn(|this, mut cx| async move {
|
||||
current_user.recv().await;
|
||||
connection_status.recv().await;
|
||||
|
@ -725,10 +714,7 @@ impl Workspace {
|
|||
status_bar,
|
||||
titlebar_item: None,
|
||||
notifications: Default::default(),
|
||||
client,
|
||||
remote_entity_subscription: None,
|
||||
user_store,
|
||||
fs,
|
||||
left_sidebar,
|
||||
right_sidebar,
|
||||
project: project.clone(),
|
||||
|
@ -738,7 +724,7 @@ impl Workspace {
|
|||
window_edited: false,
|
||||
active_call,
|
||||
database_id: workspace_id,
|
||||
background_actions,
|
||||
app_state,
|
||||
_observe_current_user,
|
||||
_apply_leader_updates,
|
||||
leader_updates_tx,
|
||||
|
@ -827,8 +813,7 @@ impl Workspace {
|
|||
serialized_workspace,
|
||||
workspace_id,
|
||||
project_handle.clone(),
|
||||
app_state.dock_default_item_factory,
|
||||
app_state.background_actions,
|
||||
app_state.clone(),
|
||||
cx,
|
||||
);
|
||||
(app_state.initialize_workspace)(&mut workspace, &app_state, cx);
|
||||
|
@ -938,8 +923,12 @@ impl Workspace {
|
|||
&self.status_bar
|
||||
}
|
||||
|
||||
pub fn app_state(&self) -> &Arc<AppState> {
|
||||
&self.app_state
|
||||
}
|
||||
|
||||
pub fn user_store(&self) -> &ModelHandle<UserStore> {
|
||||
&self.user_store
|
||||
&self.app_state.user_store
|
||||
}
|
||||
|
||||
pub fn project(&self) -> &ModelHandle<Project> {
|
||||
|
@ -947,7 +936,7 @@ impl Workspace {
|
|||
}
|
||||
|
||||
pub fn client(&self) -> &Client {
|
||||
&self.client
|
||||
&self.app_state.client
|
||||
}
|
||||
|
||||
pub fn set_titlebar_item(&mut self, item: AnyViewHandle, cx: &mut ViewContext<Self>) {
|
||||
|
@ -1183,7 +1172,7 @@ impl Workspace {
|
|||
visible: bool,
|
||||
cx: &mut ViewContext<Self>,
|
||||
) -> Task<Vec<Option<Result<Box<dyn ItemHandle>, anyhow::Error>>>> {
|
||||
let fs = self.fs.clone();
|
||||
let fs = self.app_state.fs.clone();
|
||||
|
||||
// Sort the paths to ensure we add worktrees for parents before their children.
|
||||
abs_paths.sort_unstable();
|
||||
|
@ -1494,8 +1483,14 @@ impl Workspace {
|
|||
}
|
||||
|
||||
fn add_pane(&mut self, cx: &mut ViewContext<Self>) -> ViewHandle<Pane> {
|
||||
let pane =
|
||||
cx.add_view(|cx| Pane::new(self.weak_handle(), None, self.background_actions, cx));
|
||||
let pane = cx.add_view(|cx| {
|
||||
Pane::new(
|
||||
self.weak_handle(),
|
||||
None,
|
||||
self.app_state.background_actions,
|
||||
cx,
|
||||
)
|
||||
});
|
||||
let pane_id = pane.id();
|
||||
cx.subscribe(&pane, move |this, _, event, cx| {
|
||||
this.handle_pane_event(pane_id, event, cx)
|
||||
|
@ -1688,7 +1683,7 @@ impl Workspace {
|
|||
proto::update_followers::Variant::UpdateActiveView(proto::UpdateActiveView {
|
||||
id: self.active_item(cx).and_then(|item| {
|
||||
item.to_followable_item_handle(cx)?
|
||||
.remote_id(&self.client, cx)
|
||||
.remote_id(&self.app_state.client, cx)
|
||||
.map(|id| id.to_proto())
|
||||
}),
|
||||
leader_id: self.leader_for_pane(&pane),
|
||||
|
@ -1857,8 +1852,11 @@ impl Workspace {
|
|||
|
||||
fn project_remote_id_changed(&mut self, remote_id: Option<u64>, cx: &mut ViewContext<Self>) {
|
||||
if let Some(remote_id) = remote_id {
|
||||
self.remote_entity_subscription =
|
||||
Some(self.client.add_view_for_remote_entity(remote_id, cx));
|
||||
self.remote_entity_subscription = Some(
|
||||
self.app_state
|
||||
.client
|
||||
.add_view_for_remote_entity(remote_id, cx),
|
||||
);
|
||||
} else {
|
||||
self.remote_entity_subscription.take();
|
||||
}
|
||||
|
@ -1898,7 +1896,7 @@ impl Workspace {
|
|||
cx.notify();
|
||||
|
||||
let project_id = self.project.read(cx).remote_id()?;
|
||||
let request = self.client.request(proto::Follow {
|
||||
let request = self.app_state.client.request(proto::Follow {
|
||||
project_id,
|
||||
leader_id: Some(leader_id),
|
||||
});
|
||||
|
@ -1977,7 +1975,8 @@ impl Workspace {
|
|||
if states_by_pane.is_empty() {
|
||||
self.follower_states_by_leader.remove(&leader_id);
|
||||
if let Some(project_id) = self.project.read(cx).remote_id() {
|
||||
self.client
|
||||
self.app_state
|
||||
.client
|
||||
.send(proto::Unfollow {
|
||||
project_id,
|
||||
leader_id: Some(leader_id),
|
||||
|
@ -2158,7 +2157,7 @@ impl Workspace {
|
|||
mut cx: AsyncAppContext,
|
||||
) -> Result<proto::FollowResponse> {
|
||||
this.update(&mut cx, |this, cx| {
|
||||
let client = &this.client;
|
||||
let client = &this.app_state.client;
|
||||
this.leader_state
|
||||
.followers
|
||||
.insert(envelope.original_sender_id()?);
|
||||
|
@ -2366,7 +2365,8 @@ impl Workspace {
|
|||
) -> Option<()> {
|
||||
let project_id = self.project.read(cx).remote_id()?;
|
||||
if !self.leader_state.followers.is_empty() {
|
||||
self.client
|
||||
self.app_state
|
||||
.client
|
||||
.send(proto::UpdateFollowers {
|
||||
project_id,
|
||||
follower_ids: self.leader_state.followers.iter().copied().collect(),
|
||||
|
@ -2698,7 +2698,18 @@ impl Workspace {
|
|||
|
||||
#[cfg(any(test, feature = "test-support"))]
|
||||
pub fn test_new(project: ModelHandle<Project>, cx: &mut ViewContext<Self>) -> Self {
|
||||
Self::new(None, 0, project, |_, _| None, || &[], cx)
|
||||
let app_state = Arc::new(AppState {
|
||||
languages: project.read(cx).languages().clone(),
|
||||
themes: ThemeRegistry::new((), cx.font_cache().clone()),
|
||||
client: project.read(cx).client(),
|
||||
user_store: project.read(cx).user_store(),
|
||||
fs: project.read(cx).fs().clone(),
|
||||
build_window_options: |_, _, _| Default::default(),
|
||||
initialize_workspace: |_, _, _| {},
|
||||
dock_default_item_factory: |_, _| None,
|
||||
background_actions: || &[],
|
||||
});
|
||||
Self::new(None, 0, project, app_state, cx)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2784,6 +2795,7 @@ impl View for Workspace {
|
|||
&self.follower_states_by_leader,
|
||||
self.active_call(),
|
||||
self.active_pane(),
|
||||
&self.app_state,
|
||||
cx,
|
||||
))
|
||||
.flex(1., true),
|
||||
|
@ -3015,6 +3027,87 @@ pub fn open_new(
|
|||
})
|
||||
}
|
||||
|
||||
pub fn join_remote_project(
|
||||
project_id: u64,
|
||||
follow_user_id: u64,
|
||||
app_state: Arc<AppState>,
|
||||
cx: &mut AppContext,
|
||||
) -> Task<Result<()>> {
|
||||
cx.spawn(|mut cx| async move {
|
||||
let existing_workspace = cx.update(|cx| {
|
||||
cx.window_ids()
|
||||
.filter_map(|window_id| cx.root_view(window_id)?.clone().downcast::<Workspace>())
|
||||
.find(|workspace| {
|
||||
workspace.read(cx).project().read(cx).remote_id() == Some(project_id)
|
||||
})
|
||||
});
|
||||
|
||||
let workspace = if let Some(existing_workspace) = existing_workspace {
|
||||
existing_workspace.downgrade()
|
||||
} else {
|
||||
let active_call = cx.read(ActiveCall::global);
|
||||
let room = active_call
|
||||
.read_with(&cx, |call, _| call.room().cloned())
|
||||
.ok_or_else(|| anyhow!("not in a call"))?;
|
||||
let project = room
|
||||
.update(&mut cx, |room, cx| {
|
||||
room.join_project(
|
||||
project_id,
|
||||
app_state.languages.clone(),
|
||||
app_state.fs.clone(),
|
||||
cx,
|
||||
)
|
||||
})
|
||||
.await?;
|
||||
|
||||
let (_, workspace) = cx.add_window(
|
||||
(app_state.build_window_options)(None, None, cx.platform().as_ref()),
|
||||
|cx| {
|
||||
let mut workspace =
|
||||
Workspace::new(Default::default(), 0, project, app_state.clone(), cx);
|
||||
(app_state.initialize_workspace)(&mut workspace, &app_state, cx);
|
||||
workspace
|
||||
},
|
||||
);
|
||||
workspace.downgrade()
|
||||
};
|
||||
|
||||
cx.activate_window(workspace.window_id());
|
||||
cx.platform().activate(true);
|
||||
|
||||
workspace.update(&mut cx, |workspace, cx| {
|
||||
if let Some(room) = ActiveCall::global(cx).read(cx).room().cloned() {
|
||||
let follow_peer_id = room
|
||||
.read(cx)
|
||||
.remote_participants()
|
||||
.iter()
|
||||
.find(|(_, participant)| participant.user.id == follow_user_id)
|
||||
.map(|(_, p)| p.peer_id)
|
||||
.or_else(|| {
|
||||
// If we couldn't follow the given user, follow the host instead.
|
||||
let collaborator = workspace
|
||||
.project()
|
||||
.read(cx)
|
||||
.collaborators()
|
||||
.values()
|
||||
.find(|collaborator| collaborator.replica_id == 0)?;
|
||||
Some(collaborator.peer_id)
|
||||
});
|
||||
|
||||
if let Some(follow_peer_id) = follow_peer_id {
|
||||
if !workspace.is_being_followed(follow_peer_id) {
|
||||
workspace
|
||||
.toggle_follow(follow_peer_id, cx)
|
||||
.map(|follow| follow.detach_and_log_err(cx));
|
||||
}
|
||||
}
|
||||
}
|
||||
})?;
|
||||
|
||||
anyhow::Ok(())
|
||||
})
|
||||
}
|
||||
|
||||
fn parse_pixel_position_env_var(value: &str) -> Option<Vector2F> {
|
||||
let mut parts = value.split(',');
|
||||
let width: usize = parts.next()?.parse().ok()?;
|
||||
|
@ -3041,16 +3134,7 @@ mod tests {
|
|||
|
||||
let fs = FakeFs::new(cx.background());
|
||||
let project = Project::test(fs, [], cx).await;
|
||||
let (_, workspace) = cx.add_window(|cx| {
|
||||
Workspace::new(
|
||||
Default::default(),
|
||||
0,
|
||||
project.clone(),
|
||||
|_, _| None,
|
||||
|| &[],
|
||||
cx,
|
||||
)
|
||||
});
|
||||
let (_, workspace) = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
|
||||
|
||||
// Adding an item with no ambiguity renders the tab without detail.
|
||||
let item1 = cx.add_view(&workspace, |_| {
|
||||
|
@ -3114,16 +3198,7 @@ mod tests {
|
|||
.await;
|
||||
|
||||
let project = Project::test(fs, ["root1".as_ref()], cx).await;
|
||||
let (window_id, workspace) = cx.add_window(|cx| {
|
||||
Workspace::new(
|
||||
Default::default(),
|
||||
0,
|
||||
project.clone(),
|
||||
|_, _| None,
|
||||
|| &[],
|
||||
cx,
|
||||
)
|
||||
});
|
||||
let (window_id, workspace) = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
|
||||
let worktree_id = project.read_with(cx, |project, cx| {
|
||||
project.worktrees(cx).next().unwrap().read(cx).id()
|
||||
});
|
||||
|
@ -3213,16 +3288,7 @@ mod tests {
|
|||
fs.insert_tree("/root", json!({ "one": "" })).await;
|
||||
|
||||
let project = Project::test(fs, ["root".as_ref()], cx).await;
|
||||
let (window_id, workspace) = cx.add_window(|cx| {
|
||||
Workspace::new(
|
||||
Default::default(),
|
||||
0,
|
||||
project.clone(),
|
||||
|_, _| None,
|
||||
|| &[],
|
||||
cx,
|
||||
)
|
||||
});
|
||||
let (window_id, workspace) = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
|
||||
|
||||
// When there are no dirty items, there's nothing to do.
|
||||
let item1 = cx.add_view(&workspace, |_| TestItem::new());
|
||||
|
@ -3257,9 +3323,7 @@ mod tests {
|
|||
let fs = FakeFs::new(cx.background());
|
||||
|
||||
let project = Project::test(fs, None, cx).await;
|
||||
let (window_id, workspace) = cx.add_window(|cx| {
|
||||
Workspace::new(Default::default(), 0, project, |_, _| None, || &[], cx)
|
||||
});
|
||||
let (window_id, workspace) = cx.add_window(|cx| Workspace::test_new(project, cx));
|
||||
|
||||
let item1 = cx.add_view(&workspace, |cx| {
|
||||
TestItem::new()
|
||||
|
@ -3366,9 +3430,7 @@ mod tests {
|
|||
let fs = FakeFs::new(cx.background());
|
||||
|
||||
let project = Project::test(fs, [], cx).await;
|
||||
let (window_id, workspace) = cx.add_window(|cx| {
|
||||
Workspace::new(Default::default(), 0, project, |_, _| None, || &[], cx)
|
||||
});
|
||||
let (window_id, workspace) = cx.add_window(|cx| Workspace::test_new(project, cx));
|
||||
|
||||
// Create several workspace items with single project entries, and two
|
||||
// workspace items with multiple project entries.
|
||||
|
@ -3475,9 +3537,7 @@ mod tests {
|
|||
let fs = FakeFs::new(cx.background());
|
||||
|
||||
let project = Project::test(fs, [], cx).await;
|
||||
let (window_id, workspace) = cx.add_window(|cx| {
|
||||
Workspace::new(Default::default(), 0, project, |_, _| None, || &[], cx)
|
||||
});
|
||||
let (window_id, workspace) = cx.add_window(|cx| Workspace::test_new(project, cx));
|
||||
|
||||
let item = cx.add_view(&workspace, |cx| {
|
||||
TestItem::new().with_project_items(&[TestProjectItem::new(1, "1.txt", cx)])
|
||||
|
@ -3594,9 +3654,7 @@ mod tests {
|
|||
let fs = FakeFs::new(cx.background());
|
||||
|
||||
let project = Project::test(fs, [], cx).await;
|
||||
let (_, workspace) = cx.add_window(|cx| {
|
||||
Workspace::new(Default::default(), 0, project, |_, _| None, || &[], cx)
|
||||
});
|
||||
let (_, workspace) = cx.add_window(|cx| Workspace::test_new(project, cx));
|
||||
|
||||
let item = cx.add_view(&workspace, |cx| {
|
||||
TestItem::new().with_project_items(&[TestProjectItem::new(1, "1.txt", cx)])
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue