Pretify queue widget

This commit is contained in:
2025-03-30 23:36:25 +02:00
parent affc4899f7
commit cd16a3b340
5 changed files with 51 additions and 18 deletions

7
Cargo.lock generated
View File

@@ -37,6 +37,7 @@ dependencies = [
"dotenv",
"figment",
"futures",
"humantime",
"itertools 0.14.0",
"md5",
"rand",
@@ -780,6 +781,12 @@ version = "1.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87"
[[package]]
name = "humantime"
version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b112acc8b3adf4b107a8ec20977da0273a8c386765a3ec0229bd500a1443f9f"
[[package]]
name = "hyper"
version = "1.6.0"

View File

@@ -23,6 +23,7 @@ directories = "6"
ratatui = "0.29"
crossterm = { version = "0.28.1", features = ["event-stream", "serde"] }
humantime = "2.2"
tokio = { version = "1.43", features = ["macros", "rt"] }
tokio-stream = "0.1"

View File

@@ -160,7 +160,11 @@ impl App {
Action::Init => self.tx.send(Action::RandomQueue)?,
Action::TryPlaySong(id) => self.player.try_play(id, self.client.clone())?,
Action::AddToSink(id) => {
self.player.add_to_sink(id)?;
let res = self.player.add_to_sink(id);
if res.is_err(){
self.tx.send(Action::TrackEnded)?;
}
res?
}
Action::ScrollUp => {
if self.mode == Mode::Queue {

View File

@@ -84,6 +84,10 @@ impl Player {
/// Add the song specified by the index to the sink
pub fn add_to_sink(&mut self, index: usize) -> Result<()> {
if self.sink.empty() {
// set only if is first to be added to sink
self.current_playing = index;
}
// Retrieve file from index
let id = self.songs_list.lock().unwrap()[index].id.clone();
let mut path = config::temp_dir();
@@ -94,11 +98,6 @@ impl Player {
// This help having a constant volume
let agc_source = decoder.automatic_gain_control(1.0, 4.0, 0.005, 5.0);
if self.sink.empty() {
// set only if is first to be added to sink
self.current_playing = index;
}
self.sink.append(agc_source);
debug!("{id} added to sink");

View File

@@ -1,3 +1,4 @@
use humantime::format_duration;
use itertools::Itertools;
use ratatui::{layout::Constraint::*, prelude::*, widgets::*};
use ratatui::{
@@ -5,6 +6,7 @@ use ratatui::{
widgets::{StatefulWidget, Table, TableState},
};
use std::sync::{Arc, Mutex};
use std::time::Duration;
use style::Styled;
use subsonic_types::response::Child;
@@ -29,13 +31,10 @@ impl StatefulWidget for &Queue {
type State = TableState;
fn render(self, area: Rect, buf: &mut Buffer, state: &mut Self::State) {
if !self.songs_list.lock().unwrap().is_empty() {
let vertical_pad = |line| Text::from(vec!["".into(), line, "".into()]);
let header_cells = ["#", "Title", "Artist", "Duration"]
.map(|h| h.bold().into())
.map(vertical_pad);
let header = Row::new(header_cells).height(3);
let header_cells = ["#", "Title", "Artist", "Duration"].map(|h| h.bold());
let header = Row::new(header_cells).height(2);
let column_widths = [Max(4), Max(20), Max(20), Max(6)];
let column_widths = [Max(4), Min(20), Min(20), Max(8)];
let list = self.songs_list.lock().unwrap();
let rows = list
@@ -50,14 +49,36 @@ impl StatefulWidget for &Queue {
})
.collect_vec();
let queue_duration = list.iter().fold(Duration::ZERO, |mut acc, song| {
acc += song
.duration
.map(|sec| sec.to_duration())
.unwrap_or(Duration::ZERO);
acc
});
let block = Block::new()
.border_type(BorderType::Rounded)
.borders(Borders::all())
.border_style(Style::default().fg(Color::White))
.padding(Padding::right(1))
.title("Queue")
.title(
Line::from(format!(
"| Total {} songs | {} |",
list.len(),
format_duration(queue_duration)
))
.left_aligned(),
);
let table = Table::new(rows, column_widths)
.header(header)
.column_spacing(3)
.column_spacing(2)
.highlight_spacing(HighlightSpacing::Always)
.row_highlight_style(Style::new().reversed())
.column_highlight_style(Style::new().red())
.cell_highlight_style(Style::new().blue())
.highlight_symbol(">>");
.row_highlight_style(Style::new().fg(Color::Magenta))
.highlight_symbol(">>")
.block(block);
StatefulWidget::render(table, area, buf, state);
} else {
@@ -72,6 +93,7 @@ fn row_from_song(index: usize, song: &Child) -> Row {
Text::from(index.to_string()),
Text::from(song.title.clone()),
Text::from(song.artist.clone().unwrap()),
Text::from(format!("{:0>2}:{:0>2}", duration / 60, duration % 60)),
Text::from(format!("{:0>2}:{:0>2}", duration / 60, duration % 60))
.alignment(Alignment::Right),
])
}