Merge pull request #2129 from zed-industries/move-sharing-status-indicator
Move sharing status indicator to collab ui
This commit is contained in:
commit
37bfeed2e6
4 changed files with 130 additions and 124 deletions
|
@ -1,4 +1,3 @@
|
||||||
mod indicator;
|
|
||||||
pub mod participant;
|
pub mod participant;
|
||||||
pub mod room;
|
pub mod room;
|
||||||
|
|
||||||
|
@ -10,22 +9,17 @@ use collections::HashSet;
|
||||||
use postage::watch;
|
use postage::watch;
|
||||||
|
|
||||||
use gpui::{
|
use gpui::{
|
||||||
actions, AppContext, AsyncAppContext, Entity, ModelContext, ModelHandle, MutableAppContext,
|
AppContext, AsyncAppContext, Entity, ModelContext, ModelHandle, MutableAppContext,
|
||||||
Subscription, Task, ViewHandle, WeakModelHandle,
|
Subscription, Task, WeakModelHandle,
|
||||||
};
|
};
|
||||||
use project::Project;
|
use project::Project;
|
||||||
use settings::Settings;
|
|
||||||
|
|
||||||
use indicator::SharingStatusIndicator;
|
|
||||||
pub use participant::ParticipantLocation;
|
pub use participant::ParticipantLocation;
|
||||||
pub use room::Room;
|
pub use room::Room;
|
||||||
|
|
||||||
actions!(collab, [ToggleScreenSharing]);
|
|
||||||
|
|
||||||
pub fn init(client: Arc<Client>, user_store: ModelHandle<UserStore>, cx: &mut MutableAppContext) {
|
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));
|
let active_call = cx.add_model(|cx| ActiveCall::new(client, user_store, cx));
|
||||||
cx.set_global(active_call);
|
cx.set_global(active_call);
|
||||||
cx.add_global_action(toggle_screen_sharing);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
@ -36,6 +30,7 @@ pub struct IncomingCall {
|
||||||
pub initial_project: Option<proto::ParticipantProject>,
|
pub initial_project: Option<proto::ParticipantProject>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Singleton global maintaining the user's participation in a room across workspaces.
|
||||||
pub struct ActiveCall {
|
pub struct ActiveCall {
|
||||||
room: Option<(ModelHandle<Room>, Vec<Subscription>)>,
|
room: Option<(ModelHandle<Room>, Vec<Subscription>)>,
|
||||||
location: Option<WeakModelHandle<Project>>,
|
location: Option<WeakModelHandle<Project>>,
|
||||||
|
@ -46,7 +41,6 @@ pub struct ActiveCall {
|
||||||
),
|
),
|
||||||
client: Arc<Client>,
|
client: Arc<Client>,
|
||||||
user_store: ModelHandle<UserStore>,
|
user_store: ModelHandle<UserStore>,
|
||||||
sharing_status_indicator: Option<(usize, ViewHandle<SharingStatusIndicator>)>,
|
|
||||||
_subscriptions: Vec<client::Subscription>,
|
_subscriptions: Vec<client::Subscription>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,7 +65,6 @@ impl ActiveCall {
|
||||||
],
|
],
|
||||||
client,
|
client,
|
||||||
user_store,
|
user_store,
|
||||||
sharing_status_indicator: None,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -290,8 +283,6 @@ impl ActiveCall {
|
||||||
this.set_room(None, cx).detach_and_log_err(cx);
|
this.set_room(None, cx).detach_and_log_err(cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.set_sharing_status(room.read(cx).is_screen_sharing(), cx);
|
|
||||||
|
|
||||||
cx.notify();
|
cx.notify();
|
||||||
}),
|
}),
|
||||||
cx.subscribe(&room, |_, _, event, cx| cx.emit(event.clone())),
|
cx.subscribe(&room, |_, _, event, cx| cx.emit(event.clone())),
|
||||||
|
@ -316,30 +307,4 @@ impl ActiveCall {
|
||||||
pub fn pending_invites(&self) -> &HashSet<u64> {
|
pub fn pending_invites(&self) -> &HashSet<u64> {
|
||||||
&self.pending_invites
|
&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 crate::{contact_notification::ContactNotification, contacts_popover, ToggleScreenSharing};
|
||||||
use call::{ActiveCall, ParticipantLocation, ToggleScreenSharing};
|
use call::{ActiveCall, ParticipantLocation};
|
||||||
use client::{proto::PeerId, Authenticate, ContactEventKind, User, UserStore};
|
use client::{proto::PeerId, Authenticate, ContactEventKind, User, UserStore};
|
||||||
use clock::ReplicaId;
|
use clock::ReplicaId;
|
||||||
use contacts_popover::ContactsPopover;
|
use contacts_popover::ContactsPopover;
|
||||||
|
|
|
@ -6,14 +6,17 @@ mod contacts_popover;
|
||||||
mod incoming_call_notification;
|
mod incoming_call_notification;
|
||||||
mod notifications;
|
mod notifications;
|
||||||
mod project_shared_notification;
|
mod project_shared_notification;
|
||||||
|
mod sharing_status_indicator;
|
||||||
|
|
||||||
use anyhow::anyhow;
|
use anyhow::anyhow;
|
||||||
use call::ActiveCall;
|
use call::ActiveCall;
|
||||||
pub use collab_titlebar_item::{CollabTitlebarItem, ToggleCollaborationMenu};
|
pub use collab_titlebar_item::{CollabTitlebarItem, ToggleCollaborationMenu};
|
||||||
use gpui::MutableAppContext;
|
use gpui::{actions, MutableAppContext, Task};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use workspace::{AppState, JoinProject, ToggleFollow, Workspace};
|
use workspace::{AppState, JoinProject, ToggleFollow, Workspace};
|
||||||
|
|
||||||
|
actions!(collab, [ToggleScreenSharing]);
|
||||||
|
|
||||||
pub fn init(app_state: Arc<AppState>, cx: &mut MutableAppContext) {
|
pub fn init(app_state: Arc<AppState>, cx: &mut MutableAppContext) {
|
||||||
collab_titlebar_item::init(cx);
|
collab_titlebar_item::init(cx);
|
||||||
contact_notification::init(cx);
|
contact_notification::init(cx);
|
||||||
|
@ -22,89 +25,107 @@ pub fn init(app_state: Arc<AppState>, cx: &mut MutableAppContext) {
|
||||||
contacts_popover::init(cx);
|
contacts_popover::init(cx);
|
||||||
incoming_call_notification::init(cx);
|
incoming_call_notification::init(cx);
|
||||||
project_shared_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| {
|
cx.add_global_action(move |action: &JoinProject, cx| {
|
||||||
let project_id = action.project_id;
|
join_project(action, app_state.clone(), cx);
|
||||||
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)
|
|
||||||
})
|
|
||||||
});
|
|
||||||
|
|
||||||
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?;
|
|
||||||
|
|
||||||
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
|
|
||||||
};
|
|
||||||
|
|
||||||
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);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 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)
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
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?;
|
||||||
|
|
||||||
|
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
|
||||||
|
};
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
|
@ -1,11 +1,31 @@
|
||||||
|
use call::ActiveCall;
|
||||||
use gpui::{
|
use gpui::{
|
||||||
color::Color,
|
color::Color,
|
||||||
elements::{MouseEventHandler, Svg},
|
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::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;
|
pub struct SharingStatusIndicator;
|
||||||
|
|
||||||
impl Entity for SharingStatusIndicator {
|
impl Entity for SharingStatusIndicator {
|
Loading…
Add table
Add a link
Reference in a new issue