single click channel (#7596)

- Open channel notes and chat on channel click
- WIP
- Fix compile error
- Don't join live kit until requested
- Track in_call state separately from in_room



Release Notes:

- Improved channels: you can now be in a channel without joining the
audio call automatically

**or**

- N/A

---------

Co-authored-by: Nathan Sobo <nathan@zed.dev>
This commit is contained in:
Conrad Irwin 2024-02-09 14:18:27 -07:00 committed by GitHub
parent 2b39a9512a
commit efe23ebfcd
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
26 changed files with 659 additions and 489 deletions

View file

@ -1,4 +1,7 @@
use crate::{db::ChannelId, tests::TestServer};
use crate::{
db::ChannelId,
tests::{test_server::join_channel_call, TestServer},
};
use call::ActiveCall;
use editor::Editor;
use gpui::{BackgroundExecutor, TestAppContext};
@ -32,7 +35,7 @@ async fn test_channel_guests(
cx_a.executor().run_until_parked();
// Client B joins channel A as a guest
cx_b.update(|cx| workspace::join_channel(channel_id, client_b.app_state.clone(), None, cx))
cx_b.update(|cx| workspace::open_channel(channel_id, client_b.app_state.clone(), None, cx))
.await
.unwrap();
@ -72,7 +75,7 @@ async fn test_channel_guest_promotion(cx_a: &mut TestAppContext, cx_b: &mut Test
.await;
let project_a = client_a.build_test_project(cx_a).await;
cx_a.update(|cx| workspace::join_channel(channel_id, client_a.app_state.clone(), None, cx))
cx_a.update(|cx| workspace::open_channel(channel_id, client_a.app_state.clone(), None, cx))
.await
.unwrap();
@ -84,11 +87,13 @@ async fn test_channel_guest_promotion(cx_a: &mut TestAppContext, cx_b: &mut Test
cx_a.run_until_parked();
// Client B joins channel A as a guest
cx_b.update(|cx| workspace::join_channel(channel_id, client_b.app_state.clone(), None, cx))
cx_b.update(|cx| workspace::open_channel(channel_id, client_b.app_state.clone(), None, cx))
.await
.unwrap();
cx_a.run_until_parked();
join_channel_call(cx_b).await.unwrap();
// client B opens 1.txt as a guest
let (workspace_b, cx_b) = client_b.active_workspace(cx_b);
let room_b = cx_b

View file

@ -1,7 +1,7 @@
use crate::{
db::{self, UserId},
rpc::RECONNECT_TIMEOUT,
tests::{room_participants, RoomParticipants, TestServer},
tests::{room_participants, test_server::join_channel_call, RoomParticipants, TestServer},
};
use call::ActiveCall;
use channel::{ChannelId, ChannelMembership, ChannelStore};
@ -382,6 +382,7 @@ async fn test_channel_room(
.update(cx_a, |active_call, cx| active_call.join_channel(zed_id, cx))
.await
.unwrap();
join_channel_call(cx_a).await.unwrap();
// Give everyone a chance to observe user A joining
executor.run_until_parked();
@ -429,7 +430,7 @@ async fn test_channel_room(
.update(cx_b, |active_call, cx| active_call.join_channel(zed_id, cx))
.await
.unwrap();
join_channel_call(cx_b).await.unwrap();
executor.run_until_parked();
cx_a.read(|cx| {
@ -552,6 +553,9 @@ async fn test_channel_room(
.await
.unwrap();
join_channel_call(cx_a).await.unwrap();
join_channel_call(cx_b).await.unwrap();
executor.run_until_parked();
let room_a =

View file

@ -24,7 +24,7 @@ use workspace::{
use super::TestClient;
#[gpui::test(iterations = 10)]
#[gpui::test]
async fn test_basic_following(
cx_a: &mut TestAppContext,
cx_b: &mut TestAppContext,
@ -437,6 +437,7 @@ async fn test_basic_following(
})
.await
.unwrap();
executor.run_until_parked();
let shared_screen = workspace_a.update(cx_a, |workspace, cx| {
workspace
@ -522,6 +523,7 @@ async fn test_basic_following(
workspace_a.update(cx_a, |workspace, _| workspace.leader_for_pane(&pane_a)),
None
);
executor.run_until_parked();
}
#[gpui::test]
@ -2004,7 +2006,7 @@ async fn join_channel(
client: &TestClient,
cx: &mut TestAppContext,
) -> anyhow::Result<()> {
cx.update(|cx| workspace::join_channel(channel_id, client.app_state.clone(), None, cx))
cx.update(|cx| workspace::open_channel(channel_id, client.app_state.clone(), None, cx))
.await
}

View file

@ -1881,7 +1881,7 @@ fn active_call_events(cx: &mut TestAppContext) -> Rc<RefCell<Vec<room::Event>>>
}
#[gpui::test]
async fn test_mute_deafen(
async fn test_mute(
executor: BackgroundExecutor,
cx_a: &mut TestAppContext,
cx_b: &mut TestAppContext,
@ -1920,7 +1920,7 @@ async fn test_mute_deafen(
room_a.read_with(cx_a, |room, _| assert!(!room.is_muted()));
room_b.read_with(cx_b, |room, _| assert!(!room.is_muted()));
// Users A and B are both muted.
// Users A and B are both unmuted.
assert_eq!(
participant_audio_state(&room_a, cx_a),
&[ParticipantAudioState {
@ -1962,30 +1962,6 @@ async fn test_mute_deafen(
}]
);
// User A deafens
room_a.update(cx_a, |room, cx| room.toggle_deafen(cx));
executor.run_until_parked();
// User A does not hear user B.
room_a.read_with(cx_a, |room, _| assert!(room.is_muted()));
room_b.read_with(cx_b, |room, _| assert!(!room.is_muted()));
assert_eq!(
participant_audio_state(&room_a, cx_a),
&[ParticipantAudioState {
user_id: client_b.user_id().unwrap(),
is_muted: false,
audio_tracks_playing: vec![false],
}]
);
assert_eq!(
participant_audio_state(&room_b, cx_b),
&[ParticipantAudioState {
user_id: client_a.user_id().unwrap(),
is_muted: true,
audio_tracks_playing: vec![true],
}]
);
// User B calls user C, C joins.
active_call_b
.update(cx_b, |call, cx| {
@ -2000,22 +1976,6 @@ async fn test_mute_deafen(
.unwrap();
executor.run_until_parked();
// User A does not hear users B or C.
assert_eq!(
participant_audio_state(&room_a, cx_a),
&[
ParticipantAudioState {
user_id: client_b.user_id().unwrap(),
is_muted: false,
audio_tracks_playing: vec![false],
},
ParticipantAudioState {
user_id: client_c.user_id().unwrap(),
is_muted: false,
audio_tracks_playing: vec![false],
}
]
);
assert_eq!(
participant_audio_state(&room_b, cx_b),
&[

View file

@ -13,7 +13,7 @@ use client::{
use collections::{HashMap, HashSet};
use fs::FakeFs;
use futures::{channel::oneshot, StreamExt as _};
use gpui::{BackgroundExecutor, Context, Model, TestAppContext, View, VisualTestContext};
use gpui::{BackgroundExecutor, Context, Model, Task, TestAppContext, View, VisualTestContext};
use language::LanguageRegistry;
use node_runtime::FakeNodeRuntime;
@ -36,7 +36,7 @@ use std::{
Arc,
},
};
use util::http::FakeHttpClient;
use util::{http::FakeHttpClient, SemanticVersion};
use workspace::{Workspace, WorkspaceStore};
pub struct TestServer {
@ -230,6 +230,7 @@ impl TestServer {
server_conn,
client_name,
user,
SemanticVersion::default(),
None,
Some(connection_id_tx),
Executor::Deterministic(cx.background_executor().clone()),
@ -685,7 +686,7 @@ impl TestClient {
channel_id: u64,
cx: &'a mut TestAppContext,
) -> (View<Workspace>, &'a mut VisualTestContext) {
cx.update(|cx| workspace::join_channel(channel_id, self.app_state.clone(), None, cx))
cx.update(|cx| workspace::open_channel(channel_id, self.app_state.clone(), None, cx))
.await
.unwrap();
cx.run_until_parked();
@ -760,6 +761,11 @@ impl TestClient {
}
}
pub fn join_channel_call(cx: &mut TestAppContext) -> Task<anyhow::Result<()>> {
let room = cx.read(|cx| ActiveCall::global(cx).read(cx).room().cloned());
room.unwrap().update(cx, |room, cx| room.join_call(cx))
}
impl Drop for TestClient {
fn drop(&mut self) {
self.app_state.client.teardown();