Make remote projects to sync in local user settings (#37560)

Closes https://github.com/zed-industries/zed/issues/20024
Closes https://github.com/zed-industries/zed/issues/23489



https://github.com/user-attachments/assets/6466e0c1-4188-4980-8bb6-52ef6e7591c9


Release Notes:

- Made remote projects to sync in local user settings
This commit is contained in:
Kirill Bulatov
2025-09-04 19:05:21 +00:00
committed by GitHub
parent a85946eba8
commit 223fda2fe2
8 changed files with 105 additions and 45 deletions
+8 -1
View File
@@ -1271,6 +1271,7 @@ impl Project {
fs.clone(),
worktree_store.clone(),
task_store.clone(),
Some(remote_proto.clone()),
cx,
)
});
@@ -1521,7 +1522,13 @@ impl Project {
})?;
let settings_observer = cx.new(|cx| {
SettingsObserver::new_remote(fs.clone(), worktree_store.clone(), task_store.clone(), cx)
SettingsObserver::new_remote(
fs.clone(),
worktree_store.clone(),
task_store.clone(),
None,
cx,
)
})?;
let git_store = cx.new(|cx| {
+50 -5
View File
@@ -4,7 +4,7 @@ use context_server::ContextServerCommand;
use dap::adapters::DebugAdapterName;
use fs::Fs;
use futures::StreamExt as _;
use gpui::{App, AsyncApp, BorrowAppContext, Context, Entity, EventEmitter, Task};
use gpui::{App, AsyncApp, BorrowAppContext, Context, Entity, EventEmitter, Subscription, Task};
use lsp::LanguageServerName;
use paths::{
EDITORCONFIG_NAME, local_debug_file_relative_path, local_settings_file_relative_path,
@@ -13,7 +13,7 @@ use paths::{
};
use rpc::{
AnyProtoClient, TypedEnvelope,
proto::{self, FromProto, ToProto},
proto::{self, FromProto, REMOTE_SERVER_PROJECT_ID, ToProto},
};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
@@ -658,6 +658,7 @@ pub struct SettingsObserver {
worktree_store: Entity<WorktreeStore>,
project_id: u64,
task_store: Entity<TaskStore>,
_user_settings_watcher: Option<Subscription>,
_global_task_config_watcher: Task<()>,
_global_debug_config_watcher: Task<()>,
}
@@ -670,6 +671,7 @@ pub struct SettingsObserver {
impl SettingsObserver {
pub fn init(client: &AnyProtoClient) {
client.add_entity_message_handler(Self::handle_update_worktree_settings);
client.add_entity_message_handler(Self::handle_update_user_settings);
}
pub fn new_local(
@@ -686,7 +688,8 @@ impl SettingsObserver {
task_store,
mode: SettingsObserverMode::Local(fs.clone()),
downstream_client: None,
project_id: 0,
_user_settings_watcher: None,
project_id: REMOTE_SERVER_PROJECT_ID,
_global_task_config_watcher: Self::subscribe_to_global_task_file_changes(
fs.clone(),
paths::tasks_file().clone(),
@@ -704,14 +707,38 @@ impl SettingsObserver {
fs: Arc<dyn Fs>,
worktree_store: Entity<WorktreeStore>,
task_store: Entity<TaskStore>,
upstream_client: Option<AnyProtoClient>,
cx: &mut Context<Self>,
) -> Self {
let mut user_settings_watcher = None;
if cx.try_global::<SettingsStore>().is_some() {
if let Some(upstream_client) = upstream_client {
let mut user_settings = None;
user_settings_watcher = Some(cx.observe_global::<SettingsStore>(move |_, cx| {
let new_settings = cx.global::<SettingsStore>().raw_user_settings();
if Some(new_settings) != user_settings.as_ref() {
if let Some(new_settings_string) = serde_json::to_string(new_settings).ok()
{
user_settings = Some(new_settings.clone());
upstream_client
.send(proto::UpdateUserSettings {
project_id: REMOTE_SERVER_PROJECT_ID,
contents: new_settings_string,
})
.log_err();
}
}
}));
}
};
Self {
worktree_store,
task_store,
mode: SettingsObserverMode::Remote,
downstream_client: None,
project_id: 0,
project_id: REMOTE_SERVER_PROJECT_ID,
_user_settings_watcher: user_settings_watcher,
_global_task_config_watcher: Self::subscribe_to_global_task_file_changes(
fs.clone(),
paths::tasks_file().clone(),
@@ -803,6 +830,24 @@ impl SettingsObserver {
Ok(())
}
async fn handle_update_user_settings(
_: Entity<Self>,
envelope: TypedEnvelope<proto::UpdateUserSettings>,
cx: AsyncApp,
) -> anyhow::Result<()> {
let new_settings = serde_json::from_str::<serde_json::Value>(&envelope.payload.contents)
.with_context(|| {
format!("deserializing {} user settings", envelope.payload.contents)
})?;
cx.update_global(|settings_store: &mut SettingsStore, cx| {
settings_store
.set_raw_user_settings(new_settings, cx)
.context("setting new user settings")?;
anyhow::Ok(())
})??;
Ok(())
}
fn on_worktree_store_event(
&mut self,
_: Entity<WorktreeStore>,
@@ -1089,7 +1134,7 @@ impl SettingsObserver {
project_id: self.project_id,
worktree_id: remote_worktree_id.to_proto(),
path: directory.to_proto(),
content: file_content,
content: file_content.clone(),
kind: Some(local_settings_kind_to_proto(kind).into()),
})
.log_err();