channel projects (#8456)

Add plumbing for hosted projects. This will currently show them if they
exist
but provides no UX to create/rename/delete them.

Also changed the `ChannelId` type to not auto-cast to u64; this avoids
type
confusion if you have multiple id types.


Release Notes:

- N/A
This commit is contained in:
Conrad Irwin 2024-02-26 22:15:11 -07:00 committed by GitHub
parent 8cf36ae603
commit c31626717f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
37 changed files with 446 additions and 144 deletions

View file

@ -7,8 +7,8 @@ use crate::{
CollaborationPanelSettings,
};
use call::ActiveCall;
use channel::{Channel, ChannelEvent, ChannelId, ChannelStore};
use client::{Client, Contact, User, UserStore};
use channel::{Channel, ChannelEvent, ChannelStore, HostedProjectId};
use client::{ChannelId, Client, Contact, User, UserStore};
use contact_finder::ContactFinder;
use db::kvp::KEY_VALUE_STORE;
use editor::{Editor, EditorElement, EditorStyle};
@ -184,6 +184,10 @@ enum ListEntry {
ChannelEditor {
depth: usize,
},
HostedProject {
id: HostedProjectId,
name: SharedString,
},
Contact {
contact: Arc<Contact>,
calling: bool,
@ -326,7 +330,10 @@ impl CollabPanel {
panel.width = serialized_panel.width;
panel.collapsed_channels = serialized_panel
.collapsed_channels
.unwrap_or_else(|| Vec::new());
.unwrap_or_else(|| Vec::new())
.iter()
.map(|cid| ChannelId(*cid))
.collect();
cx.notify();
});
}
@ -344,7 +351,9 @@ impl CollabPanel {
COLLABORATION_PANEL_KEY.into(),
serde_json::to_string(&SerializedCollabPanel {
width,
collapsed_channels: Some(collapsed_channels),
collapsed_channels: Some(
collapsed_channels.iter().map(|cid| cid.0).collect(),
),
})?,
)
.await?;
@ -563,6 +572,7 @@ impl CollabPanel {
}
}
let hosted_projects = channel_store.projects_for_id(channel.id);
let has_children = channel_store
.channel_at_index(mat.candidate_id + 1)
.map_or(false, |next_channel| {
@ -596,6 +606,10 @@ impl CollabPanel {
});
}
}
for (name, id) in hosted_projects {
self.entries.push(ListEntry::HostedProject { id, name })
}
}
}
@ -1023,6 +1037,33 @@ impl CollabPanel {
.tooltip(move |cx| Tooltip::text("Open Chat", cx))
}
fn render_channel_project(
&self,
id: HostedProjectId,
name: &SharedString,
is_selected: bool,
cx: &mut ViewContext<Self>,
) -> impl IntoElement {
ListItem::new(ElementId::NamedInteger(
"channel-project".into(),
id.0 as usize,
))
.indent_level(2)
.indent_step_size(px(20.))
.selected(is_selected)
.on_click(cx.listener(move |_this, _, _cx| {
// todo!()
}))
.start_slot(
h_flex()
.relative()
.gap_1()
.child(IconButton::new(0, IconName::FileTree)),
)
.child(Label::new(name.clone()))
.tooltip(move |cx| Tooltip::text("Open Project", cx))
}
fn has_subchannels(&self, ix: usize) -> bool {
self.entries.get(ix).map_or(false, |entry| {
if let ListEntry::Channel { has_children, .. } = entry {
@ -1486,6 +1527,12 @@ impl CollabPanel {
ListEntry::ChannelChat { channel_id } => {
self.join_channel_chat(*channel_id, cx)
}
ListEntry::HostedProject {
id: _id,
name: _name,
} => {
// todo!()
}
ListEntry::OutgoingRequest(_) => {}
ListEntry::ChannelEditor { .. } => {}
@ -1923,7 +1970,7 @@ impl CollabPanel {
fn respond_to_channel_invite(
&mut self,
channel_id: u64,
channel_id: ChannelId,
accept: bool,
cx: &mut ViewContext<Self>,
) {
@ -1942,7 +1989,7 @@ impl CollabPanel {
.detach_and_prompt_err("Call failed", cx, |_, _| None);
}
fn join_channel(&self, channel_id: u64, cx: &mut ViewContext<Self>) {
fn join_channel(&self, channel_id: ChannelId, cx: &mut ViewContext<Self>) {
let Some(workspace) = self.workspace.upgrade() else {
return;
};
@ -2089,6 +2136,10 @@ impl CollabPanel {
ListEntry::ChannelChat { channel_id } => self
.render_channel_chat(*channel_id, is_selected, cx)
.into_any_element(),
ListEntry::HostedProject { id, name } => self
.render_channel_project(*id, name, is_selected, cx)
.into_any_element(),
}
}
@ -2405,7 +2456,7 @@ impl CollabPanel {
.tooltip(|cx| Tooltip::text("Accept invite", cx)),
];
ListItem::new(("channel-invite", channel.id as usize))
ListItem::new(("channel-invite", channel.id.0 as usize))
.selected(is_selected)
.child(
h_flex()
@ -2497,7 +2548,7 @@ impl CollabPanel {
div()
.h_6()
.id(channel_id as usize)
.id(channel_id.0 as usize)
.group("")
.flex()
.w_full()
@ -2525,7 +2576,7 @@ impl CollabPanel {
this.move_channel(dragged_channel.id, channel_id, cx);
}))
.child(
ListItem::new(channel_id as usize)
ListItem::new(channel_id.0 as usize)
// Add one level of depth for the disclosure arrow.
.indent_level(depth + 1)
.indent_step_size(px(20.))
@ -2572,7 +2623,7 @@ impl CollabPanel {
)
.child(
h_flex()
.id(channel_id as usize)
.id(channel_id.0 as usize)
.child(Label::new(channel.name.clone()))
.children(face_pile.map(|face_pile| face_pile.p_1())),
),
@ -2826,6 +2877,11 @@ impl PartialEq for ListEntry {
return channel_1.id == channel_2.id;
}
}
ListEntry::HostedProject { id, .. } => {
if let ListEntry::HostedProject { id: other_id, .. } = other {
return id == other_id;
}
}
ListEntry::ChannelNotes { channel_id } => {
if let ListEntry::ChannelNotes {
channel_id: other_id,