collab_ui.rs

  1mod collab_titlebar_item;
  2mod collaborator_list_popover;
  3mod contact_finder;
  4mod contact_list;
  5mod contact_notification;
  6mod contacts_popover;
  7mod face_pile;
  8mod incoming_call_notification;
  9mod notifications;
 10mod project_shared_notification;
 11mod sharing_status_indicator;
 12
 13use anyhow::anyhow;
 14use call::ActiveCall;
 15pub use collab_titlebar_item::{CollabTitlebarItem, ToggleContactsMenu};
 16use gpui::{actions, AppContext, Task};
 17use std::sync::Arc;
 18use workspace::{AppState, JoinProject, ToggleFollow, Workspace};
 19
 20actions!(collab, [ToggleScreenSharing]);
 21
 22pub fn init(app_state: Arc<AppState>, cx: &mut AppContext) {
 23    collab_titlebar_item::init(cx);
 24    contact_notification::init(cx);
 25    contact_list::init(cx);
 26    contact_finder::init(cx);
 27    contacts_popover::init(cx);
 28    incoming_call_notification::init(cx);
 29    project_shared_notification::init(cx);
 30    sharing_status_indicator::init(cx);
 31
 32    cx.add_global_action(toggle_screen_sharing);
 33    cx.add_global_action(move |action: &JoinProject, cx| {
 34        join_project(action, app_state.clone(), cx);
 35    });
 36}
 37
 38pub fn toggle_screen_sharing(_: &ToggleScreenSharing, cx: &mut AppContext) {
 39    if let Some(room) = ActiveCall::global(cx).read(cx).room().cloned() {
 40        let toggle_screen_sharing = room.update(cx, |room, cx| {
 41            if room.is_screen_sharing() {
 42                Task::ready(room.unshare_screen(cx))
 43            } else {
 44                room.share_screen(cx)
 45            }
 46        });
 47        toggle_screen_sharing.detach_and_log_err(cx);
 48    }
 49}
 50
 51fn join_project(action: &JoinProject, app_state: Arc<AppState>, cx: &mut AppContext) {
 52    let project_id = action.project_id;
 53    let follow_user_id = action.follow_user_id;
 54    cx.spawn(|mut cx| async move {
 55        let existing_workspace = cx
 56            .window_ids()
 57            .into_iter()
 58            .filter_map(|window_id| cx.root_view(window_id)?.clone().downcast::<Workspace>())
 59            .find(|workspace| {
 60                cx.read_window(workspace.window_id(), |cx| {
 61                    workspace.read(cx).project().read(cx).remote_id() == Some(project_id)
 62                })
 63                .unwrap_or(false)
 64            });
 65
 66        let workspace = if let Some(existing_workspace) = existing_workspace {
 67            existing_workspace.downgrade()
 68        } else {
 69            let active_call = cx.read(ActiveCall::global);
 70            let room = active_call
 71                .read_with(&cx, |call, _| call.room().cloned())
 72                .ok_or_else(|| anyhow!("not in a call"))?;
 73            let project = room
 74                .update(&mut cx, |room, cx| {
 75                    room.join_project(
 76                        project_id,
 77                        app_state.languages.clone(),
 78                        app_state.fs.clone(),
 79                        cx,
 80                    )
 81                })
 82                .await?;
 83
 84            let (_, workspace) = cx.add_window(
 85                (app_state.build_window_options)(None, None, cx.platform().as_ref()),
 86                |cx| {
 87                    let mut workspace = Workspace::new(
 88                        Default::default(),
 89                        0,
 90                        project,
 91                        app_state.dock_default_item_factory,
 92                        app_state.background_actions,
 93                        cx,
 94                    );
 95                    (app_state.initialize_workspace)(&mut workspace, &app_state, cx);
 96                    workspace
 97                },
 98            );
 99            workspace.downgrade()
100        };
101
102        cx.activate_window(workspace.window_id());
103        cx.platform().activate(true);
104
105        workspace.update(&mut cx, |workspace, cx| {
106            if let Some(room) = ActiveCall::global(cx).read(cx).room().cloned() {
107                let follow_peer_id = room
108                    .read(cx)
109                    .remote_participants()
110                    .iter()
111                    .find(|(_, participant)| participant.user.id == follow_user_id)
112                    .map(|(_, p)| p.peer_id)
113                    .or_else(|| {
114                        // If we couldn't follow the given user, follow the host instead.
115                        let collaborator = workspace
116                            .project()
117                            .read(cx)
118                            .collaborators()
119                            .values()
120                            .find(|collaborator| collaborator.replica_id == 0)?;
121                        Some(collaborator.peer_id)
122                    });
123
124                if let Some(follow_peer_id) = follow_peer_id {
125                    if !workspace.is_being_followed(follow_peer_id) {
126                        workspace
127                            .toggle_follow(&ToggleFollow(follow_peer_id), cx)
128                            .map(|follow| follow.detach_and_log_err(cx));
129                    }
130                }
131            }
132        })?;
133
134        anyhow::Ok(())
135    })
136    .detach_and_log_err(cx);
137}