diff --git a/hammond-gtk/src/app.rs b/hammond-gtk/src/app.rs index 53ca4e2..1c214b2 100644 --- a/hammond-gtk/src/app.rs +++ b/hammond-gtk/src/app.rs @@ -5,13 +5,14 @@ use gtk::prelude::*; use gio::{ActionMapExt, ApplicationExt, ApplicationExtManual, SimpleActionExt}; use hammond_data::utils::checkup; -use hammond_data::Source; +use hammond_data::{Podcast, Source}; use headerbar::Header; use content::Content; use utils; use std::sync::Arc; +use std::time::Duration; use std::sync::mpsc::{channel, Receiver, Sender}; #[derive(Clone, Debug)] @@ -23,7 +24,10 @@ pub enum Action { RefreshShowsView, RefreshWidget, RefreshWidgetIfVis, + ReplaceWidget(Podcast), RefreshWidgetIfSame(i32), + ShowWidgetAnimated, + ShowShowsAnimated, HeaderBarShowTile(String), HeaderBarNormal, HeaderBarHideUpdateIndicator, @@ -132,8 +136,8 @@ impl App { let headerbar = self.header.clone(); let sender = self.sender.clone(); let receiver = self.receiver; - gtk::timeout_add(250, move || { - match receiver.try_recv() { + gtk::idle_add(move || { + match receiver.recv_timeout(Duration::from_millis(10)) { Ok(Action::UpdateSources(source)) => { if let Some(s) = source { utils::refresh_feed(headerbar.clone(), Some(vec![s]), sender.clone()) @@ -146,6 +150,9 @@ impl App { Ok(Action::RefreshWidgetIfSame(id)) => content.update_widget_if_same(id), Ok(Action::RefreshEpisodesView) => content.update_episode_view(), Ok(Action::RefreshEpisodesViewBGR) => content.update_episode_view_if_baground(), + Ok(Action::ReplaceWidget(ref pd)) => content.get_shows().replace_widget(pd), + Ok(Action::ShowWidgetAnimated) => content.get_shows().switch_widget_animated(), + Ok(Action::ShowShowsAnimated) => content.get_shows().switch_podcasts_animated(), Ok(Action::HeaderBarShowTile(title)) => headerbar.switch_to_back(&title), Ok(Action::HeaderBarNormal) => headerbar.switch_to_normal(), Ok(Action::HeaderBarHideUpdateIndicator) => headerbar.hide_update_notification(), diff --git a/hammond-gtk/src/content.rs b/hammond-gtk/src/content.rs index 69754a4..10d3d79 100644 --- a/hammond-gtk/src/content.rs +++ b/hammond-gtk/src/content.rs @@ -26,8 +26,8 @@ pub struct Content { impl Content { pub fn new(sender: Sender) -> Arc { let stack = gtk::Stack::new(); - let episodes = EpisodeStack::new(sender.clone()); - let shows = ShowStack::new(sender.clone()); + let episodes = Arc::new(EpisodeStack::new(sender.clone())); + let shows = Arc::new(ShowStack::new(sender.clone())); stack.add_titled(&episodes.stack, "episodes", "Episodes"); stack.add_titled(&shows.stack, "shows", "Shows"); @@ -92,15 +92,15 @@ pub struct ShowStack { } impl ShowStack { - fn new(sender: Sender) -> Arc { + fn new(sender: Sender) -> ShowStack { let stack = gtk::Stack::new(); - let show = Arc::new(ShowStack { + let show = ShowStack { stack, sender: sender.clone(), - }); + }; - let pop = ShowsPopulated::new(show.clone(), sender.clone()); + let pop = ShowsPopulated::new(sender.clone()); let widget = ShowWidget::default(); let empty = EmptyView::new(); @@ -144,7 +144,7 @@ impl ShowStack { .unwrap(); debug!("Name: {:?}", WidgetExt::get_name(&scrolled_window)); - let pop = ShowsPopulated::new(Arc::new(self.clone()), self.sender.clone()); + let pop = ShowsPopulated::new(self.sender.clone()); // Copy the vertical scrollbar adjustment from the old view into the new one. scrolled_window .get_vadjustment() @@ -174,7 +174,7 @@ impl ShowStack { .unwrap(); debug!("Name: {:?}", WidgetExt::get_name(&old)); - let new = ShowWidget::new(Arc::new(self.clone()), pd, self.sender.clone()); + let new = ShowWidget::new(pd, self.sender.clone()); // Each composite ShowWidget is a gtkBox with the Podcast.id encoded in the gtk::Widget // name. It's a hack since we can't yet subclass GObject easily. let oldid = WidgetExt::get_name(&old); @@ -253,7 +253,7 @@ pub struct EpisodeStack { } impl EpisodeStack { - fn new(sender: Sender) -> Arc { + fn new(sender: Sender) -> EpisodeStack { let episodes = EpisodesView::new(sender.clone()); let empty = EmptyView::new(); let stack = gtk::Stack::new(); @@ -267,7 +267,7 @@ impl EpisodeStack { stack.set_visible_child_name("episodes"); } - Arc::new(EpisodeStack { stack, sender }) + EpisodeStack { stack, sender } } pub fn update(&self) { diff --git a/hammond-gtk/src/views/shows.rs b/hammond-gtk/src/views/shows.rs index df8dc57..3a5b40b 100644 --- a/hammond-gtk/src/views/shows.rs +++ b/hammond-gtk/src/views/shows.rs @@ -6,11 +6,9 @@ use hammond_data::dbqueries; use hammond_data::Podcast; use utils::get_pixbuf_from_path; -use content::ShowStack; use app::Action; use std::sync::mpsc::Sender; -use std::sync::Arc; #[derive(Debug, Clone)] pub struct ShowsPopulated { @@ -35,26 +33,27 @@ impl Default for ShowsPopulated { } impl ShowsPopulated { - pub fn new(show: Arc, sender: Sender) -> ShowsPopulated { + pub fn new(sender: Sender) -> ShowsPopulated { let pop = ShowsPopulated::default(); - pop.init(show, sender); + pop.init(sender); pop } - pub fn init(&self, show: Arc, sender: Sender) { + pub fn init(&self, sender: Sender) { use gtk::WidgetExt; // TODO: handle unwraps. - self.flowbox - .connect_child_activated(clone!(show, sender => move |_, child| { + self.flowbox.connect_child_activated(move |_, child| { // This is such an ugly hack... let id = WidgetExt::get_name(child).unwrap().parse::().unwrap(); let pd = dbqueries::get_podcast_from_id(id).unwrap(); - show.replace_widget(&pd); - sender.send(Action::HeaderBarShowTile(pd.title().into())).unwrap(); - show.switch_widget_animated(); - })); + sender + .send(Action::HeaderBarShowTile(pd.title().into())) + .unwrap(); + sender.send(Action::ReplaceWidget(pd)).unwrap(); + sender.send(Action::ShowWidgetAnimated).unwrap(); + }); // Populate the flowbox with the Podcasts. self.populate_flowbox(); } diff --git a/hammond-gtk/src/widgets/show.rs b/hammond-gtk/src/widgets/show.rs index ca2e850..1b08638 100644 --- a/hammond-gtk/src/widgets/show.rs +++ b/hammond-gtk/src/widgets/show.rs @@ -10,11 +10,9 @@ use hammond_data::utils::{delete_show, replace_extra_spaces}; use widgets::episode::episodes_listbox; use utils::get_pixbuf_from_path; -use content::ShowStack; use app::Action; use std::sync::mpsc::Sender; -use std::sync::Arc; use std::thread; #[derive(Debug, Clone)] @@ -56,19 +54,19 @@ impl Default for ShowWidget { } impl ShowWidget { - pub fn new(shows: Arc, pd: &Podcast, sender: Sender) -> ShowWidget { + pub fn new(pd: &Podcast, sender: Sender) -> ShowWidget { let pdw = ShowWidget::default(); - pdw.init(shows, pd, sender); + pdw.init(pd, sender); pdw } - pub fn init(&self, shows: Arc, pd: &Podcast, sender: Sender) { + pub fn init(&self, pd: &Podcast, sender: Sender) { // Hacky workaround so the pd.id() can be retrieved from the `ShowStack`. WidgetExt::set_name(&self.container, &pd.id().to_string()); self.unsub - .connect_clicked(clone!(shows, pd, sender => move |bttn| { - on_unsub_button_clicked(shows.clone(), &pd, bttn, sender.clone()); + .connect_clicked(clone!(pd, sender => move |bttn| { + on_unsub_button_clicked(&pd, bttn, sender.clone()); })); self.setup_listbox(pd, sender.clone()); @@ -110,12 +108,7 @@ impl ShowWidget { } } -fn on_unsub_button_clicked( - shows: Arc, - pd: &Podcast, - unsub_button: >k::Button, - sender: Sender, -) { +fn on_unsub_button_clicked(pd: &Podcast, unsub_button: >k::Button, sender: Sender) { // hack to get away without properly checking for none. // if pressed twice would panic. unsub_button.hide(); @@ -126,16 +119,16 @@ fn on_unsub_button_clicked( error!("Error: {}", err); } })); - shows.switch_podcasts_animated(); sender.send(Action::HeaderBarNormal).unwrap(); + sender.send(Action::ShowShowsAnimated).unwrap(); // Queue a refresh after the switch to avoid blocking the db. sender.send(Action::RefreshShowsView).unwrap(); sender.send(Action::RefreshEpisodesView).unwrap(); } #[allow(dead_code)] -fn on_played_button_clicked(shows: Arc, pd: &Podcast) { +fn on_played_button_clicked(pd: &Podcast, sender: Sender) { let _ = dbqueries::update_none_to_played_now(pd); - shows.update_widget(); + sender.send(Action::RefreshWidget).unwrap(); }