From 1175a5426622f685bd29bd667893eef478eac479 Mon Sep 17 00:00:00 2001 From: Timofey Date: Wed, 8 Jan 2020 22:32:43 +0300 Subject: [PATCH 1/2] Synchronize feed updates --- podcasts-gtk/src/app.rs | 22 +++++++++++++++++++++- podcasts-gtk/src/utils.rs | 19 ++++++++++--------- podcasts-gtk/src/window.rs | 4 +++- 3 files changed, 34 insertions(+), 11 deletions(-) diff --git a/podcasts-gtk/src/app.rs b/podcasts-gtk/src/app.rs index 4876bd0..5d34959 100644 --- a/podcasts-gtk/src/app.rs +++ b/podcasts-gtk/src/app.rs @@ -34,7 +34,7 @@ use gettextrs::{bindtextdomain, setlocale, textdomain, LocaleCategory}; use crossbeam_channel::Receiver; use fragile::Fragile; -use podcasts_data::Show; +use podcasts_data::{Show, Source}; use crate::settings; use crate::stacks::PopulatedState; @@ -138,7 +138,9 @@ pub(crate) enum Action { HeaderBarShowTile(String), HeaderBarNormal, MarkAllPlayerNotification(Arc), + UpdateFeed(Option>), ShowUpdateNotif(Receiver), + StopUpdating, RemoveShow(Arc), ErrorNotification(String), InitEpisode(i32), @@ -248,6 +250,17 @@ impl PdApplication { let notif = InAppNotification::new(&err, 6000, callback, undo_cb); notif.show(&window.overlay); } + Action::UpdateFeed(source) => { + if window.updating.get() { + info!("Ignoring feed update request (another one is already running)") + } else { + window.updating.set(true); + utils::refresh_feed(source, window.sender.clone()) + } + } + Action::StopUpdating => { + window.updating.set(false); + } Action::ShowUpdateNotif(receiver) => { let sender = window.sender.clone(); let callback = move |revealer: gtk::Revealer| match receiver.try_recv() { @@ -255,9 +268,15 @@ impl PdApplication { Err(TryRecvError::Disconnected) => glib::Continue(false), Ok(_) => { revealer.set_reveal_child(false); + + sender + .send(Action::StopUpdating) + .expect("Action channel blew up somehow"); + sender .send(Action::RefreshAllViews) .expect("Action channel blew up somehow"); + glib::Continue(false) } }; @@ -269,6 +288,7 @@ impl PdApplication { let old = window.updater.replace(Some(updater)); old.map(|i| i.destroy()); + window .updater .borrow() diff --git a/podcasts-gtk/src/utils.rs b/podcasts-gtk/src/utils.rs index 981a3bd..77a81f1 100644 --- a/podcasts-gtk/src/utils.rs +++ b/podcasts-gtk/src/utils.rs @@ -203,10 +203,10 @@ pub(crate) fn cleanup(cleanup_date: DateTime) { .ok(); } -pub(crate) fn refresh(source: Option, sender: Sender) -where - S: IntoIterator + Send + 'static, -{ +/// Schedule feed refresh +/// If `source` is None, Refreshes all sources in the database. +/// Current implementation ignores update request if another update is already running +pub(crate) fn refresh(source: Option>, sender: Sender) { // If we try to update the whole db, // Exit early if `source` table is empty if source.is_none() { @@ -220,15 +220,16 @@ where }; } - refresh_feed(source, sender) + sender + .send(Action::UpdateFeed(source)) + .expect("Action channel blew up somehow") } /// Update the rss feed(s) originating from `source`. /// If `source` is None, Fetches all the `Source` entries in the database and updates them. -fn refresh_feed(source: Option, sender: Sender) -where - S: IntoIterator + Send + 'static, -{ +/// Do not call this function directly unless you are sure no other updates are running. +/// Use `refresh()` instead +pub(crate) fn refresh_feed(source: Option>, sender: Sender) { rayon::spawn(move || { let (up_sender, up_receiver) = bounded(1); sender diff --git a/podcasts-gtk/src/window.rs b/podcasts-gtk/src/window.rs index e73daa1..7227eb3 100644 --- a/podcasts-gtk/src/window.rs +++ b/podcasts-gtk/src/window.rs @@ -36,7 +36,7 @@ use crate::widgets::about_dialog; use crate::widgets::appnotif::InAppNotification; use crate::widgets::player; -use std::cell::RefCell; +use std::cell::{Cell, RefCell}; use std::ops::Deref; use std::rc::Rc; @@ -65,6 +65,7 @@ pub struct MainWindow { pub(crate) content: Rc, pub(crate) headerbar: Rc
, pub(crate) player: player::PlayerWrapper, + pub(crate) updating: Cell, pub(crate) updater: RefCell>, pub(crate) sender: Sender, pub(crate) receiver: Receiver, @@ -158,6 +159,7 @@ impl MainWindow { headerbar: header, content, player, + updating: Cell::new(false), updater, sender, receiver, From 685b35cb23880c54e11519a05d4ca4cb0032a731 Mon Sep 17 00:00:00 2001 From: Timofey Date: Wed, 8 Jan 2020 22:40:58 +0300 Subject: [PATCH 2/2] Rename refresh to schedule_refresh --- podcasts-gtk/src/headerbar.rs | 4 ++-- podcasts-gtk/src/utils.rs | 6 +++--- podcasts-gtk/src/window.rs | 6 +++--- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/podcasts-gtk/src/headerbar.rs b/podcasts-gtk/src/headerbar.rs index 3445082..63854e1 100644 --- a/podcasts-gtk/src/headerbar.rs +++ b/podcasts-gtk/src/headerbar.rs @@ -32,7 +32,7 @@ use podcasts_data::{dbqueries, Source}; use crate::app::Action; use crate::stacks::Content; -use crate::utils::{itunes_to_rss, refresh}; +use crate::utils::{itunes_to_rss, schedule_refresh}; use std::rc::Rc; @@ -85,7 +85,7 @@ impl AddPopover { rayon::spawn(clone!(sender => move || { if let Ok(source) = Source::from_url(&url) { - refresh(Some(vec![source]), sender.clone()); + schedule_refresh(Some(vec![source]), sender.clone()); } else { error!("Failed to convert, url: {}, to a source entry", url); } diff --git a/podcasts-gtk/src/utils.rs b/podcasts-gtk/src/utils.rs index 77a81f1..7efa171 100644 --- a/podcasts-gtk/src/utils.rs +++ b/podcasts-gtk/src/utils.rs @@ -206,7 +206,7 @@ pub(crate) fn cleanup(cleanup_date: DateTime) { /// Schedule feed refresh /// If `source` is None, Refreshes all sources in the database. /// Current implementation ignores update request if another update is already running -pub(crate) fn refresh(source: Option>, sender: Sender) { +pub(crate) fn schedule_refresh(source: Option>, sender: Sender) { // If we try to update the whole db, // Exit early if `source` table is empty if source.is_none() { @@ -228,7 +228,7 @@ pub(crate) fn refresh(source: Option>, sender: Sender) { /// Update the rss feed(s) originating from `source`. /// If `source` is None, Fetches all the `Source` entries in the database and updates them. /// Do not call this function directly unless you are sure no other updates are running. -/// Use `refresh()` instead +/// Use `schedule_refresh()` instead pub(crate) fn refresh_feed(source: Option>, sender: Sender) { rayon::spawn(move || { let (up_sender, up_receiver) = bounded(1); @@ -421,7 +421,7 @@ pub(crate) fn on_import_clicked(window: >k::ApplicationWindow, sender: &Sender // Parse the file and import the feeds if let Ok(sources) = opml::import_from_file(filename) { // Refresh the successfully parsed feeds to index them - refresh(Some(sources), sender) + schedule_refresh(Some(sources), sender) } else { let text = i18n("Failed to parse the imported file"); sender.send(Action::ErrorNotification(text)).expect("Action channel blew up somehow"); diff --git a/podcasts-gtk/src/window.rs b/podcasts-gtk/src/window.rs index 7227eb3..98eb2a0 100644 --- a/podcasts-gtk/src/window.rs +++ b/podcasts-gtk/src/window.rs @@ -138,7 +138,7 @@ impl MainWindow { if settings.get_boolean("refresh-on-startup") { info!("Refresh on startup."); let s: Option> = None; - utils::refresh(s, sender.clone()); + utils::schedule_refresh(s, sender.clone()); } let refresh_interval = settings::get_refresh_interval(&settings).num_seconds() as u32; @@ -147,7 +147,7 @@ impl MainWindow { let r_sender = sender.clone(); gtk::timeout_add_seconds(refresh_interval, move || { let s: Option> = None; - utils::refresh(s, r_sender.clone()); + utils::schedule_refresh(s, r_sender.clone()); glib::Continue(true) }); @@ -180,7 +180,7 @@ impl MainWindow { action(&self.window, "refresh", clone!(sender => move |_, _| { gtk::idle_add(clone!(sender => move || { let s: Option> = None; - utils::refresh(s, sender.clone()); + utils::schedule_refresh(s, sender.clone()); glib::Continue(false) })); }));