update sidebar for public channels

This commit is contained in:
Conrad Irwin 2023-10-17 13:19:22 -06:00
parent 8db389313b
commit 1c5e07f4a2
4 changed files with 208 additions and 50 deletions

View File

@ -1,3 +1,3 @@
<svg width="15" height="15" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M4.82479 2.32196C4.54958 2.29922 4.30805 2.50389 4.28531 2.77909C4.26257 3.0543 4.46724 3.29583 4.74244 3.31857C8.43309 3.62351 11.3765 6.56695 11.6815 10.2576C11.7042 10.5328 11.9457 10.7375 12.221 10.7147C12.4962 10.692 12.7008 10.4505 12.6781 10.1753C12.3329 5.99733 9.00272 2.66717 4.82479 2.32196ZM4.15624 5.5614C4.21065 5.29067 4.47423 5.11531 4.74496 5.16971C7.30267 5.68372 9.31629 7.69734 9.8303 10.2551C9.88471 10.5258 9.70934 10.7894 9.43862 10.8438C9.16789 10.8982 8.90431 10.7228 8.8499 10.4521C8.4153 8.28949 6.71052 6.58472 4.54793 6.15011C4.2772 6.09571 4.10184 5.83213 4.15624 5.5614ZM3.35472 8.41645C3.40912 8.14572 3.6727 7.97035 3.94343 8.02476C5.46858 8.33126 6.6688 9.53148 6.9753 11.0566C7.02971 11.3274 6.85434 11.5909 6.58361 11.6453C6.31288 11.6998 6.04931 11.5244 5.9949 11.2537C5.7678 10.1236 4.87643 9.23225 3.7464 9.00516C3.47567 8.95075 3.30031 8.68718 3.35472 8.41645Z" fill="black"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M3.74393 2.00204C3.41963 1.97524 3.13502 2.37572 3.10823 2.70001C3.08143 3.0243 3.32558 3.47321 3.64986 3.50001C7.99878 3.85934 11.1406 7.00122 11.5 11.3501C11.5267 11.6744 11.9756 12.0269 12.3 12C12.6243 11.9733 13.0247 11.5804 12.998 11.2561C12.5912 6.33295 8.66704 2.40882 3.74393 2.00204ZM2.9 6.00001C2.96411 5.68099 3.33084 5.29361 3.64986 5.35772C6.66377 5.96341 9.03654 8.33618 9.64223 11.3501C9.70634 11.6691 9.319 12.0359 8.99999 12.1C8.68097 12.1641 8.06411 11.819 7.99999 11.5C7.48788 8.95167 6.0483 7.51213 3.49999 7.00001C3.18097 6.9359 2.8359 6.31902 2.9 6.00001ZM2 9.20001C2.0641 8.88099 2.38635 8.65788 2.70537 8.722C4.50255 9.08317 5.91684 10.4975 6.27801 12.2946C6.34212 12.6137 6.13547 12.9242 5.81646 12.9883C5.49744 13.0525 4.86411 12.819 4.8 12.5C4.53239 11.1683 3.83158 10.4676 2.5 10.2C2.18098 10.1359 1.93588 9.51902 2 9.20001Z" fill="black"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1021 B

View File

