aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xsrc/app.rs33
-rwxr-xr-xsrc/connection.rs23
-rwxr-xr-xsrc/handler.rs101
-rwxr-xr-xsrc/ui.rs48
4 files changed, 159 insertions, 46 deletions
diff --git a/src/app.rs b/src/app.rs
index 8b06be8..88f6efc 100755
--- a/src/app.rs
+++ b/src/app.rs
@@ -22,6 +22,10 @@ pub struct App {
pub inputmode: InputMode,
pub search_input: String,
pub cursor_position: usize,
+
+ // add to playlists
+ pub playlist_popup: bool,
+ pub append_list: ContentList<String>,
}
#[derive(Debug, PartialEq, Clone)]
@@ -38,6 +42,7 @@ impl App {
let mut pl_list = ContentList::new();
pl_list.list = Self::get_playlist(&mut conn.conn)?;
+ let append_list = Self::get_append_list(&mut conn.conn)?;
Self::get_queue(&mut conn, &mut queue_list.list);
let browser = FileBrowser::new();
@@ -51,6 +56,8 @@ impl App {
inputmode: InputMode::Normal,
search_input: String::new(),
cursor_position: 0,
+ playlist_popup: false,
+ append_list,
})
}
@@ -91,6 +98,16 @@ impl App {
Ok(list)
}
+ pub fn get_append_list(conn: &mut Client) -> AppResult<ContentList<String>> {
+ let mut list = ContentList::new();
+ list.list.push("Current Playlist".to_string());
+ for item in Self::get_playlist(conn)? {
+ list.list.push(item.to_string());
+ }
+
+ Ok(list)
+ }
+
pub fn update_playlist(&mut self) -> AppResult<()> {
Self::get_playlist(&mut self.conn.conn)?;
Ok(())
@@ -105,21 +122,9 @@ impl App {
}
pub fn search_song(&mut self) -> AppResult<()> {
- let list = self
- .conn
- .songs_filenames
- .iter()
- .map(|f| f.as_str())
- .collect::<Vec<&str>>();
- let (filename, _) =
- rust_fuzzy_search::fuzzy_search_sorted(self.search_input.as_str(), &list)
- .get(0)
- .unwrap()
- .clone();
-
- let song = self.conn.get_song_with_only_filename(filename);
+ let filename = self.conn.get_full_path(&self.search_input)?;
+ let song = self.conn.get_song_with_only_filename(&filename);
self.conn.push(&song)?;
-
Ok(())
}
diff --git a/src/connection.rs b/src/connection.rs
index b84d429..51444dd 100755
--- a/src/connection.rs
+++ b/src/connection.rs
@@ -4,6 +4,8 @@ use simple_dmenu::dmenu;
use std::process::Command;
use std::time::Duration;
+use crate::app::AppResult;
+
pub type Result<T> = core::result::Result<T, Error>;
pub type Error = Box<dyn std::error::Error>;
@@ -143,6 +145,12 @@ impl Connection {
Ok(())
}
+ /// Add given song to playlist
+ pub fn add_to_playlist(&mut self, playlist: &str, song: &Song) -> Result<()> {
+ self.conn.pl_push(playlist, song)?;
+ Ok(())
+ }
+
/// Given a filename, get instance of Song with only filename
pub fn get_song_with_only_filename(&self, filename: &str) -> Song {
Song {
@@ -158,6 +166,21 @@ impl Connection {
}
}
+ /// Given a song name from a directory, it returns the full path of the song in the database
+ pub fn get_full_path(&self, short_path: &str) -> AppResult<String> {
+ let list = self
+ .songs_filenames
+ .iter()
+ .map(|f| f.as_str())
+ .collect::<Vec<&str>>();
+ let (filename, _) = rust_fuzzy_search::fuzzy_search_sorted(&short_path, &list)
+ .get(0)
+ .unwrap()
+ .clone();
+
+ Ok(filename.to_string())
+ }
+
/// Print status to stdout
pub fn status(&mut self) {
let current_song = self.conn.currentsong();
diff --git a/src/handler.rs b/src/handler.rs
index cb7c292..c74a3a8 100755
--- a/src/handler.rs
+++ b/src/handler.rs
@@ -6,7 +6,6 @@ use crate::{
};
use crossterm::event::{KeyCode, KeyEvent, KeyModifiers};
use rust_fuzzy_search::{self, fuzzy_search_sorted};
-use simple_dmenu::dmenu;
pub fn handle_key_events(key_event: KeyEvent, app: &mut App) -> AppResult<()> {
if app.inputmode == InputMode::Editing {
@@ -70,6 +69,52 @@ pub fn handle_key_events(key_event: KeyEvent, app: &mut App) -> AppResult<()> {
_ => {}
}
+ } else if app.playlist_popup {
+ match key_event.code {
+ KeyCode::Char('q') | KeyCode::Esc => {
+ app.playlist_popup = false;
+ }
+
+ KeyCode::Char('j') | KeyCode::Down => app.append_list.next(),
+ KeyCode::Char('k') | KeyCode::Up => app.append_list.prev(),
+
+ KeyCode::Enter => {
+ let pl_index = app.append_list.index;
+ let pl_name = app.append_list.list.get(pl_index).unwrap();
+
+ let s_index: usize;
+ let mut short_path: String = String::new();
+ match app.selected_tab {
+ SelectedTab::Queue => {
+ s_index = app.queue_list.index;
+ short_path = app.queue_list.list.get(s_index).unwrap().to_string();
+ }
+
+ SelectedTab::DirectoryBrowser => {
+ let (t, f) = app.browser.filetree.get(app.browser.selected).unwrap();
+ if t == "file" {
+ short_path = f.to_string();
+ }
+ }
+ _ => {}
+ }
+
+ let full_path = app.conn.get_full_path(&short_path)?;
+ let song = app.conn.get_song_with_only_filename(&full_path);
+
+ if pl_name == "Current Playlist" {
+ app.conn.conn.push(&song)?;
+ app.update_queue();
+ } else {
+ app.conn.add_to_playlist(pl_name, &song)?;
+ }
+
+ // hide the playlist popup
+ app.playlist_popup = false;
+ app.append_list.index = 0;
+ }
+ _ => {}
+ }
} else {
match key_event.code {
// Quit
@@ -160,32 +205,34 @@ pub fn handle_key_events(key_event: KeyEvent, app: &mut App) -> AppResult<()> {
// add to queue
KeyCode::Char('a') => {
- let list = app
- .conn
- .songs_filenames
- .iter()
- .map(|f| f.as_str())
- .collect::<Vec<&str>>();
-
- let files: Vec<String> = app
- .browser
- .filetree
- .clone()
- .into_iter()
- .map(|(_, f)| f)
- .collect();
-
- let (filename, _) = rust_fuzzy_search::fuzzy_search_sorted(
- &files.get(app.browser.selected).unwrap(),
- &list,
- )
- .get(0)
- .unwrap()
- .clone();
-
- let song = app.conn.get_song_with_only_filename(filename);
-
- app.conn.conn.push(&song)?;
+ // let list = app
+ // .conn
+ // .songs_filenames
+ // .iter()
+ // .map(|f| f.as_str())
+ // .collect::<Vec<&str>>();
+ //
+ // let files: Vec<String> = app
+ // .browser
+ // .filetree
+ // .clone()
+ // .into_iter()
+ // .map(|(_, f)| f)
+ // .collect();
+ //
+ // let (filename, _) = rust_fuzzy_search::fuzzy_search_sorted(
+ // &files.get(app.browser.selected).unwrap(),
+ // &list,
+ // )
+ // .get(0)
+ // .unwrap()
+ // .clone();
+ //
+ // let song = app.conn.get_song_with_only_filename(filename);
+ //
+ // app.conn.conn.push(&song)?;
+
+ app.playlist_popup = true;
}
KeyCode::Right => {
diff --git a/src/ui.rs b/src/ui.rs
index 2010362..0bd87af 100755
--- a/src/ui.rs
+++ b/src/ui.rs
@@ -21,11 +21,6 @@ impl InputMode {
/// Renders the user interface widgets
pub fn render(app: &mut App, frame: &mut Frame) {
- // This is where you add new widgets.
- // See the following resources:
- // - https://docs.rs/ratatui/latest/ratatui/widgets/index.html
- // - https://github.com/ratatui-org/ratatui/tree/master/examples
-
// Layout
let layout = Layout::default()
.direction(Direction::Vertical)
@@ -46,6 +41,10 @@ pub fn render(app: &mut App, frame: &mut Frame) {
draw_search_bar(frame, app, layout[1]);
}
}
+
+ if app.playlist_popup {
+ draw_add_to_playlist(frame, app, layout[0]);
+ }
}
/// Draws the file tree browser
@@ -238,3 +237,42 @@ fn draw_progress_bar(frame: &mut Frame, app: &mut App, size: Rect) {
frame.render_widget(progress_bar, size);
}
+
+fn draw_add_to_playlist(frame: &mut Frame, app: &mut App, area: Rect) {
+ let area = centered_rect(40, 50, area);
+ let mut state = ListState::default();
+ let title = Block::default()
+ .title(Title::from("Add Selected Item to: "))
+ .title(Title::from("<Esc> to Cancel".green().bold()).alignment(Alignment::Right));
+ let list = List::new(app.append_list.list.clone())
+ .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(">>")
+ .repeat_highlight_symbol(true);
+
+ state.select(Some(app.append_list.index));
+ frame.render_widget(Clear, area); //this clears out the background
+ frame.render_stateful_widget(list, area, &mut state);
+}
+
+fn centered_rect(percent_x: u16, percent_y: u16, r: Rect) -> Rect {
+ let popup_layout = Layout::vertical([
+ Constraint::Percentage((100 - percent_y) / 2),
+ Constraint::Percentage(percent_y),
+ Constraint::Percentage((100 - percent_y) / 2),
+ ])
+ .split(r);
+
+ Layout::horizontal([
+ Constraint::Percentage((100 - percent_x) / 2),
+ Constraint::Percentage(percent_x),
+ Constraint::Percentage((100 - percent_x) / 2),
+ ])
+ .split(popup_layout[1])[1]
+}