From c68f07d52200cd684febca316853de05fc23773d Mon Sep 17 00:00:00 2001 From: Gabriel Kaszewski Date: Sun, 15 Mar 2026 20:00:17 +0100 Subject: [PATCH] feat(ui): epoch-based debounce cancels stale search results --- crates/k-launcher-ui/src/app.rs | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/crates/k-launcher-ui/src/app.rs b/crates/k-launcher-ui/src/app.rs index 3ff9654..6c8a686 100644 --- a/crates/k-launcher-ui/src/app.rs +++ b/crates/k-launcher-ui/src/app.rs @@ -27,6 +27,7 @@ pub struct KLauncherApp { selected: usize, cfg: AppearanceCfg, error: Option, + search_epoch: u64, } impl KLauncherApp { @@ -43,6 +44,7 @@ impl KLauncherApp { selected: 0, cfg, error: None, + search_epoch: 0, } } } @@ -50,7 +52,7 @@ impl KLauncherApp { #[derive(Debug, Clone)] pub enum Message { QueryChanged(String), - ResultsReady(Arc>), + ResultsReady(u64, Arc>), KeyPressed(KeyEvent), } @@ -60,14 +62,21 @@ fn update(state: &mut KLauncherApp, message: Message) -> Task { state.error = None; state.query = q.clone(); state.selected = 0; + state.search_epoch += 1; + let epoch = state.search_epoch; let engine = state.engine.clone(); Task::perform( - async move { engine.search(&q).await }, - |results| Message::ResultsReady(Arc::new(results)), + async move { + tokio::time::sleep(std::time::Duration::from_millis(50)).await; + (epoch, engine.search(&q).await) + }, + |(epoch, results)| Message::ResultsReady(epoch, Arc::new(results)), ) } - Message::ResultsReady(results) => { - state.results = results; + Message::ResultsReady(epoch, results) => { + if epoch == state.search_epoch { + state.results = results; + } Task::none() } Message::KeyPressed(event) => {