Show guests in fewer places
This commit is contained in:
parent
c3402024bc
commit
1930258d39
7 changed files with 100 additions and 26 deletions
|
@ -43,6 +43,7 @@ pub struct LocalParticipant {
|
|||
pub struct RemoteParticipant {
|
||||
pub user: Arc<User>,
|
||||
pub peer_id: proto::PeerId,
|
||||
pub role: proto::ChannelRole,
|
||||
pub projects: Vec<proto::ParticipantProject>,
|
||||
pub location: ParticipantLocation,
|
||||
pub participant_index: ParticipantIndex,
|
||||
|
|
|
@ -610,6 +610,12 @@ impl Room {
|
|||
.find(|p| p.peer_id == peer_id)
|
||||
}
|
||||
|
||||
pub fn role_for_user(&self, user_id: u64) -> Option<proto::ChannelRole> {
|
||||
self.remote_participants
|
||||
.get(&user_id)
|
||||
.map(|participant| participant.role)
|
||||
}
|
||||
|
||||
pub fn pending_participants(&self) -> &[Arc<User>] {
|
||||
&self.pending_participants
|
||||
}
|
||||
|
@ -784,6 +790,7 @@ impl Room {
|
|||
});
|
||||
}
|
||||
|
||||
let role = participant.role();
|
||||
let location = ParticipantLocation::from_proto(participant.location)
|
||||
.unwrap_or(ParticipantLocation::External);
|
||||
if let Some(remote_participant) =
|
||||
|
@ -792,8 +799,11 @@ impl Room {
|
|||
remote_participant.peer_id = peer_id;
|
||||
remote_participant.projects = participant.projects;
|
||||
remote_participant.participant_index = participant_index;
|
||||
if location != remote_participant.location {
|
||||
if location != remote_participant.location
|
||||
|| role != remote_participant.role
|
||||
{
|
||||
remote_participant.location = location;
|
||||
remote_participant.role = role;
|
||||
cx.emit(Event::ParticipantLocationChanged {
|
||||
participant_id: peer_id,
|
||||
});
|
||||
|
@ -807,6 +817,7 @@ impl Room {
|
|||
peer_id,
|
||||
projects: participant.projects,
|
||||
location,
|
||||
role,
|
||||
muted: true,
|
||||
speaking: false,
|
||||
video_tracks: Default::default(),
|
||||
|
@ -1251,9 +1262,9 @@ impl Room {
|
|||
.unwrap_or(false)
|
||||
}
|
||||
|
||||
pub fn can_publish(&self) -> bool {
|
||||
self.local_participant().role == proto::ChannelRole::Member
|
||||
|| self.local_participant().role == proto::ChannelRole::Admin
|
||||
pub fn read_only(&self) -> bool {
|
||||
!(self.local_participant().role == proto::ChannelRole::Member
|
||||
|| self.local_participant().role == proto::ChannelRole::Admin)
|
||||
}
|
||||
|
||||
pub fn is_speaking(&self) -> bool {
|
||||
|
|
|
@ -7,8 +7,8 @@ use workspace::Workspace;
|
|||
#[gpui::test]
|
||||
async fn test_channel_guests(
|
||||
executor: BackgroundExecutor,
|
||||
mut cx_a: &mut TestAppContext,
|
||||
mut cx_b: &mut TestAppContext,
|
||||
cx_a: &mut TestAppContext,
|
||||
cx_b: &mut TestAppContext,
|
||||
) {
|
||||
let mut server = TestServer::start(executor.clone()).await;
|
||||
let client_a = server.create_client(cx_a, "user_a").await;
|
||||
|
@ -37,15 +37,13 @@ async fn test_channel_guests(
|
|||
.await;
|
||||
|
||||
let active_call_a = cx_a.read(ActiveCall::global);
|
||||
let active_call_b = cx_b.read(ActiveCall::global);
|
||||
|
||||
// Client A shares a project in the channel
|
||||
active_call_a
|
||||
.update(cx_a, |call, cx| call.join_channel(channel_id, cx))
|
||||
.await
|
||||
.unwrap();
|
||||
let (project_a, worktree_id) = client_a.build_local_project("/a", cx_a).await;
|
||||
let worktree_a = project_a.read_with(cx_a, |project, _| project.worktrees().next().unwrap());
|
||||
let (project_a, _) = client_a.build_local_project("/a", cx_a).await;
|
||||
let project_id = active_call_a
|
||||
.update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
|
||||
.await
|
||||
|
|
|
@ -172,7 +172,7 @@ impl ChannelView {
|
|||
cx.notify();
|
||||
}),
|
||||
ChannelBufferEvent::ChannelChanged => {
|
||||
self.editor.update(cx, |editor, cx| {
|
||||
self.editor.update(cx, |_, cx| {
|
||||
cx.emit(editor::EditorEvent::TitleChanged);
|
||||
cx.notify()
|
||||
});
|
||||
|
|
|
@ -151,6 +151,9 @@ enum ListEntry {
|
|||
peer_id: Option<PeerId>,
|
||||
is_last: bool,
|
||||
},
|
||||
GuestCount {
|
||||
count: usize,
|
||||
},
|
||||
IncomingRequest(Arc<User>),
|
||||
OutgoingRequest(Arc<User>),
|
||||
ChannelInvite(Arc<Channel>),
|
||||
|
@ -380,10 +383,13 @@ impl CollabPanel {
|
|||
|
||||
if !self.collapsed_sections.contains(&Section::ActiveCall) {
|
||||
let room = room.read(cx);
|
||||
let mut guest_count_ix = 0;
|
||||
let mut guest_count = if room.read_only() { 1 } else { 0 };
|
||||
|
||||
if let Some(channel_id) = room.channel_id() {
|
||||
self.entries.push(ListEntry::ChannelNotes { channel_id });
|
||||
self.entries.push(ListEntry::ChannelChat { channel_id })
|
||||
self.entries.push(ListEntry::ChannelChat { channel_id });
|
||||
guest_count_ix = self.entries.len();
|
||||
}
|
||||
|
||||
// Populate the active user.
|
||||
|
@ -402,7 +408,7 @@ impl CollabPanel {
|
|||
&Default::default(),
|
||||
executor.clone(),
|
||||
));
|
||||
if !matches.is_empty() {
|
||||
if !matches.is_empty() && !room.read_only() {
|
||||
let user_id = user.id;
|
||||
self.entries.push(ListEntry::CallParticipant {
|
||||
user,
|
||||
|
@ -430,13 +436,21 @@ impl CollabPanel {
|
|||
// Populate remote participants.
|
||||
self.match_candidates.clear();
|
||||
self.match_candidates
|
||||
.extend(room.remote_participants().iter().map(|(_, participant)| {
|
||||
StringMatchCandidate {
|
||||
id: participant.user.id as usize,
|
||||
string: participant.user.github_login.clone(),
|
||||
char_bag: participant.user.github_login.chars().collect(),
|
||||
}
|
||||
}));
|
||||
.extend(
|
||||
room.remote_participants()
|
||||
.iter()
|
||||
.filter_map(|(_, participant)| {
|
||||
if participant.role == proto::ChannelRole::Guest {
|
||||
guest_count += 1;
|
||||
return None;
|
||||
}
|
||||
Some(StringMatchCandidate {
|
||||
id: participant.user.id as usize,
|
||||
string: participant.user.github_login.clone(),
|
||||
char_bag: participant.user.github_login.chars().collect(),
|
||||
})
|
||||
}),
|
||||
);
|
||||
let matches = executor.block(match_strings(
|
||||
&self.match_candidates,
|
||||
&query,
|
||||
|
@ -470,6 +484,10 @@ impl CollabPanel {
|
|||
});
|
||||
}
|
||||
}
|
||||
if guest_count > 0 {
|
||||
self.entries
|
||||
.insert(guest_count_ix, ListEntry::GuestCount { count: guest_count });
|
||||
}
|
||||
|
||||
// Populate pending participants.
|
||||
self.match_candidates.clear();
|
||||
|
@ -959,6 +977,34 @@ impl CollabPanel {
|
|||
.tooltip(move |cx| Tooltip::text("Open Chat", cx))
|
||||
}
|
||||
|
||||
fn render_guest_count(
|
||||
&self,
|
||||
count: usize,
|
||||
is_selected: bool,
|
||||
cx: &mut ViewContext<Self>,
|
||||
) -> impl IntoElement {
|
||||
// TODO! disable manage_members for guests.
|
||||
ListItem::new("guest_count")
|
||||
.selected(is_selected)
|
||||
.on_click(cx.listener(move |this, _, cx| {
|
||||
if let Some(channel_id) = ActiveCall::global(cx).read(cx).channel_id(cx) {
|
||||
this.manage_members(channel_id, cx)
|
||||
}
|
||||
}))
|
||||
.start_slot(
|
||||
h_stack()
|
||||
.gap_1()
|
||||
.child(render_tree_branch(false, cx))
|
||||
.child(""),
|
||||
)
|
||||
.child(Label::new(if count == 1 {
|
||||
format!("{} guest", count)
|
||||
} else {
|
||||
format!("{} guests", count)
|
||||
}))
|
||||
.tooltip(move |cx| Tooltip::text("Manage Members", cx))
|
||||
}
|
||||
|
||||
fn has_subchannels(&self, ix: usize) -> bool {
|
||||
self.entries.get(ix).map_or(false, |entry| {
|
||||
if let ListEntry::Channel { has_children, .. } = entry {
|
||||
|
@ -1180,6 +1226,11 @@ impl CollabPanel {
|
|||
});
|
||||
}
|
||||
}
|
||||
ListEntry::GuestCount { .. } => {
|
||||
if let Some(channel_id) = ActiveCall::global(cx).read(cx).channel_id(cx) {
|
||||
self.manage_members(channel_id, cx)
|
||||
}
|
||||
}
|
||||
ListEntry::Channel { channel, .. } => {
|
||||
let is_active = maybe!({
|
||||
let call_channel = ActiveCall::global(cx)
|
||||
|
@ -1735,6 +1786,9 @@ impl CollabPanel {
|
|||
ListEntry::ParticipantScreen { peer_id, is_last } => self
|
||||
.render_participant_screen(*peer_id, *is_last, is_selected, cx)
|
||||
.into_any_element(),
|
||||
ListEntry::GuestCount { count } => self
|
||||
.render_guest_count(*count, is_selected, cx)
|
||||
.into_any_element(),
|
||||
ListEntry::ChannelNotes { channel_id } => self
|
||||
.render_channel_notes(*channel_id, is_selected, cx)
|
||||
.into_any_element(),
|
||||
|
@ -2504,6 +2558,11 @@ impl PartialEq for ListEntry {
|
|||
return true;
|
||||
}
|
||||
}
|
||||
ListEntry::GuestCount { .. } => {
|
||||
if let ListEntry::GuestCount { .. } = other {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ use gpui::{
|
|||
};
|
||||
use project::{Project, RepositoryEntry};
|
||||
use recent_projects::RecentProjects;
|
||||
use rpc::proto;
|
||||
use std::sync::Arc;
|
||||
use theme::{ActiveTheme, PlayerColors};
|
||||
use ui::{
|
||||
|
@ -173,9 +174,9 @@ impl Render for CollabTitlebarItem {
|
|||
let is_muted = room.is_muted(cx);
|
||||
let is_deafened = room.is_deafened().unwrap_or(false);
|
||||
let is_screen_sharing = room.is_screen_sharing();
|
||||
let can_publish = room.can_publish();
|
||||
let read_only = room.read_only();
|
||||
|
||||
this.when(is_local && can_publish, |this| {
|
||||
this.when(is_local && !read_only, |this| {
|
||||
this.child(
|
||||
Button::new(
|
||||
"toggle_sharing",
|
||||
|
@ -204,7 +205,7 @@ impl Render for CollabTitlebarItem {
|
|||
.detach_and_log_err(cx);
|
||||
}),
|
||||
)
|
||||
.when(can_publish, |this| {
|
||||
.when(!read_only, |this| {
|
||||
this.child(
|
||||
IconButton::new(
|
||||
"mute-microphone",
|
||||
|
@ -233,7 +234,7 @@ impl Render for CollabTitlebarItem {
|
|||
.icon_size(IconSize::Small)
|
||||
.selected(is_deafened)
|
||||
.tooltip(move |cx| {
|
||||
if can_publish {
|
||||
if !read_only {
|
||||
Tooltip::with_meta(
|
||||
"Deafen Audio",
|
||||
None,
|
||||
|
@ -246,7 +247,7 @@ impl Render for CollabTitlebarItem {
|
|||
})
|
||||
.on_click(move |_, cx| crate::toggle_deafen(&Default::default(), cx)),
|
||||
)
|
||||
.when(can_publish, |this| {
|
||||
.when(!read_only, |this| {
|
||||
this.child(
|
||||
IconButton::new("screen-share", ui::Icon::Screen)
|
||||
.style(ButtonStyle::Subtle)
|
||||
|
@ -420,6 +421,10 @@ impl CollabTitlebarItem {
|
|||
project_id: Option<u64>,
|
||||
current_user: &Arc<User>,
|
||||
) -> Option<FacePile> {
|
||||
if room.role_for_user(user.id) == Some(proto::ChannelRole::Guest) {
|
||||
return None;
|
||||
}
|
||||
|
||||
let followers = project_id.map_or(&[] as &[_], |id| room.followers_for(peer_id, id));
|
||||
|
||||
let pile = FacePile::default()
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use gpui::{hsla, Hsla};
|
||||
use gpui::Hsla;
|
||||
use serde_derive::Deserialize;
|
||||
|
||||
use crate::{amber, blue, gray, jade, lime, orange, pink, purple, red};
|
||||
use crate::{amber, blue, jade, lime, orange, pink, purple, red};
|
||||
|
||||
#[derive(Debug, Clone, Copy, Deserialize, Default)]
|
||||
pub struct PlayerColor {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue