fix following bugs (#7406)

- Another broken following test
- Fix following between two windows

Release Notes:

- Fixed following when the leader has multiple Zed windows open
This commit is contained in:
Conrad Irwin 2024-02-05 15:12:25 -07:00 committed by GitHub
parent a80a3b8706
commit 0c34bd8935
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 119 additions and 21 deletions

View file

@ -22,6 +22,8 @@ use workspace::{
SplitDirection, Workspace,
};
use super::TestClient;
#[gpui::test(iterations = 10)]
async fn test_basic_following(
cx_a: &mut TestAppContext,
@ -1996,3 +1998,82 @@ async fn test_following_to_channel_notes_without_a_shared_project(
);
});
}
async fn join_channel(
channel_id: u64,
client: &TestClient,
cx: &mut TestAppContext,
) -> anyhow::Result<()> {
cx.update(|cx| workspace::join_channel(channel_id, client.app_state.clone(), None, cx))
.await
}
async fn share_workspace(
workspace: &View<Workspace>,
cx: &mut VisualTestContext,
) -> anyhow::Result<u64> {
let project = workspace.update(cx, |workspace, _| workspace.project().clone());
cx.read(ActiveCall::global)
.update(cx, |call, cx| call.share_project(project, cx))
.await
}
#[gpui::test]
async fn test_following_to_channel_notes_other_workspace(
cx_a: &mut TestAppContext,
cx_b: &mut TestAppContext,
) {
let (_, client_a, client_b, channel) = TestServer::start2(cx_a, cx_b).await;
let mut cx_a2 = cx_a.clone();
let (workspace_a, cx_a) = client_a.build_test_workspace(cx_a).await;
join_channel(channel, &client_a, cx_a).await.unwrap();
share_workspace(&workspace_a, cx_a).await.unwrap();
// a opens 1.txt
cx_a.simulate_keystrokes("cmd-p 1 enter");
cx_a.run_until_parked();
workspace_a.update(cx_a, |workspace, cx| {
let editor = workspace.active_item(cx).unwrap();
assert_eq!(editor.tab_description(0, cx).unwrap(), "1.txt");
});
// b joins channel and is following a
join_channel(channel, &client_b, cx_b).await.unwrap();
cx_b.run_until_parked();
let (workspace_b, cx_b) = client_b.active_workspace(cx_b);
workspace_b.update(cx_b, |workspace, cx| {
let editor = workspace.active_item(cx).unwrap();
assert_eq!(editor.tab_description(0, cx).unwrap(), "1.txt");
});
// a opens a second workspace and the channel notes
let (workspace_a2, cx_a2) = client_a.build_test_workspace(&mut cx_a2).await;
cx_a2.update(|cx| cx.activate_window());
cx_a2
.update(|cx| ChannelView::open(channel, None, workspace_a2, cx))
.await
.unwrap();
cx_a2.run_until_parked();
// b should follow a to the channel notes
workspace_b.update(cx_b, |workspace, cx| {
let editor = workspace.active_item_as::<ChannelView>(cx).unwrap();
assert_eq!(editor.read(cx).channel(cx).unwrap().id, channel);
});
// a returns to the shared project
cx_a.update(|cx| cx.activate_window());
cx_a.run_until_parked();
workspace_a.update(cx_a, |workspace, cx| {
let editor = workspace.active_item(cx).unwrap();
assert_eq!(editor.tab_description(0, cx).unwrap(), "1.txt");
});
// b should follow a back
workspace_b.update(cx_b, |workspace, cx| {
let editor = workspace.active_item_as::<Editor>(cx).unwrap();
assert_eq!(editor.tab_description(0, cx).unwrap(), "1.txt");
});
}

View file

@ -123,7 +123,12 @@ impl TestServer {
let client_a = server.create_client(cx_a, "user_a").await;
let client_b = server.create_client(cx_b, "user_b").await;
let channel_id = server
.make_channel("a", None, (&client_a, cx_a), &mut [(&client_b, cx_b)])
.make_channel(
"test-channel",
None,
(&client_a, cx_a),
&mut [(&client_b, cx_b)],
)
.await;
cx_a.run_until_parked();

View file

@ -562,14 +562,23 @@ impl CollabTitlebarItem {
}
fn window_activation_changed(&mut self, cx: &mut ViewContext<Self>) {
let project = if cx.is_window_active() {
Some(self.project.clone())
} else {
None
};
ActiveCall::global(cx)
.update(cx, |call, cx| call.set_location(project.as_ref(), cx))
.detach_and_log_err(cx);
if cx.is_window_active() {
ActiveCall::global(cx)
.update(cx, |call, cx| call.set_location(Some(&self.project), cx))
.detach_and_log_err(cx);
return;
}
if cx.active_window().is_none() {
ActiveCall::global(cx)
.update(cx, |call, cx| call.set_location(None, cx))
.detach_and_log_err(cx);
}
self.workspace
.update(cx, |workspace, cx| {
workspace.update_active_view_for_followers(cx);
})
.ok();
}
fn active_call_changed(&mut self, cx: &mut ViewContext<Self>) {

View file

@ -666,6 +666,7 @@ pub trait ProjectItem: Item {
Self: Sized;
}
#[derive(Debug)]
pub enum FollowEvent {
Unfollow,
}

View file

@ -2910,25 +2910,27 @@ impl Workspace {
Ok(())
}
fn update_active_view_for_followers(&mut self, cx: &mut WindowContext) {
pub fn update_active_view_for_followers(&mut self, cx: &mut WindowContext) {
let mut is_project_item = true;
let mut update = proto::UpdateActiveView::default();
if let Some(item) = self.active_item(cx) {
if item.focus_handle(cx).contains_focused(cx) {
if let Some(item) = item.to_followable_item_handle(cx) {
is_project_item = item.is_project_item(cx);
update = proto::UpdateActiveView {
id: item
.remote_id(&self.app_state.client, cx)
.map(|id| id.to_proto()),
leader_id: self.leader_for_pane(&self.active_pane),
};
if cx.is_window_active() {
if let Some(item) = self.active_item(cx) {
if item.focus_handle(cx).contains_focused(cx) {
if let Some(item) = item.to_followable_item_handle(cx) {
is_project_item = item.is_project_item(cx);
update = proto::UpdateActiveView {
id: item
.remote_id(&self.app_state.client, cx)
.map(|id| id.to_proto()),
leader_id: self.leader_for_pane(&self.active_pane),
};
}
}
}
}
if update.id != self.last_active_view_id {
if &update.id != &self.last_active_view_id {
self.last_active_view_id = update.id.clone();
self.update_followers(
is_project_item,