add metadata in queue list

This commit is contained in:
krolxon 2024-04-29 16:27:23 +05:30
parent c61b0503c7
commit bf531facb0
5 changed files with 134 additions and 116 deletions

View File

@ -38,6 +38,6 @@ A MPD client in Rust
- [x] add to playlists
- [x] search for songs
- [x] Humantime format
- [x] metadata based tree view
- [ ] view playlist
- [ ] change playlist name
- [ ] metadata based tree view

View File

@ -98,24 +98,27 @@ impl FileBrowser {
// Go to next item in filetree
pub fn next(&mut self) {
// if self.selected < self.filetree.len() - 1 {
// self.selected += 1;
// }
if self.selected == self.filetree.len() - 1 {
self.selected = 0;
} else {
if self.selected < self.filetree.len() - 1 {
self.selected += 1;
}
// if self.selected == self.filetree.len() - 1 {
// self.selected = 0;
// } else {
// self.selected += 1;
// }
}
/// Go to previous item in filetree
pub fn prev(&mut self) {
if self.selected == 0 {
self.selected = self.filetree.len() - 1;
} else {
if self.selected != 0 {
self.selected -= 1;
}
// if self.selected == 0 {
// self.selected = self.filetree.len() - 1;
// } else {
// self.selected -= 1;
// }
}
pub fn handle_go_back(&mut self, conn: &mut Connection) -> AppResult<()> {

View File

@ -62,7 +62,6 @@ pub fn handle_key_events(key_event: KeyEvent, app: &mut App) -> AppResult<()> {
}
}
}
}
match key_event.code {
@ -200,7 +199,6 @@ pub fn handle_key_events(key_event: KeyEvent, app: &mut App) -> AppResult<()> {
app.conn
.load_playlist(app.pl_list.list.get(app.pl_list.index).unwrap())?;
}
}
app.conn.update_status();
}
@ -279,6 +277,7 @@ pub fn handle_key_events(key_event: KeyEvent, app: &mut App) -> AppResult<()> {
KeyCode::Char('>') => {
if !app.queue_list.list.is_empty() {
app.conn.conn.next()?;
app.update_queue();
}
}
@ -286,6 +285,7 @@ pub fn handle_key_events(key_event: KeyEvent, app: &mut App) -> AppResult<()> {
KeyCode::Char('<') => {
if !app.queue_list.list.is_empty() {
app.conn.conn.prev()?;
app.update_queue();
}
}

View File

@ -14,30 +14,36 @@ impl<T> ContentList<T> {
// Go to next item in list
pub fn next(&mut self) {
// if self.index < self.list.len() - 1 {
// self.index += 1;
// }
let len = self.list.len();
if len != 0 {
if self.index == self.list.len() - 1 {
self.index = 0;
} else {
if self.index < len - 1 {
self.index += 1;
}
}
// let len = self.list.len();
// if len != 0 {
// if self.index == self.list.len() - 1 {
// self.index = 0;
// } else {
// self.index += 1;
// }
// }
}
/// Go to previous item in list
pub fn prev(&mut self) {
if self.index == 0 {
let len = self.list.len();
if len != 0 {
self.index = len - 1;
}
} else {
if self.index != 0 {
self.index -= 1;
}
// if self.index == 0 {
// let len = self.list.len();
// if len != 0 {
// self.index = len - 1;
// }
// } else {
// self.index -= 1;
// }
}
pub fn reset_index(&mut self) {

181
src/ui.rs
View File

@ -1,6 +1,7 @@
use std::time::Duration;
use crate::app::{App, SelectedTab};
use mpd::Song;
use ratatui::{
prelude::*,
widgets::{block::Title, *},
@ -32,8 +33,7 @@ pub fn render(app: &mut App, frame: &mut Frame) {
match app.selected_tab {
SelectedTab::Queue => draw_queue(frame, app, layout[0]),
SelectedTab::Playlists => draw_playlists(frame, app, layout[0]),
SelectedTab::DirectoryBrowser => draw_song_browser(frame, app, layout[0]),
// SelectedTab::SongBrowser => draw_song_browser(frame, app, layout[0]),
SelectedTab::DirectoryBrowser => draw_directory_browser(frame, app, layout[0]),
}
match app.inputmode {
@ -50,63 +50,8 @@ pub fn render(app: &mut App, frame: &mut Frame) {
}
}
/// Draws the file tree browser
/// Draws the directory
fn draw_directory_browser(frame: &mut Frame, app: &mut App, size: Rect) {
let mut song_state = ListState::default();
let total_songs = app.conn.conn.stats().unwrap().songs.to_string();
let mut list: Vec<ListItem> = vec![];
for (t, s) in app.browser.filetree.iter() {
if t == "file" {
let mut status: bool = false;
for sn in app.queue_list.list.iter() {
if sn.contains(s) {
status = true;
}
}
if status {
list.push(ListItem::new(s.clone().magenta().bold()));
} else {
// list.push(ListItem::new(s.clone()));
list.push(ListItem::new(s.clone()));
}
} else {
list.push(ListItem::new(Line::styled(
format!("[{}]", *s),
Style::default(),
)));
}
}
let list = List::new(list)
.block(
Block::default()
.title(format!("Directory Browser: {}", app.browser.path.clone()).bold())
.title(
Title::from(format!("Total Songs: {}", total_songs).bold().green())
.alignment(Alignment::Center),
)
.title(
Title::from(format!("Volume: {}%", app.conn.volume).bold().green())
.alignment(Alignment::Right),
)
.borders(Borders::ALL),
)
.highlight_style(
Style::new()
.fg(Color::Cyan)
.bg(Color::Black)
.add_modifier(Modifier::BOLD)
.add_modifier(Modifier::REVERSED),
)
.highlight_symbol(">>")
.repeat_highlight_symbol(true)
.scroll_padding(20);
song_state.select(Some(app.browser.selected));
frame.render_stateful_widget(list, size, &mut song_state);
}
/// Draws the song browser
fn draw_song_browser(frame: &mut Frame, app: &mut App, size: Rect) {
let total_songs = app.conn.conn.stats().unwrap().songs.to_string();
let rows = app.browser.filetree.iter().enumerate().map(|(i, (t, s))| {
@ -149,7 +94,7 @@ fn draw_song_browser(frame: &mut Frame, app: &mut App, size: Rect) {
Cell::from(track.green()),
Cell::from(title),
Cell::from(album),
Cell::from(time.to_string().red()),
Cell::from(time.to_string().magenta()),
]);
row.magenta().bold()
} else {
@ -158,7 +103,7 @@ fn draw_song_browser(frame: &mut Frame, app: &mut App, size: Rect) {
Cell::from(track.green()),
Cell::from(title),
Cell::from(album),
Cell::from(time.to_string().red()),
Cell::from(time.to_string().magenta()),
]);
row
}
@ -178,9 +123,9 @@ fn draw_song_browser(frame: &mut Frame, app: &mut App, size: Rect) {
let table = Table::new(
rows,
[
Constraint::Percentage(33),
Constraint::Percentage(20),
Constraint::Percentage(3),
Constraint::Percentage(30),
Constraint::Min(30),
Constraint::Percentage(30),
Constraint::Percentage(3),
],
@ -205,7 +150,8 @@ fn draw_song_browser(frame: &mut Frame, app: &mut App, size: Rect) {
.bg(Color::Black),
)
.highlight_symbol(">>")
.header(header);
.header(header)
.flex(layout::Flex::Legacy);
state.select(Some(app.browser.selected));
frame.render_stateful_widget(table, size, &mut state);
@ -213,8 +159,79 @@ fn draw_song_browser(frame: &mut Frame, app: &mut App, size: Rect) {
/// draws playing queue
fn draw_queue(frame: &mut Frame, app: &mut App, size: Rect) {
let mut queue_state = ListState::default();
let title = Block::default()
let rows = app.queue_list.list.iter().map(|s| {
// metadata
let song = app
.conn
.conn
.lsinfo(&Song {
file: app.conn.get_full_path(&s).unwrap_or_default(),
..Default::default()
})
.unwrap_or_default();
let song = song.get(0).unwrap();
let title = song.clone().title.unwrap_or_else(|| song.clone().file);
let artist = song.clone().artist.unwrap_or_default().cyan();
let album = song
.tags
.iter()
.filter(|(x, _)| x == "Album")
.map(|(_, l)| l.clone())
.collect::<Vec<String>>()
.join("");
let track = song
.tags
.iter()
.filter(|(x, _)| x == "Track")
.map(|(_, l)| l.clone())
.collect::<Vec<String>>()
.join("");
let time = humantime::format_duration(
song.clone().duration.unwrap_or_else(|| Duration::new(0, 0)),
);
if s.contains(&app.conn.current_song.file) {
let row = Row::new(vec![
Cell::from(artist),
Cell::from(track.green()),
Cell::from(title),
Cell::from(album),
Cell::from(time.to_string().magenta()),
]);
row.magenta().bold()
} else {
let row = Row::new(vec![
Cell::from(artist),
Cell::from(track.green()),
Cell::from(title),
Cell::from(album),
Cell::from(time.to_string().magenta()),
]);
row
}
});
let mut state = TableState::new();
let header = ["Artist", "Track", "Title", "Album", "Time"]
.into_iter()
.map(Cell::from)
.collect::<Row>()
.bold()
.height(1);
let table = Table::new(
rows,
[
Constraint::Percentage(20),
Constraint::Percentage(3),
Constraint::Min(30),
Constraint::Percentage(30),
Constraint::Percentage(3),
],
)
.block(
Block::default()
.title(Title::from("Play Queue".green().bold()))
.title(Title::from(
format!("({} items)", app.queue_list.list.len()).bold(),
@ -222,29 +239,21 @@ fn draw_queue(frame: &mut Frame, app: &mut App, size: Rect) {
.title(
Title::from(format!("Volume: {}%", app.conn.volume).bold().green())
.alignment(Alignment::Right),
);
let mut items: Vec<ListItem> = vec![];
for item in app.queue_list.list.iter() {
if item.contains(&app.conn.current_song.file) {
items.push(ListItem::new(item.clone().magenta().bold()))
} else {
items.push(ListItem::new(item.clone()));
}
}
let list = List::new(items)
.block(title.borders(Borders::ALL))
.highlight_style(
Style::new()
.fg(Color::Cyan)
.bg(Color::Black)
.add_modifier(Modifier::BOLD)
.add_modifier(Modifier::REVERSED),
)
.highlight_symbol(">>");
.borders(Borders::ALL),
)
.highlight_style(
Style::default()
.add_modifier(Modifier::REVERSED)
.fg(Color::Cyan)
.bg(Color::Black),
)
.highlight_symbol(">>")
.header(header)
.flex(layout::Flex::Legacy);
queue_state.select(Some(app.queue_list.index));
frame.render_stateful_widget(list, size, &mut queue_state);
state.select(Some(app.queue_list.index));
frame.render_stateful_widget(table, size, &mut state);
}
/// draws all playlists