commit d85c6043b700783d825f6e5971f976e198fde112
parent 8e0e42a1f343f1c3cf87292e6d5d18bd3eea7dda
Author: William Casarin <jb55@jb55.com>
Date: Fri, 7 Mar 2025 16:01:55 -0800
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>
Diffstat:
5 files changed, 41 insertions(+), 6 deletions(-)
diff --git a/crates/notedeck_columns/src/nav.rs b/crates/notedeck_columns/src/nav.rs
@@ -18,7 +18,7 @@ use crate::{
edit_deck::{EditDeckResponse, EditDeckView},
note::{PostAction, PostType},
profile::EditProfileView,
- search::SearchView,
+ search::{FocusState, SearchView},
support::SupportView,
RelayView, View,
},
@@ -403,9 +403,23 @@ fn render_nav_body(
Route::Search => {
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 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(
ctx.ndb,
&txn,
diff --git a/crates/notedeck_columns/src/route.rs b/crates/notedeck_columns/src/route.rs
@@ -25,7 +25,6 @@ pub enum Route {
EditProfile(Pubkey),
Support,
NewDeck,
- /// Search screen
Search,
EditDeck(usize),
}
diff --git a/crates/notedeck_columns/src/ui/search/mod.rs b/crates/notedeck_columns/src/ui/search/mod.rs
@@ -12,7 +12,7 @@ use tracing::{error, info, warn};
mod state;
-pub use state::{SearchQueryState, SearchState};
+pub use state::{FocusState, SearchQueryState, SearchState};
pub struct SearchView<'a> {
query: &'a mut SearchQueryState,
@@ -57,7 +57,7 @@ impl<'a> SearchView<'a> {
}
match self.query.state {
- SearchState::New => None,
+ SearchState::New | SearchState::Navigating => None,
SearchState::Searched | 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
//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],
TextEdit::singleline(&mut query.string)
.hint_text(RichText::new("Search notes...").weak())
@@ -173,6 +173,11 @@ fn search_box(query: &mut SearchQueryState, ui: &mut egui::Ui) -> bool {
.frame(false),
);
+ if query.focus_state == FocusState::ShouldRequestFocus {
+ response.request_focus();
+ query.focus_state = FocusState::RequestedFocus;
+ }
+
let after_len = query.string.len();
let changed = before_len != after_len;
diff --git a/crates/notedeck_columns/src/ui/search/state.rs b/crates/notedeck_columns/src/ui/search/state.rs
@@ -6,9 +6,22 @@ use std::time::Duration;
pub enum SearchState {
Typing,
Searched,
+ Navigating,
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
#[derive(Debug)]
pub struct SearchQueryState {
@@ -20,6 +33,10 @@ pub struct SearchQueryState {
/// again next frames
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
pub debouncer: Debouncer,
@@ -39,6 +56,7 @@ impl SearchQueryState {
string: "".to_string(),
state: SearchState::New,
notes: TimelineTab::default(),
+ focus_state: FocusState::Navigating,
debouncer: Debouncer::new(Duration::from_millis(200)),
}
}
diff --git a/crates/notedeck_columns/src/ui/side_panel.rs b/crates/notedeck_columns/src/ui/side_panel.rs
@@ -324,7 +324,6 @@ impl<'a> DesktopSidePanel<'a> {
}
SidePanelAction::Search => {
// TODO
- info!("Clicked search button");
if router.top() == &Route::Search {
router.go_back();
} else {