@@ -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");
+ });
+}
@@ -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();
@@ -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>) {
@@ -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,