@@ -3403,8 +3403,7 @@ impl ProjectPanel {
_: &mut Window,
cx: &mut Context<Self>,
) {
- if let Some((worktree, entry)) = self.selected_sub_entry(cx) {
- let path = worktree.read(cx).absolutize(&entry.path);
+ if let Some(path) = self.reveal_in_file_manager_path(cx) {
self.project
.update(cx, |project, cx| project.reveal_path(&path, cx));
}
@@ -3761,6 +3760,20 @@ impl ProjectPanel {
}
Some((worktree, entry))
}
+
+ fn reveal_in_file_manager_path(&self, cx: &App) -> Option<PathBuf> {
+ if let Some((worktree, entry)) = self.selected_sub_entry(cx) {
+ return Some(worktree.read(cx).absolutize(&entry.path));
+ }
+
+ let root_entry_id = self.state.last_worktree_root_id?;
+ let project = self.project.read(cx);
+ let worktree = project.worktree_for_entry(root_entry_id, cx)?;
+ let worktree = worktree.read(cx);
+ let root_entry = worktree.entry_for_id(root_entry_id)?;
+ Some(worktree.absolutize(&root_entry.path))
+ }
+
fn selected_entry_handle<'a>(
&self,
cx: &'a App,
@@ -8670,6 +8670,55 @@ async fn test_compare_files_context_menu(cx: &mut gpui::TestAppContext) {
}
}
+#[gpui::test]
+async fn test_reveal_in_file_manager_path_falls_back_to_worktree_root(
+ cx: &mut gpui::TestAppContext,
+) {
+ init_test(cx);
+
+ let fs = FakeFs::new(cx.executor());
+ fs.insert_tree(
+ "/root",
+ json!({
+ "file.txt": "content",
+ "dir": {},
+ }),
+ )
+ .await;
+
+ let project = Project::test(fs.clone(), ["/root".as_ref()], cx).await;
+ let window = cx.add_window(|window, cx| MultiWorkspace::test_new(project.clone(), window, cx));
+ let workspace = window
+ .read_with(cx, |mw, _| mw.workspace().clone())
+ .unwrap();
+ let cx = &mut VisualTestContext::from_window(window.into(), cx);
+ let panel = workspace.update_in(cx, ProjectPanel::new);
+ cx.run_until_parked();
+
+ select_path(&panel, "root/file.txt", cx);
+ let selected_reveal_path = panel
+ .update(cx, |panel, cx| panel.reveal_in_file_manager_path(cx))
+ .expect("selected entry should produce a reveal path");
+ assert!(
+ selected_reveal_path.ends_with(Path::new("file.txt")),
+ "Expected selected file path, got {:?}",
+ selected_reveal_path
+ );
+
+ panel.update(cx, |panel, _| {
+ panel.selection = None;
+ panel.marked_entries.clear();
+ });
+ let fallback_reveal_path = panel
+ .update(cx, |panel, cx| panel.reveal_in_file_manager_path(cx))
+ .expect("project root should be used when selection is empty");
+ assert!(
+ fallback_reveal_path.ends_with(Path::new("root")),
+ "Expected worktree root path, got {:?}",
+ fallback_reveal_path
+ );
+}
+
#[gpui::test]
async fn test_hide_hidden_entries(cx: &mut gpui::TestAppContext) {
init_test(cx);