refactorial spring cleaning (cargo fmt + clippy)
This commit is contained in:
@@ -12,9 +12,11 @@ use ui::layout::Layout;
|
|||||||
use ui::listview::ListView;
|
use ui::listview::ListView;
|
||||||
use ui::search::SearchView;
|
use ui::search::SearchView;
|
||||||
|
|
||||||
|
type CommandResult = Result<Option<String>, String>;
|
||||||
|
type CommandCb = dyn Fn(&mut Cursive, Vec<String>) -> CommandResult;
|
||||||
|
|
||||||
pub struct CommandManager {
|
pub struct CommandManager {
|
||||||
commands:
|
commands: HashMap<String, Box<CommandCb>>,
|
||||||
HashMap<String, Box<dyn Fn(&mut Cursive, Vec<String>) -> Result<Option<String>, String>>>,
|
|
||||||
aliases: HashMap<String, String>,
|
aliases: HashMap<String, String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -26,12 +28,7 @@ impl CommandManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn register<S: Into<String>>(
|
pub fn register<S: Into<String>>(&mut self, name: S, aliases: Vec<S>, cb: Box<CommandCb>) {
|
||||||
&mut self,
|
|
||||||
name: S,
|
|
||||||
aliases: Vec<S>,
|
|
||||||
cb: Box<dyn Fn(&mut Cursive, Vec<String>) -> Result<Option<String>, String>>,
|
|
||||||
) {
|
|
||||||
let name = name.into();
|
let name = name.into();
|
||||||
for a in aliases {
|
for a in aliases {
|
||||||
self.aliases.insert(a.into(), name.clone());
|
self.aliases.insert(a.into(), name.clone());
|
||||||
@@ -112,7 +109,7 @@ impl CommandManager {
|
|||||||
v.set_view("search");
|
v.set_view("search");
|
||||||
});
|
});
|
||||||
s.call_on_id("search", |v: &mut SearchView| {
|
s.call_on_id("search", |v: &mut SearchView| {
|
||||||
if args.len() >= 1 {
|
if !args.is_empty() {
|
||||||
v.run_search(args.join(" "), spotify.clone());
|
v.run_search(args.join(" "), spotify.clone());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -145,11 +142,11 @@ impl CommandManager {
|
|||||||
"move",
|
"move",
|
||||||
Vec::new(),
|
Vec::new(),
|
||||||
Box::new(move |s, args| {
|
Box::new(move |s, args| {
|
||||||
if args.len() < 1 {
|
if args.is_empty() {
|
||||||
return Err("Missing direction (up, down, left, right)".to_string());
|
return Err("Missing direction (up, down, left, right)".to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
let dir = args.get(0).unwrap();
|
let dir = &args[0];
|
||||||
|
|
||||||
let amount: i32 = args
|
let amount: i32 = args
|
||||||
.get(1)
|
.get(1)
|
||||||
@@ -356,7 +353,7 @@ impl CommandManager {
|
|||||||
match arg.chars().next().unwrap() {
|
match arg.chars().next().unwrap() {
|
||||||
'+' | '-' => {
|
'+' | '-' => {
|
||||||
spotify.seek_relative(arg.parse::<i32>().unwrap_or(0));
|
spotify.seek_relative(arg.parse::<i32>().unwrap_or(0));
|
||||||
},
|
}
|
||||||
_ => {
|
_ => {
|
||||||
spotify.seek(arg.parse::<u32>().unwrap_or(0));
|
spotify.seek(arg.parse::<u32>().unwrap_or(0));
|
||||||
}
|
}
|
||||||
@@ -369,11 +366,11 @@ impl CommandManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_aliases(&self, name: &String) -> String {
|
fn handle_aliases(&self, name: &str) -> String {
|
||||||
if let Some(s) = self.aliases.get(name) {
|
if let Some(s) = self.aliases.get(name) {
|
||||||
self.handle_aliases(s)
|
self.handle_aliases(s)
|
||||||
} else {
|
} else {
|
||||||
name.clone()
|
name.to_string()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -394,9 +391,9 @@ impl CommandManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn register_keybinding<'a, E: Into<cursive::event::Event>, S: Into<String>>(
|
pub fn register_keybinding<E: Into<cursive::event::Event>, S: Into<String>>(
|
||||||
this: Arc<Self>,
|
this: Arc<Self>,
|
||||||
cursive: &'a mut Cursive,
|
cursive: &mut Cursive,
|
||||||
event: E,
|
event: E,
|
||||||
command: S,
|
command: S,
|
||||||
) {
|
) {
|
||||||
@@ -412,7 +409,7 @@ impl CommandManager {
|
|||||||
keybindings: Option<HashMap<String, String>>,
|
keybindings: Option<HashMap<String, String>>,
|
||||||
) {
|
) {
|
||||||
let mut kb = Self::default_keybindings();
|
let mut kb = Self::default_keybindings();
|
||||||
kb.extend(keybindings.unwrap_or(HashMap::new()));
|
kb.extend(keybindings.unwrap_or_default());
|
||||||
|
|
||||||
for (k, v) in kb {
|
for (k, v) in kb {
|
||||||
Self::register_keybinding(this.clone(), cursive, Self::parse_keybinding(k), v);
|
Self::register_keybinding(this.clone(), cursive, Self::parse_keybinding(k), v);
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ pub struct ConfigTheme {
|
|||||||
pub cmdline_bg: Option<String>,
|
pub cmdline_bg: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn proj_dirs () -> ProjectDirs {
|
fn proj_dirs() -> ProjectDirs {
|
||||||
ProjectDirs::from("org", "affekt", "ncspot").expect("can't determine project paths")
|
ProjectDirs::from("org", "affekt", "ncspot").expect("can't determine project paths")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,9 +22,9 @@ impl EventManager {
|
|||||||
let (tx, rx) = unbounded();
|
let (tx, rx) = unbounded();
|
||||||
|
|
||||||
EventManager {
|
EventManager {
|
||||||
tx: tx,
|
tx,
|
||||||
rx: rx,
|
rx,
|
||||||
cursive_sink: cursive_sink,
|
cursive_sink,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -174,7 +174,7 @@ fn main() {
|
|||||||
|
|
||||||
layout.cmdline.set_on_edit(move |s, cmd, _| {
|
layout.cmdline.set_on_edit(move |s, cmd, _| {
|
||||||
s.call_on_id("main", |v: &mut ui::layout::Layout| {
|
s.call_on_id("main", |v: &mut ui::layout::Layout| {
|
||||||
if cmd.len() == 0 {
|
if cmd.is_empty() {
|
||||||
v.clear_cmdline();
|
v.clear_cmdline();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
55
src/mpris.rs
55
src/mpris.rs
@@ -30,7 +30,7 @@ fn get_metadata(queue: Arc<Queue>) -> HashMap<String, Variant<Box<RefArg>>> {
|
|||||||
Variant(Box::new(
|
Variant(Box::new(
|
||||||
track
|
track
|
||||||
.map(|t| format!("spotify:track:{}", t.id))
|
.map(|t| format!("spotify:track:{}", t.id))
|
||||||
.unwrap_or("".to_string()),
|
.unwrap_or_default(),
|
||||||
)),
|
)),
|
||||||
);
|
);
|
||||||
hm.insert(
|
hm.insert(
|
||||||
@@ -40,26 +40,24 @@ fn get_metadata(queue: Arc<Queue>) -> HashMap<String, Variant<Box<RefArg>>> {
|
|||||||
hm.insert(
|
hm.insert(
|
||||||
"mpris:artUrl".to_string(),
|
"mpris:artUrl".to_string(),
|
||||||
Variant(Box::new(
|
Variant(Box::new(
|
||||||
track.map(|t| t.cover_url.clone()).unwrap_or("".to_string()),
|
track.map(|t| t.cover_url.clone()).unwrap_or_default(),
|
||||||
)),
|
)),
|
||||||
);
|
);
|
||||||
|
|
||||||
hm.insert(
|
hm.insert(
|
||||||
"xesam:album".to_string(),
|
"xesam:album".to_string(),
|
||||||
Variant(Box::new(
|
Variant(Box::new(track.map(|t| t.album.clone()).unwrap_or_default())),
|
||||||
track.map(|t| t.album.clone()).unwrap_or("".to_string()),
|
|
||||||
)),
|
|
||||||
);
|
);
|
||||||
hm.insert(
|
hm.insert(
|
||||||
"xesam:albumArtist".to_string(),
|
"xesam:albumArtist".to_string(),
|
||||||
Variant(Box::new(
|
Variant(Box::new(
|
||||||
track.map(|t| t.album_artists.clone()).unwrap_or(Vec::new()),
|
track.map(|t| t.album_artists.clone()).unwrap_or_default(),
|
||||||
)),
|
)),
|
||||||
);
|
);
|
||||||
hm.insert(
|
hm.insert(
|
||||||
"xesam:artist".to_string(),
|
"xesam:artist".to_string(),
|
||||||
Variant(Box::new(
|
Variant(Box::new(
|
||||||
track.map(|t| t.artists.clone()).unwrap_or(Vec::new()),
|
track.map(|t| t.artists.clone()).unwrap_or_default(),
|
||||||
)),
|
)),
|
||||||
);
|
);
|
||||||
hm.insert(
|
hm.insert(
|
||||||
@@ -68,9 +66,7 @@ fn get_metadata(queue: Arc<Queue>) -> HashMap<String, Variant<Box<RefArg>>> {
|
|||||||
);
|
);
|
||||||
hm.insert(
|
hm.insert(
|
||||||
"xesam:title".to_string(),
|
"xesam:title".to_string(),
|
||||||
Variant(Box::new(
|
Variant(Box::new(track.map(|t| t.title.clone()).unwrap_or_default())),
|
||||||
track.map(|t| t.title.clone()).unwrap_or("".to_string()),
|
|
||||||
)),
|
|
||||||
);
|
);
|
||||||
hm.insert(
|
hm.insert(
|
||||||
"xesam:trackNumber".to_string(),
|
"xesam:trackNumber".to_string(),
|
||||||
@@ -78,9 +74,7 @@ fn get_metadata(queue: Arc<Queue>) -> HashMap<String, Variant<Box<RefArg>>> {
|
|||||||
);
|
);
|
||||||
hm.insert(
|
hm.insert(
|
||||||
"xesam:url".to_string(),
|
"xesam:url".to_string(),
|
||||||
Variant(Box::new(
|
Variant(Box::new(track.map(|t| t.url.clone()).unwrap_or_default())),
|
||||||
track.map(|t| t.url.clone()).unwrap_or("".to_string()),
|
|
||||||
)),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
hm
|
hm
|
||||||
@@ -179,15 +173,18 @@ fn run_dbus_server(spotify: Arc<Spotify>, queue: Arc<Queue>, rx: mpsc::Receiver<
|
|||||||
let property_loopstatus = {
|
let property_loopstatus = {
|
||||||
let queue = queue.clone();
|
let queue = queue.clone();
|
||||||
f.property::<String, _>("LoopStatus", ())
|
f.property::<String, _>("LoopStatus", ())
|
||||||
.access(Access::Read)
|
.access(Access::Read)
|
||||||
.on_get(move |iter, _| {
|
.on_get(move |iter, _| {
|
||||||
iter.append(match queue.get_repeat() {
|
iter.append(
|
||||||
RepeatSetting::None => "None",
|
match queue.get_repeat() {
|
||||||
RepeatSetting::RepeatTrack => "Track",
|
RepeatSetting::None => "None",
|
||||||
RepeatSetting::RepeatPlaylist => "Playlist",
|
RepeatSetting::RepeatTrack => "Track",
|
||||||
}.to_string());
|
RepeatSetting::RepeatPlaylist => "Playlist",
|
||||||
Ok(())
|
}
|
||||||
})
|
.to_string(),
|
||||||
|
);
|
||||||
|
Ok(())
|
||||||
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
let property_metadata = {
|
let property_metadata = {
|
||||||
@@ -296,11 +293,11 @@ fn run_dbus_server(spotify: Arc<Spotify>, queue: Arc<Queue>, rx: mpsc::Receiver<
|
|||||||
let property_shuffle = {
|
let property_shuffle = {
|
||||||
let queue = queue.clone();
|
let queue = queue.clone();
|
||||||
f.property::<bool, _>("Shuffle", ())
|
f.property::<bool, _>("Shuffle", ())
|
||||||
.access(Access::Read)
|
.access(Access::Read)
|
||||||
.on_get(move |iter, _| {
|
.on_get(move |iter, _| {
|
||||||
iter.append(queue.get_shuffle());
|
iter.append(queue.get_shuffle());
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
let method_playpause = {
|
let method_playpause = {
|
||||||
@@ -394,7 +391,7 @@ fn run_dbus_server(spotify: Arc<Spotify>, queue: Arc<Queue>, rx: mpsc::Receiver<
|
|||||||
warn!("Unhandled dbus message: {:?}", m);
|
warn!("Unhandled dbus message: {:?}", m);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Ok(_) = rx.try_recv() {
|
if rx.try_recv().is_ok() {
|
||||||
let mut changed: PropertiesPropertiesChanged = Default::default();
|
let mut changed: PropertiesPropertiesChanged = Default::default();
|
||||||
changed.interface_name = "org.mpris.MediaPlayer2.Player".to_string();
|
changed.interface_name = "org.mpris.MediaPlayer2.Player".to_string();
|
||||||
changed.changed_properties.insert(
|
changed.changed_properties.insert(
|
||||||
@@ -427,7 +424,7 @@ impl MprisManager {
|
|||||||
run_dbus_server(spotify, queue, rx);
|
run_dbus_server(spotify, queue, rx);
|
||||||
});
|
});
|
||||||
|
|
||||||
MprisManager { tx: tx }
|
MprisManager { tx }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update(&self) {
|
pub fn update(&self) {
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ impl ListItem for Playlist {
|
|||||||
.map(|t| t.id.clone())
|
.map(|t| t.id.clone())
|
||||||
.collect();
|
.collect();
|
||||||
let ids: Vec<String> = self.tracks.iter().map(|t| t.id.clone()).collect();
|
let ids: Vec<String> = self.tracks.iter().map(|t| t.id.clone()).collect();
|
||||||
ids.len() > 0 && playing == ids
|
!ids.is_empty() && playing == ids
|
||||||
}
|
}
|
||||||
|
|
||||||
fn display_left(&self) -> String {
|
fn display_left(&self) -> String {
|
||||||
@@ -150,7 +150,7 @@ impl Playlists {
|
|||||||
store.len() - 1
|
store.len() - 1
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn overwrite_playlist(&self, id: &str, tracks: &Vec<Track>) {
|
pub fn overwrite_playlist(&self, id: &str, tracks: &[Track]) {
|
||||||
debug!("saving {} tracks to {}", tracks.len(), id);
|
debug!("saving {} tracks to {}", tracks.len(), id);
|
||||||
self.spotify.overwrite_playlist(id, &tracks);
|
self.spotify.overwrite_playlist(id, &tracks);
|
||||||
|
|
||||||
@@ -158,7 +158,7 @@ impl Playlists {
|
|||||||
self.save_cache();
|
self.save_cache();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn save_playlist(&self, name: &str, tracks: &Vec<Track>) {
|
pub fn save_playlist(&self, name: &str, tracks: &[Track]) {
|
||||||
debug!("saving {} tracks to new list {}", tracks.len(), name);
|
debug!("saving {} tracks to new list {}", tracks.len(), name);
|
||||||
match self.spotify.create_playlist(name, None, None) {
|
match self.spotify.create_playlist(name, None, None) {
|
||||||
Some(id) => self.overwrite_playlist(&id, &tracks),
|
Some(id) => self.overwrite_playlist(&id, &tracks),
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ impl Queue {
|
|||||||
current_track: RwLock::new(None),
|
current_track: RwLock::new(None),
|
||||||
repeat: RwLock::new(RepeatSetting::None),
|
repeat: RwLock::new(RepeatSetting::None),
|
||||||
random_order: RwLock::new(None),
|
random_order: RwLock::new(None),
|
||||||
spotify: spotify,
|
spotify,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -107,7 +107,7 @@ impl Queue {
|
|||||||
|
|
||||||
let first = match *self.current_track.read().unwrap() {
|
let first = match *self.current_track.read().unwrap() {
|
||||||
Some(index) => index + 1,
|
Some(index) => index + 1,
|
||||||
None => q.len()
|
None => q.len(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut i = first;
|
let mut i = first;
|
||||||
@@ -158,7 +158,9 @@ impl Queue {
|
|||||||
q.clear();
|
q.clear();
|
||||||
|
|
||||||
let mut random_order = self.random_order.write().unwrap();
|
let mut random_order = self.random_order.write().unwrap();
|
||||||
random_order.as_mut().map(|o| o.clear());
|
if let Some(o) = random_order.as_mut() {
|
||||||
|
o.clear()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn play(&self, index: usize, reshuffle: bool) {
|
pub fn play(&self, index: usize, reshuffle: bool) {
|
||||||
|
|||||||
@@ -80,10 +80,10 @@ impl Worker {
|
|||||||
player: Player,
|
player: Player,
|
||||||
) -> Worker {
|
) -> Worker {
|
||||||
Worker {
|
Worker {
|
||||||
events: events,
|
events,
|
||||||
commands: commands,
|
commands,
|
||||||
player: player,
|
player,
|
||||||
session: session,
|
session,
|
||||||
play_task: Box::new(futures::empty()),
|
play_task: Box::new(futures::empty()),
|
||||||
refresh_task: Box::new(futures::stream::empty()),
|
refresh_task: Box::new(futures::stream::empty()),
|
||||||
token_task: Box::new(futures::empty()),
|
token_task: Box::new(futures::empty()),
|
||||||
@@ -157,17 +157,13 @@ impl futures::Future for Worker {
|
|||||||
self.play_task = Box::new(futures::empty());
|
self.play_task = Box::new(futures::empty());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
match self.refresh_task.poll() {
|
if let Ok(Async::Ready(_)) = self.refresh_task.poll() {
|
||||||
Ok(Async::Ready(_)) => {
|
self.refresh_task = if self.active {
|
||||||
self.refresh_task = match self.active {
|
progress = true;
|
||||||
true => {
|
self.create_refresh()
|
||||||
progress = true;
|
} else {
|
||||||
self.create_refresh()
|
Box::new(futures::stream::empty())
|
||||||
}
|
};
|
||||||
false => Box::new(futures::stream::empty()),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
_ => (),
|
|
||||||
}
|
}
|
||||||
match self.token_task.poll() {
|
match self.token_task.poll() {
|
||||||
Ok(Async::Ready(_)) => {
|
Ok(Async::Ready(_)) => {
|
||||||
@@ -208,7 +204,7 @@ impl Spotify {
|
|||||||
elapsed: RwLock::new(None),
|
elapsed: RwLock::new(None),
|
||||||
since: RwLock::new(None),
|
since: RwLock::new(None),
|
||||||
channel: tx,
|
channel: tx,
|
||||||
user: user,
|
user,
|
||||||
};
|
};
|
||||||
|
|
||||||
// acquire token for web api usage
|
// acquire token for web api usage
|
||||||
@@ -301,7 +297,7 @@ impl Spotify {
|
|||||||
.elapsed
|
.elapsed
|
||||||
.read()
|
.read()
|
||||||
.expect("could not acquire read lock on elapsed time");
|
.expect("could not acquire read lock on elapsed time");
|
||||||
(*elapsed).clone()
|
(*elapsed)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_since(&self, new_since: Option<SystemTime>) {
|
fn set_since(&self, new_since: Option<SystemTime>) {
|
||||||
@@ -317,7 +313,7 @@ impl Spotify {
|
|||||||
.since
|
.since
|
||||||
.read()
|
.read()
|
||||||
.expect("could not acquire read lock on since time");
|
.expect("could not acquire read lock on since time");
|
||||||
(*since).clone()
|
(*since)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn refresh_token(&self) {
|
fn refresh_token(&self) {
|
||||||
@@ -370,7 +366,7 @@ impl Spotify {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn overwrite_playlist(&self, id: &str, tracks: &Vec<Track>) {
|
pub fn overwrite_playlist(&self, id: &str, tracks: &[Track]) {
|
||||||
// extract only track IDs
|
// extract only track IDs
|
||||||
let mut tracks: Vec<String> = tracks.iter().map(|track| track.id.clone()).collect();
|
let mut tracks: Vec<String> = tracks.iter().map(|track| track.id.clone()).collect();
|
||||||
|
|
||||||
@@ -387,9 +383,10 @@ impl Spotify {
|
|||||||
|
|
||||||
// send the remaining tracks in batches of max 100
|
// send the remaining tracks in batches of max 100
|
||||||
while let Some(ref mut tracks) = remainder.clone() {
|
while let Some(ref mut tracks) = remainder.clone() {
|
||||||
if let Some(_) = self.api_with_retry(|api| {
|
let result = self.api_with_retry(|api| {
|
||||||
api.user_playlist_add_tracks(&self.user, id, &tracks, None)
|
api.user_playlist_add_tracks(&self.user, id, &tracks, None)
|
||||||
}) {
|
});
|
||||||
|
if result.is_some() {
|
||||||
// grab the next set of tracks
|
// grab the next set of tracks
|
||||||
remainder = if tracks.len() > 100 {
|
remainder = if tracks.len() > 100 {
|
||||||
Some(tracks.split_off(100))
|
Some(tracks.split_off(100))
|
||||||
@@ -512,7 +509,9 @@ impl Spotify {
|
|||||||
None
|
None
|
||||||
});
|
});
|
||||||
|
|
||||||
self.channel.unbounded_send(WorkerCommand::Seek(position_ms)).unwrap();
|
self.channel
|
||||||
|
.unbounded_send(WorkerCommand::Seek(position_ms))
|
||||||
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn seek_relative(&self, delta: i32) {
|
pub fn seek_relative(&self, delta: i32) {
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ pub fn load(cfg: &Config) -> Theme {
|
|||||||
|
|
||||||
Theme {
|
Theme {
|
||||||
shadow: false,
|
shadow: false,
|
||||||
palette: palette,
|
palette,
|
||||||
borders: borders,
|
borders,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,10 +45,10 @@ impl Track {
|
|||||||
track_number: track.track_number,
|
track_number: track.track_number,
|
||||||
disc_number: track.disc_number,
|
disc_number: track.disc_number,
|
||||||
duration: track.duration_ms,
|
duration: track.duration_ms,
|
||||||
artists: artists,
|
artists,
|
||||||
album: track.album.name.clone(),
|
album: track.album.name.clone(),
|
||||||
album_artists: album_artists,
|
album_artists,
|
||||||
cover_url: cover_url,
|
cover_url,
|
||||||
url: track.uri.clone(),
|
url: track.uri.clone(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ impl Layout {
|
|||||||
screenchange: true,
|
screenchange: true,
|
||||||
last_size: Vec2::new(0, 0),
|
last_size: Vec2::new(0, 0),
|
||||||
ev: ev.clone(),
|
ev: ev.clone(),
|
||||||
theme: theme,
|
theme,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -82,7 +82,7 @@ impl Layout {
|
|||||||
|
|
||||||
pub fn set_view<S: Into<String>>(&mut self, id: S) {
|
pub fn set_view<S: Into<String>>(&mut self, id: S) {
|
||||||
let s = id.into();
|
let s = id.into();
|
||||||
let title = &self.views.get(&s).unwrap().title;
|
let title = &self.views[&s].title;
|
||||||
self.title = title.clone();
|
self.title = title.clone();
|
||||||
self.focus = Some(s);
|
self.focus = Some(s);
|
||||||
self.cmdline_focus = false;
|
self.cmdline_focus = false;
|
||||||
@@ -132,7 +132,7 @@ impl View for Layout {
|
|||||||
|
|
||||||
// screen content
|
// screen content
|
||||||
if let Some(ref id) = self.focus {
|
if let Some(ref id) = self.focus {
|
||||||
let screen = self.views.get(id).unwrap();
|
let screen = &self.views[id];
|
||||||
let printer = &printer
|
let printer = &printer
|
||||||
.offset((0, 1))
|
.offset((0, 1))
|
||||||
.cropped((printer.size.x, printer.size.y - 3 - cmdline_height))
|
.cropped((printer.size.x, printer.size.y - 3 - cmdline_height))
|
||||||
@@ -168,10 +168,7 @@ impl View for Layout {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn on_event(&mut self, event: Event) -> EventResult {
|
fn on_event(&mut self, event: Event) -> EventResult {
|
||||||
if let Event::Mouse {
|
if let Event::Mouse { position, .. } = event {
|
||||||
position,
|
|
||||||
..
|
|
||||||
} = event {
|
|
||||||
let error = self.get_error();
|
let error = self.get_error();
|
||||||
|
|
||||||
let cmdline_visible = self.cmdline.get_content().len() > 0;
|
let cmdline_visible = self.cmdline.get_content().len() > 0;
|
||||||
@@ -186,7 +183,9 @@ impl View for Layout {
|
|||||||
screen.view.on_event(event.clone());
|
screen.view.on_event(event.clone());
|
||||||
}
|
}
|
||||||
} else if position.y < self.last_size.y - cmdline_height {
|
} else if position.y < self.last_size.y - cmdline_height {
|
||||||
self.statusbar.on_event(event.relativized(Vec2::new(0, self.last_size.y - 2 - cmdline_height)));
|
self.statusbar.on_event(
|
||||||
|
event.relativized(Vec2::new(0, self.last_size.y - 2 - cmdline_height)),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return EventResult::Consumed(None);
|
return EventResult::Consumed(None);
|
||||||
|
|||||||
@@ -24,12 +24,12 @@ pub struct ListView<I: 'static + ListItem> {
|
|||||||
impl<I: ListItem> ListView<I> {
|
impl<I: ListItem> ListView<I> {
|
||||||
pub fn new(content: Arc<RwLock<Vec<I>>>, queue: Arc<Queue>) -> Self {
|
pub fn new(content: Arc<RwLock<Vec<I>>>, queue: Arc<Queue>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
content: content,
|
content,
|
||||||
last_content_length: 0,
|
last_content_length: 0,
|
||||||
selected: 0,
|
selected: 0,
|
||||||
last_size: Vec2::new(0, 0),
|
last_size: Vec2::new(0, 0),
|
||||||
scrollbar: ScrollBase::new(),
|
scrollbar: ScrollBase::new(),
|
||||||
queue: queue,
|
queue,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,9 +70,10 @@ impl<I: ListItem> View for ListView<I> {
|
|||||||
let item = &content[i];
|
let item = &content[i];
|
||||||
|
|
||||||
let style = if self.selected == i {
|
let style = if self.selected == i {
|
||||||
let fg = match item.is_playing(self.queue.clone()) {
|
let fg = if item.is_playing(self.queue.clone()) {
|
||||||
true => *printer.theme.palette.custom("playing").unwrap(),
|
*printer.theme.palette.custom("playing").unwrap()
|
||||||
false => PaletteColor::Tertiary.resolve(&printer.theme.palette)
|
} else {
|
||||||
|
PaletteColor::Tertiary.resolve(&printer.theme.palette)
|
||||||
};
|
};
|
||||||
ColorStyle::new(
|
ColorStyle::new(
|
||||||
ColorType::Color(fg),
|
ColorType::Color(fg),
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ pub struct Modal<T: View> {
|
|||||||
|
|
||||||
impl<T: View> Modal<T> {
|
impl<T: View> Modal<T> {
|
||||||
pub fn new(inner: T) -> Self {
|
pub fn new(inner: T) -> Self {
|
||||||
Modal { inner: inner }
|
Modal { inner }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ impl PlaylistView {
|
|||||||
pub fn new(playlists: &Playlists, queue: Arc<Queue>) -> PlaylistView {
|
pub fn new(playlists: &Playlists, queue: Arc<Queue>) -> PlaylistView {
|
||||||
let list = ListView::new(playlists.store.clone(), queue).with_id("list");
|
let list = ListView::new(playlists.store.clone(), queue).with_id("list");
|
||||||
|
|
||||||
PlaylistView { list: list }
|
PlaylistView { list }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,10 +21,7 @@ impl QueueView {
|
|||||||
pub fn new(queue: Arc<Queue>, playlists: Arc<Playlists>) -> QueueView {
|
pub fn new(queue: Arc<Queue>, playlists: Arc<Playlists>) -> QueueView {
|
||||||
let list = ListView::new(queue.queue.clone(), queue.clone()).with_id("queue_list");
|
let list = ListView::new(queue.queue.clone(), queue.clone()).with_id("queue_list");
|
||||||
|
|
||||||
QueueView {
|
QueueView { list, playlists }
|
||||||
list: list,
|
|
||||||
playlists: playlists,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn save_dialog_cb(s: &mut Cursive, playlists: Arc<Playlists>, id: Option<String>) {
|
fn save_dialog_cb(s: &mut Cursive, playlists: Arc<Playlists>, id: Option<String>) {
|
||||||
@@ -61,7 +58,7 @@ impl QueueView {
|
|||||||
let mut list_select: SelectView<Option<String>> = SelectView::new().autojump();
|
let mut list_select: SelectView<Option<String>> = SelectView::new().autojump();
|
||||||
list_select.add_item("[Create new]", None);
|
list_select.add_item("[Create new]", None);
|
||||||
|
|
||||||
for ref list in playlists.items().iter() {
|
for list in playlists.items().iter() {
|
||||||
list_select.add_item(list.meta.name.clone(), Some(list.meta.id.clone()));
|
list_select.add_item(list.meta.name.clone(), Some(list.meta.id.clone()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ impl SearchView {
|
|||||||
|
|
||||||
let searchfield = EditView::new()
|
let searchfield = EditView::new()
|
||||||
.on_submit(move |s, input| {
|
.on_submit(move |s, input| {
|
||||||
if input.len() > 0 {
|
if !input.is_empty() {
|
||||||
s.call_on_id("search", |v: &mut SearchView| {
|
s.call_on_id("search", |v: &mut SearchView| {
|
||||||
v.run_search(input, spotify.clone());
|
v.run_search(input, spotify.clone());
|
||||||
v.focus_view(&Selector::Id("list")).unwrap();
|
v.focus_view(&Selector::Id("list")).unwrap();
|
||||||
@@ -38,9 +38,9 @@ impl SearchView {
|
|||||||
let list = ListView::new(results.clone(), queue).with_id("list");
|
let list = ListView::new(results.clone(), queue).with_id("list");
|
||||||
|
|
||||||
SearchView {
|
SearchView {
|
||||||
results: results,
|
results,
|
||||||
edit: searchfield,
|
edit: searchfield,
|
||||||
list: list,
|
list,
|
||||||
edit_focused: true,
|
edit_focused: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -67,9 +67,10 @@ impl SearchView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn pass_event_focused(&mut self, event: Event) -> EventResult {
|
fn pass_event_focused(&mut self, event: Event) -> EventResult {
|
||||||
match self.edit_focused {
|
if self.edit_focused {
|
||||||
true => self.edit.on_event(event),
|
self.edit.on_event(event)
|
||||||
false => self.list.on_event(event),
|
} else {
|
||||||
|
self.list.on_event(event)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -111,7 +112,7 @@ impl View for SearchView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn on_event(&mut self, event: Event) -> EventResult {
|
fn on_event(&mut self, event: Event) -> EventResult {
|
||||||
let ret = match event {
|
match event {
|
||||||
Event::Key(Key::Tab) => {
|
Event::Key(Key::Tab) => {
|
||||||
self.edit_focused = !self.edit_focused;
|
self.edit_focused = !self.edit_focused;
|
||||||
EventResult::Consumed(None)
|
EventResult::Consumed(None)
|
||||||
@@ -121,8 +122,6 @@ impl View for SearchView {
|
|||||||
EventResult::Consumed(None)
|
EventResult::Consumed(None)
|
||||||
}
|
}
|
||||||
_ => self.pass_event_focused(event),
|
_ => self.pass_event_focused(event),
|
||||||
};
|
}
|
||||||
|
|
||||||
ret
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,10 +22,10 @@ pub struct StatusBar {
|
|||||||
impl StatusBar {
|
impl StatusBar {
|
||||||
pub fn new(queue: Arc<Queue>, spotify: Arc<Spotify>, cfg: &Config) -> StatusBar {
|
pub fn new(queue: Arc<Queue>, spotify: Arc<Spotify>, cfg: &Config) -> StatusBar {
|
||||||
StatusBar {
|
StatusBar {
|
||||||
queue: queue,
|
queue,
|
||||||
spotify: spotify,
|
spotify,
|
||||||
last_size: Vec2::new(0, 0),
|
last_size: Vec2::new(0, 0),
|
||||||
use_nerdfont: cfg.use_nerdfont.unwrap_or(false)
|
use_nerdfont: cfg.use_nerdfont.unwrap_or(false),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -87,13 +87,19 @@ impl View for StatusBar {
|
|||||||
RepeatSetting::RepeatPlaylist => "[R] ",
|
RepeatSetting::RepeatPlaylist => "[R] ",
|
||||||
RepeatSetting::RepeatTrack => "[R1] ",
|
RepeatSetting::RepeatTrack => "[R1] ",
|
||||||
}
|
}
|
||||||
}.to_string();
|
}
|
||||||
|
.to_string();
|
||||||
|
|
||||||
let shuffle = if self.use_nerdfont {
|
let shuffle = if self.queue.get_shuffle() {
|
||||||
if self.queue.get_shuffle() { "\u{f99c} " } else { "" }
|
if self.use_nerdfont {
|
||||||
|
"\u{f99c} "
|
||||||
|
} else {
|
||||||
|
"[Z]"
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if self.queue.get_shuffle() { "[Z] " } else { "" }
|
""
|
||||||
}.to_string();
|
}
|
||||||
|
.to_string();
|
||||||
|
|
||||||
if let Some(ref t) = self.queue.get_current() {
|
if let Some(ref t) = self.queue.get_current() {
|
||||||
let elapsed = self.spotify.get_current_progress();
|
let elapsed = self.spotify.get_current_progress();
|
||||||
@@ -105,7 +111,8 @@ impl View for StatusBar {
|
|||||||
elapsed.as_secs() % 60
|
elapsed.as_secs() % 60
|
||||||
);
|
);
|
||||||
|
|
||||||
let right = repeat + &shuffle + &format!("{} / {} ", formatted_elapsed, t.duration_str());
|
let right =
|
||||||
|
repeat + &shuffle + &format!("{} / {} ", formatted_elapsed, t.duration_str());
|
||||||
let offset = HAlign::Right.get_offset(right.width(), printer.size.x);
|
let offset = HAlign::Right.get_offset(right.width(), printer.size.x);
|
||||||
|
|
||||||
printer.with_color(style, |printer| {
|
printer.with_color(style, |printer| {
|
||||||
@@ -115,8 +122,7 @@ impl View for StatusBar {
|
|||||||
|
|
||||||
printer.with_color(style_bar, |printer| {
|
printer.with_color(style_bar, |printer| {
|
||||||
printer.print((0, 0), &"—".repeat(printer.size.x));
|
printer.print((0, 0), &"—".repeat(printer.size.x));
|
||||||
let duration_width =
|
let duration_width = (((printer.size.x as u32) * elapsed_ms) / t.duration) as usize;
|
||||||
(((printer.size.x as u32) * elapsed_ms) / t.duration) as usize;
|
|
||||||
printer.print((0, 0), &format!("{}{}", "=".repeat(duration_width), ">"));
|
printer.print((0, 0), &format!("{}{}", "=".repeat(duration_width), ">"));
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
@@ -145,8 +151,9 @@ impl View for StatusBar {
|
|||||||
if let Event::Mouse {
|
if let Event::Mouse {
|
||||||
offset,
|
offset,
|
||||||
position,
|
position,
|
||||||
event
|
event,
|
||||||
} = event {
|
} = event
|
||||||
|
{
|
||||||
let position = position - offset;
|
let position = position - offset;
|
||||||
|
|
||||||
if position.y == 0 {
|
if position.y == 0 {
|
||||||
@@ -158,20 +165,17 @@ impl View for StatusBar {
|
|||||||
self.spotify.seek_relative(500);
|
self.spotify.seek_relative(500);
|
||||||
}
|
}
|
||||||
|
|
||||||
if event == MouseEvent::Press(MouseButton::Left) ||
|
if event == MouseEvent::Press(MouseButton::Left)
|
||||||
event == MouseEvent::Hold(MouseButton::Left)
|
|| event == MouseEvent::Hold(MouseButton::Left)
|
||||||
{
|
{
|
||||||
if let Some(ref t) = self.queue.get_current() {
|
if let Some(ref t) = self.queue.get_current() {
|
||||||
let f: f32 = position.x as f32 / self.last_size.x as f32;
|
let f: f32 = position.x as f32 / self.last_size.x as f32;
|
||||||
let new = t.duration as f32 * f;
|
let new = t.duration as f32 * f;
|
||||||
self.spotify.seek(new as u32);
|
self.spotify.seek(new as u32);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if event == MouseEvent::Press(MouseButton::Left) {
|
|
||||||
self.queue.toggleplayback();
|
|
||||||
}
|
}
|
||||||
|
} else if event == MouseEvent::Press(MouseButton::Left) {
|
||||||
|
self.queue.toggleplayback();
|
||||||
}
|
}
|
||||||
|
|
||||||
EventResult::Consumed(None)
|
EventResult::Consumed(None)
|
||||||
|
|||||||
Reference in New Issue
Block a user