обновление
This commit is contained in:
130
src/ui.rs
130
src/ui.rs
@@ -1,7 +1,8 @@
|
||||
use ratatui::prelude::*;
|
||||
use ratatui::widgets::{Block, Borders, Gauge, List, ListItem, Paragraph};
|
||||
|
||||
use crate::app::App;
|
||||
use crate::app::{App, Panel};
|
||||
use crate::library::{LeftRow, SortMode};
|
||||
|
||||
pub fn draw(f: &mut Frame, app: &mut App) {
|
||||
let chunks = Layout::default()
|
||||
@@ -14,29 +15,114 @@ pub fn draw(f: &mut Frame, app: &mut App) {
|
||||
])
|
||||
.split(f.area());
|
||||
|
||||
draw_track_list(f, app, chunks[0]);
|
||||
// Горизонтальное разделение верхней области: 40% слева, 60% справа
|
||||
let top = Layout::default()
|
||||
.direction(Direction::Horizontal)
|
||||
.constraints([Constraint::Percentage(40), Constraint::Percentage(60)])
|
||||
.split(chunks[0]);
|
||||
|
||||
draw_left_panel(f, app, top[0]);
|
||||
draw_right_panel(f, app, top[1]);
|
||||
draw_progress(f, app, chunks[1]);
|
||||
draw_volume(f, app, chunks[2]);
|
||||
draw_status(f, app, chunks[3]);
|
||||
}
|
||||
|
||||
fn draw_track_list(f: &mut Frame, app: &mut App, area: Rect) {
|
||||
fn draw_left_panel(f: &mut Frame, app: &App, area: Rect) {
|
||||
let items: Vec<ListItem> = app
|
||||
.tracks
|
||||
.library
|
||||
.left_rows
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(i, t)| {
|
||||
let marker = if Some(i) == app.playing_index { "♪ " } else { " " };
|
||||
ListItem::new(format!("{}{} - {}", marker, t.artist, t.title))
|
||||
.map(|row| match row {
|
||||
LeftRow::Artist { name } => ListItem::new(Line::from(vec![
|
||||
Span::styled("▶ ", Style::default().fg(Color::Yellow)),
|
||||
Span::styled(
|
||||
name.clone(),
|
||||
Style::default()
|
||||
.fg(Color::Yellow)
|
||||
.add_modifier(Modifier::BOLD),
|
||||
),
|
||||
])),
|
||||
LeftRow::Album { name } => ListItem::new(Line::from(vec![
|
||||
Span::raw(" "),
|
||||
Span::styled(name.clone(), Style::default().fg(Color::Cyan)),
|
||||
])),
|
||||
})
|
||||
.collect();
|
||||
|
||||
let title = match app.library.sort_mode {
|
||||
SortMode::ByArtist => " Артисты / Альбомы ",
|
||||
SortMode::ByFilename => " Источник ",
|
||||
};
|
||||
|
||||
let highlight = if app.active_panel == Panel::Left {
|
||||
Style::default().add_modifier(Modifier::REVERSED)
|
||||
} else {
|
||||
Style::default().add_modifier(Modifier::DIM)
|
||||
};
|
||||
|
||||
let mut list_state = ratatui::widgets::ListState::default();
|
||||
if !app.library.left_rows.is_empty() {
|
||||
list_state.select(Some(app.library.left_selected));
|
||||
}
|
||||
|
||||
let list = List::new(items)
|
||||
.block(Block::default().borders(Borders::ALL).title(" Треки "))
|
||||
.highlight_style(Style::default().add_modifier(Modifier::REVERSED))
|
||||
.block(Block::default().borders(Borders::ALL).title(title))
|
||||
.highlight_style(highlight)
|
||||
.highlight_symbol("> ");
|
||||
|
||||
f.render_stateful_widget(list, area, &mut app.list_state);
|
||||
f.render_stateful_widget(list, area, &mut list_state);
|
||||
}
|
||||
|
||||
fn draw_right_panel(f: &mut Frame, app: &App, area: Rect) {
|
||||
let indices = app.library.current_right_indices();
|
||||
|
||||
let items: Vec<ListItem> = indices
|
||||
.iter()
|
||||
.map(|&idx| {
|
||||
let is_playing = Some(idx) == app.playing_index;
|
||||
let marker = if is_playing { "♪ " } else { " " };
|
||||
|
||||
let (title, num) = match app.library.track(idx) {
|
||||
Some(t) => (
|
||||
t.title.clone(),
|
||||
t.track_number
|
||||
.map(|n| format!("{:02}. ", n))
|
||||
.unwrap_or_default(),
|
||||
),
|
||||
None => ("<unknown>".into(), String::new()),
|
||||
};
|
||||
|
||||
let style = if is_playing {
|
||||
Style::default().fg(Color::Green)
|
||||
} else {
|
||||
Style::default()
|
||||
};
|
||||
|
||||
ListItem::new(Line::from(vec![
|
||||
Span::raw(marker),
|
||||
Span::styled(format!("{}{}", num, title), style),
|
||||
]))
|
||||
})
|
||||
.collect();
|
||||
|
||||
let highlight = if app.active_panel == Panel::Right {
|
||||
Style::default().add_modifier(Modifier::REVERSED)
|
||||
} else {
|
||||
Style::default().add_modifier(Modifier::DIM)
|
||||
};
|
||||
|
||||
let mut list_state = ratatui::widgets::ListState::default();
|
||||
if !indices.is_empty() {
|
||||
list_state.select(Some(app.library.right_selected));
|
||||
}
|
||||
|
||||
let list = List::new(items)
|
||||
.block(Block::default().borders(Borders::ALL).title(" Треки "))
|
||||
.highlight_style(highlight)
|
||||
.highlight_symbol("> ");
|
||||
|
||||
f.render_stateful_widget(list, area, &mut list_state);
|
||||
}
|
||||
|
||||
fn draw_progress(f: &mut Frame, app: &App, area: Rect) {
|
||||
@@ -53,8 +139,10 @@ fn draw_progress(f: &mut Frame, app: &App, area: Rect) {
|
||||
.ratio(ratio)
|
||||
.label(format!(
|
||||
"{:02}:{:02} / {:02}:{:02}",
|
||||
pos.as_secs() / 60, pos.as_secs() % 60,
|
||||
total.as_secs() / 60, total.as_secs() % 60,
|
||||
pos.as_secs() / 60,
|
||||
pos.as_secs() % 60,
|
||||
total.as_secs() / 60,
|
||||
total.as_secs() % 60,
|
||||
));
|
||||
|
||||
f.render_widget(gauge, area);
|
||||
@@ -63,12 +151,20 @@ fn draw_progress(f: &mut Frame, app: &App, area: Rect) {
|
||||
fn draw_volume(f: &mut Frame, app: &App, area: Rect) {
|
||||
let vol = app.player.volume();
|
||||
let ratio = (vol as f64 / 2.0).clamp(0.0, 1.0);
|
||||
let color = if vol > 1.0 { Color::Yellow }
|
||||
else if vol > 0.5 { Color::Cyan }
|
||||
else { Color::Blue };
|
||||
let color = if vol > 1.0 {
|
||||
Color::Yellow
|
||||
} else if vol > 0.5 {
|
||||
Color::Cyan
|
||||
} else {
|
||||
Color::Blue
|
||||
};
|
||||
|
||||
let gauge = Gauge::default()
|
||||
.block(Block::default().borders(Borders::ALL).title(" Громкость (+/-) "))
|
||||
.block(
|
||||
Block::default()
|
||||
.borders(Borders::ALL)
|
||||
.title(" Громкость (+/-) "),
|
||||
)
|
||||
.gauge_style(Style::default().fg(color))
|
||||
.ratio(ratio)
|
||||
.label(format!("{}%", (vol * 100.0) as u32));
|
||||
|
||||
Reference in New Issue
Block a user