use filetree view instead of all song list

This commit is contained in:
krolxon 2024-04-25 14:31:50 +05:30
parent f665c4e9f3
commit 00c5c12d82
5 changed files with 158 additions and 17 deletions

View File

@ -1,5 +1,6 @@
use std::time::Duration;
use crate::browser::FileBrowser;
use crate::connection::Connection;
use crate::list::ContentList;
use mpd::Client;
@ -17,11 +18,12 @@ pub struct App {
pub queue_list: ContentList<String>,
pub pl_list: ContentList<String>,
pub selected_tab: SelectedTab,
pub browser: FileBrowser,
}
#[derive(Debug, PartialEq, Clone)]
pub enum SelectedTab {
SongList,
DirectoryBrowser,
Queue,
Playlists,
}
@ -29,9 +31,9 @@ pub enum SelectedTab {
impl SelectedTab {
fn as_usize(&self) {
match self {
SelectedTab::SongList => 0,
SelectedTab::Queue => 1,
SelectedTab::Playlists => 2,
SelectedTab::Queue => 0,
SelectedTab::Playlists => 1,
SelectedTab::DirectoryBrowser => 2,
};
}
}
@ -48,13 +50,15 @@ impl App {
let mut song_list = ContentList::new();
song_list.list = conn.songs_filenames.clone();
let browser = FileBrowser::new();
Ok(Self {
running: true,
conn,
song_list,
queue_list,
pl_list,
selected_tab: SelectedTab::SongList,
selected_tab: SelectedTab::DirectoryBrowser,
browser,
})
}
@ -62,6 +66,7 @@ impl App {
self.conn.update_state();
self.conn.update_progress();
self.update_queue();
self.browser.update_directory(&mut self.conn).unwrap();
}
pub fn quit(&mut self) {
@ -103,9 +108,9 @@ impl App {
pub fn cycle_tabls(&mut self) {
self.selected_tab = match self.selected_tab {
SelectedTab::SongList => SelectedTab::Queue,
SelectedTab::DirectoryBrowser => SelectedTab::Queue,
SelectedTab::Queue => SelectedTab::Playlists,
SelectedTab::Playlists => SelectedTab::SongList,
SelectedTab::Playlists => SelectedTab::DirectoryBrowser,
};
}
}

92
src/browser.rs Executable file
View File

@ -0,0 +1,92 @@
use mpd::Query;
use crate::{app::AppResult, connection::Connection};
#[derive(Debug)]
pub struct FileBrowser {
pub filetree: Vec<(String, String)>,
pub selected: usize,
pub prev_selected: usize,
pub path: String,
pub prev_path: String,
}
impl FileBrowser {
pub fn new() -> FileBrowser {
FileBrowser {
filetree: Vec::new(),
selected: 0,
prev_selected: 0,
path: ".".to_string(),
prev_path: ".".to_string(),
}
}
pub fn update_directory(&mut self, conn: &mut Connection) -> AppResult<()> {
self.filetree.clear();
self.filetree = conn
.conn
.listfiles(self.path.as_str())?
.into_iter()
.filter(|(f, _)| f == "directory" || f == "file")
.collect::<Vec<(String, String)>>();
Ok(())
}
// 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 {
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 {
self.selected -= 1;
}
}
pub fn handle_enter(&mut self, conn: &mut Connection) -> AppResult<()> {
let (t, path) = self.filetree.get(self.selected).unwrap();
if t == "directory" {
if path != "." {
self.prev_path = self.path.clone();
self.path = path.to_string();
self.update_directory(conn)?;
self.prev_selected = self.selected;
self.selected = 0;
}
} else {
let list = conn
.songs_filenames
.iter()
.map(|f| f.as_str())
.collect::<Vec<&str>>();
let (filename, _) = rust_fuzzy_search::fuzzy_search_sorted(&path, &list)
.get(0)
.unwrap()
.clone();
let song = conn.get_song_with_only_filename(filename);
conn.push(&song)?;
}
Ok(())
}
pub fn handle_go_back(&mut self, conn: &mut Connection) -> AppResult<()> {
self.path = self.prev_path.clone();
self.selected = self.prev_selected;
self.update_directory(conn)?;
Ok(())
}
}

View File

@ -17,13 +17,13 @@ pub fn handle_key_events(key_event: KeyEvent, app: &mut App) -> AppResult<()> {
}
KeyCode::Char('j') | KeyCode::Down => match app.selected_tab {
SelectedTab::SongList => app.song_list.next(),
SelectedTab::DirectoryBrowser => app.browser.next(),
SelectedTab::Queue => app.queue_list.next(),
SelectedTab::Playlists => app.pl_list.next(),
},
KeyCode::Char('k') | KeyCode::Up => match app.selected_tab {
SelectedTab::SongList => app.song_list.prev(),
SelectedTab::DirectoryBrowser => app.browser.prev(),
SelectedTab::Queue => app.queue_list.prev(),
SelectedTab::Playlists => app.pl_list.prev(),
},
@ -32,12 +32,10 @@ pub fn handle_key_events(key_event: KeyEvent, app: &mut App) -> AppResult<()> {
// app.update_queue();
match app.selected_tab {
SelectedTab::SongList => {
let song = app.conn.get_song_with_only_filename(
app.conn.songs_filenames.get(app.song_list.index).unwrap(),
);
app.conn.push(&song)?;
SelectedTab::DirectoryBrowser => {
app.browser.handle_enter(&mut app.conn)?;
}
SelectedTab::Queue => {
let song = app.conn.get_song_with_only_filename(
app.queue_list.list.get(app.queue_list.index).unwrap(),
@ -51,6 +49,14 @@ pub fn handle_key_events(key_event: KeyEvent, app: &mut App) -> AppResult<()> {
}
}
KeyCode::Char('h') => match app.selected_tab {
SelectedTab::DirectoryBrowser => {
app.browser.handle_go_back(&mut app.conn)?;
}
SelectedTab::Queue => {}
SelectedTab::Playlists => {}
},
// Playback controls
// Toggle Pause
KeyCode::Char('p') => {
@ -105,7 +111,7 @@ pub fn handle_key_events(key_event: KeyEvent, app: &mut App) -> AppResult<()> {
}
KeyCode::Char('1') => {
app.selected_tab = SelectedTab::SongList;
app.selected_tab = SelectedTab::DirectoryBrowser;
}
KeyCode::Char('2') => {
@ -116,6 +122,7 @@ pub fn handle_key_events(key_event: KeyEvent, app: &mut App) -> AppResult<()> {
app.selected_tab = SelectedTab::Playlists;
}
KeyCode::Char('n') => {
app.conn.conn.next()?;
}

View File

@ -13,6 +13,9 @@ pub mod tui;
/// Content list
pub mod list;
/// File Browser
pub mod browser;
/// Event Handler
pub mod event;

View File

@ -1,4 +1,7 @@
use crate::app::{App, AppResult, SelectedTab};
use crate::{
app::{App, AppResult, SelectedTab},
browser::FileBrowser,
};
use ratatui::{
prelude::*,
widgets::{block::Title, *},
@ -48,9 +51,10 @@ pub fn render(app: &mut App, frame: &mut Frame) {
// frame.render_widget(tab, layout[0]);
match app.selected_tab {
SelectedTab::SongList => draw_song_list(frame, app, layout[1]),
// SelectedTab::SongList => draw_song_list(frame, app, layout[1]),
SelectedTab::Queue => draw_queue(frame, app, layout[1]),
SelectedTab::Playlists => draw_playlists(frame, app, layout[1]),
SelectedTab::DirectoryBrowser => draw_directory_browser(frame, app, layout[1]),
}
}
@ -147,3 +151,33 @@ fn draw_progress_bar(frame: &mut Frame, app: &mut App, size: Rect) {
frame.render_widget(progress_bar, size);
}
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<String> = vec![];
for (t, s) in app.browser.filetree.iter() {
if t == "file" {
list.push(s.to_string());
} else {
list.push(format!("[{}]", *s));
}
}
let list = List::new(list)
.block(
Block::default()
.title(format!("File Browser: {}", app.browser.path.clone()).bold())
.title(
Title::from(format!("Total Songs: {}", total_songs).bold().green())
.alignment(Alignment::Right),
)
.borders(Borders::ALL),
)
.highlight_style(Style::new().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);
}