From e060047db6369d98857dd7055d5b68efbe36bccf Mon Sep 17 00:00:00 2001 From: Alexandre Trendel Date: Tue, 24 Nov 2020 13:54:33 +0100 Subject: [PATCH] search debouncer --- src/app/components/details/details.css | 4 +++ src/app/components/details/details.rs | 5 +++- src/app/components/details/details.ui | 18 ++++++------ src/app/components/search/search.rs | 39 ++++++++++++++++++++++++-- src/app/state/browser_state.rs | 4 +-- src/app/state/screen_states.rs | 7 ++--- 6 files changed, 58 insertions(+), 19 deletions(-) diff --git a/src/app/components/details/details.css b/src/app/components/details/details.css index c70fcc0b..d56d4244 100644 --- a/src/app/components/details/details.css +++ b/src/app/components/details/details.css @@ -10,3 +10,7 @@ .details .details__album-art { border-radius: 8px; } + +.details .details__like { + font-size: 18px; +} diff --git a/src/app/components/details/details.rs b/src/app/components/details/details.rs index 3d7819f8..b4e071b5 100644 --- a/src/app/components/details/details.rs +++ b/src/app/components/details/details.rs @@ -19,7 +19,8 @@ struct DetailsWidget { pub artist_label: gtk::Label, pub album_label: gtk::Label, pub album_tracks: gtk::ListBox, - pub album_art: gtk::Image + pub album_art: gtk::Image, + pub like_button: gtk::Button } impl DetailsWidget { @@ -52,9 +53,11 @@ impl Details { let album = &info.title[..]; let artist = &info.artist[..]; let art = info.art.clone(); + let is_liked = false; self.widget.album_label.set_label(album); self.widget.artist_label.set_label(artist); + self.widget.like_button.set_label(if is_liked { "♥" } else { "♡" }); let image = self.widget.album_art.clone(); self.worker.send_task(async move { diff --git a/src/app/components/details/details.ui b/src/app/components/details/details.ui index 4615301e..6fd15de5 100644 --- a/src/app/components/details/details.ui +++ b/src/app/components/details/details.ui @@ -95,20 +95,20 @@ - + + + 35 + 35 True True True center center - none - - - True - False - gtk-apply - - + half + False diff --git a/src/app/components/search/search.rs b/src/app/components/search/search.rs index 5e88f8d5..c49fd4a7 100644 --- a/src/app/components/search/search.rs +++ b/src/app/components/search/search.rs @@ -1,4 +1,5 @@ use std::rc::Rc; +use std::cell::Cell; use gtk::prelude::*; use gio::prelude::*; use gladis::Gladis; @@ -7,6 +8,28 @@ use crate::app::dispatch::Worker; use crate::app::components::{Component, EventListener, Album, gtypes::AlbumModel}; use super::SearchResultsModel; +struct Debouncer(Rc>>); + +impl Debouncer { + + fn new() -> Self { + Self(Rc::new(Cell::new(None))) + } + + fn debounce(&self, interval_ms: u32, f: F) { + let source_clone = Rc::downgrade(&self.0); + let new_source = glib::timeout_add_local(interval_ms, move || { + f(); + if let Some(cell) = source_clone.upgrade() { + cell.set(None); + } + glib::Continue(false) + }); + if let Some(previous_source) = self.0.replace(Some(new_source)) { + glib::source_remove(previous_source); + } + } +} #[derive(Gladis, Clone)] struct SearchResultsWidget { @@ -25,7 +48,8 @@ impl SearchResultsWidget { pub struct SearchResults { widget: SearchResultsWidget, model: Rc, - album_results_model: gio::ListStore + album_results_model: gio::ListStore, + debouncer: Debouncer } impl SearchResults { @@ -53,7 +77,7 @@ impl SearchResults { child.upcast::() }); - Self { widget, model, album_results_model } + Self { widget, model, album_results_model, debouncer: Debouncer::new() } } fn update_results(&self) { @@ -71,7 +95,16 @@ impl SearchResults { } fn update_search_query(&self) { - self.model.fetch_results(); + + { + let model = Rc::downgrade(&self.model); + self.debouncer.debounce(600, move || { + if let Some(model) = model.upgrade() { + model.fetch_results(); + } + }); + } + if let Some(query) = self.model.get_query() { let formatted = format!("Search results for « {} »", *query); self.widget.results_label.set_label(&formatted[..]); diff --git a/src/app/state/browser_state.rs b/src/app/state/browser_state.rs index 7854cc7d..96b78886 100644 --- a/src/app/state/browser_state.rs +++ b/src/app/state/browser_state.rs @@ -188,7 +188,7 @@ impl UpdatableState for BrowserState { let navigation = &mut self.navigation; let screen_state = navigation.screen_state(Self::match_search); - println!("{:?}", screen_state); + let mut events = match screen_state { ScreenState::Current => vec![], ScreenState::Present => { @@ -196,7 +196,7 @@ impl UpdatableState for BrowserState { vec![BrowserEvent::NavigationPoppedTo(ScreenName::Search)] }, ScreenState::NotPresent => { - navigation.push(BrowserScreen::Search(SearchState::new(query.to_owned()))); + navigation.push(BrowserScreen::Search(Default::default())); vec![BrowserEvent::NavigationPushed(ScreenName::Search)] } }; diff --git a/src/app/state/screen_states.rs b/src/app/state/screen_states.rs index 9e495734..38245ab3 100644 --- a/src/app/state/screen_states.rs +++ b/src/app/state/screen_states.rs @@ -70,10 +70,9 @@ pub struct SearchState { pub album_results: Vec } -impl SearchState { - - pub fn new(query: String) -> Self { - Self { query, album_results: vec![] } +impl Default for SearchState { + fn default() -> Self { + Self { query: "".to_owned(), album_results: vec![] } } }