On external file drop, add visible project entries for directories only

Kirill Bulatov created

Change summary

crates/journal/src/journal.rs             |  4 
crates/terminal_view/src/terminal_view.rs | 11 ++
crates/workspace/src/pane.rs              |  9 ++
crates/workspace/src/workspace.rs         | 76 +++++++++++++++++++-----
4 files changed, 77 insertions(+), 23 deletions(-)

Detailed changes

crates/journal/src/journal.rs 🔗

@@ -11,7 +11,7 @@ use std::{
     path::{Path, PathBuf},
     sync::Arc,
 };
-use workspace::{AppState, Workspace};
+use workspace::{AppState, OpenVisible, Workspace};
 
 actions!(journal, [NewJournalEntry]);
 
@@ -100,7 +100,7 @@ pub fn new_journal_entry(app_state: Arc<AppState>, cx: &mut WindowContext) {
 
         let opened = workspace
             .update(&mut cx, |workspace, cx| {
-                workspace.open_paths(vec![entry_path], true, None, cx)
+                workspace.open_paths(vec![entry_path], OpenVisible::All, None, cx)
             })?
             .await;
 

crates/terminal_view/src/terminal_view.rs 🔗

@@ -29,7 +29,8 @@ use workspace::{
     notifications::NotifyResultExt,
     register_deserializable_item,
     searchable::{SearchEvent, SearchOptions, SearchableItem, SearchableItemHandle},
-    CloseActiveItem, NewCenterTerminal, Pane, ToolbarItemLocation, Workspace, WorkspaceId,
+    CloseActiveItem, NewCenterTerminal, OpenVisible, Pane, ToolbarItemLocation, Workspace,
+    WorkspaceId,
 };
 
 use anyhow::Context;
@@ -192,12 +193,18 @@ impl TerminalView {
                     }
                     let potential_abs_paths = possible_open_targets(&workspace, maybe_path, cx);
                     if let Some(path) = potential_abs_paths.into_iter().next() {
+                        // TODO kb wrong lib call
                         let is_dir = path.path_like.is_dir();
                         let task_workspace = workspace.clone();
                         cx.spawn(|_, mut cx| async move {
                             let opened_items = task_workspace
                                 .update(&mut cx, |workspace, cx| {
-                                    workspace.open_paths(vec![path.path_like], is_dir, None, cx)
+                                    workspace.open_paths(
+                                        vec![path.path_like],
+                                        OpenVisible::OnlyDirectories,
+                                        None,
+                                        cx,
+                                    )
                                 })
                                 .context("workspace update")?
                                 .await;

crates/workspace/src/pane.rs 🔗

@@ -2,7 +2,7 @@ use crate::{
     item::{ClosePosition, Item, ItemHandle, ItemSettings, WeakItemHandle},
     toolbar::Toolbar,
     workspace_settings::{AutosaveSetting, WorkspaceSettings},
-    NewCenterTerminal, NewFile, NewSearch, SplitDirection, ToggleZoom, Workspace,
+    NewCenterTerminal, NewFile, NewSearch, OpenVisible, SplitDirection, ToggleZoom, Workspace,
 };
 use anyhow::Result;
 use collections::{HashMap, HashSet, VecDeque};
@@ -1899,7 +1899,12 @@ impl Pane {
                         to_pane = workspace.split_pane(to_pane, split_direction, cx);
                     }
                     workspace
-                        .open_paths(paths, true, Some(to_pane.downgrade()), cx)
+                        .open_paths(
+                            paths,
+                            OpenVisible::OnlyDirectories,
+                            Some(to_pane.downgrade()),
+                            cx,
+                        )
                         .detach();
                 });
             })

crates/workspace/src/workspace.rs 🔗

@@ -431,6 +431,13 @@ pub enum Event {
     WorkspaceCreated(WeakView<Workspace>),
 }
 
