diff --git a/src/main.rs b/src/main.rs index e230a40..f967f77 100644 --- a/src/main.rs +++ b/src/main.rs @@ -91,6 +91,10 @@ fn main() { let search = ui::search::SearchView::new(spotify.clone(), queue.clone()); cursive.add_fullscreen_layer(search.view); + let queuescreen = cursive.add_active_screen(); + let mut queue = ui::queue::QueueView::new(queue.clone(), spotify.clone()); + cursive.add_fullscreen_layer(queue.view.take().unwrap()); + let logscreen = cursive.add_active_screen(); let logpanel = Panel::new(logview).title("Log"); cursive.add_fullscreen_layer(logpanel); @@ -98,7 +102,13 @@ fn main() { cursive.add_global_callback(Key::F1, move |s| { s.set_screen(logscreen); }); + cursive.add_global_callback(Key::F2, move |s| { + s.set_screen(queuescreen); + queue.redraw(s); + }); + + cursive.add_global_callback(Key::F3, move |s| { s.set_screen(searchscreen); }); diff --git a/src/queue.rs b/src/queue.rs index 9c8375e..f82b92b 100644 --- a/src/queue.rs +++ b/src/queue.rs @@ -1,4 +1,5 @@ use std::collections::VecDeque; +use std::collections::vec_deque::Iter; use rspotify::spotify::model::track::FullTrack; @@ -12,10 +13,16 @@ impl Queue { queue: VecDeque::new(), } } + pub fn remove(&mut self, index: usize) -> Option { + self.queue.remove(index) + } pub fn enqueue(&mut self, track: FullTrack) { self.queue.push_back(track); } pub fn dequeue(&mut self) -> Option { self.queue.pop_front() } + pub fn iter(&self) -> Iter { + self.queue.iter() + } } diff --git a/src/ui/mod.rs b/src/ui/mod.rs index a557bff..843100f 100644 --- a/src/ui/mod.rs +++ b/src/ui/mod.rs @@ -1 +1,2 @@ +pub mod queue; pub mod search; diff --git a/src/ui/queue.rs b/src/ui/queue.rs new file mode 100644 index 0000000..7bac246 --- /dev/null +++ b/src/ui/queue.rs @@ -0,0 +1,64 @@ +use cursive::direction::Orientation; +use cursive::traits::Boxable; +use cursive::traits::Identifiable; +use cursive::views::*; +use cursive::Cursive; + +use std::sync::Arc; +use std::sync::Mutex; + +use librespot::core::spotify_id::SpotifyId; + +use queue::Queue; +use spotify::Spotify; + +pub struct QueueView { + pub view: Option>, + queue: Arc>, + spotify: Arc, +} + +impl QueueView { + pub fn new(queue: Arc>, spotify: Arc) -> QueueView { + let queuelist = ListView::new().with_id("queue_list").full_width(); + let scrollable = ScrollView::new(queuelist).full_width().full_height(); + let layout = LinearLayout::new(Orientation::Vertical).child(scrollable); + let panel = Panel::new(layout).title("Queue"); + + QueueView { + view: Some(panel), + queue: queue, + spotify: spotify + } + } + + pub fn redraw(&self, s: &mut Cursive) { + let mut queuelist: ViewRef = s.find_id("queue_list").unwrap(); + queuelist.clear(); + + let queue_ref = self.queue.clone(); + let queue = self.queue.lock().unwrap(); + for (index, track) in queue.iter().enumerate() { + let artists = track + .artists + .iter() + .map(|ref artist| artist.name.clone()) + .collect::>() + .join(", "); + let formatted = format!("{} - {}", artists, track.name); + + let trackid = SpotifyId::from_base62(&track.id).expect("could not load track"); + let s = self.spotify.clone(); + + let queue_ref = queue_ref.clone(); + let button = Button::new_raw(formatted, move |_cursive| { + s.load(trackid); + s.play(); + queue_ref.lock().unwrap().remove(index); + // TODO: update view representation, preferably, queue changes + // cause a view refresh + }); + queuelist.add_child("", button); + } + } +}