Absolute pain of the iterator kind (start laying out a user's followers)
This commit is contained in:
parent
2592ec7265
commit
58c41778e7
3 changed files with 70 additions and 26 deletions
|
@ -55,7 +55,7 @@ pub struct Room {
|
||||||
leave_when_empty: bool,
|
leave_when_empty: bool,
|
||||||
client: Arc<Client>,
|
client: Arc<Client>,
|
||||||
user_store: ModelHandle<UserStore>,
|
user_store: ModelHandle<UserStore>,
|
||||||
follows_by_leader_id: HashMap<PeerId, HashSet<PeerId>>,
|
follows_by_leader_id: HashMap<PeerId, Vec<PeerId>>,
|
||||||
subscriptions: Vec<client::Subscription>,
|
subscriptions: Vec<client::Subscription>,
|
||||||
pending_room_update: Option<Task<()>>,
|
pending_room_update: Option<Task<()>>,
|
||||||
maintain_connection: Option<Task<Option<()>>>,
|
maintain_connection: Option<Task<Option<()>>>,
|
||||||
|
@ -459,6 +459,12 @@ impl Room {
|
||||||
self.participant_user_ids.contains(&user_id)
|
self.participant_user_ids.contains(&user_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn follows(&self, leader_id: PeerId) -> &[PeerId] {
|
||||||
|
self.follows_by_leader_id
|
||||||
|
.get(&leader_id)
|
||||||
|
.map_or(&[], |v| v.as_slice())
|
||||||
|
}
|
||||||
|
|
||||||
async fn handle_room_updated(
|
async fn handle_room_updated(
|
||||||
this: ModelHandle<Self>,
|
this: ModelHandle<Self>,
|
||||||
envelope: TypedEnvelope<proto::RoomUpdated>,
|
envelope: TypedEnvelope<proto::RoomUpdated>,
|
||||||
|
@ -636,10 +642,13 @@ impl Room {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
this.follows_by_leader_id
|
let list = this
|
||||||
|
.follows_by_leader_id
|
||||||
.entry(leader)
|
.entry(leader)
|
||||||
.or_insert(Default::default())
|
.or_insert(Vec::new());
|
||||||
.insert(follower);
|
if !list.contains(&follower) {
|
||||||
|
list.push(follower);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.pending_room_update.take();
|
this.pending_room_update.take();
|
||||||
|
|
|
@ -12,11 +12,11 @@ use gpui::{
|
||||||
elements::*,
|
elements::*,
|
||||||
geometry::{rect::RectF, vector::vec2f, PathBuilder},
|
geometry::{rect::RectF, vector::vec2f, PathBuilder},
|
||||||
json::{self, ToJson},
|
json::{self, ToJson},
|
||||||
Border, CursorStyle, Entity, ModelHandle, MouseButton, MutableAppContext, RenderContext,
|
Border, CursorStyle, Entity, ImageData, ModelHandle, MouseButton, MutableAppContext,
|
||||||
Subscription, View, ViewContext, ViewHandle, WeakViewHandle,
|
RenderContext, Subscription, View, ViewContext, ViewHandle, WeakViewHandle,
|
||||||
};
|
};
|
||||||
use settings::Settings;
|
use settings::Settings;
|
||||||
use std::ops::Range;
|
use std::{ops::Range, sync::Arc};
|
||||||
use theme::Theme;
|
use theme::Theme;
|
||||||
use util::ResultExt;
|
use util::ResultExt;
|
||||||
use workspace::{FollowNextCollaborator, JoinProject, ToggleFollow, Workspace};
|
use workspace::{FollowNextCollaborator, JoinProject, ToggleFollow, Workspace};
|
||||||
|
@ -510,11 +510,7 @@ impl CollabTitlebarItem {
|
||||||
Some(self.render_face_pile(
|
Some(self.render_face_pile(
|
||||||
&user,
|
&user,
|
||||||
replica_id,
|
replica_id,
|
||||||
Some((
|
Some((participant.peer_id, participant.location)),
|
||||||
participant.peer_id,
|
|
||||||
&user.github_login,
|
|
||||||
participant.location,
|
|
||||||
)),
|
|
||||||
workspace,
|
workspace,
|
||||||
theme,
|
theme,
|
||||||
cx,
|
cx,
|
||||||
|
@ -564,18 +560,23 @@ impl CollabTitlebarItem {
|
||||||
&self,
|
&self,
|
||||||
user: &User,
|
user: &User,
|
||||||
replica_id: Option<ReplicaId>,
|
replica_id: Option<ReplicaId>,
|
||||||
peer: Option<(PeerId, &str, ParticipantLocation)>,
|
peer_id_and_location: Option<(PeerId, ParticipantLocation)>,
|
||||||
workspace: &ViewHandle<Workspace>,
|
workspace: &ViewHandle<Workspace>,
|
||||||
theme: &Theme,
|
theme: &Theme,
|
||||||
cx: &mut RenderContext<Self>,
|
cx: &mut RenderContext<Self>,
|
||||||
) -> ElementBox {
|
) -> ElementBox {
|
||||||
let is_followed = peer.map_or(false, |(peer_id, _, _)| {
|
let is_followed = peer_id_and_location.map_or(false, |(peer_id, _)| {
|
||||||
workspace.read(cx).is_following(peer_id)
|
workspace.read(cx).is_following(peer_id)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let room = ActiveCall::global(cx).read(cx).room();
|
||||||
|
let get_followers = |leader_id: PeerId| -> &[PeerId] {
|
||||||
|
room.map_or(&[], |room| room.read(cx).follows(leader_id))
|
||||||
|
};
|
||||||
|
|
||||||
let mut avatar_style;
|
let mut avatar_style;
|
||||||
if let Some((_, _, location)) = peer.as_ref() {
|
if let Some((_, location)) = peer_id_and_location {
|
||||||
if let ParticipantLocation::SharedProject { project_id } = *location {
|
if let ParticipantLocation::SharedProject { project_id } = location {
|
||||||
if Some(project_id) == workspace.read(cx).project().read(cx).remote_id() {
|
if Some(project_id) == workspace.read(cx).project().read(cx).remote_id() {
|
||||||
avatar_style = theme.workspace.titlebar.avatar;
|
avatar_style = theme.workspace.titlebar.avatar;
|
||||||
} else {
|
} else {
|
||||||
|
@ -599,11 +600,36 @@ impl CollabTitlebarItem {
|
||||||
|
|
||||||
let content = Stack::new()
|
let content = Stack::new()
|
||||||
.with_children(user.avatar.as_ref().map(|avatar| {
|
.with_children(user.avatar.as_ref().map(|avatar| {
|
||||||
Image::new(avatar.clone())
|
Flex::row()
|
||||||
.with_style(avatar_style)
|
.with_child(Self::render_face(avatar.clone(), avatar_style, theme))
|
||||||
.constrained()
|
.with_children(
|
||||||
.with_width(theme.workspace.titlebar.avatar_width)
|
peer_id_and_location
|
||||||
.aligned()
|
.map(|(peer_id, _)| {
|
||||||
|
get_followers(peer_id)
|
||||||
|
.into_iter()
|
||||||
|
.map(|&follower| {
|
||||||
|
room.map(|room| {
|
||||||
|
room.read(cx)
|
||||||
|
.remote_participant_for_peer_id(follower)
|
||||||
|
.map(|participant| {
|
||||||
|
participant.user.avatar.as_ref().map(|avatar| {
|
||||||
|
Self::render_face(
|
||||||
|
avatar.clone(),
|
||||||
|
avatar_style,
|
||||||
|
theme,
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.flatten()
|
||||||
|
})
|
||||||
|
.flatten()
|
||||||
|
})
|
||||||
|
.flatten()
|
||||||
|
})
|
||||||
|
.into_iter()
|
||||||
|
.flatten(),
|
||||||
|
)
|
||||||
|
.with_reversed_paint_order()
|
||||||
.boxed()
|
.boxed()
|
||||||
}))
|
}))
|
||||||
.with_children(replica_color.map(|replica_color| {
|
.with_children(replica_color.map(|replica_color| {
|
||||||
|
@ -621,7 +647,7 @@ impl CollabTitlebarItem {
|
||||||
.with_margin_left(theme.workspace.titlebar.avatar_margin)
|
.with_margin_left(theme.workspace.titlebar.avatar_margin)
|
||||||
.boxed();
|
.boxed();
|
||||||
|
|
||||||
if let Some((peer_id, peer_github_login, location)) = peer {
|
if let Some((peer_id, location)) = peer_id_and_location {
|
||||||
if let Some(replica_id) = replica_id {
|
if let Some(replica_id) = replica_id {
|
||||||
MouseEventHandler::<ToggleFollow>::new(replica_id.into(), cx, move |_, _| content)
|
MouseEventHandler::<ToggleFollow>::new(replica_id.into(), cx, move |_, _| content)
|
||||||
.with_cursor_style(CursorStyle::PointingHand)
|
.with_cursor_style(CursorStyle::PointingHand)
|
||||||
|
@ -631,9 +657,9 @@ impl CollabTitlebarItem {
|
||||||
.with_tooltip::<ToggleFollow, _>(
|
.with_tooltip::<ToggleFollow, _>(
|
||||||
peer_id.as_u64() as usize,
|
peer_id.as_u64() as usize,
|
||||||
if is_followed {
|
if is_followed {
|
||||||
format!("Unfollow {}", peer_github_login)
|
format!("Unfollow {}", user.github_login)
|
||||||
} else {
|
} else {
|
||||||
format!("Follow {}", peer_github_login)
|
format!("Follow {}", user.github_login)
|
||||||
},
|
},
|
||||||
Some(Box::new(FollowNextCollaborator)),
|
Some(Box::new(FollowNextCollaborator)),
|
||||||
theme.tooltip.clone(),
|
theme.tooltip.clone(),
|
||||||
|
@ -654,7 +680,7 @@ impl CollabTitlebarItem {
|
||||||
})
|
})
|
||||||
.with_tooltip::<JoinProject, _>(
|
.with_tooltip::<JoinProject, _>(
|
||||||
peer_id.as_u64() as usize,
|
peer_id.as_u64() as usize,
|
||||||
format!("Follow {} into external project", peer_github_login),
|
format!("Follow {} into external project", user.github_login),
|
||||||
Some(Box::new(FollowNextCollaborator)),
|
Some(Box::new(FollowNextCollaborator)),
|
||||||
theme.tooltip.clone(),
|
theme.tooltip.clone(),
|
||||||
cx,
|
cx,
|
||||||
|
@ -668,6 +694,15 @@ impl CollabTitlebarItem {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn render_face(avatar: Arc<ImageData>, avatar_style: ImageStyle, theme: &Theme) -> ElementBox {
|
||||||
|
Image::new(avatar)
|
||||||
|
.with_style(avatar_style)
|
||||||
|
.constrained()
|
||||||
|
.with_width(theme.workspace.titlebar.avatar_width)
|
||||||
|
.aligned()
|
||||||
|
.boxed()
|
||||||
|
}
|
||||||
|
|
||||||
fn render_connection_status(
|
fn render_connection_status(
|
||||||
&self,
|
&self,
|
||||||
workspace: &ViewHandle<Workspace>,
|
workspace: &ViewHandle<Workspace>,
|
||||||
|
|
|
@ -837,7 +837,7 @@ impl Workspace {
|
||||||
&self.project
|
&self.project
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn client(&self) -> &Arc<Client> {
|
pub fn client(&self) -> &Client {
|
||||||
&self.client
|
&self.client
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue