use filetree view instead of all song list
This commit is contained in:
parent
f665c4e9f3
commit
00c5c12d82
19
src/app.rs
19
src/app.rs
|
|
@ -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,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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(())
|
||||
}
|
||||
}
|
||||
|
|
@ -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()?;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,6 +13,9 @@ pub mod tui;
|
|||
/// Content list
|
||||
pub mod list;
|
||||
|
||||
/// File Browser
|
||||
pub mod browser;
|
||||
|
||||
/// Event Handler
|
||||
pub mod event;
|
||||
|
||||
|
|
|
|||
38
src/ui.rs
38
src/ui.rs
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
Reference in New Issue