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}