use std::sync::Arc; use cursive::align::HAlign; use cursive::theme::ColorStyle; use cursive::traits::View; use cursive::vec::Vec2; use cursive::Printer; use unicode_width::UnicodeWidthStr; use spotify::{PlayerStatus, Spotify}; pub struct StatusBar { spotify: Arc, } impl StatusBar { pub fn new(spotify: Arc) -> StatusBar { StatusBar { spotify: spotify } } } impl View for StatusBar { fn draw(&self, printer: &Printer<'_, '_>) { if printer.size.x == 0 { return; } let style_bar = ColorStyle::secondary(); let style = ColorStyle::title_secondary(); printer.print( (0, 0), &vec![' '; printer.size.x].into_iter().collect::(), ); printer.with_color(style, |printer| { printer.print( (0, 1), &vec![' '; printer.size.x].into_iter().collect::(), ); }); let state_icon = match self.spotify.get_current_status() { PlayerStatus::Playing => " ▶ ", PlayerStatus::Paused => " ▮▮ ", PlayerStatus::Stopped => " ◼ ", } .to_string(); printer.with_color(style, |printer| { printer.print((0, 1), &state_icon); }); if let Some(ref t) = self.spotify.get_current_track() { let name = format!( "{} - {}", t.artists .iter() .map(|ref artist| artist.name.clone()) .collect::>() .join(", "), t.name ) .to_string(); let minutes = t.duration_ms / 60000; let seconds = (t.duration_ms % 60000) / 1000; let formatted_duration = format!("{:02}:{:02}", minutes, seconds); let elapsed = self.spotify.get_current_progress(); let formatted_elapsed = format!( "{:02}:{:02}", elapsed.as_secs() / 60, elapsed.as_secs() % 60 ); let duration = format!("{} / {} ", formatted_elapsed, formatted_duration); let offset = HAlign::Right.get_offset(duration.width(), printer.size.x); printer.with_color(style, |printer| { printer.print((4, 1), &name); printer.print((offset, 1), &duration); }); printer.with_color(style_bar, |printer| { printer.print((0, 0), &"—".repeat(printer.size.x)); let duration_width = (((printer.size.x as u32) * (elapsed.as_millis() as u32)) / t.duration_ms) as usize; printer.print((0, 0), &format!("{}{}", "=".repeat(duration_width), ">")); }); } else { printer.with_color(style_bar, |printer| { printer.print((0, 0), &"—".repeat(printer.size.x)); }); } } fn required_size(&mut self, constraint: Vec2) -> Vec2 { Vec2::new(constraint.x, 2) } }