Restore chat functionality with a very rough UI

This commit is contained in:
Max Brunsfeld 2023-09-07 18:06:05 -07:00
parent da5a77badf
commit ddda5a559b
13 changed files with 440 additions and 185 deletions

View file

@ -47,5 +47,6 @@ tempfile = "3"
collections = { path = "../collections", features = ["test-support"] }
gpui = { path = "../gpui", features = ["test-support"] }
rpc = { path = "../rpc", features = ["test-support"] }
client = { path = "../client", features = ["test-support"] }
settings = { path = "../settings", features = ["test-support"] }
util = { path = "../util", features = ["test-support"] }

View file

@ -111,6 +111,10 @@ impl ChannelStore {
}
}
pub fn client(&self) -> Arc<Client> {
self.client.clone()
}
pub fn has_children(&self, channel_id: ChannelId) -> bool {
self.channel_paths.iter().any(|path| {
if let Some(ix) = path.iter().position(|id| *id == channel_id) {

View file

@ -4,15 +4,12 @@ use super::*;
use client::{test::FakeServer, Client, UserStore};
use gpui::{AppContext, ModelHandle, TestAppContext};
use rpc::proto;
use settings::SettingsStore;
use util::http::FakeHttpClient;
#[gpui::test]
fn test_update_channels(cx: &mut AppContext) {
let http = FakeHttpClient::with_404_response();
let client = Client::new(http.clone(), cx);
let user_store = cx.add_model(|cx| UserStore::new(client.clone(), http, cx));
let channel_store = cx.add_model(|cx| ChannelStore::new(client, user_store, cx));
let channel_store = init_test(cx);
update_channels(
&channel_store,
@ -80,11 +77,7 @@ fn test_update_channels(cx: &mut AppContext) {
#[gpui::test]
fn test_dangling_channel_paths(cx: &mut AppContext) {
let http = FakeHttpClient::with_404_response();
let client = Client::new(http.clone(), cx);
let user_store = cx.add_model(|cx| UserStore::new(client.clone(), http, cx));
let channel_store = cx.add_model(|cx| ChannelStore::new(client, user_store, cx));
let channel_store = init_test(cx);
update_channels(
&channel_store,
@ -141,18 +134,11 @@ fn test_dangling_channel_paths(cx: &mut AppContext) {
#[gpui::test]
async fn test_channel_messages(cx: &mut TestAppContext) {
cx.foreground().forbid_parking();
let user_id = 5;
let http_client = FakeHttpClient::with_404_response();
let client = cx.update(|cx| Client::new(http_client.clone(), cx));
let server = FakeServer::for_client(user_id, &client, cx).await;
let user_store = cx.add_model(|cx| UserStore::new(client.clone(), http_client, cx));
crate::init(&client);
let channel_store = cx.add_model(|cx| ChannelStore::new(client, user_store, cx));
let channel_id = 5;
let channel_store = cx.update(init_test);
let client = channel_store.read_with(cx, |s, _| s.client());
let server = FakeServer::for_client(user_id, &client, cx).await;
// Get the available channels.
server.send(proto::UpdateChannels {
@ -163,85 +149,71 @@ async fn test_channel_messages(cx: &mut TestAppContext) {
}],
..Default::default()
});
channel_store.next_notification(cx).await;
cx.foreground().run_until_parked();
cx.read(|cx| {
assert_channels(&channel_store, &[(0, "the-channel".to_string(), false)], cx);
});
let get_users = server.receive::<proto::GetUsers>().await.unwrap();
assert_eq!(get_users.payload.user_ids, vec![5]);
server
.respond(
get_users.receipt(),
proto::UsersResponse {
users: vec![proto::User {
id: 5,
github_login: "nathansobo".into(),
avatar_url: "http://avatar.com/nathansobo".into(),
}],
},
)
.await;
server.respond(
get_users.receipt(),
proto::UsersResponse {
users: vec![proto::User {
id: 5,
github_login: "nathansobo".into(),
avatar_url: "http://avatar.com/nathansobo".into(),
}],
},
);
// Join a channel and populate its existing messages.
let channel = channel_store
.update(cx, |store, cx| {
let channel_id = store.channels().next().unwrap().1.id;
store.open_channel_chat(channel_id, cx)
})
.await
.unwrap();
channel.read_with(cx, |channel, _| assert!(channel.messages().is_empty()));
let channel = channel_store.update(cx, |store, cx| {
let channel_id = store.channels().next().unwrap().1.id;
store.open_channel_chat(channel_id, cx)
});
let join_channel = server.receive::<proto::JoinChannelChat>().await.unwrap();
server
.respond(
join_channel.receipt(),
proto::JoinChannelChatResponse {
messages: vec![
proto::ChannelMessage {
id: 10,
body: "a".into(),
timestamp: 1000,
sender_id: 5,
nonce: Some(1.into()),
},
proto::ChannelMessage {
id: 11,
body: "b".into(),
timestamp: 1001,
sender_id: 6,
nonce: Some(2.into()),
},
],
done: false,
},
)
.await;
server.respond(
join_channel.receipt(),
proto::JoinChannelChatResponse {
messages: vec![
proto::ChannelMessage {
id: 10,
body: "a".into(),
timestamp: 1000,
sender_id: 5,
nonce: Some(1.into()),
},
proto::ChannelMessage {
id: 11,
body: "b".into(),
timestamp: 1001,
sender_id: 6,
nonce: Some(2.into()),
},
],
done: false,
},
);
cx.foreground().start_waiting();
// Client requests all users for the received messages
let mut get_users = server.receive::<proto::GetUsers>().await.unwrap();
get_users.payload.user_ids.sort();
assert_eq!(get_users.payload.user_ids, vec![6]);
server
.respond(
get_users.receipt(),
proto::UsersResponse {
users: vec![proto::User {
id: 6,
github_login: "maxbrunsfeld".into(),
avatar_url: "http://avatar.com/maxbrunsfeld".into(),
}],
},
)
.await;
assert_eq!(
channel.next_event(cx).await,
ChannelChatEvent::MessagesUpdated {
old_range: 0..0,
new_count: 2,
}
server.respond(
get_users.receipt(),
proto::UsersResponse {
users: vec![proto::User {
id: 6,
github_login: "maxbrunsfeld".into(),
avatar_url: "http://avatar.com/maxbrunsfeld".into(),
}],
},
);
let channel = channel.await.unwrap();
channel.read_with(cx, |channel, _| {
assert_eq!(
channel
@ -270,18 +242,16 @@ async fn test_channel_messages(cx: &mut TestAppContext) {
// Client requests user for message since they haven't seen them yet
let get_users = server.receive::<proto::GetUsers>().await.unwrap();
assert_eq!(get_users.payload.user_ids, vec![7]);
server
.respond(
get_users.receipt(),
proto::UsersResponse {
users: vec![proto::User {
id: 7,
github_login: "as-cii".into(),
avatar_url: "http://avatar.com/as-cii".into(),
}],
},
)
.await;
server.respond(
get_users.receipt(),
proto::UsersResponse {
users: vec![proto::User {
id: 7,
github_login: "as-cii".into(),
avatar_url: "http://avatar.com/as-cii".into(),
}],
},
);
assert_eq!(
channel.next_event(cx).await,
@ -307,30 +277,28 @@ async fn test_channel_messages(cx: &mut TestAppContext) {
let get_messages = server.receive::<proto::GetChannelMessages>().await.unwrap();
assert_eq!(get_messages.payload.channel_id, 5);
assert_eq!(get_messages.payload.before_message_id, 10);
server
.respond(
get_messages.receipt(),
proto::GetChannelMessagesResponse {
done: true,
messages: vec![
proto::ChannelMessage {
id: 8,
body: "y".into(),
timestamp: 998,
sender_id: 5,
nonce: Some(4.into()),
},
proto::ChannelMessage {
id: 9,
body: "z".into(),
timestamp: 999,
sender_id: 6,
nonce: Some(5.into()),
},
],
},
)
.await;
server.respond(
get_messages.receipt(),
proto::GetChannelMessagesResponse {
done: true,
messages: vec![
proto::ChannelMessage {
id: 8,
body: "y".into(),
timestamp: 998,
sender_id: 5,
nonce: Some(4.into()),
},
proto::ChannelMessage {
id: 9,
body: "z".into(),
timestamp: 999,
sender_id: 6,
nonce: Some(5.into()),
},
],
},
);
assert_eq!(
channel.next_event(cx).await,
@ -353,6 +321,19 @@ async fn test_channel_messages(cx: &mut TestAppContext) {
});
}
fn init_test(cx: &mut AppContext) -> ModelHandle<ChannelStore> {
let http = FakeHttpClient::with_404_response();
let client = Client::new(http.clone(), cx);
let user_store = cx.add_model(|cx| UserStore::new(client.clone(), http, cx));
cx.foreground().forbid_parking();
cx.set_global(SettingsStore::test(cx));
crate::init(&client);
client::init(&client, cx);
cx.add_model(|cx| ChannelStore::new(client, user_store, cx))
}
fn update_channels(
channel_store: &ModelHandle<ChannelStore>,
message: proto::UpdateChannels,