Merge branch 'cleanups' into 'master'

Cleanups

See merge request World/podcasts!84
This commit is contained in:
Jordan Petridis 2018-11-18 13:27:59 +00:00
commit e98231c327
39 changed files with 801 additions and 745 deletions

897
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -6,7 +6,7 @@ version = "0.1.0"
[dependencies]
ammonia = "1.2.0"
chrono = "0.4.6"
derive_builder = "0.6.0"
derive_builder = "0.7.0"
lazy_static = "1.1.0"
log = "0.4.5"
rayon = "1.0.2"
@ -34,7 +34,7 @@ features = ["sqlite"]
version = "1.3.0"
[dev-dependencies]
rand = "0.5.5"
rand = "0.6.0"
tempdir = "0.3.7"
pretty_assertions = "0.5.1"
maplit = "1.0.1"

View File

@ -28,10 +28,10 @@ use diesel::r2d2::ConnectionManager;
use std::io;
use std::path::PathBuf;
use errors::DataError;
use crate::errors::DataError;
#[cfg(not(test))]
use xdg_dirs;
use crate::xdg_dirs;
type Pool = r2d2::Pool<ConnectionManager<SqliteConnection>>;

View File

@ -26,12 +26,12 @@ use diesel;
use diesel::dsl::exists;
use diesel::select;
use database::connection;
use errors::DataError;
use models::*;
use crate::database::connection;
use crate::errors::DataError;
use crate::models::*;
pub fn get_sources() -> Result<Vec<Source>, DataError> {
use schema::source::dsl::*;
use crate::schema::source::dsl::*;
let db = connection();
let con = db.get()?;
@ -42,7 +42,7 @@ pub fn get_sources() -> Result<Vec<Source>, DataError> {
}
pub fn get_podcasts() -> Result<Vec<Show>, DataError> {
use schema::shows::dsl::*;
use crate::schema::shows::dsl::*;
let db = connection();
let con = db.get()?;
@ -53,7 +53,7 @@ pub fn get_podcasts() -> Result<Vec<Show>, DataError> {
}
pub fn get_podcasts_filter(filter_ids: &[i32]) -> Result<Vec<Show>, DataError> {
use schema::shows::dsl::*;
use crate::schema::shows::dsl::*;
let db = connection();
let con = db.get()?;
@ -65,7 +65,7 @@ pub fn get_podcasts_filter(filter_ids: &[i32]) -> Result<Vec<Show>, DataError> {
}
pub fn get_episodes() -> Result<Vec<Episode>, DataError> {
use schema::episodes::dsl::*;
use crate::schema::episodes::dsl::*;
let db = connection();
let con = db.get()?;
@ -76,7 +76,7 @@ pub fn get_episodes() -> Result<Vec<Episode>, DataError> {
}
pub(crate) fn get_downloaded_episodes() -> Result<Vec<EpisodeCleanerModel>, DataError> {
use schema::episodes::dsl::*;
use crate::schema::episodes::dsl::*;
let db = connection();
let con = db.get()?;
@ -99,7 +99,7 @@ pub(crate) fn get_downloaded_episodes() -> Result<Vec<EpisodeCleanerModel>, Data
// }
pub(crate) fn get_played_cleaner_episodes() -> Result<Vec<EpisodeCleanerModel>, DataError> {
use schema::episodes::dsl::*;
use crate::schema::episodes::dsl::*;
let db = connection();
let con = db.get()?;
@ -111,7 +111,7 @@ pub(crate) fn get_played_cleaner_episodes() -> Result<Vec<EpisodeCleanerModel>,
}
pub fn get_episode_from_rowid(ep_id: i32) -> Result<Episode, DataError> {
use schema::episodes::dsl::*;
use crate::schema::episodes::dsl::*;
let db = connection();
let con = db.get()?;
@ -122,7 +122,7 @@ pub fn get_episode_from_rowid(ep_id: i32) -> Result<Episode, DataError> {
}
pub fn get_episode_widget_from_rowid(ep_id: i32) -> Result<EpisodeWidgetModel, DataError> {
use schema::episodes::dsl::*;
use crate::schema::episodes::dsl::*;
let db = connection();
let con = db.get()?;
@ -136,7 +136,7 @@ pub fn get_episode_widget_from_rowid(ep_id: i32) -> Result<EpisodeWidgetModel, D
}
pub fn get_episode_local_uri_from_id(ep_id: i32) -> Result<Option<String>, DataError> {
use schema::episodes::dsl::*;
use crate::schema::episodes::dsl::*;
let db = connection();
let con = db.get()?;
@ -151,7 +151,7 @@ pub fn get_episodes_widgets_filter_limit(
filter_ids: &[i32],
limit: u32,
) -> Result<Vec<EpisodeWidgetModel>, DataError> {
use schema::episodes::dsl::*;
use crate::schema::episodes::dsl::*;
let db = connection();
let con = db.get()?;
let columns = (
@ -168,7 +168,7 @@ pub fn get_episodes_widgets_filter_limit(
}
pub fn get_podcast_from_id(pid: i32) -> Result<Show, DataError> {
use schema::shows::dsl::*;
use crate::schema::shows::dsl::*;
let db = connection();
let con = db.get()?;
@ -179,7 +179,7 @@ pub fn get_podcast_from_id(pid: i32) -> Result<Show, DataError> {
}
pub fn get_podcast_cover_from_id(pid: i32) -> Result<ShowCoverModel, DataError> {
use schema::shows::dsl::*;
use crate::schema::shows::dsl::*;
let db = connection();
let con = db.get()?;
@ -191,7 +191,7 @@ pub fn get_podcast_cover_from_id(pid: i32) -> Result<ShowCoverModel, DataError>
}
pub fn get_pd_episodes(parent: &Show) -> Result<Vec<Episode>, DataError> {
use schema::episodes::dsl::*;
use crate::schema::episodes::dsl::*;
let db = connection();
let con = db.get()?;
@ -212,7 +212,7 @@ pub fn get_pd_episodes_count(parent: &Show) -> Result<i64, DataError> {
}
pub fn get_pd_episodeswidgets(parent: &Show) -> Result<Vec<EpisodeWidgetModel>, DataError> {
use schema::episodes::dsl::*;
use crate::schema::episodes::dsl::*;
let db = connection();
let con = db.get()?;
let columns = (
@ -228,7 +228,7 @@ pub fn get_pd_episodeswidgets(parent: &Show) -> Result<Vec<EpisodeWidgetModel>,
}
pub fn get_pd_unplayed_episodes(parent: &Show) -> Result<Vec<Episode>, DataError> {
use schema::episodes::dsl::*;
use crate::schema::episodes::dsl::*;
let db = connection();
let con = db.get()?;
@ -253,7 +253,7 @@ pub fn get_pd_unplayed_episodes(parent: &Show) -> Result<Vec<Episode>, DataError
// }
pub fn get_source_from_uri(uri_: &str) -> Result<Source, DataError> {
use schema::source::dsl::*;
use crate::schema::source::dsl::*;
let db = connection();
let con = db.get()?;
@ -264,7 +264,7 @@ pub fn get_source_from_uri(uri_: &str) -> Result<Source, DataError> {
}
pub fn get_source_from_id(id_: i32) -> Result<Source, DataError> {
use schema::source::dsl::*;
use crate::schema::source::dsl::*;
let db = connection();
let con = db.get()?;
@ -275,7 +275,7 @@ pub fn get_source_from_id(id_: i32) -> Result<Source, DataError> {
}
pub fn get_podcast_from_source_id(sid: i32) -> Result<Show, DataError> {
use schema::shows::dsl::*;
use crate::schema::shows::dsl::*;
let db = connection();
let con = db.get()?;
@ -286,7 +286,7 @@ pub fn get_podcast_from_source_id(sid: i32) -> Result<Show, DataError> {
}
pub fn get_episode_from_pk(title_: &str, pid: i32) -> Result<Episode, DataError> {
use schema::episodes::dsl::*;
use crate::schema::episodes::dsl::*;
let db = connection();
let con = db.get()?;
@ -301,7 +301,7 @@ pub(crate) fn get_episode_minimal_from_pk(
title_: &str,
pid: i32,
) -> Result<EpisodeMinimal, DataError> {
use schema::episodes::dsl::*;
use crate::schema::episodes::dsl::*;
let db = connection();
let con = db.get()?;
@ -318,7 +318,7 @@ pub(crate) fn get_episode_cleaner_from_pk(
title_: &str,
pid: i32,
) -> Result<EpisodeCleanerModel, DataError> {
use schema::episodes::dsl::*;
use crate::schema::episodes::dsl::*;
let db = connection();
let con = db.get()?;
@ -344,25 +344,25 @@ pub(crate) fn remove_feed(pd: &Show) -> Result<(), DataError> {
}
fn delete_source(con: &SqliteConnection, source_id: i32) -> QueryResult<usize> {
use schema::source::dsl::*;
use crate::schema::source::dsl::*;
diesel::delete(source.filter(id.eq(source_id))).execute(con)
}
fn delete_podcast(con: &SqliteConnection, show_id: i32) -> QueryResult<usize> {
use schema::shows::dsl::*;
use crate::schema::shows::dsl::*;
diesel::delete(shows.filter(id.eq(show_id))).execute(con)
}
fn delete_podcast_episodes(con: &SqliteConnection, parent_id: i32) -> QueryResult<usize> {
use schema::episodes::dsl::*;
use crate::schema::episodes::dsl::*;
diesel::delete(episodes.filter(show_id.eq(parent_id))).execute(con)
}
pub fn source_exists(url: &str) -> Result<bool, DataError> {
use schema::source::dsl::*;
use crate::schema::source::dsl::*;
let db = connection();
let con = db.get()?;
@ -373,7 +373,7 @@ pub fn source_exists(url: &str) -> Result<bool, DataError> {
}
pub(crate) fn podcast_exists(source_id_: i32) -> Result<bool, DataError> {
use schema::shows::dsl::*;
use crate::schema::shows::dsl::*;
let db = connection();
let con = db.get()?;
@ -385,7 +385,7 @@ pub(crate) fn podcast_exists(source_id_: i32) -> Result<bool, DataError> {
#[cfg_attr(rustfmt, rustfmt_skip)]
pub(crate) fn episode_exists(title_: &str, show_id_: i32) -> Result<bool, DataError> {
use schema::episodes::dsl::*;
use crate::schema::episodes::dsl::*;
let db = connection();
let con = db.get()?;
@ -399,7 +399,7 @@ pub(crate) fn episode_exists(title_: &str, show_id_: i32) -> Result<bool, DataEr
///
/// Return true if `episodes` table is populated.
pub fn is_episodes_populated(filter_show_ids: &[i32]) -> Result<bool, DataError> {
use schema::episodes::dsl::*;
use crate::schema::episodes::dsl::*;
let db = connection();
let con = db.get()?;
@ -413,7 +413,7 @@ pub fn is_episodes_populated(filter_show_ids: &[i32]) -> Result<bool, DataError>
///
/// Return true if `shows` table is populated.
pub fn is_podcasts_populated(filter_ids: &[i32]) -> Result<bool, DataError> {
use schema::shows::dsl::*;
use crate::schema::shows::dsl::*;
let db = connection();
let con = db.get()?;
@ -427,7 +427,7 @@ pub fn is_podcasts_populated(filter_ids: &[i32]) -> Result<bool, DataError> {
///
/// Return true if `source` table is populated.
pub fn is_source_populated(filter_ids: &[i32]) -> Result<bool, DataError> {
use schema::source::dsl::*;
use crate::schema::source::dsl::*;
let db = connection();
let con = db.get()?;
@ -438,7 +438,7 @@ pub fn is_source_populated(filter_ids: &[i32]) -> Result<bool, DataError> {
}
pub(crate) fn index_new_episodes(eps: &[NewEpisode]) -> Result<(), DataError> {
use schema::episodes::dsl::*;
use crate::schema::episodes::dsl::*;
let db = connection();
let con = db.get()?;
@ -450,7 +450,7 @@ pub(crate) fn index_new_episodes(eps: &[NewEpisode]) -> Result<(), DataError> {
}
pub fn update_none_to_played_now(parent: &Show) -> Result<usize, DataError> {
use schema::episodes::dsl::*;
use crate::schema::episodes::dsl::*;
let db = connection();
let con = db.get()?;
@ -466,9 +466,9 @@ pub fn update_none_to_played_now(parent: &Show) -> Result<usize, DataError> {
#[cfg(test)]
mod tests {
use super::*;
use database::*;
use crate::database::*;
use crate::pipeline;
use failure::Error;
use pipeline;
#[test]
fn test_update_none_to_played_now() -> Result<(), Error> {

View File

@ -29,7 +29,7 @@ use xml;
use std::io;
use models::Source;
use crate::models::Source;
#[fail(
display = "Request to {} returned {}. Context: {}",

View File

@ -26,10 +26,10 @@ use futures::prelude::*;
use futures::stream;
use rss;
use dbqueries;
use errors::DataError;
use models::{Index, IndexState, Update};
use models::{NewEpisode, NewEpisodeMinimal, NewShow, Show};
use crate::dbqueries;
use crate::errors::DataError;
use crate::models::{Index, IndexState, Update};
use crate::models::{NewEpisode, NewEpisodeMinimal, NewShow, Show};
/// Wrapper struct that hold a `Source` id and the `rss::Channel`
/// that corresponds to the `Source.uri` field.
@ -145,10 +145,10 @@ mod tests {
use rss::Channel;
use tokio::{self, prelude::*};
use database::truncate_db;
use dbqueries;
use utils::get_feed;
use Source;
use crate::database::truncate_db;
use crate::dbqueries;
use crate::utils::get_feed;
use crate::Source;
use std::fs;
use std::io::BufReader;

View File

@ -19,6 +19,7 @@
#![recursion_limit = "1024"]
#![allow(unknown_lints)]
#![feature(rust_2018_preview)]
#![cfg_attr(
all(test, feature = "clippy"),
allow(option_unwrap_used, result_unwrap_used)
@ -43,7 +44,7 @@
)]
// Enable lint group collections
#![warn(nonstandard_style, bad_style, unused)]
#![allow(edition_2018, rust_2018_idioms)]
#![warn(edition_2018, rust_2018_idioms)]
// standalone lints
#![warn(
const_err,
@ -121,9 +122,9 @@ pub mod pipeline;
mod schema;
pub mod utils;
pub use feed::{Feed, FeedBuilder};
pub use models::Save;
pub use models::{Episode, EpisodeWidgetModel, Show, ShowCoverModel, Source};
pub use crate::feed::{Feed, FeedBuilder};
pub use crate::models::Save;
pub use crate::models::{Episode, EpisodeWidgetModel, Show, ShowCoverModel, Source};
// Set the user agent, See #53 for more
// Keep this in sync with Tor-browser releases

View File

@ -22,10 +22,10 @@ use diesel;
use diesel::prelude::*;
use diesel::SaveChangesDsl;
use database::connection;
use errors::DataError;
use models::{Save, Show};
use schema::episodes;
use crate::database::connection;
use crate::errors::DataError;
use crate::models::{Save, Show};
use crate::schema::episodes;
#[derive(Queryable, Identifiable, AsChangeset, Associations, PartialEq)]
#[table_name = "episodes"]
@ -172,7 +172,7 @@ impl Save<usize> for EpisodeWidgetModel {
/// Helper method to easily save/"sync" current state of self to the
/// Database.
fn save(&self) -> Result<usize, Self::Error> {
use schema::episodes::dsl::*;
use crate::schema::episodes::dsl::*;
let db = connection();
let tempdb = db.get()?;
@ -285,7 +285,7 @@ impl Save<usize> for EpisodeCleanerModel {
/// Helper method to easily save/"sync" current state of self to the
/// Database.
fn save(&self) -> Result<usize, Self::Error> {
use schema::episodes::dsl::*;
use crate::schema::episodes::dsl::*;
let db = connection();
let tempdb = db.get()?;

View File

@ -58,7 +58,7 @@ pub trait Insert<T> {
pub trait Update<T> {
type Error;
fn update(&self, i32) -> Result<T, Self::Error>;
fn update(&self, _: i32) -> Result<T, Self::Error>;
}
// This might need to change in the future

View File

@ -23,13 +23,13 @@ use diesel::prelude::*;
use rfc822_sanitizer::parse_from_rfc2822_with_fallback as parse_rfc822;
use rss;
use database::connection;
use dbqueries;
use errors::DataError;
use models::{Episode, EpisodeMinimal, Index, Insert, Update};
use parser;
use schema::episodes;
use utils::url_cleaner;
use crate::database::connection;
use crate::dbqueries;
use crate::errors::DataError;
use crate::models::{Episode, EpisodeMinimal, Index, Insert, Update};
use crate::parser;
use crate::schema::episodes;
use crate::utils::url_cleaner;
#[derive(Insertable, AsChangeset)]
#[table_name = "episodes"]
@ -66,7 +66,7 @@ impl Insert<()> for NewEpisode {
type Error = DataError;
fn insert(&self) -> Result<(), DataError> {
use schema::episodes::dsl::*;
use crate::schema::episodes::dsl::*;
let db = connection();
let con = db.get()?;
@ -83,7 +83,7 @@ impl Update<()> for NewEpisode {
type Error = DataError;
fn update(&self, episode_id: i32) -> Result<(), DataError> {
use schema::episodes::dsl::*;
use crate::schema::episodes::dsl::*;
let db = connection();
let con = db.get()?;
@ -330,11 +330,11 @@ impl NewEpisodeMinimal {
#[cfg(test)]
mod tests {
use database::truncate_db;
use dbqueries;
use crate::database::truncate_db;
use crate::dbqueries;
use crate::models::new_episode::{NewEpisodeMinimal, NewEpisodeMinimalBuilder};
use crate::models::*;
use failure::Error;
use models::new_episode::{NewEpisodeMinimal, NewEpisodeMinimalBuilder};
use models::*;
use rss::Channel;

View File

@ -22,14 +22,14 @@ use diesel;
use diesel::prelude::*;
use rss;
use errors::DataError;
use models::Show;
use models::{Index, Insert, Update};
use schema::shows;
use crate::errors::DataError;
use crate::models::Show;
use crate::models::{Index, Insert, Update};
use crate::schema::shows;
use database::connection;
use dbqueries;
use utils::url_cleaner;
use crate::database::connection;
use crate::dbqueries;
use crate::utils::url_cleaner;
#[derive(Insertable, AsChangeset)]
#[table_name = "shows"]
@ -49,7 +49,7 @@ impl Insert<()> for NewShow {
type Error = DataError;
fn insert(&self) -> Result<(), Self::Error> {
use schema::shows::dsl::*;
use crate::schema::shows::dsl::*;
let db = connection();
let con = db.get()?;
@ -65,7 +65,7 @@ impl Update<()> for NewShow {
type Error = DataError;
fn update(&self, show_id: i32) -> Result<(), Self::Error> {
use schema::shows::dsl::*;
use crate::schema::shows::dsl::*;
let db = connection();
let con = db.get()?;
@ -179,8 +179,8 @@ mod tests {
use failure::Error;
use rss::Channel;
use database::truncate_db;
use models::NewShowBuilder;
use crate::database::truncate_db;
use crate::models::NewShowBuilder;
use std::fs::File;
use std::io::BufReader;

View File

@ -21,12 +21,12 @@ use diesel;
use diesel::prelude::*;
use url::Url;
use database::connection;
use dbqueries;
use crate::database::connection;
use crate::dbqueries;
// use models::{Insert, Update};
use errors::DataError;
use models::Source;
use schema::source;
use crate::errors::DataError;
use crate::models::Source;
use crate::schema::source;
#[derive(Insertable)]
#[table_name = "source"]
@ -50,7 +50,7 @@ impl NewSource {
}
pub(crate) fn insert_or_ignore(&self) -> Result<(), DataError> {
use schema::source::dsl::*;
use crate::schema::source::dsl::*;
let db = connection();
let con = db.get()?;

View File

@ -17,8 +17,8 @@
//
// SPDX-License-Identifier: GPL-3.0-or-later
use models::Source;
use schema::shows;
use crate::models::Source;
use crate::schema::shows;
#[derive(Queryable, Identifiable, AsChangeset, Associations, PartialEq)]
#[belongs_to(Source, foreign_key = "source_id")]

View File

@ -35,12 +35,12 @@ use http::{Request, Response, StatusCode, Uri};
use futures::future::{loop_fn, Future, Loop};
use futures::prelude::*;
use database::connection;
use errors::*;
use feed::{Feed, FeedBuilder};
use models::{NewSource, Save};
use schema::source;
use USER_AGENT;
use crate::database::connection;
use crate::errors::*;
use crate::feed::{Feed, FeedBuilder};
use crate::models::{NewSource, Save};
use crate::schema::source;
use crate::USER_AGENT;
use std::str::FromStr;
@ -316,8 +316,8 @@ mod tests {
use num_cpus;
use tokio;
use database::truncate_db;
use utils::get_feed;
use crate::database::truncate_db;
use crate::utils::get_feed;
#[test]
fn test_into_feed() -> Result<(), Error> {

View File

@ -21,8 +21,8 @@
// #![allow(unused)]
use errors::DataError;
use models::Source;
use crate::errors::DataError;
use crate::models::Source;
use xml::reader;
use std::collections::HashSet;

View File

@ -29,8 +29,8 @@ use hyper_tls::HttpsConnector;
use num_cpus;
use errors::DataError;
use Source;
use crate::errors::DataError;
use crate::Source;
use std::iter::FromIterator;
@ -87,10 +87,10 @@ where
#[cfg(test)]
mod tests {
use super::*;
use database::truncate_db;
use dbqueries;
use crate::database::truncate_db;
use crate::dbqueries;
use crate::Source;
use failure::Error;
use Source;
// (path, url) tuples.
const URLS: &[&str] = &[

View File

@ -24,10 +24,10 @@ use rayon::prelude::*;
use url::{Position, Url};
use dbqueries;
use errors::DataError;
use models::{EpisodeCleanerModel, Save, Show};
use xdg_dirs::DL_DIR;
use crate::dbqueries;
use crate::errors::DataError;
use crate::models::{EpisodeCleanerModel, Save, Show};
use crate::xdg_dirs::DL_DIR;
use std::fs;
use std::path::Path;
@ -153,13 +153,13 @@ pub fn delete_show(pd: &Show) -> Result<(), DataError> {
}
#[cfg(test)]
use Feed;
use crate::Feed;
#[cfg(test)]
/// Helper function that open a local file, parse the rss::Channel and gives back a Feed object.
/// Alternative Feed constructor to be used for tests.
pub fn get_feed(file_path: &str, id: i32) -> Feed {
use feed::FeedBuilder;
use crate::feed::FeedBuilder;
use rss::Channel;
use std::fs;
use std::io::BufReader;
@ -184,8 +184,8 @@ mod tests {
use chrono::Duration;
use failure::Error;
use database::truncate_db;
use models::NewEpisodeBuilder;
use crate::database::truncate_db;
use crate::models::NewEpisodeBuilder;
use std::fs::File;
use std::io::Write;

View File

@ -34,7 +34,7 @@ use podcasts_data::xdg_dirs::PODCASTS_CACHE;
use podcasts_data::{EpisodeWidgetModel, Save, ShowCoverModel};
// use failure::Error;
use errors::DownloadError;
use crate::errors::DownloadError;
// TODO: Replace path that are of type &str with std::path.
// TODO: Have a convention/document absolute/relative paths, if they should end

View File

@ -19,6 +19,7 @@
#![recursion_limit = "1024"]
#![allow(unknown_lints)]
#![feature(rust_2018_preview)]
#![cfg_attr(feature = "cargo-clippy", allow(blacklisted_name, option_map_unit_fn))]
// Enable lint group collections
#![warn(nonstandard_style, edition_2018, rust_2018_idioms, bad_style, unused)]

View File

@ -48,4 +48,4 @@ path = "../podcasts-data"
path = "../podcasts-downloader"
[dev-dependencies]
pretty_assertions = "0.5.1"
pretty_assertions = "0.5.1"

View File

@ -31,22 +31,22 @@ use crossbeam_channel::{unbounded, Receiver, Sender};
use fragile::Fragile;
use podcasts_data::Show;
use headerbar::Header;
use prefs::Prefs;
use settings::{self, WindowGeometry};
use stacks::{Content, PopulatedState};
use utils;
use widgets::about_dialog;
use widgets::appnotif::{InAppNotification, SpinnerState, State};
use widgets::player;
use widgets::show_menu::{mark_all_notif, remove_show_notif, ShowMenu};
use crate::headerbar::Header;
use crate::prefs::Prefs;
use crate::settings::{self, WindowGeometry};
use crate::stacks::{Content, PopulatedState};
use crate::utils;
use crate::widgets::about_dialog;
use crate::widgets::appnotif::{InAppNotification, SpinnerState, State};
use crate::widgets::player;
use crate::widgets::show_menu::{mark_all_notif, remove_show_notif, ShowMenu};
use std::cell::RefCell;
use std::env;
use std::rc::Rc;
use std::sync::Arc;
use i18n::i18n;
use crate::i18n::i18n;
pub(crate) const APP_ID: &str = env!("APP_ID");
pub(crate) const VERSION: &str = env!("VERSION");
@ -96,7 +96,7 @@ pub(crate) struct App {
settings: gio::Settings,
content: Rc<Content>,
headerbar: Rc<Header>,
player: Rc<player::PlayerWidget>,
player: player::PlayerWrapper,
updater: RefCell<Option<InAppNotification>>,
sender: Sender<Action>,
receiver: Receiver<Action>,
@ -151,7 +151,7 @@ impl App {
// Add the overlay to the main Box
wrap.add(&overlay);
let player = player::PlayerWidget::new(&sender);
let player = player::PlayerWrapper::new(&sender);
// Add the player to the main Box
wrap.add(&player.action_bar);

View File

@ -28,13 +28,13 @@ use url::Url;
use podcasts_data::{dbqueries, Source};
use app::Action;
use stacks::Content;
use utils::{itunes_to_rss, refresh};
use crate::app::Action;
use crate::stacks::Content;
use crate::utils::{itunes_to_rss, refresh};
use std::rc::Rc;
use i18n::i18n;
use crate::i18n::i18n;
#[derive(Debug, Clone)]
// TODO: Make a proper state machine for the headerbar states

View File

@ -27,6 +27,7 @@
)
)]
#![allow(unknown_lints)]
#![feature(rust_2018_preview)]
// Enable lint group collections
#![warn(nonstandard_style, edition_2018, rust_2018_idioms, bad_style, unused)]
// standalone lints
@ -126,7 +127,7 @@ mod utils;
mod i18n;
use app::App;
use crate::app::App;
#[cfg(test)]
fn init_gtk_tests() -> Result<(), failure::Error> {
@ -167,8 +168,8 @@ fn main() {
// cargo seems to create new threads and gtk refuses to initialize again.
// So we run every gtk related test here.
fn test_stuff() -> Result<(), failure::Error> {
use headerbar::Header;
use widgets::*;
use crate::headerbar::Header;
use crate::widgets::*;
init_gtk_tests()?;

View File

@ -22,7 +22,7 @@ use gio::{Settings, SettingsExt};
use gtk;
use gtk::prelude::*;
use i18n::i18n;
use crate::i18n::i18n;
#[derive(Debug, Clone)]
pub(crate) struct Prefs {

View File

@ -23,13 +23,13 @@ use gtk::prelude::*;
use crossbeam_channel::Sender;
use failure::Error;
use app::Action;
use stacks::{HomeStack, ShowStack};
use crate::app::Action;
use crate::stacks::{HomeStack, ShowStack};
use std::cell::RefCell;
use std::rc::Rc;
use i18n::i18n;
use crate::i18n::i18n;
#[derive(Debug, Clone, Copy)]
pub(crate) enum State {

View File

@ -24,9 +24,9 @@ use gtk::StackTransitionType;
use crossbeam_channel::Sender;
use failure::Error;
use app::Action;
use stacks::State;
use widgets::{EmptyView, HomeView};
use crate::app::Action;
use crate::stacks::State;
use crate::widgets::{EmptyView, HomeView};
use std::ops::Deref;
use std::rc::Rc;

View File

@ -27,8 +27,8 @@ use failure::Error;
use podcasts_data::dbqueries;
use podcasts_data::Show;
use app::Action;
use widgets::{ShowWidget, ShowsView};
use crate::app::Action;
use crate::widgets::{ShowWidget, ShowsView};
use std::rc::Rc;
use std::sync::Arc;

View File

@ -24,11 +24,11 @@ use crossbeam_channel::Sender;
use failure::Error;
use podcasts_data::dbqueries::is_episodes_populated;
use app::Action;
use stacks::content::State;
use stacks::PopulatedStack;
use utils::get_ignored_shows;
use widgets::EmptyView;
use crate::app::Action;
use crate::stacks::content::State;
use crate::stacks::PopulatedStack;
use crate::utils::get_ignored_shows;
use crate::widgets::EmptyView;
use std::cell::RefCell;
use std::ops::Deref;

View File

@ -47,9 +47,9 @@ use podcasts_downloader::downloader;
use std::collections::{HashMap, HashSet};
use std::sync::{Arc, Mutex, RwLock};
use app::Action;
use crate::app::Action;
use i18n::i18n;
use crate::i18n::i18n;
/// Lazy evaluates and loads widgets to the parent `container` widget.
///

View File

@ -17,11 +17,11 @@
//
// SPDX-License-Identifier: GPL-3.0-or-later
use app::{APP_ID, VERSION};
use crate::app::{APP_ID, VERSION};
use gtk;
use gtk::prelude::*;
use i18n::i18n;
use crate::i18n::i18n;
// Totally copied it from fractal.
// https://gitlab.gnome.org/danigm/fractal/blob/503e311e22b9d7540089d735b92af8e8f93560c5/fractal-gtk/src/app.rs#L1883-1912

View File

@ -17,8 +17,8 @@
//
// SPDX-License-Identifier: GPL-3.0-or-later
use crate::utils::smooth_scroll_to;
use gtk::{self, prelude::*, Adjustment, Orientation, PolicyType};
use utils::smooth_scroll_to;
#[derive(Debug, Clone)]
pub(crate) struct BaseView {

View File

@ -17,7 +17,7 @@
//
// SPDX-License-Identifier: GPL-3.0-or-later
use app::APP_ID;
use crate::app::APP_ID;
use gtk::{self, prelude::*};
use std::ops::Deref;

View File

@ -34,14 +34,14 @@ use podcasts_data::utils::get_download_folder;
use podcasts_data::EpisodeWidgetModel;
use podcasts_downloader::downloader::DownloadProgress;
use app::Action;
use manager;
use crate::app::Action;
use crate::manager;
use std::cell::RefCell;
use std::rc::{Rc, Weak};
use std::sync::{Arc, Mutex, TryLockError};
use i18n::i18n_f;
use crate::i18n::i18n_f;
lazy_static! {
static ref SIZE_OPTS: Arc<size_opts::FileSizeOpts> = {

View File

@ -27,9 +27,9 @@ use libhandy::{Column, ColumnExt};
use podcasts_data::dbqueries;
use podcasts_data::EpisodeWidgetModel;
use app::Action;
use utils::{self, lazy_load_full};
use widgets::{BaseView, EpisodeWidget};
use crate::app::Action;
use crate::utils::{self, lazy_load_full};
use crate::widgets::{BaseView, EpisodeWidget};
use std::cell::Cell;
use std::rc::Rc;

View File

@ -17,9 +17,9 @@
//
// SPDX-License-Identifier: GPL-3.0-or-later
use gst::prelude::*;
use gst::ClockTime;
use gst_player;
use crate::gst::prelude::*;
use crate::gst::ClockTime;
use crate::gst_player;
use gtk;
use gtk::prelude::*;
@ -35,8 +35,8 @@ use fragile::Fragile;
use podcasts_data::{dbqueries, USER_AGENT};
use podcasts_data::{EpisodeWidgetModel, ShowCoverModel};
use app::Action;
use utils::set_image_from_path;
use crate::app::Action;
use crate::utils::set_image_from_path;
use std::cell::RefCell;
use std::ops::Deref;
@ -44,7 +44,7 @@ use std::path::Path;
use std::rc::Rc;
use std::sync::Mutex;
use i18n::i18n;
use crate::i18n::i18n;
use mpris_player::{Metadata, MprisPlayer, OrgMprisMediaPlayer2Player, PlaybackStatus};
use std::sync::Arc;
@ -62,7 +62,7 @@ trait PlayerExt {
fn seek(&self, offset: ClockTime, direction: SeekDirection);
fn fast_forward(&self);
fn rewind(&self);
fn set_playback_rate(&self, f64);
fn set_playback_rate(&self, _: f64);
}
#[derive(Debug, Clone)]
@ -304,136 +304,6 @@ impl Default for PlayerWidget {
}
impl PlayerWidget {
pub(crate) fn new(sender: &Sender<Action>) -> Rc<Self> {
let w = Rc::new(Self::default());
Self::init(&w, sender);
w
}
fn init(s: &Rc<Self>, sender: &Sender<Action>) {
Self::connect_control_buttons(s);
Self::connect_rate_buttons(s);
Self::connect_mpris_buttons(s, sender);
Self::connect_gst_signals(s, sender);
}
/// Connect the `PlayerControls` buttons to the `PlayerExt` methods.
fn connect_control_buttons(s: &Rc<Self>) {
let weak = Rc::downgrade(s);
// Connect the play button to the gst Player.
s.controls.play.connect_clicked(clone!(weak => move |_| {
weak.upgrade().map(|p| p.play());
}));
// Connect the pause button to the gst Player.
s.controls.pause.connect_clicked(clone!(weak => move |_| {
weak.upgrade().map(|p| p.pause());
}));
// Connect the rewind button to the gst Player.
s.controls.rewind.connect_clicked(clone!(weak => move |_| {
weak.upgrade().map(|p| p.rewind());
}));
// Connect the fast-forward button to the gst Player.
s.controls.forward.connect_clicked(clone!(weak => move |_| {
weak.upgrade().map(|p| p.fast_forward());
}));
}
fn connect_mpris_buttons(s: &Rc<Self>, sender: &Sender<Action>) {
let weak = Rc::downgrade(s);
let mpris = s.info.mpris.clone();
s.info.mpris.connect_play_pause(clone!(weak => move || {
let player = match weak.upgrade() {
Some(s) => s,
None => return
};
if let Ok(status) = mpris.get_playback_status() {
match status.as_ref() {
"Paused" => player.play(),
"Stopped" => player.play(),
_ => player.pause(),
};
}
}));
s.info.mpris.connect_next(clone!(weak => move || {
weak.upgrade().map(|p| p.fast_forward());
}));
s.info.mpris.connect_previous(clone!(weak => move || {
weak.upgrade().map(|p| p.rewind());
}));
s.info
.mpris
.connect_raise(clone!(sender => move || sender.send(Action::RaiseWindow)));
}
#[cfg_attr(rustfmt, rustfmt_skip)]
fn connect_gst_signals(s: &Rc<Self>, sender: &Sender<Action>) {
// Log gst warnings.
s.player.connect_warning(move |_, warn| warn!("gst warning: {}", warn));
// Log gst errors.
s.player.connect_error(clone!(sender => move |_, _error| {
// sender.send(Action::ErrorNotification(format!("Player Error: {}", error)));
let s = i18n("The media player was unable to execute an action.");
sender.send(Action::ErrorNotification(s));
}));
// The following callbacks require `Send` but are handled by the gtk main loop
let weak = Fragile::new(Rc::downgrade(s));
// Update the duration label and the slider
s.player.connect_duration_changed(clone!(weak => move |_, clock| {
weak.get()
.upgrade()
.map(|p| p.timer.on_duration_changed(Duration(clock)));
}));
// Update the position label and the slider
s.player.connect_position_updated(clone!(weak => move |_, clock| {
weak.get()
.upgrade()
.map(|p| p.timer.on_position_updated(Position(clock)));
}));
// Reset the slider to 0 and show a play button
s.player.connect_end_of_stream(clone!(weak => move |_| {
weak.get()
.upgrade()
.map(|p| p.stop());
}));
}
#[cfg_attr(rustfmt, rustfmt_skip)]
fn connect_rate_buttons(s: &Rc<Self>) {
let weak = Rc::downgrade(s);
s.rate
.radio_normal
.connect_toggled(clone!(weak => move |_| {
weak.upgrade().map(|p| p.on_rate_changed(1.00));
}));
s.rate
.radio125
.connect_toggled(clone!(weak => move |_| {
weak.upgrade().map(|p| p.on_rate_changed(1.25));
}));
s.rate
.radio150
.connect_toggled(clone!(weak => move |_| {
weak.upgrade().map(|p| p.on_rate_changed(1.50));
}));
}
fn on_rate_changed(&self, rate: f64) {
self.set_playback_rate(rate);
self.rate.label.set_text(&format!("{:.2}×", rate));
@ -593,3 +463,158 @@ impl PlayerExt for PlayerWidget {
self.player.set_rate(rate);
}
}
#[derive(Debug, Clone)]
pub(crate) struct PlayerWrapper(pub Rc<PlayerWidget>);
impl Default for PlayerWrapper {
fn default() -> Self {
PlayerWrapper(Rc::new(PlayerWidget::default()))
}
}
impl Deref for PlayerWrapper {
type Target = Rc<PlayerWidget>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl PlayerWrapper {
pub(crate) fn new(sender: &Sender<Action>) -> Self {
let w = Self::default();
w.init(sender);
w
}
fn init(&self, sender: &Sender<Action>) {
self.connect_control_buttons();
self.connect_rate_buttons();
self.connect_mpris_buttons(sender);
self.connect_gst_signals(sender);
}
/// Connect the `PlayerControls` buttons to the `PlayerExt` methods.
fn connect_control_buttons(&self) {
let weak = Rc::downgrade(self);
// Connect the play button to the gst Player.
self.controls.play.connect_clicked(clone!(weak => move |_| {
weak.upgrade().map(|p| p.play());
}));
// Connect the pause button to the gst Player.
self.controls
.pause
.connect_clicked(clone!(weak => move |_| {
weak.upgrade().map(|p| p.pause());
}));
// Connect the rewind button to the gst Player.
self.controls
.rewind
.connect_clicked(clone!(weak => move |_| {
weak.upgrade().map(|p| p.rewind());
}));
// Connect the fast-forward button to the gst Player.
self.controls
.forward
.connect_clicked(clone!(weak => move |_| {
weak.upgrade().map(|p| p.fast_forward());
}));
}
#[cfg_attr(rustfmt, rustfmt_skip)]
fn connect_gst_signals(&self, sender: &Sender<Action>) {
// Log gst warnings.
self.player.connect_warning(move |_, warn| warn!("gst warning: {}", warn));
// Log gst errors.
self.player.connect_error(clone!(sender => move |_, _error| {
// sender.send(Action::ErrorNotification(format!("Player Error: {}", error)));
let s = i18n("The media player was unable to execute an action.");
sender.send(Action::ErrorNotification(s));
}));
// The following callbacks require `Send` but are handled by the gtk main loop
let weak = Fragile::new(Rc::downgrade(self));
// Update the duration label and the slider
self.player.connect_duration_changed(clone!(weak => move |_, clock| {
weak.get()
.upgrade()
.map(|p| p.timer.on_duration_changed(Duration(clock)));
}));
// Update the position label and the slider
self.player.connect_position_updated(clone!(weak => move |_, clock| {
weak.get()
.upgrade()
.map(|p| p.timer.on_position_updated(Position(clock)));
}));
// Reset the slider to 0 and show a play button
self.player.connect_end_of_stream(clone!(weak => move |_| {
weak.get()
.upgrade()
.map(|p| p.stop());
}));
}
#[cfg_attr(rustfmt, rustfmt_skip)]
fn connect_rate_buttons(&self) {
let weak = Rc::downgrade(self);
self.rate
.radio_normal
.connect_toggled(clone!(weak => move |_| {
weak.upgrade().map(|p| p.on_rate_changed(1.00));
}));
self.rate
.radio125
.connect_toggled(clone!(weak => move |_| {
weak.upgrade().map(|p| p.on_rate_changed(1.25));
}));
self.rate
.radio150
.connect_toggled(clone!(weak => move |_| {
weak.upgrade().map(|p| p.on_rate_changed(1.50));
}));
}
fn connect_mpris_buttons(&self, sender: &Sender<Action>) {
let weak = Rc::downgrade(self);
// FIXME: Refference cycle with mpris
let mpris = self.info.mpris.clone();
self.info.mpris.connect_play_pause(clone!(weak => move || {
let player = match weak.upgrade() {
Some(s) => s,
None => return
};
if let Ok(status) = mpris.get_playback_status() {
match status.as_ref() {
"Paused" => player.play(),
"Stopped" => player.play(),
_ => player.pause(),
};
}
}));
self.info.mpris.connect_next(clone!(weak => move || {
weak.upgrade().map(|p| p.fast_forward());
}));
self.info.mpris.connect_previous(clone!(weak => move || {
weak.upgrade().map(|p| p.rewind());
}));
self.info
.mpris
.connect_raise(clone!(sender => move || sender.send(Action::RaiseWindow)));
}
}

View File

@ -30,9 +30,9 @@ use rayon;
use podcasts_data::dbqueries;
use podcasts_data::Show;
use app::Action;
use utils::{self, lazy_load};
use widgets::{BaseView, EmptyShow, EpisodeWidget, ShowMenu};
use crate::app::Action;
use crate::utils::{self, lazy_load};
use crate::widgets::{BaseView, EmptyShow, EpisodeWidget, ShowMenu};
use std::ops::Deref;
use std::rc::Rc;

View File

@ -30,13 +30,13 @@ use podcasts_data::dbqueries;
use podcasts_data::utils::delete_show;
use podcasts_data::Show;
use app::Action;
use utils;
use widgets::appnotif::InAppNotification;
use crate::app::Action;
use crate::utils;
use crate::widgets::appnotif::InAppNotification;
use std::sync::Arc;
use i18n::{i18n, i18n_f};
use crate::i18n::{i18n, i18n_f};
#[derive(Debug, Clone)]
pub(crate) struct ShowMenu {

View File

@ -25,9 +25,9 @@ use failure::Error;
use podcasts_data::dbqueries;
use podcasts_data::Show;
use app::Action;
use utils::{get_ignored_shows, lazy_load, set_image_from_path};
use widgets::BaseView;
use crate::app::Action;
use crate::utils::{get_ignored_shows, lazy_load, set_image_from_path};
use crate::widgets::BaseView;
use std::cell::Cell;
use std::rc::Rc;

View File

@ -4,3 +4,4 @@ newline_style = "Unix"
format_strings = true
normalize_comments = true
use_field_init_shorthand = true
edition = "2018"