From bf488f2027a432d7cdd67771ae4bca0ba3393ed9 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Tue, 11 Oct 2022 10:59:36 +0200 Subject: [PATCH] Show project root names when displaying incoming call notification --- crates/call/src/call.rs | 4 +- crates/collab/src/integration_tests.rs | 6 ++- crates/collab/src/rpc/store.rs | 35 +++++++++----- .../src/incoming_call_notification.rs | 46 ++++++++++++++++--- crates/rpc/proto/zed.proto | 2 +- crates/theme/src/theme.rs | 3 ++ .../src/styleTree/incomingCallNotification.ts | 6 +++ .../styleTree/projectSharedNotification.ts | 2 +- 8 files changed, 81 insertions(+), 23 deletions(-) diff --git a/crates/call/src/call.rs b/crates/call/src/call.rs index 99edb33b6e..6b06d04375 100644 --- a/crates/call/src/call.rs +++ b/crates/call/src/call.rs @@ -23,7 +23,7 @@ pub struct IncomingCall { pub room_id: u64, pub caller: Arc, pub participants: Vec>, - pub initial_project_id: Option, + pub initial_project: Option, } pub struct ActiveCall { @@ -78,7 +78,7 @@ impl ActiveCall { user_store.get_user(envelope.payload.caller_user_id, cx) }) .await?, - initial_project_id: envelope.payload.initial_project_id, + initial_project: envelope.payload.initial_project, }; this.update(&mut cx, |this, _| { *this.incoming_call.0.borrow_mut() = Some(call); diff --git a/crates/collab/src/integration_tests.rs b/crates/collab/src/integration_tests.rs index 06e009d08b..ce9d01e3d3 100644 --- a/crates/collab/src/integration_tests.rs +++ b/crates/collab/src/integration_tests.rs @@ -541,13 +541,15 @@ async fn test_share_project( deterministic.run_until_parked(); let call = incoming_call_b.borrow().clone().unwrap(); assert_eq!(call.caller.github_login, "user_a"); - let project_id = call.initial_project_id.unwrap(); + let initial_project = call.initial_project.unwrap(); active_call_b .update(cx_b, |call, cx| call.accept_incoming(cx)) .await .unwrap(); let client_b_peer_id = client_b.peer_id; - let project_b = client_b.build_remote_project(project_id, cx_b).await; + let project_b = client_b + .build_remote_project(initial_project.id, cx_b) + .await; let replica_id_b = project_b.read_with(cx_b, |project, _| project.replica_id()); deterministic.run_until_parked(); diff --git a/crates/collab/src/rpc/store.rs b/crates/collab/src/rpc/store.rs index 522438255a..12f50db48e 100644 --- a/crates/collab/src/rpc/store.rs +++ b/crates/collab/src/rpc/store.rs @@ -176,9 +176,9 @@ impl Store { .iter() .map(|participant| participant.user_id) .collect(), - initial_project_id: active_call + initial_project: active_call .initial_project_id - .map(|project_id| project_id.to_proto()), + .and_then(|id| Self::build_participant_project(id, &self.projects)), }) } } else { @@ -572,7 +572,8 @@ impl Store { .iter() .map(|participant| participant.user_id) .collect(), - initial_project_id: initial_project_id.map(|project_id| project_id.to_proto()), + initial_project: initial_project_id + .and_then(|id| Self::build_participant_project(id, &self.projects)), }, )) } @@ -726,14 +727,6 @@ impl Store { .iter_mut() .find(|participant| participant.peer_id == host_connection_id.0) .ok_or_else(|| anyhow!("no such room"))?; - participant.projects.push(proto::ParticipantProject { - id: project_id.to_proto(), - worktree_root_names: worktrees - .iter() - .filter(|worktree| worktree.visible) - .map(|worktree| worktree.root_name.clone()) - .collect(), - }); connection.projects.insert(project_id); self.projects.insert( @@ -767,6 +760,10 @@ impl Store { }, ); + participant + .projects + .extend(Self::build_participant_project(project_id, &self.projects)); + Ok(room) } @@ -1011,6 +1008,22 @@ impl Store { Ok(connection_ids) } + fn build_participant_project( + project_id: ProjectId, + projects: &BTreeMap, + ) -> Option { + Some(proto::ParticipantProject { + id: project_id.to_proto(), + worktree_root_names: projects + .get(&project_id)? + .worktrees + .values() + .filter(|worktree| worktree.visible) + .map(|worktree| worktree.root_name.clone()) + .collect(), + }) + } + pub fn project_connection_ids( &self, project_id: ProjectId, diff --git a/crates/collab_ui/src/incoming_call_notification.rs b/crates/collab_ui/src/incoming_call_notification.rs index cbb23de2e6..ff359b9d9e 100644 --- a/crates/collab_ui/src/incoming_call_notification.rs +++ b/crates/collab_ui/src/incoming_call_notification.rs @@ -1,4 +1,5 @@ use call::{ActiveCall, IncomingCall}; +use client::proto; use futures::StreamExt; use gpui::{ elements::*, @@ -26,7 +27,11 @@ pub fn init(cx: &mut MutableAppContext) { if let Some(incoming_call) = incoming_call { const PADDING: f32 = 16.; let screen_size = cx.platform().screen_size(); - let window_size = vec2f(274., 64.); + + let window_size = cx.read(|cx| { + let theme = &cx.global::().theme.incoming_call_notification; + vec2f(theme.window_width, theme.window_height) + }); let (window_id, _) = cx.add_window( WindowOptions { bounds: WindowBounds::Fixed(RectF::new( @@ -66,7 +71,7 @@ impl IncomingCallNotification { if action.accept { let join = active_call.update(cx, |active_call, cx| active_call.accept_incoming(cx)); let caller_user_id = self.call.caller.id; - let initial_project_id = self.call.initial_project_id; + let initial_project_id = self.call.initial_project.as_ref().map(|project| project.id); cx.spawn_weak(|_, mut cx| async move { join.await?; if let Some(project_id) = initial_project_id { @@ -89,6 +94,12 @@ impl IncomingCallNotification { fn render_caller(&self, cx: &mut RenderContext) -> ElementBox { let theme = &cx.global::().theme.incoming_call_notification; + let default_project = proto::ParticipantProject::default(); + let initial_project = self + .call + .initial_project + .as_ref() + .unwrap_or(&default_project); Flex::row() .with_children(self.call.caller.avatar.clone().map(|avatar| { Image::new(avatar) @@ -108,11 +119,34 @@ impl IncomingCallNotification { .boxed(), ) .with_child( - Label::new("is calling you".into(), theme.caller_message.text.clone()) - .contained() - .with_style(theme.caller_message.container) - .boxed(), + Label::new( + format!( + "is sharing a project in Zed{}", + if initial_project.worktree_root_names.is_empty() { + "" + } else { + ":" + } + ), + theme.caller_message.text.clone(), + ) + .contained() + .with_style(theme.caller_message.container) + .boxed(), ) + .with_children(if initial_project.worktree_root_names.is_empty() { + None + } else { + Some( + Label::new( + initial_project.worktree_root_names.join(", "), + theme.worktree_roots.text.clone(), + ) + .contained() + .with_style(theme.worktree_roots.container) + .boxed(), + ) + }) .contained() .with_style(theme.caller_metadata) .aligned() diff --git a/crates/rpc/proto/zed.proto b/crates/rpc/proto/zed.proto index b1897653c9..2a358113e9 100644 --- a/crates/rpc/proto/zed.proto +++ b/crates/rpc/proto/zed.proto @@ -195,7 +195,7 @@ message IncomingCall { uint64 room_id = 1; uint64 caller_user_id = 2; repeated uint64 participant_user_ids = 3; - optional uint64 initial_project_id = 4; + optional ParticipantProject initial_project = 4; } message CallCanceled {} diff --git a/crates/theme/src/theme.rs b/crates/theme/src/theme.rs index 7f11ae6e03..9a836864bf 100644 --- a/crates/theme/src/theme.rs +++ b/crates/theme/src/theme.rs @@ -488,6 +488,8 @@ pub struct ProjectSharedNotification { #[derive(Deserialize, Default)] pub struct IncomingCallNotification { + pub window_height: f32, + pub window_width: f32, #[serde(default)] pub background: Color, pub caller_container: ContainerStyle, @@ -495,6 +497,7 @@ pub struct IncomingCallNotification { pub caller_metadata: ContainerStyle, pub caller_username: ContainedText, pub caller_message: ContainedText, + pub worktree_roots: ContainedText, pub button_width: f32, pub accept_button: ContainedText, pub decline_button: ContainedText, diff --git a/styles/src/styleTree/incomingCallNotification.ts b/styles/src/styleTree/incomingCallNotification.ts index d8ea7dbad9..30b8ae90ca 100644 --- a/styles/src/styleTree/incomingCallNotification.ts +++ b/styles/src/styleTree/incomingCallNotification.ts @@ -4,6 +4,8 @@ import { backgroundColor, borderColor, text } from "./components"; export default function incomingCallNotification(theme: Theme): Object { const avatarSize = 32; return { + windowHeight: 74, + windowWidth: 380, background: backgroundColor(theme, 300), callerContainer: { padding: 12, @@ -24,6 +26,10 @@ export default function incomingCallNotification(theme: Theme): Object { ...text(theme, "sans", "secondary", { size: "xs" }), margin: { top: -3 }, }, + worktreeRoots: { + ...text(theme, "sans", "secondary", { size: "xs", weight: "bold" }), + margin: { top: -3 }, + }, buttonWidth: 96, acceptButton: { background: backgroundColor(theme, "ok", "active"), diff --git a/styles/src/styleTree/projectSharedNotification.ts b/styles/src/styleTree/projectSharedNotification.ts index f6ebf4781a..e3cb29bbf1 100644 --- a/styles/src/styleTree/projectSharedNotification.ts +++ b/styles/src/styleTree/projectSharedNotification.ts @@ -4,7 +4,7 @@ import { backgroundColor, borderColor, text } from "./components"; export default function projectSharedNotification(theme: Theme): Object { const avatarSize = 48; return { - windowHeight: 72, + windowHeight: 74, windowWidth: 380, background: backgroundColor(theme, 300), ownerContainer: {