Detailed changes
@@ -1,4 +1,3 @@
-mod indicator;
pub mod participant;
pub mod room;
@@ -10,22 +9,17 @@ use collections::HashSet;
use postage::watch;
use gpui::{
- actions, AppContext, AsyncAppContext, Entity, ModelContext, ModelHandle, MutableAppContext,
- Subscription, Task, ViewHandle, WeakModelHandle,
+ AppContext, AsyncAppContext, Entity, ModelContext, ModelHandle, MutableAppContext,
+ Subscription, Task, WeakModelHandle,
};
use project::Project;
-use settings::Settings;
-use indicator::SharingStatusIndicator;
pub use participant::ParticipantLocation;
pub use room::Room;
-actions!(collab, [ToggleScreenSharing]);
-
pub fn init(client: Arc<Client>, user_store: ModelHandle<UserStore>, cx: &mut MutableAppContext) {
let active_call = cx.add_model(|cx| ActiveCall::new(client, user_store, cx));
cx.set_global(active_call);
- cx.add_global_action(toggle_screen_sharing);
}
#[derive(Clone)]
@@ -36,6 +30,7 @@ pub struct IncomingCall {
pub initial_project: Option<proto::ParticipantProject>,
}
+/// Singleton global maintaining the user's participation in a room across workspaces.
pub struct ActiveCall {
room: Option<(ModelHandle<Room>, Vec<Subscription>)>,
location: Option<WeakModelHandle<Project>>,
@@ -46,7 +41,6 @@ pub struct ActiveCall {
),
client: Arc<Client>,
user_store: ModelHandle<UserStore>,
- sharing_status_indicator: Option<(usize, ViewHandle<SharingStatusIndicator>)>,
_subscriptions: Vec<client::Subscription>,
}
@@ -71,7 +65,6 @@ impl ActiveCall {
],
client,
user_store,
- sharing_status_indicator: None,
}
}
@@ -290,8 +283,6 @@ impl ActiveCall {
this.set_room(None, cx).detach_and_log_err(cx);
}
- this.set_sharing_status(room.read(cx).is_screen_sharing(), cx);
-
cx.notify();
}),
cx.subscribe(&room, |_, _, event, cx| cx.emit(event.clone())),
@@ -316,30 +307,4 @@ impl ActiveCall {
pub fn pending_invites(&self) -> &HashSet<u64> {
&self.pending_invites
}
-
- pub fn set_sharing_status(&mut self, is_screen_sharing: bool, cx: &mut MutableAppContext) {
- if is_screen_sharing {
- if self.sharing_status_indicator.is_none()
- && cx.global::<Settings>().show_call_status_icon
- {
- self.sharing_status_indicator =
- Some(cx.add_status_bar_item(|_| SharingStatusIndicator));
- }
- } else if let Some((window_id, _)) = self.sharing_status_indicator.take() {
- cx.remove_status_bar_item(window_id);
- }
- }
-}
-
-pub fn toggle_screen_sharing(_: &ToggleScreenSharing, cx: &mut MutableAppContext) {
- if let Some(room) = ActiveCall::global(cx).read(cx).room().cloned() {
- let toggle_screen_sharing = room.update(cx, |room, cx| {
- if room.is_screen_sharing() {
- Task::ready(room.unshare_screen(cx))
- } else {
- room.share_screen(cx)
- }
- });
- toggle_screen_sharing.detach_and_log_err(cx);
- }
}
@@ -1,5 +1,5 @@
use crate::{contact_notification::ContactNotification, contacts_popover};
-use call::{ActiveCall, ParticipantLocation, ToggleScreenSharing};
+use call::{ActiveCall, ParticipantLocation};
use client::{proto::PeerId, Authenticate, ContactEventKind, User, UserStore};
use clock::ReplicaId;
use contacts_popover::ContactsPopover;
@@ -10,17 +10,21 @@ use gpui::{
geometry::{rect::RectF, vector::vec2f, PathBuilder},
json::{self, ToJson},
Border, CursorStyle, Entity, ModelHandle, MouseButton, MutableAppContext, RenderContext,
- Subscription, View, ViewContext, ViewHandle, WeakViewHandle,
+ Subscription, Task, View, ViewContext, ViewHandle, WeakViewHandle,
};
use settings::Settings;
use std::ops::Range;
use theme::Theme;
use workspace::{FollowNextCollaborator, JoinProject, ToggleFollow, Workspace};
-actions!(collab, [ToggleCollaborationMenu, ShareProject]);
+actions!(
+ collab,
+ [ToggleCollaborationMenu, ToggleScreenSharing, ShareProject]
+);
pub fn init(cx: &mut MutableAppContext) {
cx.add_action(CollabTitlebarItem::toggle_contacts_popover);
+ cx.add_global_action(CollabTitlebarItem::toggle_screen_sharing);
cx.add_action(CollabTitlebarItem::share_project);
}
@@ -168,6 +172,19 @@ impl CollabTitlebarItem {
cx.notify();
}
+ pub fn toggle_screen_sharing(_: &ToggleScreenSharing, cx: &mut MutableAppContext) {
+ if let Some(room) = ActiveCall::global(cx).read(cx).room().cloned() {
+ let toggle_screen_sharing = room.update(cx, |room, cx| {
+ if room.is_screen_sharing() {
+ Task::ready(room.unshare_screen(cx))
+ } else {
+ room.share_screen(cx)
+ }
+ });
+ toggle_screen_sharing.detach_and_log_err(cx);
+ }
+ }
+
fn render_toggle_contacts_button(
&self,
theme: &Theme,
@@ -6,14 +6,17 @@ mod contacts_popover;
mod incoming_call_notification;
mod notifications;
mod project_shared_notification;
+mod sharing_status_indicator;
use anyhow::anyhow;
use call::ActiveCall;
pub use collab_titlebar_item::{CollabTitlebarItem, ToggleCollaborationMenu};
-use gpui::MutableAppContext;
+use gpui::{actions, MutableAppContext, Task};
use std::sync::Arc;
use workspace::{AppState, JoinProject, ToggleFollow, Workspace};
+actions!(collab, [ToggleScreenSharing]);
+
pub fn init(app_state: Arc<AppState>, cx: &mut MutableAppContext) {
collab_titlebar_item::init(cx);
contact_notification::init(cx);
@@ -22,89 +25,107 @@ pub fn init(app_state: Arc<AppState>, cx: &mut MutableAppContext) {
contacts_popover::init(cx);
incoming_call_notification::init(cx);
project_shared_notification::init(cx);
+ sharing_status_indicator::init(cx);
+ cx.add_global_action(toggle_screen_sharing);
cx.add_global_action(move |action: &JoinProject, cx| {
- let project_id = action.project_id;
- let follow_user_id = action.follow_user_id;
- let app_state = app_state.clone();
- cx.spawn(|mut cx| async move {
- let existing_workspace = cx.update(|cx| {
- cx.window_ids()
- .filter_map(|window_id| cx.root_view::<Workspace>(window_id))
- .find(|workspace| {
- workspace.read(cx).project().read(cx).remote_id() == Some(project_id)
- })
- });
+ join_project(action, app_state.clone(), cx);
+ });
+}
- let workspace = if let Some(existing_workspace) = existing_workspace {
- existing_workspace
+pub fn toggle_screen_sharing(_: &ToggleScreenSharing, cx: &mut MutableAppContext) {
+ if let Some(room) = ActiveCall::global(cx).read(cx).room().cloned() {
+ let toggle_screen_sharing = room.update(cx, |room, cx| {
+ if room.is_screen_sharing() {
+ Task::ready(room.unshare_screen(cx))
} 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?;
+ room.share_screen(cx)
+ }
+ });
+ toggle_screen_sharing.detach_and_log_err(cx);
+ }
+}
- 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.dock_default_item_factory,
- cx,
- );
- (app_state.initialize_workspace)(&mut workspace, &app_state, cx);
- workspace
- },
- );
- workspace
- };
+fn join_project(action: &JoinProject, app_state: Arc<AppState>, cx: &mut MutableAppContext) {
+ let project_id = action.project_id;
+ let follow_user_id = action.follow_user_id;
+ cx.spawn(|mut cx| async move {
+ let existing_workspace = cx.update(|cx| {
+ cx.window_ids()
+ .filter_map(|window_id| cx.root_view::<Workspace>(window_id))
+ .find(|workspace| {
+ workspace.read(cx).project().read(cx).remote_id() == Some(project_id)
+ })
+ });
- cx.activate_window(workspace.window_id());
- cx.platform().activate(true);
+ let workspace = if let Some(existing_workspace) = existing_workspace {
+ existing_workspace
+ } 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?;
- 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)
- });
+ 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.dock_default_item_factory,
+ cx,
+ );
+ (app_state.initialize_workspace)(&mut workspace, &app_state, cx);
+ workspace
+ },
+ );
+ workspace
+ };
- if let Some(follow_peer_id) = follow_peer_id {
- if !workspace.is_following(follow_peer_id) {
- workspace
- .toggle_follow(&ToggleFollow(follow_peer_id), cx)
- .map(|follow| follow.detach_and_log_err(cx));
- }
+ 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_following(follow_peer_id) {
+ workspace
+ .toggle_follow(&ToggleFollow(follow_peer_id), cx)
+ .map(|follow| follow.detach_and_log_err(cx));
}
}
- });
+ }
+ });
- anyhow::Ok(())
- })
- .detach_and_log_err(cx);
- });
+ anyhow::Ok(())
+ })
+ .detach_and_log_err(cx);
}
@@ -1,10 +1,30 @@
+use call::ActiveCall;
use gpui::{
color::Color,
elements::{MouseEventHandler, Svg},
- Appearance, Element, ElementBox, Entity, MouseButton, RenderContext, View,
+ Appearance, Element, ElementBox, Entity, MouseButton, MutableAppContext, RenderContext, View,
};
+use settings::Settings;
-use crate::ToggleScreenSharing;
+use crate::collab_titlebar_item::ToggleScreenSharing;
+
+pub fn init(cx: &mut MutableAppContext) {
+ let active_call = ActiveCall::global(cx);
+
+ let mut status_indicator = None;
+ cx.observe(&active_call, move |call, cx| {
+ if let Some(room) = call.read(cx).room() {
+ if room.read(cx).is_screen_sharing() {
+ if status_indicator.is_none() && cx.global::<Settings>().show_call_status_icon {
+ status_indicator = Some(cx.add_status_bar_item(|_| SharingStatusIndicator));
+ }
+ } else if let Some((window_id, _)) = status_indicator.take() {
+ cx.remove_status_bar_item(window_id);
+ }
+ }
+ })
+ .detach();
+}
pub struct SharingStatusIndicator;