Start work on displaying channels and invites in collab panel

This commit is contained in:
Max Brunsfeld 2023-07-31 18:00:14 -07:00
parent 003a711dea
commit 7954b02819
8 changed files with 412 additions and 70 deletions

View file

@ -6,18 +6,19 @@ use rpc::{proto, TypedEnvelope};
use std::sync::Arc;
pub struct ChannelStore {
channels: Vec<Channel>,
channel_invitations: Vec<Channel>,
channels: Vec<Arc<Channel>>,
channel_invitations: Vec<Arc<Channel>>,
client: Arc<Client>,
user_store: ModelHandle<UserStore>,
_rpc_subscription: Subscription,
}
#[derive(Debug, PartialEq)]
#[derive(Clone, Debug, PartialEq)]
pub struct Channel {
pub id: u64,
pub name: String,
pub parent_id: Option<u64>,
pub depth: usize,
}
impl Entity for ChannelStore {
@ -41,11 +42,11 @@ impl ChannelStore {
}
}
pub fn channels(&self) -> &[Channel] {
pub fn channels(&self) -> &[Arc<Channel>] {
&self.channels
}
pub fn channel_invitations(&self) -> &[Channel] {
pub fn channel_invitations(&self) -> &[Arc<Channel>] {
&self.channel_invitations
}
@ -97,6 +98,10 @@ impl ChannelStore {
}
}
pub fn is_channel_invite_pending(&self, channel: &Arc<Channel>) -> bool {
false
}
pub fn remove_member(
&self,
channel_id: u64,
@ -124,66 +129,74 @@ impl ChannelStore {
_: Arc<Client>,
mut cx: AsyncAppContext,
) -> Result<()> {
let payload = message.payload;
this.update(&mut cx, |this, cx| {
this.channels
.retain(|channel| !payload.remove_channels.contains(&channel.id));
this.channel_invitations
.retain(|channel| !payload.remove_channel_invitations.contains(&channel.id));
this.update_channels(message.payload, cx);
});
Ok(())
}
for channel in payload.channel_invitations {
if let Some(existing_channel) = this
.channel_invitations
.iter_mut()
.find(|c| c.id == channel.id)
{
existing_channel.name = channel.name;
continue;
pub(crate) fn update_channels(
&mut self,
payload: proto::UpdateChannels,
cx: &mut ModelContext<ChannelStore>,
) {
self.channels
.retain(|channel| !payload.remove_channels.contains(&channel.id));
self.channel_invitations
.retain(|channel| !payload.remove_channel_invitations.contains(&channel.id));
for channel in payload.channel_invitations {
if let Some(existing_channel) = self
.channel_invitations
.iter_mut()
.find(|c| c.id == channel.id)
{
Arc::make_mut(existing_channel).name = channel.name;
continue;
}
self.channel_invitations.insert(
0,
Arc::new(Channel {
id: channel.id,
name: channel.name,
parent_id: None,
depth: 0,
}),
);
}
for channel in payload.channels {
if let Some(existing_channel) = self.channels.iter_mut().find(|c| c.id == channel.id) {
Arc::make_mut(existing_channel).name = channel.name;
continue;
}
if let Some(parent_id) = channel.parent_id {
if let Some(ix) = self.channels.iter().position(|c| c.id == parent_id) {
let depth = self.channels[ix].depth + 1;
self.channels.insert(
ix + 1,
Arc::new(Channel {
id: channel.id,
name: channel.name,
parent_id: Some(parent_id),
depth,
}),
);
}
this.channel_invitations.insert(
} else {
self.channels.insert(
0,
Channel {
Arc::new(Channel {
id: channel.id,
name: channel.name,
parent_id: None,
},
depth: 0,
}),
);
}
for channel in payload.channels {
if let Some(existing_channel) =
this.channels.iter_mut().find(|c| c.id == channel.id)
{
existing_channel.name = channel.name;
continue;
}
if let Some(parent_id) = channel.parent_id {
if let Some(ix) = this.channels.iter().position(|c| c.id == parent_id) {
this.channels.insert(
ix + 1,
Channel {
id: channel.id,
name: channel.name,
parent_id: Some(parent_id),
},
);
}
} else {
this.channels.insert(
0,
Channel {
id: channel.id,
name: channel.name,
parent_id: None,
},
);
}
}
cx.notify();
});
Ok(())
}
cx.notify();
}
}

View file

@ -0,0 +1,95 @@
use util::http::FakeHttpClient;
use super::*;
#[gpui::test]
fn test_update_channels(cx: &mut AppContext) {
let http = FakeHttpClient::with_404_response();
let client = Client::new(http.clone(), cx);
let user_store = cx.add_model(|cx| UserStore::new(client.clone(), http, cx));
let channel_store = cx.add_model(|cx| ChannelStore::new(client, user_store, cx));
update_channels(
&channel_store,
proto::UpdateChannels {
channels: vec![
proto::Channel {
id: 1,
name: "b".to_string(),
parent_id: None,
},
proto::Channel {
id: 2,
name: "a".to_string(),
parent_id: None,
},
],
..Default::default()
},
cx,
);
assert_channels(
&channel_store,
&[
//
(0, "a"),
(0, "b"),
],
cx,
);
update_channels(
&channel_store,
proto::UpdateChannels {
channels: vec![
proto::Channel {
id: 3,
name: "x".to_string(),
parent_id: Some(1),
},
proto::Channel {
id: 4,
name: "y".to_string(),
parent_id: Some(2),
},
],
..Default::default()
},
cx,
);
assert_channels(
&channel_store,
&[
//
(0, "a"),
(1, "y"),
(0, "b"),
(1, "x"),
],
cx,
);
}
fn update_channels(
channel_store: &ModelHandle<ChannelStore>,
message: proto::UpdateChannels,
cx: &mut AppContext,
) {
channel_store.update(cx, |store, cx| store.update_channels(message, cx));
}
fn assert_channels(
channel_store: &ModelHandle<ChannelStore>,
expected_channels: &[(usize, &str)],
cx: &AppContext,
) {
channel_store.read_with(cx, |store, _| {
let actual = store
.channels()
.iter()
.map(|c| (c.depth, c.name.as_str()))
.collect::<Vec<_>>();
assert_eq!(actual, expected_channels);
});
}

View file

@ -1,6 +1,9 @@
#[cfg(any(test, feature = "test-support"))]
pub mod test;
#[cfg(test)]
mod channel_store_tests;
pub mod channel_store;
pub mod telemetry;
pub mod user;