Move persistence and restoration logic from workspace into project

Co-authored-by: Antonio Scandurra <me@as-cii.com>
This commit is contained in:
Max Brunsfeld 2022-06-03 11:52:10 -07:00
parent 6a3a3a1124
commit afdd386057
2 changed files with 81 additions and 78 deletions

View file

@ -552,6 +552,50 @@ impl Project {
project
}
pub fn restore_state(&mut self, cx: &mut ModelContext<Self>) -> Task<Result<()>> {
if self.is_remote() {
return Task::ready(Ok(()));
}
let db = self.project_store.read(cx).db.clone();
let project_path_keys = self.project_path_keys(cx);
let should_be_public = cx.background().spawn(async move {
let values = db.read(project_path_keys)?;
anyhow::Ok(values.into_iter().all(|e| e.is_some()))
});
cx.spawn(|this, mut cx| async move {
let public = should_be_public.await.log_err().unwrap_or(false);
this.update(&mut cx, |this, cx| {
if let ProjectClientState::Local { public_tx, .. } = &mut this.client_state {
let mut public_tx = public_tx.borrow_mut();
if *public_tx != public {
*public_tx = public;
drop(public_tx);
this.metadata_changed(false, cx);
}
}
});
Ok(())
})
}
fn persist_state(&mut self, cx: &mut ModelContext<Self>) -> Task<Result<()>> {
if self.is_remote() {
return Task::ready(Ok(()));
}
let db = self.project_store.read(cx).db.clone();
let project_path_keys = self.project_path_keys(cx);
let public = self.is_public();
cx.background().spawn(async move {
if public {
db.write(project_path_keys.into_iter().map(|key| (key, &[])))
} else {
db.delete(project_path_keys)
}
})
}
pub fn buffer_for_id(&self, remote_id: u64, cx: &AppContext) -> Option<ModelHandle<Buffer>> {
self.opened_buffers
.get(&remote_id)
@ -633,8 +677,12 @@ impl Project {
pub fn set_public(&mut self, is_public: bool, cx: &mut ModelContext<Self>) {
if let ProjectClientState::Local { public_tx, .. } = &mut self.client_state {
*public_tx.borrow_mut() = is_public;
self.metadata_changed(cx);
let mut public_tx = public_tx.borrow_mut();
if *public_tx != is_public {
*public_tx = is_public;
drop(public_tx);
self.metadata_changed(true, cx);
}
}
}
@ -674,7 +722,7 @@ impl Project {
*remote_id_tx.borrow_mut() = None;
}
this.subscriptions.clear();
this.metadata_changed(cx);
this.metadata_changed(false, cx);
});
response.map(drop)
});
@ -698,7 +746,7 @@ impl Project {
*remote_id_tx.borrow_mut() = Some(remote_id);
}
this.metadata_changed(cx);
this.metadata_changed(false, cx);
cx.emit(Event::RemoteIdChanged(Some(remote_id)));
this.subscriptions
.push(this.client.add_model_for_remote_entity(remote_id, cx));
@ -761,7 +809,7 @@ impl Project {
}
}
fn metadata_changed(&mut self, cx: &mut ModelContext<Self>) {
fn metadata_changed(&mut self, persist: bool, cx: &mut ModelContext<Self>) {
if let ProjectClientState::Local {
remote_id_rx,
public_rx,
@ -786,6 +834,9 @@ impl Project {
}
self.project_store.update(cx, |_, cx| cx.notify());
if persist {
self.persist_state(cx).detach_and_log_err(cx);
}
cx.notify();
}
}
@ -823,6 +874,25 @@ impl Project {
.map(|tree| tree.read(cx).root_name())
}
fn project_path_keys(&self, cx: &AppContext) -> Vec<String> {
self.worktrees
.iter()
.filter_map(|worktree| {
worktree.upgrade(&cx).map(|worktree| {
format!(
"public-project-path:{}",
worktree
.read(cx)
.as_local()
.unwrap()
.abs_path()
.to_string_lossy()
)
})
})
.collect::<Vec<_>>()
}
pub fn worktree_for_id(
&self,
id: WorktreeId,
@ -3769,7 +3839,7 @@ impl Project {
false
}
});
self.metadata_changed(cx);
self.metadata_changed(true, cx);
cx.notify();
}
@ -3799,7 +3869,7 @@ impl Project {
self.worktrees
.push(WorktreeHandle::Weak(worktree.downgrade()));
}
self.metadata_changed(cx);
self.metadata_changed(true, cx);
cx.emit(Event::WorktreeAdded);
cx.notify();
}
@ -4122,7 +4192,7 @@ impl Project {
}
}
this.metadata_changed(cx);
this.metadata_changed(true, cx);
for (id, _) in old_worktrees_by_id {
cx.emit(Event::WorktreeRemoved(id));
}
@ -5274,56 +5344,6 @@ impl ProjectStore {
cx.notify();
}
}
pub fn are_all_project_paths_public(
&self,
project: &Project,
cx: &AppContext,
) -> Task<Result<bool>> {
let project_path_keys = self.project_path_keys(project, cx);
let db = self.db.clone();
cx.background().spawn(async move {
let values = db.read(project_path_keys)?;
Ok(values.into_iter().all(|e| e.is_some()))
})
}
pub fn set_project_paths_public(
&self,
project: &Project,
public: bool,
cx: &AppContext,
) -> Task<Result<()>> {
let project_path_keys = self.project_path_keys(project, cx);
let db = self.db.clone();
cx.background().spawn(async move {
if public {
db.write(project_path_keys.into_iter().map(|key| (key, &[])))
} else {
db.delete(project_path_keys)
}
})
}
fn project_path_keys(&self, project: &Project, cx: &AppContext) -> Vec<String> {
project
.worktrees
.iter()
.filter_map(|worktree| {
worktree.upgrade(&cx).map(|worktree| {
format!(
"public-project-path:{}",
worktree
.read(cx)
.as_local()
.unwrap()
.abs_path()
.to_string_lossy()
)
})
})
.collect::<Vec<_>>()
}
}
impl WorktreeHandle {

View file

@ -1057,12 +1057,6 @@ impl Workspace {
project.update(cx, |project, cx| {
let public = !project.is_public();
project.set_public(public, cx);
project.project_store().update(cx, |store, cx| {
store
.set_project_paths_public(project, public, cx)
.detach_and_log_err(cx);
cx.notify();
});
});
}
@ -2454,21 +2448,10 @@ pub fn open_paths(
.await;
if let Some(project) = new_project {
let public = project
.read_with(&cx, |project, cx| {
app_state
.project_store
.read(cx)
.are_all_project_paths_public(project, cx)
})
project
.update(&mut cx, |project, cx| project.restore_state(cx))
.await
.log_err()
.unwrap_or(false);
if public {
project.update(&mut cx, |project, cx| {
project.set_public(true, cx);
});
}
.log_err();
}
(workspace, items)