add to playlist feature

This commit is contained in:
krolxon 2024-04-26 23:10:08 +05:30
parent 8269766147
commit 59eed99c85
4 changed files with 158 additions and 45 deletions

View File

@ -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(())
}

View File

@ -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();

View File

@ -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 {
@ -68,6 +67,52 @@ pub fn handle_key_events(key_event: KeyEvent, app: &mut App) -> AppResult<()> {
app.move_cursor_right();
}
_ => {}
}
} 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 {
@ -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 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 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 => {

View File

@ -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]
}