Add basic landing page

This commit is contained in:
Piotr Osiewicz
2023-12-09 12:00:44 +01:00
parent 1bf94f0251
commit b09d2219d0
+129 -70
View File
@@ -14,9 +14,9 @@ use editor::{
};
use gpui::{
actions, div, white, Action, AnyElement, AnyView, AppContext, Context as _, Div, Element,
Entity, EntityId, EventEmitter, FocusableView, InteractiveElement, IntoElement, Model,
ModelContext, ParentElement, PromptLevel, Render, SharedString, Styled, Subscription, Task,
View, ViewContext, VisualContext, WeakModel, WeakView, WindowContext,
Entity, EntityId, EventEmitter, FocusableView, InteractiveElement, IntoElement, KeyContext,
Model, ModelContext, ParentElement, PromptLevel, Render, SharedString, Styled, Subscription,
Task, View, ViewContext, VisualContext, WeakModel, WeakView, WindowContext,
};
use menu::Confirm;
use project::{
@@ -39,7 +39,7 @@ use std::{
use theme::ActiveTheme;
use ui::{
h_stack, v_stack, Button, Clickable, Color, Disableable, Icon, IconButton, IconElement, Label,
Selectable,
LabelCommon, LabelSize, Selectable,
};
use util::{paths::PathMatcher, ResultExt as _};
use workspace::{
@@ -330,10 +330,30 @@ impl Render for ProjectSearchView {
.size_full()
.child(self.results_editor.clone())
} else {
div()
let has_no_results = self.model.read(cx).no_results.unwrap_or(false);
let middle_text = if has_no_results {
div()
.items_center()
.max_w_96()
.child(Label::new("No results for a given query"))
} else {
div()
.items_center()
.max_w_96()
.child(Label::new(self.landing_text_minor()).size(LabelSize::Small))
};
v_stack().flex_1().size_full().justify_center().child(
h_stack()
.size_full()
.justify_center()
.child(h_stack().flex_1())
.child(middle_text)
.child(h_stack().flex_1()),
)
}
}
}
// impl Entity for ProjectSearchView {
// type Event = ViewEvent;
// }
@@ -441,49 +461,6 @@ impl Render for ProjectSearchView {
// }
// };
// let previous_query_keystrokes =
// cx.binding_for_action(&PreviousHistoryQuery {})
// .map(|binding| {
// binding
// .keystrokes()
// .iter()
// .map(|k| k.to_string())
// .collect::<Vec<_>>()
// });
// let next_query_keystrokes =
// cx.binding_for_action(&NextHistoryQuery {}).map(|binding| {
// binding
// .keystrokes()
// .iter()
// .map(|k| k.to_string())
// .collect::<Vec<_>>()
// });
// let new_placeholder_text = match (previous_query_keystrokes, next_query_keystrokes) {
// (Some(previous_query_keystrokes), Some(next_query_keystrokes)) => {
// format!(
// "Search ({}/{} for previous/next query)",
// previous_query_keystrokes.join(" "),
// next_query_keystrokes.join(" ")
// )
// }
// (None, Some(next_query_keystrokes)) => {
// format!(
// "Search ({} for next query)",
// next_query_keystrokes.join(" ")
// )
// }
// (Some(previous_query_keystrokes), None) => {
// format!(
// "Search ({} for previous query)",
// previous_query_keystrokes.join(" ")
// )
// }
// (None, None) => String::new(),
// };
// self.query_editor.update(cx, |editor, cx| {
// editor.set_placeholder_text(new_placeholder_text, cx);
// });
// MouseEventHandler::new::<Status, _>(0, cx, |_, _| {
// Flex::column()
// .with_child(Flex::column().contained().flex(1., true))
@@ -1355,6 +1332,12 @@ impl ProjectSearchView {
});
}
}
fn landing_text_minor(&self) -> SharedString {
match self.current_mode {
SearchMode::Text | SearchMode::Regex => "Include/exclude specific paths with the filter option. Matching exact word and/or casing is available too.".into(),
SearchMode::Semantic => ".Simply explain the code you are looking to find. ex. 'prompt user for permissions to index their project'".into()
}
}
}
impl Default for ProjectSearchBar {
@@ -1680,6 +1663,47 @@ impl ProjectSearchBar {
});
}
}
fn new_placeholder_text(&self, cx: &mut ViewContext<Self>) -> Option<String> {
let previous_query_keystrokes = cx
.bindings_for_action(&PreviousHistoryQuery {})
.into_iter()
.next()
.map(|binding| {
binding
.keystrokes()
.iter()
.map(|k| k.to_string())
.collect::<Vec<_>>()
});
let next_query_keystrokes = cx
.bindings_for_action(&NextHistoryQuery {})
.into_iter()
.next()
.map(|binding| {
binding
.keystrokes()
.iter()
.map(|k| k.to_string())
.collect::<Vec<_>>()
});
let new_placeholder_text = match (previous_query_keystrokes, next_query_keystrokes) {
(Some(previous_query_keystrokes), Some(next_query_keystrokes)) => Some(format!(
"Search ({}/{} for previous/next query)",
previous_query_keystrokes.join(" "),
next_query_keystrokes.join(" ")
)),
(None, Some(next_query_keystrokes)) => Some(format!(
"Search ({} for next query)",
next_query_keystrokes.join(" ")
)),
(Some(previous_query_keystrokes), None) => Some(format!(
"Search ({} for previous query)",
previous_query_keystrokes.join(" ")
)),
(None, None) => None,
};
new_placeholder_text
}
}
impl Render for ProjectSearchBar {
@@ -1689,7 +1713,17 @@ impl Render for ProjectSearchBar {
let Some(search) = self.active_project_search.clone() else {
return div();
};
let mut key_context = KeyContext::default();
key_context.add("ProjectSearchBar");
if let Some(placeholder_text) = self.new_placeholder_text(cx) {
search.update(cx, |search, cx| {
search.query_editor.update(cx, |this, cx| {
this.set_placeholder_text(placeholder_text, cx)
})
});
}
let search = search.read(cx);
let query_column = v_stack()
.flex_1()
.child(
@@ -1714,6 +1748,10 @@ impl Render for ProjectSearchBar {
.on_action(cx.listener(|this, action: &ActivateRegexMode, cx| {
this.activate_search_mode(SearchMode::Regex, cx)
}))
.on_action(
cx.listener(|this, action, cx| this.previous_history_query(action, cx)),
)
.on_action(cx.listener(|this, action, cx| this.next_history_query(action, cx)))
.child(IconElement::new(Icon::MagnifyingGlass))
.child(search.query_editor.clone())
.child(
@@ -1740,34 +1778,54 @@ impl Render for ProjectSearchBar {
.when(search.filters_enabled, |this| {
this.child(
h_stack()
.child(search.included_files_editor.clone())
.child(search.excluded_files_editor.clone()),
.mt_2()
.flex_1()
.justify_between()
.child(
h_stack()
.flex_1()
.border_1()
.mr_2()
.child(search.included_files_editor.clone()),
)
.child(
h_stack()
.flex_1()
.border_1()
.ml_2()
.child(search.excluded_files_editor.clone()),
),
)
});
let mode_column = h_stack()
.child(
h_stack()
.child(
Button::new("project-search-text-button", "Text")
.selected(search.current_mode == SearchMode::Text)
.on_click(|_, cx| cx.dispatch_action(ActivateTextMode.boxed_clone())),
)
.child(
Button::new("project-search-regex-button", "Regex")
.selected(search.current_mode == SearchMode::Regex)
.on_click(|_, cx| cx.dispatch_action(ActivateRegexMode.boxed_clone())),
let mode_column = v_stack().items_start().justify_start().child(
h_stack()
.child(
h_stack()
.child(
Button::new("project-search-text-button", "Text")
.selected(search.current_mode == SearchMode::Text)
.on_click(|_, cx| {
cx.dispatch_action(ActivateTextMode.boxed_clone())
}),
)
.child(
Button::new("project-search-regex-button", "Regex")
.selected(search.current_mode == SearchMode::Regex)
.on_click(|_, cx| {
cx.dispatch_action(ActivateRegexMode.boxed_clone())
}),
),
)
.child(
IconButton::new("project-search-toggle-replace", Icon::Replace).on_click(
|_, cx| {
cx.dispatch_action(ToggleReplace.boxed_clone());
},
),
)
.child(
IconButton::new("project-search-toggle-replace", Icon::Replace).on_click(
|_, cx| {
cx.dispatch_action(ToggleReplace.boxed_clone());
},
),
);
);
let replace_column = if search.replace_enabled {
h_stack()
.bg(white())
.p_1()
.flex_1()
.border_2()
@@ -1811,6 +1869,7 @@ impl Render for ProjectSearchBar {
.on_click(|_, cx| cx.dispatch_action(SelectNextMatch.boxed_clone())),
]);
h_stack()
.key_context(key_context)
.size_full()
.p_1()
.m_2()