Krolyxon
Commit bf531fa

rmptuibf531fa

add metadata in queue list

Author
krolxon
Date
2024-04-29 16:27 +0530
Parent
c61b050
Commit
bf531facb0349c528f6f8965d05257a46a7f3fd3

+134 −116

5 files changed

  1. M README.md +1 −1
  2. M src/browser.rs +13 −10
  3. M src/handler.rs +2 −2
  4. M src/list.rs +19 −13
  5. M src/ui.rs +99 −90
M README.md View
@@ -38,6 +38,6 @@ A MPD client in Rust
3838 - [x] add to playlists
3939 - [x] search for songs
4040 - [x] Humantime format
41+- [x] metadata based tree view
4142 - [ ] view playlist
4243 - [ ] change playlist name
43−- [ ] metadata based tree view
M src/browser.rs View
@@ -98,24 +98,27 @@ impl FileBrowser {
9898
9999 // Go to next item in filetree
100100 pub fn next(&mut self) {
101− // if self.selected < self.filetree.len() - 1 {
102− // self.selected += 1;
103− // }
104−
105− if self.selected == self.filetree.len() - 1 {
106− self.selected = 0;
107− } else {
101+ if self.selected < self.filetree.len() - 1 {
108102 self.selected += 1;
109103 }
104+
105+ // if self.selected == self.filetree.len() - 1 {
106+ // self.selected = 0;
107+ // } else {
108+ // self.selected += 1;
109+ // }
110110 }
111111
112112 /// Go to previous item in filetree
113113 pub fn prev(&mut self) {
114− if self.selected == 0 {
115− self.selected = self.filetree.len() - 1;
116− } else {
114+ if self.selected != 0 {
117115 self.selected -= 1;
118116 }
117+ // if self.selected == 0 {
118+ // self.selected = self.filetree.len() - 1;
119+ // } else {
120+ // self.selected -= 1;
121+ // }
119122 }
120123
121124 pub fn handle_go_back(&mut self, conn: &mut Connection) -> AppResult<()> {
M src/handler.rs View
@@ -62,7 +62,6 @@ pub fn handle_key_events(key_event: KeyEvent, app: &mut App) -> AppResult<()> {
6262 }
6363 }
6464 }
65−
6665 }
6766
6867 match key_event.code {
@@ -200,7 +199,6 @@ pub fn handle_key_events(key_event: KeyEvent, app: &mut App) -> AppResult<()> {
200199 app.conn
201200 .load_playlist(app.pl_list.list.get(app.pl_list.index).unwrap())?;
202201 }
203−
204202 }
205203 app.conn.update_status();
206204 }
@@ -279,6 +277,7 @@ pub fn handle_key_events(key_event: KeyEvent, app: &mut App) -> AppResult<()> {
279277 KeyCode::Char('>') => {
280278 if !app.queue_list.list.is_empty() {
281279 app.conn.conn.next()?;
280+ app.update_queue();
282281 }
283282 }
284283
@@ -286,6 +285,7 @@ pub fn handle_key_events(key_event: KeyEvent, app: &mut App) -> AppResult<()> {
286285 KeyCode::Char('<') => {
287286 if !app.queue_list.list.is_empty() {
288287 app.conn.conn.prev()?;
288+ app.update_queue();
289289 }
290290 }
291291
M src/list.rs View
@@ -14,30 +14,36 @@ impl<T> ContentList<T> {
1414
1515 // Go to next item in list
1616 pub fn next(&mut self) {
17− // if self.index < self.list.len() - 1 {
18− // self.index += 1;
19− // }
20−
2117 let len = self.list.len();
2218 if len != 0 {
23− if self.index == self.list.len() - 1 {
24− self.index = 0;
25− } else {
19+ if self.index < len - 1 {
2620 self.index += 1;
2721 }
2822 }
23+
24+ // let len = self.list.len();
25+ // if len != 0 {
26+ // if self.index == self.list.len() - 1 {
27+ // self.index = 0;
28+ // } else {
29+ // self.index += 1;
30+ // }
31+ // }
2932 }
3033
3134 /// Go to previous item in list
3235 pub fn prev(&mut self) {
33− if self.index == 0 {
34− let len = self.list.len();
35− if len != 0 {
36− self.index = len - 1;
37− }
38− } else {
36+ if self.index != 0 {
3937 self.index -= 1;
4038 }
39+ // if self.index == 0 {
40+ // let len = self.list.len();
41+ // if len != 0 {
42+ // self.index = len - 1;
43+ // }
44+ // } else {
45+ // self.index -= 1;
46+ // }
4147 }
4248
4349 pub fn reset_index(&mut self) {
M src/ui.rs View
@@ -1,6 +1,7 @@
11 use std::time::Duration;
22
33 use crate::app::{App, SelectedTab};
4+use mpd::Song;
45 use ratatui::{
56 prelude::*,
67 widgets::{block::Title, *},
@@ -32,8 +33,7 @@ pub fn render(app: &mut App, frame: &mut Frame) {
3233 match app.selected_tab {
3334 SelectedTab::Queue => draw_queue(frame, app, layout[0]),
3435 SelectedTab::Playlists => draw_playlists(frame, app, layout[0]),
35− SelectedTab::DirectoryBrowser => draw_song_browser(frame, app, layout[0]),
36− // SelectedTab::SongBrowser => draw_song_browser(frame, app, layout[0]),
36+ SelectedTab::DirectoryBrowser => draw_directory_browser(frame, app, layout[0]),
3737 }
3838
3939 match app.inputmode {
@@ -50,63 +50,8 @@ pub fn render(app: &mut App, frame: &mut Frame) {
5050 }
5151 }
5252
53−/// Draws the file tree browser
53+/// Draws the directory
5454 fn draw_directory_browser(frame: &mut Frame, app: &mut App, size: Rect) {
55− let mut song_state = ListState::default();
56− let total_songs = app.conn.conn.stats().unwrap().songs.to_string();
57− let mut list: Vec<ListItem> = vec![];
58− for (t, s) in app.browser.filetree.iter() {
59− if t == "file" {
60− let mut status: bool = false;
61− for sn in app.queue_list.list.iter() {
62− if sn.contains(s) {
63− status = true;
64− }
65− }
66− if status {
67− list.push(ListItem::new(s.clone().magenta().bold()));
68− } else {
69− // list.push(ListItem::new(s.clone()));
70− list.push(ListItem::new(s.clone()));
71− }
72− } else {
73− list.push(ListItem::new(Line::styled(
74− format!("[{}]", *s),
75− Style::default(),
76− )));
77− }
78− }
79− let list = List::new(list)
80− .block(
81− Block::default()
82− .title(format!("Directory Browser: {}", app.browser.path.clone()).bold())
83− .title(
84− Title::from(format!("Total Songs: {}", total_songs).bold().green())
85− .alignment(Alignment::Center),
86− )
87− .title(
88− Title::from(format!("Volume: {}%", app.conn.volume).bold().green())
89− .alignment(Alignment::Right),
90− )
91− .borders(Borders::ALL),
92− )
93− .highlight_style(
94− Style::new()
95− .fg(Color::Cyan)
96− .bg(Color::Black)
97− .add_modifier(Modifier::BOLD)
98− .add_modifier(Modifier::REVERSED),
99− )
100− .highlight_symbol(">>")
101− .repeat_highlight_symbol(true)
102− .scroll_padding(20);
103−
104− song_state.select(Some(app.browser.selected));
105− frame.render_stateful_widget(list, size, &mut song_state);
106−}
107−
108−/// Draws the song browser
109−fn draw_song_browser(frame: &mut Frame, app: &mut App, size: Rect) {
11055 let total_songs = app.conn.conn.stats().unwrap().songs.to_string();
11156
11257 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) {
14994 Cell::from(track.green()),
15095 Cell::from(title),
15196 Cell::from(album),
152− Cell::from(time.to_string().red()),
97+ Cell::from(time.to_string().magenta()),
15398 ]);
15499 row.magenta().bold()
155100 } else {
@@ -158,7 +103,7 @@ fn draw_song_browser(frame: &mut Frame, app: &mut App, size: Rect) {
158103 Cell::from(track.green()),
159104 Cell::from(title),
160105 Cell::from(album),
161− Cell::from(time.to_string().red()),
106+ Cell::from(time.to_string().magenta()),
162107 ]);
163108 row
164109 }
@@ -178,9 +123,9 @@ fn draw_song_browser(frame: &mut Frame, app: &mut App, size: Rect) {
178123 let table = Table::new(
179124 rows,
180125 [
181− Constraint::Percentage(33),
126+ Constraint::Percentage(20),
182127 Constraint::Percentage(3),
183− Constraint::Percentage(30),
128+ Constraint::Min(30),
184129 Constraint::Percentage(30),
185130 Constraint::Percentage(3),
186131 ],
@@ -205,7 +150,8 @@ fn draw_song_browser(frame: &mut Frame, app: &mut App, size: Rect) {
205150 .bg(Color::Black),
206151 )
207152 .highlight_symbol(">>")
208− .header(header);
153+ .header(header)
154+ .flex(layout::Flex::Legacy);
209155
210156 state.select(Some(app.browser.selected));
211157 frame.render_stateful_widget(table, size, &mut state);
@@ -213,38 +159,101 @@ fn draw_song_browser(frame: &mut Frame, app: &mut App, size: Rect) {
213159
214160 /// draws playing queue
215161 fn draw_queue(frame: &mut Frame, app: &mut App, size: Rect) {
216− let mut queue_state = ListState::default();
217− let title = Block::default()
218− .title(Title::from("Play Queue".green().bold()))
219− .title(Title::from(
220− format!("({} items)", app.queue_list.list.len()).bold(),
221− ))
222− .title(
223− Title::from(format!("Volume: {}%", app.conn.volume).bold().green())
224− .alignment(Alignment::Right),
162+ let rows = app.queue_list.list.iter().map(|s| {
163+ // metadata
164+ let song = app
165+ .conn
166+ .conn
167+ .lsinfo(&Song {
168+ file: app.conn.get_full_path(&s).unwrap_or_default(),
169+ ..Default::default()
170+ })
171+ .unwrap_or_default();
172+ let song = song.get(0).unwrap();
173+ let title = song.clone().title.unwrap_or_else(|| song.clone().file);
174+ let artist = song.clone().artist.unwrap_or_default().cyan();
175+ let album = song
176+ .tags
177+ .iter()
178+ .filter(|(x, _)| x == "Album")
179+ .map(|(_, l)| l.clone())
180+ .collect::<Vec<String>>()
181+ .join("");
182+
183+ let track = song
184+ .tags
185+ .iter()
186+ .filter(|(x, _)| x == "Track")
187+ .map(|(_, l)| l.clone())
188+ .collect::<Vec<String>>()
189+ .join("");
190+
191+ let time = humantime::format_duration(
192+ song.clone().duration.unwrap_or_else(|| Duration::new(0, 0)),
225193 );
226194
227− let mut items: Vec<ListItem> = vec![];
228− for item in app.queue_list.list.iter() {
229− if item.contains(&app.conn.current_song.file) {
230− items.push(ListItem::new(item.clone().magenta().bold()))
195+ if s.contains(&app.conn.current_song.file) {
196+ let row = Row::new(vec![
197+ Cell::from(artist),
198+ Cell::from(track.green()),
199+ Cell::from(title),
200+ Cell::from(album),
201+ Cell::from(time.to_string().magenta()),
202+ ]);
203+ row.magenta().bold()
231204 } else {
232− items.push(ListItem::new(item.clone()));
205+ let row = Row::new(vec![
206+ Cell::from(artist),
207+ Cell::from(track.green()),
208+ Cell::from(title),
209+ Cell::from(album),
210+ Cell::from(time.to_string().magenta()),
211+ ]);
212+ row
233213 }
234− }
235− let list = List::new(items)
236− .block(title.borders(Borders::ALL))
237− .highlight_style(
238− Style::new()
239− .fg(Color::Cyan)
240− .bg(Color::Black)
241− .add_modifier(Modifier::BOLD)
242− .add_modifier(Modifier::REVERSED),
243− )
244− .highlight_symbol(">>");
214+ });
215+
216+ let mut state = TableState::new();
217+ let header = ["Artist", "Track", "Title", "Album", "Time"]
218+ .into_iter()
219+ .map(Cell::from)
220+ .collect::<Row>()
221+ .bold()
222+ .height(1);
223+ let table = Table::new(
224+ rows,
225+ [
226+ Constraint::Percentage(20),
227+ Constraint::Percentage(3),
228+ Constraint::Min(30),
229+ Constraint::Percentage(30),
230+ Constraint::Percentage(3),
231+ ],
232+ )
233+ .block(
234+ Block::default()
235+ .title(Title::from("Play Queue".green().bold()))
236+ .title(Title::from(
237+ format!("({} items)", app.queue_list.list.len()).bold(),
238+ ))
239+ .title(
240+ Title::from(format!("Volume: {}%", app.conn.volume).bold().green())
241+ .alignment(Alignment::Right),
242+ )
243+ .borders(Borders::ALL),
244+ )
245+ .highlight_style(
246+ Style::default()
247+ .add_modifier(Modifier::REVERSED)
248+ .fg(Color::Cyan)
249+ .bg(Color::Black),
250+ )
251+ .highlight_symbol(">>")
252+ .header(header)
253+ .flex(layout::Flex::Legacy);
245254
246− queue_state.select(Some(app.queue_list.index));
247− frame.render_stateful_widget(list, size, &mut queue_state);
255+ state.select(Some(app.queue_list.index));
256+ frame.render_stateful_widget(table, size, &mut state);
248257 }
249258
250259 /// draws all playlists