EpisodeWidget: Migrate to use a Channel Action instead of simple Action.

This commit is contained in:
Jordan Petridis 2018-01-03 06:53:19 +02:00
parent 84da6aac8c
commit 33cd6e69ff
No known key found for this signature in database
GPG Key ID: CEABAD9F5683B9A6
6 changed files with 43 additions and 44 deletions

View File

@ -197,7 +197,6 @@
<property name="tooltip_text" translatable="yes">Download this episode</property> <property name="tooltip_text" translatable="yes">Download this episode</property>
<property name="halign">end</property> <property name="halign">end</property>
<property name="valign">center</property> <property name="valign">center</property>
<property name="action_name">app.refresh_episodes</property>
<property name="always_show_image">True</property> <property name="always_show_image">True</property>
<child> <child>
<object class="GtkImage"> <object class="GtkImage">
@ -221,7 +220,6 @@
<property name="no_show_all">True</property> <property name="no_show_all">True</property>
<property name="tooltip_text" translatable="yes">Play this episode</property> <property name="tooltip_text" translatable="yes">Play this episode</property>
<property name="valign">center</property> <property name="valign">center</property>
<property name="action_name">app.refresh_episodes</property>
<child> <child>
<object class="GtkImage"> <object class="GtkImage">
<property name="visible">True</property> <property name="visible">True</property>

View File

@ -19,7 +19,7 @@ use std::time::Duration;
pub enum Action { pub enum Action {
UpdateSources(Option<Source>), UpdateSources(Option<Source>),
RefreshViews, RefreshViews,
RefreshEpisodesView, RefreshEpisodesViewBGR,
} }
#[derive(Debug)] #[derive(Debug)]
@ -169,8 +169,8 @@ impl App {
Ok(Action::RefreshViews) => { Ok(Action::RefreshViews) => {
content.update(); content.update();
} }
Ok(Action::RefreshEpisodesView) => { Ok(Action::RefreshEpisodesViewBGR) => {
content.update_episode_view(); content.update_episode_view_if_baground();
} }
_ => (), _ => (),
} }

View File

