Switch project search deploy behavior to be isolated to a pane (#4072)
This adjusts the solution in https://github.com/zed-industries/zed/pull/4014 to fix the double-focus issue, allowing each pane's project search to work independently. Release Notes: - Changed the name of the `workspace::DeploySearch` action to `pane::DeploySearch` and changed it's behavior to open a new search OR focus an existing project search in the current pane. (https://github.com/zed-industries/community/issues/2395)
This commit is contained in:
commit
d00067cd86
4 changed files with 49 additions and 31 deletions
|
@ -402,7 +402,7 @@
|
||||||
"cmd-r": "workspace::ToggleRightDock",
|
"cmd-r": "workspace::ToggleRightDock",
|
||||||
"cmd-j": "workspace::ToggleBottomDock",
|
"cmd-j": "workspace::ToggleBottomDock",
|
||||||
"alt-cmd-y": "workspace::CloseAllDocks",
|
"alt-cmd-y": "workspace::CloseAllDocks",
|
||||||
"cmd-shift-f": "workspace::DeploySearch",
|
"cmd-shift-f": "pane::DeploySearch",
|
||||||
"cmd-k cmd-t": "theme_selector::Toggle",
|
"cmd-k cmd-t": "theme_selector::Toggle",
|
||||||
"cmd-k cmd-s": "zed::OpenKeymap",
|
"cmd-k cmd-s": "zed::OpenKeymap",
|
||||||
"cmd-t": "project_symbols::Toggle",
|
"cmd-t": "project_symbols::Toggle",
|
||||||
|
|
|
@ -54,14 +54,10 @@ actions!(
|
||||||
[SearchInNew, ToggleFocus, NextField, ToggleFilters]
|
[SearchInNew, ToggleFocus, NextField, ToggleFilters]
|
||||||
);
|
);
|
||||||
|
|
||||||
#[derive(Default)]
|
|
||||||
struct ActiveSearches(HashMap<WeakModel<Project>, WeakView<ProjectSearchView>>);
|
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
struct ActiveSettings(HashMap<WeakModel<Project>, ProjectSearchSettings>);
|
struct ActiveSettings(HashMap<WeakModel<Project>, ProjectSearchSettings>);
|
||||||
|
|
||||||
pub fn init(cx: &mut AppContext) {
|
pub fn init(cx: &mut AppContext) {
|
||||||
cx.set_global(ActiveSearches::default());
|
|
||||||
cx.set_global(ActiveSettings::default());
|
cx.set_global(ActiveSettings::default());
|
||||||
cx.observe_new_views(|workspace: &mut Workspace, _cx| {
|
cx.observe_new_views(|workspace: &mut Workspace, _cx| {
|
||||||
workspace
|
workspace
|
||||||
|
@ -948,25 +944,19 @@ impl ProjectSearchView {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Re-activate the most recently activated search or the most recent if it has been closed.
|
// Re-activate the most recently activated search in this pane or the most recent if it has been closed.
|
||||||
// If no search exists in the workspace, create a new one.
|
// If no search exists in the workspace, create a new one.
|
||||||
fn deploy_search(
|
fn deploy_search(
|
||||||
workspace: &mut Workspace,
|
workspace: &mut Workspace,
|
||||||
_: &workspace::DeploySearch,
|
_: &workspace::DeploySearch,
|
||||||
cx: &mut ViewContext<Workspace>,
|
cx: &mut ViewContext<Workspace>,
|
||||||
) {
|
) {
|
||||||
let active_search = cx
|
let existing = workspace
|
||||||
.global::<ActiveSearches>()
|
.active_pane()
|
||||||
.0
|
.read(cx)
|
||||||
.get(&workspace.project().downgrade());
|
.items()
|
||||||
let existing = active_search
|
.find_map(|item| item.downcast::<ProjectSearchView>());
|
||||||
.and_then(|active_search| {
|
|
||||||
workspace
|
|
||||||
.items_of_type::<ProjectSearchView>(cx)
|
|
||||||
.filter(|search| &search.downgrade() == active_search)
|
|
||||||
.last()
|
|
||||||
})
|
|
||||||
.or_else(|| workspace.item_of_type::<ProjectSearchView>(cx));
|
|
||||||
Self::existing_or_new_search(workspace, existing, cx)
|
Self::existing_or_new_search(workspace, existing, cx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -984,11 +974,6 @@ impl ProjectSearchView {
|
||||||
existing: Option<View<ProjectSearchView>>,
|
existing: Option<View<ProjectSearchView>>,
|
||||||
cx: &mut ViewContext<Workspace>,
|
cx: &mut ViewContext<Workspace>,
|
||||||
) {
|
) {
|
||||||
// Clean up entries for dropped projects
|
|
||||||
cx.update_global(|state: &mut ActiveSearches, _cx| {
|
|
||||||
state.0.retain(|project, _| project.is_upgradable())
|
|
||||||
});
|
|
||||||
|
|
||||||
let query = workspace.active_item(cx).and_then(|item| {
|
let query = workspace.active_item(cx).and_then(|item| {
|
||||||
let editor = item.act_as::<Editor>(cx)?;
|
let editor = item.act_as::<Editor>(cx)?;
|
||||||
let query = editor.query_suggestion(cx);
|
let query = editor.query_suggestion(cx);
|
||||||
|
@ -1020,6 +1005,7 @@ impl ProjectSearchView {
|
||||||
workspace.add_item(Box::new(view.clone()), cx);
|
workspace.add_item(Box::new(view.clone()), cx);
|
||||||
view
|
view
|
||||||
};
|
};
|
||||||
|
|
||||||
search.update(cx, |search, cx| {
|
search.update(cx, |search, cx| {
|
||||||
if let Some(query) = query {
|
if let Some(query) = query {
|
||||||
search.set_query(&query, cx);
|
search.set_query(&query, cx);
|
||||||
|
@ -3118,6 +3104,7 @@ pub mod tests {
|
||||||
async fn test_deploy_search_with_multiple_panes(cx: &mut TestAppContext) {
|
async fn test_deploy_search_with_multiple_panes(cx: &mut TestAppContext) {
|
||||||
init_test(cx);
|
init_test(cx);
|
||||||
|
|
||||||
|
// Setup 2 panes, both with a file open and one with a project search.
|
||||||
let fs = FakeFs::new(cx.background_executor.clone());
|
let fs = FakeFs::new(cx.background_executor.clone());
|
||||||
fs.insert_tree(
|
fs.insert_tree(
|
||||||
"/dir",
|
"/dir",
|
||||||
|
@ -3176,6 +3163,8 @@ pub mod tests {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
// Add a project search item to the second pane
|
||||||
window
|
window
|
||||||
.update(cx, {
|
.update(cx, {
|
||||||
let search_bar = search_bar.clone();
|
let search_bar = search_bar.clone();
|
||||||
|
@ -3195,6 +3184,8 @@ pub mod tests {
|
||||||
cx.run_until_parked();
|
cx.run_until_parked();
|
||||||
assert_eq!(cx.update(|cx| second_pane.read(cx).items_len()), 2);
|
assert_eq!(cx.update(|cx| second_pane.read(cx).items_len()), 2);
|
||||||
assert_eq!(cx.update(|cx| first_pane.read(cx).items_len()), 1);
|
assert_eq!(cx.update(|cx| first_pane.read(cx).items_len()), 1);
|
||||||
|
|
||||||
|
// Focus the first pane
|
||||||
window
|
window
|
||||||
.update(cx, |workspace, cx| {
|
.update(cx, |workspace, cx| {
|
||||||
assert_eq!(workspace.active_pane(), &second_pane);
|
assert_eq!(workspace.active_pane(), &second_pane);
|
||||||
|
@ -3213,20 +3204,47 @@ pub mod tests {
|
||||||
assert_eq!(second_pane.read(cx).items_len(), 2);
|
assert_eq!(second_pane.read(cx).items_len(), 2);
|
||||||
})
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
// Deploy a new search
|
||||||
cx.dispatch_action(window.into(), DeploySearch);
|
cx.dispatch_action(window.into(), DeploySearch);
|
||||||
|
|
||||||
// We should have same # of items in workspace, the only difference being that
|
// Both panes should now have a project search in them
|
||||||
// the search we've deployed previously should now be focused.
|
|
||||||
window
|
window
|
||||||
.update(cx, |workspace, cx| {
|
.update(cx, |workspace, cx| {
|
||||||
assert_eq!(workspace.active_pane(), &second_pane);
|
assert_eq!(workspace.active_pane(), &first_pane);
|
||||||
second_pane.update(cx, |this, _| {
|
first_pane.update(cx, |this, _| {
|
||||||
assert_eq!(this.active_item_index(), 1);
|
assert_eq!(this.active_item_index(), 1);
|
||||||
assert_eq!(this.items_len(), 2);
|
assert_eq!(this.items_len(), 2);
|
||||||
});
|
});
|
||||||
first_pane.update(cx, |this, cx| {
|
second_pane.update(cx, |this, cx| {
|
||||||
assert!(!cx.focus_handle().contains_focused(cx));
|
assert!(!cx.focus_handle().contains_focused(cx));
|
||||||
assert_eq!(this.items_len(), 1);
|
assert_eq!(this.items_len(), 2);
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// Focus the second pane's non-search item
|
||||||
|
window
|
||||||
|
.update(cx, |_workspace, cx| {
|
||||||
|
second_pane.update(cx, |pane, cx| pane.activate_next_item(true, cx));
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// Deploy a new search
|
||||||
|
cx.dispatch_action(window.into(), DeploySearch);
|
||||||
|
|
||||||
|
// The project search view should now be focused in the second pane
|
||||||
|
// And the number of items should be unchanged.
|
||||||
|
window
|
||||||
|
.update(cx, |_workspace, cx| {
|
||||||
|
second_pane.update(cx, |pane, _cx| {
|
||||||
|
assert!(pane
|
||||||
|
.active_item()
|
||||||
|
.unwrap()
|
||||||
|
.downcast::<ProjectSearchView>()
|
||||||
|
.is_some());
|
||||||
|
|
||||||
|
assert_eq!(pane.items_len(), 2);
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
@ -3236,7 +3254,7 @@ pub mod tests {
|
||||||
cx.update(|cx| {
|
cx.update(|cx| {
|
||||||
let settings = SettingsStore::test(cx);
|
let settings = SettingsStore::test(cx);
|
||||||
cx.set_global(settings);
|
cx.set_global(settings);
|
||||||
cx.set_global(ActiveSearches::default());
|
|
||||||
SemanticIndexSettings::register(cx);
|
SemanticIndexSettings::register(cx);
|
||||||
|
|
||||||
theme::init(theme::LoadThemes::JustBase, cx);
|
theme::init(theme::LoadThemes::JustBase, cx);
|
||||||
|
|
|
@ -99,6 +99,7 @@ actions!(
|
||||||
CloseItemsToTheLeft,
|
CloseItemsToTheLeft,
|
||||||
CloseItemsToTheRight,
|
CloseItemsToTheRight,
|
||||||
GoBack,
|
GoBack,
|
||||||
|
DeploySearch,
|
||||||
GoForward,
|
GoForward,
|
||||||
ReopenClosedItem,
|
ReopenClosedItem,
|
||||||
SplitLeft,
|
SplitLeft,
|
||||||
|
|
|
@ -108,7 +108,6 @@ actions!(
|
||||||
NewCenterTerminal,
|
NewCenterTerminal,
|
||||||
ToggleTerminalFocus,
|
ToggleTerminalFocus,
|
||||||
NewSearch,
|
NewSearch,
|
||||||
DeploySearch,
|
|
||||||
Feedback,
|
Feedback,
|
||||||
Restart,
|
Restart,
|
||||||
Welcome,
|
Welcome,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue