wait for workspace window to show

Agus Zubiaga created

Change summary

crates/git_ui/src/clone.rs          | 24 +++++++++++++----
crates/git_ui/src/git_panel.rs      |  2 
crates/zed/src/main.rs              | 42 ++++++++++++++++++++++++------
crates/zed/src/zed/open_listener.rs |  6 ++-
4 files changed, 56 insertions(+), 18 deletions(-)

Detailed changes

crates/git_ui/src/clone.rs 🔗

@@ -1,12 +1,12 @@
 use gpui::{App, Context, WeakEntity, Window};
 use notifications::status_toast::{StatusToast, ToastIcon};
 use std::sync::Arc;
-use ui::{Color, IconName};
+use ui::{Color, IconName, SharedString};
 use util::ResultExt;
 use workspace::{self, Workspace};
 
 pub fn clone_and_open(
-    repo_url: String,
+    repo_url: SharedString,
     workspace: WeakEntity<Workspace>,
     window: &mut Window,
     cx: &mut App,
@@ -57,8 +57,14 @@ pub fn clone_and_open(
                 return None;
             }
 
-            let prompt_answer = cx
-                .update(|window, cx| {
+            let has_worktrees = workspace
+                .read_with(cx, |workspace, cx| {
+                    workspace.project().read(cx).worktrees(cx).next().is_some()
+                })
+                .ok()?;
+
+            let prompt_answer = if has_worktrees {
+                cx.update(|window, cx| {
                     window.prompt(
                         gpui::PromptLevel::Info,
                         &format!("Git Clone: {}", repo_name),
@@ -67,11 +73,17 @@ pub fn clone_and_open(
                         cx,
                     )
                 })
-                .ok()?;
+                .ok()?
+                .await
+                .ok()?
+            } else {
+                // Don't ask if project is empty
+                0
+            };
 
             destination_dir.push(&repo_name);
 
-            match prompt_answer.await.ok()? {
+            match prompt_answer {
                 0 => {
                     workspace
                         .update_in(cx, |workspace, window, cx| {

crates/git_ui/src/git_panel.rs 🔗

@@ -2851,7 +2851,7 @@ impl GitPanel {
         let workspace = self.workspace.clone();
 
         crate::clone::clone_and_open(
-            repo,
+            repo.into(),
             workspace,
             window,
             cx,

crates/zed/src/main.rs 🔗

@@ -35,10 +35,12 @@ use release_channel::{AppCommitSha, AppVersion, ReleaseChannel};
 use session::{AppSession, Session};
 use settings::{BaseKeymap, Settings, SettingsStore, watch_config_file};
 use std::{
+    cell::RefCell,
     env,
     io::{self, IsTerminal},
     path::{Path, PathBuf},
     process,
+    rc::Rc,
     sync::{Arc, OnceLock},
     time::Instant,
 };
@@ -897,15 +899,37 @@ fn handle_open_request(request: OpenRequest, app_state: Arc<AppState>, cx: &mut
             }
             OpenRequestKind::GitClone { repo_url } => {
                 workspace::with_active_or_new_workspace(cx, |_workspace, window, cx| {
-                    clone_and_open(
-                        repo_url,
-                        cx.entity().downgrade(),
-                        window,
-                        cx,
-                        Arc::new(|workspace: &mut workspace::Workspace, window, cx| {
-                            workspace.focus_panel::<ProjectPanel>(window, cx);
-                        }),
-                    );
+                    if window.is_window_active() {
+                        clone_and_open(
+                            repo_url,
+                            cx.weak_entity(),
+                            window,
+                            cx,
+                            Arc::new(|workspace: &mut workspace::Workspace, window, cx| {
+                                workspace.focus_panel::<ProjectPanel>(window, cx);
+                            }),
+                        );
+                        return;
+                    }
+
+                    let subscription = Rc::new(RefCell::new(None));
+                    subscription.replace(Some(cx.observe_in(&cx.entity(), window, {
+                        let subscription = subscription.clone();
+                        let repo_url = repo_url.clone();
+                        move |_, workspace_entity, window, cx| {
+                            if window.is_window_active() && subscription.take().is_some() {
+                                clone_and_open(
+                                    repo_url.clone(),
+                                    workspace_entity.downgrade(),
+                                    window,
+                                    cx,
+                                    Arc::new(|workspace: &mut workspace::Workspace, window, cx| {
+                                        workspace.focus_panel::<ProjectPanel>(window, cx);
+                                    }),
+                                );
+                            }
+                        }
+                    })));
                 });
             }
             OpenRequestKind::GitCommit { sha } => {

crates/zed/src/zed/open_listener.rs 🔗

@@ -25,6 +25,7 @@ use std::path::{Path, PathBuf};
 use std::sync::Arc;
 use std::thread;
 use std::time::Duration;
+use ui::SharedString;
 use util::ResultExt;
 use util::paths::PathWithPosition;
 use workspace::PathList;
@@ -59,7 +60,7 @@ pub enum OpenRequestKind {
         setting_path: Option<String>,
     },
     GitClone {
-        repo_url: String,
+        repo_url: SharedString,
     },
     GitCommit {
         sha: String,
@@ -160,7 +161,8 @@ impl OpenRequest {
             .find_map(|(key, value)| (key == "repo").then_some(value))
             .filter(|s| !s.is_empty())
             .context("invalid git clone url: missing repo query parameter")?
-            .to_string();
+            .to_string()
+            .into();
 
         self.kind = Some(OpenRequestKind::GitClone { repo_url });