@ -44,7 +44,7 @@ CREATE UNIQUE INDEX "index_rooms_on_channel_id" ON "rooms" ("channel_id");
CREATE TABLE "projects" (
"id" INTEGER PRIMARY KEY AUTOINCREMENT,
"room_id" INTEGER REFERENCES rooms (id) NOT NULL,
"room_id" INTEGER REFERENCES rooms (id) ON DELETE CASCADE NOT NULL,
"host_user_id" INTEGER REFERENCES users (id) NOT NULL,
"host_connection_id" INTEGER,
"host_connection_server_id" INTEGER REFERENCES servers (id) ON DELETE CASCADE,

View File

@ -0,0 +1,8 @@
-- Add migration script here
ALTER TABLE projects
DROP CONSTRAINT projects_room_id_fkey,
ADD CONSTRAINT projects_room_id_fkey
FOREIGN KEY (room_id)
REFERENCES rooms (id)
ON DELETE CASCADE;

View File

@ -11,7 +11,10 @@ use anyhow::Result;
use call::ActiveCall;
use channel::{Channel, ChannelData, ChannelEvent, ChannelId, ChannelPath, ChannelStore};
use channel_modal::ChannelModal;
use client::{proto::PeerId, Client, Contact, User, UserStore};
use client::{
proto::{self, PeerId},
Client, Contact, User, UserStore,
};
use contact_finder::ContactFinder;
use context_menu::{ContextMenu, ContextMenuItem};
use db::kvp::KEY_VALUE_STORE;
@ -428,7 +431,7 @@ enum ListEntry {
is_last: bool,
},
ParticipantScreen {
peer_id: PeerId,
peer_id: Option<PeerId>,
is_last: bool,
},
IncomingRequest(Arc<User>),
@ -442,6 +445,9 @@ enum ListEntry {
ChannelNotes {
channel_id: ChannelId,
},
ChannelChat {
channel_id: ChannelId,
},
ChannelEditor {
depth: usize,
},
@ -602,6 +608,13 @@ impl CollabPanel {
ix,
cx,
),
ListEntry::ChannelChat { channel_id } => this.render_channel_chat(
*channel_id,
&theme.collab_panel,
is_selected,
ix,
cx,
),
ListEntry::ChannelInvite(channel) => Self::render_channel_invite(
channel.clone(),
this.channel_store.clone(),
@ -804,7 +817,8 @@ impl CollabPanel {
let room = room.read(cx);
if let Some(channel_id) = room.channel_id() {
self.entries.push(ListEntry::ChannelNotes { channel_id })
self.entries.push(ListEntry::ChannelNotes { channel_id });
self.entries.push(ListEntry::ChannelChat { channel_id })
}
// Populate the active user.
@ -836,7 +850,13 @@ impl CollabPanel {
project_id: project.id,
worktree_root_names: project.worktree_root_names.clone(),
host_user_id: user_id,
is_last: projects.peek().is_none(),
is_last: projects.peek().is_none() && !room.is_screen_sharing(),
});
}
if room.is_screen_sharing() {
self.entries.push(ListEntry::ParticipantScreen {
peer_id: None,
is_last: true,
});
}
}
@ -880,7 +900,7 @@ impl CollabPanel {
}
if !participant.video_tracks.is_empty() {
self.entries.push(ListEntry::ParticipantScreen {
peer_id: participant.peer_id,
peer_id: Some(participant.peer_id),
is_last: true,
});
}
@ -1225,14 +1245,18 @@ impl CollabPanel {
) -> AnyElement<Self> {
enum CallParticipant {}
enum CallParticipantTooltip {}
enum LeaveCallButton {}
enum LeaveCallTooltip {}
let collab_theme = &theme.collab_panel;
let is_current_user =
user_store.read(cx).current_user().map(|user| user.id) == Some(user.id);
let content =
MouseEventHandler::new::<CallParticipant, _>(user.id as usize, cx, |mouse_state, _| {
let content = MouseEventHandler::new::<CallParticipant, _>(
user.id as usize,
cx,
|mouse_state, cx| {
let style = if is_current_user {
*collab_theme
.contact_row
@ -1268,14 +1292,32 @@ impl CollabPanel {
Label::new("Calling", collab_theme.calling_indicator.text.clone())
.contained()
.with_style(collab_theme.calling_indicator.container)
.aligned(),
.aligned()
.into_any(),
)
} else if is_current_user {
Some(
Label::new("You", collab_theme.calling_indicator.text.clone())
.contained()
.with_style(collab_theme.calling_indicator.container)
.aligned(),
MouseEventHandler::new::<LeaveCallButton, _>(0, cx, |state, _| {
render_icon_button(
theme
.collab_panel
.leave_call_button
.style_for(is_selected, state),
"icons/exit.svg",
)
})
.with_cursor_style(CursorStyle::PointingHand)
.on_click(MouseButton::Left, |_, _, cx| {
Self::leave_call(cx);
})
.with_tooltip::<LeaveCallTooltip>(
0,
"Leave call",
None,
theme.tooltip.clone(),
cx,
)
.into_any(),
)
} else {
None
@ -1284,7 +1326,8 @@ impl CollabPanel {
.with_height(collab_theme.row_height)
.contained()
.with_style(style)
});
},
);
if is_current_user || is_pending || peer_id.is_none() {
return content.into_any();
@ -1406,7 +1449,7 @@ impl CollabPanel {
}
fn render_participant_screen(
peer_id: PeerId,
peer_id: Option<PeerId>,
is_last: bool,
is_selected: bool,
theme: &theme::CollabPanel,
@ -1421,8 +1464,8 @@ impl CollabPanel {
.unwrap_or(0.);
let tree_branch = theme.tree_branch;
MouseEventHandler::new::<OpenSharedScreen, _>(
peer_id.as_u64() as usize,
let handler = MouseEventHandler::new::<OpenSharedScreen, _>(
peer_id.map(|id| id.as_u64()).unwrap_or(0) as usize,
cx,
|mouse_state, cx| {
let tree_branch = *tree_branch.in_state(is_selected).style_for(mouse_state);
@ -1460,16 +1503,20 @@ impl CollabPanel {
.contained()
.with_style(row.container)
},
)
.with_cursor_style(CursorStyle::PointingHand)
.on_click(MouseButton::Left, move |_, this, cx| {
if let Some(workspace) = this.workspace.upgrade(cx) {
workspace.update(cx, |workspace, cx| {
workspace.open_shared_screen(peer_id, cx)
});
}
})
.into_any()
);
if peer_id.is_none() {
return handler.into_any();
}
handler
.with_cursor_style(CursorStyle::PointingHand)
.on_click(MouseButton::Left, move |_, this, cx| {
if let Some(workspace) = this.workspace.upgrade(cx) {
workspace.update(cx, |workspace, cx| {
workspace.open_shared_screen(peer_id.unwrap(), cx)
});
}
})
.into_any()
}
fn take_editing_state(&mut self, cx: &mut ViewContext<Self>) -> bool {
@ -1496,23 +1543,32 @@ impl CollabPanel {
enum AddChannel {}
let tooltip_style = &theme.tooltip;
let mut channel_link = None;
let mut channel_tooltip_text = None;
let mut channel_icon = None;
let text = match section {
Section::ActiveCall => {
let channel_name = iife!({
let channel_id = ActiveCall::global(cx).read(cx).channel_id(cx)?;
let name = self
.channel_store
.read(cx)
.channel_for_id(channel_id)?
.name
.as_str();
let channel = self.channel_store.read(cx).channel_for_id(channel_id)?;
Some(name)
channel_link = Some(channel.link());
(channel_icon, channel_tooltip_text) = match channel.visibility {
proto::ChannelVisibility::Public => {
(Some("icons/public.svg"), Some("Copy public channel link."))
}
proto::ChannelVisibility::Members => {
(Some("icons/hash.svg"), Some("Copy private channel link."))
}
};
Some(channel.name.as_str())
});
if let Some(name) = channel_name {
Cow::Owned(format!("#{}", name))
Cow::Owned(format!("{}", name))
} else {
Cow::Borrowed("Current Call")
}
@ -1527,28 +1583,30 @@ impl CollabPanel {
enum AddContact {}
let button = match section {
Section::ActiveCall => Some(
Section::ActiveCall => channel_link.map(|channel_link| {
let channel_link_copy = channel_link.clone();
MouseEventHandler::new::<AddContact, _>(0, cx, |state, _| {
render_icon_button(
theme
.collab_panel
.leave_call_button
.style_for(is_selected, state),
"icons/exit.svg",
"icons/link.svg",
)
})
.with_cursor_style(CursorStyle::PointingHand)
.on_click(MouseButton::Left, |_, _, cx| {
Self::leave_call(cx);
.on_click(MouseButton::Left, move |_, _, cx| {
let item = ClipboardItem::new(channel_link_copy.clone());
cx.write_to_clipboard(item)
})
.with_tooltip::<AddContact>(
0,
"Leave call",
channel_tooltip_text.unwrap(),
None,
tooltip_style.clone(),
cx,
),
),
)
}),
Section::Contacts => Some(
MouseEventHandler::new::<LeaveCallContactList, _>(0, cx, |state, _| {
render_icon_button(
@ -1633,6 +1691,21 @@ impl CollabPanel {
theme.collab_panel.contact_username.container.margin.left,
),
)
} else if let Some(channel_icon) = channel_icon {
Some(
Svg::new(channel_icon)
.with_color(header_style.text.color)
.constrained()
.with_max_width(icon_size)
.with_max_height(icon_size)
.aligned()
.constrained()
.with_width(icon_size)
.contained()
.with_margin_right(
theme.collab_panel.contact_username.container.margin.left,
),
)
} else {
None
})
@ -1908,6 +1981,12 @@ impl CollabPanel {
let channel_id = channel.id;
let collab_theme = &theme.collab_panel;
let has_children = self.channel_store.read(cx).has_children(channel_id);
let is_public = self
.channel_store
.read(cx)
.channel_for_id(channel_id)
.map(|channel| channel.visibility)
== Some(proto::ChannelVisibility::Public);
let other_selected =
self.selected_channel().map(|channel| channel.0.id) == Some(channel.id);
let disclosed = has_children.then(|| !self.collapsed_channels.binary_search(&path).is_ok());
@ -1965,12 +2044,16 @@ impl CollabPanel {
Flex::<Self>::row()
.with_child(
Svg::new("icons/hash.svg")
.with_color(collab_theme.channel_hash.color)
.constrained()
.with_width(collab_theme.channel_hash.width)
.aligned()
.left(),
Svg::new(if is_public {
"icons/public.svg"
} else {
"icons/hash.svg"
})
.with_color(collab_theme.channel_hash.color)
.constrained()
.with_width(collab_theme.channel_hash.width)
.aligned()
.left(),
)
.with_child({
let style = collab_theme.channel_name.inactive_state();
@ -2275,7 +2358,7 @@ impl CollabPanel {
.with_child(render_tree_branch(
tree_branch,
&row.name.text,
true,
false,
vec2f(host_avatar_width, theme.row_height),
cx.font_cache(),
))
@ -2308,6 +2391,62 @@ impl CollabPanel {
.into_any()
}
fn render_channel_chat(
&self,
channel_id: ChannelId,
theme: &theme::CollabPanel,
is_selected: bool,
ix: usize,
cx: &mut ViewContext<Self>,
) -> AnyElement<Self> {
enum ChannelChat {}
let host_avatar_width = theme
.contact_avatar
.width
.or(theme.contact_avatar.height)
.unwrap_or(0.);
MouseEventHandler::new::<ChannelChat, _>(ix as usize, cx, |state, cx| {
let tree_branch = *theme.tree_branch.in_state(is_selected).style_for(state);
let row = theme.project_row.in_state(is_selected).style_for(state);
Flex::<Self>::row()
.with_child(render_tree_branch(
tree_branch,
&row.name.text,
true,
vec2f(host_avatar_width, theme.row_height),
cx.font_cache(),
))
.with_child(
Svg::new("icons/conversations.svg")
.with_color(theme.channel_hash.color)
.constrained()
.with_width(theme.channel_hash.width)
.aligned()
.left(),
)
.with_child(
Label::new("chat", theme.channel_name.text.clone())
.contained()
.with_style(theme.channel_name.container)
.aligned()
.left()
.flex(1., true),
)
.constrained()
.with_height(theme.row_height)
.contained()
.with_style(*theme.channel_row.style_for(is_selected, state))
.with_padding_left(theme.channel_row.default_style().padding.left)
})
.on_click(MouseButton::Left, move |_, this, cx| {
this.join_channel_chat(&JoinChannelChat { channel_id }, cx);
})
.with_cursor_style(CursorStyle::PointingHand)
.into_any()
}
fn render_channel_invite(
channel: Arc<Channel>,
channel_store: ModelHandle<ChannelStore>,
@ -2771,6 +2910,9 @@ impl CollabPanel {
}
}
ListEntry::ParticipantScreen { peer_id, .. } => {
let Some(peer_id) = peer_id else {
return;
};
if let Some(workspace) = self.workspace.upgrade(cx) {
workspace.update(cx, |workspace, cx| {
workspace.open_shared_screen(*peer_id, cx)
@ -3498,6 +3640,14 @@ impl PartialEq for ListEntry {
return channel_id == other_id;
}
}
ListEntry::ChannelChat { channel_id } => {
if let ListEntry::ChannelChat {
channel_id: other_id,
} = other
{
return channel_id == other_id;
}
}
ListEntry::ChannelInvite(channel_1) => {
if let ListEntry::ChannelInvite(channel_2) = other {
return channel_1.id == channel_2.id;