+pub enum OpenVisible {
+    All,
+    None,
+    OnlyFiles,
+    OnlyDirectories,
+}
+
 pub struct Workspace {
     weak_self: WeakView<Self>,
     workspace_actions: Vec<Box<dyn Fn(Div, &mut ViewContext<Self>) -> Div>>,
@@ -1317,7 +1324,7 @@ impl Workspace {
     pub fn open_paths(
         &mut self,
         mut abs_paths: Vec<PathBuf>,
-        visible: bool,
+        visible: OpenVisible,
         pane: Option<WeakView<Pane>>,
         cx: &mut ViewContext<Self>,
     ) -> Task<Vec<Option<Result<Box<dyn ItemHandle>, anyhow::Error>>>> {
@@ -1329,19 +1336,43 @@ impl Workspace {
         abs_paths.sort_unstable();
         cx.spawn(move |this, mut cx| async move {
             let mut tasks = Vec::with_capacity(abs_paths.len());
+
             for abs_path in &abs_paths {
-                let project_path = match this
-                    .update(&mut cx, |this, cx| {
-                        Workspace::project_path_for_path(
-                            this.project.clone(),
-                            abs_path,
-                            visible,
-                            cx,
-                        )
-                    })
-                    .log_err()
-                {
-                    Some(project_path) => project_path.await.log_err(),
+                let visible = match visible {
+                    OpenVisible::All => Some(true),
+                    OpenVisible::None => Some(false),
+                    OpenVisible::OnlyFiles => match fs.metadata(abs_path).await.log_err() {
+                        Some(Some(metadata)) => Some(!metadata.is_dir),
+                        Some(None) => {
+                            log::error!("No metadata for file {abs_path:?}");
+                            None
+                        }
+                        None => None,
+                    },
+                    OpenVisible::OnlyDirectories => match fs.metadata(abs_path).await.log_err() {
+                        Some(Some(metadata)) => Some(metadata.is_dir),
+                        Some(None) => {
+                            log::error!("No metadata for file {abs_path:?}");
+                            None
+                        }
+                        None => None,
+                    },
+                };
+                let project_path = match visible {
+                    Some(visible) => match this
+                        .update(&mut cx, |this, cx| {
+                            Workspace::project_path_for_path(
+                                this.project.clone(),
+                                abs_path,
+                                visible,
+                                cx,
+                            )
+                        })
+                        .log_err()
+                    {
+                        Some(project_path) => project_path.await.log_err(),
+                        None => None,
+                    },
                     None => None,
                 };
 
@@ -1400,7 +1431,9 @@ impl Workspace {
         cx.spawn(|this, mut cx| async move {
             if let Some(paths) = paths.await.log_err().flatten() {
                 let results = this
-                    .update(&mut cx, |this, cx| this.open_paths(paths, true, None, cx))?
+                    .update(&mut cx, |this, cx| {
+                        this.open_paths(paths, OpenVisible::All, None, cx)
+                    })?
                     .await;
                 for result in results.into_iter().flatten() {
                     result.log_err();
@@ -1786,7 +1819,16 @@ impl Workspace {
         cx.spawn(|workspace, mut cx| async move {
             let open_paths_task_result = workspace
                 .update(&mut cx, |workspace, cx| {
-                    workspace.open_paths(vec![abs_path.clone()], visible, None, cx)
+                    workspace.open_paths(
+                        vec![abs_path.clone()],
+                        if visible {
+                            OpenVisible::All
+                        } else {
+                            OpenVisible::None
+                        },
+                        None,
+                        cx,
+                    )
                 })
                 .with_context(|| format!("open abs path {abs_path:?} task spawn"))?
                 .await;
@@ -4085,7 +4127,7 @@ pub fn open_paths(
                 existing.clone(),
                 existing
                     .update(&mut cx, |workspace, cx| {
-                        workspace.open_paths(abs_paths, true, None, cx)
+                        workspace.open_paths(abs_paths, OpenVisible::All, None, cx)
                     })?
                     .await,
             ))
@@ -4133,7 +4175,7 @@ pub fn create_and_open_local_file(
         let mut items = workspace
             .update(&mut cx, |workspace, cx| {
                 workspace.with_local_workspace(cx, |workspace, cx| {
-                    workspace.open_paths(vec![path.to_path_buf()], false, None, cx)
+                    workspace.open_paths(vec![path.to_path_buf()], OpenVisible::None, None, cx)
                 })
             })?
             .await?