Set up basic RPC for managing channels
Co-authored-by: Mikayla <mikayla@zed.dev>
This commit is contained in:
parent
758e1f6e57
commit
4b94bfa045
12 changed files with 541 additions and 150 deletions
189
crates/client/src/channel_store.rs
Normal file
189
crates/client/src/channel_store.rs
Normal file
|
@ -0,0 +1,189 @@
|
||||||
|
use crate::{Client, Subscription, User, UserStore};
|
||||||
|
use anyhow::Result;
|
||||||
|
use futures::Future;
|
||||||
|
use gpui::{AsyncAppContext, Entity, ModelContext, ModelHandle, Task};
|
||||||
|
use rpc::{proto, TypedEnvelope};
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
pub struct ChannelStore {
|
||||||
|
channels: Vec<Channel>,
|
||||||
|
channel_invitations: Vec<Channel>,
|
||||||
|
client: Arc<Client>,
|
||||||
|
user_store: ModelHandle<UserStore>,
|
||||||
|
rpc_subscription: Subscription,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq)]
|
||||||
|
pub struct Channel {
|
||||||
|
pub id: u64,
|
||||||
|
pub name: String,
|
||||||
|
pub parent_id: Option<u64>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Entity for ChannelStore {
|
||||||
|
type Event = ();
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ChannelStore {
|
||||||
|
pub fn new(
|
||||||
|
client: Arc<Client>,
|
||||||
|
user_store: ModelHandle<UserStore>,
|
||||||
|
cx: &mut ModelContext<Self>,
|
||||||
|
) -> Self {
|
||||||
|
let rpc_subscription =
|
||||||
|
client.add_message_handler(cx.handle(), Self::handle_update_channels);
|
||||||
|
Self {
|
||||||
|
channels: vec![],
|
||||||
|
channel_invitations: vec![],
|
||||||
|
client,
|
||||||
|
user_store,
|
||||||
|
rpc_subscription,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn channels(&self) -> &[Channel] {
|
||||||
|
&self.channels
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn channel_invitations(&self) -> &[Channel] {
|
||||||
|
&self.channel_invitations
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create_channel(
|
||||||
|
&self,
|
||||||
|
name: &str,
|
||||||
|
parent_id: Option<u64>,
|
||||||
|
) -> impl Future<Output = Result<u64>> {
|
||||||
|
let client = self.client.clone();
|
||||||
|
let name = name.to_owned();
|
||||||
|
async move {
|
||||||
|
Ok(client
|
||||||
|
.request(proto::CreateChannel { name, parent_id })
|
||||||
|
.await?
|
||||||
|
.channel_id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn invite_member(
|
||||||
|
&self,
|
||||||
|
channel_id: u64,
|
||||||
|
user_id: u64,
|
||||||
|
admin: bool,
|
||||||
|
) -> impl Future<Output = Result<()>> {
|
||||||
|
let client = self.client.clone();
|
||||||
|
async move {
|
||||||
|
client
|
||||||
|
.request(proto::InviteChannelMember {
|
||||||
|
channel_id,
|
||||||
|
user_id,
|
||||||
|
admin,
|
||||||
|
})
|
||||||
|
.await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn respond_to_channel_invite(
|
||||||
|
&mut self,
|
||||||
|
channel_id: u64,
|
||||||
|
accept: bool,
|
||||||
|
) -> impl Future<Output = Result<()>> {
|
||||||
|
let client = self.client.clone();
|
||||||
|
async move {
|
||||||
|
client
|
||||||
|
.request(proto::RespondToChannelInvite { channel_id, accept })
|
||||||
|
.await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn remove_member(
|
||||||
|
&self,
|
||||||
|
channel_id: u64,
|
||||||
|
user_id: u64,
|
||||||
|
cx: &mut ModelContext<Self>,
|
||||||
|
) -> Task<Result<()>> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn channel_members(
|
||||||
|
&self,
|
||||||
|
channel_id: u64,
|
||||||
|
cx: &mut ModelContext<Self>,
|
||||||
|
) -> Task<Result<Vec<Arc<User>>>> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add_guest_channel(&self, channel_id: u64) -> Task<Result<()>> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn handle_update_channels(
|
||||||
|
this: ModelHandle<Self>,
|
||||||
|
message: TypedEnvelope<proto::UpdateChannels>,
|
||||||
|
_: 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));
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.channel_invitations.insert(
|
||||||
|
0,
|
||||||
|
Channel {
|
||||||
|
id: channel.id,
|
||||||
|
name: channel.name,
|
||||||
|
parent_id: None,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
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(())
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
#[cfg(any(test, feature = "test-support"))]
|
#[cfg(any(test, feature = "test-support"))]
|
||||||
pub mod test;
|
pub mod test;
|
||||||
|
|
||||||
|
pub mod channel_store;
|
||||||
pub mod telemetry;
|
pub mod telemetry;
|
||||||
pub mod user;
|
pub mod user;
|
||||||
|
|
||||||
|
@ -44,6 +45,7 @@ use util::channel::ReleaseChannel;
|
||||||
use util::http::HttpClient;
|
use util::http::HttpClient;
|
||||||
use util::{ResultExt, TryFutureExt};
|
use util::{ResultExt, TryFutureExt};
|
||||||
|
|
||||||
|
pub use channel_store::*;
|
||||||
pub use rpc::*;
|
pub use rpc::*;
|
||||||
pub use telemetry::ClickhouseEvent;
|
pub use telemetry::ClickhouseEvent;
|
||||||
pub use user::*;
|
pub use user::*;
|
||||||
|
|
|
@ -203,6 +203,7 @@ CREATE TABLE "channel_members" (
|
||||||
"channel_id" INTEGER NOT NULL REFERENCES channels (id) ON DELETE CASCADE,
|
"channel_id" INTEGER NOT NULL REFERENCES channels (id) ON DELETE CASCADE,
|
||||||
"user_id" INTEGER NOT NULL REFERENCES users (id) ON DELETE CASCADE,
|
"user_id" INTEGER NOT NULL REFERENCES users (id) ON DELETE CASCADE,
|
||||||
"admin" BOOLEAN NOT NULL DEFAULT false,
|
"admin" BOOLEAN NOT NULL DEFAULT false,
|
||||||
|
"accepted" BOOLEAN NOT NULL DEFAULT false,
|
||||||
"updated_at" TIMESTAMP NOT NULL DEFAULT now
|
"updated_at" TIMESTAMP NOT NULL DEFAULT now
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,7 @@ CREATE TABLE "channel_members" (
|
||||||
"channel_id" INTEGER NOT NULL REFERENCES channels (id) ON DELETE CASCADE,
|
"channel_id" INTEGER NOT NULL REFERENCES channels (id) ON DELETE CASCADE,
|
||||||
"user_id" INTEGER NOT NULL REFERENCES users (id) ON DELETE CASCADE,
|
"user_id" INTEGER NOT NULL REFERENCES users (id) ON DELETE CASCADE,
|
||||||
"admin" BOOLEAN NOT NULL DEFAULT false,
|
"admin" BOOLEAN NOT NULL DEFAULT false,
|
||||||
|
"accepted" BOOLEAN NOT NULL DEFAULT false,
|
||||||
"updated_at" TIMESTAMP NOT NULL DEFAULT now()
|
"updated_at" TIMESTAMP NOT NULL DEFAULT now()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -3032,11 +3032,16 @@ impl Database {
|
||||||
|
|
||||||
// channels
|
// channels
|
||||||
|
|
||||||
pub async fn create_root_channel(&self, name: &str) -> Result<ChannelId> {
|
pub async fn create_root_channel(&self, name: &str, creator_id: UserId) -> Result<ChannelId> {
|
||||||
self.create_channel(name, None).await
|
self.create_channel(name, None, creator_id).await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn create_channel(&self, name: &str, parent: Option<ChannelId>) -> Result<ChannelId> {
|
pub async fn create_channel(
|
||||||
|
&self,
|
||||||
|
name: &str,
|
||||||
|
parent: Option<ChannelId>,
|
||||||
|
creator_id: UserId,
|
||||||
|
) -> Result<ChannelId> {
|
||||||
self.transaction(move |tx| async move {
|
self.transaction(move |tx| async move {
|
||||||
let tx = tx;
|
let tx = tx;
|
||||||
|
|
||||||
|
@ -3056,19 +3061,50 @@ impl Database {
|
||||||
.await?;
|
.await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
channel_member::ActiveModel {
|
||||||
|
channel_id: ActiveValue::Set(channel.id),
|
||||||
|
user_id: ActiveValue::Set(creator_id),
|
||||||
|
accepted: ActiveValue::Set(true),
|
||||||
|
admin: ActiveValue::Set(true),
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
.insert(&*tx)
|
||||||
|
.await?;
|
||||||
|
|
||||||
Ok(channel.id)
|
Ok(channel.id)
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
// Property: Members are only
|
pub async fn invite_channel_member(
|
||||||
pub async fn add_channel_member(&self, channel_id: ChannelId, user_id: UserId) -> Result<()> {
|
&self,
|
||||||
|
channel_id: ChannelId,
|
||||||
|
invitee_id: UserId,
|
||||||
|
inviter_id: UserId,
|
||||||
|
is_admin: bool,
|
||||||
|
) -> Result<()> {
|
||||||
self.transaction(move |tx| async move {
|
self.transaction(move |tx| async move {
|
||||||
let tx = tx;
|
let tx = tx;
|
||||||
|
|
||||||
|
// Check if inviter is a member
|
||||||
|
channel_member::Entity::find()
|
||||||
|
.filter(
|
||||||
|
channel_member::Column::ChannelId
|
||||||
|
.eq(channel_id)
|
||||||
|
.and(channel_member::Column::UserId.eq(inviter_id))
|
||||||
|
.and(channel_member::Column::Admin.eq(true)),
|
||||||
|
)
|
||||||
|
.one(&*tx)
|
||||||
|
.await?
|
||||||
|
.ok_or_else(|| {
|
||||||
|
anyhow!("Inviter does not have permissions to invite the invitee")
|
||||||
|
})?;
|
||||||
|
|
||||||
let channel_membership = channel_member::ActiveModel {
|
let channel_membership = channel_member::ActiveModel {
|
||||||
channel_id: ActiveValue::Set(channel_id),
|
channel_id: ActiveValue::Set(channel_id),
|
||||||
user_id: ActiveValue::Set(user_id),
|
user_id: ActiveValue::Set(invitee_id),
|
||||||
|
accepted: ActiveValue::Set(false),
|
||||||
|
admin: ActiveValue::Set(is_admin),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -3079,6 +3115,50 @@ impl Database {
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn respond_to_channel_invite(
|
||||||
|
&self,
|
||||||
|
channel_id: ChannelId,
|
||||||
|
user_id: UserId,
|
||||||
|
accept: bool,
|
||||||
|
) -> Result<()> {
|
||||||
|
self.transaction(move |tx| async move {
|
||||||
|
let tx = tx;
|
||||||
|
|
||||||
|
let rows_affected = if accept {
|
||||||
|
channel_member::Entity::update_many()
|
||||||
|
.set(channel_member::ActiveModel {
|
||||||
|
accepted: ActiveValue::Set(accept),
|
||||||
|
..Default::default()
|
||||||
|
})
|
||||||
|
.filter(
|
||||||
|
channel_member::Column::ChannelId
|
||||||
|
.eq(channel_id)
|
||||||
|
.and(channel_member::Column::UserId.eq(user_id))
|
||||||
|
.and(channel_member::Column::Accepted.eq(false)),
|
||||||
|
)
|
||||||
|
.exec(&*tx)
|
||||||
|
.await?
|
||||||
|
.rows_affected
|
||||||
|
} else {
|
||||||
|
channel_member::ActiveModel {
|
||||||
|
channel_id: ActiveValue::Unchanged(channel_id),
|
||||||
|
user_id: ActiveValue::Unchanged(user_id),
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
.delete(&*tx)
|
||||||
|
.await?
|
||||||
|
.rows_affected
|
||||||
|
};
|
||||||
|
|
||||||
|
if rows_affected == 0 {
|
||||||
|
Err(anyhow!("no such invitation"))?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
})
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn get_channels(&self, user_id: UserId) -> Result<Vec<Channel>> {
|
pub async fn get_channels(&self, user_id: UserId) -> Result<Vec<Channel>> {
|
||||||
self.transaction(|tx| async move {
|
self.transaction(|tx| async move {
|
||||||
let tx = tx;
|
let tx = tx;
|
||||||
|
@ -3087,7 +3167,7 @@ impl Database {
|
||||||
WITH RECURSIVE channel_tree(child_id, parent_id, depth) AS (
|
WITH RECURSIVE channel_tree(child_id, parent_id, depth) AS (
|
||||||
SELECT channel_id as child_id, CAST(NULL as INTEGER) as parent_id, 0
|
SELECT channel_id as child_id, CAST(NULL as INTEGER) as parent_id, 0
|
||||||
FROM channel_members
|
FROM channel_members
|
||||||
WHERE user_id = $1
|
WHERE user_id = $1 AND accepted
|
||||||
UNION
|
UNION
|
||||||
SELECT channel_parents.child_id, channel_parents.parent_id, channel_tree.depth + 1
|
SELECT channel_parents.child_id, channel_parents.parent_id, channel_tree.depth + 1
|
||||||
FROM channel_parents, channel_tree
|
FROM channel_parents, channel_tree
|
||||||
|
@ -3114,6 +3194,22 @@ impl Database {
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn get_channel(&self, channel_id: ChannelId) -> Result<Channel> {
|
||||||
|
self.transaction(|tx| async move {
|
||||||
|
let tx = tx;
|
||||||
|
let channel = channel::Entity::find_by_id(channel_id)
|
||||||
|
.one(&*tx)
|
||||||
|
.await?
|
||||||
|
.ok_or_else(|| anyhow!("no such channel"))?;
|
||||||
|
Ok(Channel {
|
||||||
|
id: channel.id,
|
||||||
|
name: channel.name,
|
||||||
|
parent_id: None,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
|
||||||
async fn transaction<F, Fut, T>(&self, f: F) -> Result<T>
|
async fn transaction<F, Fut, T>(&self, f: F) -> Result<T>
|
||||||
where
|
where
|
||||||
F: Send + Fn(TransactionHandle) -> Fut,
|
F: Send + Fn(TransactionHandle) -> Fut,
|
||||||
|
|
|
@ -10,6 +10,8 @@ pub struct Model {
|
||||||
pub id: ChannelMemberId,
|
pub id: ChannelMemberId,
|
||||||
pub channel_id: ChannelId,
|
pub channel_id: ChannelId,
|
||||||
pub user_id: UserId,
|
pub user_id: UserId,
|
||||||
|
pub accepted: bool,
|
||||||
|
pub admin: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ActiveModelBehavior for ActiveModel {}
|
impl ActiveModelBehavior for ActiveModel {}
|
||||||
|
|
|
@ -894,18 +894,21 @@ test_both_dbs!(test_channels_postgres, test_channels_sqlite, db, {
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.user_id;
|
.user_id;
|
||||||
|
|
||||||
let zed_id = db.create_root_channel("zed").await.unwrap();
|
let zed_id = db.create_root_channel("zed", a_id).await.unwrap();
|
||||||
let crdb_id = db.create_channel("crdb", Some(zed_id)).await.unwrap();
|
let crdb_id = db.create_channel("crdb", Some(zed_id), a_id).await.unwrap();
|
||||||
let livestreaming_id = db
|
let livestreaming_id = db
|
||||||
.create_channel("livestreaming", Some(zed_id))
|
.create_channel("livestreaming", Some(zed_id), a_id)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
let replace_id = db
|
||||||
|
.create_channel("replace", Some(zed_id), a_id)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
let rust_id = db.create_root_channel("rust", a_id).await.unwrap();
|
||||||
|
let cargo_id = db
|
||||||
|
.create_channel("cargo", Some(rust_id), a_id)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let replace_id = db.create_channel("replace", Some(zed_id)).await.unwrap();
|
|
||||||
let rust_id = db.create_root_channel("rust").await.unwrap();
|
|
||||||
let cargo_id = db.create_channel("cargo", Some(rust_id)).await.unwrap();
|
|
||||||
|
|
||||||
db.add_channel_member(zed_id, a_id).await.unwrap();
|
|
||||||
db.add_channel_member(rust_id, a_id).await.unwrap();
|
|
||||||
|
|
||||||
let channels = db.get_channels(a_id).await.unwrap();
|
let channels = db.get_channels(a_id).await.unwrap();
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ mod connection_pool;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
auth,
|
auth,
|
||||||
db::{self, Database, ProjectId, RoomId, ServerId, User, UserId},
|
db::{self, ChannelId, Database, ProjectId, RoomId, ServerId, User, UserId},
|
||||||
executor::Executor,
|
executor::Executor,
|
||||||
AppState, Result,
|
AppState, Result,
|
||||||
};
|
};
|
||||||
|
@ -239,6 +239,10 @@ impl Server {
|
||||||
.add_request_handler(request_contact)
|
.add_request_handler(request_contact)
|
||||||
.add_request_handler(remove_contact)
|
.add_request_handler(remove_contact)
|
||||||
.add_request_handler(respond_to_contact_request)
|
.add_request_handler(respond_to_contact_request)
|
||||||
|
.add_request_handler(create_channel)
|
||||||
|
.add_request_handler(invite_channel_member)
|
||||||
|
.add_request_handler(remove_channel_member)
|
||||||
|
.add_request_handler(respond_to_channel_invite)
|
||||||
.add_request_handler(follow)
|
.add_request_handler(follow)
|
||||||
.add_message_handler(unfollow)
|
.add_message_handler(unfollow)
|
||||||
.add_message_handler(update_followers)
|
.add_message_handler(update_followers)
|
||||||
|
@ -2084,6 +2088,100 @@ async fn remove_contact(
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn create_channel(
|
||||||
|
request: proto::CreateChannel,
|
||||||
|
response: Response<proto::CreateChannel>,
|
||||||
|
session: Session,
|
||||||
|
) -> Result<()> {
|
||||||
|
let db = session.db().await;
|
||||||
|
let id = db
|
||||||
|
.create_channel(
|
||||||
|
&request.name,
|
||||||
|
request.parent_id.map(|id| ChannelId::from_proto(id)),
|
||||||
|
session.user_id,
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
let mut update = proto::UpdateChannels::default();
|
||||||
|
update.channels.push(proto::Channel {
|
||||||
|
id: id.to_proto(),
|
||||||
|
name: request.name,
|
||||||
|
parent_id: request.parent_id,
|
||||||
|
});
|
||||||
|
session.peer.send(session.connection_id, update)?;
|
||||||
|
response.send(proto::CreateChannelResponse {
|
||||||
|
channel_id: id.to_proto(),
|
||||||
|
})?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn invite_channel_member(
|
||||||
|
request: proto::InviteChannelMember,
|
||||||
|
response: Response<proto::InviteChannelMember>,
|
||||||
|
session: Session,
|
||||||
|
) -> Result<()> {
|
||||||
|
let db = session.db().await;
|
||||||
|
let channel_id = ChannelId::from_proto(request.channel_id);
|
||||||
|
let channel = db.get_channel(channel_id).await?;
|
||||||
|
let invitee_id = UserId::from_proto(request.user_id);
|
||||||
|
db.invite_channel_member(channel_id, invitee_id, session.user_id, false)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
let mut update = proto::UpdateChannels::default();
|
||||||
|
update.channel_invitations.push(proto::Channel {
|
||||||
|
id: channel.id.to_proto(),
|
||||||
|
name: channel.name,
|
||||||
|
parent_id: None,
|
||||||
|
});
|
||||||
|
for connection_id in session
|
||||||
|
.connection_pool()
|
||||||
|
.await
|
||||||
|
.user_connection_ids(invitee_id)
|
||||||
|
{
|
||||||
|
session.peer.send(connection_id, update.clone())?;
|
||||||
|
}
|
||||||
|
|
||||||
|
response.send(proto::Ack {})?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn remove_channel_member(
|
||||||
|
request: proto::RemoveChannelMember,
|
||||||
|
response: Response<proto::RemoveChannelMember>,
|
||||||
|
session: Session,
|
||||||
|
) -> Result<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn respond_to_channel_invite(
|
||||||
|
request: proto::RespondToChannelInvite,
|
||||||
|
response: Response<proto::RespondToChannelInvite>,
|
||||||
|
session: Session,
|
||||||
|
) -> Result<()> {
|
||||||
|
let db = session.db().await;
|
||||||
|
let channel_id = ChannelId::from_proto(request.channel_id);
|
||||||
|
let channel = db.get_channel(channel_id).await?;
|
||||||
|
db.respond_to_channel_invite(channel_id, session.user_id, request.accept)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
let mut update = proto::UpdateChannels::default();
|
||||||
|
update
|
||||||
|
.remove_channel_invitations
|
||||||
|
.push(channel_id.to_proto());
|
||||||
|
if request.accept {
|
||||||
|
update.channels.push(proto::Channel {
|
||||||
|
id: channel.id.to_proto(),
|
||||||
|
name: channel.name,
|
||||||
|
parent_id: None,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
session.peer.send(session.connection_id, update)?;
|
||||||
|
response.send(proto::Ack {})?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
async fn update_diff_base(request: proto::UpdateDiffBase, session: Session) -> Result<()> {
|
async fn update_diff_base(request: proto::UpdateDiffBase, session: Session) -> Result<()> {
|
||||||
let project_id = ProjectId::from_proto(request.project_id);
|
let project_id = ProjectId::from_proto(request.project_id);
|
||||||
let project_connection_ids = session
|
let project_connection_ids = session
|
||||||
|
|
|
@ -7,7 +7,8 @@ use crate::{
|
||||||
use anyhow::anyhow;
|
use anyhow::anyhow;
|
||||||
use call::ActiveCall;
|
use call::ActiveCall;
|
||||||
use client::{
|
use client::{
|
||||||
self, proto::PeerId, Client, Connection, Credentials, EstablishConnectionError, UserStore,
|
self, proto::PeerId, ChannelStore, Client, Connection, Credentials, EstablishConnectionError,
|
||||||
|
UserStore,
|
||||||
};
|
};
|
||||||
use collections::{HashMap, HashSet};
|
use collections::{HashMap, HashSet};
|
||||||
use fs::FakeFs;
|
use fs::FakeFs;
|
||||||
|
@ -33,9 +34,9 @@ use std::{
|
||||||
use util::http::FakeHttpClient;
|
use util::http::FakeHttpClient;
|
||||||
use workspace::Workspace;
|
use workspace::Workspace;
|
||||||
|
|
||||||
|
mod channel_tests;
|
||||||
mod integration_tests;
|
mod integration_tests;
|
||||||
mod randomized_integration_tests;
|
mod randomized_integration_tests;
|
||||||
mod channel_tests;
|
|
||||||
|
|
||||||
struct TestServer {
|
struct TestServer {
|
||||||
app_state: Arc<AppState>,
|
app_state: Arc<AppState>,
|
||||||
|
@ -187,6 +188,8 @@ impl TestServer {
|
||||||
|
|
||||||
let fs = FakeFs::new(cx.background());
|
let fs = FakeFs::new(cx.background());
|
||||||
let user_store = cx.add_model(|cx| UserStore::new(client.clone(), http, cx));
|
let user_store = cx.add_model(|cx| UserStore::new(client.clone(), http, cx));
|
||||||
|
let channel_store =
|
||||||
|
cx.add_model(|cx| ChannelStore::new(client.clone(), user_store.clone(), cx));
|
||||||
let app_state = Arc::new(workspace::AppState {
|
let app_state = Arc::new(workspace::AppState {
|
||||||
client: client.clone(),
|
client: client.clone(),
|
||||||
user_store: user_store.clone(),
|
user_store: user_store.clone(),
|
||||||
|
@ -218,6 +221,7 @@ impl TestServer {
|
||||||
username: name.to_string(),
|
username: name.to_string(),
|
||||||
state: Default::default(),
|
state: Default::default(),
|
||||||
user_store,
|
user_store,
|
||||||
|
channel_store,
|
||||||
fs,
|
fs,
|
||||||
language_registry: Arc::new(LanguageRegistry::test()),
|
language_registry: Arc::new(LanguageRegistry::test()),
|
||||||
};
|
};
|
||||||
|
@ -320,6 +324,7 @@ struct TestClient {
|
||||||
username: String,
|
username: String,
|
||||||
state: RefCell<TestClientState>,
|
state: RefCell<TestClientState>,
|
||||||
pub user_store: ModelHandle<UserStore>,
|
pub user_store: ModelHandle<UserStore>,
|
||||||
|
pub channel_store: ModelHandle<ChannelStore>,
|
||||||
language_registry: Arc<LanguageRegistry>,
|
language_registry: Arc<LanguageRegistry>,
|
||||||
fs: Arc<FakeFs>,
|
fs: Arc<FakeFs>,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,85 +1,108 @@
|
||||||
|
use client::Channel;
|
||||||
use gpui::{executor::Deterministic, TestAppContext};
|
use gpui::{executor::Deterministic, TestAppContext};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use crate::db::Channel;
|
|
||||||
|
|
||||||
use super::TestServer;
|
use super::TestServer;
|
||||||
|
|
||||||
#[gpui::test]
|
#[gpui::test]
|
||||||
async fn test_basic_channels(deterministic: Arc<Deterministic>, cx: &mut TestAppContext) {
|
async fn test_basic_channels(
|
||||||
|
deterministic: Arc<Deterministic>,
|
||||||
|
cx_a: &mut TestAppContext,
|
||||||
|
cx_b: &mut TestAppContext,
|
||||||
|
) {
|
||||||
deterministic.forbid_parking();
|
deterministic.forbid_parking();
|
||||||
let mut server = TestServer::start(&deterministic).await;
|
let mut server = TestServer::start(&deterministic).await;
|
||||||
let client_a = server.create_client(cx, "user_a").await;
|
let client_a = server.create_client(cx_a, "user_a").await;
|
||||||
let a_id = crate::db::UserId(client_a.user_id().unwrap() as i32);
|
let client_b = server.create_client(cx_b, "user_b").await;
|
||||||
let db = server._test_db.db();
|
|
||||||
|
|
||||||
let zed_id = db.create_root_channel("zed").await.unwrap();
|
let channel_a_id = client_a
|
||||||
let crdb_id = db.create_channel("crdb", Some(zed_id)).await.unwrap();
|
.channel_store
|
||||||
let livestreaming_id = db
|
.update(cx_a, |channel_store, _| {
|
||||||
.create_channel("livestreaming", Some(zed_id))
|
channel_store.create_channel("channel-a", None)
|
||||||
|
})
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let replace_id = db.create_channel("replace", Some(zed_id)).await.unwrap();
|
|
||||||
let rust_id = db.create_root_channel("rust").await.unwrap();
|
|
||||||
let cargo_id = db.create_channel("cargo", Some(rust_id)).await.unwrap();
|
|
||||||
|
|
||||||
db.add_channel_member(zed_id, a_id).await.unwrap();
|
client_a.channel_store.read_with(cx_a, |channels, _| {
|
||||||
db.add_channel_member(rust_id, a_id).await.unwrap();
|
assert_eq!(
|
||||||
|
channels.channels(),
|
||||||
let channels = db.get_channels(a_id).await.unwrap();
|
&[Channel {
|
||||||
assert_eq!(
|
id: channel_a_id,
|
||||||
channels,
|
name: "channel-a".to_string(),
|
||||||
vec![
|
|
||||||
Channel {
|
|
||||||
id: zed_id,
|
|
||||||
name: "zed".to_string(),
|
|
||||||
parent_id: None,
|
parent_id: None,
|
||||||
},
|
}]
|
||||||
Channel {
|
)
|
||||||
id: rust_id,
|
});
|
||||||
name: "rust".to_string(),
|
|
||||||
parent_id: None,
|
|
||||||
},
|
|
||||||
Channel {
|
|
||||||
id: crdb_id,
|
|
||||||
name: "crdb".to_string(),
|
|
||||||
parent_id: Some(zed_id),
|
|
||||||
},
|
|
||||||
Channel {
|
|
||||||
id: livestreaming_id,
|
|
||||||
name: "livestreaming".to_string(),
|
|
||||||
parent_id: Some(zed_id),
|
|
||||||
},
|
|
||||||
Channel {
|
|
||||||
id: replace_id,
|
|
||||||
name: "replace".to_string(),
|
|
||||||
parent_id: Some(zed_id),
|
|
||||||
},
|
|
||||||
Channel {
|
|
||||||
id: cargo_id,
|
|
||||||
name: "cargo".to_string(),
|
|
||||||
parent_id: Some(rust_id),
|
|
||||||
}
|
|
||||||
]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[gpui::test]
|
client_b
|
||||||
async fn test_block_cycle_creation(deterministic: Arc<Deterministic>, cx: &mut TestAppContext) {
|
.channel_store
|
||||||
deterministic.forbid_parking();
|
.read_with(cx_b, |channels, _| assert_eq!(channels.channels(), &[]));
|
||||||
let mut server = TestServer::start(&deterministic).await;
|
|
||||||
let client_a = server.create_client(cx, "user_a").await;
|
|
||||||
let a_id = crate::db::UserId(client_a.user_id().unwrap() as i32);
|
|
||||||
let db = server._test_db.db();
|
|
||||||
|
|
||||||
let zed_id = db.create_root_channel("zed").await.unwrap();
|
// Invite client B to channel A as client A.
|
||||||
let first_id = db.create_channel("first", Some(zed_id)).await.unwrap();
|
client_a
|
||||||
let second_id = db
|
.channel_store
|
||||||
.create_channel("second_id", Some(first_id))
|
.update(cx_a, |channel_store, _| {
|
||||||
|
channel_store.invite_member(channel_a_id, client_b.user_id().unwrap(), false)
|
||||||
|
})
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
// Wait for client b to see the invitation
|
||||||
|
deterministic.run_until_parked();
|
||||||
|
|
||||||
|
client_b.channel_store.read_with(cx_b, |channels, _| {
|
||||||
|
assert_eq!(
|
||||||
|
channels.channel_invitations(),
|
||||||
|
&[Channel {
|
||||||
|
id: channel_a_id,
|
||||||
|
name: "channel-a".to_string(),
|
||||||
|
parent_id: None,
|
||||||
|
}]
|
||||||
|
)
|
||||||
|
});
|
||||||
|
|
||||||
|
// Client B now sees that they are in channel A.
|
||||||
|
client_b
|
||||||
|
.channel_store
|
||||||
|
.update(cx_b, |channels, _| {
|
||||||
|
channels.respond_to_channel_invite(channel_a_id, true)
|
||||||
|
})
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
client_b.channel_store.read_with(cx_b, |channels, _| {
|
||||||
|
assert_eq!(channels.channel_invitations(), &[]);
|
||||||
|
assert_eq!(
|
||||||
|
channels.channels(),
|
||||||
|
&[Channel {
|
||||||
|
id: channel_a_id,
|
||||||
|
name: "channel-a".to_string(),
|
||||||
|
parent_id: None,
|
||||||
|
}]
|
||||||
|
)
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO:
|
||||||
|
// Invariants to test:
|
||||||
|
// 1. Dag structure is maintained for all operations (can't make a cycle)
|
||||||
|
// 2. Can't be a member of a super channel, and accept a membership of a sub channel (by definition, a noop)
|
||||||
|
|
||||||
|
// #[gpui::test]
|
||||||
|
// async fn test_block_cycle_creation(deterministic: Arc<Deterministic>, cx: &mut TestAppContext) {
|
||||||
|
// // deterministic.forbid_parking();
|
||||||
|
// // let mut server = TestServer::start(&deterministic).await;
|
||||||
|
// // let client_a = server.create_client(cx, "user_a").await;
|
||||||
|
// // let a_id = crate::db::UserId(client_a.user_id().unwrap() as i32);
|
||||||
|
// // let db = server._test_db.db();
|
||||||
|
|
||||||
|
// // let zed_id = db.create_root_channel("zed", a_id).await.unwrap();
|
||||||
|
// // let first_id = db.create_channel("first", Some(zed_id)).await.unwrap();
|
||||||
|
// // let second_id = db
|
||||||
|
// // .create_channel("second_id", Some(first_id))
|
||||||
|
// // .await
|
||||||
|
// // .unwrap();
|
||||||
|
// }
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Linear things:
|
Linear things:
|
||||||
- A way of expressing progress to the team
|
- A way of expressing progress to the team
|
||||||
|
|
|
@ -102,17 +102,6 @@ message Envelope {
|
||||||
SearchProject search_project = 80;
|
SearchProject search_project = 80;
|
||||||
SearchProjectResponse search_project_response = 81;
|
SearchProjectResponse search_project_response = 81;
|
||||||
|
|
||||||
GetChannels get_channels = 82;
|
|
||||||
GetChannelsResponse get_channels_response = 83;
|
|
||||||
JoinChannel join_channel = 84;
|
|
||||||
JoinChannelResponse join_channel_response = 85;
|
|
||||||
LeaveChannel leave_channel = 86;
|
|
||||||
SendChannelMessage send_channel_message = 87;
|
|
||||||
SendChannelMessageResponse send_channel_message_response = 88;
|
|
||||||
ChannelMessageSent channel_message_sent = 89;
|
|
||||||
GetChannelMessages get_channel_messages = 90;
|
|
||||||
GetChannelMessagesResponse get_channel_messages_response = 91;
|
|
||||||
|
|
||||||
UpdateContacts update_contacts = 92;
|
UpdateContacts update_contacts = 92;
|
||||||
UpdateInviteInfo update_invite_info = 93;
|
UpdateInviteInfo update_invite_info = 93;
|
||||||
ShowContacts show_contacts = 94;
|
ShowContacts show_contacts = 94;
|
||||||
|
@ -140,6 +129,13 @@ message Envelope {
|
||||||
InlayHints inlay_hints = 116;
|
InlayHints inlay_hints = 116;
|
||||||
InlayHintsResponse inlay_hints_response = 117;
|
InlayHintsResponse inlay_hints_response = 117;
|
||||||
RefreshInlayHints refresh_inlay_hints = 118;
|
RefreshInlayHints refresh_inlay_hints = 118;
|
||||||
|
|
||||||
|
CreateChannel create_channel = 119;
|
||||||
|
CreateChannelResponse create_channel_response = 120;
|
||||||
|
InviteChannelMember invite_channel_member = 121;
|
||||||
|
RemoveChannelMember remove_channel_member = 122;
|
||||||
|
RespondToChannelInvite respond_to_channel_invite = 123;
|
||||||
|
UpdateChannels update_channels = 124;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -867,23 +863,36 @@ message LspDiskBasedDiagnosticsUpdating {}
|
||||||
|
|
||||||
message LspDiskBasedDiagnosticsUpdated {}
|
message LspDiskBasedDiagnosticsUpdated {}
|
||||||
|
|
||||||
message GetChannels {}
|
message UpdateChannels {
|
||||||
|
|
||||||
message GetChannelsResponse {
|
|
||||||
repeated Channel channels = 1;
|
repeated Channel channels = 1;
|
||||||
|
repeated uint64 remove_channels = 2;
|
||||||
|
repeated Channel channel_invitations = 3;
|
||||||
|
repeated uint64 remove_channel_invitations = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
message JoinChannel {
|
message CreateChannel {
|
||||||
|
string name = 1;
|
||||||
|
optional uint64 parent_id = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message CreateChannelResponse {
|
||||||
uint64 channel_id = 1;
|
uint64 channel_id = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
message JoinChannelResponse {
|
message InviteChannelMember {
|
||||||
repeated ChannelMessage messages = 1;
|
uint64 channel_id = 1;
|
||||||
bool done = 2;
|
uint64 user_id = 2;
|
||||||
|
bool admin = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
message LeaveChannel {
|
message RemoveChannelMember {
|
||||||
uint64 channel_id = 1;
|
uint64 channel_id = 1;
|
||||||
|
uint64 user_id = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message RespondToChannelInvite {
|
||||||
|
uint64 channel_id = 1;
|
||||||
|
bool accept = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
message GetUsers {
|
message GetUsers {
|
||||||
|
@ -918,31 +927,6 @@ enum ContactRequestResponse {
|
||||||
Dismiss = 3;
|
Dismiss = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
message SendChannelMessage {
|
|
||||||
uint64 channel_id = 1;
|
|
||||||
string body = 2;
|
|
||||||
Nonce nonce = 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
message SendChannelMessageResponse {
|
|
||||||
ChannelMessage message = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
message ChannelMessageSent {
|
|
||||||
uint64 channel_id = 1;
|
|
||||||
ChannelMessage message = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
message GetChannelMessages {
|
|
||||||
uint64 channel_id = 1;
|
|
||||||
uint64 before_message_id = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
message GetChannelMessagesResponse {
|
|
||||||
repeated ChannelMessage messages = 1;
|
|
||||||
bool done = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
message UpdateContacts {
|
message UpdateContacts {
|
||||||
repeated Contact contacts = 1;
|
repeated Contact contacts = 1;
|
||||||
repeated uint64 remove_contacts = 2;
|
repeated uint64 remove_contacts = 2;
|
||||||
|
@ -1274,14 +1258,7 @@ message Nonce {
|
||||||
message Channel {
|
message Channel {
|
||||||
uint64 id = 1;
|
uint64 id = 1;
|
||||||
string name = 2;
|
string name = 2;
|
||||||
}
|
optional uint64 parent_id = 3;
|
||||||
|
|
||||||
message ChannelMessage {
|
|
||||||
uint64 id = 1;
|
|
||||||
string body = 2;
|
|
||||||
uint64 timestamp = 3;
|
|
||||||
uint64 sender_id = 4;
|
|
||||||
Nonce nonce = 5;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
message Contact {
|
message Contact {
|
||||||
|
|
|
@ -143,9 +143,10 @@ messages!(
|
||||||
(Call, Foreground),
|
(Call, Foreground),
|
||||||
(CallCanceled, Foreground),
|
(CallCanceled, Foreground),
|
||||||
(CancelCall, Foreground),
|
(CancelCall, Foreground),
|
||||||
(ChannelMessageSent, Foreground),
|
|
||||||
(CopyProjectEntry, Foreground),
|
(CopyProjectEntry, Foreground),
|
||||||
(CreateBufferForPeer, Foreground),
|
(CreateBufferForPeer, Foreground),
|
||||||
|
(CreateChannel, Foreground),
|
||||||
|
(CreateChannelResponse, Foreground),
|
||||||
(CreateProjectEntry, Foreground),
|
(CreateProjectEntry, Foreground),
|
||||||
(CreateRoom, Foreground),
|
(CreateRoom, Foreground),
|
||||||
(CreateRoomResponse, Foreground),
|
(CreateRoomResponse, Foreground),
|
||||||
|
@ -158,10 +159,6 @@ messages!(
|
||||||
(FormatBuffers, Foreground),
|
(FormatBuffers, Foreground),
|
||||||
(FormatBuffersResponse, Foreground),
|
(FormatBuffersResponse, Foreground),
|
||||||
(FuzzySearchUsers, Foreground),
|
(FuzzySearchUsers, Foreground),
|
||||||
(GetChannelMessages, Foreground),
|
|
||||||
(GetChannelMessagesResponse, Foreground),
|
|
||||||
(GetChannels, Foreground),
|
|
||||||
(GetChannelsResponse, Foreground),
|
|
||||||
(GetCodeActions, Background),
|
(GetCodeActions, Background),
|
||||||
(GetCodeActionsResponse, Background),
|
(GetCodeActionsResponse, Background),
|
||||||
(GetHover, Background),
|
(GetHover, Background),
|
||||||
|
@ -181,14 +178,12 @@ messages!(
|
||||||
(GetUsers, Foreground),
|
(GetUsers, Foreground),
|
||||||
(Hello, Foreground),
|
(Hello, Foreground),
|
||||||
(IncomingCall, Foreground),
|
(IncomingCall, Foreground),
|
||||||
|
(InviteChannelMember, Foreground),
|
||||||
(UsersResponse, Foreground),
|
(UsersResponse, Foreground),
|
||||||
(JoinChannel, Foreground),
|
|
||||||
(JoinChannelResponse, Foreground),
|
|
||||||
(JoinProject, Foreground),
|
(JoinProject, Foreground),
|
||||||
(JoinProjectResponse, Foreground),
|
(JoinProjectResponse, Foreground),
|
||||||
(JoinRoom, Foreground),
|
(JoinRoom, Foreground),
|
||||||
(JoinRoomResponse, Foreground),
|
(JoinRoomResponse, Foreground),
|
||||||
(LeaveChannel, Foreground),
|
|
||||||
(LeaveProject, Foreground),
|
(LeaveProject, Foreground),
|
||||||
(LeaveRoom, Foreground),
|
(LeaveRoom, Foreground),
|
||||||
(OpenBufferById, Background),
|
(OpenBufferById, Background),
|
||||||
|
@ -211,18 +206,18 @@ messages!(
|
||||||
(RejoinRoom, Foreground),
|
(RejoinRoom, Foreground),
|
||||||
(RejoinRoomResponse, Foreground),
|
(RejoinRoomResponse, Foreground),
|
||||||
(RemoveContact, Foreground),
|
(RemoveContact, Foreground),
|
||||||
|
(RemoveChannelMember, Foreground),
|
||||||
(ReloadBuffers, Foreground),
|
(ReloadBuffers, Foreground),
|
||||||
(ReloadBuffersResponse, Foreground),
|
(ReloadBuffersResponse, Foreground),
|
||||||
(RemoveProjectCollaborator, Foreground),
|
(RemoveProjectCollaborator, Foreground),
|
||||||
(RenameProjectEntry, Foreground),
|
(RenameProjectEntry, Foreground),
|
||||||
(RequestContact, Foreground),
|
(RequestContact, Foreground),
|
||||||
(RespondToContactRequest, Foreground),
|
(RespondToContactRequest, Foreground),
|
||||||
|
(RespondToChannelInvite, Foreground),
|
||||||
(RoomUpdated, Foreground),
|
(RoomUpdated, Foreground),
|
||||||
(SaveBuffer, Foreground),
|
(SaveBuffer, Foreground),
|
||||||
(SearchProject, Background),
|
(SearchProject, Background),
|
||||||
(SearchProjectResponse, Background),
|
(SearchProjectResponse, Background),
|
||||||
(SendChannelMessage, Foreground),
|
|
||||||
(SendChannelMessageResponse, Foreground),
|
|
||||||
(ShareProject, Foreground),
|
(ShareProject, Foreground),
|
||||||
(ShareProjectResponse, Foreground),
|
(ShareProjectResponse, Foreground),
|
||||||
(ShowContacts, Foreground),
|
(ShowContacts, Foreground),
|
||||||
|
@ -235,6 +230,7 @@ messages!(
|
||||||
(UpdateBuffer, Foreground),
|
(UpdateBuffer, Foreground),
|
||||||
(UpdateBufferFile, Foreground),
|
(UpdateBufferFile, Foreground),
|
||||||
(UpdateContacts, Foreground),
|
(UpdateContacts, Foreground),
|
||||||
|
(UpdateChannels, Foreground),
|
||||||
(UpdateDiagnosticSummary, Foreground),
|
(UpdateDiagnosticSummary, Foreground),
|
||||||
(UpdateFollowers, Foreground),
|
(UpdateFollowers, Foreground),
|
||||||
(UpdateInviteInfo, Foreground),
|
(UpdateInviteInfo, Foreground),
|
||||||
|
@ -260,13 +256,12 @@ request_messages!(
|
||||||
(CopyProjectEntry, ProjectEntryResponse),
|
(CopyProjectEntry, ProjectEntryResponse),
|
||||||
(CreateProjectEntry, ProjectEntryResponse),
|
(CreateProjectEntry, ProjectEntryResponse),
|
||||||
(CreateRoom, CreateRoomResponse),
|
(CreateRoom, CreateRoomResponse),
|
||||||
|
(CreateChannel, CreateChannelResponse),
|
||||||
(DeclineCall, Ack),
|
(DeclineCall, Ack),
|
||||||
(DeleteProjectEntry, ProjectEntryResponse),
|
(DeleteProjectEntry, ProjectEntryResponse),
|
||||||
(ExpandProjectEntry, ExpandProjectEntryResponse),
|
(ExpandProjectEntry, ExpandProjectEntryResponse),
|
||||||
(Follow, FollowResponse),
|
(Follow, FollowResponse),
|
||||||
(FormatBuffers, FormatBuffersResponse),
|
(FormatBuffers, FormatBuffersResponse),
|
||||||
(GetChannelMessages, GetChannelMessagesResponse),
|
|
||||||
(GetChannels, GetChannelsResponse),
|
|
||||||
(GetCodeActions, GetCodeActionsResponse),
|
(GetCodeActions, GetCodeActionsResponse),
|
||||||
(GetHover, GetHoverResponse),
|
(GetHover, GetHoverResponse),
|
||||||
(GetCompletions, GetCompletionsResponse),
|
(GetCompletions, GetCompletionsResponse),
|
||||||
|
@ -278,7 +273,7 @@ request_messages!(
|
||||||
(GetProjectSymbols, GetProjectSymbolsResponse),
|
(GetProjectSymbols, GetProjectSymbolsResponse),
|
||||||
(FuzzySearchUsers, UsersResponse),
|
(FuzzySearchUsers, UsersResponse),
|
||||||
(GetUsers, UsersResponse),
|
(GetUsers, UsersResponse),
|
||||||
(JoinChannel, JoinChannelResponse),
|
(InviteChannelMember, Ack),
|
||||||
(JoinProject, JoinProjectResponse),
|
(JoinProject, JoinProjectResponse),
|
||||||
(JoinRoom, JoinRoomResponse),
|
(JoinRoom, JoinRoomResponse),
|
||||||
(LeaveRoom, Ack),
|
(LeaveRoom, Ack),
|
||||||
|
@ -295,12 +290,13 @@ request_messages!(
|
||||||
(RefreshInlayHints, Ack),
|
(RefreshInlayHints, Ack),
|
||||||
(ReloadBuffers, ReloadBuffersResponse),
|
(ReloadBuffers, ReloadBuffersResponse),
|
||||||
(RequestContact, Ack),
|
(RequestContact, Ack),
|
||||||
|
(RemoveChannelMember, Ack),
|
||||||
(RemoveContact, Ack),
|
(RemoveContact, Ack),
|
||||||
(RespondToContactRequest, Ack),
|
(RespondToContactRequest, Ack),
|
||||||
|
(RespondToChannelInvite, Ack),
|
||||||
(RenameProjectEntry, ProjectEntryResponse),
|
(RenameProjectEntry, ProjectEntryResponse),
|
||||||
(SaveBuffer, BufferSaved),
|
(SaveBuffer, BufferSaved),
|
||||||
(SearchProject, SearchProjectResponse),
|
(SearchProject, SearchProjectResponse),
|
||||||
(SendChannelMessage, SendChannelMessageResponse),
|
|
||||||
(ShareProject, ShareProjectResponse),
|
(ShareProject, ShareProjectResponse),
|
||||||
(SynchronizeBuffers, SynchronizeBuffersResponse),
|
(SynchronizeBuffers, SynchronizeBuffersResponse),
|
||||||
(Test, Test),
|
(Test, Test),
|
||||||
|
@ -363,8 +359,6 @@ entity_messages!(
|
||||||
UpdateDiffBase
|
UpdateDiffBase
|
||||||
);
|
);
|
||||||
|
|
||||||
entity_messages!(channel_id, ChannelMessageSent);
|
|
||||||
|
|
||||||
const KIB: usize = 1024;
|
const KIB: usize = 1024;
|
||||||
const MIB: usize = KIB * 1024;
|
const MIB: usize = KIB * 1024;
|
||||||
const MAX_BUFFER_LEN: usize = MIB;
|
const MAX_BUFFER_LEN: usize = MIB;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue