From 77dbe08d9d9c26dca41f53b420f26d2c5d74cc35 Mon Sep 17 00:00:00 2001 From: Samuel Oldham <77629938+SO9010@users.noreply.github.com> Date: Wed, 22 Oct 2025 11:20:09 +0100 Subject: [PATCH] project_panel: Fix buffer focus when canceling filename edit (#40747) Closes #37726 Release Notes: - Fixed an issue where the buffer would not regain focus when clicked while a filename edit was in progress in the project panel. --------- Co-authored-by: Smit Barmase --- crates/project_panel/src/project_panel.rs | 21 +++------ .../project_panel/src/project_panel_tests.rs | 46 +++++++++---------- 2 files changed, 30 insertions(+), 37 deletions(-) diff --git a/crates/project_panel/src/project_panel.rs b/crates/project_panel/src/project_panel.rs index 67d01a4459bde943e1bdcbaf3d15b3db0f56ce3e..e33dbfd9d0142f335d827b01a07ea66c10efe45a 100644 --- a/crates/project_panel/src/project_panel.rs +++ b/crates/project_panel/src/project_panel.rs @@ -491,10 +491,6 @@ impl ProjectPanel { let project_panel = cx.new(|cx| { let focus_handle = cx.focus_handle(); cx.on_focus(&focus_handle, window, Self::focus_in).detach(); - cx.on_focus_out(&focus_handle, window, |this, _, window, cx| { - this.focus_out(window, cx); - }) - .detach(); cx.subscribe_in( &git_store, @@ -646,7 +642,7 @@ impl ProjectPanel { .as_ref() .is_some_and(|state| state.processing_filename.is_none()) { - match project_panel.confirm_edit(window, cx) { + match project_panel.confirm_edit(false, window, cx) { Some(task) => { task.detach_and_notify_err(window, cx); } @@ -950,12 +946,6 @@ impl ProjectPanel { } } - fn focus_out(&mut self, window: &mut Window, cx: &mut Context) { - if !self.focus_handle.is_focused(window) { - self.confirm(&Confirm, window, cx); - } - } - fn deploy_context_menu( &mut self, position: Point, @@ -1424,7 +1414,7 @@ impl ProjectPanel { } fn confirm(&mut self, _: &Confirm, window: &mut Window, cx: &mut Context) { - if let Some(task) = self.confirm_edit(window, cx) { + if let Some(task) = self.confirm_edit(true, window, cx) { task.detach_and_notify_err(window, cx); } } @@ -1556,6 +1546,7 @@ impl ProjectPanel { fn confirm_edit( &mut self, + refocus: bool, window: &mut Window, cx: &mut Context, ) -> Option>> { @@ -1609,7 +1600,7 @@ impl ProjectPanel { filename.clone() }; if let Some(existing) = worktree.read(cx).entry_for_path(&new_path) { - if existing.id == entry.id { + if existing.id == entry.id && refocus { window.focus(&self.focus_handle); } return None; @@ -1620,7 +1611,9 @@ impl ProjectPanel { }); }; - window.focus(&self.focus_handle); + if refocus { + window.focus(&self.focus_handle); + } edit_state.processing_filename = Some(filename); cx.notify(); diff --git a/crates/project_panel/src/project_panel_tests.rs b/crates/project_panel/src/project_panel_tests.rs index 890041728988bab2914ad7f00ae11637cd9291eb..b6cd1da132ad5c1633001bd53fe365f24870cd7c 100644 --- a/crates/project_panel/src/project_panel_tests.rs +++ b/crates/project_panel/src/project_panel_tests.rs @@ -556,7 +556,7 @@ async fn test_editing_files(cx: &mut gpui::TestAppContext) { panel.filename_editor.update(cx, |editor, cx| { editor.set_text("the-new-filename", window, cx) }); - panel.confirm_edit(window, cx).unwrap() + panel.confirm_edit(true, window, cx).unwrap() }); assert_eq!( visible_entries_as_strings(&panel, 0..10, cx), @@ -616,7 +616,7 @@ async fn test_editing_files(cx: &mut gpui::TestAppContext) { panel.filename_editor.update(cx, |editor, cx| { editor.set_text("another-filename.txt", window, cx) }); - panel.confirm_edit(window, cx).unwrap() + panel.confirm_edit(true, window, cx).unwrap() }) .await .unwrap(); @@ -676,7 +676,7 @@ async fn test_editing_files(cx: &mut gpui::TestAppContext) { editor.set_text("a-different-filename.tar.gz", window, cx) }); - panel.confirm_edit(window, cx).unwrap() + panel.confirm_edit(true, window, cx).unwrap() }); assert_eq!( visible_entries_as_strings(&panel, 0..10, cx), @@ -765,7 +765,7 @@ async fn test_editing_files(cx: &mut gpui::TestAppContext) { panel .filename_editor .update(cx, |editor, cx| editor.set_text("new-dir", window, cx)); - panel.confirm_edit(window, cx).unwrap() + panel.confirm_edit(true, window, cx).unwrap() }); panel.update_in(cx, |panel, window, cx| { panel.select_next(&Default::default(), window, cx) @@ -863,11 +863,11 @@ async fn test_editing_files(cx: &mut gpui::TestAppContext) { panel.filename_editor.update(cx, |editor, cx| { editor.set_text("", window, cx); }); - assert!(panel.confirm_edit(window, cx).is_none()); + assert!(panel.confirm_edit(true, window, cx).is_none()); panel.filename_editor.update(cx, |editor, cx| { editor.set_text(" ", window, cx); }); - assert!(panel.confirm_edit(window, cx).is_none()); + assert!(panel.confirm_edit(true, window, cx).is_none()); panel.cancel(&menu::Cancel, window, cx); panel.update_visible_entries(None, false, false, window, cx); }); @@ -986,7 +986,7 @@ async fn test_adding_directories_via_file(cx: &mut gpui::TestAppContext) { panel.filename_editor.update(cx, |editor, cx| { editor.set_text("/bdir1/dir2/the-new-filename", window, cx) }); - panel.confirm_edit(window, cx).unwrap() + panel.confirm_edit(true, window, cx).unwrap() }); assert_eq!( @@ -1082,7 +1082,7 @@ async fn test_adding_directory_via_file(cx: &mut gpui::TestAppContext) { panel .filename_editor .update(cx, |editor, cx| editor.set_text("new_dir/", window, cx)); - panel.confirm_edit(window, cx).unwrap() + panel.confirm_edit(true, window, cx).unwrap() }); assert_eq!( @@ -1115,7 +1115,7 @@ async fn test_adding_directory_via_file(cx: &mut gpui::TestAppContext) { panel .filename_editor .update(cx, |editor, cx| editor.set_text("new dir 2/", window, cx)); - panel.confirm_edit(window, cx).unwrap() + panel.confirm_edit(true, window, cx).unwrap() }); confirm.await.unwrap(); cx.run_until_parked(); @@ -1140,7 +1140,7 @@ async fn test_adding_directory_via_file(cx: &mut gpui::TestAppContext) { panel .filename_editor .update(cx, |editor, cx| editor.set_text("new_dir_3\\", window, cx)); - panel.confirm_edit(window, cx).unwrap() + panel.confirm_edit(true, window, cx).unwrap() }); confirm.await.unwrap(); cx.run_until_parked(); @@ -1232,7 +1232,7 @@ async fn test_copy_paste(cx: &mut gpui::TestAppContext) { "Should select the file name disambiguation until the extension" ); }); - assert!(panel.confirm_edit(window, cx).is_none()); + assert!(panel.confirm_edit(true, window, cx).is_none()); }); panel.update_in(cx, |panel, window, cx| { @@ -1253,7 +1253,7 @@ async fn test_copy_paste(cx: &mut gpui::TestAppContext) { ); panel.update_in(cx, |panel, window, cx| { - assert!(panel.confirm_edit(window, cx).is_none()) + assert!(panel.confirm_edit(true, window, cx).is_none()) }); } @@ -1672,7 +1672,7 @@ async fn test_copy_paste_directory(cx: &mut gpui::TestAppContext) { panel .filename_editor .update(cx, |editor, cx| editor.set_text("c", window, cx)); - panel.confirm_edit(window, cx).unwrap() + panel.confirm_edit(true, window, cx).unwrap() }); assert_eq!( visible_entries_as_strings(&panel, 0..50, cx), @@ -2060,7 +2060,7 @@ async fn test_create_duplicate_items(cx: &mut gpui::TestAppContext) { .filename_editor .update(cx, |editor, cx| editor.set_text("test", window, cx)); assert!( - panel.confirm_edit(window, cx).is_none(), + panel.confirm_edit(true, window, cx).is_none(), "Should not allow to confirm on conflicting new directory name" ); }); @@ -2116,7 +2116,7 @@ async fn test_create_duplicate_items(cx: &mut gpui::TestAppContext) { .filename_editor .update(cx, |editor, cx| editor.set_text("first.rs", window, cx)); assert!( - panel.confirm_edit(window, cx).is_none(), + panel.confirm_edit(true, window, cx).is_none(), "Should not allow to confirm on conflicting new file name" ); }); @@ -2174,7 +2174,7 @@ async fn test_create_duplicate_items(cx: &mut gpui::TestAppContext) { .filename_editor .update(cx, |editor, cx| editor.set_text("second.rs", window, cx)); assert!( - panel.confirm_edit(window, cx).is_none(), + panel.confirm_edit(true, window, cx).is_none(), "Should not allow to confirm on conflicting file rename" ) }); @@ -3041,7 +3041,7 @@ async fn test_rename_root_of_worktree(cx: &mut gpui::TestAppContext) { panel .filename_editor .update(cx, |editor, cx| editor.set_text("new_root1", window, cx)); - panel.confirm_edit(window, cx).unwrap() + panel.confirm_edit(true, window, cx).unwrap() }); confirm.await.unwrap(); cx.run_until_parked(); @@ -4173,7 +4173,7 @@ async fn test_creating_excluded_entries(cx: &mut gpui::TestAppContext) { panel.filename_editor.update(cx, |editor, cx| { editor.set_text(excluded_file_path, window, cx) }); - panel.confirm_edit(window, cx).unwrap() + panel.confirm_edit(true, window, cx).unwrap() }) .await .unwrap(); @@ -4229,7 +4229,7 @@ async fn test_creating_excluded_entries(cx: &mut gpui::TestAppContext) { panel.filename_editor.update(cx, |editor, cx| { editor.set_text(excluded_file_path, window, cx) }); - panel.confirm_edit(window, cx).unwrap() + panel.confirm_edit(true, window, cx).unwrap() }) .await .unwrap(); @@ -4273,7 +4273,7 @@ async fn test_creating_excluded_entries(cx: &mut gpui::TestAppContext) { panel.filename_editor.update(cx, |editor, cx| { editor.set_text(excluded_dir_path, window, cx) }); - panel.confirm_edit(window, cx).unwrap() + panel.confirm_edit(true, window, cx).unwrap() }) .await .unwrap(); @@ -5694,7 +5694,7 @@ async fn test_create_entries_without_selection(cx: &mut gpui::TestAppContext) { panel.filename_editor.update(cx, |editor, cx| { editor.set_text("hello_from_no_selections", window, cx) }); - panel.confirm_edit(window, cx).unwrap() + panel.confirm_edit(true, window, cx).unwrap() }) .await .unwrap(); @@ -5792,7 +5792,7 @@ async fn test_create_entries_without_selection_hide_root(cx: &mut gpui::TestAppC panel.filename_editor.update(cx, |editor, cx| { editor.set_text("new_file_at_root.txt", window, cx) }); - panel.confirm_edit(window, cx).unwrap() + panel.confirm_edit(true, window, cx).unwrap() }); confirm.await.unwrap(); cx.run_until_parked(); @@ -5843,7 +5843,7 @@ async fn test_create_entries_without_selection_hide_root(cx: &mut gpui::TestAppC panel.filename_editor.update(cx, |editor, cx| { editor.set_text("new_dir_at_root", window, cx) }); - panel.confirm_edit(window, cx).unwrap() + panel.confirm_edit(true, window, cx).unwrap() }); confirm.await.unwrap(); cx.run_until_parked();