search: auto-focus search field on navigate
I'm going to add a search changelog on this commit since I forgot to do so previously. Fixes: https://linear.app/damus/issue/DECK-538/auto-focus-search-field-on-search-view Changelog-Added: Added fulltext search ui Signed-off-by: William Casarin <jb55@jb55.com>
This commit is contained in:
@@ -18,7 +18,7 @@ use crate::{
|
|||||||
edit_deck::{EditDeckResponse, EditDeckView},
|
edit_deck::{EditDeckResponse, EditDeckView},
|
||||||
note::{PostAction, PostType},
|
note::{PostAction, PostType},
|
||||||
profile::EditProfileView,
|
profile::EditProfileView,
|
||||||
search::SearchView,
|
search::{FocusState, SearchView},
|
||||||
support::SupportView,
|
support::SupportView,
|
||||||
RelayView, View,
|
RelayView, View,
|
||||||
},
|
},
|
||||||
@@ -403,9 +403,23 @@ fn render_nav_body(
|
|||||||
|
|
||||||
Route::Search => {
|
Route::Search => {
|
||||||
let id = ui.id().with(("search", depth, col));
|
let id = ui.id().with(("search", depth, col));
|
||||||
|
let navigating = app
|
||||||
|
.columns_mut(ctx.accounts)
|
||||||
|
.column(col)
|
||||||
|
.router()
|
||||||
|
.navigating;
|
||||||
let search_buffer = app.view_state.searches.entry(id).or_default();
|
let search_buffer = app.view_state.searches.entry(id).or_default();
|
||||||
let txn = Transaction::new(ctx.ndb).expect("txn");
|
let txn = Transaction::new(ctx.ndb).expect("txn");
|
||||||
|
|
||||||
|
if navigating {
|
||||||
|
search_buffer.focus_state = FocusState::Navigating
|
||||||
|
} else if search_buffer.focus_state == FocusState::Navigating {
|
||||||
|
// we're not navigating but our last search buffer state
|
||||||
|
// says we were navigating. This means that navigating has
|
||||||
|
// stopped. Let's make sure to focus the input field
|
||||||
|
search_buffer.focus_state = FocusState::ShouldRequestFocus;
|
||||||
|
}
|
||||||
|
|
||||||
SearchView::new(
|
SearchView::new(
|
||||||
ctx.ndb,
|
ctx.ndb,
|
||||||
&txn,
|
&txn,
|
||||||
|
|||||||
@@ -25,7 +25,6 @@ pub enum Route {
|
|||||||
EditProfile(Pubkey),
|
EditProfile(Pubkey),
|
||||||
Support,
|
Support,
|
||||||
NewDeck,
|
NewDeck,
|
||||||
/// Search screen
|
|
||||||
Search,
|
Search,
|
||||||
EditDeck(usize),
|
EditDeck(usize),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ use tracing::{error, info, warn};
|
|||||||
|
|
||||||
mod state;
|
mod state;
|
||||||
|
|
||||||
pub use state::{SearchQueryState, SearchState};
|
pub use state::{FocusState, SearchQueryState, SearchState};
|
||||||
|
|
||||||
pub struct SearchView<'a> {
|
pub struct SearchView<'a> {
|
||||||
query: &'a mut SearchQueryState,
|
query: &'a mut SearchQueryState,
|
||||||
@@ -57,7 +57,7 @@ impl<'a> SearchView<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
match self.query.state {
|
match self.query.state {
|
||||||
SearchState::New => None,
|
SearchState::New | SearchState::Navigating => None,
|
||||||
|
|
||||||
SearchState::Searched | SearchState::Typing => {
|
SearchState::Searched | SearchState::Typing => {
|
||||||
if self.query.state == SearchState::Typing {
|
if self.query.state == SearchState::Typing {
|
||||||
@@ -163,7 +163,7 @@ fn search_box(query: &mut SearchQueryState, ui: &mut egui::Ui) -> bool {
|
|||||||
|
|
||||||
// Search input field
|
// Search input field
|
||||||
//let font_size = notedeck::fonts::get_font_size(ui.ctx(), &NotedeckTextStyle::Body);
|
//let font_size = notedeck::fonts::get_font_size(ui.ctx(), &NotedeckTextStyle::Body);
|
||||||
ui.add_sized(
|
let response = ui.add_sized(
|
||||||
[ui.available_width(), search_height],
|
[ui.available_width(), search_height],
|
||||||
TextEdit::singleline(&mut query.string)
|
TextEdit::singleline(&mut query.string)
|
||||||
.hint_text(RichText::new("Search notes...").weak())
|
.hint_text(RichText::new("Search notes...").weak())
|
||||||
@@ -173,6 +173,11 @@ fn search_box(query: &mut SearchQueryState, ui: &mut egui::Ui) -> bool {
|
|||||||
.frame(false),
|
.frame(false),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if query.focus_state == FocusState::ShouldRequestFocus {
|
||||||
|
response.request_focus();
|
||||||
|
query.focus_state = FocusState::RequestedFocus;
|
||||||
|
}
|
||||||
|
|
||||||
let after_len = query.string.len();
|
let after_len = query.string.len();
|
||||||
|
|
||||||
let changed = before_len != after_len;
|
let changed = before_len != after_len;
|
||||||
|
|||||||
@@ -6,9 +6,22 @@ use std::time::Duration;
|
|||||||
pub enum SearchState {
|
pub enum SearchState {
|
||||||
Typing,
|
Typing,
|
||||||
Searched,
|
Searched,
|
||||||
|
Navigating,
|
||||||
New,
|
New,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Eq, PartialEq)]
|
||||||
|
pub enum FocusState {
|
||||||
|
/// Get ready to focus
|
||||||
|
Navigating,
|
||||||
|
|
||||||
|
/// We should request focus when we stop navigating
|
||||||
|
ShouldRequestFocus,
|
||||||
|
|
||||||
|
/// We already focused, we don't need to do that again
|
||||||
|
RequestedFocus,
|
||||||
|
}
|
||||||
|
|
||||||
/// Search query state that exists between frames
|
/// Search query state that exists between frames
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct SearchQueryState {
|
pub struct SearchQueryState {
|
||||||
@@ -20,6 +33,10 @@ pub struct SearchQueryState {
|
|||||||
/// again next frames
|
/// again next frames
|
||||||
pub state: SearchState,
|
pub state: SearchState,
|
||||||
|
|
||||||
|
/// A bit of context to know if we're navigating to the view. We
|
||||||
|
/// can use this to know when to request focus on the textedit
|
||||||
|
pub focus_state: FocusState,
|
||||||
|
|
||||||
/// When was the input updated? We use this to debounce searches
|
/// When was the input updated? We use this to debounce searches
|
||||||
pub debouncer: Debouncer,
|
pub debouncer: Debouncer,
|
||||||
|
|
||||||
@@ -39,6 +56,7 @@ impl SearchQueryState {
|
|||||||
string: "".to_string(),
|
string: "".to_string(),
|
||||||
state: SearchState::New,
|
state: SearchState::New,
|
||||||
notes: TimelineTab::default(),
|
notes: TimelineTab::default(),
|
||||||
|
focus_state: FocusState::Navigating,
|
||||||
debouncer: Debouncer::new(Duration::from_millis(200)),
|
debouncer: Debouncer::new(Duration::from_millis(200)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -324,7 +324,6 @@ impl<'a> DesktopSidePanel<'a> {
|
|||||||
}
|
}
|
||||||
SidePanelAction::Search => {
|
SidePanelAction::Search => {
|
||||||
// TODO
|
// TODO
|
||||||
info!("Clicked search button");
|
|
||||||
if router.top() == &Route::Search {
|
if router.top() == &Route::Search {
|
||||||
router.go_back();
|
router.go_back();
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
Reference in New Issue
Block a user