diff --git a/hammond-gtk/src/app.rs b/hammond-gtk/src/app.rs index 5a13913..02edbfa 100644 --- a/hammond-gtk/src/app.rs +++ b/hammond-gtk/src/app.rs @@ -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(), diff --git a/hammond-gtk/src/content.rs b/hammond-gtk/src/content.rs index 17811cd..f73803c 100644 --- a/hammond-gtk/src/content.rs +++ b/hammond-gtk/src/content.rs @@ -26,20 +26,20 @@ pub struct Content { } impl Content { - pub fn new(sender: Sender) -> Content { + pub fn new(sender: Sender) -> Result { 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) -> ShowStack { + fn new(sender: Sender) -> Result { 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) -> EpisodeStack { - let episodes = EpisodesView::new(sender.clone()); + fn new(sender: Sender) -> Result { + 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() diff --git a/hammond-gtk/src/headerbar.rs b/hammond-gtk/src/headerbar.rs index e8ba764..399d3c6 100644 --- a/hammond-gtk/src/headerbar.rs +++ b/hammond-gtk/src/headerbar.rs @@ -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 diff --git a/hammond-gtk/src/manager.rs b/hammond-gtk/src/manager.rs index da958d2..a9d70fe 100644 --- a/hammond-gtk/src/manager.rs +++ b/hammond-gtk/src/manager.rs @@ -112,8 +112,12 @@ pub fn add(id: i32, directory: &str, sender: Sender) -> 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."); } }); diff --git a/hammond-gtk/src/utils.rs b/hammond-gtk/src/utils.rs index ffac353..1d91f74 100644 --- a/hammond-gtk/src/utils.rs +++ b/hammond-gtk/src/utils.rs @@ -17,14 +17,23 @@ use std::thread; use app::Action; +pub fn refresh_feed_wrapper(source: Option>, sender: Sender) { + 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>, sender: Sender) { - sender.send(Action::HeaderBarShowUpdateIndicator).unwrap(); +fn refresh_feed(source: Option>, sender: Sender) -> 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>, sender: Sender) { 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>, sender: Sender) { } } - 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! { diff --git a/hammond-gtk/src/views/episodes.rs b/hammond-gtk/src/views/episodes.rs index e4893d6..2321665 100644 --- a/hammond-gtk/src/views/episodes.rs +++ b/hammond-gtk/src/views/episodes.rs @@ -75,9 +75,9 @@ impl Default for EpisodesView { // TODO: REFACTOR ME impl EpisodesView { - pub fn new(sender: Sender) -> EpisodesView { + pub fn new(sender: Sender) -> Result { 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 { diff --git a/hammond-gtk/src/views/shows.rs b/hammond-gtk/src/views/shows.rs index 3f72981..52be6a1 100644 --- a/hammond-gtk/src/views/shows.rs +++ b/hammond-gtk/src/views/shows.rs @@ -33,41 +33,34 @@ impl Default for ShowsPopulated { } impl ShowsPopulated { - pub fn new(sender: Sender) -> ShowsPopulated { + pub fn new(sender: Sender) -> Result { let pop = ShowsPopulated::default(); - pop.init(sender); - pop + pop.init(sender)?; + Ok(pop) } - pub fn init(&self, sender: Sender) { - use gtk::WidgetExt; - - // TODO: handle unwraps. + pub fn init(&self, sender: Sender) -> Result<(), Error> { self.flowbox.connect_child_activated(move |_, child| { - // This is such an ugly hack... - let id = WidgetExt::get_name(child).unwrap().parse::().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: >k::FlowBoxChild, sender: Sender) -> 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::()?; + 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,