diff --git a/crates/call2/src/call2.rs b/crates/call2/src/call2.rs index 9aa8c1142850aad3e438d5f076733a48bf0814ff..e778316d59545f2ec81b553ddbb604cc3afcff1b 100644 --- a/crates/call2/src/call2.rs +++ b/crates/call2/src/call2.rs @@ -17,6 +17,7 @@ use gpui::{ Subscription, Task, View, ViewContext, WeakModel, WeakView, }; pub use participant::ParticipantLocation; +use participant::RemoteParticipant; use postage::watch; use project::Project; use room::Event; @@ -628,6 +629,42 @@ impl CallHandler for Call { this.invite(called_user_id, initial_project, cx) }) } + fn remote_participants(&self, cx: &AppContext) -> Option>> { + self.active_call + .as_ref() + .map(|call| { + call.0.read(cx).room().map(|room| { + room.read(cx) + .remote_participants() + .iter() + .map(|participant| participant.1.user.clone()) + .collect() + }) + }) + .flatten() + } + fn is_muted(&self, cx: &AppContext) -> Option { + self.active_call + .as_ref() + .map(|call| { + call.0 + .read(cx) + .room() + .map(|room| room.read(cx).is_muted(cx)) + }) + .flatten() + } + fn toggle_mute(&self, cx: &mut AppContext) { + self.active_call.as_ref().map(|call| { + call.0.update(cx, |this, cx| { + this.room().map(|room| { + room.update(cx, |this, cx| { + this.toggle_mute(cx); + }) + }) + }) + }); + } } #[cfg(test)] diff --git a/crates/call2/src/room.rs b/crates/call2/src/room.rs index 87118764fdc717620521b32e5b77aa7e1c4aca9f..d73a522937615b9239877f7205d8f30d1bd82ad8 100644 --- a/crates/call2/src/room.rs +++ b/crates/call2/src/room.rs @@ -333,7 +333,8 @@ impl Room { } pub fn mute_on_join(cx: &AppContext) -> bool { - CallSettings::get_global(cx).mute_on_join || client::IMPERSONATE_LOGIN.is_some() + false + //CallSettings::get_global(cx).mute_on_join || client::IMPERSONATE_LOGIN.is_some() } fn from_join_response( diff --git a/crates/client2/src/client2.rs b/crates/client2/src/client2.rs index 4ad354f2f91bd56cdb0c1f657137d1beac9a3e4f..b31451aa87a55f5ed65a7a9cdb6a0149d52cfe80 100644 --- a/crates/client2/src/client2.rs +++ b/crates/client2/src/client2.rs @@ -551,7 +551,6 @@ impl Client { F: 'static + Future>, { let message_type_id = TypeId::of::(); - let mut state = self.state.write(); state .models_by_message_type diff --git a/crates/collab_ui2/src/collab_titlebar_item.rs b/crates/collab_ui2/src/collab_titlebar_item.rs index 7c9cb9f45347284cc34b56ba9acee3ff995fd0b3..bcb43d4972b270b454e2e95741f1261643e51bfd 100644 --- a/crates/collab_ui2/src/collab_titlebar_item.rs +++ b/crates/collab_ui2/src/collab_titlebar_item.rs @@ -37,7 +37,8 @@ use gpui::{ }; use project::Project; use theme::ActiveTheme; -use ui::{h_stack, Button, ButtonVariant, Color, IconButton, KeyBinding, Tooltip}; +use ui::{h_stack, Avatar, Button, ButtonVariant, Color, IconButton, KeyBinding, Label, Tooltip}; +use util::ResultExt; use workspace::Workspace; // const MAX_PROJECT_NAME_LENGTH: usize = 40; @@ -92,6 +93,23 @@ impl Render for CollabTitlebarItem { let is_shared = is_in_room && self.project.read(cx).is_shared(); let current_user = self.user_store.read(cx).current_user(); let client = self.client.clone(); + let users = self + .workspace + .update(cx, |this, cx| this.call_state().remote_participants(cx)) + .log_err() + .flatten(); + let mic_icon = if self + .workspace + .update(cx, |this, cx| this.call_state().is_muted(cx)) + .log_err() + .flatten() + .unwrap_or_default() + { + ui::Icon::MicMute + } else { + ui::Icon::Mic + }; + let workspace = self.workspace.clone(); h_stack() .id("titlebar") .justify_between() @@ -157,22 +175,23 @@ impl Render for CollabTitlebarItem { }), ), ) - .map(|this| { - if let Some(user) = current_user { - this.when_some(user.avatar.clone(), |this, avatar| { - this.child(ui::Avatar::new(avatar)) - }) - } else { - this.child(Button::new("Sign in").on_click(move |_, cx| { - let client = client.clone(); - cx.spawn(move |cx| async move { - client.authenticate_and_connect(true, &cx).await?; - Ok::<(), anyhow::Error>(()) - }) - .detach_and_log_err(cx); - })) - } - }) + .when_some( + users.zip(current_user.clone()), + |this, (remote_participants, current_user)| { + this.children( + current_user + .avatar + .clone() + .map(|avatar| Avatar::new(avatar.clone())) + .into_iter() + .chain(remote_participants.into_iter().flat_map(|user| { + user.avatar + .as_ref() + .map(|avatar| Avatar::new(avatar.clone())) + })), + ) + }, + ) .when(is_in_room, |this| { this.child( h_stack() @@ -183,13 +202,35 @@ impl Render for CollabTitlebarItem { ) .child( h_stack() - .child(IconButton::new("mute-microphone", ui::Icon::Mic)) + .child(IconButton::new("mute-microphone", mic_icon).on_click( + move |_, cx| { + workspace.update(cx, |this, cx| { + this.call_state().toggle_mute(cx); + }); + }, + )) .child(IconButton::new("mute-sound", ui::Icon::AudioOn)) .child(IconButton::new("screen-share", ui::Icon::Screen)) .pl_2(), ), ) }) + .map(|this| { + if let Some(user) = current_user { + this.when_some(user.avatar.clone(), |this, avatar| { + this.child(ui::Avatar::new(avatar)) + }) + } else { + this.child(Button::new("Sign in").on_click(move |_, cx| { + let client = client.clone(); + cx.spawn(move |cx| async move { + client.authenticate_and_connect(true, &cx).await?; + Ok::<(), anyhow::Error>(()) + }) + .detach_and_log_err(cx); + })) + } + }) } } diff --git a/crates/workspace2/src/workspace2.rs b/crates/workspace2/src/workspace2.rs index 8c687becd0c57d4afa92ba15689b26288f24a3c5..bccb25b64ddc3a0cedce22b5e71a8ebcfccf551f 100644 --- a/crates/workspace2/src/workspace2.rs +++ b/crates/workspace2/src/workspace2.rs @@ -19,7 +19,7 @@ use anyhow::{anyhow, Context as _, Result}; use async_trait::async_trait; use client2::{ proto::{self, PeerId}, - Client, TypedEnvelope, UserStore, + Client, TypedEnvelope, User, UserStore, }; use collections::{hash_map, HashMap, HashSet}; use dock::{Dock, DockPosition, Panel, PanelButtons, PanelHandle}; @@ -351,7 +351,27 @@ impl CallHandler for TestCallHandler { fn active_project(&self, cx: &AppContext) -> Option> { None } + + fn invite( + &mut self, + called_user_id: u64, + initial_project: Option>, + cx: &mut AppContext, + ) -> Task> { + unimplemented!() + } + + fn remote_participants(&self, cx: &AppContext) -> Option> { + None + } + + fn is_muted(&self, cx: &AppContext) -> Option { + None + } + + fn toggle_mute(&self, cx: &mut AppContext) {} } + impl AppState { #[cfg(any(test, feature = "test-support"))] pub fn test(cx: &mut AppContext) -> Arc { @@ -460,6 +480,9 @@ pub trait CallHandler { initial_project: Option>, cx: &mut AppContext, ) -> Task>; + fn remote_participants(&self, cx: &AppContext) -> Option>>; + fn is_muted(&self, cx: &AppContext) -> Option; + fn toggle_mute(&self, cx: &mut AppContext); } pub struct Workspace {