channel_store.rs

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