Fix project panel losing focus after file creation attempt (#20273)

Closes https://github.com/zed-industries/zed/issues/19771

### Before

When pressing <kbd>esc</kbd> after attempting to create a file, the
focus is lost and you don't know where it went.


https://github.com/user-attachments/assets/2ccd82b7-b7d2-49e4-b1c7-1867331ab9dc

### After

Now, after pressing <kbd>esc</kbd>, the focus returns to where it was
before trying to create a new file.


https://github.com/user-attachments/assets/a8eb1cf1-dfef-42eb-9f3d-2ab6200056c4

Release Notes:

- Fix project panel losing focus after file creation attempt
([#19771](https://github.com/zed-industries/zed/issues/19771))

---------

Co-authored-by: Kirill Bulatov <mail4score@gmail.com>
This commit is contained in:
Danilo Leal 2024-11-06 04:59:06 -03:00 committed by GitHub
parent 846aec701f
commit 3f777f0c68
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -101,6 +101,7 @@ struct EditState {
is_dir: bool,
depth: usize,
processing_filename: Option<String>,
previously_focused: Option<SelectedEntry>,
}
impl EditState {
@ -945,9 +946,17 @@ impl ProjectPanel {
}
fn cancel(&mut self, _: &menu::Cancel, cx: &mut ViewContext<Self>) {
self.edit_state = None;
let previous_edit_state = self.edit_state.take();
self.update_visible_entries(None, cx);
self.marked_entries.clear();
if let Some(previously_focused) =
previous_edit_state.and_then(|edit_state| edit_state.previously_focused)
{
self.selection = Some(previously_focused);
self.autoscroll(cx);
}
cx.focus(&self.focus_handle);
cx.notify();
}
@ -1026,6 +1035,7 @@ impl ProjectPanel {
leaf_entry_id: None,
is_dir,
processing_filename: None,
previously_focused: self.selection,
depth: 0,
});
self.filename_editor.update(cx, |editor, cx| {
@ -1065,6 +1075,7 @@ impl ProjectPanel {
leaf_entry_id: Some(entry_id),
is_dir: entry.is_dir(),
processing_filename: None,
previously_focused: None,
depth: 0,
});
let file_name = entry
@ -6015,6 +6026,70 @@ mod tests {
);
}
#[gpui::test]
async fn test_selection_restored_when_creation_cancelled(cx: &mut gpui::TestAppContext) {
init_test_with_editor(cx);
let fs = FakeFs::new(cx.executor().clone());
fs.insert_tree(
"/src",
json!({
"test": {
"first.rs": "// First Rust file",
"second.rs": "// Second Rust file",
"third.rs": "// Third Rust file",
}
}),
)
.await;
let project = Project::test(fs.clone(), ["/src".as_ref()], cx).await;
let workspace = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
let cx = &mut VisualTestContext::from_window(*workspace, cx);
let panel = workspace
.update(cx, |workspace, cx| {
let panel = ProjectPanel::new(workspace, cx);
workspace.add_panel(panel.clone(), cx);
panel
})
.unwrap();
select_path(&panel, "src/", cx);
panel.update(cx, |panel, cx| panel.confirm(&Confirm, cx));
cx.executor().run_until_parked();
assert_eq!(
visible_entries_as_strings(&panel, 0..10, cx),
&[
//
"v src <== selected",
" > test"
]
);
panel.update(cx, |panel, cx| panel.new_directory(&NewDirectory, cx));
panel.update(cx, |panel, cx| {
assert!(panel.filename_editor.read(cx).is_focused(cx));
});
assert_eq!(
visible_entries_as_strings(&panel, 0..10, cx),
&[
//
"v src",
" > [EDITOR: ''] <== selected",
" > test"
]
);
panel.update(cx, |panel, cx| panel.cancel(&menu::Cancel, cx));
assert_eq!(
visible_entries_as_strings(&panel, 0..10, cx),
&[
//
"v src <== selected",
" > test"
]
);
}
fn toggle_expand_dir(
panel: &View<ProjectPanel>,
path: impl AsRef<Path>,