EpisodeWidget: Handle updating states, withotu having to reload the views.

This code is ugly and terrible but it works™. Previsously when a download
would finish it would refresh all the views. Now the if the widget get's
into the Donwloading state, it will setup a callback that will check
periodicly if it's still downloading and update the widget state when
the episode stops downloading.
This commit is contained in:
Jordan Petridis
2018-04-28 14:09:26 +03:00
parent 63e2ea987e
commit 03bd951848
3 changed files with 56 additions and 30 deletions
+3 -16
View File
@@ -5,10 +5,7 @@ use rayon;
use hammond_data::dbqueries;
use hammond_downloader::downloader::{get_episode, DownloadProgress};
use app::Action;
use std::collections::HashMap;
use std::sync::mpsc::Sender;
use std::sync::{Arc, Mutex, RwLock};
// use std::sync::atomic::AtomicUsize;
// use std::path::PathBuf;
@@ -78,7 +75,7 @@ lazy_static! {
static ref DLPOOL: rayon::ThreadPool = rayon::ThreadPoolBuilder::new().build().unwrap();
}
pub fn add(id: i32, directory: String, sender: Sender<Action>) -> Result<(), Error> {
pub fn add(id: i32, directory: String) -> Result<(), Error> {
// Create a new `Progress` struct to keep track of dl progress.
let prog = Arc::new(Mutex::new(Progress::default()));
@@ -88,11 +85,10 @@ pub fn add(id: i32, directory: String, sender: Sender<Action>) -> Result<(), Err
};
DLPOOL.spawn(move || {
if let Ok(episode) = dbqueries::get_episode_from_rowid(id) {
if let Ok(mut episode) = dbqueries::get_episode_widget_from_rowid(id) {
let id = episode.rowid();
let pid = episode.podcast_id();
get_episode(&mut episode.into(), directory.as_str(), Some(prog))
get_episode(&mut episode, directory.as_str(), Some(prog))
.map_err(|err| error!("Download Failed: {}", err))
.ok();
@@ -104,15 +100,6 @@ pub fn add(id: i32, directory: String, sender: Sender<Action>) -> Result<(), Err
// if let Ok(m) = ACTIVE_DOWNLOADS.read() {
// debug!("ACTIVE DOWNLOADS: {:#?}", m);
// }
sender
.send(Action::RefreshWidgetIfSame(pid))
.map_err(|err| error!("Action Sender: {}", err))
.ok();
sender
.send(Action::RefreshEpisodesView)
.map_err(|err| error!("Action Sender: {}", err))
.ok();
}
});
+39 -14
View File
@@ -128,10 +128,10 @@ impl EpisodeWidget {
.and_then(|_| {
info!("Donwload started succesfully.");
determine_media_state(media_machine.clone(), &ep)
})
.map_err(|err| error!("Error: {}", err))
.map_err(|_| error!("Could not determine Media State"))
.ok();
})
.map_err(|err| error!("Error: {}", err))
.map_err(|_| error!("Could not determine Media State"))
.ok();
}
// Restore sensitivity after operations above complete
@@ -190,20 +190,42 @@ fn determine_media_state(
// Show or hide the play/delete/download buttons upon widget initialization.
if let Some(prog) = active_dl {
let episode = episode.clone();
// set a callback that will update the state when the download finishes
let id = episode.rowid();
let callback = clone!(media_machine => move || {
if let Ok(guard) = manager::ACTIVE_DOWNLOADS.read() {
if !guard.contains_key(&id) {
if let Ok(ep) = dbqueries::get_episode_widget_from_rowid(id) {
determine_media_state(media_machine.clone(), &ep)
.map_err(|err| error!("Error: {}", err))
.map_err(|_| error!("Could not determine Media State"))
.ok();
return glib::Continue(false)
}
}
}
glib::Continue(true)
});
gtk::timeout_add(250, callback);
lock.cancel_connect_clicked(clone!(prog, media_machine => move |_| {
if let Ok(mut m) = prog.lock() {
m.cancel();
}
if let Ok(mut lock) = media_machine.try_borrow_mut() {
take_mut::take(lock.deref_mut(), |media| {
media.determine_state(
episode.length(),
false,
episode.local_uri().is_some(),
)
});
if let Ok(episode) = dbqueries::get_episode_widget_from_rowid(id) {
take_mut::take(lock.deref_mut(), |media| {
media.determine_state(
episode.length(),
false,
episode.local_uri().is_some(),
)
});
}
}
}));
drop(lock);
@@ -221,12 +243,15 @@ fn determine_media_state(
}
#[inline]
fn on_download_clicked(ep: &EpisodeWidgetQuery, sender: Sender<Action>) -> Result<(), Error> {
fn on_download_clicked(
ep: &EpisodeWidgetQuery,
sender: Sender<Action>,
) -> Result<(), Error> {
let pd = dbqueries::get_podcast_from_id(ep.podcast_id())?;
let download_fold = get_download_folder(&pd.title())?;
// Start a new download.
manager::add(ep.rowid(), download_fold, sender.clone())?;
manager::add(ep.rowid(), download_fold)?;
// Update Views
sender.send(Action::RefreshEpisodesViewBGR)?;