diff --git a/crates/call/src/call.rs b/crates/call/src/call.rs index ca0d06beb6..d86ed1be37 100644 --- a/crates/call/src/call.rs +++ b/crates/call/src/call.rs @@ -291,10 +291,10 @@ impl ActiveCall { &mut self, channel_id: u64, cx: &mut ModelContext, - ) -> Task> { + ) -> Task>> { if let Some(room) = self.room().cloned() { if room.read(cx).channel_id() == Some(channel_id) { - return Task::ready(Ok(())); + return Task::ready(Ok(room)); } else { room.update(cx, |room, cx| room.clear_state(cx)); } @@ -309,7 +309,7 @@ impl ActiveCall { this.update(&mut cx, |this, cx| { this.report_call_event("join channel", cx) }); - Ok(()) + Ok(room) }) } diff --git a/crates/call/src/room.rs b/crates/call/src/room.rs index 130a7a64f0..f24a8e9a9c 100644 --- a/crates/call/src/room.rs +++ b/crates/call/src/room.rs @@ -594,6 +594,33 @@ impl Room { .map_or(&[], |v| v.as_slice()) } + /// projects_to_join returns a list of shared projects sorted such + /// that the most 'active' projects appear last. + pub fn projects_to_join(&self) -> Vec<(u64, u64)> { + let mut projects = HashMap::default(); + let mut hosts = HashMap::default(); + for participant in self.remote_participants.values() { + match participant.location { + ParticipantLocation::SharedProject { project_id } => { + *projects.entry(project_id).or_insert(0) += 1; + } + ParticipantLocation::External | ParticipantLocation::UnsharedProject => {} + } + for project in &participant.projects { + *projects.entry(project.id).or_insert(0) += 1; + hosts.insert(project.id, participant.user.id); + } + } + + let mut pairs: Vec<(u64, usize)> = projects.into_iter().collect(); + pairs.sort_by_key(|(_, count)| 0 - *count as i32); + + pairs + .into_iter() + .map(|(project_id, _)| (project_id, hosts[&project_id])) + .collect() + } + async fn handle_room_updated( this: ModelHandle, envelope: TypedEnvelope, diff --git a/crates/collab_ui/src/collab_panel.rs b/crates/collab_ui/src/collab_panel.rs index 22ab573974..eeae37bbe5 100644 --- a/crates/collab_ui/src/collab_panel.rs +++ b/crates/collab_ui/src/collab_panel.rs @@ -8,7 +8,7 @@ use crate::{ panel_settings, CollaborationPanelSettings, }; use anyhow::Result; -use call::ActiveCall; +use call::{participant, ActiveCall}; use channel::{Channel, ChannelData, ChannelEvent, ChannelId, ChannelPath, ChannelStore}; use channel_modal::ChannelModal; use client::{proto::PeerId, Client, Contact, User, UserStore}; @@ -1929,7 +1929,7 @@ impl CollabPanel { })) .into_any() } else if row_hovered { - Svg::new("icons/speaker-loud.svg") + Svg::new("icons/file.svg") .with_color(theme.channel_hash.color) .constrained() .with_width(theme.channel_hash.width) @@ -1939,7 +1939,11 @@ impl CollabPanel { } }) .on_click(MouseButton::Left, move |_, this, cx| { - this.join_channel_call(channel_id, cx); + if !is_active { + this.join_channel_call(channel_id, cx); + } else { + this.open_channel_notes(&OpenChannelNotes { channel_id }, cx) + } }), ) .align_children_center() @@ -1968,6 +1972,12 @@ impl CollabPanel { }) .on_click(MouseButton::Left, move |_, this, cx| { if this.drag_target_channel.take().is_none() { + if is_active { + this.open_channel_notes(&OpenChannelNotes { channel_id }, cx) + } else { + this.join_channel_call(channel_id, cx) + } + this.join_channel_chat(channel_id, cx); } }) @@ -2991,10 +3001,37 @@ impl CollabPanel { .detach_and_log_err(cx); } - fn join_channel_call(&self, channel: u64, cx: &mut ViewContext) { - ActiveCall::global(cx) - .update(cx, |call, cx| call.join_channel(channel, cx)) - .detach_and_log_err(cx); + fn join_channel_call(&self, channel_id: u64, cx: &mut ViewContext) { + let join = ActiveCall::global(cx).update(cx, |call, cx| call.join_channel(channel_id, cx)); + let workspace = self.workspace.clone(); + + cx.spawn(|_, mut cx| async move { + let room = join.await?; + + let tasks = room.update(&mut cx, |room, cx| { + let Some(workspace) = workspace.upgrade(cx) else { + return vec![]; + }; + let projects = room.projects_to_join(); + + if projects.is_empty() { + ChannelView::open(channel_id, workspace, cx).detach(); + return vec![]; + } + room.projects_to_join() + .into_iter() + .map(|(project_id, user_id)| { + let app_state = workspace.read(cx).app_state().clone(); + workspace::join_remote_project(project_id, user_id, app_state, cx) + }) + .collect() + }); + for task in tasks { + task.await?; + } + Ok::<(), anyhow::Error>(()) + }) + .detach_and_log_err(cx); } fn join_channel_chat(&mut self, channel_id: u64, cx: &mut ViewContext) {