mirror of
https://github.com/zed-industries/zed.git
synced 2024-11-08 07:35:01 +03:00
Scroll project search results to the top (#8329)
Scroll project search results to the top after every new search. Release Notes: - Fixed autoscrolling of the project search results ([8237](https://github.com/zed-industries/zed/issues/8237))
This commit is contained in:
parent
d6492d091d
commit
aeed9d0d8b
@ -7,16 +7,18 @@ use crate::{
|
|||||||
use anyhow::{Context as _, Result};
|
use anyhow::{Context as _, Result};
|
||||||
use collections::HashMap;
|
use collections::HashMap;
|
||||||
use editor::{
|
use editor::{
|
||||||
actions::SelectAll, items::active_match_index, scroll::Autoscroll, Anchor, Editor, EditorEvent,
|
actions::SelectAll,
|
||||||
MultiBuffer, MAX_TAB_TITLE_LEN,
|
items::active_match_index,
|
||||||
|
scroll::{Autoscroll, Axis},
|
||||||
|
Anchor, Editor, EditorEvent, MultiBuffer, MAX_TAB_TITLE_LEN,
|
||||||
};
|
};
|
||||||
use editor::{EditorElement, EditorStyle};
|
use editor::{EditorElement, EditorStyle};
|
||||||
use gpui::{
|
use gpui::{
|
||||||
actions, div, Action, AnyElement, AnyView, AppContext, Context as _, Element, EntityId,
|
actions, div, Action, AnyElement, AnyView, AppContext, Context as _, Element, EntityId,
|
||||||
EventEmitter, FocusHandle, FocusableView, FontStyle, FontWeight, Global, Hsla,
|
EventEmitter, FocusHandle, FocusableView, FontStyle, FontWeight, Global, Hsla,
|
||||||
InteractiveElement, IntoElement, KeyContext, Model, ModelContext, ParentElement, PromptLevel,
|
InteractiveElement, IntoElement, KeyContext, Model, ModelContext, ParentElement, Point,
|
||||||
Render, SharedString, Styled, Subscription, Task, TextStyle, View, ViewContext, VisualContext,
|
PromptLevel, Render, SharedString, Styled, Subscription, Task, TextStyle, View, ViewContext,
|
||||||
WeakModel, WeakView, WhiteSpace, WindowContext,
|
VisualContext, WeakModel, WeakView, WhiteSpace, WindowContext,
|
||||||
};
|
};
|
||||||
use menu::Confirm;
|
use menu::Confirm;
|
||||||
use project::{
|
use project::{
|
||||||
@ -1302,6 +1304,7 @@ impl ProjectSearchView {
|
|||||||
editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
|
editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
|
||||||
s.select_ranges(range_to_select)
|
s.select_ranges(range_to_select)
|
||||||
});
|
});
|
||||||
|
editor.scroll(Point::default(), Some(Axis::Vertical), cx);
|
||||||
}
|
}
|
||||||
editor.highlight_background::<Self>(
|
editor.highlight_background::<Self>(
|
||||||
match_ranges,
|
match_ranges,
|
||||||
@ -2094,11 +2097,12 @@ fn register_workspace_action_for_present_search<A: Action>(
|
|||||||
pub mod tests {
|
pub mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use editor::DisplayPoint;
|
use editor::DisplayPoint;
|
||||||
use gpui::{Action, TestAppContext};
|
use gpui::{Action, TestAppContext, WindowHandle};
|
||||||
use project::FakeFs;
|
use project::FakeFs;
|
||||||
use semantic_index::semantic_index_settings::SemanticIndexSettings;
|
use semantic_index::semantic_index_settings::SemanticIndexSettings;
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
use settings::{Settings, SettingsStore};
|
use settings::{Settings, SettingsStore};
|
||||||
|
use std::sync::Arc;
|
||||||
use workspace::DeploySearch;
|
use workspace::DeploySearch;
|
||||||
|
|
||||||
#[gpui::test]
|
#[gpui::test]
|
||||||
@ -2120,15 +2124,7 @@ pub mod tests {
|
|||||||
let search = cx.new_model(|cx| ProjectSearch::new(project, cx));
|
let search = cx.new_model(|cx| ProjectSearch::new(project, cx));
|
||||||
let search_view = cx.add_window(|cx| ProjectSearchView::new(search.clone(), cx, None));
|
let search_view = cx.add_window(|cx| ProjectSearchView::new(search.clone(), cx, None));
|
||||||
|
|
||||||
search_view
|
perform_search(search_view, "TWO", cx);
|
||||||
.update(cx, |search_view, cx| {
|
|
||||||
search_view
|
|
||||||
.query_editor
|
|
||||||
.update(cx, |query_editor, cx| query_editor.set_text("TWO", cx));
|
|
||||||
search_view.search(cx);
|
|
||||||
})
|
|
||||||
.unwrap();
|
|
||||||
cx.background_executor.run_until_parked();
|
|
||||||
search_view.update(cx, |search_view, cx| {
|
search_view.update(cx, |search_view, cx| {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
search_view
|
search_view
|
||||||
@ -3377,7 +3373,78 @@ pub mod tests {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn init_test(cx: &mut TestAppContext) {
|
#[gpui::test]
|
||||||
|
async fn test_scroll_search_results_to_top(cx: &mut TestAppContext) {
|
||||||
|
init_test(cx);
|
||||||
|
|
||||||
|
// We need many lines in the search results to be able to scroll the window
|
||||||
|
let fs = FakeFs::new(cx.background_executor.clone());
|
||||||
|
fs.insert_tree(
|
||||||
|
"/dir",
|
||||||
|
json!({
|
||||||
|
"1.txt": "\n\n\n\n\n A \n\n\n\n\n",
|
||||||
|
"2.txt": "\n\n\n\n\n A \n\n\n\n\n",
|
||||||
|
"3.rs": "\n\n\n\n\n A \n\n\n\n\n",
|
||||||
|
"4.rs": "\n\n\n\n\n A \n\n\n\n\n",
|
||||||
|
"5.rs": "\n\n\n\n\n A \n\n\n\n\n",
|
||||||
|
"6.rs": "\n\n\n\n\n A \n\n\n\n\n",
|
||||||
|
"7.rs": "\n\n\n\n\n A \n\n\n\n\n",
|
||||||
|
"8.rs": "\n\n\n\n\n A \n\n\n\n\n",
|
||||||
|
"9.rs": "\n\n\n\n\n A \n\n\n\n\n",
|
||||||
|
"a.rs": "\n\n\n\n\n A \n\n\n\n\n",
|
||||||
|
"b.rs": "\n\n\n\n\n B \n\n\n\n\n",
|
||||||
|
"c.rs": "\n\n\n\n\n B \n\n\n\n\n",
|
||||||
|
"d.rs": "\n\n\n\n\n B \n\n\n\n\n",
|
||||||
|
"e.rs": "\n\n\n\n\n B \n\n\n\n\n",
|
||||||
|
"f.rs": "\n\n\n\n\n B \n\n\n\n\n",
|
||||||
|
"g.rs": "\n\n\n\n\n B \n\n\n\n\n",
|
||||||
|
"h.rs": "\n\n\n\n\n B \n\n\n\n\n",
|
||||||
|
"i.rs": "\n\n\n\n\n B \n\n\n\n\n",
|
||||||
|
"j.rs": "\n\n\n\n\n B \n\n\n\n\n",
|
||||||
|
"k.rs": "\n\n\n\n\n B \n\n\n\n\n",
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
let project = Project::test(fs.clone(), ["/dir".as_ref()], cx).await;
|
||||||
|
let search = cx.new_model(|cx| ProjectSearch::new(project, cx));
|
||||||
|
let search_view = cx.add_window(|cx| ProjectSearchView::new(search.clone(), cx, None));
|
||||||
|
|
||||||
|
// First search
|
||||||
|
perform_search(search_view.clone(), "A", cx);
|
||||||
|
search_view
|
||||||
|
.update(cx, |search_view, cx| {
|
||||||
|
search_view.results_editor.update(cx, |results_editor, cx| {
|
||||||
|
// Results are correct and scrolled to the top
|
||||||
|
assert_eq!(
|
||||||
|
results_editor.display_text(cx).match_indices(" A ").count(),
|
||||||
|
10
|
||||||
|
);
|
||||||
|
assert_eq!(results_editor.scroll_position(cx), Point::default());
|
||||||
|
|
||||||
|
// Scroll results all the way down
|
||||||
|
results_editor.scroll(Point::new(0., f32::MAX), Some(Axis::Vertical), cx);
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.expect("unable to update search view");
|
||||||
|
|
||||||
|
// Second search
|
||||||
|
perform_search(search_view.clone(), "B", cx);
|
||||||
|
search_view
|
||||||
|
.update(cx, |search_view, cx| {
|
||||||
|
search_view.results_editor.update(cx, |results_editor, cx| {
|
||||||
|
// Results are correct...
|
||||||
|
assert_eq!(
|
||||||
|
results_editor.display_text(cx).match_indices(" B ").count(),
|
||||||
|
10
|
||||||
|
);
|
||||||
|
// ...and scrolled back to the top
|
||||||
|
assert_eq!(results_editor.scroll_position(cx), Point::default());
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.expect("unable to update search view");
|
||||||
|
}
|
||||||
|
|
||||||
|
fn init_test(cx: &mut TestAppContext) {
|
||||||
cx.update(|cx| {
|
cx.update(|cx| {
|
||||||
let settings = SettingsStore::test(cx);
|
let settings = SettingsStore::test(cx);
|
||||||
cx.set_global(settings);
|
cx.set_global(settings);
|
||||||
@ -3394,4 +3461,20 @@ pub mod tests {
|
|||||||
super::init(cx);
|
super::init(cx);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn perform_search(
|
||||||
|
search_view: WindowHandle<ProjectSearchView>,
|
||||||
|
text: impl Into<Arc<str>>,
|
||||||
|
cx: &mut TestAppContext,
|
||||||
|
) {
|
||||||
|
search_view
|
||||||
|
.update(cx, |search_view, cx| {
|
||||||
|
search_view
|
||||||
|
.query_editor
|
||||||
|
.update(cx, |query_editor, cx| query_editor.set_text(text, cx));
|
||||||
|
search_view.search(cx);
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
cx.background_executor.run_until_parked();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user