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}