Detailed changes
@@ -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(),
@@ -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"
@@ -26,11 +26,6 @@ pub fn menus(state: &Arc<AppState>) -> Vec<Menu<'static>> {
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"),
@@ -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<UserStore>,
@@ -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::<PeoplePanel, _, _, _>(
+ 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()
@@ -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,
@@ -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<Arc<User>>,
@@ -36,7 +37,7 @@ pub struct WorktreeMetadata {
pub struct UserStore {
users: HashMap<u64, Arc<User>>,
current_user: watch::Receiver<Option<Arc<User>>>,
- collaborators: Vec<Collaborator>,
+ collaborators: Arc<[Collaborator]>,
rpc: Arc<Client>,
http: Arc<dyn HttpClient>,
_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,
@@ -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<AppState>);
action!(OpenPaths, OpenParams);
action!(OpenNew, Arc<AppState>);
action!(ShareWorktree);
-action!(JoinWorktree, Arc<AppState>);
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<Self>) {
+ fn join_worktree(&mut self, action: &JoinWorktree, cx: &mut ViewContext<Self>) {
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);
@@ -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;
}