From 412535420bdaf2fd3af686c118c2c7f7e589401d Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Tue, 21 Sep 2021 12:21:03 -0700 Subject: [PATCH] Allow joining worktrees by clicking them in the people panel Co-Authored-By: Antonio Scandurra Co-Authored-By: Nathan Sobo --- server/src/rpc/store.rs | 1 + zed/assets/themes/_base.toml | 14 +++++--- zed/src/menus.rs | 5 --- zed/src/people_panel.rs | 67 ++++++++++++++++++++++-------------- zed/src/theme.rs | 9 ++--- zed/src/user.rs | 10 +++--- zed/src/workspace.rs | 10 +++--- zrpc/proto/zed.proto | 7 ++-- 8 files changed, 74 insertions(+), 49 deletions(-) diff --git a/server/src/rpc/store.rs b/server/src/rpc/store.rs index f57e7ed59b8912766815be4acad79178a5fc1c7b..80cd8e2b3be1ecaacd443630f517a8a699974310 100644 --- a/server/src/rpc/store.rs +++ b/server/src/rpc/store.rs @@ -202,6 +202,7 @@ impl Store { worktrees: Vec::new(), }); host.worktrees.push(proto::WorktreeMetadata { + id: *worktree_id, root_name: worktree.root_name.clone(), is_shared: worktree.share().is_ok(), guests: guests.into_iter().collect(), diff --git a/zed/assets/themes/_base.toml b/zed/assets/themes/_base.toml index 7b1fd8b9ffd75e918bc8c4da116f5c6437114828..58d0965defec60ef66765d18777e8d5eb59196bc 100644 --- a/zed/assets/themes/_base.toml +++ b/zed/assets/themes/_base.toml @@ -125,14 +125,20 @@ color = "$text.1.color" [people_panel] extends = "$panel" +host_avatar = { corner_radius = 10, width = 20 } host_username = { extends = "$text.0", padding.left = 5 } -worktree_host_avatar = { corner_radius = 10, width = 20 } -worktree_guest_avatar = { corner_radius = 8, width = 16 } +guest_avatar = { corner_radius = 8, width = 16 } -[people_panel.worktree_name] -extends = "$text.0" +[people_panel.worktree] +extends = "$text.1" padding = { left = 5 } +[people_panel.hovered_worktree] +extends = "$text.0" +padding = { left = 8 } +# extends = "$people_panel.worktree" +# color = "$text.0.color" + [people_panel.tree_branch] width = 1 color = "$surface.2" diff --git a/zed/src/menus.rs b/zed/src/menus.rs index 9ba28f9cef875b699bdc9ab5cc401c2f0c87332e..1fe4bd922ac09376f3dd3cb1b12718f3d2e45457 100644 --- a/zed/src/menus.rs +++ b/zed/src/menus.rs @@ -26,11 +26,6 @@ pub fn menus(state: &Arc) -> Vec> { keystroke: None, action: Box::new(workspace::ShareWorktree), }, - MenuItem::Action { - name: "Join", - keystroke: None, - action: Box::new(workspace::JoinWorktree(state.clone())), - }, MenuItem::Action { name: "Quit", keystroke: Some("cmd-q"), diff --git a/zed/src/people_panel.rs b/zed/src/people_panel.rs index 26dbc19f74c00e49792ce3cc3a4198069439f6a4..24cd7c96bbcfc3db83b2544039125c2a370d340c 100644 --- a/zed/src/people_panel.rs +++ b/zed/src/people_panel.rs @@ -4,13 +4,17 @@ use crate::{ Settings, }; use gpui::{ + action, elements::*, geometry::{rect::RectF, vector::vec2f}, - Element, ElementBox, Entity, FontCache, ModelHandle, RenderContext, Subscription, View, + platform::CursorStyle, + Element, ElementBox, Entity, LayoutContext, ModelHandle, RenderContext, Subscription, View, ViewContext, }; use postage::watch; +action!(JoinWorktree, u64); + pub struct PeoplePanel { collaborators: ListState, user_store: ModelHandle, @@ -33,11 +37,8 @@ impl PeoplePanel { let user_store = user_store.clone(); let settings = settings.clone(); move |ix, cx| { - Self::render_collaborator( - &user_store.read(cx).collaborators()[ix], - &settings.borrow().theme, - cx.font_cache(), - ) + let collaborators = user_store.read(cx).collaborators().clone(); + Self::render_collaborator(&collaborators[ix], &settings.borrow().theme, cx) } }, ), @@ -56,23 +57,26 @@ impl PeoplePanel { fn render_collaborator( collaborator: &Collaborator, theme: &Theme, - font_cache: &FontCache, + cx: &mut LayoutContext, ) -> ElementBox { let theme = &theme.people_panel; let worktree_count = collaborator.worktrees.len(); - let line_height = theme.worktree_name.text.line_height(font_cache); - let cap_height = theme.worktree_name.text.cap_height(font_cache); - let baseline_offset = theme.worktree_name.text.baseline_offset(font_cache); + let font_cache = cx.font_cache(); + let line_height = theme.worktree.text.line_height(font_cache); + let cap_height = theme.worktree.text.cap_height(font_cache); + let baseline_offset = theme.worktree.text.baseline_offset(font_cache); let tree_branch = theme.tree_branch; Flex::column() .with_child( Flex::row() - .with_children(collaborator.user.avatar.clone().map(|avatar| { - Image::new(avatar) - .with_style(theme.worktree_host_avatar) - .boxed() - })) + .with_children( + collaborator + .user + .avatar + .clone() + .map(|avatar| Image::new(avatar).with_style(theme.host_avatar).boxed()), + ) .with_child( Container::new( Label::new( @@ -92,6 +96,7 @@ impl PeoplePanel { .iter() .enumerate() .map(|(ix, worktree)| { + let worktree_id = worktree.id; Flex::row() .with_child( ConstrainedBox::new( @@ -136,21 +141,33 @@ impl PeoplePanel { .boxed(), ) .with_child( - Container::new( - Label::new( - worktree.root_name.clone(), - theme.worktree_name.text.clone(), - ) - .boxed(), + MouseEventHandler::new::( + worktree_id as usize, + cx, + |mouse_state, _| { + let style = if mouse_state.hovered { + &theme.hovered_worktree + } else { + &theme.worktree + }; + Container::new( + Label::new( + worktree.root_name.clone(), + style.text.clone(), + ) + .boxed(), + ) + .with_style(style.container) + .boxed() + }, ) - .with_style(theme.worktree_name.container) + .with_cursor_style(CursorStyle::PointingHand) + .on_click(move |cx| cx.dispatch_action(JoinWorktree(worktree_id))) .boxed(), ) .with_children(worktree.guests.iter().filter_map(|participant| { participant.avatar.clone().map(|avatar| { - Image::new(avatar) - .with_style(theme.worktree_guest_avatar) - .boxed() + Image::new(avatar).with_style(theme.guest_avatar).boxed() }) })) .boxed() diff --git a/zed/src/theme.rs b/zed/src/theme.rs index b7a4f41023dda27fcd7cdee3e32c404e4967bb14..3dbf9d0601d327cbbbd709d67d4f5954631e708e 100644 --- a/zed/src/theme.rs +++ b/zed/src/theme.rs @@ -109,10 +109,11 @@ pub struct ChatPanel { pub struct PeoplePanel { #[serde(flatten)] pub container: ContainerStyle, + pub host_avatar: ImageStyle, pub host_username: ContainedText, - pub worktree_name: ContainedText, - pub worktree_host_avatar: ImageStyle, - pub worktree_guest_avatar: ImageStyle, + pub worktree: ContainedText, + pub hovered_worktree: ContainedText, + pub guest_avatar: ImageStyle, pub tree_branch: TreeBranch, } @@ -161,7 +162,7 @@ pub struct Selector { pub active_item: ContainedLabel, } -#[derive(Deserialize)] +#[derive(Debug, Deserialize)] pub struct ContainedText { #[serde(flatten)] pub container: ContainerStyle, diff --git a/zed/src/user.rs b/zed/src/user.rs index 32c271257fc49676ea54315eb17d452716e691c5..4c59f64b83503bd63ab6bc3cfce5408c4aeacaad 100644 --- a/zed/src/user.rs +++ b/zed/src/user.rs @@ -28,6 +28,7 @@ pub struct Collaborator { #[derive(Debug)] pub struct WorktreeMetadata { + pub id: u64, pub root_name: String, pub is_shared: bool, pub guests: Vec>, @@ -36,7 +37,7 @@ pub struct WorktreeMetadata { pub struct UserStore { users: HashMap>, current_user: watch::Receiver>>, - collaborators: Vec, + collaborators: Arc<[Collaborator]>, rpc: Arc, http: Arc, _maintain_collaborators: Task<()>, @@ -64,7 +65,7 @@ impl UserStore { Self { users: Default::default(), current_user: current_user_rx, - collaborators: Default::default(), + collaborators: Arc::from([]), rpc: rpc.clone(), http, _maintain_collaborators: cx.spawn_weak(|this, mut cx| async move { @@ -127,7 +128,7 @@ impl UserStore { } this.update(&mut cx, |this, cx| { - this.collaborators = collaborators; + this.collaborators = collaborators.into(); cx.notify(); }); @@ -135,7 +136,7 @@ impl UserStore { }) } - pub fn collaborators(&self) -> &[Collaborator] { + pub fn collaborators(&self) -> &Arc<[Collaborator]> { &self.collaborators } @@ -235,6 +236,7 @@ impl Collaborator { ); } worktrees.push(WorktreeMetadata { + id: worktree.id, root_name: worktree.root_name, is_shared: worktree.is_shared, guests, diff --git a/zed/src/workspace.rs b/zed/src/workspace.rs index f3db51077dd42a1d057dc4cc96b309d86309486b..89a48a99fdf929da95b10ab22e8c08d8304e542a 100644 --- a/zed/src/workspace.rs +++ b/zed/src/workspace.rs @@ -7,7 +7,7 @@ use crate::{ editor::Buffer, fs::Fs, language::LanguageRegistry, - people_panel::PeoplePanel, + people_panel::{JoinWorktree, PeoplePanel}, project_browser::ProjectBrowser, rpc, settings::Settings, @@ -44,7 +44,6 @@ action!(Open, Arc); action!(OpenPaths, OpenParams); action!(OpenNew, Arc); action!(ShareWorktree); -action!(JoinWorktree, Arc); action!(Save); action!(DebugElements); @@ -59,6 +58,7 @@ pub fn init(cx: &mut MutableAppContext) { cx.add_action(Workspace::open_new_file); cx.add_action(Workspace::share_worktree); cx.add_action(Workspace::toggle_sidebar_item); + cx.add_action(Workspace::join_worktree); cx.add_bindings(vec![ Binding::new("cmd-s", Save, None), Binding::new("cmd-alt-i", DebugElements, None), @@ -839,14 +839,16 @@ impl Workspace { .detach(); } - fn join_worktree(&mut self, id: u64, cx: &mut ViewContext) { + fn join_worktree(&mut self, action: &JoinWorktree, cx: &mut ViewContext) { let rpc = self.rpc.clone(); let languages = self.languages.clone(); + let worktree_id = action.0; cx.spawn(|this, mut cx| { async move { rpc.authenticate_and_connect(&cx).await?; - let worktree = Worktree::open_remote(rpc.clone(), id, languages, &mut cx).await?; + let worktree = + Worktree::open_remote(rpc.clone(), worktree_id, languages, &mut cx).await?; this.update(&mut cx, |workspace, cx| { cx.observe(&worktree, |_, _, cx| cx.notify()).detach(); workspace.worktrees.insert(worktree); diff --git a/zrpc/proto/zed.proto b/zrpc/proto/zed.proto index be85fdecd6ba49235de13bb157c2610a7e22a21b..0f0ea69261c07edbf9357959a5b0c39345631994 100644 --- a/zrpc/proto/zed.proto +++ b/zrpc/proto/zed.proto @@ -343,7 +343,8 @@ message Collaborator { } message WorktreeMetadata { - string root_name = 1; - bool is_shared = 2; - repeated uint64 guests = 3; + uint64 id = 1; + string root_name = 2; + bool is_shared = 3; + repeated uint64 guests = 4; }