From 1fbcfa47ac3bc820f72a22d0c9f445ff09e7ab1d Mon Sep 17 00:00:00 2001 From: Jordan Petridis Date: Thu, 30 Nov 2017 21:02:26 +0200 Subject: [PATCH 01/41] Refactor Headerbar into a Wrapped struct type. --- hammond-gtk/resources/gtk/headerbar.ui | 1 - hammond-gtk/src/headerbar.rs | 75 +++++++++++++++++++++++--- 2 files changed, 68 insertions(+), 8 deletions(-) diff --git a/hammond-gtk/resources/gtk/headerbar.ui b/hammond-gtk/resources/gtk/headerbar.ui index e84409d..d28c2ae 100644 --- a/hammond-gtk/resources/gtk/headerbar.ui +++ b/hammond-gtk/resources/gtk/headerbar.ui @@ -3,7 +3,6 @@ - True False Add a new feed center diff --git a/hammond-gtk/src/headerbar.rs b/hammond-gtk/src/headerbar.rs index ac6c736..2ebb4cc 100644 --- a/hammond-gtk/src/headerbar.rs +++ b/hammond-gtk/src/headerbar.rs @@ -7,6 +7,68 @@ use hammond_data::utils::url_cleaner; use podcasts_view::update_podcasts_view; use utils; +#[derive(Debug)] +pub struct Header { + container: gtk::HeaderBar, + home: gtk::Button, + refresh: gtk::Button, + add_toggle: gtk::MenuButton, +} + +impl Header { + fn new() -> Header { + let builder = gtk::Builder::new_from_resource("/org/gnome/hammond/gtk/headerbar.ui"); + + let header: gtk::HeaderBar = builder.get_object("headerbar1").unwrap(); + let home: gtk::Button = builder.get_object("homebutton").unwrap(); + let refresh: gtk::Button = builder.get_object("refbutton").unwrap(); + let add_toggle: gtk::MenuButton = builder.get_object("add-toggle-button").unwrap(); + + Header { + container: header, + home, + refresh, + add_toggle, + } + } + + fn init(&self, stack: >k::Stack) { + let builder = gtk::Builder::new_from_resource("/org/gnome/hammond/gtk/headerbar.ui"); + + let add_popover: gtk::Popover = builder.get_object("add-popover").unwrap(); + let new_url: gtk::Entry = builder.get_object("new-url").unwrap(); + let add_button: gtk::Button = builder.get_object("add-button").unwrap(); + + new_url.connect_changed(move |url| { + println!("{:?}", url.get_text()); + }); + + add_button.connect_clicked(clone!(stack, add_popover, new_url => move |_| { + on_add_bttn_clicked(&stack, &new_url); + + // TODO: lock the button instead of hiding and add notification of feed added. + // TODO: map the spinner + add_popover.hide(); + })); + self.add_toggle.set_popover(&add_popover); + + // TODO: make it a back arrow button, that will hide when appropriate, + // and add a StackSwitcher when more views are added. + self.home.connect_clicked(clone!(stack => move |_| { + let vis = stack.get_visible_child_name().unwrap(); + stack.set_visible_child_name("fb_parent"); + if vis != "pdw" { + update_podcasts_view(&stack); + } + })); + + // FIXME: There appears to be a memmory leak here. + self.refresh.connect_clicked(clone!(stack => move |_| { + utils::refresh_feed(&stack, None, None); + })); + } +} + pub fn get_headerbar(stack: >k::Stack) -> gtk::HeaderBar { let builder = gtk::Builder::new_from_resource("/org/gnome/hammond/gtk/headerbar.ui"); @@ -23,16 +85,13 @@ pub fn get_headerbar(stack: >k::Stack) -> gtk::HeaderBar { println!("{:?}", url.get_text()); }); - add_button.connect_clicked(clone!(stack, add_popover => move |_| { - let url = new_url.get_text().unwrap_or_default(); - let url = url_cleaner(&url); - on_add_bttn_clicked(&stack, &url); + add_button.connect_clicked(clone!(stack, add_popover, new_url => move |_| { + on_add_bttn_clicked(&stack, &new_url); // TODO: lock the button instead of hiding and add notification of feed added. // TODO: map the spinner add_popover.hide(); })); - add_popover.hide(); add_toggle_button.set_popover(&add_popover); // TODO: make it a back arrow button, that will hide when appropriate, @@ -53,8 +112,10 @@ pub fn get_headerbar(stack: >k::Stack) -> gtk::HeaderBar { header } -fn on_add_bttn_clicked(stack: >k::Stack, url: &str) { - let source = Source::from_url(url); +fn on_add_bttn_clicked(stack: >k::Stack, entry: >k::Entry) { + let url = entry.get_text().unwrap_or_default(); + let url = url_cleaner(&url); + let source = Source::from_url(&url); if let Ok(s) = source { info!("{:?} feed added", url); From b32e35c5749ec3d8a823060c266c49e44ccc272e Mon Sep 17 00:00:00 2001 From: Jordan Petridis Date: Thu, 30 Nov 2017 21:10:05 +0200 Subject: [PATCH 02/41] Rename podcasts_view module. --- hammond-gtk/src/headerbar.rs | 2 +- hammond-gtk/src/main.rs | 6 ++++-- hammond-gtk/src/utils.rs | 4 ++-- hammond-gtk/src/views/mod.rs | 2 +- hammond-gtk/src/views/{podcasts_view.rs => podcasts.rs} | 0 hammond-gtk/src/widgets/podcast.rs | 2 +- 6 files changed, 9 insertions(+), 7 deletions(-) rename hammond-gtk/src/views/{podcasts_view.rs => podcasts.rs} (100%) diff --git a/hammond-gtk/src/headerbar.rs b/hammond-gtk/src/headerbar.rs index 2ebb4cc..3ccf41e 100644 --- a/hammond-gtk/src/headerbar.rs +++ b/hammond-gtk/src/headerbar.rs @@ -4,7 +4,7 @@ use gtk::prelude::*; use hammond_data::Source; use hammond_data::utils::url_cleaner; -use podcasts_view::update_podcasts_view; +use views::podcasts::update_podcasts_view; use utils; #[derive(Debug)] diff --git a/hammond-gtk/src/main.rs b/hammond-gtk/src/main.rs index 5f65291..15dfb31 100644 --- a/hammond-gtk/src/main.rs +++ b/hammond-gtk/src/main.rs @@ -1,3 +1,5 @@ +#![allow(dead_code)] + extern crate gdk; extern crate gdk_pixbuf; extern crate gio; @@ -47,7 +49,7 @@ mod headerbar; mod utils; mod static_resource; -use views::podcasts_view; +use views::podcasts; /* THIS IS STILL A PROTOTYPE. @@ -63,7 +65,7 @@ fn build_ui(app: >k::Application) { let window = gtk::ApplicationWindow::new(app); window.set_default_size(1150, 650); // Setup the Stack that will manage the switch between podcasts_view and podcast_widget. - let stack = podcasts_view::setup_stack(); + let stack = podcasts::setup_stack(); window.add(&stack); window.connect_delete_event(|w, _| { diff --git a/hammond-gtk/src/utils.rs b/hammond-gtk/src/utils.rs index 69bd584..2799f6d 100644 --- a/hammond-gtk/src/utils.rs +++ b/hammond-gtk/src/utils.rs @@ -8,7 +8,7 @@ use std::{thread, time}; use std::cell::RefCell; use std::sync::mpsc::{channel, Receiver}; -use views::podcasts_view; +use views::podcasts; type Foo = RefCell)>>; @@ -55,7 +55,7 @@ fn refresh_podcasts_view() -> glib::Continue { GLOBAL.with(|global| { if let Some((ref stack, ref reciever)) = *global.borrow() { if reciever.try_recv().is_ok() { - podcasts_view::update_podcasts_view(stack); + podcasts::update_podcasts_view(stack); } } }); diff --git a/hammond-gtk/src/views/mod.rs b/hammond-gtk/src/views/mod.rs index 69e01ee..398798f 100644 --- a/hammond-gtk/src/views/mod.rs +++ b/hammond-gtk/src/views/mod.rs @@ -1 +1 @@ -pub mod podcasts_view; +pub mod podcasts; diff --git a/hammond-gtk/src/views/podcasts_view.rs b/hammond-gtk/src/views/podcasts.rs similarity index 100% rename from hammond-gtk/src/views/podcasts_view.rs rename to hammond-gtk/src/views/podcasts.rs diff --git a/hammond-gtk/src/widgets/podcast.rs b/hammond-gtk/src/widgets/podcast.rs index 6d765a3..1dbbf8f 100644 --- a/hammond-gtk/src/widgets/podcast.rs +++ b/hammond-gtk/src/widgets/podcast.rs @@ -9,7 +9,7 @@ use hammond_data::Podcast; use hammond_downloader::downloader; use widgets::episode::episodes_listbox; -use podcasts_view::update_podcasts_view; +use views::podcasts::update_podcasts_view; pub fn podcast_widget(stack: >k::Stack, pd: &Podcast) -> gtk::Box { // Adapted from gnome-music AlbumWidget From bf240a00f482858000d9c71c06bfcab6da15e38f Mon Sep 17 00:00:00 2001 From: Jordan Petridis Date: Thu, 30 Nov 2017 21:19:03 +0200 Subject: [PATCH 03/41] Make a PodcastWidget Struct type. --- hammond-gtk/src/widgets/podcast.rs | 65 ++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/hammond-gtk/src/widgets/podcast.rs b/hammond-gtk/src/widgets/podcast.rs index 1dbbf8f..e696dec 100644 --- a/hammond-gtk/src/widgets/podcast.rs +++ b/hammond-gtk/src/widgets/podcast.rs @@ -11,6 +11,71 @@ use hammond_downloader::downloader; use widgets::episode::episodes_listbox; use views::podcasts::update_podcasts_view; +#[derive(Debug)] +struct PodcastWidget { + container: gtk::Box, + cover: gtk::Image, + title: gtk::Label, + description: gtk::TextView, + view: gtk::Viewport, + unsub: gtk::Button, + played: gtk::Button, +} + +impl PodcastWidget { + fn new() -> PodcastWidget { + // Adapted from gnome-music AlbumWidget + let builder = gtk::Builder::new_from_resource("/org/gnome/hammond/gtk/podcast_widget.ui"); + let container: gtk::Box = builder.get_object("podcast_widget").unwrap(); + + let cover: gtk::Image = builder.get_object("cover").unwrap(); + let title: gtk::Label = builder.get_object("title_label").unwrap(); + let description: gtk::TextView = builder.get_object("desc_text_view").unwrap(); + let view: gtk::Viewport = builder.get_object("view").unwrap(); + let unsub: gtk::Button = builder.get_object("unsub_button").unwrap(); + let played: gtk::Button = builder.get_object("mark_all_played_button").unwrap(); + + PodcastWidget { + container, + cover, + title, + description, + view, + unsub, + played, + } + } + + pub fn init(&self, stack: >k::Stack, pd: &Podcast) { + // TODO: should spawn a thread to avoid locking the UI probably. + self.unsub.connect_clicked(clone!(stack, pd => move |bttn| { + on_unsub_button_clicked(&stack, &pd, bttn); + })); + + self.title.set_text(pd.title()); + let listbox = episodes_listbox(pd); + if let Ok(l) = listbox { + self.view.add(&l); + } + + { + let buff = self.description.get_buffer().unwrap(); + buff.set_text(pd.description()); + } + + let img = get_pixbuf_from_path(pd); + if let Some(i) = img { + self.cover.set_from_pixbuf(&i); + } + + self.played.connect_clicked(clone!(stack, pd => move |_| { + on_played_button_clicked(&stack, &pd); + })); + + show_played_button(pd, &self.played); + } +} + pub fn podcast_widget(stack: >k::Stack, pd: &Podcast) -> gtk::Box { // Adapted from gnome-music AlbumWidget let builder = gtk::Builder::new_from_resource("/org/gnome/hammond/gtk/podcast_widget.ui"); From 94879b4256ca52817b3d0203ebbe48744c3d1f14 Mon Sep 17 00:00:00 2001 From: Jordan Petridis Date: Thu, 30 Nov 2017 21:38:21 +0200 Subject: [PATCH 04/41] Move get_pixbuf_from_path into hammond_gtk/src/utils.rs module. --- hammond-gtk/src/utils.rs | 41 +++++++++++++++++++++++++++++- hammond-gtk/src/views/podcasts.rs | 1 + hammond-gtk/src/widgets/podcast.rs | 38 +-------------------------- 3 files changed, 42 insertions(+), 38 deletions(-) diff --git a/hammond-gtk/src/utils.rs b/hammond-gtk/src/utils.rs index 2799f6d..794765c 100644 --- a/hammond-gtk/src/utils.rs +++ b/hammond-gtk/src/utils.rs @@ -1,8 +1,10 @@ use glib; use gtk; +use gdk_pixbuf::Pixbuf; use hammond_data::feed; -use hammond_data::Source; +use hammond_data::{Podcast, Source}; +use hammond_downloader::downloader; use std::{thread, time}; use std::cell::RefCell; @@ -61,3 +63,40 @@ fn refresh_podcasts_view() -> glib::Continue { }); glib::Continue(false) } + +pub fn get_pixbuf_from_path(pd: &Podcast) -> Option { + let img_path = downloader::cache_image(pd); + if let Some(i) = img_path { + Pixbuf::new_from_file_at_scale(&i, 256, 256, true).ok() + } else { + None + } +} + +#[cfg(test)] +mod tests { + use hammond_data::Source; + use hammond_data::feed::index; + use hammond_data::dbqueries; + use diesel::Identifiable; + use super::*; + + #[test] + fn test_get_pixbuf_from_path() { + let url = "http://www.newrustacean.com/feed.xml"; + + // Create and index a source + let source = Source::from_url(url).unwrap(); + // Copy it's id + let sid = source.id().clone(); + + // Convert Source it into a Feed and index it + let feed = source.into_feed().unwrap(); + index(vec![feed]); + + // Get the Podcast + let pd = dbqueries::get_podcast_from_source_id(sid).unwrap(); + let pxbuf = get_pixbuf_from_path(&pd); + assert!(pxbuf.is_some()); + } +} diff --git a/hammond-gtk/src/views/podcasts.rs b/hammond-gtk/src/views/podcasts.rs index 44de32e..2b55a96 100644 --- a/hammond-gtk/src/views/podcasts.rs +++ b/hammond-gtk/src/views/podcasts.rs @@ -7,6 +7,7 @@ use hammond_data::dbqueries; use hammond_data::Podcast; use widgets::podcast::*; +use utils::get_pixbuf_from_path; fn setup_empty_view(stack: >k::Stack) { let builder = gtk::Builder::new_from_resource("/org/gnome/hammond/gtk/empty_view.ui"); diff --git a/hammond-gtk/src/widgets/podcast.rs b/hammond-gtk/src/widgets/podcast.rs index e696dec..9e9afd6 100644 --- a/hammond-gtk/src/widgets/podcast.rs +++ b/hammond-gtk/src/widgets/podcast.rs @@ -1,6 +1,5 @@ use gtk::prelude::*; use gtk; -use gdk_pixbuf::Pixbuf; use std::fs; @@ -10,6 +9,7 @@ use hammond_downloader::downloader; use widgets::episode::episodes_listbox; use views::podcasts::update_podcasts_view; +use utils::get_pixbuf_from_path; #[derive(Debug)] struct PodcastWidget { @@ -154,15 +154,6 @@ fn show_played_button(pd: &Podcast, played_button: >k::Button) { } } -pub fn get_pixbuf_from_path(pd: &Podcast) -> Option { - let img_path = downloader::cache_image(pd); - if let Some(i) = img_path { - Pixbuf::new_from_file_at_scale(&i, 256, 256, true).ok() - } else { - None - } -} - pub fn setup_podcast_widget(stack: >k::Stack) { let builder = gtk::Builder::new_from_resource("/org/gnome/hammond/gtk/podcast_widget.ui"); let pd_widget: gtk::Box = builder.get_object("podcast_widget").unwrap(); @@ -180,30 +171,3 @@ pub fn update_podcast_widget(stack: >k::Stack, pd: &Podcast) { stack.set_visible_child_name(&vis); old.destroy(); } - -#[cfg(test)] -mod tests { - use hammond_data::Source; - use hammond_data::feed::index; - use diesel::Identifiable; - use super::*; - - #[test] - fn test_get_pixbuf_from_path() { - let url = "http://www.newrustacean.com/feed.xml"; - - // Create and index a source - let source = Source::from_url(url).unwrap(); - // Copy it's id - let sid = source.id().clone(); - - // Convert Source it into a Feed and index it - let feed = source.into_feed().unwrap(); - index(vec![feed]); - - // Get the Podcast - let pd = dbqueries::get_podcast_from_source_id(sid).unwrap(); - let pxbuf = get_pixbuf_from_path(&pd); - assert!(pxbuf.is_some()); - } -} From 84c918bbd5dda2579baff82f7b984e6bc20d18fd Mon Sep 17 00:00:00 2001 From: Jordan Petridis Date: Thu, 30 Nov 2017 21:39:21 +0200 Subject: [PATCH 05/41] Fix bug where the played button will always be shown by setting default state to not visible. --- hammond-gtk/resources/gtk/podcast_widget.ui | 1 - 1 file changed, 1 deletion(-) diff --git a/hammond-gtk/resources/gtk/podcast_widget.ui b/hammond-gtk/resources/gtk/podcast_widget.ui index f8e9b44..0241f05 100644 --- a/hammond-gtk/resources/gtk/podcast_widget.ui +++ b/hammond-gtk/resources/gtk/podcast_widget.ui @@ -109,7 +109,6 @@ Warn: This will delete downloaded content associated with this Podcast. - True True True Mark all episodes as Played. From f1f4d10fe32335dd55007ac38bfd30e0b7b24b7f Mon Sep 17 00:00:00 2001 From: Jordan Petridis Date: Fri, 1 Dec 2017 01:00:07 +0200 Subject: [PATCH 06/41] Add PopulatedView struct. --- hammond-gtk/src/views/podcasts.rs | 39 ++++++++++++++++++++++++++++++ hammond-gtk/src/widgets/podcast.rs | 15 +++++++++++- 2 files changed, 53 insertions(+), 1 deletion(-) diff --git a/hammond-gtk/src/views/podcasts.rs b/hammond-gtk/src/views/podcasts.rs index 2b55a96..a3de458 100644 --- a/hammond-gtk/src/views/podcasts.rs +++ b/hammond-gtk/src/views/podcasts.rs @@ -9,6 +9,45 @@ use hammond_data::Podcast; use widgets::podcast::*; use utils::get_pixbuf_from_path; +#[derive(Debug, Clone)] +pub struct PopulatedView { + container: gtk::Box, + flowbox: gtk::FlowBox, + viewport: gtk::Viewport, +} + +impl PopulatedView { + pub fn new() -> PopulatedView { + let builder = gtk::Builder::new_from_resource("/org/gnome/hammond/gtk/podcasts_view.ui"); + let container: gtk::Box = builder.get_object("fb_parent").unwrap(); + let flowbox: gtk::FlowBox = builder.get_object("flowbox").unwrap(); + let viewport: gtk::Viewport = builder.get_object("viewport").unwrap(); + + PopulatedView { + container, + flowbox, + viewport, + } + } + + pub fn init(&self, content_stack: >k::Stack) { + use gtk::WidgetExt; + + // TODO: handle unwraps. + let stack = content_stack; + self.flowbox + .connect_child_activated(clone!(stack => move |_, child| { + // This is such an ugly hack... + // let id = child.get_name().unwrap().parse::().unwrap(); + let id = WidgetExt::get_name(child).unwrap().parse::().unwrap(); + let parent = dbqueries::get_podcast_from_id(id).unwrap(); + on_flowbox_child_activate(&stack, &parent); + })); + // Populate the flowbox with the Podcasts. + populate_flowbox(&self.flowbox); + } +} + fn setup_empty_view(stack: >k::Stack) { let builder = gtk::Builder::new_from_resource("/org/gnome/hammond/gtk/empty_view.ui"); let view: gtk::Box = builder.get_object("empty_view").unwrap(); diff --git a/hammond-gtk/src/widgets/podcast.rs b/hammond-gtk/src/widgets/podcast.rs index 9e9afd6..f40bea2 100644 --- a/hammond-gtk/src/widgets/podcast.rs +++ b/hammond-gtk/src/widgets/podcast.rs @@ -72,7 +72,17 @@ impl PodcastWidget { on_played_button_clicked(&stack, &pd); })); - show_played_button(pd, &self.played); + self.show_played_button(pd); + } + + fn show_played_button(&self, pd: &Podcast) { + let new_episodes = dbqueries::get_pd_unplayed_episodes(pd); + + if let Ok(n) = new_episodes { + if !n.is_empty() { + self.played.show() + } + } } } @@ -118,6 +128,7 @@ pub fn podcast_widget(stack: >k::Stack, pd: &Podcast) -> gtk::Box { pd_widget } +// Note: Stack manipulation fn on_unsub_button_clicked(stack: >k::Stack, pd: &Podcast, unsub_button: >k::Button) { let res = dbqueries::remove_feed(pd); if res.is_ok() { @@ -154,6 +165,7 @@ fn show_played_button(pd: &Podcast, played_button: >k::Button) { } } +// Note: Stack manipulation pub fn setup_podcast_widget(stack: >k::Stack) { let builder = gtk::Builder::new_from_resource("/org/gnome/hammond/gtk/podcast_widget.ui"); let pd_widget: gtk::Box = builder.get_object("podcast_widget").unwrap(); @@ -161,6 +173,7 @@ pub fn setup_podcast_widget(stack: >k::Stack) { stack.add_named(&pd_widget, "pdw"); } +// Note: Stack manipulation pub fn update_podcast_widget(stack: >k::Stack, pd: &Podcast) { let old = stack.get_child_by_name("pdw").unwrap(); let pdw = podcast_widget(stack, pd); From 774e5b38a0d445e33459be66cbd2bbe5801b4e15 Mon Sep 17 00:00:00 2001 From: Jordan Petridis Date: Fri, 1 Dec 2017 01:03:10 +0200 Subject: [PATCH 07/41] Add EmptyView Struct. --- hammond-gtk/src/views/empty.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 hammond-gtk/src/views/empty.rs diff --git a/hammond-gtk/src/views/empty.rs b/hammond-gtk/src/views/empty.rs new file mode 100644 index 0000000..c45ef47 --- /dev/null +++ b/hammond-gtk/src/views/empty.rs @@ -0,0 +1,15 @@ +use gtk; + +#[derive(Debug, Clone)] +pub struct EmptyView { + container: gtk::Box, +} + +impl EmptyView { + pub fn new() -> EmptyView { + let builder = gtk::Builder::new_from_resource("/org/gnome/hammond/gtk/empty_view.ui"); + let view: gtk::Box = builder.get_object("empty_view").unwrap(); + + EmptyView { container: view } + } +} From dd0034327b3c43041c56557b17ce19e28066b0f3 Mon Sep 17 00:00:00 2001 From: Jordan Petridis Date: Fri, 1 Dec 2017 01:12:25 +0200 Subject: [PATCH 08/41] Add Content Struct. --- hammond-gtk/src/content.rs | 60 ++++++++++++++++++++++++++++++ hammond-gtk/src/main.rs | 1 + hammond-gtk/src/views/empty.rs | 2 +- hammond-gtk/src/views/mod.rs | 1 + hammond-gtk/src/views/podcasts.rs | 2 +- hammond-gtk/src/widgets/podcast.rs | 6 +-- 6 files changed, 67 insertions(+), 5 deletions(-) create mode 100644 hammond-gtk/src/content.rs diff --git a/hammond-gtk/src/content.rs b/hammond-gtk/src/content.rs new file mode 100644 index 0000000..85cd98f --- /dev/null +++ b/hammond-gtk/src/content.rs @@ -0,0 +1,60 @@ +use gtk; +use gtk::prelude::*; +// use gdk_pixbuf::Pixbuf; + +// use diesel::Identifiable; + +// use hammond_data::dbqueries; +// use hammond_data::Podcast; + +use widgets::podcast::PodcastWidget; +use views::podcasts::PopulatedView; +use views::empty::EmptyView; + +#[derive(Debug)] +pub struct Content { + pub stack: gtk::Stack, + pub state: ContentState, + widget: PodcastWidget, + podcasts: PopulatedView, + empty: EmptyView, +} + +#[derive(Debug)] +pub enum ContentState { + Widget(PodcastWidget), + Empty(EmptyView), + Populated(PopulatedView), +} + +impl Content { + pub fn new() -> Content { + let stack = gtk::Stack::new(); + let widget = PodcastWidget::new(); + let pop = PopulatedView::new(); + let empty = EmptyView::new(); + // TODO: Avoid cloning + let state = ContentState::Populated(pop.clone()); + + let content = Content { + stack, + state, + widget, + empty, + podcasts: pop, + }; + + content.setup_stack(); + content.podcasts.init(&content.stack); + content + } + + fn setup_stack(&self) { + self.stack + .set_transition_type(gtk::StackTransitionType::SlideLeftRight); + + self.stack.add_named(&self.widget.container, "pdw"); // Rename into "widget" + self.stack.add_named(&self.podcasts.container, "fb_parent"); // Rename into "podcasts" + self.stack.add_named(&self.empty.container, "empty"); // Rename into "empty" + } +} diff --git a/hammond-gtk/src/main.rs b/hammond-gtk/src/main.rs index 15dfb31..56e089a 100644 --- a/hammond-gtk/src/main.rs +++ b/hammond-gtk/src/main.rs @@ -45,6 +45,7 @@ macro_rules! clone { mod views; mod widgets; mod headerbar; +mod content; mod utils; mod static_resource; diff --git a/hammond-gtk/src/views/empty.rs b/hammond-gtk/src/views/empty.rs index c45ef47..1c93da7 100644 --- a/hammond-gtk/src/views/empty.rs +++ b/hammond-gtk/src/views/empty.rs @@ -2,7 +2,7 @@ use gtk; #[derive(Debug, Clone)] pub struct EmptyView { - container: gtk::Box, + pub container: gtk::Box, } impl EmptyView { diff --git a/hammond-gtk/src/views/mod.rs b/hammond-gtk/src/views/mod.rs index 398798f..9c47e7d 100644 --- a/hammond-gtk/src/views/mod.rs +++ b/hammond-gtk/src/views/mod.rs @@ -1 +1,2 @@ pub mod podcasts; +pub mod empty; diff --git a/hammond-gtk/src/views/podcasts.rs b/hammond-gtk/src/views/podcasts.rs index a3de458..fee922a 100644 --- a/hammond-gtk/src/views/podcasts.rs +++ b/hammond-gtk/src/views/podcasts.rs @@ -11,7 +11,7 @@ use utils::get_pixbuf_from_path; #[derive(Debug, Clone)] pub struct PopulatedView { - container: gtk::Box, + pub container: gtk::Box, flowbox: gtk::FlowBox, viewport: gtk::Viewport, } diff --git a/hammond-gtk/src/widgets/podcast.rs b/hammond-gtk/src/widgets/podcast.rs index f40bea2..68a940e 100644 --- a/hammond-gtk/src/widgets/podcast.rs +++ b/hammond-gtk/src/widgets/podcast.rs @@ -12,8 +12,8 @@ use views::podcasts::update_podcasts_view; use utils::get_pixbuf_from_path; #[derive(Debug)] -struct PodcastWidget { - container: gtk::Box, +pub struct PodcastWidget { + pub container: gtk::Box, cover: gtk::Image, title: gtk::Label, description: gtk::TextView, @@ -23,7 +23,7 @@ struct PodcastWidget { } impl PodcastWidget { - fn new() -> PodcastWidget { + pub fn new() -> PodcastWidget { // Adapted from gnome-music AlbumWidget let builder = gtk::Builder::new_from_resource("/org/gnome/hammond/gtk/podcast_widget.ui"); let container: gtk::Box = builder.get_object("podcast_widget").unwrap(); From 5414dbdb3796c374ef8229097e77a654dfe3bc68 Mon Sep 17 00:00:00 2001 From: Jordan Petridis Date: Fri, 1 Dec 2017 01:20:49 +0200 Subject: [PATCH 09/41] Wire and use the new Header struct instead. --- hammond-gtk/src/content.rs | 8 ++++++-- hammond-gtk/src/headerbar.rs | 10 ++++++++-- hammond-gtk/src/main.rs | 6 ++++-- 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/hammond-gtk/src/content.rs b/hammond-gtk/src/content.rs index 85cd98f..642078f 100644 --- a/hammond-gtk/src/content.rs +++ b/hammond-gtk/src/content.rs @@ -44,8 +44,7 @@ impl Content { podcasts: pop, }; - content.setup_stack(); - content.podcasts.init(&content.stack); + content.init(); content } @@ -57,4 +56,9 @@ impl Content { self.stack.add_named(&self.podcasts.container, "fb_parent"); // Rename into "podcasts" self.stack.add_named(&self.empty.container, "empty"); // Rename into "empty" } + + fn init(&self) { + self.setup_stack(); + self.podcasts.init(&self.stack); + } } diff --git a/hammond-gtk/src/headerbar.rs b/hammond-gtk/src/headerbar.rs index 3ccf41e..56aa666 100644 --- a/hammond-gtk/src/headerbar.rs +++ b/hammond-gtk/src/headerbar.rs @@ -9,14 +9,14 @@ use utils; #[derive(Debug)] pub struct Header { - container: gtk::HeaderBar, + pub container: gtk::HeaderBar, home: gtk::Button, refresh: gtk::Button, add_toggle: gtk::MenuButton, } impl Header { - fn new() -> Header { + pub fn new() -> Header { let builder = gtk::Builder::new_from_resource("/org/gnome/hammond/gtk/headerbar.ui"); let header: gtk::HeaderBar = builder.get_object("headerbar1").unwrap(); @@ -32,6 +32,12 @@ impl Header { } } + pub fn new_initialized(stack: >k::Stack) -> Header { + let header = Header::new(); + header.init(stack); + header + } + fn init(&self, stack: >k::Stack) { let builder = gtk::Builder::new_from_resource("/org/gnome/hammond/gtk/headerbar.ui"); diff --git a/hammond-gtk/src/main.rs b/hammond-gtk/src/main.rs index 56e089a..0499015 100644 --- a/hammond-gtk/src/main.rs +++ b/hammond-gtk/src/main.rs @@ -101,8 +101,10 @@ fn build_ui(app: >k::Application) { }); // Get the headerbar - let header = headerbar::get_headerbar(&stack); - window.set_titlebar(&header); + // let header = headerbar::get_headerbar(&stack); + // window.set_titlebar(&header); + let header = headerbar::Header::new_initialized(&stack); + window.set_titlebar(&header.container); window.show_all(); window.activate(); From b4b2f24c77e9fe772c42c4a2881161cb31ba0d34 Mon Sep 17 00:00:00 2001 From: Jordan Petridis Date: Fri, 1 Dec 2017 01:30:19 +0200 Subject: [PATCH 10/41] Use content struct instead of plain stack. --- hammond-gtk/resources/gtk/podcasts_view.ui | 2 +- hammond-gtk/src/content.rs | 3 +++ hammond-gtk/src/main.rs | 6 ++++-- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/hammond-gtk/resources/gtk/podcasts_view.ui b/hammond-gtk/resources/gtk/podcasts_view.ui index 4cdc447..5a3dff6 100644 --- a/hammond-gtk/resources/gtk/podcasts_view.ui +++ b/hammond-gtk/resources/gtk/podcasts_view.ui @@ -12,7 +12,7 @@ True in - + True False diff --git a/hammond-gtk/src/content.rs b/hammond-gtk/src/content.rs index 642078f..05eefb4 100644 --- a/hammond-gtk/src/content.rs +++ b/hammond-gtk/src/content.rs @@ -55,6 +55,9 @@ impl Content { self.stack.add_named(&self.widget.container, "pdw"); // Rename into "widget" self.stack.add_named(&self.podcasts.container, "fb_parent"); // Rename into "podcasts" self.stack.add_named(&self.empty.container, "empty"); // Rename into "empty" + + // FIXME: needs actuall logic + self.stack.set_visible_child_name("fb_parent") } fn init(&self) { diff --git a/hammond-gtk/src/main.rs b/hammond-gtk/src/main.rs index 0499015..fd0a024 100644 --- a/hammond-gtk/src/main.rs +++ b/hammond-gtk/src/main.rs @@ -50,7 +50,7 @@ mod content; mod utils; mod static_resource; -use views::podcasts; +// use views::podcasts; /* THIS IS STILL A PROTOTYPE. @@ -66,7 +66,9 @@ fn build_ui(app: >k::Application) { let window = gtk::ApplicationWindow::new(app); window.set_default_size(1150, 650); // Setup the Stack that will manage the switch between podcasts_view and podcast_widget. - let stack = podcasts::setup_stack(); + // let stack = podcasts::setup_stack(); + let content = content::Content::new(); + let stack = content.stack.clone(); window.add(&stack); window.connect_delete_event(|w, _| { From 326ee75cd8c56b4a1850f794452191d0b7edd5cd Mon Sep 17 00:00:00 2001 From: Jordan Petridis Date: Fri, 1 Dec 2017 02:57:55 +0200 Subject: [PATCH 11/41] Remove old implementation. --- hammond-gtk/src/app.rs | 38 +++++++++++++++++ hammond-gtk/src/content.rs | 5 +-- hammond-gtk/src/headerbar.rs | 43 -------------------- hammond-gtk/src/main.rs | 8 +--- hammond-gtk/src/views/podcasts.rs | 24 +++-------- hammond-gtk/src/widgets/podcast.rs | 65 ++---------------------------- 6 files changed, 50 insertions(+), 133 deletions(-) create mode 100644 hammond-gtk/src/app.rs diff --git a/hammond-gtk/src/app.rs b/hammond-gtk/src/app.rs new file mode 100644 index 0000000..eab786a --- /dev/null +++ b/hammond-gtk/src/app.rs @@ -0,0 +1,38 @@ +use gtk::prelude::*; +use gtk::{Window, WindowType}; + +use headerbar::Header; +use content::Content; + +#[derive(Debug)] +pub struct App<'a> { + window: Window, + header: Header, + content: Content<'a>, +} + +impl <'a>App<'a> { + pub fn new() -> App<'a> { + let window = Window::new(WindowType::Toplevel); + let content = Content::new(); + let header = Header::new(content.stack.clone()); + + window.set_default_size(1150, 650); + window.connect_delete_event(|w, _| { + w.destroy(); + Inhibit(false) + }); + + window.set_titlebar(&header.container); + window.add(&content.stack); + + window.show_all(); + window.activate(); + + App { + window, + header, + content, + } + } +} diff --git a/hammond-gtk/src/content.rs b/hammond-gtk/src/content.rs index 05eefb4..cb492c7 100644 --- a/hammond-gtk/src/content.rs +++ b/hammond-gtk/src/content.rs @@ -4,8 +4,7 @@ use gtk::prelude::*; // use diesel::Identifiable; -// use hammond_data::dbqueries; -// use hammond_data::Podcast; +use hammond_data::Podcast; use widgets::podcast::PodcastWidget; use views::podcasts::PopulatedView; @@ -16,7 +15,7 @@ pub struct Content { pub stack: gtk::Stack, pub state: ContentState, widget: PodcastWidget, - podcasts: PopulatedView, + pub podcasts: PopulatedView, empty: EmptyView, } diff --git a/hammond-gtk/src/headerbar.rs b/hammond-gtk/src/headerbar.rs index 56aa666..9675a3f 100644 --- a/hammond-gtk/src/headerbar.rs +++ b/hammond-gtk/src/headerbar.rs @@ -75,49 +75,6 @@ impl Header { } } -pub fn get_headerbar(stack: >k::Stack) -> gtk::HeaderBar { - let builder = gtk::Builder::new_from_resource("/org/gnome/hammond/gtk/headerbar.ui"); - - let header: gtk::HeaderBar = builder.get_object("headerbar1").unwrap(); - let home_button: gtk::Button = builder.get_object("homebutton").unwrap(); - let refresh_button: gtk::Button = builder.get_object("refbutton").unwrap(); - - let add_toggle_button: gtk::MenuButton = builder.get_object("add-toggle-button").unwrap(); - let add_popover: gtk::Popover = builder.get_object("add-popover").unwrap(); - let new_url: gtk::Entry = builder.get_object("new-url").unwrap(); - let add_button: gtk::Button = builder.get_object("add-button").unwrap(); - // TODO: check if url exists in the db and lock the button - new_url.connect_changed(move |url| { - println!("{:?}", url.get_text()); - }); - - add_button.connect_clicked(clone!(stack, add_popover, new_url => move |_| { - on_add_bttn_clicked(&stack, &new_url); - - // TODO: lock the button instead of hiding and add notification of feed added. - // TODO: map the spinner - add_popover.hide(); - })); - add_toggle_button.set_popover(&add_popover); - - // TODO: make it a back arrow button, that will hide when appropriate, - // and add a StackSwitcher when more views are added. - home_button.connect_clicked(clone!(stack => move |_| { - let vis = stack.get_visible_child_name().unwrap(); - stack.set_visible_child_name("fb_parent"); - if vis != "pdw" { - update_podcasts_view(&stack); - } - })); - - // FIXME: There appears to be a memmory leak here. - refresh_button.connect_clicked(clone!(stack => move |_| { - utils::refresh_feed(&stack, None, None); - })); - - header -} - fn on_add_bttn_clicked(stack: >k::Stack, entry: >k::Entry) { let url = entry.get_text().unwrap_or_default(); let url = url_cleaner(&url); diff --git a/hammond-gtk/src/main.rs b/hammond-gtk/src/main.rs index fd0a024..ff4e601 100644 --- a/hammond-gtk/src/main.rs +++ b/hammond-gtk/src/main.rs @@ -1,5 +1,3 @@ -#![allow(dead_code)] - extern crate gdk; extern crate gdk_pixbuf; extern crate gio; @@ -67,8 +65,8 @@ fn build_ui(app: >k::Application) { window.set_default_size(1150, 650); // Setup the Stack that will manage the switch between podcasts_view and podcast_widget. // let stack = podcasts::setup_stack(); - let content = content::Content::new(); - let stack = content.stack.clone(); + let ct = content::Content::new(); + let stack = ct.stack.clone(); window.add(&stack); window.connect_delete_event(|w, _| { @@ -103,8 +101,6 @@ fn build_ui(app: >k::Application) { }); // Get the headerbar - // let header = headerbar::get_headerbar(&stack); - // window.set_titlebar(&header); let header = headerbar::Header::new_initialized(&stack); window.set_titlebar(&header.container); diff --git a/hammond-gtk/src/views/podcasts.rs b/hammond-gtk/src/views/podcasts.rs index fee922a..1690ef1 100644 --- a/hammond-gtk/src/views/podcasts.rs +++ b/hammond-gtk/src/views/podcasts.rs @@ -12,7 +12,7 @@ use utils::get_pixbuf_from_path; #[derive(Debug, Clone)] pub struct PopulatedView { pub container: gtk::Box, - flowbox: gtk::FlowBox, + pub flowbox: gtk::FlowBox, viewport: gtk::Viewport, } @@ -48,12 +48,6 @@ impl PopulatedView { } } -fn setup_empty_view(stack: >k::Stack) { - let builder = gtk::Builder::new_from_resource("/org/gnome/hammond/gtk/empty_view.ui"); - let view: gtk::Box = builder.get_object("empty_view").unwrap(); - stack.add_named(&view, "empty"); -} - fn show_empty_view(stack: >k::Stack) { stack.set_visible_child_name("empty"); @@ -118,11 +112,12 @@ fn configure_banner(pd: &Podcast, banner: >k::Image, banner_title: >k::Label fn on_flowbox_child_activate(stack: >k::Stack, parent: &Podcast) { let old = stack.get_child_by_name("pdw").unwrap(); - let pdw = podcast_widget(stack, parent); + let pdw = PodcastWidget::new(); + pdw.init(stack, parent); stack.remove(&old); - stack.add_named(&pdw, "pdw"); - stack.set_visible_child(&pdw); + stack.add_named(&pdw.container, "pdw"); + stack.set_visible_child_name("pdw"); // aggresive memory cleanup // probably not needed @@ -146,15 +141,6 @@ fn setup_podcasts_flowbox(stack: >k::Stack) -> gtk::FlowBox { flowbox } -pub fn setup_stack() -> gtk::Stack { - let stack = gtk::Stack::new(); - stack.set_transition_type(gtk::StackTransitionType::SlideLeftRight); - setup_empty_view(&stack); - setup_podcast_widget(&stack); - setup_podcasts_flowbox(&stack); - stack -} - pub fn update_podcasts_view(stack: >k::Stack) { let vis = stack.get_visible_child_name().unwrap(); let old = stack.get_child_by_name("fb_parent").unwrap(); diff --git a/hammond-gtk/src/widgets/podcast.rs b/hammond-gtk/src/widgets/podcast.rs index 68a940e..dc8c458 100644 --- a/hammond-gtk/src/widgets/podcast.rs +++ b/hammond-gtk/src/widgets/podcast.rs @@ -86,48 +86,6 @@ impl PodcastWidget { } } -pub fn podcast_widget(stack: >k::Stack, pd: &Podcast) -> gtk::Box { - // Adapted from gnome-music AlbumWidget - let builder = gtk::Builder::new_from_resource("/org/gnome/hammond/gtk/podcast_widget.ui"); - let pd_widget: gtk::Box = builder.get_object("podcast_widget").unwrap(); - - let cover: gtk::Image = builder.get_object("cover").unwrap(); - let title_label: gtk::Label = builder.get_object("title_label").unwrap(); - let desc_text_view: gtk::TextView = builder.get_object("desc_text_view").unwrap(); - let view: gtk::Viewport = builder.get_object("view").unwrap(); - let unsub_button: gtk::Button = builder.get_object("unsub_button").unwrap(); - let played_button: gtk::Button = builder.get_object("mark_all_played_button").unwrap(); - - // TODO: should spawn a thread to avoid locking the UI probably. - unsub_button.connect_clicked(clone!(stack, pd => move |bttn| { - on_unsub_button_clicked(&stack, &pd, bttn); - })); - - title_label.set_text(pd.title()); - let listbox = episodes_listbox(pd); - if let Ok(l) = listbox { - view.add(&l); - } - - { - let buff = desc_text_view.get_buffer().unwrap(); - buff.set_text(pd.description()); - } - - let img = get_pixbuf_from_path(pd); - if let Some(i) = img { - cover.set_from_pixbuf(&i); - } - - played_button.connect_clicked(clone!(stack, pd => move |_| { - on_played_button_clicked(&stack, &pd); - })); - - show_played_button(pd, &played_button); - - pd_widget -} - // Note: Stack manipulation fn on_unsub_button_clicked(stack: >k::Stack, pd: &Podcast, unsub_button: >k::Button) { let res = dbqueries::remove_feed(pd); @@ -155,32 +113,15 @@ fn on_played_button_clicked(stack: >k::Stack, pd: &Podcast) { update_podcast_widget(stack, pd); } -fn show_played_button(pd: &Podcast, played_button: >k::Button) { - let new_episodes = dbqueries::get_pd_unplayed_episodes(pd); - - if let Ok(n) = new_episodes { - if !n.is_empty() { - played_button.show() - } - } -} - -// Note: Stack manipulation -pub fn setup_podcast_widget(stack: >k::Stack) { - let builder = gtk::Builder::new_from_resource("/org/gnome/hammond/gtk/podcast_widget.ui"); - let pd_widget: gtk::Box = builder.get_object("podcast_widget").unwrap(); - - stack.add_named(&pd_widget, "pdw"); -} - // Note: Stack manipulation pub fn update_podcast_widget(stack: >k::Stack, pd: &Podcast) { let old = stack.get_child_by_name("pdw").unwrap(); - let pdw = podcast_widget(stack, pd); + let pdw = PodcastWidget::new(); + pdw.init(stack, pd); let vis = stack.get_visible_child_name().unwrap(); stack.remove(&old); - stack.add_named(&pdw, "pdw"); + stack.add_named(&pdw.container, "pdw"); stack.set_visible_child_name(&vis); old.destroy(); } From 300fc3467d0491ea15ec879deba3981e03d05e24 Mon Sep 17 00:00:00 2001 From: Jordan Petridis Date: Fri, 1 Dec 2017 03:50:23 +0200 Subject: [PATCH 12/41] Remove more stuff. --- hammond-gtk/src/views/podcasts.rs | 66 +++++++------------------------ 1 file changed, 15 insertions(+), 51 deletions(-) diff --git a/hammond-gtk/src/views/podcasts.rs b/hammond-gtk/src/views/podcasts.rs index 1690ef1..2514279 100644 --- a/hammond-gtk/src/views/podcasts.rs +++ b/hammond-gtk/src/views/podcasts.rs @@ -30,11 +30,10 @@ impl PopulatedView { } } - pub fn init(&self, content_stack: >k::Stack) { + pub fn init(&self, stack: >k::Stack) { use gtk::WidgetExt; // TODO: handle unwraps. - let stack = content_stack; self.flowbox .connect_child_activated(clone!(stack => move |_, child| { // This is such an ugly hack... @@ -44,25 +43,19 @@ impl PopulatedView { on_flowbox_child_activate(&stack, &parent); })); // Populate the flowbox with the Podcasts. - populate_flowbox(&self.flowbox); + self.populate_flowbox(); } -} -fn show_empty_view(stack: >k::Stack) { - stack.set_visible_child_name("empty"); + fn populate_flowbox(&self) { + let podcasts = dbqueries::get_podcasts(); - info!("Empty view."); -} - -fn populate_flowbox(flowbox: >k::FlowBox) { - let podcasts = dbqueries::get_podcasts(); - - if let Ok(pds) = podcasts { - pds.iter().for_each(|parent| { - let f = create_flowbox_child(parent); - flowbox.add(&f); - }); - flowbox.show_all(); + if let Ok(pds) = podcasts { + pds.iter().for_each(|parent| { + let f = create_flowbox_child(parent); + self.flowbox.add(&f); + }); + self.flowbox.show_all(); + } } } @@ -124,29 +117,15 @@ fn on_flowbox_child_activate(stack: >k::Stack, parent: &Podcast) { old.destroy(); } -fn setup_podcasts_flowbox(stack: >k::Stack) -> gtk::FlowBox { - let builder = gtk::Builder::new_from_resource("/org/gnome/hammond/gtk/podcasts_view.ui"); - let fb_parent: gtk::Box = builder.get_object("fb_parent").unwrap(); - let flowbox: gtk::FlowBox = builder.get_object("flowbox").unwrap(); - init_flowbox(stack, &flowbox); - - stack.add_named(&fb_parent, "fb_parent"); - - if flowbox.get_children().is_empty() { - show_empty_view(stack); - } else { - stack.set_visible_child(&fb_parent); - }; - - flowbox -} - pub fn update_podcasts_view(stack: >k::Stack) { let vis = stack.get_visible_child_name().unwrap(); let old = stack.get_child_by_name("fb_parent").unwrap(); stack.remove(&old); - let flowbox = setup_podcasts_flowbox(stack); + let pdw = PopulatedView::new(); + pdw.init(stack); + stack.add_named(&pdw.container, "fb_parent"); + let flowbox = &pdw.flowbox; if vis == "empty" && !flowbox.get_children().is_empty() { stack.set_visible_child_name("fb_parent"); @@ -161,18 +140,3 @@ pub fn update_podcasts_view(stack: >k::Stack) { // probably not needed old.destroy(); } - -fn init_flowbox(stack: >k::Stack, flowbox: >k::FlowBox) { - use gtk::WidgetExt; - - // TODO: handle unwraps. - flowbox.connect_child_activated(clone!(stack => move |_, child| { - // This is such an ugly hack... - // let id = child.get_name().unwrap().parse::().unwrap(); - let id = WidgetExt::get_name(child).unwrap().parse::().unwrap(); - let parent = dbqueries::get_podcast_from_id(id).unwrap(); - on_flowbox_child_activate(&stack, &parent); - })); - // Populate the flowbox with the Podcasts. - populate_flowbox(flowbox); -} From dcc541d8323aeff6eddf1c296d395106b7cca73f Mon Sep 17 00:00:00 2001 From: Jordan Petridis Date: Fri, 1 Dec 2017 04:22:26 +0200 Subject: [PATCH 13/41] Added a PodcastChild struct and groupd some flowbox_child methods. --- hammond-gtk/src/content.rs | 2 - hammond-gtk/src/views/podcasts.rs | 96 ++++++++++++++++++++----------- 2 files changed, 62 insertions(+), 36 deletions(-) diff --git a/hammond-gtk/src/content.rs b/hammond-gtk/src/content.rs index cb492c7..99e5ff9 100644 --- a/hammond-gtk/src/content.rs +++ b/hammond-gtk/src/content.rs @@ -4,8 +4,6 @@ use gtk::prelude::*; // use diesel::Identifiable; -use hammond_data::Podcast; - use widgets::podcast::PodcastWidget; use views::podcasts::PopulatedView; use views::empty::EmptyView; diff --git a/hammond-gtk/src/views/podcasts.rs b/hammond-gtk/src/views/podcasts.rs index 2514279..b8d106b 100644 --- a/hammond-gtk/src/views/podcasts.rs +++ b/hammond-gtk/src/views/podcasts.rs @@ -12,10 +12,20 @@ use utils::get_pixbuf_from_path; #[derive(Debug, Clone)] pub struct PopulatedView { pub container: gtk::Box, - pub flowbox: gtk::FlowBox, + flowbox: gtk::FlowBox, viewport: gtk::Viewport, } +#[derive(Debug)] +struct PodcastChild { + container: gtk::Box, + title: gtk::Label, + cover: gtk::Image, + banner: gtk::Image, + number: gtk::Label, + child: gtk::FlowBoxChild, +} + impl PopulatedView { pub fn new() -> PopulatedView { let builder = gtk::Builder::new_from_resource("/org/gnome/hammond/gtk/podcasts_view.ui"); @@ -51,53 +61,71 @@ impl PopulatedView { if let Ok(pds) = podcasts { pds.iter().for_each(|parent| { - let f = create_flowbox_child(parent); - self.flowbox.add(&f); + let flowbox_child = PodcastChild::new_initialized(parent); + self.flowbox.add(&flowbox_child.child); }); self.flowbox.show_all(); } } } -fn create_flowbox_child(pd: &Podcast) -> gtk::FlowBoxChild { - let builder = gtk::Builder::new_from_resource("/org/gnome/hammond/gtk/podcasts_child.ui"); +impl PodcastChild { + fn new() -> PodcastChild { + let builder = gtk::Builder::new_from_resource("/org/gnome/hammond/gtk/podcasts_child.ui"); - // Copy of gnome-music AlbumWidget - let box_: gtk::Box = builder.get_object("fb_child").unwrap(); - let pd_title: gtk::Label = builder.get_object("pd_title").unwrap(); - let pd_cover: gtk::Image = builder.get_object("pd_cover").unwrap(); - let banner: gtk::Image = builder.get_object("banner").unwrap(); - let banner_title: gtk::Label = builder.get_object("banner_label").unwrap(); + // Copy of gnome-music AlbumWidget + let container: gtk::Box = builder.get_object("fb_child").unwrap(); + let title: gtk::Label = builder.get_object("pd_title").unwrap(); + let cover: gtk::Image = builder.get_object("pd_cover").unwrap(); + let banner: gtk::Image = builder.get_object("banner").unwrap(); + let number: gtk::Label = builder.get_object("banner_label").unwrap(); - pd_title.set_text(pd.title()); + let child = gtk::FlowBoxChild::new(); + child.add(&container); - let cover = get_pixbuf_from_path(pd); - if let Some(img) = cover { - pd_cover.set_from_pixbuf(&img); - }; + PodcastChild { + container, + title, + cover, + banner, + number, + child, + } + } - configure_banner(pd, &banner, &banner_title); + fn init(&self, pd: &Podcast) { + self.title.set_text(pd.title()); - let fbc = gtk::FlowBoxChild::new(); - // There's probably a better way to store the id somewhere. - // fbc.set_name(&pd.id().to_string()); - WidgetExt::set_name(&fbc, &pd.id().to_string()); - fbc.add(&box_); - fbc -} + let cover = get_pixbuf_from_path(pd); + if let Some(img) = cover { + self.cover.set_from_pixbuf(&img); + }; -fn configure_banner(pd: &Podcast, banner: >k::Image, banner_title: >k::Label) { - let bann = Pixbuf::new_from_resource_at_scale("/org/gnome/hammond/banner.png", 256, 256, true); - if let Ok(b) = bann { - banner.set_from_pixbuf(&b); + WidgetExt::set_name(&self.child, &pd.id().to_string()); + self.configure_banner(pd); + } - let new_episodes = dbqueries::get_pd_unplayed_episodes(pd); + pub fn new_initialized(pd: &Podcast) -> PodcastChild { + let child = PodcastChild::new(); + child.init(pd); - if let Ok(n) = new_episodes { - if !n.is_empty() { - banner_title.set_text(&n.len().to_string()); - banner.show(); - banner_title.show(); + child + } + + fn configure_banner(&self, pd: &Podcast) { + let bann = + Pixbuf::new_from_resource_at_scale("/org/gnome/hammond/banner.png", 256, 256, true); + if let Ok(b) = bann { + self.banner.set_from_pixbuf(&b); + + let new_episodes = dbqueries::get_pd_unplayed_episodes(pd); + + if let Ok(n) = new_episodes { + if !n.is_empty() { + self.number.set_text(&n.len().to_string()); + self.banner.show(); + self.number.show(); + } } } } From 3fca086d14de541582358a038658508186247d2f Mon Sep 17 00:00:00 2001 From: Jordan Petridis Date: Fri, 1 Dec 2017 05:32:47 +0200 Subject: [PATCH 14/41] Renamed stack children. --- hammond-gtk/src/content.rs | 10 ++++++---- hammond-gtk/src/headerbar.rs | 4 ++-- hammond-gtk/src/views/podcasts.rs | 14 +++++++------- hammond-gtk/src/widgets/podcast.rs | 6 +++--- 4 files changed, 18 insertions(+), 16 deletions(-) diff --git a/hammond-gtk/src/content.rs b/hammond-gtk/src/content.rs index 99e5ff9..2a8659a 100644 --- a/hammond-gtk/src/content.rs +++ b/hammond-gtk/src/content.rs @@ -18,6 +18,8 @@ pub struct Content { } #[derive(Debug)] +#[allow(dead_code)] +// TODO: find a way to wrap gtk::Stack into a State machine. pub enum ContentState { Widget(PodcastWidget), Empty(EmptyView), @@ -49,12 +51,12 @@ impl Content { self.stack .set_transition_type(gtk::StackTransitionType::SlideLeftRight); - self.stack.add_named(&self.widget.container, "pdw"); // Rename into "widget" - self.stack.add_named(&self.podcasts.container, "fb_parent"); // Rename into "podcasts" - self.stack.add_named(&self.empty.container, "empty"); // Rename into "empty" + self.stack.add_named(&self.widget.container, "widget"); + self.stack.add_named(&self.podcasts.container, "podcasts"); + self.stack.add_named(&self.empty.container, "empty"); // FIXME: needs actuall logic - self.stack.set_visible_child_name("fb_parent") + self.stack.set_visible_child_name("podcasts") } fn init(&self) { diff --git a/hammond-gtk/src/headerbar.rs b/hammond-gtk/src/headerbar.rs index 9675a3f..7e13ffa 100644 --- a/hammond-gtk/src/headerbar.rs +++ b/hammond-gtk/src/headerbar.rs @@ -62,8 +62,8 @@ impl Header { // and add a StackSwitcher when more views are added. self.home.connect_clicked(clone!(stack => move |_| { let vis = stack.get_visible_child_name().unwrap(); - stack.set_visible_child_name("fb_parent"); - if vis != "pdw" { + stack.set_visible_child_name("podcasts"); + if vis != "widget" { update_podcasts_view(&stack); } })); diff --git a/hammond-gtk/src/views/podcasts.rs b/hammond-gtk/src/views/podcasts.rs index b8d106b..16168d1 100644 --- a/hammond-gtk/src/views/podcasts.rs +++ b/hammond-gtk/src/views/podcasts.rs @@ -132,13 +132,13 @@ impl PodcastChild { } fn on_flowbox_child_activate(stack: >k::Stack, parent: &Podcast) { - let old = stack.get_child_by_name("pdw").unwrap(); + let old = stack.get_child_by_name("widget").unwrap(); let pdw = PodcastWidget::new(); pdw.init(stack, parent); stack.remove(&old); - stack.add_named(&pdw.container, "pdw"); - stack.set_visible_child_name("pdw"); + stack.add_named(&pdw.container, "widget"); + stack.set_visible_child_name("widget"); // aggresive memory cleanup // probably not needed @@ -147,17 +147,17 @@ fn on_flowbox_child_activate(stack: >k::Stack, parent: &Podcast) { pub fn update_podcasts_view(stack: >k::Stack) { let vis = stack.get_visible_child_name().unwrap(); - let old = stack.get_child_by_name("fb_parent").unwrap(); + let old = stack.get_child_by_name("podcasts").unwrap(); stack.remove(&old); let pdw = PopulatedView::new(); pdw.init(stack); - stack.add_named(&pdw.container, "fb_parent"); + stack.add_named(&pdw.container, "podcasts"); let flowbox = &pdw.flowbox; if vis == "empty" && !flowbox.get_children().is_empty() { - stack.set_visible_child_name("fb_parent"); - } else if vis == "fb_parent" && flowbox.get_children().is_empty() { + stack.set_visible_child_name("podcasts"); + } else if vis == "podcasts" && flowbox.get_children().is_empty() { stack.set_visible_child_name("empty"); } else { // preserve the visible widget diff --git a/hammond-gtk/src/widgets/podcast.rs b/hammond-gtk/src/widgets/podcast.rs index dc8c458..116e221 100644 --- a/hammond-gtk/src/widgets/podcast.rs +++ b/hammond-gtk/src/widgets/podcast.rs @@ -103,7 +103,7 @@ fn on_unsub_button_clicked(stack: >k::Stack, pd: &Podcast, unsub_button: >k: } }; } - stack.set_visible_child_name("fb_parent"); + stack.set_visible_child_name("podcasts"); update_podcasts_view(stack); } @@ -115,13 +115,13 @@ fn on_played_button_clicked(stack: >k::Stack, pd: &Podcast) { // Note: Stack manipulation pub fn update_podcast_widget(stack: >k::Stack, pd: &Podcast) { - let old = stack.get_child_by_name("pdw").unwrap(); + let old = stack.get_child_by_name("widget").unwrap(); let pdw = PodcastWidget::new(); pdw.init(stack, pd); let vis = stack.get_visible_child_name().unwrap(); stack.remove(&old); - stack.add_named(&pdw.container, "pdw"); + stack.add_named(&pdw.container, "widget"); stack.set_visible_child_name(&vis); old.destroy(); } From fb6fc68d234336226ffbb27ba1a7f08191de8f1c Mon Sep 17 00:00:00 2001 From: Jordan Petridis Date: Fri, 1 Dec 2017 06:00:06 +0200 Subject: [PATCH 15/41] Fix empty view. --- TODO.md | 5 ----- hammond-gtk/src/content.rs | 19 +++++++++++++------ hammond-gtk/src/views/podcasts.rs | 2 +- 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/TODO.md b/TODO.md index 0316ac8..1ed5678 100644 --- a/TODO.md +++ b/TODO.md @@ -1,14 +1,9 @@ ## TODOs: -**General:** - -- [ ] Write docs - ## Planned Features ## Priorities: -- [ ] Discuss and decide when to schedule the download cleaner. [#3](https://gitlab.gnome.org/alatiera/Hammond/issues/3) - [ ] Unplayed Only and Downloaded only view. - [ ] Auto-updater - [ ] OPML import/export // Probably need to create a crate. diff --git a/hammond-gtk/src/content.rs b/hammond-gtk/src/content.rs index 2a8659a..f707b76 100644 --- a/hammond-gtk/src/content.rs +++ b/hammond-gtk/src/content.rs @@ -11,12 +11,20 @@ use views::empty::EmptyView; #[derive(Debug)] pub struct Content { pub stack: gtk::Stack, - pub state: ContentState, widget: PodcastWidget, - pub podcasts: PopulatedView, + podcasts: PopulatedView, empty: EmptyView, } +// #[derive(Debug)] +// pub struct Content { +// pub stack: gtk::Stack, +// pub state: ContentState, +// widget: PodcastWidget, +// pub podcasts: PopulatedView, +// empty: EmptyView, +// } + #[derive(Debug)] #[allow(dead_code)] // TODO: find a way to wrap gtk::Stack into a State machine. @@ -32,12 +40,9 @@ impl Content { let widget = PodcastWidget::new(); let pop = PopulatedView::new(); let empty = EmptyView::new(); - // TODO: Avoid cloning - let state = ContentState::Populated(pop.clone()); let content = Content { stack, - state, widget, empty, podcasts: pop, @@ -55,12 +60,14 @@ impl Content { self.stack.add_named(&self.podcasts.container, "podcasts"); self.stack.add_named(&self.empty.container, "empty"); - // FIXME: needs actuall logic self.stack.set_visible_child_name("podcasts") } fn init(&self) { self.setup_stack(); self.podcasts.init(&self.stack); + if self.podcasts.flowbox.get_children().is_empty() { + self.stack.set_visible_child_name("empty"); + } } } diff --git a/hammond-gtk/src/views/podcasts.rs b/hammond-gtk/src/views/podcasts.rs index 16168d1..8a2e4e4 100644 --- a/hammond-gtk/src/views/podcasts.rs +++ b/hammond-gtk/src/views/podcasts.rs @@ -12,7 +12,7 @@ use utils::get_pixbuf_from_path; #[derive(Debug, Clone)] pub struct PopulatedView { pub container: gtk::Box, - flowbox: gtk::FlowBox, + pub flowbox: gtk::FlowBox, viewport: gtk::Viewport, } From 2d4acc3ba3e7fa6293550db760daf98b800d53e5 Mon Sep 17 00:00:00 2001 From: Jordan Petridis Date: Fri, 1 Dec 2017 06:21:48 +0200 Subject: [PATCH 16/41] Tweaked stack transition effects. --- hammond-gtk/src/content.rs | 4 ++-- hammond-gtk/src/views/podcasts.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/hammond-gtk/src/content.rs b/hammond-gtk/src/content.rs index f707b76..6a38fae 100644 --- a/hammond-gtk/src/content.rs +++ b/hammond-gtk/src/content.rs @@ -53,8 +53,8 @@ impl Content { } fn setup_stack(&self) { - self.stack - .set_transition_type(gtk::StackTransitionType::SlideLeftRight); + // self.stack + // .set_transition_type(gtk::StackTransitionType::SlideLeftRight); self.stack.add_named(&self.widget.container, "widget"); self.stack.add_named(&self.podcasts.container, "podcasts"); diff --git a/hammond-gtk/src/views/podcasts.rs b/hammond-gtk/src/views/podcasts.rs index 8a2e4e4..1b6cc8f 100644 --- a/hammond-gtk/src/views/podcasts.rs +++ b/hammond-gtk/src/views/podcasts.rs @@ -138,7 +138,7 @@ fn on_flowbox_child_activate(stack: >k::Stack, parent: &Podcast) { stack.remove(&old); stack.add_named(&pdw.container, "widget"); - stack.set_visible_child_name("widget"); + stack.set_visible_child_full("widget", gtk::StackTransitionType::SlideLeft); // aggresive memory cleanup // probably not needed From 91ac2c64458cda31b7d9c77a43ff23e0b066a01f Mon Sep 17 00:00:00 2001 From: Jordan Petridis Date: Fri, 1 Dec 2017 06:40:32 +0200 Subject: [PATCH 17/41] Minor cleanups. --- hammond-gtk/src/app.rs | 38 ------------------------------- hammond-gtk/src/content.rs | 3 --- hammond-gtk/src/utils.rs | 8 ++----- hammond-gtk/src/views/podcasts.rs | 7 ++++++ 4 files changed, 9 insertions(+), 47 deletions(-) delete mode 100644 hammond-gtk/src/app.rs diff --git a/hammond-gtk/src/app.rs b/hammond-gtk/src/app.rs deleted file mode 100644 index eab786a..0000000 --- a/hammond-gtk/src/app.rs +++ /dev/null @@ -1,38 +0,0 @@ -use gtk::prelude::*; -use gtk::{Window, WindowType}; - -use headerbar::Header; -use content::Content; - -#[derive(Debug)] -pub struct App<'a> { - window: Window, - header: Header, - content: Content<'a>, -} - -impl <'a>App<'a> { - pub fn new() -> App<'a> { - let window = Window::new(WindowType::Toplevel); - let content = Content::new(); - let header = Header::new(content.stack.clone()); - - window.set_default_size(1150, 650); - window.connect_delete_event(|w, _| { - w.destroy(); - Inhibit(false) - }); - - window.set_titlebar(&header.container); - window.add(&content.stack); - - window.show_all(); - window.activate(); - - App { - window, - header, - content, - } - } -} diff --git a/hammond-gtk/src/content.rs b/hammond-gtk/src/content.rs index 6a38fae..00677ba 100644 --- a/hammond-gtk/src/content.rs +++ b/hammond-gtk/src/content.rs @@ -53,9 +53,6 @@ impl Content { } fn setup_stack(&self) { - // self.stack - // .set_transition_type(gtk::StackTransitionType::SlideLeftRight); - self.stack.add_named(&self.widget.container, "widget"); self.stack.add_named(&self.podcasts.container, "podcasts"); self.stack.add_named(&self.empty.container, "empty"); diff --git a/hammond-gtk/src/utils.rs b/hammond-gtk/src/utils.rs index 794765c..ca8db76 100644 --- a/hammond-gtk/src/utils.rs +++ b/hammond-gtk/src/utils.rs @@ -65,12 +65,8 @@ fn refresh_podcasts_view() -> glib::Continue { } pub fn get_pixbuf_from_path(pd: &Podcast) -> Option { - let img_path = downloader::cache_image(pd); - if let Some(i) = img_path { - Pixbuf::new_from_file_at_scale(&i, 256, 256, true).ok() - } else { - None - } + let img_path = downloader::cache_image(pd)?; + Pixbuf::new_from_file_at_scale(&img_path, 256, 256, true).ok() } #[cfg(test)] diff --git a/hammond-gtk/src/views/podcasts.rs b/hammond-gtk/src/views/podcasts.rs index 1b6cc8f..0d906a4 100644 --- a/hammond-gtk/src/views/podcasts.rs +++ b/hammond-gtk/src/views/podcasts.rs @@ -40,6 +40,13 @@ impl PopulatedView { } } + #[allow(dead_code)] + pub fn new_initialized(stack: >k::Stack) -> PopulatedView { + let pop = PopulatedView::new(); + pop.init(stack); + pop + } + pub fn init(&self, stack: >k::Stack) { use gtk::WidgetExt; From 0359e9dd351548921127246ce43e627f5792694e Mon Sep 17 00:00:00 2001 From: Jordan Petridis Date: Fri, 1 Dec 2017 07:13:41 +0200 Subject: [PATCH 18/41] Convert EpisodeWidget into a Composed struct. --- hammond-gtk/src/main.rs | 5 +- hammond-gtk/src/widgets/episode.rs | 210 ++++++++++++++++++----------- 2 files changed, 130 insertions(+), 85 deletions(-) diff --git a/hammond-gtk/src/main.rs b/hammond-gtk/src/main.rs index ff4e601..5afcb5f 100644 --- a/hammond-gtk/src/main.rs +++ b/hammond-gtk/src/main.rs @@ -48,8 +48,6 @@ mod content; mod utils; mod static_resource; -// use views::podcasts; - /* THIS IS STILL A PROTOTYPE. */ @@ -63,8 +61,7 @@ fn build_ui(app: >k::Application) { // Get the main window let window = gtk::ApplicationWindow::new(app); window.set_default_size(1150, 650); - // Setup the Stack that will manage the switch between podcasts_view and podcast_widget. - // let stack = podcasts::setup_stack(); + let ct = content::Content::new(); let stack = ct.stack.clone(); window.add(&stack); diff --git a/hammond-gtk/src/widgets/episode.rs b/hammond-gtk/src/widgets/episode.rs index 4851a03..4d51d85 100644 --- a/hammond-gtk/src/widgets/episode.rs +++ b/hammond-gtk/src/widgets/episode.rs @@ -22,94 +22,141 @@ type Foo = RefCell thread_local!(static GLOBAL: Foo = RefCell::new(None)); -fn epidose_widget(episode: &mut Episode, pd_title: &str) -> gtk::Box { - // This is just a prototype and will be reworked probably. - let builder = gtk::Builder::new_from_resource("/org/gnome/hammond/gtk/episode_widget.ui"); +#[derive(Debug)] +struct EpisodeWidget { + container: gtk::Box, + download: gtk::Button, + play: gtk::Button, + delete: gtk::Button, + played: gtk::Button, + unplayed: gtk::Button, + title: gtk::Label, + description: gtk::TextView, + expander: gtk::Expander, +} - let ep: gtk::Box = builder.get_object("episode_box").unwrap(); - let download_button: gtk::Button = builder.get_object("download_button").unwrap(); - let play_button: gtk::Button = builder.get_object("play_button").unwrap(); - let delete_button: gtk::Button = builder.get_object("delete_button").unwrap(); - let played_button: gtk::Button = builder.get_object("mark_played_button").unwrap(); - let unplayed_button: gtk::Button = builder.get_object("mark_unplayed_button").unwrap(); +impl EpisodeWidget { + fn new() -> EpisodeWidget { + // This is just a prototype and will be reworked probably. + let builder = gtk::Builder::new_from_resource("/org/gnome/hammond/gtk/episode_widget.ui"); - let title_label: gtk::Label = builder.get_object("title_label").unwrap(); - // let desc_label: gtk::Label = builder.get_object("desc_label").unwrap(); - let expander: gtk::Expander = builder.get_object("expand_desc").unwrap(); - let desc_text_view: gtk::TextView = builder.get_object("desc_text_view").unwrap(); + let container: gtk::Box = builder.get_object("episode_box").unwrap(); + let download: gtk::Button = builder.get_object("download_button").unwrap(); + let play: gtk::Button = builder.get_object("play_button").unwrap(); + let delete: gtk::Button = builder.get_object("delete_button").unwrap(); + let played: gtk::Button = builder.get_object("mark_played_button").unwrap(); + let unplayed: gtk::Button = builder.get_object("mark_unplayed_button").unwrap(); - title_label.set_xalign(0.0); + let title: gtk::Label = builder.get_object("title_label").unwrap(); + let expander: gtk::Expander = builder.get_object("expand_desc").unwrap(); + let description: gtk::TextView = builder.get_object("desc_text_view").unwrap(); - if let Some(t) = episode.title() { - title_label.set_text(t); + EpisodeWidget { + container, + download, + play, + delete, + played, + unplayed, + title, + expander, + description, + } } - if episode.description().is_some() { - let d = episode.description().unwrap().to_owned(); - - expander.connect_activate(move |_| { - let plain_text = strip_html_tags(&d).join(" "); - // TODO: handle unwrap - let buff = desc_text_view.get_buffer().unwrap(); - buff.set_text(plain_text.trim()); - }); + pub fn new_initialized(episode: &mut Episode, pd: &Podcast) -> EpisodeWidget { + let widget = EpisodeWidget::new(); + widget.init(episode, pd); + widget } - if episode.played().is_some() { - unplayed_button.show(); - played_button.hide(); + fn init(&self, episode: &mut Episode, pd: &Podcast) { + self.title.set_xalign(0.0); + + if let Some(t) = episode.title() { + self.title.set_text(t); + } + + if episode.description().is_some() { + let d = episode.description().unwrap().to_owned(); + + let description = &self.description; + self.expander + .connect_activate(clone!(description => move |_| { + let plain_text = strip_html_tags(&d).join(" "); + // TODO: handle unwrap + let buff = description.get_buffer().unwrap(); + buff.set_text(plain_text.trim()); + })); + } + + if episode.played().is_some() { + self.unplayed.show(); + self.played.hide(); + } + + // Show or hide the play/delete/download buttons upon widget initialization. + let local_uri = episode.local_uri(); + if local_uri.is_some() && Path::new(local_uri.unwrap()).exists() { + self.download.hide(); + self.play.show(); + self.delete.show(); + } + + let played = &self.played; + let unplayed = &self.unplayed; + self.play + .connect_clicked(clone!(episode, played, unplayed => move |_| { + let mut episode = episode.clone(); + on_play_bttn_clicked(*episode.id()); + let _ = episode.set_played_now(); + played.hide(); + unplayed.show(); + })); + + let play = &self.play; + let download = &self.download; + self.delete + .connect_clicked(clone!(episode, play, download => move |del| { + on_delete_bttn_clicked(*episode.id()); + del.hide(); + play.hide(); + download.show(); + })); + + let unplayed = &self.unplayed; + self.played + .connect_clicked(clone!(episode, unplayed => move |played| { + let mut episode = episode.clone(); + let _ = episode.set_played_now(); + played.hide(); + unplayed.show(); + })); + + let played = &self.played; + self.unplayed + .connect_clicked(clone!(episode, played => move |un| { + let mut episode = episode.clone(); + episode.set_played(None); + let _ = episode.save(); + un.hide(); + played.show(); + })); + + let pd_title = pd.title().to_owned(); + let play = &self.play; + let delete = &self.delete; + self.download + .connect_clicked(clone!(play, delete, episode => move |dl| { + on_download_clicked( + &pd_title, + &mut episode.clone(), + dl, + &play, + &delete, + ); + })); } - - // Show or hide the play/delete/download buttons upon widget initialization. - let local_uri = episode.local_uri(); - if local_uri.is_some() && Path::new(local_uri.unwrap()).exists() { - download_button.hide(); - play_button.show(); - delete_button.show(); - } - - play_button.connect_clicked(clone!(episode, played_button, unplayed_button => move |_| { - let mut episode = episode.clone(); - on_play_bttn_clicked(*episode.id()); - let _ = episode.set_played_now(); - played_button.hide(); - unplayed_button.show(); - })); - - delete_button.connect_clicked(clone!(episode, play_button, download_button => move |del| { - on_delete_bttn_clicked(*episode.id()); - del.hide(); - play_button.hide(); - download_button.show(); - })); - - played_button.connect_clicked(clone!(episode, unplayed_button => move |played| { - let mut episode = episode.clone(); - let _ = episode.set_played_now(); - played.hide(); - unplayed_button.show(); - })); - - unplayed_button.connect_clicked(clone!(episode, played_button => move |un| { - let mut episode = episode.clone(); - episode.set_played(None); - let _ = episode.save(); - un.hide(); - played_button.show(); - })); - - let pd_title = pd_title.to_owned(); - download_button.connect_clicked(clone!(play_button, delete_button, episode => move |dl| { - on_download_clicked( - &pd_title, - &mut episode.clone(), - dl, - &play_button, - &delete_button, - ); - })); - - ep } // TODO: show notification when dl is finished. @@ -192,8 +239,9 @@ pub fn episodes_listbox(pd: &Podcast) -> Result { let list = gtk::ListBox::new(); episodes.into_iter().for_each(|mut ep| { - let w = epidose_widget(&mut ep, pd.title()); - list.add(&w) + // let w = epidose_widget(&mut ep, pd.title()); + let widget = EpisodeWidget::new_initialized(&mut ep, pd); + list.add(&widget.container) }); list.set_vexpand(false); From 8d63db047adccb710ecc2c3c16d617c47bd530e7 Mon Sep 17 00:00:00 2001 From: Jordan Petridis Date: Fri, 1 Dec 2017 07:30:28 +0200 Subject: [PATCH 19/41] Temporary removed unused Content.fields. --- hammond-gtk/src/content.rs | 37 +++++++++++++++++-------------------- 1 file changed, 17 insertions(+), 20 deletions(-) diff --git a/hammond-gtk/src/content.rs b/hammond-gtk/src/content.rs index 00677ba..0dd278f 100644 --- a/hammond-gtk/src/content.rs +++ b/hammond-gtk/src/content.rs @@ -11,9 +11,9 @@ use views::empty::EmptyView; #[derive(Debug)] pub struct Content { pub stack: gtk::Stack, - widget: PodcastWidget, - podcasts: PopulatedView, - empty: EmptyView, + // widget: PodcastWidget, + // podcasts: PopulatedView, + // empty: EmptyView, } // #[derive(Debug)] @@ -37,33 +37,30 @@ pub enum ContentState { impl Content { pub fn new() -> Content { let stack = gtk::Stack::new(); - let widget = PodcastWidget::new(); - let pop = PopulatedView::new(); - let empty = EmptyView::new(); let content = Content { stack, - widget, - empty, - podcasts: pop, + // widget, + // empty, + // podcasts: pop, }; content.init(); content } - fn setup_stack(&self) { - self.stack.add_named(&self.widget.container, "widget"); - self.stack.add_named(&self.podcasts.container, "podcasts"); - self.stack.add_named(&self.empty.container, "empty"); - - self.stack.set_visible_child_name("podcasts") - } - fn init(&self) { - self.setup_stack(); - self.podcasts.init(&self.stack); - if self.podcasts.flowbox.get_children().is_empty() { + let widget = PodcastWidget::new(); + let podcasts = PopulatedView::new(); + let empty = EmptyView::new(); + + self.stack.add_named(&widget.container, "widget"); + self.stack.add_named(&podcasts.container, "podcasts"); + self.stack.add_named(&empty.container, "empty"); + self.stack.set_visible_child_name("podcasts"); + + podcasts.init(&self.stack); + if podcasts.flowbox.get_children().is_empty() { self.stack.set_visible_child_name("empty"); } } From 9312366f62f4854a86ba22fc40224a8785d98815 Mon Sep 17 00:00:00 2001 From: Jordan Petridis Date: Sat, 2 Dec 2017 00:06:42 +0200 Subject: [PATCH 20/41] Enable more lints. --- hammond-data/src/lib.rs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/hammond-data/src/lib.rs b/hammond-data/src/lib.rs index e8ca7f4..636f68f 100644 --- a/hammond-data/src/lib.rs +++ b/hammond-data/src/lib.rs @@ -1,5 +1,4 @@ #![recursion_limit = "1024"] -#![deny(missing_docs)] #![cfg_attr(feature = "cargo-clippy", allow(blacklisted_name))] #![cfg_attr(feature = "clippy", warn(option_unwrap_used, result_unwrap_used, print_stdout, @@ -11,6 +10,15 @@ //! A libraty for parsing, indexing and retrieving podcast Feeds, //! into and from a Database. +#![deny(bad_style, const_err, dead_code, improper_ctypes, legacy_directory_ownership, + non_shorthand_field_patterns, no_mangle_generic_items, overflowing_literals, + path_statements, patterns_in_fns_without_body, plugin_as_library, private_in_public, + private_no_mangle_fns, private_no_mangle_statics, safe_extern_statics, + unconditional_recursion, unions_with_drop_fields, unused, unused_allocation, + unused_comparisons, unused_parens, while_true)] +#![deny(missing_debug_implementations, missing_docs, trivial_casts, trivial_numeric_casts, + unused_extern_crates)] + #[macro_use] extern crate error_chain; @@ -49,6 +57,7 @@ mod schema; pub use models::queryables::{Episode, Podcast, Source}; /// [XDG Base Direcotory](https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html) Paths. +#[allow(missing_debug_implementations)] pub mod xdg_dirs { use std::path::PathBuf; use xdg; From 74a1aae168ceab9ce48f6ba3393fa103d60a40f4 Mon Sep 17 00:00:00 2001 From: Jordan Petridis Date: Sat, 2 Dec 2017 01:39:28 +0200 Subject: [PATCH 21/41] Upgraded diesel to 0.99 and switched from the git master into crated.io. Also did a cargo upgrade of all the dependancies. Notable upgrades are r2d2, lazystatic 1.0, loggerv 0.6 and rss 1.2 --- Cargo.lock | 301 +++++++++++++++------------ Cargo.toml | 4 - hammond-data/Cargo.toml | 14 +- hammond-data/src/database.rs | 12 +- hammond-data/src/errors.rs | 4 +- hammond-data/src/feed.rs | 2 +- hammond-data/src/lib.rs | 3 +- hammond-downloader/Cargo.toml | 4 +- hammond-downloader/src/downloader.rs | 2 +- hammond-gtk/Cargo.toml | 8 +- hammond-gtk/src/content.rs | 2 +- hammond-gtk/src/utils.rs | 2 +- org.gnome.Hammond.json | 2 +- 13 files changed, 193 insertions(+), 167 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1a740c6..bd05568 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -14,10 +14,10 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "memchr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -38,7 +38,7 @@ dependencies = [ "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "glib-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "gobject-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -48,7 +48,7 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)", "termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -62,7 +62,7 @@ dependencies = [ "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-demangle 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -73,7 +73,7 @@ version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -81,7 +81,7 @@ name = "base64" version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -107,7 +107,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "byteorder" -version = "1.1.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -115,7 +115,7 @@ name = "bytes" version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -133,7 +133,7 @@ dependencies = [ "cairo-sys-rs 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "glib 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "glib-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -142,7 +142,7 @@ name = "cairo-sys-rs" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -162,7 +162,7 @@ name = "chrono" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "num 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", + "num 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -181,7 +181,7 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "core-foundation-sys 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -189,7 +189,7 @@ name = "core-foundation-sys" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -256,31 +256,30 @@ dependencies = [ [[package]] name = "diesel" -version = "0.16.0" -source = "git+https://github.com/diesel-rs/diesel.git#07f80c3a0d07daa26efff3166fbf0297dc0f0a7b" +version = "0.99.0" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "diesel_derives 0.99.0 (registry+https://github.com/rust-lang/crates.io-index)", "libsqlite3-sys 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "diesel_codegen" -version = "0.16.0" -source = "git+https://github.com/diesel-rs/diesel.git#07f80c3a0d07daa26efff3166fbf0297dc0f0a7b" +name = "diesel_derives" +version = "0.99.0" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "diesel 0.16.0 (git+https://github.com/diesel-rs/diesel.git)", - "diesel_infer_schema 0.16.0 (git+https://github.com/diesel-rs/diesel.git)", - "dotenv 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "diesel_infer_schema" -version = "0.16.0" -source = "git+https://github.com/diesel-rs/diesel.git#07f80c3a0d07daa26efff3166fbf0297dc0f0a7b" +name = "diesel_migrations" +version = "0.99.0" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "diesel 0.16.0 (git+https://github.com/diesel-rs/diesel.git)", + "migrations_internals 0.99.0 (registry+https://github.com/rust-lang/crates.io-index)", + "migrations_macros 0.99.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -299,7 +298,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "derive-error-chain 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "error-chain 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -338,7 +337,15 @@ dependencies = [ [[package]] name = "foreign-types" -version = "0.2.0" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -394,7 +401,7 @@ dependencies = [ "glib 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "glib-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "gobject-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)", "pango 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -407,7 +414,7 @@ dependencies = [ "glib 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "glib-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "gobject-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -419,7 +426,7 @@ dependencies = [ "gio-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "glib-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "gobject-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -434,7 +441,7 @@ dependencies = [ "gio-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "glib-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "gobject-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)", "pango-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -449,7 +456,7 @@ dependencies = [ "glib 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "glib-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "gobject-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -460,7 +467,7 @@ dependencies = [ "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "glib-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "gobject-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -473,7 +480,7 @@ dependencies = [ "glib-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "gobject-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -482,7 +489,7 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -493,7 +500,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "glib-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -515,7 +522,7 @@ dependencies = [ "glib-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "gobject-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "gtk-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)", "pango 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -532,7 +539,7 @@ dependencies = [ "gio-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "glib-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "gobject-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)", "pango-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -542,19 +549,19 @@ name = "hammond-data" version = "0.1.0" dependencies = [ "chrono 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "diesel 0.16.0 (git+https://github.com/diesel-rs/diesel.git)", - "diesel_codegen 0.16.0 (git+https://github.com/diesel-rs/diesel.git)", + "diesel 0.99.0 (registry+https://github.com/rust-lang/crates.io-index)", + "diesel_migrations 0.99.0 (registry+https://github.com/rust-lang/crates.io-index)", "dotenv 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", - "r2d2 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", - "r2d2-diesel 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", + "r2d2 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "r2d2-diesel 0.99.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)", "rayon 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "reqwest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "rfc822_sanitizer 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "rss 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rss 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "xdg 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -564,12 +571,12 @@ dependencies = [ name = "hammond-downloader" version = "0.1.0" dependencies = [ - "diesel 0.16.0 (git+https://github.com/diesel-rs/diesel.git)", + "diesel 0.99.0 (registry+https://github.com/rust-lang/crates.io-index)", "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "hammond-data 0.1.0", "hyper 0.11.7 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", - "mime_guess 1.8.2 (registry+https://github.com/rust-lang/crates.io-index)", + "mime_guess 1.8.3 (registry+https://github.com/rust-lang/crates.io-index)", "reqwest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -578,8 +585,7 @@ dependencies = [ name = "hammond-gtk" version = "0.1.0" dependencies = [ - "diesel 0.16.0 (git+https://github.com/diesel-rs/diesel.git)", - "diesel_codegen 0.16.0 (git+https://github.com/diesel-rs/diesel.git)", + "diesel 0.99.0 (registry+https://github.com/rust-lang/crates.io-index)", "dissolve 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "gdk 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "gdk-pixbuf 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -589,7 +595,7 @@ dependencies = [ "hammond-data 0.1.0", "hammond-downloader 0.1.0", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", - "loggerv 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "loggerv 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "open 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "rayon 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -663,7 +669,7 @@ name = "iovec" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -691,6 +697,11 @@ name = "lazy_static" version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "lazy_static" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "lazycell" version = "0.5.1" @@ -698,7 +709,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "libc" -version = "0.2.33" +version = "0.2.34" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -707,7 +718,7 @@ version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "adler32 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "crc 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -727,7 +738,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "loggerv" -version = "0.5.1" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -760,10 +771,28 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "memchr" -version = "1.0.2" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "migrations_internals" +version = "0.99.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "diesel 0.99.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "migrations_macros" +version = "0.99.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "migrations_internals 0.99.0 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -784,7 +813,7 @@ dependencies = [ [[package]] name = "mime_guess" -version = "1.8.2" +version = "1.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "mime 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -795,7 +824,7 @@ dependencies = [ [[package]] name = "mime_guess" -version = "2.0.0-alpha.2" +version = "2.0.0-alpha.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "mime 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -814,7 +843,7 @@ dependencies = [ "iovec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazycell 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)", @@ -838,7 +867,7 @@ name = "native-tls" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "openssl 0.9.21 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl 0.9.22 (registry+https://github.com/rust-lang/crates.io-index)", "schannel 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "security-framework 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "security-framework-sys 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", @@ -852,19 +881,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "num" -version = "0.1.40" +version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "num-integer 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", "num-iter 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -872,7 +901,7 @@ name = "num-integer" version = "0.1.35" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -881,12 +910,12 @@ version = "0.1.34" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "num-integer 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "num-traits" -version = "0.1.40" +version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -894,7 +923,7 @@ name = "num_cpus" version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -904,23 +933,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "openssl" -version = "0.9.21" +version = "0.9.22" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", - "foreign-types 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.21 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.22 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "openssl-sys" -version = "0.9.21" +version = "0.9.22" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "vcpkg 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -934,7 +963,7 @@ dependencies = [ "glib 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "glib-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "gobject-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)", "pango-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -946,7 +975,7 @@ dependencies = [ "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "glib-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "gobject-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1002,12 +1031,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "quick-xml" -version = "0.9.4" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "encoding_rs 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "error-chain 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1017,21 +1046,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "r2d2" -version = "0.7.4" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "antidote 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", - "scheduled-thread-pool 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "scheduled-thread-pool 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "r2d2-diesel" -version = "0.16.0" +version = "0.99.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "diesel 0.16.0 (git+https://github.com/diesel-rs/diesel.git)", - "r2d2 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", + "diesel 0.99.0 (registry+https://github.com/rust-lang/crates.io-index)", + "r2d2 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1040,7 +1069,7 @@ version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "fuchsia-zircon 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1059,14 +1088,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "coco 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "redox_syscall" -version = "0.1.31" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1074,16 +1103,16 @@ name = "redox_termios" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "redox_syscall 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "regex" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "aho-corasick 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "thread_local 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1113,10 +1142,10 @@ dependencies = [ "hyper-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "libflate 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", - "mime_guess 2.0.0-alpha.2 (registry+https://github.com/rust-lang/crates.io-index)", + "mime_guess 2.0.0-alpha.3 (registry+https://github.com/rust-lang/crates.io-index)", "native-tls 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", "serde_urlencoded 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-core 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1132,16 +1161,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "chrono 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rss" -version = "1.1.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "derive_builder 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "quick-xml 0.9.4 (registry+https://github.com/rust-lang/crates.io-index)", + "quick-xml 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1175,7 +1204,7 @@ dependencies = [ [[package]] name = "scheduled-thread-pool" -version = "0.1.0" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "antidote 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1207,7 +1236,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "core-foundation 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "core-foundation-sys 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)", "security-framework-sys 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1217,23 +1246,23 @@ version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "core-foundation-sys 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde" -version = "1.0.21" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde_json" -version = "1.0.6" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "itoa 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1243,7 +1272,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "itoa 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1276,7 +1305,7 @@ dependencies = [ "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "phf_shared 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", "precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)", "string_cache_codegen 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "string_cache_shared 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1343,8 +1372,8 @@ name = "termion" version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)", "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1363,8 +1392,8 @@ version = "0.1.38" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1552,7 +1581,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [metadata] "checksum adler32 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6cbd0b9af8587c72beadc9f72d35b9fbb070982c9e6203e46e93f10df25f8f45" "checksum advapi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e06588080cb19d0acb6739808aafa5f26bfb2ca015b2b6370028b44cf7cb8a9a" -"checksum aho-corasick 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "500909c4f87a9e52355b26626d890833e9e1d53ac566db76c36faa984b889699" +"checksum aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d6531d44de723825aa81398a6415283229725a00fa30713812ab9323faa82fc4" "checksum ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6b3568b48b7cefa6b8ce125f9bb4989e52fbcc29ebea88df04cc7c5f12f70455" "checksum antidote 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "34fde25430d87a9388dadbe6e34d7f72a462c8b43ac8d309b42b0a8505d7e2a5" "checksum atk-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "33a67fd81e1922dddc335887516f2f5254534e89c9d39fa89bca5d79bd150d34" @@ -1564,7 +1593,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5" "checksum bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b3c30d3802dfb7281680d6285f2ccdaa8c2d8fee41f93805dba5c4cf50dc23cf" "checksum build_const 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e90dc84f5e62d2ebe7676b83c22d33b6db8bd27340fb6ffbff0a364efa0cb9c9" -"checksum byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff81738b726f5d099632ceaffe7fb65b90212e8dce59d518729e7e8634032d3d" +"checksum byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "652805b7e73fada9d85e9a6682a4abd490cb52d96aeecc12e33a0de34dfd0d23" "checksum bytes 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d828f97b58cc5de3e40c421d0cf2132d6b2da4ee0e11b8632fa838f0f9333ad6" "checksum c_vec 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6237ac5a4b1e81c213c24c6437964c61e646df910a914b4ab1487b46df20bd13" "checksum cairo-rs 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b6b5695f59fd036fe5741bc5a4eb20c78fbe42256e3b08a2af26bbcbe8070bf3" @@ -1582,9 +1611,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum derive-error-chain 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3c9ca9ade651388daad7c993f005d0d20c4f6fe78c1cdc93e95f161c6f5ede4a" "checksum derive_builder 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "03600ae366b6eb2314e54d62adc833d9866da03798acc61c61789654ceaa227a" "checksum derive_builder_core 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "eed37eae64daa5511467b1a55cebdf472deeaef108d22f62f25e8bbcaffd56ac" -"checksum diesel 0.16.0 (git+https://github.com/diesel-rs/diesel.git)" = "" -"checksum diesel_codegen 0.16.0 (git+https://github.com/diesel-rs/diesel.git)" = "" -"checksum diesel_infer_schema 0.16.0 (git+https://github.com/diesel-rs/diesel.git)" = "" +"checksum diesel 0.99.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0b97bd43f72d4819fac99f24d0030184c64c5ebdee96f94c7a7d4215c50506a7" +"checksum diesel_derives 0.99.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ad228b6fd05c86050b95f56e497a8135073ffce28602e2200e63a21047eb474d" +"checksum diesel_migrations 0.99.0 (registry+https://github.com/rust-lang/crates.io-index)" = "745dcfe39e3043c267e46dbe4f2ebbc9917039bdf4d81b108950be61244dfc89" "checksum dissolve 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "898542be4716d992082c8e4fc331b792d626cfa71cb2b4790f828b9a8f921a90" "checksum dotenv 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d6f0e2bb24d163428d8031d3ebd2d2bd903ad933205a97d0f18c7c1aade380f3" "checksum dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "09c3753c3db574d215cba4ea76018483895d7bff25a31b49ba45db21c48e50ab" @@ -1592,7 +1621,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum encoding_rs 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f5215aabf22b83153be3ee44dfe3f940214541b2ce13d419c55e7a115c8c51a9" "checksum error-chain 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d9435d864e017c3c6afeac1654189b06cdb491cf2ff73dbf0d73b0f292f42ff8" "checksum error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3" -"checksum foreign-types 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3e4056b9bd47f8ac5ba12be771f77a0dae796d1bbaaf5fd0b9c2d38b69b8a29d" +"checksum foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +"checksum foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" "checksum fuchsia-zircon 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f6c0581a4e363262e52b87f59ee2afe3415361c6ec35e665924eb08afe8ff159" "checksum fuchsia-zircon-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "43f3795b4bae048dc6123a6b972cadde2e676f9ded08aef6bb77f5f157684a82" "checksum futf 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "51f93f3de6ba1794dcd5810b3546d004600a59a98266487c8407bc4b24e398f3" @@ -1619,32 +1649,35 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a" "checksum lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "76f033c7ad61445c5b347c7382dd1237847eb1bce590fe50365dcb33d546be73" +"checksum lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c8f31047daa365f19be14b47c29df4f7c3b581832407daabe6ae77397619237d" "checksum lazycell 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3b585b7a6811fb03aa10e74b278a0f00f8dd9b45dc681f148bb29fa5cb61859b" -"checksum libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "5ba3df4dcb460b9dfbd070d41c94c19209620c191b0340b929ce748a2bcd42d2" +"checksum libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)" = "36fbc8a8929c632868295d0178dd8f63fc423fd7537ad0738372bd010b3ac9b0" "checksum libflate 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "ae46bcdafa496981e996e57c5be82c0a7f130a071323764c6faa4803619f1e67" "checksum libsqlite3-sys 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "370090ad578ba845a3ad4f383ceb3deba7abd51ab1915ad1f2c982cc6035e31c" "checksum log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "880f77541efa6e5cc74e76910c9884d9859683118839d6a1dc3b11e63512565b" -"checksum loggerv 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5bb7c9e1ed99294067005cc7d4413441197ba354e8286c36b72a66a557c13661" +"checksum loggerv 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b178879253fab6ddb4ea931e1e6f514d45ce6a53f7fe618a0a8751f43e42e4f1" "checksum mac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4" "checksum markup5ever 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2cf89d3e0486c32c9d99521455ddf9a438910a1ce2bd376936086edc15dff5fc" "checksum matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "100aabe6b8ff4e4a7e32c1c13523379802df0772b82466207ac25b013f193376" -"checksum memchr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "148fab2e51b4f1cfc66da2a7c32981d1d3c083a803978268bb11fe4b86925e7a" +"checksum memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "796fba70e76612589ed2ce7f45282f5af869e0fdd7cc6199fa1aa1f1d591ba9d" +"checksum migrations_internals 0.99.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f9ac1d17f6f161f4d91cb7e5a72cce5b24a60b80f96580a8ac94351c56b8606a" +"checksum migrations_macros 0.99.0 (registry+https://github.com/rust-lang/crates.io-index)" = "dc767420eac6b718cd593aaa09c06a31d4ed228291c8538b274737e28a29939b" "checksum mime 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ba626b8a6de5da682e1caa06bdb42a335aee5a84db8e5046a3e8ab17ba0a3ae0" "checksum mime 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e2e00e17be181010a91dbfefb01660b17311059dc8c7f48b9017677721e732bd" -"checksum mime_guess 1.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bbee1a836f344ac39d4a59bfe7be2bd3150353ff71678afb740216f8270b333e" -"checksum mime_guess 2.0.0-alpha.2 (registry+https://github.com/rust-lang/crates.io-index)" = "27a5e6679a0614e25adc14c6434ba84e41632b765a6d9cb2031a0cca682699ae" +"checksum mime_guess 1.8.3 (registry+https://github.com/rust-lang/crates.io-index)" = "dc7e82a15629bb4ecd9e72365bf33d1382be91e030f820edb8e2a21c02430da8" +"checksum mime_guess 2.0.0-alpha.3 (registry+https://github.com/rust-lang/crates.io-index)" = "013572795763289e14710c7b279461295f2673b2b338200c235082cd7ca9e495" "checksum mio 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)" = "0e8411968194c7b139e9105bc4ae7db0bae232af087147e72f0616ebf5fdb9cb" "checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" "checksum native-tls 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "04b781c9134a954c84f0594b9ab3f5606abc516030388e8511887ef4c204a1e5" "checksum net2 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)" = "3a80f842784ef6c9a958b68b7516bc7e35883c614004dd94959a4dca1b716c09" -"checksum num 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "a311b77ebdc5dd4cf6449d81e4135d9f0e3b153839ac90e648a8ef538f923525" +"checksum num 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "cc4083e14b542ea3eb9b5f33ff48bd373a92d78687e74f4cc0a30caeb754f0ca" "checksum num-integer 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)" = "d1452e8b06e448a07f0e6ebb0bb1d92b8890eea63288c0b627331d53514d0fba" "checksum num-iter 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)" = "7485fcc84f85b4ecd0ea527b14189281cf27d60e583ae65ebc9c088b13dffe01" -"checksum num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "99843c856d68d8b4313b03a17e33c4bb42ae8f6610ea81b28abe076ac721b9b0" +"checksum num-traits 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "cacfcab5eb48250ee7d0c7896b51a2c5eec99c1feea5f32025635f5ae4b00070" "checksum num_cpus 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "514f0d73e64be53ff320680ca671b64fe3fb91da01e1ae2ddc99eb51d453b20d" "checksum open 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c281318d992e4432cfa799969467003d05921582a7489a8325e37f8a450d5113" -"checksum openssl 0.9.21 (registry+https://github.com/rust-lang/crates.io-index)" = "2225c305d8f57001a0d34263e046794aa251695f20773102fbbfeb1e7b189955" -"checksum openssl-sys 0.9.21 (registry+https://github.com/rust-lang/crates.io-index)" = "92867746af30eea7a89feade385f7f5366776f1c52ec6f0de81360373fa88363" +"checksum openssl 0.9.22 (registry+https://github.com/rust-lang/crates.io-index)" = "419ef26bb651d72b6c5a603bcc4e4856a362460e62352dfffa53de91d2e81181" +"checksum openssl-sys 0.9.22 (registry+https://github.com/rust-lang/crates.io-index)" = "5483bdc56756041ba6aa37c9cb59cc2219f012a2a1377d97ad35556ac6676ee7" "checksum pango 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3e81c404ab81ea7ea2fc2431a0a7672507b80e4b8bf4b41eac3fc83cc665104e" "checksum pango-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "34f34a1be107fe16abb2744e0e206bee4b3b07460b5fddd3009a6aaf60bd69ab" "checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" @@ -1654,33 +1687,33 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum phf_shared 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "07e24b0ca9643bdecd0632f2b3da6b1b89bbb0030e0b992afc1113b23a7bc2f2" "checksum pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "3a8b4c6b8165cd1a1cd4b9b120978131389f64bdaf456435caa41e630edba903" "checksum precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" -"checksum quick-xml 0.9.4 (registry+https://github.com/rust-lang/crates.io-index)" = "19a3a610544419c527d5f51ae1a6ae3db533e25c117d3eed8fce6434f70c5e95" +"checksum quick-xml 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d0fb3e41d968cd20da34a9e81abae097398b38fe0987149e321572eb75d3317" "checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" -"checksum r2d2 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)" = "2c8284508b38df440f8f3527395e23c4780b22f74226b270daf58fee38e4bcce" -"checksum r2d2-diesel 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f6b921696a6c45991296d21b52ed973b9fb56f6c47524fda1f99458c2d6c0478" +"checksum r2d2 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "59611202bee496c586ecd84e3ed149b4ec75981b0fc10d7f60e878fa23ae16e9" +"checksum r2d2-diesel 0.99.0 (registry+https://github.com/rust-lang/crates.io-index)" = "77aaed149a82720f4b664427f359e1b2a34d8787c1bc3fb1d167b104a1ddd866" "checksum rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)" = "6475140dfd8655aeb72e1fd4b7a1cc1c202be65d71669476e392fe62532b9edd" "checksum rayon 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ed02d09394c94ffbdfdc755ad62a132e94c3224a8354e78a1200ced34df12edf" "checksum rayon-core 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e64b609139d83da75902f88fd6c01820046840a18471e4dfcd5ac7c0f46bea53" -"checksum redox_syscall 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)" = "8dde11f18c108289bef24469638a04dce49da56084f2d50618b226e47eb04509" +"checksum redox_syscall 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)" = "ab105df655884ede59d45b7070c8a65002d921461ee813a024558ca16030eea0" "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" -"checksum regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1731164734096285ec2a5ec7fea5248ae2f5485b3feeb0115af4fda2183b2d1b" +"checksum regex 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ac6ab4e9218ade5b423358bbd2567d1617418403c7a512603630181813316322" "checksum regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ad890a5eef7953f55427c50575c680c42841653abd2b028b68cd223d157f62db" "checksum relay 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f301bafeb60867c85170031bdb2fcf24c8041f33aee09e7b116a58d4e9f781c5" "checksum reqwest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f73a8482e3b2b20ef5c07168b27048fc3778a012ce9b11a021556a450a01e9b5" "checksum rfc822_sanitizer 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "680e8305c1e0cdf836dc4bec5424e045f278c975a3cac36d1ca01c4695f9d815" -"checksum rss 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "70294b2be2d620fed3939032067684c53b8ccae18e8ca0b8410447f0f07228c5" +"checksum rss 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3fbc1a0587ebbc7404b3295c8e1f717d00dad48e3c205adadf916f15ff67d05b" "checksum rustc-demangle 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "aee45432acc62f7b9a108cc054142dac51f979e69e71ddce7d6fc7adf29e817e" "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" "checksum safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e27a8b19b835f7aea908818e871f5cc3a5a186550c30773be987e155e8163d8f" "checksum schannel 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7554288337c1110e34d7a2433518d889374c1de1a45f856b7bcddb03702131fc" -"checksum scheduled-thread-pool 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2d9fbe48ead32343b76f544c85953bf260ed39219a8bbbb62cd85f6a00f9644f" +"checksum scheduled-thread-pool 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1a2ff3fc5223829be817806c6441279c676e454cc7da608faf03b0ccc09d3889" "checksum scoped-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f417c22df063e9450888a7561788e9bd46d3bb3c1466435b4eccb903807f147d" "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" "checksum secur32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3f412dfa83308d893101dd59c10d6fda8283465976c28c287c5c855bf8d216bc" "checksum security-framework 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "dfa44ee9c54ce5eecc9de7d5acbad112ee58755239381f687e564004ba4a2332" "checksum security-framework-sys 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "5421621e836278a0b139268f36eee0dc7e389b784dc3f79d8f11aabadf41bead" -"checksum serde 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)" = "6eda663e865517ee783b0891a3f6eb3a253e0b0dabb46418969ee9635beadd9e" -"checksum serde_json 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "e4586746d1974a030c48919731ecffd0ed28d0c40749d0d18d43b3a7d6c9b20e" +"checksum serde 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)" = "6a7c37d7f192f00041e8a613e936717923a71bc0c9051fc4425a49b104140f05" +"checksum serde_json 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "ea28ea0cca944668919bec6af209864a8dfe769fd2b0b723f36b22e20c1bf69f" "checksum serde_urlencoded 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ce0fd303af908732989354c6f02e05e2e6d597152870f2c6990efb0577137480" "checksum siphasher 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0df90a788073e8d0235a67e50441d47db7c8ad9debd91cbf43736a2a92d36537" "checksum slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "17b4fcaed89ab08ef143da37bc52adbcc04d4a69014f4c1208d6b51f0c47bc23" diff --git a/Cargo.toml b/Cargo.toml index 545646a..d1deebf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,7 +8,3 @@ members = [ [profile.release] debug = false -[patch.crates-io] -diesel = { git = "https://github.com/diesel-rs/diesel.git" } -diesel_infer_schema = { git = "https://github.com/diesel-rs/diesel.git" } -diesel_codegen = { git = "https://github.com/diesel-rs/diesel.git" } diff --git a/hammond-data/Cargo.toml b/hammond-data/Cargo.toml index 2083fe0..420d67d 100644 --- a/hammond-data/Cargo.toml +++ b/hammond-data/Cargo.toml @@ -8,24 +8,24 @@ workspace = "../" chrono = "0.4.0" dotenv = "0.10.1" error-chain = "0.11.0" -lazy_static = "0.2.11" +lazy_static = "1.0.0" log = "0.3.8" -r2d2 = "0.7.4" -r2d2-diesel = "0.16.0" +r2d2 = "0.8.1" +r2d2-diesel = "0.99.0" rayon = "0.9.0" reqwest = "0.8.1" rfc822_sanitizer = "0.3.3" -rss = "1.1.0" +rss = "1.2.1" url = "1.6.0" xdg = "2.1.0" [dependencies.diesel] features = ["sqlite"] -git = "https://github.com/diesel-rs/diesel.git" +version = "0.99.0" -[dependencies.diesel_codegen] +[dependencies.diesel_migrations] features = ["sqlite"] -git = "https://github.com/diesel-rs/diesel.git" +version = "0.99.0" [dev-dependencies] rand = "0.3.18" diff --git a/hammond-data/src/database.rs b/hammond-data/src/database.rs index c3f024e..8d37380 100644 --- a/hammond-data/src/database.rs +++ b/hammond-data/src/database.rs @@ -5,7 +5,6 @@ use r2d2; use std::path::PathBuf; use std::sync::Arc; use std::io; -use std::time::Duration; use errors::*; @@ -42,12 +41,13 @@ pub(crate) fn connection() -> Pool { } fn init_pool(db_path: &str) -> Pool { - let config = r2d2::Config::builder() - .pool_size(1) - .connection_timeout(Duration::from_secs(60)) - .build(); let manager = ConnectionManager::::new(db_path); - let pool = Arc::new(r2d2::Pool::new(config, manager).expect("Failed to create pool.")); + let config = r2d2::Pool::builder() + .max_size(1) + .build(manager) + .expect("Failed to create pool."); + + let pool = Arc::new(config); { let db = Arc::clone(&pool).get().expect("Failed to initialize pool."); diff --git a/hammond-data/src/errors.rs b/hammond-data/src/errors.rs index 372cc55..274a1a1 100644 --- a/hammond-data/src/errors.rs +++ b/hammond-data/src/errors.rs @@ -1,5 +1,5 @@ use diesel::result; -use diesel::migrations::RunMigrationsError; +use diesel_migrations::RunMigrationsError; use rss; use reqwest; use r2d2; @@ -8,7 +8,7 @@ use std::io; error_chain! { foreign_links { - R2D2TimeoutError(r2d2::GetTimeout); + R2D2Error(r2d2::Error); DieselResultError(result::Error); DieselMigrationError(RunMigrationsError); RSSError(rss::Error); diff --git a/hammond-data/src/feed.rs b/hammond-data/src/feed.rs index 5fd9d33..a87f98f 100644 --- a/hammond-data/src/feed.rs +++ b/hammond-data/src/feed.rs @@ -4,7 +4,7 @@ use rayon::prelude::*; use diesel::prelude::*; use rayon::iter::IntoParallelIterator; -use diesel::Identifiable; +use diesel::associations::Identifiable; use rss; use dbqueries; diff --git a/hammond-data/src/lib.rs b/hammond-data/src/lib.rs index 636f68f..388d2bc 100644 --- a/hammond-data/src/lib.rs +++ b/hammond-data/src/lib.rs @@ -30,8 +30,9 @@ extern crate log; #[macro_use] extern crate diesel; + #[macro_use] -extern crate diesel_codegen; +extern crate diesel_migrations; extern crate chrono; extern crate r2d2; diff --git a/hammond-downloader/Cargo.toml b/hammond-downloader/Cargo.toml index 7d19efc..f063adc 100644 --- a/hammond-downloader/Cargo.toml +++ b/hammond-downloader/Cargo.toml @@ -8,13 +8,13 @@ workspace = "../" error-chain = "0.11.0" hyper = "0.11.7" log = "0.3.8" -mime_guess = "1.8.2" +mime_guess = "1.8.3" reqwest = "0.8.1" tempdir = "0.3.5" [dependencies.diesel] features = ["sqlite"] -git = "https://github.com/diesel-rs/diesel.git" +version = "0.99" [dependencies.hammond-data] path = "../hammond-data" diff --git a/hammond-downloader/src/downloader.rs b/hammond-downloader/src/downloader.rs index 64df7de..b19de6c 100644 --- a/hammond-downloader/src/downloader.rs +++ b/hammond-downloader/src/downloader.rs @@ -185,7 +185,7 @@ mod tests { use hammond_data::Source; use hammond_data::feed::index; use hammond_data::dbqueries; - use diesel::Identifiable; + use diesel::associations::Identifiable; use std::fs; diff --git a/hammond-gtk/Cargo.toml b/hammond-gtk/Cargo.toml index 39b12fe..a59c1ef 100644 --- a/hammond-gtk/Cargo.toml +++ b/hammond-gtk/Cargo.toml @@ -12,17 +12,13 @@ gdk-pixbuf = "0.3.0" gio = "0.3.0" glib = "0.4.0" log = "0.3.8" -loggerv = "0.5.1" +loggerv = "0.6.0" open = "1.2.1" rayon = "0.9.0" [dependencies.diesel] features = ["sqlite"] -git = "https://github.com/diesel-rs/diesel.git" - -[dependencies.diesel_codegen] -features = ["sqlite"] -git = "https://github.com/diesel-rs/diesel.git" +version = "0.99.0" [dependencies.gtk] features = ["v3_22"] diff --git a/hammond-gtk/src/content.rs b/hammond-gtk/src/content.rs index 0dd278f..99194dc 100644 --- a/hammond-gtk/src/content.rs +++ b/hammond-gtk/src/content.rs @@ -2,7 +2,7 @@ use gtk; use gtk::prelude::*; // use gdk_pixbuf::Pixbuf; -// use diesel::Identifiable; +// use diesel::associations::Identifiable; use widgets::podcast::PodcastWidget; use views::podcasts::PopulatedView; diff --git a/hammond-gtk/src/utils.rs b/hammond-gtk/src/utils.rs index ca8db76..e0aff6c 100644 --- a/hammond-gtk/src/utils.rs +++ b/hammond-gtk/src/utils.rs @@ -74,7 +74,7 @@ mod tests { use hammond_data::Source; use hammond_data::feed::index; use hammond_data::dbqueries; - use diesel::Identifiable; + use diesel::associations::Identifiable; use super::*; #[test] diff --git a/org.gnome.Hammond.json b/org.gnome.Hammond.json index 459b13c..a3638e5 100644 --- a/org.gnome.Hammond.json +++ b/org.gnome.Hammond.json @@ -30,7 +30,7 @@ { "type": "git", "url": "https://gitlab.gnome.org/alatiera/Hammond.git", - "branch": "master" + "branch": "client-rework" } ] } From 7727bc5ec3b518505ba2d0f1d95239cb02afda45 Mon Sep 17 00:00:00 2001 From: Jordan Petridis Date: Sat, 2 Dec 2017 01:46:37 +0200 Subject: [PATCH 22/41] Remove unnecessary Arc. --- hammond-data/src/database.rs | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/hammond-data/src/database.rs b/hammond-data/src/database.rs index 8d37380..bb18bda 100644 --- a/hammond-data/src/database.rs +++ b/hammond-data/src/database.rs @@ -3,7 +3,6 @@ use diesel::prelude::*; use r2d2; use std::path::PathBuf; -use std::sync::Arc; use std::io; use errors::*; @@ -11,7 +10,7 @@ use errors::*; #[cfg(not(test))] use xdg_dirs; -type Pool = Arc>>; +type Pool = r2d2::Pool>; embed_migrations!("migrations/"); @@ -37,20 +36,18 @@ lazy_static! { } pub(crate) fn connection() -> Pool { - Arc::clone(&POOL) + POOL.clone() } fn init_pool(db_path: &str) -> Pool { let manager = ConnectionManager::::new(db_path); - let config = r2d2::Pool::builder() + let pool = r2d2::Pool::builder() .max_size(1) .build(manager) .expect("Failed to create pool."); - let pool = Arc::new(config); - { - let db = Arc::clone(&pool).get().expect("Failed to initialize pool."); + let db = pool.get().expect("Failed to initialize pool."); run_migration_on(&*db).expect("Failed to run migrations during init."); } info!("Database pool initialized."); From 8bd48a09a6f2b43abcf9e01c66bb4cb9744ba6ec Mon Sep 17 00:00:00 2001 From: Jordan Petridis Date: Sat, 2 Dec 2017 08:58:28 +0200 Subject: [PATCH 23/41] Groupd stack manipulation functions into content module. --- hammond-gtk/src/content.rs | 79 ++++++++++++++++++++++++++++++ hammond-gtk/src/headerbar.rs | 8 +-- hammond-gtk/src/utils.rs | 4 +- hammond-gtk/src/views/podcasts.rs | 39 ++------------- hammond-gtk/src/widgets/podcast.rs | 28 ++++------- org.gnome.Hammond.json | 2 +- 6 files changed, 97 insertions(+), 63 deletions(-) diff --git a/hammond-gtk/src/content.rs b/hammond-gtk/src/content.rs index 99194dc..2d91541 100644 --- a/hammond-gtk/src/content.rs +++ b/hammond-gtk/src/content.rs @@ -3,6 +3,7 @@ use gtk::prelude::*; // use gdk_pixbuf::Pixbuf; // use diesel::associations::Identifiable; +use hammond_data::Podcast; use widgets::podcast::PodcastWidget; use views::podcasts::PopulatedView; @@ -65,3 +66,81 @@ impl Content { } } } + +fn replace_widget(stack: >k::Stack, pdw: &PodcastWidget) { + let old = stack.get_child_by_name("widget").unwrap(); + stack.remove(&old); + stack.add_named(&pdw.container, "widget"); + old.destroy(); +} + +fn replace_podcasts(stack: >k::Stack, pop: &PopulatedView) { + let old = stack.get_child_by_name("podcasts").unwrap(); + stack.remove(&old); + stack.add_named(&pop.container, "podcasts"); + old.destroy(); +} + +// This won't ever be needed probably +// pub fn replace_empty(stack: >k::Stack, emp: &EmptyView ) { +// let old = stack.get_child_by_name("empty").unwrap(); +// stack.remove(&old); +// stack.add_named(&emp.container, "empty"); +// old.destroy(); +// } + +pub fn show_widget(stack: >k::Stack) { + stack.set_visible_child_name("widget") +} + +pub fn show_podcasts(stack: >k::Stack) { + stack.set_visible_child_name("podcasts") +} + +pub fn show_empty(stack: >k::Stack) { + stack.set_visible_child_name("empty") +} + +pub fn update_podcasts(stack: >k::Stack) { + let pods = PopulatedView::new_initialized(stack); + + if pods.flowbox.get_children().is_empty() { + show_empty(stack) + } + + replace_podcasts(stack, &pods); +} + +pub fn update_widget(stack: >k::Stack, pd: &Podcast) { + let pdw = PodcastWidget::new_initialized(stack, pd); + replace_widget(stack, &pdw); +} + +pub fn update_podcasts_preserve_vis(stack: >k::Stack) { + let vis = stack.get_visible_child_name().unwrap(); + update_podcasts(stack); + if vis != "empty" { + stack.set_visible_child_name(&vis) + } +} + +pub fn update_widget_preserve_vis(stack: >k::Stack, pd: &Podcast) { + let vis = stack.get_visible_child_name().unwrap(); + update_widget(stack, pd); + stack.set_visible_child_name(&vis) +} + +pub fn on_podcasts_child_activate(stack: >k::Stack, pd: &Podcast) { + update_widget(stack, pd); + stack.set_visible_child_full("widget", gtk::StackTransitionType::SlideLeft); +} + +pub fn on_home_button_activate(stack: >k::Stack) { + let vis = stack.get_visible_child_name().unwrap(); + + if vis != "widget" { + update_podcasts(stack); + } + + show_podcasts(stack); +} diff --git a/hammond-gtk/src/headerbar.rs b/hammond-gtk/src/headerbar.rs index 7e13ffa..20f491e 100644 --- a/hammond-gtk/src/headerbar.rs +++ b/hammond-gtk/src/headerbar.rs @@ -4,8 +4,8 @@ use gtk::prelude::*; use hammond_data::Source; use hammond_data::utils::url_cleaner; -use views::podcasts::update_podcasts_view; use utils; +use content; #[derive(Debug)] pub struct Header { @@ -61,11 +61,7 @@ impl Header { // TODO: make it a back arrow button, that will hide when appropriate, // and add a StackSwitcher when more views are added. self.home.connect_clicked(clone!(stack => move |_| { - let vis = stack.get_visible_child_name().unwrap(); - stack.set_visible_child_name("podcasts"); - if vis != "widget" { - update_podcasts_view(&stack); - } + content::on_home_button_activate(&stack); })); // FIXME: There appears to be a memmory leak here. diff --git a/hammond-gtk/src/utils.rs b/hammond-gtk/src/utils.rs index e0aff6c..14e8b46 100644 --- a/hammond-gtk/src/utils.rs +++ b/hammond-gtk/src/utils.rs @@ -10,7 +10,7 @@ use std::{thread, time}; use std::cell::RefCell; use std::sync::mpsc::{channel, Receiver}; -use views::podcasts; +use content; type Foo = RefCell)>>; @@ -57,7 +57,7 @@ fn refresh_podcasts_view() -> glib::Continue { GLOBAL.with(|global| { if let Some((ref stack, ref reciever)) = *global.borrow() { if reciever.try_recv().is_ok() { - podcasts::update_podcasts_view(stack); + content::update_podcasts_preserve_vis(stack); } } }); diff --git a/hammond-gtk/src/views/podcasts.rs b/hammond-gtk/src/views/podcasts.rs index 0d906a4..711be87 100644 --- a/hammond-gtk/src/views/podcasts.rs +++ b/hammond-gtk/src/views/podcasts.rs @@ -6,9 +6,10 @@ use diesel::associations::Identifiable; use hammond_data::dbqueries; use hammond_data::Podcast; -use widgets::podcast::*; use utils::get_pixbuf_from_path; +use content; + #[derive(Debug, Clone)] pub struct PopulatedView { pub container: gtk::Box, @@ -139,39 +140,5 @@ impl PodcastChild { } fn on_flowbox_child_activate(stack: >k::Stack, parent: &Podcast) { - let old = stack.get_child_by_name("widget").unwrap(); - let pdw = PodcastWidget::new(); - pdw.init(stack, parent); - - stack.remove(&old); - stack.add_named(&pdw.container, "widget"); - stack.set_visible_child_full("widget", gtk::StackTransitionType::SlideLeft); - - // aggresive memory cleanup - // probably not needed - old.destroy(); -} - -pub fn update_podcasts_view(stack: >k::Stack) { - let vis = stack.get_visible_child_name().unwrap(); - let old = stack.get_child_by_name("podcasts").unwrap(); - stack.remove(&old); - - let pdw = PopulatedView::new(); - pdw.init(stack); - stack.add_named(&pdw.container, "podcasts"); - let flowbox = &pdw.flowbox; - - if vis == "empty" && !flowbox.get_children().is_empty() { - stack.set_visible_child_name("podcasts"); - } else if vis == "podcasts" && flowbox.get_children().is_empty() { - stack.set_visible_child_name("empty"); - } else { - // preserve the visible widget - stack.set_visible_child_name(&vis); - }; - - // aggresive memory cleanup - // probably not needed - old.destroy(); + content::on_podcasts_child_activate(stack, parent) } diff --git a/hammond-gtk/src/widgets/podcast.rs b/hammond-gtk/src/widgets/podcast.rs index 116e221..140e313 100644 --- a/hammond-gtk/src/widgets/podcast.rs +++ b/hammond-gtk/src/widgets/podcast.rs @@ -8,8 +8,8 @@ use hammond_data::Podcast; use hammond_downloader::downloader; use widgets::episode::episodes_listbox; -use views::podcasts::update_podcasts_view; use utils::get_pixbuf_from_path; +use content; #[derive(Debug)] pub struct PodcastWidget { @@ -46,6 +46,12 @@ impl PodcastWidget { } } + pub fn new_initialized(stack: >k::Stack, pd: &Podcast) -> PodcastWidget { + let pdw = PodcastWidget::new(); + pdw.init(stack, pd); + pdw + } + pub fn init(&self, stack: >k::Stack, pd: &Podcast) { // TODO: should spawn a thread to avoid locking the UI probably. self.unsub.connect_clicked(clone!(stack, pd => move |bttn| { @@ -86,7 +92,6 @@ impl PodcastWidget { } } -// Note: Stack manipulation fn on_unsub_button_clicked(stack: >k::Stack, pd: &Podcast, unsub_button: >k::Button) { let res = dbqueries::remove_feed(pd); if res.is_ok() { @@ -103,25 +108,12 @@ fn on_unsub_button_clicked(stack: >k::Stack, pd: &Podcast, unsub_button: >k: } }; } - stack.set_visible_child_name("podcasts"); - update_podcasts_view(stack); + content::show_podcasts(stack); + content::update_podcasts(stack); } fn on_played_button_clicked(stack: >k::Stack, pd: &Podcast) { let _ = dbqueries::update_none_to_played_now(pd); - update_podcast_widget(stack, pd); -} - -// Note: Stack manipulation -pub fn update_podcast_widget(stack: >k::Stack, pd: &Podcast) { - let old = stack.get_child_by_name("widget").unwrap(); - let pdw = PodcastWidget::new(); - pdw.init(stack, pd); - let vis = stack.get_visible_child_name().unwrap(); - - stack.remove(&old); - stack.add_named(&pdw.container, "widget"); - stack.set_visible_child_name(&vis); - old.destroy(); + content::update_widget_preserve_vis(stack, pd); } diff --git a/org.gnome.Hammond.json b/org.gnome.Hammond.json index a3638e5..459b13c 100644 --- a/org.gnome.Hammond.json +++ b/org.gnome.Hammond.json @@ -30,7 +30,7 @@ { "type": "git", "url": "https://gitlab.gnome.org/alatiera/Hammond.git", - "branch": "client-rework" + "branch": "master" } ] } From 276169e43d5fdccad5e3bf421aaa86e106a11914 Mon Sep 17 00:00:00 2001 From: Jordan Petridis Date: Mon, 4 Dec 2017 14:32:16 +0200 Subject: [PATCH 24/41] Minor cleanup of nested match/if let statements into using and_then(). --- hammond-downloader/src/downloader.rs | 32 ++++++++++++---------------- hammond-gtk/src/content.rs | 3 +-- 2 files changed, 15 insertions(+), 20 deletions(-) diff --git a/hammond-downloader/src/downloader.rs b/hammond-downloader/src/downloader.rs index b19de6c..97b1752 100644 --- a/hammond-downloader/src/downloader.rs +++ b/hammond-downloader/src/downloader.rs @@ -38,24 +38,7 @@ fn download_into(dir: &str, file_title: &str, url: &str) -> Result { ct_len.map(|x| info!("File Lenght: {}", x)); ct_type.map(|x| info!("Content Type: {}", x)); - // This could be prettier. - // Determine the file extension from the http content-type header. - let ext = if let Some(t) = ct_type { - let mime = mime_guess::get_extensions(t.type_().as_ref(), t.subtype().as_ref()); - if let Some(m) = mime { - if m.contains(&t.subtype().as_ref()) { - t.subtype().as_ref().to_string() - } else { - m.first().unwrap().to_string() - } - } else { - error!("Unkown mime type. {}", t); - "unkown".to_string() - } - } else { - error!("Unkown mime type."); - "unkown".to_string() - }; + let ext = get_ext(ct_type.cloned()).unwrap_or(String::from("unkown")); info!("Extension: {}", ext); // Construct a temp file to save desired content. @@ -74,6 +57,19 @@ fn download_into(dir: &str, file_title: &str, url: &str) -> Result { Ok(target) } +// Determine the file extension from the http content-type header. +fn get_ext(content: Option) -> Option { + let cont = content.clone()?; + content.and_then(|c| mime_guess::get_extensions(c.type_().as_ref(), c.subtype().as_ref())) + .and_then(|c| { + if c.contains(&cont.subtype().as_ref()) { + Some(cont.subtype().as_ref().to_string()) + } else { + Some(c.first().unwrap().to_string()) + } + }) +} + // TODO: Write unit-tests. /// Handles the I/O of fetching a remote file and saving into a Buffer and A File. fn save_io(file: &str, resp: &mut reqwest::Response, content_lenght: Option) -> Result<()> { diff --git a/hammond-gtk/src/content.rs b/hammond-gtk/src/content.rs index 2d91541..0783f8c 100644 --- a/hammond-gtk/src/content.rs +++ b/hammond-gtk/src/content.rs @@ -1,8 +1,6 @@ use gtk; use gtk::prelude::*; -// use gdk_pixbuf::Pixbuf; -// use diesel::associations::Identifiable; use hammond_data::Podcast; use widgets::podcast::PodcastWidget; @@ -89,6 +87,7 @@ fn replace_podcasts(stack: >k::Stack, pop: &PopulatedView) { // old.destroy(); // } +#[allow(dead_code)] pub fn show_widget(stack: >k::Stack) { stack.set_visible_child_name("widget") } From ca2ad9b2da37070810d6796037e3d12b69aa8c14 Mon Sep 17 00:00:00 2001 From: Jordan Petridis Date: Mon, 4 Dec 2017 14:32:38 +0200 Subject: [PATCH 25/41] rustfmt fix?. --- rustfmt.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/rustfmt.toml b/rustfmt.toml index 3a40cc5..477cd1c 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -1,3 +1,4 @@ +unstable_features = true verbose = false disable_all_formatting = false skip_children = false From 0835b5ed4f122ea265d9775a1048a37b1e0fb37c Mon Sep 17 00:00:00 2001 From: Jordan Petridis Date: Tue, 5 Dec 2017 06:22:59 +0200 Subject: [PATCH 26/41] flatpak manifest update --- org.gnome.Hammond.json | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/org.gnome.Hammond.json b/org.gnome.Hammond.json index 459b13c..09b1936 100644 --- a/org.gnome.Hammond.json +++ b/org.gnome.Hammond.json @@ -14,23 +14,23 @@ "--talk-name=org.freedesktop.Notifications" ], "build-options": { + "append-path": "/usr/lib/sdk/rust-stable/bin", + "build-args": [ + "--share=network" + ], "env": { "CARGO_HOME": "/run/build/Hammond/cargo" - }, - "build-args": [ "--share=network" ] + } }, "modules": [ { "name": "Hammond", - "buildsystem": "simple", - "build-commands": [ - "source /usr/lib/sdk/rust-stable/enable.sh && ./configure --prefix=/app && make && make install" - ], + "buildsystem": "meson", "sources": [ { "type": "git", "url": "https://gitlab.gnome.org/alatiera/Hammond.git", - "branch": "master" + "branch": "client-rework" } ] } From c8c0699d9ca533d4e8f3ca100e58cf3b8424e9a0 Mon Sep 17 00:00:00 2001 From: Jordan Petridis Date: Tue, 5 Dec 2017 07:37:43 +0200 Subject: [PATCH 27/41] gitlab-ci tweak. --- .gitlab-ci.yml | 12 ++++++++---- org.gnome.Hammond.json | 2 +- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index f9fdf03..d4a490f 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -38,19 +38,21 @@ variables: # - ./configure --prefix=/usr/local # - make && sudo make install -test:stable: +stable:test: # Stable img # https://hub.docker.com/_/rust/ image: "rust" + stage: test script: - rustc --version && cargo --version - cargo build - cargo test --verbose -- --test-threads=1 -test:nightly: +nightly:test: # Nightly # https://hub.docker.com/r/rustlang/rust/ image: "rustlang/rust:nightly" + stage: test script: - rustc --version && cargo --version - cargo build @@ -59,8 +61,9 @@ test:nightly: # Configure and run rustfmt on nightly # Exits and builds fails if on bad format -lint:rustfmt: +rustfmt: image: "rustlang/rust:nightly" + stage: lint script: - rustc --version && cargo --version - cargo install rustfmt-nightly @@ -68,8 +71,9 @@ lint:rustfmt: # Configure and run clippy on nightly # Only fails on errors atm. -lint:clippy: +clippy: image: "rustlang/rust:nightly" + stage: lint script: - rustc --version && cargo --version - cargo install clippy diff --git a/org.gnome.Hammond.json b/org.gnome.Hammond.json index 09b1936..ea403fc 100644 --- a/org.gnome.Hammond.json +++ b/org.gnome.Hammond.json @@ -30,7 +30,7 @@ { "type": "git", "url": "https://gitlab.gnome.org/alatiera/Hammond.git", - "branch": "client-rework" + "branch": "master" } ] } From 35f7464540852ee53eed10d45a0ccba213f8b9e9 Mon Sep 17 00:00:00 2001 From: Jordan Petridis Date: Tue, 5 Dec 2017 07:47:07 +0200 Subject: [PATCH 28/41] Use a gitlab-ci template instead of script duplication. --- .gitlab-ci.yml | 42 +++++++++--------------------------------- 1 file changed, 9 insertions(+), 33 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index d4a490f..1bc2bbc 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -14,50 +14,26 @@ before_script: # kcov # - apt-get install -y libcurl4-openssl-dev libelf-dev libdw-dev cmake gcc binutils-dev libiberty-dev +.cargo_test_template: &cargo_test + stage: test + script: + - rustc --version && cargo --version + - cargo build + - cargo test --verbose -- --test-threads=1 + variables: # RUSTFLAGS: "-C link-dead-code" RUST_BACKTRACE: "FULL" -# Currently doesnt work. -# # Build with meson -# build:stable: -# # Stable img -# # https://hub.docker.com/_/rust/ -# image: "rust" -# script: -# - rustc --version && cargo --version -# - ./configure --prefix=/usr/local -# - make && sudo make install - -# build:nightly: -# # Nightly -# # https://hub.docker.com/r/rustlang/rust/ -# image: "rustlang/rust:nightly" -# script: -# - rustc --version && cargo --version -# - ./configure --prefix=/usr/local -# - make && sudo make install - stable:test: - # Stable img # https://hub.docker.com/_/rust/ image: "rust" - stage: test - script: - - rustc --version && cargo --version - - cargo build - - cargo test --verbose -- --test-threads=1 + <<: *cargo_test nightly:test: - # Nightly # https://hub.docker.com/r/rustlang/rust/ image: "rustlang/rust:nightly" - stage: test - script: - - rustc --version && cargo --version - - cargo build - - cargo test --verbose -- --test-threads=1 - # - cargo bench + <<: *cargo_test # Configure and run rustfmt on nightly # Exits and builds fails if on bad format From 8e6cc4d2f235f3cd3de33e8a4cc7485142ea7b54 Mon Sep 17 00:00:00 2001 From: Jordan Petridis Date: Tue, 5 Dec 2017 09:10:02 +0200 Subject: [PATCH 29/41] Remove custom builders in favor of derive_builder crate. --- Cargo.lock | 1 + hammond-data/Cargo.toml | 1 + hammond-data/src/lib.rs | 3 + hammond-data/src/models/insertables.rs | 200 ++----------------------- hammond-data/src/parser.rs | 8 +- hammond-data/src/utils.rs | 17 ++- 6 files changed, 38 insertions(+), 192 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index bd05568..280ca0f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -549,6 +549,7 @@ name = "hammond-data" version = "0.1.0" dependencies = [ "chrono 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "derive_builder 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "diesel 0.99.0 (registry+https://github.com/rust-lang/crates.io-index)", "diesel_migrations 0.99.0 (registry+https://github.com/rust-lang/crates.io-index)", "dotenv 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/hammond-data/Cargo.toml b/hammond-data/Cargo.toml index 420d67d..f20c271 100644 --- a/hammond-data/Cargo.toml +++ b/hammond-data/Cargo.toml @@ -18,6 +18,7 @@ rfc822_sanitizer = "0.3.3" rss = "1.2.1" url = "1.6.0" xdg = "2.1.0" +derive_builder = "0.5.0" [dependencies.diesel] features = ["sqlite"] diff --git a/hammond-data/src/lib.rs b/hammond-data/src/lib.rs index 388d2bc..25994a8 100644 --- a/hammond-data/src/lib.rs +++ b/hammond-data/src/lib.rs @@ -34,6 +34,9 @@ extern crate diesel; #[macro_use] extern crate diesel_migrations; +#[macro_use] +extern crate derive_builder; + extern crate chrono; extern crate r2d2; extern crate r2d2_diesel; diff --git a/hammond-data/src/models/insertables.rs b/hammond-data/src/models/insertables.rs index 7a0ddef..c303dfa 100644 --- a/hammond-data/src/models/insertables.rs +++ b/hammond-data/src/models/insertables.rs @@ -1,3 +1,5 @@ +#![allow(unused_mut)] + use diesel::prelude::*; use schema::{episode, podcast, source}; @@ -20,7 +22,10 @@ trait Update { #[derive(Insertable)] #[table_name = "source"] -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Default, Builder)] +#[builder(default)] +#[builder(derive(Debug))] +#[builder(setter(into))] pub(crate) struct NewSource { uri: String, last_modified: Option, @@ -63,15 +68,15 @@ impl NewSource { #[derive(Insertable, AsChangeset)] #[table_name = "podcast"] -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Default, Builder)] +#[builder(default)] +#[builder(derive(Debug))] +#[builder(setter(into))] pub(crate) struct NewPodcast { title: String, link: String, description: String, image_uri: Option, - favorite: bool, - archive: bool, - always_dl: bool, source_id: i32, } @@ -124,78 +129,6 @@ impl NewPodcast { } } -#[derive(Debug, Default)] -pub(crate) struct NewPodcastBuilder { - title: String, - link: String, - description: String, - image_uri: Option, - favorite: bool, - archive: bool, - always_dl: bool, - source_id: i32, -} - -#[allow(dead_code)] -impl NewPodcastBuilder { - pub(crate) fn new() -> NewPodcastBuilder { - NewPodcastBuilder::default() - } - - pub(crate) fn title(mut self, s: String) -> NewPodcastBuilder { - self.title = s; - self - } - - pub(crate) fn link(mut self, s: String) -> NewPodcastBuilder { - self.link = s; - self - } - - pub(crate) fn description(mut self, s: String) -> NewPodcastBuilder { - self.description = s; - self - } - - pub(crate) fn image_uri(mut self, s: Option) -> NewPodcastBuilder { - self.image_uri = s; - self - } - - pub(crate) fn source_id(mut self, s: i32) -> NewPodcastBuilder { - self.source_id = s; - self - } - - pub(crate) fn favorite(mut self, s: bool) -> NewPodcastBuilder { - self.favorite = s; - self - } - - pub(crate) fn archive(mut self, s: bool) -> NewPodcastBuilder { - self.archive = s; - self - } - - pub(crate) fn always_dl(mut self, s: bool) -> NewPodcastBuilder { - self.always_dl = s; - self - } - - pub(crate) fn build(self) -> NewPodcast { - NewPodcast { - title: self.title, - link: self.link, - description: self.description, - image_uri: self.image_uri, - favorite: self.favorite, - archive: self.archive, - always_dl: self.always_dl, - source_id: self.source_id, - } - } -} - #[allow(dead_code)] // Ignore the following geters. They are used in unit tests mainly. impl NewPodcast { @@ -222,19 +155,18 @@ impl NewPodcast { #[derive(Insertable, AsChangeset)] #[table_name = "episode"] -#[derive(Debug, Clone, Default)] +#[derive(Debug, Clone, Default, Builder)] +#[builder(default)] +#[builder(derive(Debug))] +#[builder(setter(into))] pub(crate) struct NewEpisode { title: Option, uri: String, - local_uri: Option, description: Option, published_date: Option, length: Option, guid: Option, epoch: i32, - played: Option, - favorite: bool, - archive: bool, podcast_id: i32, } @@ -256,8 +188,6 @@ impl Update for NewEpisode { } impl NewEpisode { - // TODO: Currently using diesel from master git. - // Watch out for v0.99.0 beta and change the toml. // TODO: Refactor into batch indexes instead. pub(crate) fn into_episode(self, con: &SqliteConnection) -> Result { self.index(con)?; @@ -287,108 +217,8 @@ impl NewEpisode { } } -#[derive(Debug, Default)] -pub(crate) struct NewEpisodeBuilder { - title: Option, - uri: String, - local_uri: Option, - description: Option, - published_date: Option, - length: Option, - guid: Option, - epoch: i32, - played: Option, - favorite: bool, - archive: bool, - podcast_id: i32, -} - #[allow(dead_code)] -impl NewEpisodeBuilder { - pub(crate) fn new() -> NewEpisodeBuilder { - NewEpisodeBuilder::default() - } - - pub(crate) fn title(mut self, s: Option) -> NewEpisodeBuilder { - self.title = s; - self - } - - pub(crate) fn uri(mut self, s: String) -> NewEpisodeBuilder { - self.uri = s; - self - } - - pub(crate) fn local_uri(mut self, s: Option) -> NewEpisodeBuilder { - self.local_uri = s; - self - } - - pub(crate) fn description(mut self, s: Option) -> NewEpisodeBuilder { - self.description = s; - self - } - - pub(crate) fn published_date(mut self, s: Option) -> NewEpisodeBuilder { - self.published_date = s; - self - } - - pub(crate) fn length(mut self, s: Option) -> NewEpisodeBuilder { - self.length = s; - self - } - - pub(crate) fn played(mut self, s: Option) -> NewEpisodeBuilder { - self.played = s; - self - } - - pub(crate) fn guid(mut self, s: Option) -> NewEpisodeBuilder { - self.guid = s; - self - } - - pub(crate) fn epoch(mut self, s: i32) -> NewEpisodeBuilder { - self.epoch = s; - self - } - - pub(crate) fn podcast_id(mut self, s: i32) -> NewEpisodeBuilder { - self.podcast_id = s; - self - } - - pub(crate) fn favorite(mut self, s: bool) -> NewEpisodeBuilder { - self.favorite = s; - self - } - - pub(crate) fn archive(mut self, s: bool) -> NewEpisodeBuilder { - self.archive = s; - self - } - - pub(crate) fn build(self) -> NewEpisode { - NewEpisode { - title: self.title, - uri: self.uri, - local_uri: self.local_uri, - description: self.description, - published_date: self.published_date, - length: self.length, - guid: self.guid, - epoch: self.epoch, - played: self.played, - favorite: self.favorite, - archive: self.archive, - podcast_id: self.podcast_id, - } - } -} - -#[allow(dead_code)] -// Ignore the following geters. They are used in unit tests mainly. +// Ignore the following getters. They are used in unit tests mainly. impl NewEpisode { pub(crate) fn title(&self) -> Option<&str> { self.title.as_ref().map(|s| s.as_str()) diff --git a/hammond-data/src/parser.rs b/hammond-data/src/parser.rs index 5ea6ce2..0f69281 100644 --- a/hammond-data/src/parser.rs +++ b/hammond-data/src/parser.rs @@ -20,13 +20,14 @@ pub(crate) fn new_podcast(chan: &Channel, source_id: i32) -> NewPodcast { chan.image().map(|foo| url_cleaner(foo.url())) }; - NewPodcastBuilder::new() + NewPodcastBuilder::default() .title(title) .description(description) .link(link) .image_uri(image_uri) .source_id(source_id) .build() + .unwrap() } /// Parses an `rss::Item` into a `NewEpisode` Struct. @@ -61,7 +62,7 @@ pub(crate) fn new_episode(item: &Item, parent_id: i32) -> Result { let length = item.enclosure().map(|x| x.length().parse().unwrap_or(0)); Ok( - NewEpisodeBuilder::new() + NewEpisodeBuilder::default() .title(title) .uri(uri) .description(description) @@ -70,7 +71,8 @@ pub(crate) fn new_episode(item: &Item, parent_id: i32) -> Result { .epoch(epoch) .guid(guid) .podcast_id(parent_id) - .build(), + .build() + .unwrap() ) } diff --git a/hammond-data/src/utils.rs b/hammond-data/src/utils.rs index a29ad6b..75e78f5 100644 --- a/hammond-data/src/utils.rs +++ b/hammond-data/src/utils.rs @@ -129,19 +129,28 @@ mod tests { // Setup episodes let db = connection(); let con = db.get().unwrap(); - NewEpisodeBuilder::new() + NewEpisodeBuilder::default() .uri("foo_bar".to_string()) - .local_uri(Some(valid_path.to_str().unwrap().to_owned())) .build() + .unwrap() .into_episode(&con) .unwrap(); - NewEpisodeBuilder::new() + NewEpisodeBuilder::default() .uri("bar_baz".to_string()) - .local_uri(Some(bad_path.to_str().unwrap().to_owned())) .build() + .unwrap() .into_episode(&con) .unwrap(); + + let mut ep1 = dbqueries::get_episode_from_uri(&con, "foo_bar").unwrap(); + let mut ep2 = dbqueries::get_episode_from_uri(&con, "bar_baz").unwrap(); + ep1.set_local_uri(Some(valid_path.to_str().unwrap())); + ep2.set_local_uri(Some(bad_path.to_str().unwrap())); + + drop(con); + ep1.save().unwrap(); + ep2.save().unwrap(); tmp_dir } From 05e056481f0637d6be91535b5f4d7bbe82dd4a12 Mon Sep 17 00:00:00 2001 From: Jordan Petridis Date: Tue, 5 Dec 2017 09:28:13 +0200 Subject: [PATCH 30/41] Take advantage of trait from the generated builders. --- hammond-data/src/parser.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hammond-data/src/parser.rs b/hammond-data/src/parser.rs index 0f69281..da04862 100644 --- a/hammond-data/src/parser.rs +++ b/hammond-data/src/parser.rs @@ -9,10 +9,10 @@ use errors::*; // TODO: Extend the support for parsing itunes extensions /// Parses a `rss::Channel` into a `NewPodcast` Struct. pub(crate) fn new_podcast(chan: &Channel, source_id: i32) -> NewPodcast { - let title = chan.title().trim().to_owned(); - let description = chan.description().trim().to_owned(); + let title = chan.title().trim(); + let description = chan.description().trim(); - let link = url_cleaner(chan.link()).to_owned(); + let link = url_cleaner(chan.link()); let x = chan.itunes_ext().map(|s| s.image()); let image_uri = if let Some(img) = x { img.map(|s| url_cleaner(s)) From c07d2405326000eac1976b1ffad137ec2878b67e Mon Sep 17 00:00:00 2001 From: Jordan Petridis Date: Thu, 7 Dec 2017 06:38:31 +0200 Subject: [PATCH 31/41] Sanitize html during feed parsing. --- Cargo.lock | 22 ++++++++++++++++++++++ hammond-data/Cargo.toml | 3 ++- hammond-data/src/lib.rs | 1 + hammond-data/src/parser.rs | 25 +++++++++++++------------ hammond-gtk/src/widgets/episode.rs | 29 ++++++++++++++++++----------- scripts/release.sh | 2 -- 6 files changed, 56 insertions(+), 26 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 280ca0f..f6037b3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -20,6 +20,19 @@ dependencies = [ "memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "ammonia" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "html5ever 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "maplit 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tendril 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "ansi_term" version = "0.10.2" @@ -548,6 +561,7 @@ dependencies = [ name = "hammond-data" version = "0.1.0" dependencies = [ + "ammonia 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "chrono 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "derive_builder 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "diesel 0.99.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -599,6 +613,7 @@ dependencies = [ "loggerv 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "open 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "rayon 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -752,6 +767,11 @@ name = "mac" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "maplit" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "markup5ever" version = "0.6.2" @@ -1583,6 +1603,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum adler32 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6cbd0b9af8587c72beadc9f72d35b9fbb070982c9e6203e46e93f10df25f8f45" "checksum advapi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e06588080cb19d0acb6739808aafa5f26bfb2ca015b2b6370028b44cf7cb8a9a" "checksum aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d6531d44de723825aa81398a6415283229725a00fa30713812ab9323faa82fc4" +"checksum ammonia 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2cc0ea12b4977283c563e78eaf227b024d89d72a6394040fad4063899bfcfb48" "checksum ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6b3568b48b7cefa6b8ce125f9bb4989e52fbcc29ebea88df04cc7c5f12f70455" "checksum antidote 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "34fde25430d87a9388dadbe6e34d7f72a462c8b43ac8d309b42b0a8505d7e2a5" "checksum atk-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "33a67fd81e1922dddc335887516f2f5254534e89c9d39fa89bca5d79bd150d34" @@ -1658,6 +1679,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "880f77541efa6e5cc74e76910c9884d9859683118839d6a1dc3b11e63512565b" "checksum loggerv 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b178879253fab6ddb4ea931e1e6f514d45ce6a53f7fe618a0a8751f43e42e4f1" "checksum mac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4" +"checksum maplit 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5ed95049d40b8a1a7691adbabca028ad481f7e6a2921ce4846e1ee168b4e4ca5" "checksum markup5ever 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2cf89d3e0486c32c9d99521455ddf9a438910a1ce2bd376936086edc15dff5fc" "checksum matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "100aabe6b8ff4e4a7e32c1c13523379802df0772b82466207ac25b013f193376" "checksum memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "796fba70e76612589ed2ce7f45282f5af869e0fdd7cc6199fa1aa1f1d591ba9d" diff --git a/hammond-data/Cargo.toml b/hammond-data/Cargo.toml index f20c271..34e41c4 100644 --- a/hammond-data/Cargo.toml +++ b/hammond-data/Cargo.toml @@ -5,7 +5,9 @@ version = "0.1.0" workspace = "../" [dependencies] +ammonia = "1.0.0" chrono = "0.4.0" +derive_builder = "0.5.0" dotenv = "0.10.1" error-chain = "0.11.0" lazy_static = "1.0.0" @@ -18,7 +20,6 @@ rfc822_sanitizer = "0.3.3" rss = "1.2.1" url = "1.6.0" xdg = "2.1.0" -derive_builder = "0.5.0" [dependencies.diesel] features = ["sqlite"] diff --git a/hammond-data/src/lib.rs b/hammond-data/src/lib.rs index 25994a8..b4465f1 100644 --- a/hammond-data/src/lib.rs +++ b/hammond-data/src/lib.rs @@ -46,6 +46,7 @@ extern crate rfc822_sanitizer; extern crate rss; extern crate url; extern crate xdg; +extern crate ammonia; #[allow(missing_docs)] pub mod dbqueries; diff --git a/hammond-data/src/parser.rs b/hammond-data/src/parser.rs index da04862..2cddc50 100644 --- a/hammond-data/src/parser.rs +++ b/hammond-data/src/parser.rs @@ -1,3 +1,4 @@ +use ammonia; use rss::{Channel, Item}; use rfc822_sanitizer::parse_from_rfc2822_with_fallback; @@ -10,7 +11,7 @@ use errors::*; /// Parses a `rss::Channel` into a `NewPodcast` Struct. pub(crate) fn new_podcast(chan: &Channel, source_id: i32) -> NewPodcast { let title = chan.title().trim(); - let description = chan.description().trim(); + let description = ammonia::clean(chan.description().trim()); let link = url_cleaner(chan.link()); let x = chan.itunes_ext().map(|s| s.image()); @@ -33,7 +34,7 @@ pub(crate) fn new_podcast(chan: &Channel, source_id: i32) -> NewPodcast { /// Parses an `rss::Item` into a `NewEpisode` Struct. pub(crate) fn new_episode(item: &Item, parent_id: i32) -> Result { let title = item.title().map(|s| s.trim().to_owned()); - let description = item.description().map(|s| s.trim().to_owned()); + let description = item.description().map(|s| ammonia::clean(s.trim())); let guid = item.guid().map(|s| s.value().trim().to_owned()); // Its kinda weird this being an Option type. @@ -276,10 +277,10 @@ mod tests { let channel = Channel::read_from(BufReader::new(file)).unwrap(); let firstitem = channel.items().first().unwrap(); - let descr = - "Audit your network with a couple of easy commands on Kali Linux. Chris decides to \ - blow off a little steam by attacking his IoT devices, Wes has the scope on Equifax \ - blaming open source & the Beard just saved the show. It’s a really packed episode!"; + let descr = "Audit your network with a couple of easy commands on Kali Linux. Chris \ + decides to blow off a little steam by attacking his IoT devices, Wes has \ + the scope on Equifax blaming open source & the Beard just saved the \ + show. It’s a really packed episode!"; let i = new_episode(&firstitem, 0).unwrap(); assert_eq!(i.title(), Some("Hacking Devices with Kali Linux | LUP 214")); @@ -301,7 +302,7 @@ mod tests { decisions for the next version of Gnome have us worried about the \ future.

