From 82988b60117027583010c8473ce3f31c2c19eacc Mon Sep 17 00:00:00 2001 From: Jordan Petridis Date: Fri, 9 Mar 2018 14:53:13 +0200 Subject: [PATCH] Implement in-app notifications as App wide actions. At first I tried creating custom InAppNotifications and send them to the main loop to be added. That does not work sicne gtk widgets are not thread safe. For now we can try having Action messages that create them on demand. As oppose to create first then pass them. --- hammond-gtk/resources/gtk/inapp_notif.ui | 2 +- hammond-gtk/resources/resources.xml | 1 + hammond-gtk/src/app.rs | 21 ++++++++++++++++++++- hammond-gtk/src/appnotif.rs | 13 ++++++++----- hammond-gtk/src/widgets/mod.rs | 1 + hammond-gtk/src/widgets/show.rs | 16 +++------------- 6 files changed, 34 insertions(+), 20 deletions(-) diff --git a/hammond-gtk/resources/gtk/inapp_notif.ui b/hammond-gtk/resources/gtk/inapp_notif.ui index c14a5e9..443be4a 100644 --- a/hammond-gtk/resources/gtk/inapp_notif.ui +++ b/hammond-gtk/resources/gtk/inapp_notif.ui @@ -2,7 +2,7 @@ - + True False center diff --git a/hammond-gtk/resources/resources.xml b/hammond-gtk/resources/resources.xml index 366f71c..51b44cf 100644 --- a/hammond-gtk/resources/resources.xml +++ b/hammond-gtk/resources/resources.xml @@ -9,6 +9,7 @@ gtk/shows_view.ui gtk/shows_child.ui gtk/headerbar.ui + gtk/inapp_notif.ui gtk/style.css diff --git a/hammond-gtk/src/app.rs b/hammond-gtk/src/app.rs index 215ecf9..0f48e97 100644 --- a/hammond-gtk/src/app.rs +++ b/hammond-gtk/src/app.rs @@ -8,9 +8,11 @@ use gtk::prelude::*; use hammond_data::{Podcast, Source}; use hammond_data::utils::checkup; +use appnotif::*; use headerbar::Header; use stacks::Content; use utils; +use widgets::mark_all_watched; use std::sync::Arc; use std::sync::mpsc::{channel, Receiver, Sender}; @@ -33,6 +35,7 @@ pub enum Action { HeaderBarNormal, HeaderBarShowUpdateIndicator, HeaderBarHideUpdateIndicator, + MarkAllPlayerNotification(Arc), } #[derive(Debug)] @@ -92,7 +95,7 @@ impl App { } } - pub fn setup_timed_callbacks(&self) { + fn setup_timed_callbacks(&self) { let sender = self.sender.clone(); // Update the feeds right after the Application is initialized. gtk::timeout_add_seconds(2, move || { @@ -128,6 +131,7 @@ impl App { let content = self.content.clone(); let headerbar = self.header.clone(); let sender = self.sender.clone(); + let overlay = self.overlay.clone(); let receiver = self.receiver; gtk::idle_add(move || { match receiver.recv_timeout(Duration::from_millis(10)) { @@ -157,6 +161,21 @@ impl App { Ok(Action::HeaderBarNormal) => headerbar.switch_to_normal(), Ok(Action::HeaderBarShowUpdateIndicator) => headerbar.show_update_notification(), Ok(Action::HeaderBarHideUpdateIndicator) => headerbar.hide_update_notification(), + Ok(Action::MarkAllPlayerNotification(pd)) => { + let sender = sender.clone(); + let callback = clone!(sender => move || { + if let Err(err) = mark_all_watched(&pd, sender.clone()) { + error!("Something went horribly wrong with the notif callback: {}", err); + } + glib::Continue(false) + }); + let text = "All episodes where marked as watched."; + + let sender = sender.clone(); + let notif = InAppNotification::new(text.into(), callback, sender); + overlay.add_overlay(¬if.overlay); + overlay.show_all(); + } Err(_) => (), } diff --git a/hammond-gtk/src/appnotif.rs b/hammond-gtk/src/appnotif.rs index 593688c..879f2f2 100644 --- a/hammond-gtk/src/appnotif.rs +++ b/hammond-gtk/src/appnotif.rs @@ -10,6 +10,7 @@ use std::sync::mpsc::Sender; #[derive(Debug, Clone)] pub struct InAppNotification { + pub overlay: gtk::Overlay, revealer: gtk::Revealer, text: gtk::Label, undo: gtk::Button, @@ -17,13 +18,15 @@ pub struct InAppNotification { impl Default for InAppNotification { fn default() -> Self { - let builder = gtk::Builder::new_from_resource("/org/gnome/hammond/gtk/inappp_notif.ui"); + let builder = gtk::Builder::new_from_resource("/org/gnome/hammond/gtk/inapp_notif.ui"); + let overlay: gtk::Overlay = builder.get_object("notif_overlay").unwrap(); let revealer: gtk::Revealer = builder.get_object("notif_revealer").unwrap(); let text: gtk::Label = builder.get_object("notif_label").unwrap(); let undo: gtk::Button = builder.get_object("undo_button").unwrap(); InAppNotification { + overlay, revealer, text, undo, @@ -32,16 +35,16 @@ impl Default for InAppNotification { } impl InAppNotification { - pub fn new(text: &str, callback: F, sender: Sender) -> Self + pub fn new(text: String, callback: F, sender: Sender) -> Self where - F: FnMut() -> Continue + 'static, + F: FnMut() -> glib::Continue + 'static, { let notif = InAppNotification::default(); - notif.text.set_text(text); + notif.text.set_text(&text); notif.revealer.set_reveal_child(true); - let id = timeout_add_seconds(10, callback); + let id = timeout_add_seconds(60, callback); let id = Rc::new(RefCell::new(Some(id))); // Cancel the callback diff --git a/hammond-gtk/src/widgets/mod.rs b/hammond-gtk/src/widgets/mod.rs index 3b348fa..c6aa66c 100644 --- a/hammond-gtk/src/widgets/mod.rs +++ b/hammond-gtk/src/widgets/mod.rs @@ -3,3 +3,4 @@ mod episode; pub use self::episode::EpisodeWidget; pub use self::show::ShowWidget; +pub use self::show::mark_all_watched; diff --git a/hammond-gtk/src/widgets/show.rs b/hammond-gtk/src/widgets/show.rs index 118d830..abe9a37 100644 --- a/hammond-gtk/src/widgets/show.rs +++ b/hammond-gtk/src/widgets/show.rs @@ -1,6 +1,6 @@ use dissolve; use failure::Error; -use glib; +// use glib; use gtk; use gtk::prelude::*; use open; @@ -10,7 +10,6 @@ use hammond_data::dbqueries; use hammond_data::utils::{delete_show, replace_extra_spaces}; use app::Action; -use appnotif::InAppNotification; use utils::get_pixbuf_from_path; use widgets::episode::episodes_listbox; @@ -165,19 +164,10 @@ fn on_played_button_clicked(pd: Arc, episodes: >k::Frame, sender: Sen warn!("RUN WHILE YOU STILL CAN!"); } - let text = "All episodes where marked as watched."; - - // Set up the callback - let callback = clone!(sender => move || { - if let Err(err) = wrap(&pd, sender.clone()) { - error!("Something went horribly wrong with the notif callback: {}", err); - } - glib::Continue(false) - }); - let _notif = InAppNotification::new(text, callback, sender); + sender.send(Action::MarkAllPlayerNotification(pd)).unwrap(); } -fn wrap(pd: &Podcast, sender: Sender) -> Result<(), Error> { +pub fn mark_all_watched(pd: &Podcast, sender: Sender) -> Result<(), Error> { dbqueries::update_none_to_played_now(pd)?; sender.send(Action::RefreshWidgetIfVis)?; sender.send(Action::RefreshEpisodesView)?;