Async search so UI doesn't lag when typing
This commit is contained in:
parent
6fd3b4eba1
commit
f70e4c3006
@ -219,28 +219,88 @@ impl GtkLauncherUI {
|
|||||||
// Set initial focus to search input so user can start typing immediately
|
// Set initial focus to search input so user can start typing immediately
|
||||||
search_input.grab_focus();
|
search_input.grab_focus();
|
||||||
|
|
||||||
// Set up event handlers directly
|
// Set up async search handlers to prevent UI blocking
|
||||||
let launcher_for_search = launcher.clone();
|
let launcher_for_search = launcher.clone();
|
||||||
let list_store_for_search = list_store.clone();
|
let list_store_for_search = list_store.clone();
|
||||||
|
let selection_for_search = selection.clone();
|
||||||
|
|
||||||
|
// Add debouncing to avoid excessive searches with generation counter
|
||||||
|
let search_generation = Rc::new(RefCell::new(0u64));
|
||||||
|
|
||||||
search_input.connect_changed(move |entry| {
|
search_input.connect_changed(move |entry| {
|
||||||
let query = entry.text().to_string();
|
let query = entry.text().to_string();
|
||||||
let mut launcher_ref = launcher_for_search.borrow_mut();
|
|
||||||
let results = if query.trim().is_empty() {
|
// Increment generation to cancel any pending searches
|
||||||
launcher_ref.get_default_results()
|
*search_generation.borrow_mut() += 1;
|
||||||
|
|
||||||
|
if query.trim().is_empty() {
|
||||||
|
// Handle empty query synchronously for immediate response
|
||||||
|
let mut launcher_ref = launcher_for_search.borrow_mut();
|
||||||
|
let results = launcher_ref.get_default_results();
|
||||||
|
|
||||||
|
list_store_for_search.remove_all();
|
||||||
|
for entry in results.iter() {
|
||||||
|
let item_obj = LauncherItemObject::new(
|
||||||
|
entry.title(),
|
||||||
|
entry.description(),
|
||||||
|
entry.icon(),
|
||||||
|
entry.id(),
|
||||||
|
);
|
||||||
|
list_store_for_search.append(&item_obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Select first item
|
||||||
|
if list_store_for_search.n_items() > 0 {
|
||||||
|
selection_for_search.set_selected(0);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
launcher_ref.search(&query)
|
// Debounced async search for non-empty queries
|
||||||
};
|
let launcher_clone = launcher_for_search.clone();
|
||||||
|
let list_store_clone = list_store_for_search.clone();
|
||||||
// Update the list store
|
let selection_clone = selection_for_search.clone();
|
||||||
list_store_for_search.remove_all();
|
|
||||||
for entry in results.iter() {
|
let current_generation = *search_generation.borrow();
|
||||||
let item_obj = LauncherItemObject::new(
|
let generation_check = search_generation.clone();
|
||||||
entry.title(),
|
let _timeout_id = glib::timeout_add_local(std::time::Duration::from_millis(150), move || {
|
||||||
entry.description(),
|
// Check if this search is still the current one
|
||||||
entry.icon(),
|
if *generation_check.borrow() != current_generation {
|
||||||
entry.id(),
|
return glib::ControlFlow::Break; // This search was superseded
|
||||||
);
|
}
|
||||||
list_store_for_search.append(&item_obj);
|
|
||||||
|
let launcher_clone = launcher_clone.clone();
|
||||||
|
let list_store_clone = list_store_clone.clone();
|
||||||
|
let selection_clone = selection_clone.clone();
|
||||||
|
let query = query.clone();
|
||||||
|
|
||||||
|
glib::spawn_future_local(async move {
|
||||||
|
// Run search and collect items immediately
|
||||||
|
let items: Vec<LauncherItemObject> = {
|
||||||
|
let mut launcher_ref = launcher_clone.borrow_mut();
|
||||||
|
let results = launcher_ref.search(&query);
|
||||||
|
results.iter().map(|entry| {
|
||||||
|
LauncherItemObject::new(
|
||||||
|
entry.title(),
|
||||||
|
entry.description(),
|
||||||
|
entry.icon(),
|
||||||
|
entry.id(),
|
||||||
|
)
|
||||||
|
}).collect()
|
||||||
|
};
|
||||||
|
|
||||||
|
// Update UI on main thread
|
||||||
|
list_store_clone.remove_all();
|
||||||
|
for item_obj in items {
|
||||||
|
list_store_clone.append(&item_obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Select first item
|
||||||
|
if list_store_clone.n_items() > 0 {
|
||||||
|
selection_clone.set_selected(0);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
glib::ControlFlow::Break
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user