From 204cb18410c7e116e38bdf073d3e18243509dbf1 Mon Sep 17 00:00:00 2001 From: Henrik Friedrichsen Date: Tue, 26 Feb 2019 23:30:16 +0100 Subject: [PATCH] implement preliminary queue view this approach needs some (re)work, as the UI is not fully sync'd with the data, yet. it'd probably be better to have an event system triggered by the queue, that will cause a UI refresh or similar. --- src/main.rs | 10 ++++++++ src/queue.rs | 7 ++++++ src/ui/mod.rs | 1 + src/ui/queue.rs | 64 +++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 82 insertions(+) create mode 100644 src/ui/queue.rs 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); + } + } +}