use crate::App;
use crate::app::{
PanelFocus,
ui::{
DisplayItem, compute_album_display_list, compute_albums_display_list_genres,
compute_albums_display_list_years,
},
};
use log::error;
use mpd_client::{Client, commands};
use ratatui::widgets::ListState;
use std::collections::HashSet;
async fn toggle_album_expansion_generic(
queue: &mut [crate::app::SongInfo],
display_list_state: &mut ListState,
display_items: &[DisplayItem],
album_indices: &[Option<usize>],
expansion_set: &mut HashSet<(String, String)>,
get_album_key: impl Fn(usize) -> Option<(String, String)>,
client: &Client,
) -> color_eyre::Result<()> {
if let Some(display_index) = display_list_state.selected()
&& let Some(display_item) = display_items.get(display_index)
{
match display_item {
DisplayItem::Album(_) => {
if let Some(album_index) = album_indices.get(display_index).copied().flatten()
&& let Some(album_key) = get_album_key(album_index)
{
if expansion_set.contains(&album_key) {
expansion_set.remove(&album_key);
} else {
expansion_set.insert(album_key);
}
}
}
DisplayItem::Song(_title, _duration, file_path) => {
let queue_was_empty = queue.is_empty();
if let Err(e) = client
.command(commands::Add::uri(file_path.to_str().unwrap()))
.await
{
error!("Error adding song to queue: {}", e);
} else if queue_was_empty {
if let Err(e) = client.command(commands::Play::current()).await {
error!("Error starting playback: {}", e);
}
}
}
}
}
Ok(())
}
impl App {
pub async fn handle_album_toggle(&mut self, client: &Client) -> color_eyre::Result<()> {
if let (Some(library), Some(selected_artist_index)) =
(&self.library, self.artist_list_state.selected())
&& let Some(selected_artist) = library.get_artist(selected_artist_index)
{
let (display_items, album_indices) =
compute_album_display_list(&selected_artist, &self.expanded_albums);
let selected_artist_clone = selected_artist.clone();
let get_album_key = move |album_idx: usize| -> Option<(String, String)> {
selected_artist_clone
.albums
.get(album_idx)
.map(|album| (selected_artist_clone.name.clone(), album.name.clone()))
};
toggle_album_expansion_generic(
&mut self.queue,
&mut self.album_display_list_state,
&display_items,
&album_indices,
&mut self.expanded_albums,
get_album_key,
client,
)
.await?;
}
self.dirty.mark_library();
Ok(())
}
pub async fn handle_year_album_toggle(&mut self, client: &Client) -> color_eyre::Result<()> {
if let (Some(library), Some(selected_year_index)) =
(&self.library, self.year_list_state.selected())
&& let Some(selected_year) = library.albums_by_year.get(selected_year_index)
{
let (display_items, album_indices) =
compute_albums_display_list_years(&selected_year.1, &self.expanded_albums_years);
let selected_year_clone = selected_year.clone();
let get_album_key = move |album_idx: usize| -> Option<(String, String)> {
selected_year_clone
.1
.get(album_idx)
.map(|(artist_name, album)| (artist_name.clone(), album.name.clone()))
};
toggle_album_expansion_generic(
&mut self.queue,
&mut self.year_album_display_list_state,
&display_items,
&album_indices,
&mut self.expanded_albums_years,
get_album_key,
client,
)
.await?;
}
self.dirty.mark_library();
Ok(())
}
pub async fn handle_genre_album_toggle(&mut self, client: &Client) -> color_eyre::Result<()> {
if let (Some(library), Some(selected_genre_index)) =
(&self.library, self.genre_list_state.selected())
&& let Some(selected_genre) = library.albums_by_genre.get(selected_genre_index)
{
let (display_items, album_indices) =
compute_albums_display_list_genres(&selected_genre.1, &self.expanded_albums_genres);
let selected_genre_clone = selected_genre.clone();
let get_album_key = move |album_idx: usize| -> Option<(String, String)> {
selected_genre_clone
.1
.get(album_idx)
.map(|(artist_name, album)| (artist_name.clone(), album.name.clone()))
};
toggle_album_expansion_generic(
&mut self.queue,
&mut self.genre_album_display_list_state,
&display_items,
&album_indices,
&mut self.expanded_albums_genres,
get_album_key,
client,
)
.await?;
}
self.dirty.mark_library();
Ok(())
}
pub async fn handle_add_to_queue_context_aware(
&mut self,
client: &Client,
) -> color_eyre::Result<()> {
if let (Some(library), Some(selected_artist_index)) =
(&self.library, self.artist_list_state.selected())
&& let Some(selected_artist) = library.get_artist(selected_artist_index)
&& let Some(display_index) = self.album_display_list_state.selected()
{
let (display_items, _album_indices) =
compute_album_display_list(&selected_artist, &self.expanded_albums);
if let Some(display_item) = display_items.get(display_index) {
match display_item {
DisplayItem::Album(album_name) => {
if let Some(album) = selected_artist
.albums
.iter()
.find(|a| &a.name == album_name)
{
let queue_was_empty = self.queue.is_empty();
for song in &album.tracks {
if let Err(e) = client
.command(commands::Add::uri(song.file_path.to_str().unwrap()))
.await
{
error!("Error adding song to queue: {}", e);
}
}
if queue_was_empty
&& let Err(e) = client.command(commands::Play::current()).await
{
error!("Error starting playback: {}", e);
}
}
}
DisplayItem::Song(_title, _duration, file_path) => {
let queue_was_empty = self.queue.is_empty();
if let Err(e) = client
.command(commands::Add::uri(file_path.to_str().unwrap()))
.await
{
error!("Error adding song to queue: {}", e);
} else if queue_was_empty
&& let Err(e) = client.command(commands::Play::current()).await
{
error!("Error starting playback: {}", e);
}
}
}
}
}
Ok(())
}
pub async fn handle_add_to_queue_years_context_aware(
&mut self,
client: &Client,
) -> color_eyre::Result<()> {
if self.panel_focus != PanelFocus::YearAlbums {
return Ok(());
}
if let (Some(library), Some(selected_year_index)) =
(&self.library, self.year_list_state.selected())
&& let Some(selected_year) = library.albums_by_year.get(selected_year_index)
&& let Some(display_index) = self.year_album_display_list_state.selected()
{
let (display_items, _album_indices) =
compute_albums_display_list_years(&selected_year.1, &self.expanded_albums_years);
if let Some(display_item) = display_items.get(display_index) {
match display_item {
DisplayItem::Album(_album_name) => {
if let Some(album_idx) =
_album_indices.get(display_index).copied().flatten()
&& let Some((_artist_name, album)) = selected_year.1.get(album_idx)
{
let queue_was_empty = self.queue.is_empty();
for song in &album.tracks {
if let Err(e) = client
.command(commands::Add::uri(song.file_path.to_str().unwrap()))
.await
{
error!("Error adding song to queue: {}", e);
}
}
if queue_was_empty
&& let Err(e) = client.command(commands::Play::current()).await
{
error!("Error starting playback: {}", e);
}
}
}
DisplayItem::Song(_title, _duration, file_path) => {
let queue_was_empty = self.queue.is_empty();
if let Err(e) = client
.command(commands::Add::uri(file_path.to_str().unwrap()))
.await
{
error!("Error adding song to queue: {}", e);
} else if queue_was_empty
&& let Err(e) = client.command(commands::Play::current()).await
{
error!("Error starting playback: {}", e);
}
}
}
}
}
Ok(())
}
pub async fn handle_add_to_queue_genres_context_aware(
&mut self,
client: &Client,
) -> color_eyre::Result<()> {
if self.panel_focus != PanelFocus::GenreAlbums {
return Ok(());
}
if let (Some(library), Some(selected_genre_index)) =
(&self.library, self.genre_list_state.selected())
&& let Some(selected_genre) = library.albums_by_genre.get(selected_genre_index)
&& let Some(display_index) = self.genre_album_display_list_state.selected()
{
let (display_items, _album_indices) =
compute_albums_display_list_genres(&selected_genre.1, &self.expanded_albums_genres);
if let Some(display_item) = display_items.get(display_index) {
match display_item {
DisplayItem::Album(_album_name) => {
if let Some(album_idx) =
_album_indices.get(display_index).copied().flatten()
&& let Some((_artist_name, album)) = selected_genre.1.get(album_idx)
{
let queue_was_empty = self.queue.is_empty();
for song in &album.tracks {
if let Err(e) = client
.command(commands::Add::uri(song.file_path.to_str().unwrap()))
.await
{
error!("Error adding song to queue: {}", e);
}
}
if queue_was_empty
&& let Err(e) = client.command(commands::Play::current()).await
{
error!("Error starting playback: {}", e);
}
}
}
DisplayItem::Song(_title, _duration, file_path) => {
let queue_was_empty = self.queue.is_empty();
if let Err(e) = client
.command(commands::Add::uri(file_path.to_str().unwrap()))
.await
{
error!("Error adding song to queue: {}", e);
} else if queue_was_empty
&& let Err(e) = client.command(commands::Play::current()).await
{
error!("Error starting playback: {}", e);
}
}
}
}
}
Ok(())
}
}