Allow active call to be optional on workspace

This prepares us for a future where the workspace is unaware of the
active call and doesn't require all tests to invoke `call::init`.
This commit is contained in:
Antonio Scandurra 2022-10-11 17:25:35 +02:00
parent ee2587d3e5
commit 4c07a0782b
3 changed files with 42 additions and 24 deletions

View file

@ -60,9 +60,11 @@ impl PaneGroup {
project: &ModelHandle<Project>, project: &ModelHandle<Project>,
theme: &Theme, theme: &Theme,
follower_states: &FollowerStatesByLeader, follower_states: &FollowerStatesByLeader,
active_call: Option<&ModelHandle<ActiveCall>>,
cx: &mut RenderContext<Workspace>, cx: &mut RenderContext<Workspace>,
) -> ElementBox { ) -> ElementBox {
self.root.render(project, theme, follower_states, cx) self.root
.render(project, theme, follower_states, active_call, cx)
} }
pub(crate) fn panes(&self) -> Vec<&ViewHandle<Pane>> { pub(crate) fn panes(&self) -> Vec<&ViewHandle<Pane>> {
@ -105,6 +107,7 @@ impl Member {
project: &ModelHandle<Project>, project: &ModelHandle<Project>,
theme: &Theme, theme: &Theme,
follower_states: &FollowerStatesByLeader, follower_states: &FollowerStatesByLeader,
active_call: Option<&ModelHandle<ActiveCall>>,
cx: &mut RenderContext<Workspace>, cx: &mut RenderContext<Workspace>,
) -> ElementBox { ) -> ElementBox {
enum FollowIntoExternalProject {} enum FollowIntoExternalProject {}
@ -121,7 +124,7 @@ impl Member {
} }
}) })
.and_then(|leader_id| { .and_then(|leader_id| {
let room = ActiveCall::global(cx).read(cx).room()?.read(cx); let room = active_call?.read(cx).room()?.read(cx);
let collaborator = project.read(cx).collaborators().get(leader_id)?; let collaborator = project.read(cx).collaborators().get(leader_id)?;
let participant = room.remote_participants().get(&leader_id)?; let participant = room.remote_participants().get(&leader_id)?;
Some((collaborator.replica_id, participant)) Some((collaborator.replica_id, participant))
@ -223,7 +226,7 @@ impl Member {
.with_children(prompt) .with_children(prompt)
.boxed() .boxed()
} }
Member::Axis(axis) => axis.render(project, theme, follower_states, cx), Member::Axis(axis) => axis.render(project, theme, follower_states, active_call, cx),
} }
} }
@ -328,12 +331,13 @@ impl PaneAxis {
project: &ModelHandle<Project>, project: &ModelHandle<Project>,
theme: &Theme, theme: &Theme,
follower_state: &FollowerStatesByLeader, follower_state: &FollowerStatesByLeader,
active_call: Option<&ModelHandle<ActiveCall>>,
cx: &mut RenderContext<Workspace>, cx: &mut RenderContext<Workspace>,
) -> ElementBox { ) -> ElementBox {
let last_member_ix = self.members.len() - 1; let last_member_ix = self.members.len() - 1;
Flex::new(self.axis) Flex::new(self.axis)
.with_children(self.members.iter().enumerate().map(|(ix, member)| { .with_children(self.members.iter().enumerate().map(|(ix, member)| {
let mut member = member.render(project, theme, follower_state, cx); let mut member = member.render(project, theme, follower_state, active_call, cx);
if ix < last_member_ix { if ix < last_member_ix {
let mut border = theme.workspace.pane_divider; let mut border = theme.workspace.pane_divider;
border.left = false; border.left = false;

View file

@ -980,8 +980,9 @@ pub struct Workspace {
follower_states_by_leader: FollowerStatesByLeader, follower_states_by_leader: FollowerStatesByLeader,
last_leaders_by_pane: HashMap<WeakViewHandle<Pane>, PeerId>, last_leaders_by_pane: HashMap<WeakViewHandle<Pane>, PeerId>,
window_edited: bool, window_edited: bool,
active_call: Option<ModelHandle<ActiveCall>>,
_observe_current_user: Task<()>, _observe_current_user: Task<()>,
_active_call_observation: gpui::Subscription, _active_call_observation: Option<gpui::Subscription>,
} }
#[derive(Default)] #[derive(Default)]
@ -1090,6 +1091,14 @@ impl Workspace {
drag_and_drop.register_container(weak_handle.clone()); drag_and_drop.register_container(weak_handle.clone());
}); });
let mut active_call = None;
let mut active_call_observation = None;
if cx.has_global::<ModelHandle<ActiveCall>>() {
let call = cx.global::<ModelHandle<ActiveCall>>().clone();
active_call_observation = Some(cx.observe(&call, |_, _, cx| cx.notify()));
active_call = Some(call);
}
let mut this = Workspace { let mut this = Workspace {
modal: None, modal: None,
weak_self: weak_handle, weak_self: weak_handle,
@ -1116,8 +1125,9 @@ impl Workspace {
follower_states_by_leader: Default::default(), follower_states_by_leader: Default::default(),
last_leaders_by_pane: Default::default(), last_leaders_by_pane: Default::default(),
window_edited: false, window_edited: false,
active_call,
_observe_current_user, _observe_current_user,
_active_call_observation: cx.observe(&ActiveCall::global(cx), |_, _, cx| cx.notify()), _active_call_observation: active_call_observation,
}; };
this.project_remote_id_changed(this.project.read(cx).remote_id(), cx); this.project_remote_id_changed(this.project.read(cx).remote_id(), cx);
cx.defer(|this, cx| this.update_window_title(cx)); cx.defer(|this, cx| this.update_window_title(cx));
@ -1248,30 +1258,32 @@ impl Workspace {
quitting: bool, quitting: bool,
cx: &mut ViewContext<Self>, cx: &mut ViewContext<Self>,
) -> Task<Result<bool>> { ) -> Task<Result<bool>> {
let active_call = ActiveCall::global(cx); let active_call = self.active_call.clone();
let window_id = cx.window_id(); let window_id = cx.window_id();
let workspace_count = cx let workspace_count = cx
.window_ids() .window_ids()
.flat_map(|window_id| cx.root_view::<Workspace>(window_id)) .flat_map(|window_id| cx.root_view::<Workspace>(window_id))
.count(); .count();
cx.spawn(|this, mut cx| async move { cx.spawn(|this, mut cx| async move {
if !quitting if let Some(active_call) = active_call {
&& workspace_count == 1 if !quitting
&& active_call.read_with(&cx, |call, _| call.room().is_some()) && workspace_count == 1
{ && active_call.read_with(&cx, |call, _| call.room().is_some())
let answer = cx {
.prompt( let answer = cx
window_id, .prompt(
PromptLevel::Warning, window_id,
"Do you want to leave the current call?", PromptLevel::Warning,
&["Close window and hang up", "Cancel"], "Do you want to leave the current call?",
) &["Close window and hang up", "Cancel"],
.next() )
.await; .next()
if answer == Some(1) { .await;
return anyhow::Ok(false); if answer == Some(1) {
} else { return anyhow::Ok(false);
active_call.update(&mut cx, |call, cx| call.hang_up(cx))?; } else {
active_call.update(&mut cx, |call, cx| call.hang_up(cx))?;
}
} }
} }
@ -2571,6 +2583,7 @@ impl View for Workspace {
&project, &project,
&theme, &theme,
&self.follower_states_by_leader, &self.follower_states_by_leader,
self.active_call.as_ref(),
cx, cx,
)) ))
.flex(1., true) .flex(1., true)

View file

@ -1755,6 +1755,7 @@ mod tests {
let state = Arc::get_mut(&mut app_state).unwrap(); let state = Arc::get_mut(&mut app_state).unwrap();
state.initialize_workspace = initialize_workspace; state.initialize_workspace = initialize_workspace;
state.build_window_options = build_window_options; state.build_window_options = build_window_options;
call::init(app_state.client.clone(), app_state.user_store.clone(), cx);
workspace::init(app_state.clone(), cx); workspace::init(app_state.clone(), cx);
editor::init(cx); editor::init(cx);
pane::init(cx); pane::init(cx);