Hammond-gtk: Stack, Content constructors return Results now.

Constructors now proxy underlying errors that migth occur during initialazation.
I think that's about the last unwraps in the main thread.
This commit is contained in:
Jordan Petridis 2018-02-07 03:17:37 +02:00
parent 89564996df
commit 2d33606251
No known key found for this signature in database
GPG Key ID: CEABAD9F5683B9A6
7 changed files with 92 additions and 61 deletions

View File

@ -65,7 +65,8 @@ impl App {
let (sender, receiver) = channel();
// Create a content instance
let content = Arc::new(Content::new(sender.clone()));
let content =
Arc::new(Content::new(sender.clone()).expect("Content Initialization failed."));
// Create the headerbar
let header = Arc::new(Header::new(content.clone(), &window, sender.clone()));
@ -87,7 +88,7 @@ impl App {
let sender = self.sender.clone();
// Update the feeds right after the Application is initialized.
gtk::timeout_add_seconds(2, move || {
utils::refresh_feed(None, sender.clone());
utils::refresh_feed_wrapper(None, sender.clone());
glib::Continue(false)
});
@ -95,7 +96,7 @@ impl App {
// Auto-updater, runs every hour.
// TODO: expose the interval in which it run to a user setting.
gtk::timeout_add_seconds(3600, move || {
utils::refresh_feed(None, sender.clone());
utils::refresh_feed_wrapper(None, sender.clone());
glib::Continue(true)
});
@ -122,9 +123,9 @@ impl App {
match receiver.recv_timeout(Duration::from_millis(10)) {
Ok(Action::UpdateSources(source)) => {
if let Some(s) = source {
utils::refresh_feed(Some(vec![s]), sender.clone());
utils::refresh_feed_wrapper(Some(vec![s]), sender.clone());
} else {
utils::refresh_feed(None, sender.clone());
utils::refresh_feed_wrapper(None, sender.clone());
}
}
Ok(Action::RefreshAllViews) => content.update(),

View File

@ -26,20 +26,20 @@ pub struct Content {
}
impl Content {
pub fn new(sender: Sender<Action>) -> Content {
pub fn new(sender: Sender<Action>) -> Result<Content, Error> {
let stack = gtk::Stack::new();
let episodes = Arc::new(EpisodeStack::new(sender.clone()));
let shows = Arc::new(ShowStack::new(sender.clone()));
let episodes = Arc::new(EpisodeStack::new(sender.clone())?);
let shows = Arc::new(ShowStack::new(sender.clone())?);
stack.add_titled(&episodes.stack, "episodes", "Episodes");
stack.add_titled(&shows.stack, "shows", "Shows");
Content {
Ok(Content {
stack,
shows,
episodes,
sender,
}
})
}
pub fn update(&self) {
@ -107,7 +107,7 @@ pub struct ShowStack {
}
impl ShowStack {
fn new(sender: Sender<Action>) -> ShowStack {
fn new(sender: Sender<Action>) -> Result<ShowStack, Error> {
let stack = gtk::Stack::new();
let show = ShowStack {
@ -115,7 +115,7 @@ impl ShowStack {
sender: sender.clone(),
};
let pop = ShowsPopulated::new(sender.clone());
let pop = ShowsPopulated::new(sender.clone())?;
let widget = ShowWidget::default();
let empty = EmptyView::new();
@ -129,7 +129,7 @@ impl ShowStack {
show.stack.set_visible_child_name("podcasts")
}
show
Ok(show)
}
// pub fn update(&self) {
@ -138,7 +138,9 @@ impl ShowStack {
// }
pub fn update_podcasts(&self) -> Result<(), Error> {
let vis = self.stack.get_visible_child_name().unwrap();
let vis = self.stack
.get_visible_child_name()
.ok_or_else(|| format_err!("Failed to get visible child name."))?;
let old = self.stack
.get_child_by_name("podcasts")
@ -155,7 +157,7 @@ impl ShowStack {
.map_err(|_| format_err!("Failed to downcast stack child to a ScrolledWindow."))?;
debug!("Name: {:?}", WidgetExt::get_name(&scrolled_window));
let pop = ShowsPopulated::new(self.sender.clone());
let pop = ShowsPopulated::new(self.sender.clone())?;
// Copy the vertical scrollbar adjustment from the old view into the new one.
scrolled_window
.get_vadjustment()
@ -269,8 +271,8 @@ pub struct EpisodeStack {
}
impl EpisodeStack {
fn new(sender: Sender<Action>) -> EpisodeStack {
let episodes = EpisodesView::new(sender.clone());
fn new(sender: Sender<Action>) -> Result<EpisodeStack, Error> {
let episodes = EpisodesView::new(sender.clone())?;
let empty = EmptyView::new();
let stack = gtk::Stack::new();
@ -283,7 +285,7 @@ impl EpisodeStack {
stack.set_visible_child_name("episodes");
}
EpisodeStack { stack, sender }
Ok(EpisodeStack { stack, sender })
}
// Look into refactoring to a state-machine.
@ -303,7 +305,7 @@ impl EpisodeStack {
.map_err(|_| format_err!("Failed to downcast stack child to a ScrolledWindow."))?;
debug!("Name: {:?}", WidgetExt::get_name(&scrolled_window));
let eps = EpisodesView::new(self.sender.clone());
let eps = EpisodesView::new(self.sender.clone())?;
// Copy the vertical scrollbar adjustment from the old view into the new one.
scrolled_window
.get_vadjustment()

View File

@ -90,7 +90,9 @@ impl Header {
self.add_toggle.set_popover(&add_popover);
self.update_button.connect_clicked(move |_| {
sender.send(Action::UpdateSources(None)).unwrap();
sender
.send(Action::UpdateSources(None))
.expect("Action channel blew up.");
});
self.about_button

View File

@ -112,8 +112,12 @@ pub fn add(id: i32, directory: &str, sender: Sender<Action>) -> Result<(), Error
// }
// }
sender.send(Action::RefreshEpisodesView).unwrap();
sender.send(Action::RefreshWidgetIfSame(pid)).unwrap();
sender
.send(Action::RefreshEpisodesView)
.expect("Action channel blew up.");
sender
.send(Action::RefreshWidgetIfSame(pid))
.expect("Action channel blew up.");
}
});

View File

@ -17,14 +17,23 @@ use std::thread;
use app::Action;
pub fn refresh_feed_wrapper(source: Option<Vec<Source>>, sender: Sender<Action>) {
if let Err(err) = refresh_feed(source, sender) {
error!("An error occured while trying to update the feeds.");
error!("Error: {}", err);
}
}
/// Update the rss feed(s) originating from `source`.
/// If `source` is None, Fetches all the `Source` entries in the database and updates them.
/// When It's done,it queues up a `RefreshViews` action.
pub fn refresh_feed(source: Option<Vec<Source>>, sender: Sender<Action>) {
sender.send(Action::HeaderBarShowUpdateIndicator).unwrap();
fn refresh_feed(source: Option<Vec<Source>>, sender: Sender<Action>) -> Result<(), Error> {
sender.send(Action::HeaderBarShowUpdateIndicator)?;
thread::spawn(move || {
let mut sources = source.unwrap_or_else(|| dbqueries::get_sources().unwrap());
let mut sources = source.unwrap_or_else(|| {
dbqueries::get_sources().expect("Failed to retrieve Sources from the database.")
});
// Work around to improve the feed addition experience.
// Many times links to rss feeds are just redirects(usually to an https version).
@ -40,11 +49,11 @@ pub fn refresh_feed(source: Option<Vec<Source>>, sender: Sender<Action>) {
if let Err(err) = pipeline::index_single_source(source, false) {
error!("Error While trying to update the database.");
error!("Error msg: {}", err);
let source = dbqueries::get_source_from_id(id).unwrap();
if let Err(err) = pipeline::index_single_source(source, false) {
error!("Error While trying to update the database.");
error!("Error msg: {}", err);
if let Ok(source) = dbqueries::get_source_from_id(id) {
if let Err(err) = pipeline::index_single_source(source, false) {
error!("Error While trying to update the database.");
error!("Error msg: {}", err);
}
}
}
} else {
@ -55,9 +64,14 @@ pub fn refresh_feed(source: Option<Vec<Source>>, sender: Sender<Action>) {
}
}
sender.send(Action::HeaderBarHideUpdateIndicator).unwrap();
sender.send(Action::RefreshAllViews).unwrap();
sender
.send(Action::HeaderBarHideUpdateIndicator)
.expect("Action channel blew up.");
sender
.send(Action::RefreshAllViews)
.expect("Action channel blew up.");
});
Ok(())
}
lazy_static! {

View File

@ -75,9 +75,9 @@ impl Default for EpisodesView {
// TODO: REFACTOR ME
impl EpisodesView {
pub fn new(sender: Sender<Action>) -> EpisodesView {
pub fn new(sender: Sender<Action>) -> Result<EpisodesView, Error> {
let view = EpisodesView::default();
let episodes = dbqueries::get_episodes_widgets_with_limit(50).unwrap();
let episodes = dbqueries::get_episodes_widgets_with_limit(50)?;
let now_utc = Utc::now();
episodes.into_iter().for_each(|mut ep| {
@ -124,7 +124,7 @@ impl EpisodesView {
}
view.container.show_all();
view
Ok(view)
}
pub fn is_empty(&self) -> bool {

View File

@ -33,41 +33,34 @@ impl Default for ShowsPopulated {
}
impl ShowsPopulated {
pub fn new(sender: Sender<Action>) -> ShowsPopulated {
pub fn new(sender: Sender<Action>) -> Result<ShowsPopulated, Error> {
let pop = ShowsPopulated::default();
pop.init(sender);
pop
pop.init(sender)?;
Ok(pop)
}
pub fn init(&self, sender: Sender<Action>) {
use gtk::WidgetExt;
// TODO: handle unwraps.
pub fn init(&self, sender: Sender<Action>) -> Result<(), Error> {
self.flowbox.connect_child_activated(move |_, child| {
// This is such an ugly hack...
let id = WidgetExt::get_name(child).unwrap().parse::<i32>().unwrap();
let pd = dbqueries::get_podcast_from_id(id).unwrap();
sender
.send(Action::HeaderBarShowTile(pd.title().into()))
.unwrap();
sender.send(Action::ReplaceWidget(pd)).unwrap();
sender.send(Action::ShowWidgetAnimated).unwrap();
if let Err(err) = on_child_activate(child, sender.clone()) {
error!(
"Something went wrong during flowbox child activation: {}.",
err
)
};
});
// Populate the flowbox with the Podcasts.
self.populate_flowbox();
self.populate_flowbox()
}
fn populate_flowbox(&self) {
let podcasts = dbqueries::get_podcasts();
fn populate_flowbox(&self) -> Result<(), Error> {
let podcasts = dbqueries::get_podcasts()?;
if let Ok(pds) = podcasts {
pds.iter().for_each(|parent| {
let flowbox_child = ShowsChild::new(parent);
self.flowbox.add(&flowbox_child.child);
});
self.flowbox.show_all();
}
podcasts.iter().for_each(|parent| {
let flowbox_child = ShowsChild::new(parent);
self.flowbox.add(&flowbox_child.child);
});
self.flowbox.show_all();
Ok(())
}
pub fn is_empty(&self) -> bool {
@ -80,6 +73,21 @@ impl ShowsPopulated {
}
}
fn on_child_activate(child: &gtk::FlowBoxChild, sender: Sender<Action>) -> Result<(), Error> {
use gtk::WidgetExt;
// This is such an ugly hack...
let id = WidgetExt::get_name(child)
.ok_or_else(|| format_err!("Faild to get \"episodes\" child from the stack."))?
.parse::<i32>()?;
let pd = dbqueries::get_podcast_from_id(id)?;
sender.send(Action::HeaderBarShowTile(pd.title().into()))?;
sender.send(Action::ReplaceWidget(pd))?;
sender.send(Action::ShowWidgetAnimated)?;
Ok(())
}
#[derive(Debug)]
struct ShowsChild {
container: gtk::Box,