EpisodeWidget: Migrate to use a Channel Action instead of simple Action.
This commit is contained in:
parent
84da6aac8c
commit
33cd6e69ff
@ -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>
|
||||||
|
|||||||
@ -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();
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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");
|
||||||
|
|||||||
@ -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 {
|
||||||
|
|||||||
@ -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: >k::Button,
|
play_bttn: >k::Button,
|
||||||
cancel_bttn: >k::Button,
|
cancel_bttn: >k::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);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user