cargo fmt/clippy all the things + make them mandatory in CI
This commit is contained in:
@@ -6,3 +6,8 @@ matrix:
|
|||||||
fast_finish: true
|
fast_finish: true
|
||||||
before_install:
|
before_install:
|
||||||
- sudo apt-get install -y libasound2-dev libdbus-1-dev
|
- sudo apt-get install -y libasound2-dev libdbus-1-dev
|
||||||
|
script:
|
||||||
|
- cargo update
|
||||||
|
- rustup component add clippy rustfmt
|
||||||
|
- cargo clippy --all-targets -- -D warnings
|
||||||
|
- cargo fmt --all -- --check
|
||||||
|
|||||||
30
src/album.rs
30
src/album.rs
@@ -16,7 +16,7 @@ pub struct Album {
|
|||||||
pub year: String,
|
pub year: String,
|
||||||
pub cover_url: Option<String>,
|
pub cover_url: Option<String>,
|
||||||
pub url: String,
|
pub url: String,
|
||||||
pub tracks: Option<Vec<Track>>
|
pub tracks: Option<Vec<Track>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Album {
|
impl Album {
|
||||||
@@ -26,10 +26,12 @@ impl Album {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let Some(fa) = spotify.full_album(&self.id) {
|
if let Some(fa) = spotify.full_album(&self.id) {
|
||||||
self.tracks = Some(fa.tracks.items
|
self.tracks = Some(
|
||||||
.iter()
|
fa.tracks
|
||||||
.map(|st| Track::from_simplified_track(&st, &fa))
|
.items
|
||||||
.collect()
|
.iter()
|
||||||
|
.map(|st| Track::from_simplified_track(&st, &fa))
|
||||||
|
.collect(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -41,30 +43,32 @@ impl From<&SimplifiedAlbum> for Album {
|
|||||||
id: sa.id.clone(),
|
id: sa.id.clone(),
|
||||||
title: sa.name.clone(),
|
title: sa.name.clone(),
|
||||||
artists: sa.artists.iter().map(|sa| sa.name.clone()).collect(),
|
artists: sa.artists.iter().map(|sa| sa.name.clone()).collect(),
|
||||||
year: sa.release_date.split("-").next().unwrap().into(),
|
year: sa.release_date.split('-').next().unwrap().into(),
|
||||||
cover_url: sa.images.get(0).map(|i| i.url.clone()),
|
cover_url: sa.images.get(0).map(|i| i.url.clone()),
|
||||||
url: sa.uri.clone(),
|
url: sa.uri.clone(),
|
||||||
tracks: None
|
tracks: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<&FullAlbum> for Album {
|
impl From<&FullAlbum> for Album {
|
||||||
fn from(fa: &FullAlbum) -> Self {
|
fn from(fa: &FullAlbum) -> Self {
|
||||||
let tracks = Some(fa.tracks.items
|
let tracks = Some(
|
||||||
.iter()
|
fa.tracks
|
||||||
.map(|st| Track::from_simplified_track(&st, &fa))
|
.items
|
||||||
.collect()
|
.iter()
|
||||||
|
.map(|st| Track::from_simplified_track(&st, &fa))
|
||||||
|
.collect(),
|
||||||
);
|
);
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
id: fa.id.clone(),
|
id: fa.id.clone(),
|
||||||
title: fa.name.clone(),
|
title: fa.name.clone(),
|
||||||
artists: fa.artists.iter().map(|sa| sa.name.clone()).collect(),
|
artists: fa.artists.iter().map(|sa| sa.name.clone()).collect(),
|
||||||
year: fa.release_date.split("-").next().unwrap().into(),
|
year: fa.release_date.split('-').next().unwrap().into(),
|
||||||
cover_url: fa.images.get(0).map(|i| i.url.clone()),
|
cover_url: fa.images.get(0).map(|i| i.url.clone()),
|
||||||
url: fa.uri.clone(),
|
url: fa.uri.clone(),
|
||||||
tracks: tracks
|
tracks,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ pub struct Artist {
|
|||||||
pub id: String,
|
pub id: String,
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub url: String,
|
pub url: String,
|
||||||
pub albums: Option<Vec<Album>>
|
pub albums: Option<Vec<Album>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Artist {
|
impl Artist {
|
||||||
@@ -42,11 +42,12 @@ impl Artist {
|
|||||||
|
|
||||||
fn tracks(&self) -> Option<Vec<&Track>> {
|
fn tracks(&self) -> Option<Vec<&Track>> {
|
||||||
if let Some(albums) = self.albums.as_ref() {
|
if let Some(albums) = self.albums.as_ref() {
|
||||||
Some(albums
|
Some(
|
||||||
.iter()
|
albums
|
||||||
.map(|a| a.tracks.as_ref().unwrap())
|
.iter()
|
||||||
.flatten()
|
.map(|a| a.tracks.as_ref().unwrap())
|
||||||
.collect()
|
.flatten()
|
||||||
|
.collect(),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
@@ -60,7 +61,7 @@ impl From<&FullArtist> for Artist {
|
|||||||
id: fa.id.clone(),
|
id: fa.id.clone(),
|
||||||
name: fa.name.clone(),
|
name: fa.name.clone(),
|
||||||
url: fa.uri.clone(),
|
url: fa.uri.clone(),
|
||||||
albums: None
|
albums: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,16 +55,16 @@ pub fn create_credentials(path: &Path) -> Result<RespotCredentials, String> {
|
|||||||
.json()
|
.json()
|
||||||
.expect("didn't parse");
|
.expect("didn't parse");
|
||||||
// not a dialog to let people copy & paste the URL
|
// not a dialog to let people copy & paste the URL
|
||||||
let url_notice = TextView::new(format!("Browse to {}", urls.get("login_url").unwrap()));
|
let url_notice = TextView::new(format!("Browse to {}", &urls["login_url"]));
|
||||||
|
|
||||||
let controls = Button::new("Quit", |s| s.quit());
|
let controls = Button::new("Quit", |s| s.quit());
|
||||||
|
|
||||||
let login_view = LinearLayout::new(cursive::direction::Orientation::Vertical)
|
let login_view = LinearLayout::new(cursive::direction::Orientation::Vertical)
|
||||||
.child(url_notice)
|
.child(url_notice)
|
||||||
.child(controls);
|
.child(controls);
|
||||||
let url = urls.get("login_url").unwrap();
|
let url = &urls["login_url"];
|
||||||
webbrowser::open(url).ok();
|
webbrowser::open(url).ok();
|
||||||
auth_poller(urls.get("credentials_url").unwrap(), &s.cb_sink());
|
auth_poller(&urls["credentials_url"], &s.cb_sink());
|
||||||
s.pop_layer();
|
s.pop_layer();
|
||||||
s.add_layer(login_view)
|
s.add_layer(login_view)
|
||||||
})
|
})
|
||||||
@@ -76,7 +76,7 @@ pub fn create_credentials(path: &Path) -> Result<RespotCredentials, String> {
|
|||||||
login_cursive
|
login_cursive
|
||||||
.user_data()
|
.user_data()
|
||||||
.cloned()
|
.cloned()
|
||||||
.unwrap_or(Err("Didn't obtain any credentials".to_string()))
|
.unwrap_or_else(|| Err("Didn't obtain any credentials".to_string()))
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: better with futures?
|
// TODO: better with futures?
|
||||||
|
|||||||
@@ -88,11 +88,9 @@ pub fn load_or_generate_default<
|
|||||||
|
|
||||||
// Deserialize the content, optionally fall back to default if it fails
|
// Deserialize the content, optionally fall back to default if it fails
|
||||||
let result = toml::from_str(&contents);
|
let result = toml::from_str(&contents);
|
||||||
if default_on_parse_failure {
|
if default_on_parse_failure && result.is_err() {
|
||||||
if let Err(_) = result {
|
let value = default(&path)?;
|
||||||
let value = default(&path)?;
|
return write_content_helper(&path, value);
|
||||||
return write_content_helper(&path, value);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
result.map_err(|e| format!("Unable to parse {}: {}", path.to_string_lossy(), e))
|
result.map_err(|e| format!("Unable to parse {}: {}", path.to_string_lossy(), e))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,9 @@ use rspotify::spotify::client::Spotify as SpotifyAPI;
|
|||||||
use rspotify::spotify::model::album::{FullAlbum, SimplifiedAlbum};
|
use rspotify::spotify::model::album::{FullAlbum, SimplifiedAlbum};
|
||||||
use rspotify::spotify::model::page::Page;
|
use rspotify::spotify::model::page::Page;
|
||||||
use rspotify::spotify::model::playlist::{PlaylistTrack, SimplifiedPlaylist};
|
use rspotify::spotify::model::playlist::{PlaylistTrack, SimplifiedPlaylist};
|
||||||
use rspotify::spotify::model::search::{SearchTracks, SearchAlbums, SearchArtists, SearchPlaylists};
|
use rspotify::spotify::model::search::{
|
||||||
|
SearchAlbums, SearchArtists, SearchPlaylists, SearchTracks,
|
||||||
|
};
|
||||||
|
|
||||||
use failure::Error;
|
use failure::Error;
|
||||||
|
|
||||||
@@ -344,7 +346,10 @@ impl Spotify {
|
|||||||
|
|
||||||
// update token used by web api calls
|
// update token used by web api calls
|
||||||
self.api.write().expect("can't writelock api").access_token = Some(token.access_token);
|
self.api.write().expect("can't writelock api").access_token = Some(token.access_token);
|
||||||
self.token_issued.write().unwrap().replace(SystemTime::now());
|
self.token_issued
|
||||||
|
.write()
|
||||||
|
.unwrap()
|
||||||
|
.replace(SystemTime::now());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// retries once when rate limits are hit
|
/// retries once when rate limits are hit
|
||||||
@@ -485,15 +490,11 @@ impl Spotify {
|
|||||||
&self,
|
&self,
|
||||||
artist_id: &str,
|
artist_id: &str,
|
||||||
limit: u32,
|
limit: u32,
|
||||||
offset: u32
|
offset: u32,
|
||||||
) -> Option<Page<SimplifiedAlbum>> {
|
) -> Option<Page<SimplifiedAlbum>> {
|
||||||
self.api_with_retry(|api| api.artist_albums(
|
self.api_with_retry(|api| {
|
||||||
artist_id,
|
api.artist_albums(artist_id, None, None, Some(limit), Some(offset))
|
||||||
None,
|
})
|
||||||
None,
|
|
||||||
Some(limit),
|
|
||||||
Some(offset)
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn load(&self, track: &Track) {
|
pub fn load(&self, track: &Track) {
|
||||||
|
|||||||
@@ -54,10 +54,26 @@ impl SearchView {
|
|||||||
.with_id(EDIT_ID);
|
.with_id(EDIT_ID);
|
||||||
|
|
||||||
let tabs = TabView::new()
|
let tabs = TabView::new()
|
||||||
.tab("tracks", "Tracks", ListView::new(results_tracks.clone(), queue.clone()))
|
.tab(
|
||||||
.tab("albums", "Albums", ListView::new(results_albums.clone(), queue.clone()))
|
"tracks",
|
||||||
.tab("artists", "Artists", ListView::new(results_artists.clone(), queue.clone()))
|
"Tracks",
|
||||||
.tab("playlists", "Playlists", ListView::new(results_playlists.clone(), queue.clone()));
|
ListView::new(results_tracks.clone(), queue.clone()),
|
||||||
|
)
|
||||||
|
.tab(
|
||||||
|
"albums",
|
||||||
|
"Albums",
|
||||||
|
ListView::new(results_albums.clone(), queue.clone()),
|
||||||
|
)
|
||||||
|
.tab(
|
||||||
|
"artists",
|
||||||
|
"Artists",
|
||||||
|
ListView::new(results_artists.clone(), queue.clone()),
|
||||||
|
)
|
||||||
|
.tab(
|
||||||
|
"playlists",
|
||||||
|
"Playlists",
|
||||||
|
ListView::new(results_playlists.clone(), queue.clone()),
|
||||||
|
);
|
||||||
|
|
||||||
SearchView {
|
SearchView {
|
||||||
results_tracks,
|
results_tracks,
|
||||||
@@ -79,52 +95,25 @@ impl SearchView {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn search_track(
|
fn search_track(spotify: Arc<Spotify>, tracks: Arc<RwLock<Vec<Track>>>, query: String) {
|
||||||
spotify: Arc<Spotify>,
|
|
||||||
tracks: Arc<RwLock<Vec<Track>>>,
|
|
||||||
query: String,
|
|
||||||
) {
|
|
||||||
if let Some(results) = spotify.search_track(&query, 50, 0) {
|
if let Some(results) = spotify.search_track(&query, 50, 0) {
|
||||||
let t = results
|
let t = results.tracks.items.iter().map(|ft| ft.into()).collect();
|
||||||
.tracks
|
|
||||||
.items
|
|
||||||
.iter()
|
|
||||||
.map(|ft| ft.into())
|
|
||||||
.collect();
|
|
||||||
let mut r = tracks.write().unwrap();
|
let mut r = tracks.write().unwrap();
|
||||||
*r = t;
|
*r = t;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn search_album(
|
fn search_album(spotify: Arc<Spotify>, albums: Arc<RwLock<Vec<Album>>>, query: String) {
|
||||||
spotify: Arc<Spotify>,
|
|
||||||
albums: Arc<RwLock<Vec<Album>>>,
|
|
||||||
query: String,
|
|
||||||
) {
|
|
||||||
if let Some(results) = spotify.search_album(&query, 50, 0) {
|
if let Some(results) = spotify.search_album(&query, 50, 0) {
|
||||||
let a = results
|
let a = results.albums.items.iter().map(|sa| sa.into()).collect();
|
||||||
.albums
|
|
||||||
.items
|
|
||||||
.iter()
|
|
||||||
.map(|sa| sa.into())
|
|
||||||
.collect();
|
|
||||||
let mut r = albums.write().unwrap();
|
let mut r = albums.write().unwrap();
|
||||||
*r = a;
|
*r = a;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn search_artist(
|
fn search_artist(spotify: Arc<Spotify>, artists: Arc<RwLock<Vec<Artist>>>, query: String) {
|
||||||
spotify: Arc<Spotify>,
|
|
||||||
artists: Arc<RwLock<Vec<Artist>>>,
|
|
||||||
query: String,
|
|
||||||
) {
|
|
||||||
if let Some(results) = spotify.search_artist(&query, 50, 0) {
|
if let Some(results) = spotify.search_artist(&query, 50, 0) {
|
||||||
let a = results
|
let a = results.artists.items.iter().map(|fa| fa.into()).collect();
|
||||||
.artists
|
|
||||||
.items
|
|
||||||
.iter()
|
|
||||||
.map(|fa| fa.into())
|
|
||||||
.collect();
|
|
||||||
let mut r = artists.write().unwrap();
|
let mut r = artists.write().unwrap();
|
||||||
*r = a;
|
*r = a;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,7 +40,13 @@ impl View for StatusBar {
|
|||||||
ColorType::Palette(PaletteColor::Background),
|
ColorType::Palette(PaletteColor::Background),
|
||||||
);
|
);
|
||||||
let style_bar_bg = ColorStyle::new(
|
let style_bar_bg = ColorStyle::new(
|
||||||
ColorType::Color(*printer.theme.palette.custom("statusbar_progress_bg").unwrap()),
|
ColorType::Color(
|
||||||
|
*printer
|
||||||
|
.theme
|
||||||
|
.palette
|
||||||
|
.custom("statusbar_progress_bg")
|
||||||
|
.unwrap(),
|
||||||
|
),
|
||||||
ColorType::Palette(PaletteColor::Background),
|
ColorType::Palette(PaletteColor::Background),
|
||||||
);
|
);
|
||||||
let style = ColorStyle::new(
|
let style = ColorStyle::new(
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ use cursive::{Cursive, Printer, Vec2};
|
|||||||
use unicode_width::UnicodeWidthStr;
|
use unicode_width::UnicodeWidthStr;
|
||||||
|
|
||||||
use commands::CommandResult;
|
use commands::CommandResult;
|
||||||
use traits::{ViewExt, IntoBoxedViewExt};
|
use traits::{IntoBoxedViewExt, ViewExt};
|
||||||
|
|
||||||
pub struct Tab {
|
pub struct Tab {
|
||||||
title: String,
|
title: String,
|
||||||
@@ -18,7 +18,7 @@ pub struct Tab {
|
|||||||
pub struct TabView {
|
pub struct TabView {
|
||||||
tabs: Vec<Tab>,
|
tabs: Vec<Tab>,
|
||||||
ids: HashMap<String, usize>,
|
ids: HashMap<String, usize>,
|
||||||
selected: usize
|
selected: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TabView {
|
impl TabView {
|
||||||
@@ -26,14 +26,14 @@ impl TabView {
|
|||||||
Self {
|
Self {
|
||||||
tabs: Vec::new(),
|
tabs: Vec::new(),
|
||||||
ids: HashMap::new(),
|
ids: HashMap::new(),
|
||||||
selected: 0
|
selected: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_tab<S: Into<String>, V: IntoBoxedViewExt>(&mut self, id: S, title: S, view: V) {
|
pub fn add_tab<S: Into<String>, V: IntoBoxedViewExt>(&mut self, id: S, title: S, view: V) {
|
||||||
let tab = Tab {
|
let tab = Tab {
|
||||||
title: title.into(),
|
title: title.into(),
|
||||||
view: view.as_boxed_view_ext()
|
view: view.as_boxed_view_ext(),
|
||||||
};
|
};
|
||||||
self.tabs.push(tab);
|
self.tabs.push(tab);
|
||||||
self.ids.insert(id.into(), self.tabs.len() - 1);
|
self.ids.insert(id.into(), self.tabs.len() - 1);
|
||||||
@@ -57,7 +57,7 @@ impl TabView {
|
|||||||
|
|
||||||
impl View for TabView {
|
impl View for TabView {
|
||||||
fn draw(&self, printer: &Printer<'_, '_>) {
|
fn draw(&self, printer: &Printer<'_, '_>) {
|
||||||
if self.tabs.len() == 0 {
|
if self.tabs.is_empty() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user