131 lines
3.9 KiB
Rust
131 lines
3.9 KiB
Rust
use ratatui::{
|
|
prelude::*,
|
|
widgets::{block::Title, *},
|
|
};
|
|
|
|
use super::app::App;
|
|
|
|
pub fn draw<B: Backend>(f: &mut Frame<B>, app: &mut App) {
|
|
let chunks = Layout::default()
|
|
.constraints([Constraint::Min(3), Constraint::Length(2)].as_ref())
|
|
.split(f.size());
|
|
draw_playlist(f, app, chunks[0]);
|
|
draw_player(f, app, chunks[1]);
|
|
}
|
|
|
|
static PRIMARY_COLOR: Color = Color::Rgb(200, 150, 70);
|
|
static SECONDARY_COLOR: Color = Color::Rgb(200, 200, 200);
|
|
|
|
static PRIMARY_CONTRAST: Color = Color::Black;
|
|
static CLEAR_CONTRAST: Color = Color::Rgb(100, 100, 100);
|
|
|
|
fn draw_playlist<B: Backend>(f: &mut Frame<B>, app: &App, area: Rect) {
|
|
let tracks: Vec<_> = app
|
|
.queue_playlist
|
|
.playlist
|
|
.items
|
|
.iter()
|
|
.enumerate()
|
|
.map(|(index, path)| {
|
|
let selected = app
|
|
.queue_playlist
|
|
.playlist
|
|
.state
|
|
.selected()
|
|
.map_or(false, |selected| index == selected);
|
|
// let playing = app
|
|
// .player_state
|
|
// .currently_playing
|
|
// .clone()
|
|
// .map_or(false, |currently_playing| currently_playing == *path);
|
|
let playing = false;
|
|
let mut style = Style::default();
|
|
match (selected, playing) {
|
|
(true, false) => {
|
|
style.fg = Some(Color::Black);
|
|
style.bg = Some(PRIMARY_COLOR);
|
|
}
|
|
(false, true) => style.fg = Some(PRIMARY_COLOR),
|
|
(true, true) => {
|
|
style.fg = None;
|
|
style.bg = Some(PRIMARY_COLOR);
|
|
}
|
|
(_, _) => (),
|
|
}
|
|
let content = Span::from(path.to_string_lossy().to_string());
|
|
ListItem::new(content).set_style(style)
|
|
})
|
|
.collect();
|
|
let playlist = List::new(tracks)
|
|
.block(
|
|
Block::default()
|
|
.borders(Borders::ALL)
|
|
.border_style(Style::default().fg(SECONDARY_COLOR)),
|
|
)
|
|
.start_corner(Corner::TopLeft);
|
|
f.render_widget(playlist, area);
|
|
}
|
|
|
|
fn draw_player<B: Backend>(f: &mut Frame<B>, app: &App, area: Rect) {
|
|
fn decorate_bool(span: Span, value: bool) -> Span {
|
|
match value {
|
|
true => span.bg(PRIMARY_COLOR).fg(PRIMARY_CONTRAST),
|
|
false => span.fg(CLEAR_CONTRAST),
|
|
}
|
|
}
|
|
|
|
let track_title = vec![
|
|
Span::from("[ "),
|
|
Span::from("??").fg(PRIMARY_COLOR),
|
|
Span::from(" ]"),
|
|
];
|
|
|
|
let mut block = Block::default()
|
|
.borders(Borders::TOP)
|
|
.border_style(Style::default().fg(SECONDARY_COLOR))
|
|
.title(track_title);
|
|
|
|
// Horrible to look at, worse to write
|
|
let param_titles: Vec<Title> = vec![
|
|
(
|
|
app.track_change_options.next,
|
|
vec![
|
|
Span::from("NE"),
|
|
Span::from("X").underlined(),
|
|
Span::from("T"),
|
|
],
|
|
),
|
|
(
|
|
app.track_change_options.shuffle,
|
|
vec![Span::from("S").underlined(), Span::from("HUFFLE")],
|
|
),
|
|
(
|
|
app.track_change_options.repeat,
|
|
vec![Span::from("R").underlined(), Span::from("EPEAT")],
|
|
),
|
|
]
|
|
.iter()
|
|
.map(|(value, spans)| {
|
|
spans
|
|
.iter()
|
|
.map(|span| decorate_bool(span.clone(), *value))
|
|
.collect::<Vec<_>>()
|
|
})
|
|
.map(|spans| Title::from([&[Span::from(" ")], spans.as_slice(), &[Span::from(" ")]].concat()))
|
|
.collect();
|
|
|
|
for title in param_titles {
|
|
block = block.title(title);
|
|
}
|
|
|
|
let block = block.title_position(block::Position::Top);
|
|
|
|
let player = Gauge::default()
|
|
.block(block)
|
|
.gauge_style(Style::default().fg(PRIMARY_COLOR))
|
|
.ratio(0.25)
|
|
.label("[ PAUSED ]");
|
|
|
|
f.render_widget(player, area)
|
|
}
|