@ -26,7 +26,7 @@ pub struct Content {
impl Content { impl Content {
pub fn new(header: Rc<Header>, sender: Sender<Action>) -> Rc<Content> { pub fn new(header: Rc<Header>, sender: Sender<Action>) -> Rc<Content> {
let stack = gtk::Stack::new(); let stack = gtk::Stack::new();
let episodes = EpisodeStack::new(); let episodes = EpisodeStack::new(sender.clone());
let shows = ShowStack::new(header, episodes.clone(), sender.clone()); let shows = ShowStack::new(header, episodes.clone(), sender.clone());
stack.add_titled(&episodes.stack, "episodes", "Episodes"); stack.add_titled(&episodes.stack, "episodes", "Episodes");
@ -49,6 +49,12 @@ impl Content {
self.episodes.update(); self.episodes.update();
} }
pub fn update_episode_view_if_baground(&self) {
if self.stack.get_visible_child_name() != Some("episodes".into()) {
self.episodes.update();
}
}
pub fn update_shows_view(&self) { pub fn update_shows_view(&self) {
self.shows.update(); self.shows.update();
} }
@ -178,11 +184,12 @@ pub struct EpisodeStack {
// populated: RecentEpisodes, // populated: RecentEpisodes,
// empty: EmptyView, // empty: EmptyView,
stack: gtk::Stack, stack: gtk::Stack,
sender: Sender<Action>,
} }
impl EpisodeStack { impl EpisodeStack {
fn new() -> Rc<EpisodeStack> { fn new(sender: Sender<Action>) -> Rc<EpisodeStack> {
let episodes = EpisodesView::new(); let episodes = EpisodesView::new(sender.clone());
let empty = EmptyView::new(); let empty = EmptyView::new();
let stack = gtk::Stack::new(); let stack = gtk::Stack::new();
@ -199,12 +206,13 @@ impl EpisodeStack {
// empty, // empty,
// populated: pop, // populated: pop,
stack, stack,
sender,
}) })
} }
pub fn update(&self) { pub fn update(&self) {
let old = self.stack.get_child_by_name("episodes").unwrap(); let old = self.stack.get_child_by_name("episodes").unwrap();
let eps = EpisodesView::new(); let eps = EpisodesView::new(self.sender.clone());
self.stack.remove(&old); self.stack.remove(&old);
self.stack.add_named(&eps.container, "episodes"); self.stack.add_named(&eps.container, "episodes");

View File

@ -7,8 +7,10 @@ use hammond_data::EpisodeWidgetQuery;
use widgets::episode::EpisodeWidget; use widgets::episode::EpisodeWidget;
use utils::get_pixbuf_from_path; use utils::get_pixbuf_from_path;
use app::Action;
use std::rc::Rc; use std::rc::Rc;
use std::sync::mpsc::Sender;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
enum ListSplit { enum ListSplit {
@ -69,13 +71,13 @@ impl Default for EpisodesView {
} }
impl EpisodesView { impl EpisodesView {
pub fn new() -> Rc<EpisodesView> { pub fn new(sender: Sender<Action>) -> Rc<EpisodesView> {
let view = EpisodesView::default(); let view = EpisodesView::default();
let episodes = dbqueries::get_episodes_widgets_with_limit(100).unwrap(); let episodes = dbqueries::get_episodes_widgets_with_limit(100).unwrap();
let now_utc = Utc::now(); let now_utc = Utc::now();
episodes.into_iter().for_each(|mut ep| { episodes.into_iter().for_each(|mut ep| {
let viewep = EpisodesViewWidget::new(&mut ep); let viewep = EpisodesViewWidget::new(&mut ep, sender.clone());
let t = split(&now_utc, i64::from(ep.epoch())); let t = split(&now_utc, i64::from(ep.epoch()));
match t { match t {
@ -187,7 +189,7 @@ impl Default for EpisodesViewWidget {
} }
impl EpisodesViewWidget { impl EpisodesViewWidget {
fn new(episode: &mut EpisodeWidgetQuery) -> EpisodesViewWidget { fn new(episode: &mut EpisodeWidgetQuery, sender: Sender<Action>) -> EpisodesViewWidget {
let builder = let builder =
gtk::Builder::new_from_resource("/org/gnome/hammond/gtk/episodes_view_widget.ui"); gtk::Builder::new_from_resource("/org/gnome/hammond/gtk/episodes_view_widget.ui");
let container: gtk::Box = builder.get_object("container").unwrap(); let container: gtk::Box = builder.get_object("container").unwrap();
@ -200,7 +202,7 @@ impl EpisodesViewWidget {
} }
} }
let ep = EpisodeWidget::new(episode); let ep = EpisodeWidget::new(episode, sender.clone());
container.pack_start(&ep.container, true, true, 6); container.pack_start(&ep.container, true, true, 6);
EpisodesViewWidget { EpisodesViewWidget {

View File

@ -13,9 +13,11 @@ use hammond_data::{EpisodeWidgetQuery, Podcast};
use hammond_data::errors::*; use hammond_data::errors::*;
use hammond_downloader::downloader; use hammond_downloader::downloader;
use app::Action;
use std::thread; use std::thread;
use std::cell::RefCell; use std::cell::RefCell;
use std::sync::mpsc::{channel, Receiver}; use std::sync::mpsc::{channel, Receiver, Sender};
use std::path::Path; use std::path::Path;
type Foo = RefCell< type Foo = RefCell<
@ -86,16 +88,16 @@ impl Default for EpisodeWidget {
} }
impl EpisodeWidget { impl EpisodeWidget {
pub fn new(episode: &mut EpisodeWidgetQuery) -> EpisodeWidget { pub fn new(episode: &mut EpisodeWidgetQuery, sender: Sender<Action>) -> EpisodeWidget {
let widget = EpisodeWidget::default(); let widget = EpisodeWidget::default();
widget.init(episode); widget.init(episode, sender);
widget widget
} }
// TODO: calculate lenght. // TODO: calculate lenght.
// TODO: wire the progress_bar to the downloader. // TODO: wire the progress_bar to the downloader.
// TODO: wire the cancel button. // TODO: wire the cancel button.
fn init(&self, episode: &mut EpisodeWidgetQuery) { fn init(&self, episode: &mut EpisodeWidgetQuery, sender: Sender<Action>) {
// Set the title label state. // Set the title label state.
self.set_title(episode); self.set_title(episode);
@ -113,29 +115,32 @@ impl EpisodeWidget {
let title = &self.title; let title = &self.title;
self.play self.play
.connect_clicked(clone!(episode, title => move |_| { .connect_clicked(clone!(episode, title, sender => move |_| {
let mut episode = episode.clone(); let mut episode = episode.clone();
on_play_bttn_clicked(episode.rowid()); on_play_bttn_clicked(episode.rowid());
if episode.set_played_now().is_ok() { if episode.set_played_now().is_ok() {
title title
.get_style_context() .get_style_context()
.map(|c| c.add_class("dim-label")); .map(|c| c.add_class("dim-label"));
sender.clone().send(Action::RefreshEpisodesViewBGR).unwrap();
}; };
})); }));
let play = &self.play; let play = &self.play;
let cancel = &self.cancel; let cancel = &self.cancel;
let progress = self.progress.clone(); let progress = self.progress.clone();
self.download self.download.connect_clicked(
.connect_clicked(clone!(play, episode, cancel, progress => move |dl| { clone!(play, episode, cancel, progress, sender => move |dl| {
on_download_clicked( on_download_clicked(
&mut episode.clone(), &mut episode.clone(),
dl, dl,
&play, &play,
&cancel, &cancel,
progress.clone() progress.clone(),
sender.clone()
); );
})); }),
);
} }
/// Show or hide the play/delete/download buttons upon widget initialization. /// Show or hide the play/delete/download buttons upon widget initialization.
@ -214,6 +219,7 @@ fn on_download_clicked(
play_bttn: &gtk::Button, play_bttn: &gtk::Button,
cancel_bttn: &gtk::Button, cancel_bttn: &gtk::Button,
progress_bar: gtk::ProgressBar, progress_bar: gtk::ProgressBar,
sender: Sender<Action>,
) { ) {
let progress = progress_bar.clone(); let progress = progress_bar.clone();
@ -223,27 +229,13 @@ fn on_download_clicked(
glib::Continue(true) glib::Continue(true)
}); });
// Create a async channel.
let (sender, receiver) = channel();
// Pass the desired arguments into the Local Thread Storage.
GLOBAL.with(
clone!(download_bttn, play_bttn, cancel_bttn, progress => move |global| {
*global.borrow_mut() = Some((
download_bttn,
play_bttn,
cancel_bttn,
progress,
receiver));
}),
);
let pd = dbqueries::get_podcast_from_id(ep.podcast_id()).unwrap(); let pd = dbqueries::get_podcast_from_id(ep.podcast_id()).unwrap();
let pd_title = pd.title().to_owned(); let pd_title = pd.title().to_owned();
let mut ep = ep.clone(); let mut ep = ep.clone();
cancel_bttn.show(); cancel_bttn.show();
progress.show(); progress.show();
download_bttn.hide(); download_bttn.hide();
sender.send(Action::RefreshEpisodesViewBGR);
thread::spawn(move || { thread::spawn(move || {
let download_fold = downloader::get_download_folder(&pd_title).unwrap(); let download_fold = downloader::get_download_folder(&pd_title).unwrap();
let e = downloader::get_episode(&mut ep, download_fold.as_str()); let e = downloader::get_episode(&mut ep, download_fold.as_str());
@ -251,8 +243,7 @@ fn on_download_clicked(
error!("Error while trying to download: {:?}", ep.uri()); error!("Error while trying to download: {:?}", ep.uri());
error!("Error: {}", err); error!("Error: {}", err);
}; };
sender.send(true).expect("Couldn't send data to channel");; sender.send(Action::RefreshViews);
glib::idle_add(receive);
}); });
} }
@ -309,13 +300,13 @@ fn receive() -> glib::Continue {
glib::Continue(false) glib::Continue(false)
} }
pub fn episodes_listbox(pd: &Podcast) -> Result<gtk::ListBox> { pub fn episodes_listbox(pd: &Podcast, sender: Sender<Action>) -> Result<gtk::ListBox> {
let episodes = dbqueries::get_pd_episodeswidgets(pd)?; let episodes = dbqueries::get_pd_episodeswidgets(pd)?;
let list = gtk::ListBox::new(); let list = gtk::ListBox::new();
episodes.into_iter().for_each(|mut ep| { episodes.into_iter().for_each(|mut ep| {
let widget = EpisodeWidget::new(&mut ep); let widget = EpisodeWidget::new(&mut ep, sender.clone());
list.add(&widget.container); list.add(&widget.container);
}); });

View File

@ -82,7 +82,7 @@ impl ShowWidget {
header.switch_to_normal(); header.switch_to_normal();
})); }));
self.setup_listbox(pd); self.setup_listbox(pd, sender.clone());
self.set_cover(pd); self.set_cover(pd);
self.set_description(pd.description()); self.set_description(pd.description());
@ -95,8 +95,8 @@ impl ShowWidget {
} }
/// Populate the listbox with the shows episodes. /// Populate the listbox with the shows episodes.
fn setup_listbox(&self, pd: &Podcast) { fn setup_listbox(&self, pd: &Podcast, sender: Sender<Action>) {
let listbox = episodes_listbox(pd); let listbox = episodes_listbox(pd, sender.clone());
if let Ok(l) = listbox { if let Ok(l) = listbox {
self.episodes.add(&l); self.episodes.add(&l);
} }