diff --git a/src/queue.rs b/src/queue.rs index 6798ff8..97eefd2 100644 --- a/src/queue.rs +++ b/src/queue.rs @@ -163,6 +163,29 @@ impl Queue { } } + pub fn len(&self) -> usize { + self.queue.read().unwrap().len() + } + + pub fn shift(&self, from: usize, to: usize) { + let mut queue = self.queue.write().unwrap(); + let item = queue.remove(from); + queue.insert(to, item); + + // if the currently playing track is affected by the shift, update its + // index + let mut current = self.current_track.write().unwrap(); + if let Some(index) = *current { + if index == from { + current.replace(to); + } else if index == to && from > index { + current.replace(to + 1); + } else if index == to && from < index { + current.replace(to - 1); + } + } + } + pub fn play(&self, index: usize, reshuffle: bool) { if let Some(track) = &self.queue.read().unwrap().get(index) { self.spotify.load(&track); diff --git a/src/ui/listview.rs b/src/ui/listview.rs index d8b28eb..491e17c 100644 --- a/src/ui/listview.rs +++ b/src/ui/listview.rs @@ -20,7 +20,6 @@ pub struct ListView { last_size: Vec2, scrollbar: ScrollBase, queue: Arc, - shiftable: bool, } impl ListView { @@ -32,15 +31,9 @@ impl ListView { last_size: Vec2::new(0, 0), scrollbar: ScrollBase::new(), queue, - shiftable: false, } } - pub fn shiftable(mut self) -> Self { - self.shiftable = true; - self - } - pub fn get_selected_index(&self) -> usize { self.selected } @@ -55,11 +48,6 @@ impl ListView { let new = self.selected as i32 + delta; self.move_focus_to(max(new, 0) as usize); } - - pub fn swap(&mut self, a: usize, b: usize) { - let mut content = self.content.write().expect("can't writelock content"); - content.swap(a, b); - } } impl View for ListView { @@ -208,7 +196,7 @@ impl ViewExt for ListView { return Ok(CommandResult::Consumed(None)); } - if cmd == "move" || cmd == "shift" { + if cmd == "move" { if let Some(dir) = args.get(0) { let amount: usize = args .get(1) @@ -216,22 +204,14 @@ impl ViewExt for ListView { .parse() .map_err(|e| format!("{:?}", e))?; - let shift = cmd == "shift" && self.shiftable; - let selected = self.selected; let len = self.content.read().unwrap().len(); if dir == "up" && self.selected > 0 { - if shift { - self.swap(selected, selected.saturating_sub(amount)); - } self.move_focus(-(amount as i32)); return Ok(CommandResult::Consumed(None)); } if dir == "down" && self.selected < len.saturating_sub(1) { - if shift { - self.swap(selected, min(selected + amount as usize, len - 1)); - } self.move_focus(amount as i32); return Ok(CommandResult::Consumed(None)); } diff --git a/src/ui/queue.rs b/src/ui/queue.rs index 0e5e46d..8c9d77b 100644 --- a/src/ui/queue.rs +++ b/src/ui/queue.rs @@ -4,6 +4,7 @@ use cursive::view::ViewWrapper; use cursive::views::{Dialog, EditView, ScrollView, SelectView}; use cursive::Cursive; +use std::cmp::min; use std::sync::Arc; use commands::CommandResult; @@ -22,7 +23,7 @@ pub struct QueueView { impl QueueView { pub fn new(queue: Arc, playlists: Arc) -> QueueView { - let list = ListView::new(queue.queue.clone(), queue.clone()).shiftable(); + let list = ListView::new(queue.queue.clone(), queue.clone()); QueueView { list, @@ -124,6 +125,28 @@ impl ViewExt for QueueView { return Ok(CommandResult::Consumed(None)); } + if cmd == "shift" { + if let Some(dir) = args.get(0) { + let amount: usize = args + .get(1) + .unwrap_or(&"1".to_string()) + .parse() + .map_err(|e| format!("{:?}", e))?; + let selected = self.list.get_selected_index(); + let len = self.queue.len(); + if dir == "up" && selected > 0 { + self.queue.shift(selected, selected.saturating_sub(amount)); + self.list.move_focus(-(amount as i32)); + return Ok(CommandResult::Consumed(None)); + } else if dir == "down" && selected < len.saturating_sub(1) { + self.queue + .shift(selected, min(selected + amount as usize, len - 1)); + self.list.move_focus(amount as i32); + return Ok(CommandResult::Consumed(None)); + } + } + } + self.with_view_mut(move |v| v.on_command(s, cmd, args)) .unwrap() }