Use a different style for inactive participants

This commit is contained in:
Antonio Scandurra 2022-10-04 14:50:41 +02:00
parent 456dde200c
commit de917c4678
5 changed files with 82 additions and 35 deletions

View file

@ -20,6 +20,7 @@ impl ParticipantLocation {
} }
} }
#[derive(Clone)]
pub struct RemoteParticipant { pub struct RemoteParticipant {
pub user: Arc<User>, pub user: Arc<User>,
pub project_ids: Vec<u64>, pub project_ids: Vec<u64>,

View file

@ -1,4 +1,5 @@
use crate::contacts_popover; use crate::contacts_popover;
use call::{ActiveCall, ParticipantLocation};
use client::{Authenticate, PeerId}; use client::{Authenticate, PeerId};
use clock::ReplicaId; use clock::ReplicaId;
use contacts_popover::ContactsPopover; use contacts_popover::ContactsPopover;
@ -25,6 +26,7 @@ pub fn init(cx: &mut MutableAppContext) {
pub struct CollabTitlebarItem { pub struct CollabTitlebarItem {
workspace: WeakViewHandle<Workspace>, workspace: WeakViewHandle<Workspace>,
contacts_popover: Option<ViewHandle<ContactsPopover>>, contacts_popover: Option<ViewHandle<ContactsPopover>>,
room_subscription: Option<Subscription>,
_subscriptions: Vec<Subscription>, _subscriptions: Vec<Subscription>,
} }
@ -56,12 +58,27 @@ impl View for CollabTitlebarItem {
impl CollabTitlebarItem { impl CollabTitlebarItem {
pub fn new(workspace: &ViewHandle<Workspace>, cx: &mut ViewContext<Self>) -> Self { pub fn new(workspace: &ViewHandle<Workspace>, cx: &mut ViewContext<Self>) -> Self {
let observe_workspace = cx.observe(workspace, |_, _, cx| cx.notify()); let active_call = ActiveCall::global(cx);
Self { let mut subscriptions = Vec::new();
subscriptions.push(cx.observe(workspace, |_, _, cx| cx.notify()));
subscriptions.push(cx.observe(&active_call, |this, _, cx| this.active_call_changed(cx)));
let mut this = Self {
workspace: workspace.downgrade(), workspace: workspace.downgrade(),
contacts_popover: None, contacts_popover: None,
_subscriptions: vec![observe_workspace], room_subscription: None,
_subscriptions: subscriptions,
};
this.active_call_changed(cx);
this
}
fn active_call_changed(&mut self, cx: &mut ViewContext<Self>) {
if let Some(room) = ActiveCall::global(cx).read(cx).room().cloned() {
self.room_subscription = Some(cx.observe(&room, |_, _, cx| cx.notify()));
} else {
self.room_subscription = None;
} }
cx.notify();
} }
fn toggle_contacts_popover(&mut self, _: &ToggleContactsPopover, cx: &mut ViewContext<Self>) { fn toggle_contacts_popover(&mut self, _: &ToggleContactsPopover, cx: &mut ViewContext<Self>) {
@ -151,28 +168,40 @@ impl CollabTitlebarItem {
theme: &Theme, theme: &Theme,
cx: &mut RenderContext<Self>, cx: &mut RenderContext<Self>,
) -> Vec<ElementBox> { ) -> Vec<ElementBox> {
let mut collaborators = workspace let active_call = ActiveCall::global(cx);
.read(cx) if let Some(room) = active_call.read(cx).room().cloned() {
.project() let project = workspace.read(cx).project().read(cx);
.read(cx) let project_id = project.remote_id();
.collaborators() let mut collaborators = project
.values() .collaborators()
.cloned() .values()
.collect::<Vec<_>>(); .cloned()
collaborators.sort_unstable_by_key(|collaborator| collaborator.replica_id); .collect::<Vec<_>>();
collaborators collaborators.sort_by_key(|collaborator| collaborator.replica_id);
.into_iter() collaborators
.filter_map(|collaborator| { .into_iter()
Some(self.render_avatar( .filter_map(|collaborator| {
collaborator.user.avatar.clone()?, let participant = room
collaborator.replica_id, .read(cx)
Some((collaborator.peer_id, &collaborator.user.github_login)), .remote_participants()
workspace, .get(&collaborator.peer_id)?;
theme, let is_active = project_id.map_or(false, |project_id| {
cx, participant.location == ParticipantLocation::Project { project_id }
)) });
}) Some(self.render_avatar(
.collect() collaborator.user.avatar.clone()?,
collaborator.replica_id,
Some((collaborator.peer_id, &collaborator.user.github_login)),
is_active,
workspace,
theme,
cx,
))
})
.collect()
} else {
Default::default()
}
} }
fn render_current_user( fn render_current_user(
@ -185,7 +214,7 @@ impl CollabTitlebarItem {
let replica_id = workspace.read(cx).project().read(cx).replica_id(); let replica_id = workspace.read(cx).project().read(cx).replica_id();
let status = *workspace.read(cx).client().status().borrow(); let status = *workspace.read(cx).client().status().borrow();
if let Some(avatar) = user.and_then(|user| user.avatar.clone()) { if let Some(avatar) = user.and_then(|user| user.avatar.clone()) {
Some(self.render_avatar(avatar, replica_id, None, workspace, theme, cx)) Some(self.render_avatar(avatar, replica_id, None, true, workspace, theme, cx))
} else if matches!(status, client::Status::UpgradeRequired) { } else if matches!(status, client::Status::UpgradeRequired) {
None None
} else { } else {
@ -214,6 +243,7 @@ impl CollabTitlebarItem {
avatar: Arc<ImageData>, avatar: Arc<ImageData>,
replica_id: ReplicaId, replica_id: ReplicaId,
peer: Option<(PeerId, &str)>, peer: Option<(PeerId, &str)>,
is_active: bool,
workspace: &ViewHandle<Workspace>, workspace: &ViewHandle<Workspace>,
theme: &Theme, theme: &Theme,
cx: &mut RenderContext<Self>, cx: &mut RenderContext<Self>,
@ -222,10 +252,18 @@ impl CollabTitlebarItem {
let is_followed = peer.map_or(false, |(peer_id, _)| { let is_followed = peer.map_or(false, |(peer_id, _)| {
workspace.read(cx).is_following(peer_id) workspace.read(cx).is_following(peer_id)
}); });
let mut avatar_style = theme.workspace.titlebar.avatar; let mut avatar_style;
if is_active {
avatar_style = theme.workspace.titlebar.avatar;
} else {
avatar_style = theme.workspace.titlebar.inactive_avatar;
}
if is_followed { if is_followed {
avatar_style.border = Border::all(1.0, replica_color); avatar_style.border = Border::all(1.0, replica_color);
} }
let content = Stack::new() let content = Stack::new()
.with_child( .with_child(
Image::new(avatar) Image::new(avatar)

View file

@ -159,14 +159,7 @@ impl ContactsPopover {
let active_call = ActiveCall::global(cx); let active_call = ActiveCall::global(cx);
let mut subscriptions = Vec::new(); let mut subscriptions = Vec::new();
subscriptions.push(cx.observe(&user_store, |this, _, cx| this.update_entries(cx))); subscriptions.push(cx.observe(&user_store, |this, _, cx| this.update_entries(cx)));
subscriptions.push(cx.observe(&active_call, |this, active_call, cx| { subscriptions.push(cx.observe(&active_call, |this, _, cx| this.active_call_changed(cx)));
if let Some(room) = active_call.read(cx).room().cloned() {
this.room_subscription = Some(cx.observe(&room, |_, _, cx| cx.notify()));
} else {
this.room_subscription = None;
}
cx.notify();
}));
let mut this = Self { let mut this = Self {
room_subscription: None, room_subscription: None,
@ -180,9 +173,19 @@ impl ContactsPopover {
user_store, user_store,
}; };
this.update_entries(cx); this.update_entries(cx);
this.active_call_changed(cx);
this this
} }
fn active_call_changed(&mut self, cx: &mut ViewContext<Self>) {
if let Some(room) = ActiveCall::global(cx).read(cx).room().cloned() {
self.room_subscription = Some(cx.observe(&room, |_, _, cx| cx.notify()));
} else {
self.room_subscription = None;
}
cx.notify();
}
fn clear_filter(&mut self, _: &Cancel, cx: &mut ViewContext<Self>) { fn clear_filter(&mut self, _: &Cancel, cx: &mut ViewContext<Self>) {
let did_clear = self.filter_editor.update(cx, |editor, cx| { let did_clear = self.filter_editor.update(cx, |editor, cx| {
if editor.buffer().read(cx).len(cx) > 0 { if editor.buffer().read(cx).len(cx) > 0 {

View file

@ -71,6 +71,7 @@ pub struct Titlebar {
pub avatar_ribbon: AvatarRibbon, pub avatar_ribbon: AvatarRibbon,
pub offline_icon: OfflineIcon, pub offline_icon: OfflineIcon,
pub avatar: ImageStyle, pub avatar: ImageStyle,
pub inactive_avatar: ImageStyle,
pub sign_in_prompt: Interactive<ContainedText>, pub sign_in_prompt: Interactive<ContainedText>,
pub outdated_warning: ContainedText, pub outdated_warning: ContainedText,
pub toggle_contacts_button: Interactive<IconButton>, pub toggle_contacts_button: Interactive<IconButton>,

View file

@ -69,6 +69,10 @@ export default function workspace(theme: Theme) {
width: 1, width: 1,
}, },
}, },
inactiveAvatar: {
cornerRadius: 10,
opacity: 0.65,
},
avatarRibbon: { avatarRibbon: {
height: 3, height: 3,
width: 12, width: 12,