From 6a5d0a508395b2dde17ed9dfce08daaa05c77bd4 Mon Sep 17 00:00:00 2001 From: ZZzzaaKK <66885975+ZZzzaaKK@users.noreply.github.com> Date: Thu, 29 Aug 2024 06:18:42 +0200 Subject: [PATCH] Reuse workspace on new journal entry command if possible (#16924) Closes #6783 With this PR, the `journal: new journal entry` command only opens a new workspace if the current workspace does not already contain the `journal` directory. Both the root of the work tree and all its subdirectories are checked. This does not yet check for the day's file specifically, as suggested [here](https://github.com/zed-industries/zed/issues/6783#issuecomment-2268509463). I'm new to writing Rust code in production (as well as contributing in general), so any feedback is much appreciated! Release Notes: - Reuse workspace on `journal: new journal entry` command if possible --- crates/journal/src/journal.rs | 64 +++++++++++++++++++++++++---------- 1 file changed, 46 insertions(+), 18 deletions(-) diff --git a/crates/journal/src/journal.rs b/crates/journal/src/journal.rs index ebb4f4b9a2..860ba53f1f 100644 --- a/crates/journal/src/journal.rs +++ b/crates/journal/src/journal.rs @@ -61,14 +61,14 @@ pub fn init(_: Arc, cx: &mut AppContext) { cx.observe_new_views( |workspace: &mut Workspace, _cx: &mut ViewContext| { workspace.register_action(|workspace, _: &NewJournalEntry, cx| { - new_journal_entry(workspace.app_state().clone(), cx); + new_journal_entry(&workspace, cx); }); }, ) .detach(); } -pub fn new_journal_entry(app_state: Arc, cx: &mut WindowContext) { +pub fn new_journal_entry(workspace: &Workspace, cx: &mut WindowContext) { let settings = JournalSettings::get_global(cx); let journal_dir = match journal_dir(settings.path.as_ref().unwrap()) { Some(journal_dir) => journal_dir, @@ -77,6 +77,7 @@ pub fn new_journal_entry(app_state: Arc, cx: &mut WindowContext) { return; } }; + let journal_dir_clone = journal_dir.clone(); let now = Local::now(); let month_dir = journal_dir @@ -96,24 +97,51 @@ pub fn new_journal_entry(app_state: Arc, cx: &mut WindowContext) { Ok::<_, std::io::Error>((journal_dir, entry_path)) }); + let worktrees = workspace.visible_worktrees(cx).collect::>(); + let mut open_new_workspace = true; + 'outer: for worktree in worktrees.iter() { + let worktree_root = worktree.read(cx).abs_path(); + if *worktree_root == journal_dir_clone { + open_new_workspace = false; + break; + } + for directory in worktree.read(cx).directories(true, 1) { + let full_directory_path = worktree_root.join(&directory.path); + if full_directory_path.ends_with(&journal_dir_clone) { + open_new_workspace = false; + break 'outer; + } + } + } + + let app_state = workspace.app_state().clone(); + let view_snapshot = workspace.weak_handle().clone(); + cx.spawn(|mut cx| async move { let (journal_dir, entry_path) = create_entry.await?; - let (workspace, _) = cx - .update(|cx| { - workspace::open_paths( - &[journal_dir], - app_state, - workspace::OpenOptions::default(), - cx, - ) - })? - .await?; - - let opened = workspace - .update(&mut cx, |workspace, cx| { - workspace.open_paths(vec![entry_path], OpenVisible::All, None, cx) - })? - .await; + let opened = if open_new_workspace { + let (new_workspace, _) = cx + .update(|cx| { + workspace::open_paths( + &[journal_dir], + app_state, + workspace::OpenOptions::default(), + cx, + ) + })? + .await?; + new_workspace + .update(&mut cx, |workspace, cx| { + workspace.open_paths(vec![entry_path], OpenVisible::All, None, cx) + })? + .await + } else { + view_snapshot + .update(&mut cx, |workspace, cx| { + workspace.open_paths(vec![entry_path], OpenVisible::All, None, cx) + })? + .await + }; if let Some(Some(Ok(item))) = opened.first() { if let Some(editor) = item.downcast::().map(|editor| editor.downgrade()) {