feat: TUI support for deleting a Lidarr album from the artist details popup
This commit is contained in:
@@ -36,15 +36,16 @@ pub static ADD_ARTIST_SEARCH_RESULTS_CONTEXT_CLUES: [ContextClue; 2] = [
|
|||||||
(DEFAULT_KEYBINDINGS.esc, "edit search"),
|
(DEFAULT_KEYBINDINGS.esc, "edit search"),
|
||||||
];
|
];
|
||||||
|
|
||||||
pub static ARTIST_DETAILS_CONTEXT_CLUES: [ContextClue; 7] = [
|
pub static ARTIST_DETAILS_CONTEXT_CLUES: [ContextClue; 8] = [
|
||||||
(
|
(
|
||||||
DEFAULT_KEYBINDINGS.refresh,
|
DEFAULT_KEYBINDINGS.refresh,
|
||||||
DEFAULT_KEYBINDINGS.refresh.desc,
|
DEFAULT_KEYBINDINGS.refresh.desc,
|
||||||
),
|
),
|
||||||
(DEFAULT_KEYBINDINGS.edit, DEFAULT_KEYBINDINGS.edit.desc),
|
(DEFAULT_KEYBINDINGS.edit, "edit artist"),
|
||||||
|
(DEFAULT_KEYBINDINGS.delete, "delete album"),
|
||||||
(
|
(
|
||||||
DEFAULT_KEYBINDINGS.toggle_monitoring,
|
DEFAULT_KEYBINDINGS.toggle_monitoring,
|
||||||
DEFAULT_KEYBINDINGS.toggle_monitoring.desc,
|
"toggle album monitoring",
|
||||||
),
|
),
|
||||||
(DEFAULT_KEYBINDINGS.search, DEFAULT_KEYBINDINGS.search.desc),
|
(DEFAULT_KEYBINDINGS.search, DEFAULT_KEYBINDINGS.search.desc),
|
||||||
(DEFAULT_KEYBINDINGS.update, DEFAULT_KEYBINDINGS.update.desc),
|
(DEFAULT_KEYBINDINGS.update, DEFAULT_KEYBINDINGS.update.desc),
|
||||||
|
|||||||
@@ -81,13 +81,17 @@ mod tests {
|
|||||||
);
|
);
|
||||||
assert_some_eq_x!(
|
assert_some_eq_x!(
|
||||||
artist_details_context_clues_iter.next(),
|
artist_details_context_clues_iter.next(),
|
||||||
&(DEFAULT_KEYBINDINGS.edit, DEFAULT_KEYBINDINGS.edit.desc)
|
&(DEFAULT_KEYBINDINGS.edit, "edit artist")
|
||||||
|
);
|
||||||
|
assert_some_eq_x!(
|
||||||
|
artist_details_context_clues_iter.next(),
|
||||||
|
&(DEFAULT_KEYBINDINGS.delete, "delete album")
|
||||||
);
|
);
|
||||||
assert_some_eq_x!(
|
assert_some_eq_x!(
|
||||||
artist_details_context_clues_iter.next(),
|
artist_details_context_clues_iter.next(),
|
||||||
&(
|
&(
|
||||||
DEFAULT_KEYBINDINGS.toggle_monitoring,
|
DEFAULT_KEYBINDINGS.toggle_monitoring,
|
||||||
DEFAULT_KEYBINDINGS.toggle_monitoring.desc,
|
"toggle album monitoring",
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
assert_some_eq_x!(
|
assert_some_eq_x!(
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
use crate::app::App;
|
use crate::app::App;
|
||||||
use crate::event::Key;
|
use crate::event::Key;
|
||||||
|
use crate::handlers::lidarr_handlers::library::delete_album_handler::DeleteAlbumHandler;
|
||||||
use crate::handlers::table_handler::{TableHandlingConfig, handle_table};
|
use crate::handlers::table_handler::{TableHandlingConfig, handle_table};
|
||||||
use crate::handlers::{KeyEventHandler, handle_prompt_toggle};
|
use crate::handlers::{KeyEventHandler, handle_prompt_toggle};
|
||||||
use crate::matches_key;
|
use crate::matches_key;
|
||||||
use crate::models::lidarr_models::Album;
|
use crate::models::lidarr_models::Album;
|
||||||
use crate::models::servarr_data::lidarr::lidarr_data::{
|
use crate::models::servarr_data::lidarr::lidarr_data::{
|
||||||
ARTIST_DETAILS_BLOCKS, ActiveLidarrBlock, EDIT_ARTIST_SELECTION_BLOCKS,
|
ARTIST_DETAILS_BLOCKS, ActiveLidarrBlock, DELETE_ALBUM_SELECTION_BLOCKS,
|
||||||
|
EDIT_ARTIST_SELECTION_BLOCKS,
|
||||||
};
|
};
|
||||||
use crate::models::{BlockSelectionState, Route};
|
use crate::models::{BlockSelectionState, Route};
|
||||||
use crate::network::lidarr_network::LidarrEvent;
|
use crate::network::lidarr_network::LidarrEvent;
|
||||||
@@ -18,7 +20,7 @@ pub struct ArtistDetailsHandler<'a, 'b> {
|
|||||||
key: Key,
|
key: Key,
|
||||||
app: &'a mut App<'b>,
|
app: &'a mut App<'b>,
|
||||||
active_lidarr_block: ActiveLidarrBlock,
|
active_lidarr_block: ActiveLidarrBlock,
|
||||||
_context: Option<ActiveLidarrBlock>,
|
context: Option<ActiveLidarrBlock>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ArtistDetailsHandler<'_, '_> {
|
impl ArtistDetailsHandler<'_, '_> {
|
||||||
@@ -44,12 +46,18 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveLidarrBlock> for ArtistDetailsHandler
|
|||||||
|app| &mut app.data.lidarr_data.albums,
|
|app| &mut app.data.lidarr_data.albums,
|
||||||
albums_table_handling_config,
|
albums_table_handling_config,
|
||||||
) {
|
) {
|
||||||
self.handle_key_event();
|
match self.active_lidarr_block {
|
||||||
|
_ if DeleteAlbumHandler::accepts(self.active_lidarr_block) => {
|
||||||
|
DeleteAlbumHandler::new(self.key, self.app, self.active_lidarr_block, self.context)
|
||||||
|
.handle();
|
||||||
|
}
|
||||||
|
_ => self.handle_key_event(),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn accepts(active_block: ActiveLidarrBlock) -> bool {
|
fn accepts(active_block: ActiveLidarrBlock) -> bool {
|
||||||
ARTIST_DETAILS_BLOCKS.contains(&active_block)
|
DeleteAlbumHandler::accepts(active_block) || ARTIST_DETAILS_BLOCKS.contains(&active_block)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ignore_special_keys(&self) -> bool {
|
fn ignore_special_keys(&self) -> bool {
|
||||||
@@ -60,13 +68,13 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveLidarrBlock> for ArtistDetailsHandler
|
|||||||
key: Key,
|
key: Key,
|
||||||
app: &'a mut App<'b>,
|
app: &'a mut App<'b>,
|
||||||
active_block: ActiveLidarrBlock,
|
active_block: ActiveLidarrBlock,
|
||||||
_context: Option<ActiveLidarrBlock>,
|
context: Option<ActiveLidarrBlock>,
|
||||||
) -> ArtistDetailsHandler<'a, 'b> {
|
) -> ArtistDetailsHandler<'a, 'b> {
|
||||||
ArtistDetailsHandler {
|
ArtistDetailsHandler {
|
||||||
key,
|
key,
|
||||||
app,
|
app,
|
||||||
active_lidarr_block: active_block,
|
active_lidarr_block: active_block,
|
||||||
_context,
|
context,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,7 +94,15 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveLidarrBlock> for ArtistDetailsHandler
|
|||||||
|
|
||||||
fn handle_end(&mut self) {}
|
fn handle_end(&mut self) {}
|
||||||
|
|
||||||
fn handle_delete(&mut self) {}
|
fn handle_delete(&mut self) {
|
||||||
|
if self.active_lidarr_block == ActiveLidarrBlock::ArtistDetails {
|
||||||
|
self
|
||||||
|
.app
|
||||||
|
.push_navigation_stack(ActiveLidarrBlock::DeleteAlbumPrompt.into());
|
||||||
|
self.app.data.lidarr_data.selected_block =
|
||||||
|
BlockSelectionState::new(DELETE_ALBUM_SELECTION_BLOCKS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn handle_left_right_action(&mut self) {
|
fn handle_left_right_action(&mut self) {
|
||||||
match self.active_lidarr_block {
|
match self.active_lidarr_block {
|
||||||
|
|||||||
@@ -9,9 +9,42 @@ mod tests {
|
|||||||
use crate::handlers::KeyEventHandler;
|
use crate::handlers::KeyEventHandler;
|
||||||
use crate::handlers::lidarr_handlers::library::artist_details_handler::ArtistDetailsHandler;
|
use crate::handlers::lidarr_handlers::library::artist_details_handler::ArtistDetailsHandler;
|
||||||
use crate::models::servarr_data::lidarr::lidarr_data::{
|
use crate::models::servarr_data::lidarr::lidarr_data::{
|
||||||
ARTIST_DETAILS_BLOCKS, ActiveLidarrBlock,
|
ARTIST_DETAILS_BLOCKS, ActiveLidarrBlock, DELETE_ALBUM_BLOCKS,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
mod test_handle_delete {
|
||||||
|
use super::*;
|
||||||
|
use crate::assert_delete_prompt;
|
||||||
|
use crate::event::Key;
|
||||||
|
use crate::models::lidarr_models::Album;
|
||||||
|
use crate::models::servarr_data::lidarr::lidarr_data::DELETE_ALBUM_SELECTION_BLOCKS;
|
||||||
|
use pretty_assertions::assert_eq;
|
||||||
|
|
||||||
|
const DELETE_KEY: Key = DEFAULT_KEYBINDINGS.delete.key;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_album_delete() {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app
|
||||||
|
.data
|
||||||
|
.lidarr_data
|
||||||
|
.albums
|
||||||
|
.set_items(vec![Album::default()]);
|
||||||
|
app.push_navigation_stack(ActiveLidarrBlock::ArtistDetails.into());
|
||||||
|
|
||||||
|
assert_delete_prompt!(
|
||||||
|
ArtistDetailsHandler,
|
||||||
|
app,
|
||||||
|
ActiveLidarrBlock::ArtistDetails,
|
||||||
|
ActiveLidarrBlock::DeleteAlbumPrompt
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
app.data.lidarr_data.selected_block.blocks,
|
||||||
|
DELETE_ALBUM_SELECTION_BLOCKS
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
mod test_handle_left_right_action {
|
mod test_handle_left_right_action {
|
||||||
use rstest::rstest;
|
use rstest::rstest;
|
||||||
|
|
||||||
@@ -436,8 +469,11 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_artist_details_handler_accepts() {
|
fn test_artist_details_handler_accepts() {
|
||||||
|
let mut artist_details_blocks = ARTIST_DETAILS_BLOCKS.clone().to_vec();
|
||||||
|
artist_details_blocks.extend(DELETE_ALBUM_BLOCKS);
|
||||||
|
|
||||||
ActiveLidarrBlock::iter().for_each(|active_lidarr_block| {
|
ActiveLidarrBlock::iter().for_each(|active_lidarr_block| {
|
||||||
if ARTIST_DETAILS_BLOCKS.contains(&active_lidarr_block) {
|
if artist_details_blocks.contains(&active_lidarr_block) {
|
||||||
assert!(ArtistDetailsHandler::accepts(active_lidarr_block));
|
assert!(ArtistDetailsHandler::accepts(active_lidarr_block));
|
||||||
} else {
|
} else {
|
||||||
assert!(!ArtistDetailsHandler::accepts(active_lidarr_block));
|
assert!(!ArtistDetailsHandler::accepts(active_lidarr_block));
|
||||||
|
|||||||
@@ -0,0 +1,150 @@
|
|||||||
|
use crate::models::Route;
|
||||||
|
use crate::models::lidarr_models::DeleteParams;
|
||||||
|
use crate::models::servarr_data::lidarr::lidarr_data::DELETE_ALBUM_BLOCKS;
|
||||||
|
use crate::network::lidarr_network::LidarrEvent;
|
||||||
|
use crate::{
|
||||||
|
app::App,
|
||||||
|
event::Key,
|
||||||
|
handlers::{KeyEventHandler, handle_prompt_toggle},
|
||||||
|
matches_key,
|
||||||
|
models::servarr_data::lidarr::lidarr_data::ActiveLidarrBlock,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
#[path = "delete_album_handler_tests.rs"]
|
||||||
|
mod delete_album_handler_tests;
|
||||||
|
|
||||||
|
pub(in crate::handlers::lidarr_handlers) struct DeleteAlbumHandler<'a, 'b> {
|
||||||
|
key: Key,
|
||||||
|
app: &'a mut App<'b>,
|
||||||
|
active_lidarr_block: ActiveLidarrBlock,
|
||||||
|
_context: Option<ActiveLidarrBlock>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DeleteAlbumHandler<'_, '_> {
|
||||||
|
fn build_delete_album_params(&mut self) -> DeleteParams {
|
||||||
|
let id = self.app.data.lidarr_data.albums.current_selection().id;
|
||||||
|
let delete_files = self.app.data.lidarr_data.delete_files;
|
||||||
|
let add_import_list_exclusion = self.app.data.lidarr_data.add_import_list_exclusion;
|
||||||
|
self.app.data.lidarr_data.reset_delete_preferences();
|
||||||
|
|
||||||
|
DeleteParams {
|
||||||
|
id,
|
||||||
|
delete_files,
|
||||||
|
add_import_list_exclusion,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveLidarrBlock> for DeleteAlbumHandler<'a, 'b> {
|
||||||
|
fn accepts(active_block: ActiveLidarrBlock) -> bool {
|
||||||
|
DELETE_ALBUM_BLOCKS.contains(&active_block)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ignore_special_keys(&self) -> bool {
|
||||||
|
self.app.ignore_special_keys_for_textbox_input
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new(
|
||||||
|
key: Key,
|
||||||
|
app: &'a mut App<'b>,
|
||||||
|
active_block: ActiveLidarrBlock,
|
||||||
|
_context: Option<ActiveLidarrBlock>,
|
||||||
|
) -> Self {
|
||||||
|
DeleteAlbumHandler {
|
||||||
|
key,
|
||||||
|
app,
|
||||||
|
active_lidarr_block: active_block,
|
||||||
|
_context,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_key(&self) -> Key {
|
||||||
|
self.key
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_ready(&self) -> bool {
|
||||||
|
!self.app.is_loading
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_scroll_up(&mut self) {
|
||||||
|
if self.active_lidarr_block == ActiveLidarrBlock::DeleteAlbumPrompt {
|
||||||
|
self.app.data.lidarr_data.selected_block.up();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_scroll_down(&mut self) {
|
||||||
|
if self.active_lidarr_block == ActiveLidarrBlock::DeleteAlbumPrompt {
|
||||||
|
self.app.data.lidarr_data.selected_block.down();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_home(&mut self) {}
|
||||||
|
|
||||||
|
fn handle_end(&mut self) {}
|
||||||
|
|
||||||
|
fn handle_delete(&mut self) {}
|
||||||
|
|
||||||
|
fn handle_left_right_action(&mut self) {
|
||||||
|
if self.active_lidarr_block == ActiveLidarrBlock::DeleteAlbumPrompt {
|
||||||
|
handle_prompt_toggle(self.app, self.key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_submit(&mut self) {
|
||||||
|
if self.active_lidarr_block == ActiveLidarrBlock::DeleteAlbumPrompt {
|
||||||
|
match self.app.data.lidarr_data.selected_block.get_active_block() {
|
||||||
|
ActiveLidarrBlock::DeleteAlbumConfirmPrompt => {
|
||||||
|
if self.app.data.lidarr_data.prompt_confirm {
|
||||||
|
self.app.data.lidarr_data.prompt_confirm_action =
|
||||||
|
Some(LidarrEvent::DeleteAlbum(self.build_delete_album_params()));
|
||||||
|
self.app.should_refresh = true;
|
||||||
|
} else {
|
||||||
|
self.app.data.lidarr_data.reset_delete_preferences();
|
||||||
|
}
|
||||||
|
|
||||||
|
self.app.pop_navigation_stack();
|
||||||
|
}
|
||||||
|
ActiveLidarrBlock::DeleteAlbumToggleDeleteFile => {
|
||||||
|
self.app.data.lidarr_data.delete_files = !self.app.data.lidarr_data.delete_files;
|
||||||
|
}
|
||||||
|
ActiveLidarrBlock::DeleteAlbumToggleAddListExclusion => {
|
||||||
|
self.app.data.lidarr_data.add_import_list_exclusion =
|
||||||
|
!self.app.data.lidarr_data.add_import_list_exclusion;
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_esc(&mut self) {
|
||||||
|
if self.active_lidarr_block == ActiveLidarrBlock::DeleteAlbumPrompt {
|
||||||
|
self.app.pop_navigation_stack();
|
||||||
|
self.app.data.lidarr_data.reset_delete_preferences();
|
||||||
|
self.app.data.lidarr_data.prompt_confirm = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_char_key_event(&mut self) {
|
||||||
|
if self.active_lidarr_block == ActiveLidarrBlock::DeleteAlbumPrompt
|
||||||
|
&& self.app.data.lidarr_data.selected_block.get_active_block()
|
||||||
|
== ActiveLidarrBlock::DeleteAlbumConfirmPrompt
|
||||||
|
&& matches_key!(confirm, self.key)
|
||||||
|
{
|
||||||
|
self.app.data.lidarr_data.prompt_confirm = true;
|
||||||
|
self.app.data.lidarr_data.prompt_confirm_action =
|
||||||
|
Some(LidarrEvent::DeleteAlbum(self.build_delete_album_params()));
|
||||||
|
self.app.should_refresh = true;
|
||||||
|
|
||||||
|
self.app.pop_navigation_stack();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn app_mut(&mut self) -> &mut App<'b> {
|
||||||
|
self.app
|
||||||
|
}
|
||||||
|
|
||||||
|
fn current_route(&self) -> Route {
|
||||||
|
self.app.get_current_route()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,404 @@
|
|||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use pretty_assertions::assert_eq;
|
||||||
|
use rstest::rstest;
|
||||||
|
use strum::IntoEnumIterator;
|
||||||
|
|
||||||
|
use crate::app::App;
|
||||||
|
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
||||||
|
use crate::event::Key;
|
||||||
|
use crate::handlers::KeyEventHandler;
|
||||||
|
use crate::handlers::lidarr_handlers::library::delete_album_handler::DeleteAlbumHandler;
|
||||||
|
use crate::models::lidarr_models::{Album, DeleteParams};
|
||||||
|
use crate::models::servarr_data::lidarr::lidarr_data::{ActiveLidarrBlock, DELETE_ALBUM_BLOCKS};
|
||||||
|
|
||||||
|
mod test_handle_scroll_up_and_down {
|
||||||
|
use pretty_assertions::assert_eq;
|
||||||
|
use rstest::rstest;
|
||||||
|
|
||||||
|
use crate::models::BlockSelectionState;
|
||||||
|
use crate::models::servarr_data::lidarr::lidarr_data::DELETE_ALBUM_SELECTION_BLOCKS;
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
fn test_delete_album_prompt_scroll(#[values(Key::Up, Key::Down)] key: Key) {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.data.lidarr_data.selected_block = BlockSelectionState::new(DELETE_ALBUM_SELECTION_BLOCKS);
|
||||||
|
app.data.lidarr_data.selected_block.down();
|
||||||
|
|
||||||
|
DeleteAlbumHandler::new(key, &mut app, ActiveLidarrBlock::DeleteAlbumPrompt, None).handle();
|
||||||
|
|
||||||
|
if key == Key::Up {
|
||||||
|
assert_eq!(
|
||||||
|
app.data.lidarr_data.selected_block.get_active_block(),
|
||||||
|
ActiveLidarrBlock::DeleteAlbumToggleDeleteFile
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
assert_eq!(
|
||||||
|
app.data.lidarr_data.selected_block.get_active_block(),
|
||||||
|
ActiveLidarrBlock::DeleteAlbumConfirmPrompt
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
fn test_delete_album_prompt_scroll_no_op_when_not_ready(
|
||||||
|
#[values(Key::Up, Key::Down)] key: Key,
|
||||||
|
) {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.is_loading = true;
|
||||||
|
app.data.lidarr_data.selected_block = BlockSelectionState::new(DELETE_ALBUM_SELECTION_BLOCKS);
|
||||||
|
app.data.lidarr_data.selected_block.down();
|
||||||
|
|
||||||
|
DeleteAlbumHandler::new(key, &mut app, ActiveLidarrBlock::DeleteAlbumPrompt, None).handle();
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
app.data.lidarr_data.selected_block.get_active_block(),
|
||||||
|
ActiveLidarrBlock::DeleteAlbumToggleAddListExclusion
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mod test_handle_left_right_action {
|
||||||
|
use rstest::rstest;
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
fn test_left_right_prompt_toggle(#[values(Key::Left, Key::Right)] key: Key) {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.push_navigation_stack(ActiveLidarrBlock::DeleteAlbumPrompt.into());
|
||||||
|
|
||||||
|
DeleteAlbumHandler::new(key, &mut app, ActiveLidarrBlock::DeleteAlbumPrompt, None).handle();
|
||||||
|
|
||||||
|
assert!(app.data.lidarr_data.prompt_confirm);
|
||||||
|
|
||||||
|
DeleteAlbumHandler::new(key, &mut app, ActiveLidarrBlock::DeleteAlbumPrompt, None).handle();
|
||||||
|
|
||||||
|
assert!(!app.data.lidarr_data.prompt_confirm);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mod test_handle_submit {
|
||||||
|
use pretty_assertions::assert_eq;
|
||||||
|
|
||||||
|
use crate::models::BlockSelectionState;
|
||||||
|
use crate::models::servarr_data::lidarr::lidarr_data::DELETE_ALBUM_SELECTION_BLOCKS;
|
||||||
|
use crate::network::lidarr_network::LidarrEvent;
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
use crate::assert_navigation_popped;
|
||||||
|
|
||||||
|
const SUBMIT_KEY: Key = DEFAULT_KEYBINDINGS.submit.key;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_delete_album_prompt_prompt_decline_submit() {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.push_navigation_stack(ActiveLidarrBlock::ArtistDetails.into());
|
||||||
|
app.push_navigation_stack(ActiveLidarrBlock::DeleteAlbumPrompt.into());
|
||||||
|
app.data.lidarr_data.selected_block = BlockSelectionState::new(DELETE_ALBUM_SELECTION_BLOCKS);
|
||||||
|
app
|
||||||
|
.data
|
||||||
|
.lidarr_data
|
||||||
|
.selected_block
|
||||||
|
.set_index(0, DELETE_ALBUM_SELECTION_BLOCKS.len() - 1);
|
||||||
|
app.data.lidarr_data.delete_files = true;
|
||||||
|
app.data.lidarr_data.add_import_list_exclusion = true;
|
||||||
|
|
||||||
|
DeleteAlbumHandler::new(
|
||||||
|
SUBMIT_KEY,
|
||||||
|
&mut app,
|
||||||
|
ActiveLidarrBlock::DeleteAlbumPrompt,
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
.handle();
|
||||||
|
|
||||||
|
assert_navigation_popped!(app, ActiveLidarrBlock::ArtistDetails.into());
|
||||||
|
assert_none!(app.data.lidarr_data.prompt_confirm_action);
|
||||||
|
assert!(!app.data.lidarr_data.prompt_confirm);
|
||||||
|
assert!(!app.data.lidarr_data.delete_files);
|
||||||
|
assert!(!app.data.lidarr_data.add_import_list_exclusion);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_delete_album_confirm_prompt_prompt_confirmation_submit() {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.push_navigation_stack(ActiveLidarrBlock::ArtistDetails.into());
|
||||||
|
app.push_navigation_stack(ActiveLidarrBlock::DeleteAlbumPrompt.into());
|
||||||
|
app.data.lidarr_data.prompt_confirm = true;
|
||||||
|
app.data.lidarr_data.delete_files = true;
|
||||||
|
app.data.lidarr_data.add_import_list_exclusion = true;
|
||||||
|
app
|
||||||
|
.data
|
||||||
|
.lidarr_data
|
||||||
|
.albums
|
||||||
|
.set_items(vec![Album::default()]);
|
||||||
|
let expected_delete_album_params = DeleteParams {
|
||||||
|
id: 0,
|
||||||
|
delete_files: true,
|
||||||
|
add_import_list_exclusion: true,
|
||||||
|
};
|
||||||
|
app.data.lidarr_data.selected_block = BlockSelectionState::new(DELETE_ALBUM_SELECTION_BLOCKS);
|
||||||
|
app
|
||||||
|
.data
|
||||||
|
.lidarr_data
|
||||||
|
.selected_block
|
||||||
|
.set_index(0, DELETE_ALBUM_SELECTION_BLOCKS.len() - 1);
|
||||||
|
|
||||||
|
DeleteAlbumHandler::new(
|
||||||
|
SUBMIT_KEY,
|
||||||
|
&mut app,
|
||||||
|
ActiveLidarrBlock::DeleteAlbumPrompt,
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
.handle();
|
||||||
|
|
||||||
|
assert_navigation_popped!(app, ActiveLidarrBlock::ArtistDetails.into());
|
||||||
|
assert_eq!(
|
||||||
|
app.data.lidarr_data.prompt_confirm_action,
|
||||||
|
Some(LidarrEvent::DeleteAlbum(expected_delete_album_params))
|
||||||
|
);
|
||||||
|
assert!(app.should_refresh);
|
||||||
|
assert!(app.data.lidarr_data.prompt_confirm);
|
||||||
|
assert!(!app.data.lidarr_data.delete_files);
|
||||||
|
assert!(!app.data.lidarr_data.add_import_list_exclusion);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_delete_album_confirm_prompt_prompt_confirmation_submit_no_op_when_not_ready() {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.is_loading = true;
|
||||||
|
app.push_navigation_stack(ActiveLidarrBlock::ArtistDetails.into());
|
||||||
|
app.push_navigation_stack(ActiveLidarrBlock::DeleteAlbumPrompt.into());
|
||||||
|
app.data.lidarr_data.prompt_confirm = true;
|
||||||
|
app.data.lidarr_data.delete_files = true;
|
||||||
|
app.data.lidarr_data.add_import_list_exclusion = true;
|
||||||
|
|
||||||
|
DeleteAlbumHandler::new(
|
||||||
|
SUBMIT_KEY,
|
||||||
|
&mut app,
|
||||||
|
ActiveLidarrBlock::DeleteAlbumPrompt,
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
.handle();
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
app.get_current_route(),
|
||||||
|
ActiveLidarrBlock::DeleteAlbumPrompt.into()
|
||||||
|
);
|
||||||
|
assert_none!(app.data.lidarr_data.prompt_confirm_action);
|
||||||
|
assert!(!app.should_refresh);
|
||||||
|
assert!(app.data.lidarr_data.prompt_confirm);
|
||||||
|
assert!(app.data.lidarr_data.delete_files);
|
||||||
|
assert!(app.data.lidarr_data.add_import_list_exclusion);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_delete_album_toggle_delete_files_submit() {
|
||||||
|
let current_route = ActiveLidarrBlock::DeleteAlbumPrompt.into();
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.data.lidarr_data.selected_block = BlockSelectionState::new(DELETE_ALBUM_SELECTION_BLOCKS);
|
||||||
|
app.push_navigation_stack(ActiveLidarrBlock::DeleteAlbumPrompt.into());
|
||||||
|
|
||||||
|
DeleteAlbumHandler::new(
|
||||||
|
SUBMIT_KEY,
|
||||||
|
&mut app,
|
||||||
|
ActiveLidarrBlock::DeleteAlbumPrompt,
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
.handle();
|
||||||
|
|
||||||
|
assert_eq!(app.get_current_route(), current_route);
|
||||||
|
assert_eq!(app.data.lidarr_data.delete_files, true);
|
||||||
|
|
||||||
|
DeleteAlbumHandler::new(
|
||||||
|
SUBMIT_KEY,
|
||||||
|
&mut app,
|
||||||
|
ActiveLidarrBlock::DeleteAlbumPrompt,
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
.handle();
|
||||||
|
|
||||||
|
assert_eq!(app.get_current_route(), current_route);
|
||||||
|
assert_eq!(app.data.lidarr_data.delete_files, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mod test_handle_esc {
|
||||||
|
use super::*;
|
||||||
|
use crate::assert_navigation_popped;
|
||||||
|
use rstest::rstest;
|
||||||
|
|
||||||
|
const ESC_KEY: Key = DEFAULT_KEYBINDINGS.esc.key;
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
fn test_delete_album_prompt_esc(#[values(true, false)] is_ready: bool) {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.is_loading = is_ready;
|
||||||
|
app.push_navigation_stack(ActiveLidarrBlock::ArtistDetails.into());
|
||||||
|
app.push_navigation_stack(ActiveLidarrBlock::DeleteAlbumPrompt.into());
|
||||||
|
app.data.lidarr_data.prompt_confirm = true;
|
||||||
|
app.data.lidarr_data.delete_files = true;
|
||||||
|
app.data.lidarr_data.add_import_list_exclusion = true;
|
||||||
|
|
||||||
|
DeleteAlbumHandler::new(
|
||||||
|
ESC_KEY,
|
||||||
|
&mut app,
|
||||||
|
ActiveLidarrBlock::DeleteAlbumPrompt,
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
.handle();
|
||||||
|
|
||||||
|
assert_navigation_popped!(app, ActiveLidarrBlock::ArtistDetails.into());
|
||||||
|
assert!(!app.data.lidarr_data.prompt_confirm);
|
||||||
|
assert!(!app.data.lidarr_data.delete_files);
|
||||||
|
assert!(!app.data.lidarr_data.add_import_list_exclusion);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mod test_handle_key_char {
|
||||||
|
use crate::{
|
||||||
|
assert_navigation_popped,
|
||||||
|
models::{
|
||||||
|
BlockSelectionState, servarr_data::lidarr::lidarr_data::DELETE_ALBUM_SELECTION_BLOCKS,
|
||||||
|
},
|
||||||
|
network::lidarr_network::LidarrEvent,
|
||||||
|
};
|
||||||
|
use pretty_assertions::assert_eq;
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_delete_album_confirm_prompt_prompt_confirm() {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.push_navigation_stack(ActiveLidarrBlock::ArtistDetails.into());
|
||||||
|
app.push_navigation_stack(ActiveLidarrBlock::DeleteAlbumPrompt.into());
|
||||||
|
app.data.lidarr_data.delete_files = true;
|
||||||
|
app.data.lidarr_data.add_import_list_exclusion = true;
|
||||||
|
app
|
||||||
|
.data
|
||||||
|
.lidarr_data
|
||||||
|
.albums
|
||||||
|
.set_items(vec![Album::default()]);
|
||||||
|
let expected_delete_album_params = DeleteParams {
|
||||||
|
id: 0,
|
||||||
|
delete_files: true,
|
||||||
|
add_import_list_exclusion: true,
|
||||||
|
};
|
||||||
|
app.data.lidarr_data.selected_block = BlockSelectionState::new(DELETE_ALBUM_SELECTION_BLOCKS);
|
||||||
|
app
|
||||||
|
.data
|
||||||
|
.lidarr_data
|
||||||
|
.selected_block
|
||||||
|
.set_index(0, DELETE_ALBUM_SELECTION_BLOCKS.len() - 1);
|
||||||
|
|
||||||
|
DeleteAlbumHandler::new(
|
||||||
|
DEFAULT_KEYBINDINGS.confirm.key,
|
||||||
|
&mut app,
|
||||||
|
ActiveLidarrBlock::DeleteAlbumPrompt,
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
.handle();
|
||||||
|
|
||||||
|
assert_navigation_popped!(app, ActiveLidarrBlock::ArtistDetails.into());
|
||||||
|
assert_eq!(
|
||||||
|
app.data.lidarr_data.prompt_confirm_action,
|
||||||
|
Some(LidarrEvent::DeleteAlbum(expected_delete_album_params))
|
||||||
|
);
|
||||||
|
assert!(app.should_refresh);
|
||||||
|
assert!(app.data.lidarr_data.prompt_confirm);
|
||||||
|
assert!(!app.data.lidarr_data.delete_files);
|
||||||
|
assert!(!app.data.lidarr_data.add_import_list_exclusion);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_delete_album_handler_accepts() {
|
||||||
|
ActiveLidarrBlock::iter().for_each(|active_lidarr_block| {
|
||||||
|
if DELETE_ALBUM_BLOCKS.contains(&active_lidarr_block) {
|
||||||
|
assert!(DeleteAlbumHandler::accepts(active_lidarr_block));
|
||||||
|
} else {
|
||||||
|
assert!(!DeleteAlbumHandler::accepts(active_lidarr_block));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
fn test_delete_album_handler_ignore_special_keys(
|
||||||
|
#[values(true, false)] ignore_special_keys_for_textbox_input: bool,
|
||||||
|
) {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.ignore_special_keys_for_textbox_input = ignore_special_keys_for_textbox_input;
|
||||||
|
let handler = DeleteAlbumHandler::new(
|
||||||
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
|
&mut app,
|
||||||
|
ActiveLidarrBlock::default(),
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
handler.ignore_special_keys(),
|
||||||
|
ignore_special_keys_for_textbox_input
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_build_delete_album_params() {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app
|
||||||
|
.data
|
||||||
|
.lidarr_data
|
||||||
|
.albums
|
||||||
|
.set_items(vec![Album::default()]);
|
||||||
|
app.data.lidarr_data.delete_files = true;
|
||||||
|
app.data.lidarr_data.add_import_list_exclusion = true;
|
||||||
|
let expected_delete_album_params = DeleteParams {
|
||||||
|
id: 0,
|
||||||
|
delete_files: true,
|
||||||
|
add_import_list_exclusion: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
let delete_album_params = DeleteAlbumHandler::new(
|
||||||
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
|
&mut app,
|
||||||
|
ActiveLidarrBlock::DeleteAlbumPrompt,
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
.build_delete_album_params();
|
||||||
|
|
||||||
|
assert_eq!(delete_album_params, expected_delete_album_params);
|
||||||
|
assert!(!app.data.lidarr_data.delete_files);
|
||||||
|
assert!(!app.data.lidarr_data.add_import_list_exclusion);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_delete_album_handler_not_ready_when_loading() {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.is_loading = true;
|
||||||
|
|
||||||
|
let handler = DeleteAlbumHandler::new(
|
||||||
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
|
&mut app,
|
||||||
|
ActiveLidarrBlock::DeleteAlbumPrompt,
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
|
||||||
|
assert!(!handler.is_ready());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_delete_album_handler_ready_when_not_loading() {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.is_loading = false;
|
||||||
|
|
||||||
|
let handler = DeleteAlbumHandler::new(
|
||||||
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
|
&mut app,
|
||||||
|
ActiveLidarrBlock::DeleteAlbumPrompt,
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
|
||||||
|
assert!(handler.is_ready());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -23,9 +23,9 @@ pub(in crate::handlers::lidarr_handlers) struct DeleteArtistHandler<'a, 'b> {
|
|||||||
impl DeleteArtistHandler<'_, '_> {
|
impl DeleteArtistHandler<'_, '_> {
|
||||||
fn build_delete_artist_params(&mut self) -> DeleteParams {
|
fn build_delete_artist_params(&mut self) -> DeleteParams {
|
||||||
let id = self.app.data.lidarr_data.artists.current_selection().id;
|
let id = self.app.data.lidarr_data.artists.current_selection().id;
|
||||||
let delete_files = self.app.data.lidarr_data.delete_artist_files;
|
let delete_files = self.app.data.lidarr_data.delete_files;
|
||||||
let add_import_list_exclusion = self.app.data.lidarr_data.add_import_list_exclusion;
|
let add_import_list_exclusion = self.app.data.lidarr_data.add_import_list_exclusion;
|
||||||
self.app.data.lidarr_data.reset_delete_artist_preferences();
|
self.app.data.lidarr_data.reset_delete_preferences();
|
||||||
|
|
||||||
DeleteParams {
|
DeleteParams {
|
||||||
id,
|
id,
|
||||||
@@ -99,14 +99,13 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveLidarrBlock> for DeleteArtistHandler<
|
|||||||
Some(LidarrEvent::DeleteArtist(self.build_delete_artist_params()));
|
Some(LidarrEvent::DeleteArtist(self.build_delete_artist_params()));
|
||||||
self.app.should_refresh = true;
|
self.app.should_refresh = true;
|
||||||
} else {
|
} else {
|
||||||
self.app.data.lidarr_data.reset_delete_artist_preferences();
|
self.app.data.lidarr_data.reset_delete_preferences();
|
||||||
}
|
}
|
||||||
|
|
||||||
self.app.pop_navigation_stack();
|
self.app.pop_navigation_stack();
|
||||||
}
|
}
|
||||||
ActiveLidarrBlock::DeleteArtistToggleDeleteFile => {
|
ActiveLidarrBlock::DeleteArtistToggleDeleteFile => {
|
||||||
self.app.data.lidarr_data.delete_artist_files =
|
self.app.data.lidarr_data.delete_files = !self.app.data.lidarr_data.delete_files;
|
||||||
!self.app.data.lidarr_data.delete_artist_files;
|
|
||||||
}
|
}
|
||||||
ActiveLidarrBlock::DeleteArtistToggleAddListExclusion => {
|
ActiveLidarrBlock::DeleteArtistToggleAddListExclusion => {
|
||||||
self.app.data.lidarr_data.add_import_list_exclusion =
|
self.app.data.lidarr_data.add_import_list_exclusion =
|
||||||
@@ -120,7 +119,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveLidarrBlock> for DeleteArtistHandler<
|
|||||||
fn handle_esc(&mut self) {
|
fn handle_esc(&mut self) {
|
||||||
if self.active_lidarr_block == ActiveLidarrBlock::DeleteArtistPrompt {
|
if self.active_lidarr_block == ActiveLidarrBlock::DeleteArtistPrompt {
|
||||||
self.app.pop_navigation_stack();
|
self.app.pop_navigation_stack();
|
||||||
self.app.data.lidarr_data.reset_delete_artist_preferences();
|
self.app.data.lidarr_data.reset_delete_preferences();
|
||||||
self.app.data.lidarr_data.prompt_confirm = false;
|
self.app.data.lidarr_data.prompt_confirm = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ mod tests {
|
|||||||
.lidarr_data
|
.lidarr_data
|
||||||
.selected_block
|
.selected_block
|
||||||
.set_index(0, DELETE_ARTIST_SELECTION_BLOCKS.len() - 1);
|
.set_index(0, DELETE_ARTIST_SELECTION_BLOCKS.len() - 1);
|
||||||
app.data.lidarr_data.delete_artist_files = true;
|
app.data.lidarr_data.delete_files = true;
|
||||||
app.data.lidarr_data.add_import_list_exclusion = true;
|
app.data.lidarr_data.add_import_list_exclusion = true;
|
||||||
|
|
||||||
DeleteArtistHandler::new(
|
DeleteArtistHandler::new(
|
||||||
@@ -120,7 +120,7 @@ mod tests {
|
|||||||
assert_navigation_popped!(app, ActiveLidarrBlock::Artists.into());
|
assert_navigation_popped!(app, ActiveLidarrBlock::Artists.into());
|
||||||
assert_none!(app.data.lidarr_data.prompt_confirm_action);
|
assert_none!(app.data.lidarr_data.prompt_confirm_action);
|
||||||
assert!(!app.data.lidarr_data.prompt_confirm);
|
assert!(!app.data.lidarr_data.prompt_confirm);
|
||||||
assert!(!app.data.lidarr_data.delete_artist_files);
|
assert!(!app.data.lidarr_data.delete_files);
|
||||||
assert!(!app.data.lidarr_data.add_import_list_exclusion);
|
assert!(!app.data.lidarr_data.add_import_list_exclusion);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -130,7 +130,7 @@ mod tests {
|
|||||||
app.push_navigation_stack(ActiveLidarrBlock::Artists.into());
|
app.push_navigation_stack(ActiveLidarrBlock::Artists.into());
|
||||||
app.push_navigation_stack(ActiveLidarrBlock::DeleteArtistPrompt.into());
|
app.push_navigation_stack(ActiveLidarrBlock::DeleteArtistPrompt.into());
|
||||||
app.data.lidarr_data.prompt_confirm = true;
|
app.data.lidarr_data.prompt_confirm = true;
|
||||||
app.data.lidarr_data.delete_artist_files = true;
|
app.data.lidarr_data.delete_files = true;
|
||||||
app.data.lidarr_data.add_import_list_exclusion = true;
|
app.data.lidarr_data.add_import_list_exclusion = true;
|
||||||
app
|
app
|
||||||
.data
|
.data
|
||||||
@@ -165,7 +165,7 @@ mod tests {
|
|||||||
);
|
);
|
||||||
assert!(app.should_refresh);
|
assert!(app.should_refresh);
|
||||||
assert!(app.data.lidarr_data.prompt_confirm);
|
assert!(app.data.lidarr_data.prompt_confirm);
|
||||||
assert!(!app.data.lidarr_data.delete_artist_files);
|
assert!(!app.data.lidarr_data.delete_files);
|
||||||
assert!(!app.data.lidarr_data.add_import_list_exclusion);
|
assert!(!app.data.lidarr_data.add_import_list_exclusion);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -176,7 +176,7 @@ mod tests {
|
|||||||
app.push_navigation_stack(ActiveLidarrBlock::Artists.into());
|
app.push_navigation_stack(ActiveLidarrBlock::Artists.into());
|
||||||
app.push_navigation_stack(ActiveLidarrBlock::DeleteArtistPrompt.into());
|
app.push_navigation_stack(ActiveLidarrBlock::DeleteArtistPrompt.into());
|
||||||
app.data.lidarr_data.prompt_confirm = true;
|
app.data.lidarr_data.prompt_confirm = true;
|
||||||
app.data.lidarr_data.delete_artist_files = true;
|
app.data.lidarr_data.delete_files = true;
|
||||||
app.data.lidarr_data.add_import_list_exclusion = true;
|
app.data.lidarr_data.add_import_list_exclusion = true;
|
||||||
|
|
||||||
DeleteArtistHandler::new(
|
DeleteArtistHandler::new(
|
||||||
@@ -194,7 +194,7 @@ mod tests {
|
|||||||
assert_none!(app.data.lidarr_data.prompt_confirm_action);
|
assert_none!(app.data.lidarr_data.prompt_confirm_action);
|
||||||
assert!(!app.should_refresh);
|
assert!(!app.should_refresh);
|
||||||
assert!(app.data.lidarr_data.prompt_confirm);
|
assert!(app.data.lidarr_data.prompt_confirm);
|
||||||
assert!(app.data.lidarr_data.delete_artist_files);
|
assert!(app.data.lidarr_data.delete_files);
|
||||||
assert!(app.data.lidarr_data.add_import_list_exclusion);
|
assert!(app.data.lidarr_data.add_import_list_exclusion);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -215,7 +215,7 @@ mod tests {
|
|||||||
.handle();
|
.handle();
|
||||||
|
|
||||||
assert_eq!(app.get_current_route(), current_route);
|
assert_eq!(app.get_current_route(), current_route);
|
||||||
assert_eq!(app.data.lidarr_data.delete_artist_files, true);
|
assert_eq!(app.data.lidarr_data.delete_files, true);
|
||||||
|
|
||||||
DeleteArtistHandler::new(
|
DeleteArtistHandler::new(
|
||||||
SUBMIT_KEY,
|
SUBMIT_KEY,
|
||||||
@@ -226,7 +226,7 @@ mod tests {
|
|||||||
.handle();
|
.handle();
|
||||||
|
|
||||||
assert_eq!(app.get_current_route(), current_route);
|
assert_eq!(app.get_current_route(), current_route);
|
||||||
assert_eq!(app.data.lidarr_data.delete_artist_files, false);
|
assert_eq!(app.data.lidarr_data.delete_files, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -244,7 +244,7 @@ mod tests {
|
|||||||
app.push_navigation_stack(ActiveLidarrBlock::Artists.into());
|
app.push_navigation_stack(ActiveLidarrBlock::Artists.into());
|
||||||
app.push_navigation_stack(ActiveLidarrBlock::DeleteArtistPrompt.into());
|
app.push_navigation_stack(ActiveLidarrBlock::DeleteArtistPrompt.into());
|
||||||
app.data.lidarr_data.prompt_confirm = true;
|
app.data.lidarr_data.prompt_confirm = true;
|
||||||
app.data.lidarr_data.delete_artist_files = true;
|
app.data.lidarr_data.delete_files = true;
|
||||||
app.data.lidarr_data.add_import_list_exclusion = true;
|
app.data.lidarr_data.add_import_list_exclusion = true;
|
||||||
|
|
||||||
DeleteArtistHandler::new(
|
DeleteArtistHandler::new(
|
||||||
@@ -257,7 +257,7 @@ mod tests {
|
|||||||
|
|
||||||
assert_navigation_popped!(app, ActiveLidarrBlock::Artists.into());
|
assert_navigation_popped!(app, ActiveLidarrBlock::Artists.into());
|
||||||
assert!(!app.data.lidarr_data.prompt_confirm);
|
assert!(!app.data.lidarr_data.prompt_confirm);
|
||||||
assert!(!app.data.lidarr_data.delete_artist_files);
|
assert!(!app.data.lidarr_data.delete_files);
|
||||||
assert!(!app.data.lidarr_data.add_import_list_exclusion);
|
assert!(!app.data.lidarr_data.add_import_list_exclusion);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -279,7 +279,7 @@ mod tests {
|
|||||||
let mut app = App::test_default();
|
let mut app = App::test_default();
|
||||||
app.push_navigation_stack(ActiveLidarrBlock::Artists.into());
|
app.push_navigation_stack(ActiveLidarrBlock::Artists.into());
|
||||||
app.push_navigation_stack(ActiveLidarrBlock::DeleteArtistPrompt.into());
|
app.push_navigation_stack(ActiveLidarrBlock::DeleteArtistPrompt.into());
|
||||||
app.data.lidarr_data.delete_artist_files = true;
|
app.data.lidarr_data.delete_files = true;
|
||||||
app.data.lidarr_data.add_import_list_exclusion = true;
|
app.data.lidarr_data.add_import_list_exclusion = true;
|
||||||
app
|
app
|
||||||
.data
|
.data
|
||||||
@@ -314,7 +314,7 @@ mod tests {
|
|||||||
);
|
);
|
||||||
assert!(app.should_refresh);
|
assert!(app.should_refresh);
|
||||||
assert!(app.data.lidarr_data.prompt_confirm);
|
assert!(app.data.lidarr_data.prompt_confirm);
|
||||||
assert!(!app.data.lidarr_data.delete_artist_files);
|
assert!(!app.data.lidarr_data.delete_files);
|
||||||
assert!(!app.data.lidarr_data.add_import_list_exclusion);
|
assert!(!app.data.lidarr_data.add_import_list_exclusion);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -357,7 +357,7 @@ mod tests {
|
|||||||
.lidarr_data
|
.lidarr_data
|
||||||
.artists
|
.artists
|
||||||
.set_items(vec![Artist::default()]);
|
.set_items(vec![Artist::default()]);
|
||||||
app.data.lidarr_data.delete_artist_files = true;
|
app.data.lidarr_data.delete_files = true;
|
||||||
app.data.lidarr_data.add_import_list_exclusion = true;
|
app.data.lidarr_data.add_import_list_exclusion = true;
|
||||||
let expected_delete_artist_params = DeleteParams {
|
let expected_delete_artist_params = DeleteParams {
|
||||||
id: 0,
|
id: 0,
|
||||||
@@ -374,7 +374,7 @@ mod tests {
|
|||||||
.build_delete_artist_params();
|
.build_delete_artist_params();
|
||||||
|
|
||||||
assert_eq!(delete_artist_params, expected_delete_artist_params);
|
assert_eq!(delete_artist_params, expected_delete_artist_params);
|
||||||
assert!(!app.data.lidarr_data.delete_artist_files);
|
assert!(!app.data.lidarr_data.delete_files);
|
||||||
assert!(!app.data.lidarr_data.add_import_list_exclusion);
|
assert!(!app.data.lidarr_data.add_import_list_exclusion);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,10 +11,10 @@ mod tests {
|
|||||||
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
||||||
use crate::handlers::KeyEventHandler;
|
use crate::handlers::KeyEventHandler;
|
||||||
use crate::handlers::lidarr_handlers::library::{LibraryHandler, artists_sorting_options};
|
use crate::handlers::lidarr_handlers::library::{LibraryHandler, artists_sorting_options};
|
||||||
use crate::models::lidarr_models::{Artist, ArtistStatistics, ArtistStatus};
|
use crate::models::lidarr_models::{Album, Artist, ArtistStatistics, ArtistStatus};
|
||||||
use crate::models::servarr_data::lidarr::lidarr_data::{
|
use crate::models::servarr_data::lidarr::lidarr_data::{
|
||||||
ADD_ARTIST_BLOCKS, ARTIST_DETAILS_BLOCKS, ActiveLidarrBlock, DELETE_ARTIST_BLOCKS,
|
ADD_ARTIST_BLOCKS, ARTIST_DETAILS_BLOCKS, ActiveLidarrBlock, DELETE_ALBUM_BLOCKS,
|
||||||
EDIT_ARTIST_BLOCKS, EDIT_ARTIST_SELECTION_BLOCKS, LIBRARY_BLOCKS,
|
DELETE_ARTIST_BLOCKS, EDIT_ARTIST_BLOCKS, EDIT_ARTIST_SELECTION_BLOCKS, LIBRARY_BLOCKS,
|
||||||
};
|
};
|
||||||
use crate::models::servarr_data::lidarr::modals::EditArtistModal;
|
use crate::models::servarr_data::lidarr::modals::EditArtistModal;
|
||||||
use crate::network::lidarr_network::LidarrEvent;
|
use crate::network::lidarr_network::LidarrEvent;
|
||||||
@@ -28,6 +28,7 @@ mod tests {
|
|||||||
library_handler_blocks.extend(LIBRARY_BLOCKS);
|
library_handler_blocks.extend(LIBRARY_BLOCKS);
|
||||||
library_handler_blocks.extend(ARTIST_DETAILS_BLOCKS);
|
library_handler_blocks.extend(ARTIST_DETAILS_BLOCKS);
|
||||||
library_handler_blocks.extend(DELETE_ARTIST_BLOCKS);
|
library_handler_blocks.extend(DELETE_ARTIST_BLOCKS);
|
||||||
|
library_handler_blocks.extend(DELETE_ALBUM_BLOCKS);
|
||||||
library_handler_blocks.extend(EDIT_ARTIST_BLOCKS);
|
library_handler_blocks.extend(EDIT_ARTIST_BLOCKS);
|
||||||
library_handler_blocks.extend(ADD_ARTIST_BLOCKS);
|
library_handler_blocks.extend(ADD_ARTIST_BLOCKS);
|
||||||
|
|
||||||
@@ -533,6 +534,31 @@ mod tests {
|
|||||||
assert_eq!(app.get_current_route(), ActiveLidarrBlock::Artists.into());
|
assert_eq!(app.get_current_route(), ActiveLidarrBlock::Artists.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_delegates_delete_album_blocks_to_delete_album_handler() {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app
|
||||||
|
.data
|
||||||
|
.lidarr_data
|
||||||
|
.albums
|
||||||
|
.set_items(vec![Album::default()]);
|
||||||
|
app.push_navigation_stack(ActiveLidarrBlock::ArtistDetails.into());
|
||||||
|
app.push_navigation_stack(ActiveLidarrBlock::DeleteAlbumPrompt.into());
|
||||||
|
|
||||||
|
LibraryHandler::new(
|
||||||
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
|
&mut app,
|
||||||
|
ActiveLidarrBlock::DeleteAlbumPrompt,
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
.handle();
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
app.get_current_route(),
|
||||||
|
ActiveLidarrBlock::ArtistDetails.into()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_delegates_delete_artist_blocks_to_delete_artist_handler() {
|
fn test_delegates_delete_artist_blocks_to_delete_artist_handler() {
|
||||||
let mut app = App::test_default();
|
let mut app = App::test_default();
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ use crate::handlers::table_handler::{TableHandlingConfig, handle_table};
|
|||||||
|
|
||||||
mod add_artist_handler;
|
mod add_artist_handler;
|
||||||
mod artist_details_handler;
|
mod artist_details_handler;
|
||||||
|
mod delete_album_handler;
|
||||||
mod delete_artist_handler;
|
mod delete_artist_handler;
|
||||||
mod edit_artist_handler;
|
mod edit_artist_handler;
|
||||||
|
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ pub struct LidarrData<'a> {
|
|||||||
pub albums: StatefulTable<Album>,
|
pub albums: StatefulTable<Album>,
|
||||||
pub artist_info_tabs: TabState,
|
pub artist_info_tabs: TabState,
|
||||||
pub artists: StatefulTable<Artist>,
|
pub artists: StatefulTable<Artist>,
|
||||||
pub delete_artist_files: bool,
|
pub delete_files: bool,
|
||||||
pub disk_space_vec: Vec<DiskSpace>,
|
pub disk_space_vec: Vec<DiskSpace>,
|
||||||
pub downloads: StatefulTable<DownloadRecord>,
|
pub downloads: StatefulTable<DownloadRecord>,
|
||||||
pub edit_artist_modal: Option<EditArtistModal>,
|
pub edit_artist_modal: Option<EditArtistModal>,
|
||||||
@@ -57,8 +57,8 @@ pub struct LidarrData<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl LidarrData<'_> {
|
impl LidarrData<'_> {
|
||||||
pub fn reset_delete_artist_preferences(&mut self) {
|
pub fn reset_delete_preferences(&mut self) {
|
||||||
self.delete_artist_files = false;
|
self.delete_files = false;
|
||||||
self.add_import_list_exclusion = false;
|
self.add_import_list_exclusion = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -108,7 +108,7 @@ impl<'a> Default for LidarrData<'a> {
|
|||||||
add_searched_artists: None,
|
add_searched_artists: None,
|
||||||
albums: StatefulTable::default(),
|
albums: StatefulTable::default(),
|
||||||
artists: StatefulTable::default(),
|
artists: StatefulTable::default(),
|
||||||
delete_artist_files: false,
|
delete_files: false,
|
||||||
disk_space_vec: Vec::new(),
|
disk_space_vec: Vec::new(),
|
||||||
downloads: StatefulTable::default(),
|
downloads: StatefulTable::default(),
|
||||||
edit_artist_modal: None,
|
edit_artist_modal: None,
|
||||||
@@ -176,7 +176,7 @@ impl LidarrData<'_> {
|
|||||||
.set_items(vec![metadata_profile().name]);
|
.set_items(vec![metadata_profile().name]);
|
||||||
|
|
||||||
let mut lidarr_data = LidarrData {
|
let mut lidarr_data = LidarrData {
|
||||||
delete_artist_files: true,
|
delete_files: true,
|
||||||
disk_space_vec: vec![diskspace()],
|
disk_space_vec: vec![diskspace()],
|
||||||
quality_profile_map: quality_profile_map(),
|
quality_profile_map: quality_profile_map(),
|
||||||
metadata_profile_map: metadata_profile_map(),
|
metadata_profile_map: metadata_profile_map(),
|
||||||
@@ -226,6 +226,10 @@ pub enum ActiveLidarrBlock {
|
|||||||
AddArtistSelectRootFolder,
|
AddArtistSelectRootFolder,
|
||||||
AddArtistTagsInput,
|
AddArtistTagsInput,
|
||||||
AutomaticallySearchArtistPrompt,
|
AutomaticallySearchArtistPrompt,
|
||||||
|
DeleteAlbumPrompt,
|
||||||
|
DeleteAlbumConfirmPrompt,
|
||||||
|
DeleteAlbumToggleDeleteFile,
|
||||||
|
DeleteAlbumToggleAddListExclusion,
|
||||||
DeleteArtistPrompt,
|
DeleteArtistPrompt,
|
||||||
DeleteArtistConfirmPrompt,
|
DeleteArtistConfirmPrompt,
|
||||||
DeleteArtistToggleDeleteFile,
|
DeleteArtistToggleDeleteFile,
|
||||||
@@ -304,6 +308,19 @@ pub const DELETE_ARTIST_SELECTION_BLOCKS: &[&[ActiveLidarrBlock]] = &[
|
|||||||
&[ActiveLidarrBlock::DeleteArtistConfirmPrompt],
|
&[ActiveLidarrBlock::DeleteArtistConfirmPrompt],
|
||||||
];
|
];
|
||||||
|
|
||||||
|
pub static DELETE_ALBUM_BLOCKS: [ActiveLidarrBlock; 4] = [
|
||||||
|
ActiveLidarrBlock::DeleteAlbumPrompt,
|
||||||
|
ActiveLidarrBlock::DeleteAlbumConfirmPrompt,
|
||||||
|
ActiveLidarrBlock::DeleteAlbumToggleDeleteFile,
|
||||||
|
ActiveLidarrBlock::DeleteAlbumToggleAddListExclusion,
|
||||||
|
];
|
||||||
|
|
||||||
|
pub const DELETE_ALBUM_SELECTION_BLOCKS: &[&[ActiveLidarrBlock]] = &[
|
||||||
|
&[ActiveLidarrBlock::DeleteAlbumToggleDeleteFile],
|
||||||
|
&[ActiveLidarrBlock::DeleteAlbumToggleAddListExclusion],
|
||||||
|
&[ActiveLidarrBlock::DeleteAlbumConfirmPrompt],
|
||||||
|
];
|
||||||
|
|
||||||
pub static EDIT_ARTIST_BLOCKS: [ActiveLidarrBlock; 8] = [
|
pub static EDIT_ARTIST_BLOCKS: [ActiveLidarrBlock; 8] = [
|
||||||
ActiveLidarrBlock::EditArtistPrompt,
|
ActiveLidarrBlock::EditArtistPrompt,
|
||||||
ActiveLidarrBlock::EditArtistConfirmPrompt,
|
ActiveLidarrBlock::EditArtistConfirmPrompt,
|
||||||
|
|||||||
@@ -5,8 +5,9 @@ mod tests {
|
|||||||
};
|
};
|
||||||
use crate::models::lidarr_models::Album;
|
use crate::models::lidarr_models::Album;
|
||||||
use crate::models::servarr_data::lidarr::lidarr_data::{
|
use crate::models::servarr_data::lidarr::lidarr_data::{
|
||||||
ADD_ARTIST_BLOCKS, ADD_ARTIST_SELECTION_BLOCKS, ARTIST_DETAILS_BLOCKS, DELETE_ARTIST_BLOCKS,
|
ADD_ARTIST_BLOCKS, ADD_ARTIST_SELECTION_BLOCKS, ARTIST_DETAILS_BLOCKS, DELETE_ALBUM_BLOCKS,
|
||||||
DELETE_ARTIST_SELECTION_BLOCKS, EDIT_ARTIST_BLOCKS, EDIT_ARTIST_SELECTION_BLOCKS,
|
DELETE_ALBUM_SELECTION_BLOCKS, DELETE_ARTIST_BLOCKS, DELETE_ARTIST_SELECTION_BLOCKS,
|
||||||
|
EDIT_ARTIST_BLOCKS, EDIT_ARTIST_SELECTION_BLOCKS,
|
||||||
};
|
};
|
||||||
use crate::models::{
|
use crate::models::{
|
||||||
BlockSelectionState, Route,
|
BlockSelectionState, Route,
|
||||||
@@ -34,16 +35,16 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_reset_delete_artist_preferences() {
|
fn test_reset_delete_preferences() {
|
||||||
let mut lidarr_data = LidarrData {
|
let mut lidarr_data = LidarrData {
|
||||||
delete_artist_files: true,
|
delete_files: true,
|
||||||
add_import_list_exclusion: true,
|
add_import_list_exclusion: true,
|
||||||
..LidarrData::default()
|
..LidarrData::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
lidarr_data.reset_delete_artist_preferences();
|
lidarr_data.reset_delete_preferences();
|
||||||
|
|
||||||
assert!(!lidarr_data.delete_artist_files);
|
assert!(!lidarr_data.delete_files);
|
||||||
assert!(!lidarr_data.add_import_list_exclusion);
|
assert!(!lidarr_data.add_import_list_exclusion);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -129,7 +130,7 @@ mod tests {
|
|||||||
assert_none!(lidarr_data.add_searched_artists);
|
assert_none!(lidarr_data.add_searched_artists);
|
||||||
assert_is_empty!(lidarr_data.albums);
|
assert_is_empty!(lidarr_data.albums);
|
||||||
assert_is_empty!(lidarr_data.artists);
|
assert_is_empty!(lidarr_data.artists);
|
||||||
assert!(!lidarr_data.delete_artist_files);
|
assert!(!lidarr_data.delete_files);
|
||||||
assert_is_empty!(lidarr_data.disk_space_vec);
|
assert_is_empty!(lidarr_data.disk_space_vec);
|
||||||
assert_is_empty!(lidarr_data.downloads);
|
assert_is_empty!(lidarr_data.downloads);
|
||||||
assert_none!(lidarr_data.edit_artist_modal);
|
assert_none!(lidarr_data.edit_artist_modal);
|
||||||
@@ -271,6 +272,34 @@ mod tests {
|
|||||||
assert_none!(delete_artist_block_iter.next());
|
assert_none!(delete_artist_block_iter.next());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_delete_album_blocks_contents() {
|
||||||
|
assert_eq!(DELETE_ALBUM_BLOCKS.len(), 4);
|
||||||
|
assert!(DELETE_ALBUM_BLOCKS.contains(&ActiveLidarrBlock::DeleteAlbumPrompt));
|
||||||
|
assert!(DELETE_ALBUM_BLOCKS.contains(&ActiveLidarrBlock::DeleteAlbumConfirmPrompt));
|
||||||
|
assert!(DELETE_ALBUM_BLOCKS.contains(&ActiveLidarrBlock::DeleteAlbumToggleDeleteFile));
|
||||||
|
assert!(DELETE_ALBUM_BLOCKS.contains(&ActiveLidarrBlock::DeleteAlbumToggleAddListExclusion));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_delete_album_selection_blocks_ordering() {
|
||||||
|
let mut delete_album_block_iter = DELETE_ALBUM_SELECTION_BLOCKS.iter();
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
delete_album_block_iter.next().unwrap(),
|
||||||
|
&[ActiveLidarrBlock::DeleteAlbumToggleDeleteFile]
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
delete_album_block_iter.next().unwrap(),
|
||||||
|
&[ActiveLidarrBlock::DeleteAlbumToggleAddListExclusion]
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
delete_album_block_iter.next().unwrap(),
|
||||||
|
&[ActiveLidarrBlock::DeleteAlbumConfirmPrompt]
|
||||||
|
);
|
||||||
|
assert_none!(delete_album_block_iter.next());
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_edit_artist_blocks() {
|
fn test_edit_artist_blocks() {
|
||||||
assert_eq!(EDIT_ARTIST_BLOCKS.len(), 8);
|
assert_eq!(EDIT_ARTIST_BLOCKS.len(), 8);
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ use crate::app::App;
|
|||||||
use crate::models::Route;
|
use crate::models::Route;
|
||||||
use crate::models::lidarr_models::Album;
|
use crate::models::lidarr_models::Album;
|
||||||
use crate::models::servarr_data::lidarr::lidarr_data::{ARTIST_DETAILS_BLOCKS, ActiveLidarrBlock};
|
use crate::models::servarr_data::lidarr::lidarr_data::{ARTIST_DETAILS_BLOCKS, ActiveLidarrBlock};
|
||||||
|
use crate::ui::lidarr_ui::library::delete_album_ui::DeleteAlbumUi;
|
||||||
use crate::ui::styles::ManagarrStyle;
|
use crate::ui::styles::ManagarrStyle;
|
||||||
use crate::ui::utils::{
|
use crate::ui::utils::{
|
||||||
borderless_block, get_width_from_percentage, layout_block_top_border, title_block,
|
borderless_block, get_width_from_percentage, layout_block_top_border, title_block,
|
||||||
@@ -32,10 +33,10 @@ impl DrawUi for ArtistDetailsUi {
|
|||||||
let Route::Lidarr(active_lidarr_block, _) = route else {
|
let Route::Lidarr(active_lidarr_block, _) = route else {
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
ARTIST_DETAILS_BLOCKS.contains(&active_lidarr_block)
|
DeleteAlbumUi::accepts(route) || ARTIST_DETAILS_BLOCKS.contains(&active_lidarr_block)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw(f: &mut Frame<'_>, app: &mut App<'_>, _area: Rect) {
|
fn draw(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) {
|
||||||
let route = app.get_current_route();
|
let route = app.get_current_route();
|
||||||
if let Route::Lidarr(active_lidarr_block, _) = route {
|
if let Route::Lidarr(active_lidarr_block, _) = route {
|
||||||
let draw_artist_details_popup = |f: &mut Frame<'_>, app: &mut App<'_>, popup_area: Rect| {
|
let draw_artist_details_popup = |f: &mut Frame<'_>, app: &mut App<'_>, popup_area: Rect| {
|
||||||
@@ -65,6 +66,7 @@ impl DrawUi for ArtistDetailsUi {
|
|||||||
draw_artist_details(f, app, content_area);
|
draw_artist_details(f, app, content_area);
|
||||||
|
|
||||||
match active_lidarr_block {
|
match active_lidarr_block {
|
||||||
|
_ if DeleteAlbumUi::accepts(route) => DeleteAlbumUi::draw(f, app, area),
|
||||||
ActiveLidarrBlock::AutomaticallySearchArtistPrompt => {
|
ActiveLidarrBlock::AutomaticallySearchArtistPrompt => {
|
||||||
let prompt = format!(
|
let prompt = format!(
|
||||||
"Do you want to trigger an automatic search of your indexers for all monitored album(s) for the artist: {}?",
|
"Do you want to trigger an automatic search of your indexers for all monitored album(s) for the artist: {}?",
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ mod tests {
|
|||||||
use strum::IntoEnumIterator;
|
use strum::IntoEnumIterator;
|
||||||
|
|
||||||
use crate::models::servarr_data::lidarr::lidarr_data::{
|
use crate::models::servarr_data::lidarr::lidarr_data::{
|
||||||
ARTIST_DETAILS_BLOCKS, ActiveLidarrBlock,
|
ARTIST_DETAILS_BLOCKS, ActiveLidarrBlock, DELETE_ALBUM_BLOCKS,
|
||||||
};
|
};
|
||||||
use crate::ui::DrawUi;
|
use crate::ui::DrawUi;
|
||||||
use crate::ui::lidarr_ui::library::artist_details_ui::ArtistDetailsUi;
|
use crate::ui::lidarr_ui::library::artist_details_ui::ArtistDetailsUi;
|
||||||
@@ -11,6 +11,8 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_artist_details_ui_accepts() {
|
fn test_artist_details_ui_accepts() {
|
||||||
let mut blocks = ARTIST_DETAILS_BLOCKS.clone().to_vec();
|
let mut blocks = ARTIST_DETAILS_BLOCKS.clone().to_vec();
|
||||||
|
blocks.extend(DELETE_ALBUM_BLOCKS);
|
||||||
|
|
||||||
ActiveLidarrBlock::iter().for_each(|active_lidarr_block| {
|
ActiveLidarrBlock::iter().for_each(|active_lidarr_block| {
|
||||||
if blocks.contains(&active_lidarr_block) {
|
if blocks.contains(&active_lidarr_block) {
|
||||||
assert!(ArtistDetailsUi::accepts(active_lidarr_block.into()));
|
assert!(ArtistDetailsUi::accepts(active_lidarr_block.into()));
|
||||||
@@ -24,7 +26,10 @@ mod tests {
|
|||||||
use rstest::rstest;
|
use rstest::rstest;
|
||||||
|
|
||||||
use crate::app::App;
|
use crate::app::App;
|
||||||
use crate::models::servarr_data::lidarr::lidarr_data::ActiveLidarrBlock;
|
use crate::models::BlockSelectionState;
|
||||||
|
use crate::models::servarr_data::lidarr::lidarr_data::{
|
||||||
|
ActiveLidarrBlock, DELETE_ALBUM_SELECTION_BLOCKS,
|
||||||
|
};
|
||||||
use crate::models::stateful_table::StatefulTable;
|
use crate::models::stateful_table::StatefulTable;
|
||||||
use crate::ui::DrawUi;
|
use crate::ui::DrawUi;
|
||||||
use crate::ui::lidarr_ui::library::artist_details_ui::ArtistDetailsUi;
|
use crate::ui::lidarr_ui::library::artist_details_ui::ArtistDetailsUi;
|
||||||
@@ -96,6 +101,20 @@ mod tests {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_artist_details_ui_renders_delete_album_prompt_over_artist_details() {
|
||||||
|
let mut app = App::test_default_fully_populated();
|
||||||
|
app.data.lidarr_data.selected_block = BlockSelectionState::new(DELETE_ALBUM_SELECTION_BLOCKS);
|
||||||
|
app.push_navigation_stack(ActiveLidarrBlock::ArtistDetails.into());
|
||||||
|
app.push_navigation_stack(ActiveLidarrBlock::DeleteAlbumPrompt.into());
|
||||||
|
|
||||||
|
let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| {
|
||||||
|
ArtistDetailsUi::draw(f, app, f.area());
|
||||||
|
});
|
||||||
|
|
||||||
|
insta::assert_snapshot!(output);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_artist_details_ui_renders_update_and_scan_prompt_over_artist_details() {
|
fn test_artist_details_ui_renders_update_and_scan_prompt_over_artist_details() {
|
||||||
let mut app = App::test_default_fully_populated();
|
let mut app = App::test_default_fully_populated();
|
||||||
|
|||||||
@@ -0,0 +1,57 @@
|
|||||||
|
use ratatui::Frame;
|
||||||
|
use ratatui::layout::Rect;
|
||||||
|
|
||||||
|
use crate::app::App;
|
||||||
|
use crate::models::Route;
|
||||||
|
use crate::models::servarr_data::lidarr::lidarr_data::{ActiveLidarrBlock, DELETE_ALBUM_BLOCKS};
|
||||||
|
use crate::ui::DrawUi;
|
||||||
|
use crate::ui::widgets::checkbox::Checkbox;
|
||||||
|
use crate::ui::widgets::confirmation_prompt::ConfirmationPrompt;
|
||||||
|
use crate::ui::widgets::popup::{Popup, Size};
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
#[path = "delete_album_ui_tests.rs"]
|
||||||
|
mod delete_album_ui_tests;
|
||||||
|
|
||||||
|
pub(in crate::ui::lidarr_ui) struct DeleteAlbumUi;
|
||||||
|
|
||||||
|
impl DrawUi for DeleteAlbumUi {
|
||||||
|
fn accepts(route: Route) -> bool {
|
||||||
|
let Route::Lidarr(active_lidarr_block, _) = route else {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
DELETE_ALBUM_BLOCKS.contains(&active_lidarr_block)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn draw(f: &mut Frame<'_>, app: &mut App<'_>, _area: Rect) {
|
||||||
|
if matches!(
|
||||||
|
app.get_current_route(),
|
||||||
|
Route::Lidarr(ActiveLidarrBlock::DeleteAlbumPrompt, _)
|
||||||
|
) {
|
||||||
|
let selected_block = app.data.lidarr_data.selected_block.get_active_block();
|
||||||
|
let prompt = format!(
|
||||||
|
"Do you really want to delete the album: \n{}?",
|
||||||
|
app.data.lidarr_data.albums.current_selection().title.text
|
||||||
|
);
|
||||||
|
let checkboxes = vec![
|
||||||
|
Checkbox::new("Delete Album Files")
|
||||||
|
.checked(app.data.lidarr_data.delete_files)
|
||||||
|
.highlighted(selected_block == ActiveLidarrBlock::DeleteAlbumToggleDeleteFile),
|
||||||
|
Checkbox::new("Add List Exclusion")
|
||||||
|
.checked(app.data.lidarr_data.add_import_list_exclusion)
|
||||||
|
.highlighted(selected_block == ActiveLidarrBlock::DeleteAlbumToggleAddListExclusion),
|
||||||
|
];
|
||||||
|
let confirmation_prompt = ConfirmationPrompt::new()
|
||||||
|
.title("Delete Album")
|
||||||
|
.prompt(&prompt)
|
||||||
|
.checkboxes(checkboxes)
|
||||||
|
.yes_no_highlighted(selected_block == ActiveLidarrBlock::DeleteAlbumConfirmPrompt)
|
||||||
|
.yes_no_value(app.data.lidarr_data.prompt_confirm);
|
||||||
|
|
||||||
|
f.render_widget(
|
||||||
|
Popup::new(confirmation_prompt).size(Size::MediumPrompt),
|
||||||
|
f.area(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use strum::IntoEnumIterator;
|
||||||
|
|
||||||
|
use crate::app::App;
|
||||||
|
use crate::models::BlockSelectionState;
|
||||||
|
use crate::models::servarr_data::lidarr::lidarr_data::{
|
||||||
|
ActiveLidarrBlock, DELETE_ALBUM_BLOCKS, DELETE_ALBUM_SELECTION_BLOCKS,
|
||||||
|
};
|
||||||
|
use crate::ui::DrawUi;
|
||||||
|
use crate::ui::lidarr_ui::library::delete_album_ui::DeleteAlbumUi;
|
||||||
|
use crate::ui::ui_test_utils::test_utils::render_to_string_with_app;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_delete_album_ui_accepts() {
|
||||||
|
ActiveLidarrBlock::iter().for_each(|active_lidarr_block| {
|
||||||
|
if DELETE_ALBUM_BLOCKS.contains(&active_lidarr_block) {
|
||||||
|
assert!(DeleteAlbumUi::accepts(active_lidarr_block.into()));
|
||||||
|
} else {
|
||||||
|
assert!(!DeleteAlbumUi::accepts(active_lidarr_block.into()));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
mod snapshot_tests {
|
||||||
|
use crate::ui::ui_test_utils::test_utils::TerminalSize;
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_delete_album_ui_renders_delete_album() {
|
||||||
|
let mut app = App::test_default_fully_populated();
|
||||||
|
app.push_navigation_stack(ActiveLidarrBlock::DeleteAlbumPrompt.into());
|
||||||
|
app.data.lidarr_data.selected_block = BlockSelectionState::new(DELETE_ALBUM_SELECTION_BLOCKS);
|
||||||
|
|
||||||
|
let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| {
|
||||||
|
DeleteAlbumUi::draw(f, app, f.area());
|
||||||
|
});
|
||||||
|
|
||||||
|
insta::assert_snapshot!(output);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -41,7 +41,7 @@ impl DrawUi for DeleteArtistUi {
|
|||||||
);
|
);
|
||||||
let checkboxes = vec![
|
let checkboxes = vec![
|
||||||
Checkbox::new("Delete Artist Files")
|
Checkbox::new("Delete Artist Files")
|
||||||
.checked(app.data.lidarr_data.delete_artist_files)
|
.checked(app.data.lidarr_data.delete_files)
|
||||||
.highlighted(selected_block == ActiveLidarrBlock::DeleteArtistToggleDeleteFile),
|
.highlighted(selected_block == ActiveLidarrBlock::DeleteArtistToggleDeleteFile),
|
||||||
Checkbox::new("Add List Exclusion")
|
Checkbox::new("Add List Exclusion")
|
||||||
.checked(app.data.lidarr_data.add_import_list_exclusion)
|
.checked(app.data.lidarr_data.add_import_list_exclusion)
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ mod tests {
|
|||||||
|
|
||||||
use crate::models::lidarr_models::{Artist, ArtistStatistics, ArtistStatus};
|
use crate::models::lidarr_models::{Artist, ArtistStatistics, ArtistStatus};
|
||||||
use crate::models::servarr_data::lidarr::lidarr_data::{
|
use crate::models::servarr_data::lidarr::lidarr_data::{
|
||||||
ADD_ARTIST_BLOCKS, ARTIST_DETAILS_BLOCKS, ActiveLidarrBlock, DELETE_ARTIST_BLOCKS,
|
ADD_ARTIST_BLOCKS, ARTIST_DETAILS_BLOCKS, ActiveLidarrBlock, DELETE_ALBUM_BLOCKS,
|
||||||
EDIT_ARTIST_BLOCKS, LIBRARY_BLOCKS,
|
DELETE_ARTIST_BLOCKS, EDIT_ARTIST_BLOCKS, LIBRARY_BLOCKS,
|
||||||
};
|
};
|
||||||
use crate::ui::DrawUi;
|
use crate::ui::DrawUi;
|
||||||
use crate::ui::lidarr_ui::library::{LibraryUi, decorate_artist_row_with_style};
|
use crate::ui::lidarr_ui::library::{LibraryUi, decorate_artist_row_with_style};
|
||||||
@@ -18,6 +18,7 @@ mod tests {
|
|||||||
let mut library_ui_blocks = Vec::new();
|
let mut library_ui_blocks = Vec::new();
|
||||||
library_ui_blocks.extend(LIBRARY_BLOCKS);
|
library_ui_blocks.extend(LIBRARY_BLOCKS);
|
||||||
library_ui_blocks.extend(DELETE_ARTIST_BLOCKS);
|
library_ui_blocks.extend(DELETE_ARTIST_BLOCKS);
|
||||||
|
library_ui_blocks.extend(DELETE_ALBUM_BLOCKS);
|
||||||
library_ui_blocks.extend(EDIT_ARTIST_BLOCKS);
|
library_ui_blocks.extend(EDIT_ARTIST_BLOCKS);
|
||||||
library_ui_blocks.extend(ADD_ARTIST_BLOCKS);
|
library_ui_blocks.extend(ADD_ARTIST_BLOCKS);
|
||||||
library_ui_blocks.extend(ARTIST_DETAILS_BLOCKS);
|
library_ui_blocks.extend(ARTIST_DETAILS_BLOCKS);
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ mod artist_details_ui;
|
|||||||
mod delete_artist_ui;
|
mod delete_artist_ui;
|
||||||
mod edit_artist_ui;
|
mod edit_artist_ui;
|
||||||
|
|
||||||
|
mod delete_album_ui;
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
#[path = "library_ui_tests.rs"]
|
#[path = "library_ui_tests.rs"]
|
||||||
mod library_ui_tests;
|
mod library_ui_tests;
|
||||||
@@ -59,8 +60,8 @@ impl DrawUi for LibraryUi {
|
|||||||
match route {
|
match route {
|
||||||
_ if AddArtistUi::accepts(route) => AddArtistUi::draw(f, app, area),
|
_ if AddArtistUi::accepts(route) => AddArtistUi::draw(f, app, area),
|
||||||
_ if DeleteArtistUi::accepts(route) => DeleteArtistUi::draw(f, app, area),
|
_ if DeleteArtistUi::accepts(route) => DeleteArtistUi::draw(f, app, area),
|
||||||
_ if EditArtistUi::accepts(route) => EditArtistUi::draw(f, app, area),
|
|
||||||
_ if ArtistDetailsUi::accepts(route) => ArtistDetailsUi::draw(f, app, area),
|
_ if ArtistDetailsUi::accepts(route) => ArtistDetailsUi::draw(f, app, area),
|
||||||
|
_ if EditArtistUi::accepts(route) => EditArtistUi::draw(f, app, area),
|
||||||
Route::Lidarr(ActiveLidarrBlock::UpdateAllArtistsPrompt, _) => {
|
Route::Lidarr(ActiveLidarrBlock::UpdateAllArtistsPrompt, _) => {
|
||||||
let confirmation_prompt = ConfirmationPrompt::new()
|
let confirmation_prompt = ConfirmationPrompt::new()
|
||||||
.title("Update All Artists")
|
.title("Update All Artists")
|
||||||
|
|||||||
+52
@@ -0,0 +1,52 @@
|
|||||||
|
---
|
||||||
|
source: src/ui/lidarr_ui/library/artist_details_ui_tests.rs
|
||||||
|
expression: output
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
╭ Alex ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
|
||||||
|
│Artist: Alex │
|
||||||
|
│Overview: some interesting description of the artist │
|
||||||
|
│Disambiguation: American pianist │
|
||||||
|
│Type: Person │
|
||||||
|
│Status: Continuing │
|
||||||
|
│Genres: soundtrack │
|
||||||
|
│Rating: 84% │
|
||||||
|
│Path: /nfs/music/test-artist │
|
||||||
|
│Quality Profile: Lossless │
|
||||||
|
│Metadata Profile: Standard │
|
||||||
|
│Monitored: Yes │
|
||||||
|
│Albums: 1 │
|
||||||
|
│Tracks: 15/15 ╭───────────────────── Delete Album ──────────────────────╮ │
|
||||||
|
│Size on Disk: 0.00 GB │ Do you really want to delete the album: │ │
|
||||||
|
│ │ Test Album? │ │
|
||||||
|
│ │ │ │
|
||||||
|
│╭ Artist Details ───────────────────────│ │───────────────────────────────────────────╮│
|
||||||
|
││ Albums │ ╭───╮ │ ││
|
||||||
|
││─────────────────────────────────────────│ Delete Album Files: │ ✔ │ │───────────────────────────────────────────││
|
||||||
|
││ Monitored Title │ ╰───╯ │ Release Date Size ││
|
||||||
|
││=> 🏷 Test Album │ ╭───╮ │ 2023-01-01 0.00 GB ││
|
||||||
|
││ │ Add List Exclusion: │ │ │ ││
|
||||||
|
││ │ ╰───╯ │ ││
|
||||||
|
││ │ │ ││
|
||||||
|
││ │ │ ││
|
||||||
|
││ │ │ ││
|
||||||
|
││ │╭────────────────────────────╮╭───────────────────────────╮│ ││
|
||||||
|
││ ││ Yes ││ No ││ ││
|
||||||
|
││ │╰────────────────────────────╯╰───────────────────────────╯│ ││
|
||||||
|
││ ╰───────────────────────────────────────────────────────────╯ ││
|
||||||
|
││ ││
|
||||||
|
││ ││
|
||||||
|
││ ││
|
||||||
|
││ ││
|
||||||
|
││ ││
|
||||||
|
││ ││
|
||||||
|
││ ││
|
||||||
|
││ ││
|
||||||
|
││ ││
|
||||||
|
││ ││
|
||||||
|
││ ││
|
||||||
|
││ ││
|
||||||
|
│╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯│
|
||||||
|
╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
|
||||||
+38
@@ -0,0 +1,38 @@
|
|||||||
|
---
|
||||||
|
source: src/ui/lidarr_ui/library/delete_album_ui_tests.rs
|
||||||
|
expression: output
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
╭───────────────────── Delete Album ──────────────────────╮
|
||||||
|
│ Do you really want to delete the album: │
|
||||||
|
│ Test Album? │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ ╭───╮ │
|
||||||
|
│ Delete Album Files: │ ✔ │ │
|
||||||
|
│ ╰───╯ │
|
||||||
|
│ ╭───╮ │
|
||||||
|
│ Add List Exclusion: │ │ │
|
||||||
|
│ ╰───╯ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│╭────────────────────────────╮╭───────────────────────────╮│
|
||||||
|
││ Yes ││ No ││
|
||||||
|
│╰────────────────────────────╯╰───────────────────────────╯│
|
||||||
|
╰───────────────────────────────────────────────────────────╯
|
||||||
Reference in New Issue
Block a user