mirror of
https://github.com/zed-industries/zed.git
synced 2025-02-03 17:44:30 +00:00
Update collaborators as worktrees are opened/shared/closed
This commit is contained in:
parent
f13af7dc59
commit
d8ea220acc
1 changed files with 87 additions and 76 deletions
|
@ -99,7 +99,7 @@ impl Server {
|
|||
server
|
||||
.add_handler(Server::ping)
|
||||
.add_handler(Server::open_worktree)
|
||||
.add_handler(Server::close_worktree)
|
||||
.add_handler(Server::handle_close_worktree)
|
||||
.add_handler(Server::share_worktree)
|
||||
.add_handler(Server::unshare_worktree)
|
||||
.add_handler(Server::join_worktree)
|
||||
|
@ -195,22 +195,7 @@ impl Server {
|
|||
|
||||
async fn sign_out(self: &Arc<Self>, connection_id: zrpc::ConnectionId) -> tide::Result<()> {
|
||||
self.peer.disconnect(connection_id).await;
|
||||
let worktree_ids = self.remove_connection(connection_id).await;
|
||||
for worktree_id in worktree_ids {
|
||||
let state = self.state.read().await;
|
||||
if let Some(worktree) = state.worktrees.get(&worktree_id) {
|
||||
broadcast(connection_id, worktree.connection_ids(), |conn_id| {
|
||||
self.peer.send(
|
||||
conn_id,
|
||||
proto::RemovePeer {
|
||||
worktree_id,
|
||||
peer_id: connection_id.0,
|
||||
},
|
||||
)
|
||||
})
|
||||
.await?;
|
||||
}
|
||||
}
|
||||
self.remove_connection(connection_id).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -233,29 +218,20 @@ impl Server {
|
|||
}
|
||||
|
||||
// Remove the given connection and its association with any worktrees.
|
||||
async fn remove_connection(&self, connection_id: ConnectionId) -> Vec<u64> {
|
||||
async fn remove_connection(
|
||||
self: &Arc<Server>,
|
||||
connection_id: ConnectionId,
|
||||
) -> tide::Result<()> {
|
||||
let mut worktree_ids = Vec::new();
|
||||
let mut state = self.state.write().await;
|
||||
if let Some(connection) = state.connections.remove(&connection_id) {
|
||||
worktree_ids = connection.worktrees.into_iter().collect();
|
||||
|
||||
for channel_id in connection.channels {
|
||||
if let Some(channel) = state.channels.get_mut(&channel_id) {
|
||||
channel.connection_ids.remove(&connection_id);
|
||||
}
|
||||
}
|
||||
for worktree_id in connection.worktrees {
|
||||
if let Some(worktree) = state.worktrees.get_mut(&worktree_id) {
|
||||
if worktree.host_connection_id == connection_id {
|
||||
worktree_ids.push(worktree_id);
|
||||
} else if let Some(share_state) = worktree.share.as_mut() {
|
||||
if let Some(replica_id) =
|
||||
share_state.guest_connection_ids.remove(&connection_id)
|
||||
{
|
||||
share_state.active_replica_ids.remove(&replica_id);
|
||||
worktree_ids.push(worktree_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let user_connections = state
|
||||
.connections_by_user_id
|
||||
|
@ -266,7 +242,12 @@ impl Server {
|
|||
state.connections_by_user_id.remove(&connection.user_id);
|
||||
}
|
||||
}
|
||||
worktree_ids
|
||||
|
||||
for worktree_id in worktree_ids {
|
||||
self.close_worktree(worktree_id, connection_id).await?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn ping(self: Arc<Server>, request: TypedEnvelope<proto::Ping>) -> tide::Result<()> {
|
||||
|
@ -279,7 +260,7 @@ impl Server {
|
|||
request: TypedEnvelope<proto::OpenWorktree>,
|
||||
) -> tide::Result<()> {
|
||||
let receipt = request.receipt();
|
||||
let user_id = self
|
||||
let host_user_id = self
|
||||
.state
|
||||
.read()
|
||||
.await
|
||||
|
@ -289,7 +270,7 @@ impl Server {
|
|||
for github_login in request.payload.collaborator_logins {
|
||||
match self.app_state.db.create_user(&github_login, false).await {
|
||||
Ok(collaborator_user_id) => {
|
||||
if collaborator_user_id != user_id {
|
||||
if collaborator_user_id != host_user_id {
|
||||
collaborator_user_ids.push(collaborator_user_id);
|
||||
}
|
||||
}
|
||||
|
@ -303,18 +284,24 @@ impl Server {
|
|||
}
|
||||
}
|
||||
|
||||
let mut state = self.state.write().await;
|
||||
let worktree_id = state.add_worktree(Worktree {
|
||||
host_connection_id: request.sender_id,
|
||||
collaborator_user_ids: collaborator_user_ids.clone(),
|
||||
root_name: request.payload.root_name,
|
||||
share: None,
|
||||
});
|
||||
let worktree_id;
|
||||
let mut user_ids;
|
||||
{
|
||||
let mut state = self.state.write().await;
|
||||
worktree_id = state.add_worktree(Worktree {
|
||||
host_connection_id: request.sender_id,
|
||||
collaborator_user_ids: collaborator_user_ids.clone(),
|
||||
root_name: request.payload.root_name,
|
||||
share: None,
|
||||
});
|
||||
user_ids = collaborator_user_ids;
|
||||
user_ids.push(host_user_id);
|
||||
}
|
||||
|
||||
self.peer
|
||||
.respond(receipt, proto::OpenWorktreeResponse { worktree_id })
|
||||
.await?;
|
||||
self.update_collaborators(&collaborator_user_ids).await?;
|
||||
self.update_collaborators_for_users(&user_ids).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -323,6 +310,11 @@ impl Server {
|
|||
self: Arc<Server>,
|
||||
mut request: TypedEnvelope<proto::ShareWorktree>,
|
||||
) -> tide::Result<()> {
|
||||
let host_user_id = self
|
||||
.state
|
||||
.read()
|
||||
.await
|
||||
.user_id_for_connection(request.sender_id)?;
|
||||
let worktree = request
|
||||
.payload
|
||||
.worktree
|
||||
|
@ -332,6 +324,7 @@ impl Server {
|
|||
.into_iter()
|
||||
.map(|entry| (entry.id, entry))
|
||||
.collect();
|
||||
|
||||
let mut state = self.state.write().await;
|
||||
if let Some(worktree) = state.worktrees.get_mut(&worktree.id) {
|
||||
worktree.share = Some(WorktreeShare {
|
||||
|
@ -339,13 +332,15 @@ impl Server {
|
|||
active_replica_ids: Default::default(),
|
||||
entries,
|
||||
});
|
||||
|
||||
let mut user_ids = worktree.collaborator_user_ids.clone();
|
||||
user_ids.push(host_user_id);
|
||||
|
||||
drop(state);
|
||||
self.peer
|
||||
.respond(request.receipt(), proto::ShareWorktreeResponse {})
|
||||
.await?;
|
||||
|
||||
let collaborator_user_ids = worktree.collaborator_user_ids.clone();
|
||||
drop(state);
|
||||
self.update_collaborators(&collaborator_user_ids).await?;
|
||||
self.update_collaborators_for_users(&user_ids).await?;
|
||||
} else {
|
||||
self.peer
|
||||
.respond_with_error(
|
||||
|
@ -364,9 +359,14 @@ impl Server {
|
|||
request: TypedEnvelope<proto::UnshareWorktree>,
|
||||
) -> tide::Result<()> {
|
||||
let worktree_id = request.payload.worktree_id;
|
||||
let host_user_id = self
|
||||
.state
|
||||
.read()
|
||||
.await
|
||||
.user_id_for_connection(request.sender_id)?;
|
||||
|
||||
let connection_ids;
|
||||
let collaborator_user_ids;
|
||||
let mut user_ids;
|
||||
{
|
||||
let mut state = self.state.write().await;
|
||||
let worktree = state.write_worktree(worktree_id, request.sender_id)?;
|
||||
|
@ -375,7 +375,8 @@ impl Server {
|
|||
}
|
||||
|
||||
connection_ids = worktree.connection_ids();
|
||||
collaborator_user_ids = worktree.collaborator_user_ids.clone();
|
||||
user_ids = worktree.collaborator_user_ids.clone();
|
||||
user_ids.push(host_user_id);
|
||||
worktree.share.take();
|
||||
for connection_id in &connection_ids {
|
||||
if let Some(connection) = state.connections.get_mut(connection_id) {
|
||||
|
@ -389,7 +390,7 @@ impl Server {
|
|||
.send(conn_id, proto::UnshareWorktree { worktree_id })
|
||||
})
|
||||
.await?;
|
||||
self.update_collaborators(&collaborator_user_ids).await?;
|
||||
self.update_collaborators_for_users(&user_ids).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -407,7 +408,7 @@ impl Server {
|
|||
|
||||
let response;
|
||||
let connection_ids;
|
||||
let collaborator_user_ids;
|
||||
let mut user_ids;
|
||||
let mut state = self.state.write().await;
|
||||
match state.join_worktree(request.sender_id, user_id, worktree_id) {
|
||||
Ok((peer_replica_id, worktree)) => {
|
||||
|
@ -426,8 +427,6 @@ impl Server {
|
|||
});
|
||||
}
|
||||
}
|
||||
connection_ids = worktree.connection_ids();
|
||||
collaborator_user_ids = worktree.collaborator_user_ids.clone();
|
||||
response = proto::JoinWorktreeResponse {
|
||||
worktree: Some(proto::Worktree {
|
||||
id: worktree_id,
|
||||
|
@ -437,6 +436,11 @@ impl Server {
|
|||
replica_id: peer_replica_id as u32,
|
||||
peers,
|
||||
};
|
||||
|
||||
let host_connection_id = worktree.host_connection_id;
|
||||
connection_ids = worktree.connection_ids();
|
||||
user_ids = worktree.collaborator_user_ids.clone();
|
||||
user_ids.push(state.user_id_for_connection(host_connection_id)?);
|
||||
}
|
||||
Err(error) => {
|
||||
self.peer
|
||||
|
@ -465,55 +469,69 @@ impl Server {
|
|||
})
|
||||
.await?;
|
||||
self.peer.respond(request.receipt(), response).await?;
|
||||
self.update_collaborators(&collaborator_user_ids).await?;
|
||||
self.update_collaborators_for_users(&user_ids).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn close_worktree(
|
||||
async fn handle_close_worktree(
|
||||
self: Arc<Server>,
|
||||
request: TypedEnvelope<proto::CloseWorktree>,
|
||||
) -> tide::Result<()> {
|
||||
let worktree_id = request.payload.worktree_id;
|
||||
self.close_worktree(request.payload.worktree_id, request.sender_id)
|
||||
.await
|
||||
}
|
||||
|
||||
async fn close_worktree(
|
||||
self: &Arc<Server>,
|
||||
worktree_id: u64,
|
||||
conn_id: ConnectionId,
|
||||
) -> tide::Result<()> {
|
||||
let connection_ids;
|
||||
let mut user_ids;
|
||||
|
||||
let mut is_host = false;
|
||||
let mut is_guest = false;
|
||||
{
|
||||
let mut state = self.state.write().await;
|
||||
let worktree = state.write_worktree(worktree_id, request.sender_id)?;
|
||||
let worktree = state.write_worktree(worktree_id, conn_id)?;
|
||||
let host_connection_id = worktree.host_connection_id;
|
||||
connection_ids = worktree.connection_ids();
|
||||
user_ids = worktree.collaborator_user_ids.clone();
|
||||
|
||||
if worktree.host_connection_id == request.sender_id {
|
||||
if worktree.host_connection_id == conn_id {
|
||||
is_host = true;
|
||||
state.remove_worktree(worktree_id);
|
||||
} else {
|
||||
let share = worktree.share_mut()?;
|
||||
if let Some(replica_id) = share.guest_connection_ids.remove(&request.sender_id) {
|
||||
if let Some(replica_id) = share.guest_connection_ids.remove(&conn_id) {
|
||||
is_guest = true;
|
||||
share.active_replica_ids.remove(&replica_id);
|
||||
}
|
||||
}
|
||||
|
||||
user_ids.push(state.user_id_for_connection(host_connection_id)?);
|
||||
}
|
||||
|
||||
if is_host {
|
||||
broadcast(request.sender_id, connection_ids, |conn_id| {
|
||||
broadcast(conn_id, connection_ids, |conn_id| {
|
||||
self.peer
|
||||
.send(conn_id, proto::UnshareWorktree { worktree_id })
|
||||
})
|
||||
.await?;
|
||||
} else if is_guest {
|
||||
broadcast(request.sender_id, connection_ids, |conn_id| {
|
||||
broadcast(conn_id, connection_ids, |conn_id| {
|
||||
self.peer.send(
|
||||
conn_id,
|
||||
proto::RemovePeer {
|
||||
worktree_id,
|
||||
peer_id: request.sender_id.0,
|
||||
peer_id: conn_id.0,
|
||||
},
|
||||
)
|
||||
})
|
||||
.await?
|
||||
}
|
||||
|
||||
self.update_collaborators_for_users(&user_ids).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -694,7 +712,10 @@ impl Server {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
async fn update_collaborators(self: &Arc<Server>, user_ids: &[UserId]) -> tide::Result<()> {
|
||||
async fn update_collaborators_for_users<'a>(
|
||||
self: &Arc<Server>,
|
||||
user_ids: impl IntoIterator<Item = &'a UserId>,
|
||||
) -> tide::Result<()> {
|
||||
let mut send_futures = Vec::new();
|
||||
|
||||
let state = self.state.read().await;
|
||||
|
@ -730,15 +751,8 @@ impl Server {
|
|||
});
|
||||
}
|
||||
|
||||
let connection_ids = self
|
||||
.state
|
||||
.read()
|
||||
.await
|
||||
.user_connection_ids(*user_id)
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let collaborators = collaborators.into_values().collect::<Vec<_>>();
|
||||
for connection_id in connection_ids {
|
||||
for connection_id in state.user_connection_ids(*user_id) {
|
||||
send_futures.push(self.peer.send(
|
||||
connection_id,
|
||||
proto::UpdateCollaborators {
|
||||
|
@ -748,6 +762,7 @@ impl Server {
|
|||
}
|
||||
}
|
||||
|
||||
drop(state);
|
||||
futures::future::try_join_all(send_futures).await?;
|
||||
|
||||
Ok(())
|
||||
|
@ -1052,10 +1067,6 @@ impl ServerState {
|
|||
.copied()
|
||||
}
|
||||
|
||||
fn is_online(&self, user_id: UserId) -> bool {
|
||||
self.connections_by_user_id.contains_key(&user_id)
|
||||
}
|
||||
|
||||
// Add the given connection as a guest of the given worktree
|
||||
fn join_worktree(
|
||||
&mut self,
|
||||
|
|
Loading…
Reference in a new issue