\n\n

Plus we chat with Wimpy about the Ubuntu Rally in NYC, \ Microsoft’s sneaky move to turn Windows 10 into the “ULTIMATE LINUX \ - RUNTIME”, community news & more!

"; + RUNTIME”, community news & more!

"; assert_eq!(i2.title(), Some("Gnome Does it Again | LUP 213")); assert_eq!( i2.uri(), @@ -321,8 +322,8 @@ mod tests { let firstitem = channel.items().iter().nth(9).unwrap(); let descr = "This week we look at RFC 2094 \ - \"Non-lexical lifetimes\""; + href=\"https://github.com/rust-lang/rfcs/pull/2094\" rel=\"noopener \ + noreferrer\">RFC 2094 \"Non-lexical lifetimes\""; let i = new_episode(&firstitem, 0).unwrap(); assert_eq!(i.title(), Some("Episode #9 - A Once in a Lifetime RFC")); @@ -343,9 +344,9 @@ mod tests { let second = channel.items().iter().nth(8).unwrap(); let i2 = new_episode(&second, 0).unwrap(); - let descr2 = "This week we look at RFC 2071 \"Add \ - impl Trait type alias and variable declarations\""; + let descr2 = "This week we look at RFC 2071 \"Add impl Trait type alias and \ + variable declarations\""; assert_eq!(i2.title(), Some("Episode #8 - An Existential Crisis")); assert_eq!( i2.uri(), diff --git a/hammond-gtk/src/widgets/episode.rs b/hammond-gtk/src/widgets/episode.rs index 4d51d85..4d876df 100644 --- a/hammond-gtk/src/widgets/episode.rs +++ b/hammond-gtk/src/widgets/episode.rs @@ -1,23 +1,25 @@ +use glib; +use gtk; +use gtk::prelude::*; +use gtk::{ContainerExt, TextBufferExt}; + use open; +use dissolve::strip_html_tags; +use diesel::associations::Identifiable; + use hammond_data::dbqueries; use hammond_data::{Episode, Podcast}; use hammond_downloader::downloader; use hammond_data::utils::*; use hammond_data::errors::*; -use dissolve::strip_html_tags; -use diesel::associations::Identifiable; +// use utils::html_to_markup; use std::thread; use std::cell::RefCell; use std::sync::mpsc::{channel, Receiver}; use std::path::Path; -use glib; -use gtk; -use gtk::prelude::*; -use gtk::{ContainerExt, TextBufferExt}; - type Foo = RefCell)>>; thread_local!(static GLOBAL: Foo = RefCell::new(None)); @@ -32,6 +34,7 @@ struct EpisodeWidget { unplayed: gtk::Button, title: gtk::Label, description: gtk::TextView, + // description: gtk::Label, expander: gtk::Expander, } @@ -50,6 +53,7 @@ impl EpisodeWidget { let title: gtk::Label = builder.get_object("title_label").unwrap(); let expander: gtk::Expander = builder.get_object("expand_desc").unwrap(); let description: gtk::TextView = builder.get_object("desc_text_view").unwrap(); + // let description: gtk::Label = builder.get_object("desc_text").unwrap(); EpisodeWidget { container, @@ -78,12 +82,15 @@ impl EpisodeWidget { } if episode.description().is_some() { - let d = episode.description().unwrap().to_owned(); - + let text = episode.description().unwrap().to_owned(); let description = &self.description; self.expander - .connect_activate(clone!(description => move |_| { - let plain_text = strip_html_tags(&d).join(" "); + .connect_activate(clone!(description, text => move |_| { + // let mut text = text.clone(); + // html_to_markup(&mut text); + // description.set_markup(&text) + + let plain_text = strip_html_tags(&text).join(""); // TODO: handle unwrap let buff = description.get_buffer().unwrap(); buff.set_text(plain_text.trim()); diff --git a/scripts/release.sh b/scripts/release.sh index 9715f8b..cced5a7 100755 --- a/scripts/release.sh +++ b/scripts/release.sh @@ -12,14 +12,12 @@ mkdir -p $DIST cp -rf hammond-data $DIST cp -rf hammond-gtk $DIST cp -rf hammond-downloader $DIST -cp build.rs $DIST cp Cargo.toml $DIST cp configure $DIST cp meson.build $DIST cp Hammond.doap $DIST cp LICENSE $DIST cp README.md $DIST -# cp -rf assets/org.gnome.Hammond.desktop $DIST cp -rf assets $DIST cp -rf scripts $DIST From d7af108833919d8e57ff6bea2de44c0211361406 Mon Sep 17 00:00:00 2001 From: Jordan Petridis Date: Thu, 7 Dec 2017 06:41:10 +0200 Subject: [PATCH 32/41] WIP markup to html parser func. --- hammond-gtk/Cargo.toml | 1 + hammond-gtk/src/main.rs | 1 + hammond-gtk/src/utils.rs | 14 ++++++++++++++ 3 files changed, 16 insertions(+) diff --git a/hammond-gtk/Cargo.toml b/hammond-gtk/Cargo.toml index a59c1ef..810cbbb 100644 --- a/hammond-gtk/Cargo.toml +++ b/hammond-gtk/Cargo.toml @@ -15,6 +15,7 @@ log = "0.3.8" loggerv = "0.6.0" open = "1.2.1" rayon = "0.9.0" +regex = "0.2.3" [dependencies.diesel] features = ["sqlite"] diff --git a/hammond-gtk/src/main.rs b/hammond-gtk/src/main.rs index 5afcb5f..d231464 100644 --- a/hammond-gtk/src/main.rs +++ b/hammond-gtk/src/main.rs @@ -12,6 +12,7 @@ extern crate hammond_downloader; extern crate log; extern crate loggerv; extern crate open; +extern crate regex; // extern crate rayon; // use rayon::prelude::*; diff --git a/hammond-gtk/src/utils.rs b/hammond-gtk/src/utils.rs index 14e8b46..5402b90 100644 --- a/hammond-gtk/src/utils.rs +++ b/hammond-gtk/src/utils.rs @@ -9,8 +9,10 @@ use hammond_downloader::downloader; use std::{thread, time}; use std::cell::RefCell; use std::sync::mpsc::{channel, Receiver}; +use std::borrow::Cow; use content; +use regex::Regex; type Foo = RefCell)>>; @@ -69,6 +71,18 @@ pub fn get_pixbuf_from_path(pd: &Podcast) -> Option { Pixbuf::new_from_file_at_scale(&img_path, 256, 256, true).ok() } +#[allow(dead_code)] +// WIP: parse html to markup +pub fn html_to_markup(s: &mut str) -> Cow { + s.trim(); + s.replace('&', "&"); + s.replace('<', "<"); + s.replace('>', ">"); + + let re = Regex::new("(?Phttps?://[^\\s&,)(\"]+(&\\w=[\\w._-]?)*(#[\\w._-]+)?)").unwrap(); + re.replace_all(s, "$url") +} + #[cfg(test)] mod tests { use hammond_data::Source; From 9431fb827f0556a3ab8f23e6203d72ecd5fabad6 Mon Sep 17 00:00:00 2001 From: Jordan Petridis Date: Thu, 7 Dec 2017 08:42:36 +0200 Subject: [PATCH 33/41] Bug fix. --- hammond-gtk/src/widgets/podcast.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hammond-gtk/src/widgets/podcast.rs b/hammond-gtk/src/widgets/podcast.rs index 140e313..4fe93dd 100644 --- a/hammond-gtk/src/widgets/podcast.rs +++ b/hammond-gtk/src/widgets/podcast.rs @@ -108,8 +108,8 @@ fn on_unsub_button_clicked(stack: >k::Stack, pd: &Podcast, unsub_button: >k: } }; } - content::show_podcasts(stack); content::update_podcasts(stack); + content::show_podcasts(stack); } fn on_played_button_clicked(stack: >k::Stack, pd: &Podcast) { From 2b2f44b10eddf6badad79056302b322c5ae6d735 Mon Sep 17 00:00:00 2001 From: Jordan Petridis Date: Thu, 7 Dec 2017 08:50:20 +0200 Subject: [PATCH 34/41] Attempt n42 of implementing a StateMachine. --- hammond-gtk/src/content.rs | 154 +++++++++++++++++++++++++++---------- hammond-gtk/src/main.rs | 4 +- 2 files changed, 115 insertions(+), 43 deletions(-) diff --git a/hammond-gtk/src/content.rs b/hammond-gtk/src/content.rs index 0783f8c..b7dc9be 100644 --- a/hammond-gtk/src/content.rs +++ b/hammond-gtk/src/content.rs @@ -10,57 +10,129 @@ use views::empty::EmptyView; #[derive(Debug)] pub struct Content { pub stack: gtk::Stack, - // widget: PodcastWidget, - // podcasts: PopulatedView, - // empty: EmptyView, -} - -// #[derive(Debug)] -// pub struct Content { -// pub stack: gtk::Stack, -// pub state: ContentState, -// widget: PodcastWidget, -// pub podcasts: PopulatedView, -// empty: EmptyView, -// } - -#[derive(Debug)] -#[allow(dead_code)] -// TODO: find a way to wrap gtk::Stack into a State machine. -pub enum ContentState { - Widget(PodcastWidget), - Empty(EmptyView), - Populated(PopulatedView), + pub widget: PodcastWidget, + pub podcasts: PopulatedView, + pub empty: EmptyView, } impl Content { - pub fn new() -> Content { + fn new() -> Content { let stack = gtk::Stack::new(); - let content = Content { - stack, - // widget, - // empty, - // podcasts: pop, - }; - - content.init(); - content - } - - fn init(&self) { let widget = PodcastWidget::new(); let podcasts = PopulatedView::new(); let empty = EmptyView::new(); - self.stack.add_named(&widget.container, "widget"); - self.stack.add_named(&podcasts.container, "podcasts"); - self.stack.add_named(&empty.container, "empty"); - self.stack.set_visible_child_name("podcasts"); + stack.add_named(&widget.container, "widget"); + stack.add_named(&podcasts.container, "podcasts"); + stack.add_named(&empty.container, "empty"); - podcasts.init(&self.stack); - if podcasts.flowbox.get_children().is_empty() { - self.stack.set_visible_child_name("empty"); + Content { + stack, + widget, + empty, + podcasts, + } + } +} + +#[derive(Debug)] +struct Empty { + content: Content +} + +#[derive(Debug)] +struct PodcastsView { + content: Content +} + +#[derive(Debug)] +struct WidgetsView { + content: Content +} + +impl Empty { + fn into_podcasts(self) -> Result { + if self.content.podcasts.flowbox.get_children().is_empty() { + return Err(self); + } + + self.content.stack.set_visible_child_name("podcasts"); + + Ok( + PodcastsView { + content: self.content + } + ) + } +} + +impl PodcastsView { + fn into_empty(self) -> Result { + if !self.content.podcasts.flowbox.get_children().is_empty() { + return Err(self); + } + + self.content.stack.set_visible_child_name("empty"); + + Ok( + Empty { + content: self.content + } + ) + } + + fn into_widget(self) -> WidgetsView { + self.content.stack.set_visible_child_name("widget"); + + WidgetsView { + content: self.content + } + } +} + +impl WidgetsView { + fn into_podcasts(self) -> PodcastsView { + self.content.stack.set_visible_child_name("podcasts"); + PodcastsView { + content: self.content + } + } + + fn into_empty(self) -> Empty { + self.content.stack.set_visible_child_name("empty"); + Empty { + content: self.content + } + } +} + +#[derive(Debug)] +pub enum ContentState { + empty(Empty), + pop(PodcastsView), + pd(WidgetsView), +} + +impl ContentState { + pub fn new() -> ContentState { + let content = Content::new(); + + content.podcasts.init(&content.stack); + if content.podcasts.flowbox.get_children().is_empty() { + content.stack.set_visible_child_name("empty"); + return ContentState::empty(Empty { content }) + } + + content.stack.set_visible_child_name("podcasts"); + ContentState::pop(PodcastsView{ content }) + } + + pub fn get_stack(&self) -> gtk::Stack { + match *self { + ContentState::empty(ref e) => e.content.stack.clone(), + ContentState::pop(ref e) => e.content.stack.clone(), + ContentState::pd(ref e) => e.content.stack.clone(), } } } diff --git a/hammond-gtk/src/main.rs b/hammond-gtk/src/main.rs index d231464..a4aa344 100644 --- a/hammond-gtk/src/main.rs +++ b/hammond-gtk/src/main.rs @@ -63,8 +63,8 @@ fn build_ui(app: >k::Application) { let window = gtk::ApplicationWindow::new(app); window.set_default_size(1150, 650); - let ct = content::Content::new(); - let stack = ct.stack.clone(); + let ct = content::ContentState::new(); + let stack = ct.get_stack(); window.add(&stack); window.connect_delete_event(|w, _| { From 973212254ce78f66c987592acd6f202e16cd1e6a Mon Sep 17 00:00:00 2001 From: Jordan Petridis Date: Thu, 7 Dec 2017 09:43:47 +0200 Subject: [PATCH 35/41] My code is horrible, don't look at it. --- hammond-gtk/src/content.rs | 44 ++++++++++++++++++++++++++++++ hammond-gtk/src/widgets/podcast.rs | 3 ++ 2 files changed, 47 insertions(+) diff --git a/hammond-gtk/src/content.rs b/hammond-gtk/src/content.rs index b7dc9be..dc8e0d0 100644 --- a/hammond-gtk/src/content.rs +++ b/hammond-gtk/src/content.rs @@ -2,6 +2,7 @@ use gtk; use gtk::prelude::*; use hammond_data::Podcast; +use hammond_data::dbqueries; use widgets::podcast::PodcastWidget; use views::podcasts::PopulatedView; @@ -36,6 +37,10 @@ impl Content { } } +trait UpdateView { + fn update(&mut self); +} + #[derive(Debug)] struct Empty { content: Content @@ -67,6 +72,10 @@ impl Empty { } } +impl UpdateView for Empty { + fn update(&mut self) {} +} + impl PodcastsView { fn into_empty(self) -> Result { if !self.content.podcasts.flowbox.get_children().is_empty() { @@ -91,6 +100,19 @@ impl PodcastsView { } } +impl UpdateView for PodcastsView { + fn update(&mut self) { + let old = self.content.stack.get_child_by_name("podcasts").unwrap(); + + self.content.podcasts = PopulatedView::new_initialized(&self.content.stack); + + self.content.stack.remove(&old); + self.content.stack.add_named(&self.content.podcasts.container, "podcasts"); + + old.destroy(); + } +} + impl WidgetsView { fn into_podcasts(self) -> PodcastsView { self.content.stack.set_visible_child_name("podcasts"); @@ -107,6 +129,20 @@ impl WidgetsView { } } +impl UpdateView for WidgetsView { + fn update(&mut self) { + let old = self.content.stack.get_child_by_name("widget").unwrap(); + let id = WidgetExt::get_name(&old).unwrap(); + let pd = dbqueries::get_podcast_from_id(id.parse::().unwrap()).unwrap(); + + self.content.widget = PodcastWidget::new_initialized(&self.content.stack, &pd);; + self.content.stack.remove(&old); + self.content.stack.add_named(&self.content.widget.container, "widget"); + + old.destroy(); + } +} + #[derive(Debug)] pub enum ContentState { empty(Empty), @@ -135,6 +171,14 @@ impl ContentState { ContentState::pd(ref e) => e.content.stack.clone(), } } + + pub fn update(&mut self) { + match *self { + ContentState::empty(ref mut e) => e.update(), + ContentState::pop(ref mut e) => e.update(), + ContentState::pd(ref mut e) => e.update(), + } + } } fn replace_widget(stack: >k::Stack, pdw: &PodcastWidget) { diff --git a/hammond-gtk/src/widgets/podcast.rs b/hammond-gtk/src/widgets/podcast.rs index 4fe93dd..206ffd9 100644 --- a/hammond-gtk/src/widgets/podcast.rs +++ b/hammond-gtk/src/widgets/podcast.rs @@ -1,5 +1,6 @@ use gtk::prelude::*; use gtk; +use diesel::Identifiable; use std::fs; @@ -53,6 +54,8 @@ impl PodcastWidget { } pub fn init(&self, stack: >k::Stack, pd: &Podcast) { + WidgetExt::set_name(&self.container, &pd.id().to_string()); + // TODO: should spawn a thread to avoid locking the UI probably. self.unsub.connect_clicked(clone!(stack, pd => move |bttn| { on_unsub_button_clicked(&stack, &pd, bttn); From 6801d0b1d1e0c13a20d7e6872f2c1fadcf1bf213 Mon Sep 17 00:00:00 2001 From: Jordan Petridis Date: Thu, 7 Dec 2017 10:51:16 +0200 Subject: [PATCH 36/41] Move replace_*view functions inot Content methods. --- hammond-gtk/src/content.rs | 35 ++++++++++++++++++++++------------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/hammond-gtk/src/content.rs b/hammond-gtk/src/content.rs index dc8e0d0..be858f0 100644 --- a/hammond-gtk/src/content.rs +++ b/hammond-gtk/src/content.rs @@ -35,6 +35,24 @@ impl Content { podcasts, } } + + fn replace_widget(&mut self, pdw: PodcastWidget) { + let old = self.stack.get_child_by_name("widget").unwrap(); + self.stack.remove(&old); + + self.widget = pdw; + self.stack.add_named(&self.widget.container, "widget"); + old.destroy(); + } + + fn replace_podcasts(&mut self, pop: PopulatedView) { + let old = self.stack.get_child_by_name("podcasts").unwrap(); + self.stack.remove(&old); + + self.podcasts = pop; + self.stack.add_named(&self.podcasts.container, "podcasts"); + old.destroy(); + } } trait UpdateView { @@ -102,14 +120,8 @@ impl PodcastsView { impl UpdateView for PodcastsView { fn update(&mut self) { - let old = self.content.stack.get_child_by_name("podcasts").unwrap(); - - self.content.podcasts = PopulatedView::new_initialized(&self.content.stack); - - self.content.stack.remove(&old); - self.content.stack.add_named(&self.content.podcasts.container, "podcasts"); - - old.destroy(); + let pop = PopulatedView::new_initialized(&self.content.stack); + self.content.replace_podcasts(pop) } } @@ -135,11 +147,8 @@ impl UpdateView for WidgetsView { let id = WidgetExt::get_name(&old).unwrap(); let pd = dbqueries::get_podcast_from_id(id.parse::().unwrap()).unwrap(); - self.content.widget = PodcastWidget::new_initialized(&self.content.stack, &pd);; - self.content.stack.remove(&old); - self.content.stack.add_named(&self.content.widget.container, "widget"); - - old.destroy(); + let pdw = PodcastWidget::new_initialized(&self.content.stack, &pd);; + self.content.replace_widget(pdw); } } From 41b0a36b81d08be92e023656d8ed8c3895aa7758 Mon Sep 17 00:00:00 2001 From: Jordan Petridis Date: Thu, 7 Dec 2017 11:14:12 +0200 Subject: [PATCH 37/41] Implement Into ContentState types. --- hammond-gtk/src/content.rs | 57 ++++++++++++++++---------------------- 1 file changed, 24 insertions(+), 33 deletions(-) diff --git a/hammond-gtk/src/content.rs b/hammond-gtk/src/content.rs index be858f0..d022c05 100644 --- a/hammond-gtk/src/content.rs +++ b/hammond-gtk/src/content.rs @@ -74,19 +74,20 @@ struct WidgetsView { content: Content } -impl Empty { - fn into_podcasts(self) -> Result { - if self.content.podcasts.flowbox.get_children().is_empty() { - return Err(self); - } +#[derive(Debug)] +pub enum ContentState { + empty(Empty), + pop(PodcastsView), + pd(WidgetsView), +} +impl Into for Empty { + fn into(self) -> PodcastsView { self.content.stack.set_visible_child_name("podcasts"); - Ok( - PodcastsView { - content: self.content - } - ) + PodcastsView { + content: self.content + } } } @@ -94,22 +95,17 @@ impl UpdateView for Empty { fn update(&mut self) {} } -impl PodcastsView { - fn into_empty(self) -> Result { - if !self.content.podcasts.flowbox.get_children().is_empty() { - return Err(self); - } - +impl Into for PodcastsView { + fn into(self) -> Empty { self.content.stack.set_visible_child_name("empty"); - - Ok( - Empty { - content: self.content - } - ) + Empty { + content: self.content + } } +} - fn into_widget(self) -> WidgetsView { +impl Into for PodcastsView { + fn into(self) -> WidgetsView { self.content.stack.set_visible_child_name("widget"); WidgetsView { @@ -125,15 +121,17 @@ impl UpdateView for PodcastsView { } } -impl WidgetsView { - fn into_podcasts(self) -> PodcastsView { +impl Into for WidgetsView { + fn into(self) -> PodcastsView { self.content.stack.set_visible_child_name("podcasts"); PodcastsView { content: self.content } } +} - fn into_empty(self) -> Empty { +impl Into for WidgetsView { + fn into(self) -> Empty { self.content.stack.set_visible_child_name("empty"); Empty { content: self.content @@ -152,13 +150,6 @@ impl UpdateView for WidgetsView { } } -#[derive(Debug)] -pub enum ContentState { - empty(Empty), - pop(PodcastsView), - pd(WidgetsView), -} - impl ContentState { pub fn new() -> ContentState { let content = Content::new(); From 1266c6e971e952ffc1ebbcafe9ef36ac2e39e90e Mon Sep 17 00:00:00 2001 From: Jordan Petridis Date: Thu, 7 Dec 2017 15:24:15 +0200 Subject: [PATCH 38/41] Switch to a Generic Struct instead of an Enum. --- hammond-gtk/src/content.rs | 111 ++++++++++++++++++------------------- hammond-gtk/src/main.rs | 3 +- 2 files changed, 56 insertions(+), 58 deletions(-) diff --git a/hammond-gtk/src/content.rs b/hammond-gtk/src/content.rs index d022c05..7554cb3 100644 --- a/hammond-gtk/src/content.rs +++ b/hammond-gtk/src/content.rs @@ -37,109 +37,111 @@ impl Content { } fn replace_widget(&mut self, pdw: PodcastWidget) { + let vis = self.stack.get_visible_child_name().unwrap(); let old = self.stack.get_child_by_name("widget").unwrap(); self.stack.remove(&old); self.widget = pdw; self.stack.add_named(&self.widget.container, "widget"); + self.stack.set_visible_child_name(&vis); old.destroy(); } fn replace_podcasts(&mut self, pop: PopulatedView) { + let vis = self.stack.get_visible_child_name().unwrap(); let old = self.stack.get_child_by_name("podcasts").unwrap(); self.stack.remove(&old); self.podcasts = pop; self.stack.add_named(&self.podcasts.container, "podcasts"); + self.stack.set_visible_child_name(&vis); old.destroy(); } } -trait UpdateView { +#[derive(Debug)] +pub struct ContentState { + content: Content, + state: S, +} + +pub trait UpdateView { fn update(&mut self); } #[derive(Debug)] -struct Empty { - content: Content -} +pub struct Empty {} #[derive(Debug)] -struct PodcastsView { - content: Content -} +pub struct PodcastsView {} #[derive(Debug)] -struct WidgetsView { - content: Content -} +pub struct WidgetsView {} -#[derive(Debug)] -pub enum ContentState { - empty(Empty), - pop(PodcastsView), - pd(WidgetsView), -} - -impl Into for Empty { - fn into(self) -> PodcastsView { +impl Into> for ContentState { + fn into(self) -> ContentState { self.content.stack.set_visible_child_name("podcasts"); - PodcastsView { - content: self.content + ContentState{ + content: self.content, + state: PodcastsView{}, } } } -impl UpdateView for Empty { +impl UpdateView for ContentState { fn update(&mut self) {} } -impl Into for PodcastsView { - fn into(self) -> Empty { +impl Into> for ContentState { + fn into(self) -> ContentState { self.content.stack.set_visible_child_name("empty"); - Empty { - content: self.content + ContentState{ + content: self.content, + state: Empty{}, } } } -impl Into for PodcastsView { - fn into(self) -> WidgetsView { +impl Into> for ContentState { + fn into(self) -> ContentState { self.content.stack.set_visible_child_name("widget"); - WidgetsView { - content: self.content + ContentState{ + content: self.content, + state: WidgetsView{}, } } } -impl UpdateView for PodcastsView { +impl UpdateView for ContentState { fn update(&mut self) { let pop = PopulatedView::new_initialized(&self.content.stack); self.content.replace_podcasts(pop) } } -impl Into for WidgetsView { - fn into(self) -> PodcastsView { +impl Into> for ContentState { + fn into(self) -> ContentState { self.content.stack.set_visible_child_name("podcasts"); - PodcastsView { - content: self.content + ContentState{ + content: self.content, + state: PodcastsView{}, } } } -impl Into for WidgetsView { - fn into(self) -> Empty { +impl Into> for ContentState { + fn into(self) -> ContentState { self.content.stack.set_visible_child_name("empty"); - Empty { - content: self.content + ContentState{ + content: self.content, + state: Empty{}, } } } -impl UpdateView for WidgetsView { +impl UpdateView for ContentState { fn update(&mut self) { let old = self.content.stack.get_child_by_name("widget").unwrap(); let id = WidgetExt::get_name(&old).unwrap(); @@ -150,34 +152,29 @@ impl UpdateView for WidgetsView { } } -impl ContentState { - pub fn new() -> ContentState { +impl ContentState { + pub fn new() -> Result, ContentState> { let content = Content::new(); content.podcasts.init(&content.stack); if content.podcasts.flowbox.get_children().is_empty() { content.stack.set_visible_child_name("empty"); - return ContentState::empty(Empty { content }) + return Err( + ContentState{ + content, + state: Empty{}, + }); } content.stack.set_visible_child_name("podcasts"); - ContentState::pop(PodcastsView{ content }) + Ok(ContentState { + content, + state: PodcastsView{}, + }) } pub fn get_stack(&self) -> gtk::Stack { - match *self { - ContentState::empty(ref e) => e.content.stack.clone(), - ContentState::pop(ref e) => e.content.stack.clone(), - ContentState::pd(ref e) => e.content.stack.clone(), - } - } - - pub fn update(&mut self) { - match *self { - ContentState::empty(ref mut e) => e.update(), - ContentState::pop(ref mut e) => e.update(), - ContentState::pd(ref mut e) => e.update(), - } + self.content.stack.clone() } } diff --git a/hammond-gtk/src/main.rs b/hammond-gtk/src/main.rs index a4aa344..afe1012 100644 --- a/hammond-gtk/src/main.rs +++ b/hammond-gtk/src/main.rs @@ -63,7 +63,8 @@ fn build_ui(app: >k::Application) { let window = gtk::ApplicationWindow::new(app); window.set_default_size(1150, 650); - let ct = content::ContentState::new(); + // TODO: this will blow horribly + let ct = content::ContentState::new().unwrap(); let stack = ct.get_stack(); window.add(&stack); From 48e61c63773491f7801b746c57a1c6727e4f12bf Mon Sep 17 00:00:00 2001 From: Jordan Petridis Date: Thu, 7 Dec 2017 18:31:45 +0200 Subject: [PATCH 39/41] Added small a utility that eats extra whitespace. --- hammond-data/src/utils.rs | 27 +++++++++++++++++++++++++++ hammond-gtk/src/widgets/episode.rs | 5 +++-- 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/hammond-data/src/utils.rs b/hammond-data/src/utils.rs index 75e78f5..e342151 100644 --- a/hammond-data/src/utils.rs +++ b/hammond-data/src/utils.rs @@ -105,6 +105,15 @@ pub fn url_cleaner(s: &str) -> String { } } +/// Placeholder +// TODO: Docs +pub fn replace_extra_spaces(s: &str) -> String { + s.lines() + .map(|x| x.split_whitespace().collect::>().join(" ")) + .filter(|x| !x.is_empty()) + .collect::>().join("\n") +} + #[cfg(test)] mod tests { extern crate tempdir; @@ -241,4 +250,22 @@ mod tests { assert_eq!(url_cleaner(good_url), good_url); assert_eq!(url_cleaner(&format!(" {}\t\n", bad_url)), good_url); } + + #[test] + fn test_whitespace() { + let bad_txt = "1 2 3 4 5"; + let valid_txt = "1 2 3 4 5"; + + assert_eq!(replace_extra_spaces(&bad_txt), valid_txt); + + let bad_txt = "1 2 3 \n 4 5\n"; + let valid_txt = "1 2 3\n4 5"; + + assert_eq!(replace_extra_spaces(&bad_txt), valid_txt); + + let bad_txt = "1 2 3 \n\n\n \n 4 5\n"; + let valid_txt = "1 2 3\n4 5"; + + assert_eq!(replace_extra_spaces(&bad_txt), valid_txt); + } } diff --git a/hammond-gtk/src/widgets/episode.rs b/hammond-gtk/src/widgets/episode.rs index 4d876df..4c61aac 100644 --- a/hammond-gtk/src/widgets/episode.rs +++ b/hammond-gtk/src/widgets/episode.rs @@ -12,6 +12,7 @@ use hammond_data::{Episode, Podcast}; use hammond_downloader::downloader; use hammond_data::utils::*; use hammond_data::errors::*; +use hammond_data::utils::replace_extra_spaces; // use utils::html_to_markup; @@ -90,10 +91,10 @@ impl EpisodeWidget { // html_to_markup(&mut text); // description.set_markup(&text) - let plain_text = strip_html_tags(&text).join(""); + let plain_text = strip_html_tags(&text).join(" "); // TODO: handle unwrap let buff = description.get_buffer().unwrap(); - buff.set_text(plain_text.trim()); + buff.set_text(&replace_extra_spaces(&plain_text)); })); } From 5b19274e6a689d90fc412095e7e5480c69786d1a Mon Sep 17 00:00:00 2001 From: Jordan Petridis Date: Fri, 8 Dec 2017 10:00:21 +0200 Subject: [PATCH 40/41] Ignore the stack state machine until TryInto trait is stabilized. --- hammond-gtk/src/content.rs | 30 +++++++++++++++++++++--------- hammond-gtk/src/main.rs | 7 +++++-- 2 files changed, 26 insertions(+), 11 deletions(-) diff --git a/hammond-gtk/src/content.rs b/hammond-gtk/src/content.rs index 7554cb3..e8c359f 100644 --- a/hammond-gtk/src/content.rs +++ b/hammond-gtk/src/content.rs @@ -17,7 +17,7 @@ pub struct Content { } impl Content { - fn new() -> Content { + pub fn new() -> Content { let stack = gtk::Stack::new(); let widget = PodcastWidget::new(); @@ -36,6 +36,22 @@ impl Content { } } + pub fn new_initialized() -> Content { + let ct = Content::new(); + ct.init(); + ct + } + + pub fn init(&self) { + self.podcasts.init(&self.stack); + if self.podcasts.flowbox.get_children().is_empty() { + self.stack.set_visible_child_name("empty"); + return + } + + self.stack.set_visible_child_name("podcasts"); + } + fn replace_widget(&mut self, pdw: PodcastWidget) { let vis = self.stack.get_visible_child_name().unwrap(); let old = self.stack.get_child_by_name("widget").unwrap(); @@ -60,6 +76,8 @@ impl Content { } #[derive(Debug)] +// Experiementing with Wrapping gtk::Stack into a State machine. +// Gonna revist it when TryInto trais is stabilized. pub struct ContentState { content: Content, state: S, @@ -153,6 +171,7 @@ impl UpdateView for ContentState { } impl ContentState { + #[allow(dead_code)] pub fn new() -> Result, ContentState> { let content = Content::new(); @@ -173,6 +192,7 @@ impl ContentState { }) } + #[allow(dead_code)] pub fn get_stack(&self) -> gtk::Stack { self.content.stack.clone() } @@ -192,14 +212,6 @@ fn replace_podcasts(stack: >k::Stack, pop: &PopulatedView) { old.destroy(); } -// This won't ever be needed probably -// pub fn replace_empty(stack: >k::Stack, emp: &EmptyView ) { -// let old = stack.get_child_by_name("empty").unwrap(); -// stack.remove(&old); -// stack.add_named(&emp.container, "empty"); -// old.destroy(); -// } - #[allow(dead_code)] pub fn show_widget(stack: >k::Stack) { stack.set_visible_child_name("widget") diff --git a/hammond-gtk/src/main.rs b/hammond-gtk/src/main.rs index afe1012..f4fd89b 100644 --- a/hammond-gtk/src/main.rs +++ b/hammond-gtk/src/main.rs @@ -64,8 +64,11 @@ fn build_ui(app: >k::Application) { window.set_default_size(1150, 650); // TODO: this will blow horribly - let ct = content::ContentState::new().unwrap(); - let stack = ct.get_stack(); + // let ct = content::ContentState::new().unwrap(); + // let stack = ct.get_stack(); + + let ct = content::Content::new_initialized(); + let stack = ct.stack; window.add(&stack); window.connect_delete_event(|w, _| { From b528c48e3b7258ae16b9970eea772e5fca61c507 Mon Sep 17 00:00:00 2001 From: Jordan Petridis Date: Sat, 9 Dec 2017 05:57:16 +0200 Subject: [PATCH 41/41] Run rustfmt. --- .gitlab-ci.yml | 2 ++ hammond-data/src/dbqueries.rs | 9 +++--- hammond-data/src/feed.rs | 9 +++--- hammond-data/src/lib.rs | 2 +- hammond-data/src/models/queryables.rs | 6 ++-- hammond-data/src/parser.rs | 42 +++++++++++++-------------- hammond-data/src/utils.rs | 9 +++--- hammond-downloader/src/downloader.rs | 19 ++++++------ hammond-gtk/src/content.rs | 35 +++++++++++----------- hammond-gtk/src/widgets/episode.rs | 2 +- 10 files changed, 68 insertions(+), 67 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 1bc2bbc..8726f9e 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -40,6 +40,8 @@ nightly:test: rustfmt: image: "rustlang/rust:nightly" stage: lint + variables: + CFG_RELEASE_CHANNEL: "nightly" script: - rustc --version && cargo --version - cargo install rustfmt-nightly diff --git a/hammond-data/src/dbqueries.rs b/hammond-data/src/dbqueries.rs index f4c0791..1604547 100644 --- a/hammond-data/src/dbqueries.rs +++ b/hammond-data/src/dbqueries.rs @@ -198,9 +198,10 @@ pub fn update_none_to_played_now(parent: &Podcast) -> Result { let epoch_now = Utc::now().timestamp() as i32; con.transaction(|| -> Result { - Ok(diesel::update( - Episode::belonging_to(parent).filter(played.is_null()), - ).set(played.eq(Some(epoch_now))) - .execute(&*con)?) + Ok( + diesel::update(Episode::belonging_to(parent).filter(played.is_null())) + .set(played.eq(Some(epoch_now))) + .execute(&*con)?, + ) }) } diff --git a/hammond-data/src/feed.rs b/hammond-data/src/feed.rs index a87f98f..af38f1a 100644 --- a/hammond-data/src/feed.rs +++ b/hammond-data/src/feed.rs @@ -276,13 +276,12 @@ mod tests { f2.get_episodes().unwrap() }; - eps1.into_par_iter() - .zip(eps2) - .into_par_iter() - .for_each(|(ep1, ep2): (Episode, Episode)| { + eps1.into_par_iter().zip(eps2).into_par_iter().for_each( + |(ep1, ep2): (Episode, Episode)| { assert_eq!(ep1, ep2); assert_eq!(ep1.id(), ep2.id()); assert_eq!(ep1.podcast_id(), ep2.podcast_id()); - }); + }, + ); } } diff --git a/hammond-data/src/lib.rs b/hammond-data/src/lib.rs index b4465f1..9828740 100644 --- a/hammond-data/src/lib.rs +++ b/hammond-data/src/lib.rs @@ -37,6 +37,7 @@ extern crate diesel_migrations; #[macro_use] extern crate derive_builder; +extern crate ammonia; extern crate chrono; extern crate r2d2; extern crate r2d2_diesel; @@ -46,7 +47,6 @@ extern crate rfc822_sanitizer; extern crate rss; extern crate url; extern crate xdg; -extern crate ammonia; #[allow(missing_docs)] pub mod dbqueries; diff --git a/hammond-data/src/models/queryables.rs b/hammond-data/src/models/queryables.rs index 2e991df..2e41ea6 100644 --- a/hammond-data/src/models/queryables.rs +++ b/hammond-data/src/models/queryables.rs @@ -342,9 +342,9 @@ impl<'a> Source { let lmod = headers.get::(); // FIXME: This dsnt work most of the time apparently - if self.http_etag() != etag.map(|x| x.tag()) - || self.last_modified != lmod.map(|x| format!("{}", x)) - { + if self.http_etag() != etag.map(|x| x.tag()) || self.last_modified != lmod.map(|x| { + format!("{}", x) + }) { self.http_etag = etag.map(|x| x.tag().to_string().to_owned()); self.last_modified = lmod.map(|x| format!("{}", x)); self.save()?; diff --git a/hammond-data/src/parser.rs b/hammond-data/src/parser.rs index 2cddc50..97043a5 100644 --- a/hammond-data/src/parser.rs +++ b/hammond-data/src/parser.rs @@ -62,19 +62,17 @@ pub(crate) fn new_episode(item: &Item, parent_id: i32) -> Result { let length = item.enclosure().map(|x| x.length().parse().unwrap_or(0)); - Ok( - NewEpisodeBuilder::default() - .title(title) - .uri(uri) - .description(description) - .length(length) - .published_date(pub_date) - .epoch(epoch) - .guid(guid) - .podcast_id(parent_id) - .build() - .unwrap() - ) + Ok(NewEpisodeBuilder::default() + .title(title) + .uri(uri) + .description(description) + .length(length) + .published_date(pub_date) + .epoch(epoch) + .guid(guid) + .podcast_id(parent_id) + .build() + .unwrap()) } @@ -278,9 +276,9 @@ mod tests { let firstitem = channel.items().first().unwrap(); let descr = "Audit your network with a couple of easy commands on Kali Linux. Chris \ - decides to blow off a little steam by attacking his IoT devices, Wes has \ - the scope on Equifax blaming open source & the Beard just saved the \ - show. It’s a really packed episode!"; + decides to blow off a little steam by attacking his IoT devices, Wes has the \ + scope on Equifax blaming open source & the Beard just saved the show. \ + It’s a really packed episode!"; let i = new_episode(&firstitem, 0).unwrap(); assert_eq!(i.title(), Some("Hacking Devices with Kali Linux | LUP 214")); @@ -321,9 +319,8 @@ mod tests { let channel = Channel::read_from(BufReader::new(file)).unwrap(); let firstitem = channel.items().iter().nth(9).unwrap(); - let descr = "This week we look at RFC 2094 \"Non-lexical lifetimes\""; + let descr = "This week we look at RFC 2094 \"Non-lexical lifetimes\""; let i = new_episode(&firstitem, 0).unwrap(); assert_eq!(i.title(), Some("Episode #9 - A Once in a Lifetime RFC")); @@ -344,9 +341,10 @@ mod tests { let second = channel.items().iter().nth(8).unwrap(); let i2 = new_episode(&second, 0).unwrap(); - let descr2 = "This week we look at RFC 2071 \"Add impl Trait type alias and \ - variable declarations\""; + let descr2 = "This week we look at RFC 2071 \"Add impl Trait type alias and variable \ + declarations\""; assert_eq!(i2.title(), Some("Episode #8 - An Existential Crisis")); assert_eq!( i2.uri(), diff --git a/hammond-data/src/utils.rs b/hammond-data/src/utils.rs index e342151..d297102 100644 --- a/hammond-data/src/utils.rs +++ b/hammond-data/src/utils.rs @@ -109,9 +109,10 @@ pub fn url_cleaner(s: &str) -> String { // TODO: Docs pub fn replace_extra_spaces(s: &str) -> String { s.lines() - .map(|x| x.split_whitespace().collect::>().join(" ")) - .filter(|x| !x.is_empty()) - .collect::>().join("\n") + .map(|x| x.split_whitespace().collect::>().join(" ")) + .filter(|x| !x.is_empty()) + .collect::>() + .join("\n") } #[cfg(test)] @@ -151,7 +152,7 @@ mod tests { .unwrap() .into_episode(&con) .unwrap(); - + let mut ep1 = dbqueries::get_episode_from_uri(&con, "foo_bar").unwrap(); let mut ep2 = dbqueries::get_episode_from_uri(&con, "bar_baz").unwrap(); ep1.set_local_uri(Some(valid_path.to_str().unwrap())); diff --git a/hammond-downloader/src/downloader.rs b/hammond-downloader/src/downloader.rs index 97b1752..f3b695a 100644 --- a/hammond-downloader/src/downloader.rs +++ b/hammond-downloader/src/downloader.rs @@ -60,15 +60,16 @@ fn download_into(dir: &str, file_title: &str, url: &str) -> Result { // Determine the file extension from the http content-type header. fn get_ext(content: Option) -> Option { let cont = content.clone()?; - content.and_then(|c| mime_guess::get_extensions(c.type_().as_ref(), c.subtype().as_ref())) - .and_then(|c| { - if c.contains(&cont.subtype().as_ref()) { - Some(cont.subtype().as_ref().to_string()) - } else { - Some(c.first().unwrap().to_string()) - } - }) -} + content + .and_then(|c| mime_guess::get_extensions(c.type_().as_ref(), c.subtype().as_ref())) + .and_then(|c| { + if c.contains(&cont.subtype().as_ref()) { + Some(cont.subtype().as_ref().to_string()) + } else { + Some(c.first().unwrap().to_string()) + } + }) +} // TODO: Write unit-tests. /// Handles the I/O of fetching a remote file and saving into a Buffer and A File. diff --git a/hammond-gtk/src/content.rs b/hammond-gtk/src/content.rs index e8c359f..249f589 100644 --- a/hammond-gtk/src/content.rs +++ b/hammond-gtk/src/content.rs @@ -46,7 +46,7 @@ impl Content { self.podcasts.init(&self.stack); if self.podcasts.flowbox.get_children().is_empty() { self.stack.set_visible_child_name("empty"); - return + return; } self.stack.set_visible_child_name("podcasts"); @@ -100,9 +100,9 @@ impl Into> for ContentState { fn into(self) -> ContentState { self.content.stack.set_visible_child_name("podcasts"); - ContentState{ + ContentState { content: self.content, - state: PodcastsView{}, + state: PodcastsView {}, } } } @@ -114,9 +114,9 @@ impl UpdateView for ContentState { impl Into> for ContentState { fn into(self) -> ContentState { self.content.stack.set_visible_child_name("empty"); - ContentState{ + ContentState { content: self.content, - state: Empty{}, + state: Empty {}, } } } @@ -125,9 +125,9 @@ impl Into> for ContentState { fn into(self) -> ContentState { self.content.stack.set_visible_child_name("widget"); - ContentState{ + ContentState { content: self.content, - state: WidgetsView{}, + state: WidgetsView {}, } } } @@ -142,9 +142,9 @@ impl UpdateView for ContentState { impl Into> for ContentState { fn into(self) -> ContentState { self.content.stack.set_visible_child_name("podcasts"); - ContentState{ + ContentState { content: self.content, - state: PodcastsView{}, + state: PodcastsView {}, } } } @@ -152,9 +152,9 @@ impl Into> for ContentState { impl Into> for ContentState { fn into(self) -> ContentState { self.content.stack.set_visible_child_name("empty"); - ContentState{ + ContentState { content: self.content, - state: Empty{}, + state: Empty {}, } } } @@ -165,7 +165,7 @@ impl UpdateView for ContentState { let id = WidgetExt::get_name(&old).unwrap(); let pd = dbqueries::get_podcast_from_id(id.parse::().unwrap()).unwrap(); - let pdw = PodcastWidget::new_initialized(&self.content.stack, &pd);; + let pdw = PodcastWidget::new_initialized(&self.content.stack, &pd); self.content.replace_widget(pdw); } } @@ -178,17 +178,16 @@ impl ContentState { content.podcasts.init(&content.stack); if content.podcasts.flowbox.get_children().is_empty() { content.stack.set_visible_child_name("empty"); - return Err( - ContentState{ - content, - state: Empty{}, - }); + return Err(ContentState { + content, + state: Empty {}, + }); } content.stack.set_visible_child_name("podcasts"); Ok(ContentState { content, - state: PodcastsView{}, + state: PodcastsView {}, }) } diff --git a/hammond-gtk/src/widgets/episode.rs b/hammond-gtk/src/widgets/episode.rs index 4c61aac..c113b51 100644 --- a/hammond-gtk/src/widgets/episode.rs +++ b/hammond-gtk/src/widgets/episode.rs @@ -90,7 +90,7 @@ impl EpisodeWidget { // let mut text = text.clone(); // html_to_markup(&mut text); // description.set_markup(&text) - + let plain_text = strip_html_tags(&text).join(" "); // TODO: handle unwrap let buff = description.get_buffer().unwrap();