channel_store.rs

  1use crate::{Client, Subscription, User, UserStore};
  2use anyhow::Result;
  3use collections::HashMap;
  4use futures::Future;
  5use gpui::{AsyncAppContext, Entity, ModelContext, ModelHandle, Task};
  6use rpc::{proto, TypedEnvelope};
  7use std::sync::Arc;
  8
  9type ChannelId = u64;
 10
 11pub struct ChannelStore {
 12    channels: Vec<Arc<Channel>>,
 13    channel_invitations: Vec<Arc<Channel>>,
 14    channel_participants: HashMap<ChannelId, Vec<ChannelId>>,
 15    client: Arc<Client>,
 16    user_store: ModelHandle<UserStore>,
 17    _rpc_subscription: Subscription,
 18}
 19
 20#[derive(Clone, Debug, PartialEq)]
 21pub struct Channel {
 22    pub id: ChannelId,
 23    pub name: String,
 24    pub parent_id: Option<ChannelId>,
 25    pub depth: usize,
 26}
 27
 28impl Entity for ChannelStore {
 29    type Event = ();
 30}
 31
 32impl ChannelStore {
 33    pub fn new(
 34        client: Arc<Client>,
 35        user_store: ModelHandle<UserStore>,
 36        cx: &mut ModelContext<Self>,
 37    ) -> Self {
 38        let rpc_subscription =
 39            client.add_message_handler(cx.handle(), Self::handle_update_channels);
 40
 41        Self {
 42            channels: vec![],
 43            channel_invitations: vec![],
 44            channel_participants: Default::default(),
 45            client,
 46            user_store,
 47            _rpc_subscription: rpc_subscription,
 48        }
 49    }
 50
 51    pub fn channels(&self) -> &[Arc<Channel>] {
 52        &self.channels
 53    }
 54
 55    pub fn channel_invitations(&self) -> &[Arc<Channel>] {
 56        &self.channel_invitations
 57    }
 58
 59    pub fn channel_for_id(&self, channel_id: ChannelId) -> Option<Arc<Channel>> {
 60        self.channels.iter().find(|c| c.id == channel_id).cloned()
 61    }
 62
 63    pub fn create_channel(
 64        &self,
 65        name: &str,
 66        parent_id: Option<ChannelId>,
 67    ) -> impl Future<Output = Result<ChannelId>> {
 68        let client = self.client.clone();
 69        let name = name.to_owned();
 70        async move {
 71            Ok(client
 72                .request(proto::CreateChannel { name, parent_id })
 73                .await?
 74                .channel_id)
 75        }
 76    }
 77
 78    pub fn invite_member(
 79        &self,
 80        channel_id: ChannelId,
 81        user_id: u64,
 82        admin: bool,
 83    ) -> impl Future<Output = Result<()>> {
 84        let client = self.client.clone();
 85        async move {
 86            client
 87                .request(proto::InviteChannelMember {
 88                    channel_id,
 89                    user_id,
 90                    admin,
 91                })
 92                .await?;
 93            Ok(())
 94        }
 95    }
 96
 97    pub fn respond_to_channel_invite(
 98        &mut self,
 99        channel_id: ChannelId,
100        accept: bool,
101    ) -> impl Future<Output = Result<()>> {
102        let client = self.client.clone();
103        async move {
104            client
105                .request(proto::RespondToChannelInvite { channel_id, accept })
106                .await?;
107            Ok(())
108        }
109    }
110
111    pub fn is_channel_invite_pending(&self, channel: &Arc<Channel>) -> bool {
112        false
113    }
114
115    pub fn remove_channel(&self, channel_id: ChannelId) -> impl Future<Output = Result<()>> {
116        let client = self.client.clone();
117        async move {
118            client.request(proto::RemoveChannel { channel_id }).await?;
119            Ok(())
120        }
121    }
122
123    pub fn remove_member(
124        &self,
125        channel_id: ChannelId,
126        user_id: u64,
127        cx: &mut ModelContext<Self>,
128    ) -> Task<Result<()>> {
129        todo!()
130    }
131
132    pub fn channel_members(
133        &self,
134        channel_id: ChannelId,
135        cx: &mut ModelContext<Self>,
136    ) -> Task<Result<Vec<Arc<User>>>> {
137        todo!()
138    }
139
140    pub fn add_guest_channel(&self, channel_id: ChannelId) -> Task<Result<()>> {
141        todo!()
142    }
143
144    async fn handle_update_channels(
145        this: ModelHandle<Self>,
146        message: TypedEnvelope<proto::UpdateChannels>,
147        _: Arc<Client>,
148        mut cx: AsyncAppContext,
149    ) -> Result<()> {
150        this.update(&mut cx, |this, cx| {
151            this.update_channels(message.payload, cx);
152        });
153        Ok(())
154    }
155
156    pub(crate) fn update_channels(
157        &mut self,
158        payload: proto::UpdateChannels,
159        cx: &mut ModelContext<ChannelStore>,
160    ) {
161        self.channels
162            .retain(|channel| !payload.remove_channels.contains(&channel.id));
163        self.channel_invitations
164            .retain(|channel| !payload.remove_channel_invitations.contains(&channel.id));
165
166        for channel in payload.channel_invitations {
167            if let Some(existing_channel) = self
168                .channel_invitations
169                .iter_mut()
170                .find(|c| c.id == channel.id)
171            {
172                Arc::make_mut(existing_channel).name = channel.name;
173                continue;
174            }
175
176            self.channel_invitations.insert(
177                0,
178                Arc::new(Channel {
179                    id: channel.id,
180                    name: channel.name,
181                    parent_id: None,
182                    depth: 0,
183                }),
184            );
185        }
186
187        for channel in payload.channels {
188            if let Some(existing_channel) = self.channels.iter_mut().find(|c| c.id == channel.id) {
189                Arc::make_mut(existing_channel).name = channel.name;
190                continue;
191            }
192
193            if let Some(parent_id) = channel.parent_id {
194                if let Some(ix) = self.channels.iter().position(|c| c.id == parent_id) {
195                    let depth = self.channels[ix].depth + 1;
196                    self.channels.insert(
197                        ix + 1,
198                        Arc::new(Channel {
199                            id: channel.id,
200                            name: channel.name,
201                            parent_id: Some(parent_id),
202                            depth,
203                        }),
204                    );
205                }
206            } else {
207                self.channels.insert(
208                    0,
209                    Arc::new(Channel {
210                        id: channel.id,
211                        name: channel.name,
212                        parent_id: None,
213                        depth: 0,
214                    }),
215                );
216            }
217        }
218        cx.notify();
219    }
220}