diff --git a/.cargo-husky/hooks/pre-commit b/.cargo-husky/hooks/pre-commit old mode 100755 new mode 100644 diff --git a/.cargo-husky/hooks/pre-push b/.cargo-husky/hooks/pre-push old mode 100755 new mode 100644 diff --git a/Cargo.toml b/Cargo.toml index 89143f6..9fb8d5d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "managarr" -version = "0.0.19" +version = "0.0.20" authors = ["Alex Clarke "] description = "A TUI for managing *arr servers" keywords = ["managarr", "tui-rs", "dashboard", "servarr"] diff --git a/src/app/app_tests.rs b/src/app/app_tests.rs index 1beb12c..115ffad 100644 --- a/src/app/app_tests.rs +++ b/src/app/app_tests.rs @@ -6,7 +6,7 @@ mod tests { use crate::app::context_clues::{build_context_clue_string, SERVARR_CONTEXT_CLUES}; use crate::app::{App, Data, RadarrConfig, DEFAULT_ROUTE}; - use crate::models::servarr_data::radarr_data::{ActiveRadarrBlock, RadarrData}; + use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, RadarrData}; use crate::models::{HorizontallyScrollableText, Route, TabRoute}; use crate::network::radarr_network::RadarrEvent; use crate::network::NetworkEvent; diff --git a/src/app/mod.rs b/src/app/mod.rs index 305f135..d38821d 100644 --- a/src/app/mod.rs +++ b/src/app/mod.rs @@ -6,7 +6,7 @@ use tokio::time::Instant; use tokio_util::sync::CancellationToken; use crate::app::context_clues::{build_context_clue_string, SERVARR_CONTEXT_CLUES}; -use crate::models::servarr_data::radarr_data::{ActiveRadarrBlock, RadarrData}; +use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, RadarrData}; use crate::models::{HorizontallyScrollableText, Route, TabRoute, TabState}; use crate::network::NetworkEvent; diff --git a/src/app/radarr/mod.rs b/src/app/radarr/mod.rs index e9d45f8..b70fdba 100644 --- a/src/app/radarr/mod.rs +++ b/src/app/radarr/mod.rs @@ -1,5 +1,5 @@ use crate::app::App; -use crate::models::servarr_data::radarr_data::ActiveRadarrBlock; +use crate::models::servarr_data::radarr::radarr_data::ActiveRadarrBlock; use crate::network::radarr_network::RadarrEvent; pub mod radarr_context_clues; diff --git a/src/handlers/handler_test_utils.rs b/src/handlers/handler_test_utils.rs index c241b32..ed09f47 100644 --- a/src/handlers/handler_test_utils.rs +++ b/src/handlers/handler_test_utils.rs @@ -202,42 +202,6 @@ mod test_utils { }; } - #[macro_export] - macro_rules! test_enum_scroll { - ($func:ident, $handler:ident, $name:ident, $data_ref:ident, $block:expr, $context:expr) => { - #[rstest] - fn $func(#[values(DEFAULT_KEYBINDINGS.up.key, DEFAULT_KEYBINDINGS.down.key)] key: Key) { - let reference_vec = Vec::from_iter($name::iter()); - let mut app = App::default(); - app - .data - .radarr_data - .$data_ref - .set_items(reference_vec.clone()); - - if key == Key::Up { - for i in (0..reference_vec.len()).rev() { - $handler::with(&key, &mut app, &$block, &$context).handle(); - - assert_eq!( - app.data.radarr_data.$data_ref.current_selection(), - &reference_vec[i] - ); - } - } else { - for i in 0..reference_vec.len() { - $handler::with(&key, &mut app, &$block, &$context).handle(); - - assert_eq!( - app.data.radarr_data.$data_ref.current_selection(), - &reference_vec[(i + 1) % reference_vec.len()] - ); - } - } - } - }; - } - #[macro_export] macro_rules! test_scrollable_text_scroll { ($func:ident, $handler:ident, $data_ref:ident, $block:expr) => { @@ -362,36 +326,6 @@ mod test_utils { }; } - #[macro_export] - macro_rules! test_enum_home_and_end { - ($func:ident, $handler:ident, $name:ident, $data_ref:ident, $block:expr, $context:expr) => { - #[test] - fn $func() { - let reference_vec = Vec::from_iter($name::iter()); - let mut app = App::default(); - app - .data - .radarr_data - .$data_ref - .set_items(reference_vec.clone()); - - $handler::with(&DEFAULT_KEYBINDINGS.end.key, &mut app, &$block, &$context).handle(); - - assert_eq!( - app.data.radarr_data.$data_ref.current_selection(), - &reference_vec[reference_vec.len() - 1] - ); - - $handler::with(&DEFAULT_KEYBINDINGS.home.key, &mut app, &$block, &$context).handle(); - - assert_eq!( - app.data.radarr_data.$data_ref.current_selection(), - &reference_vec[0] - ); - } - }; - } - #[macro_export] macro_rules! test_scrollable_text_home_and_end { ($func:ident, $handler:ident, $data_ref:ident, $block:expr) => { diff --git a/src/handlers/radarr_handlers/collections/collection_details_handler.rs b/src/handlers/radarr_handlers/collections/collection_details_handler.rs index 7adb1b7..44c67b5 100644 --- a/src/handlers/radarr_handlers/collections/collection_details_handler.rs +++ b/src/handlers/radarr_handlers/collections/collection_details_handler.rs @@ -2,11 +2,11 @@ use crate::app::key_binding::DEFAULT_KEYBINDINGS; use crate::app::App; use crate::event::Key; use crate::handlers::KeyEventHandler; -use crate::models::servarr_data::radarr_data::{ +use crate::models::servarr_data::radarr::radarr_data::{ ActiveRadarrBlock, ADD_MOVIE_SELECTION_BLOCKS, COLLECTION_DETAILS_BLOCKS, EDIT_COLLECTION_SELECTION_BLOCKS, }; -use crate::models::{BlockSelectionState, Scrollable}; +use crate::models::{BlockSelectionState, Scrollable, StatefulTable}; #[cfg(test)] #[path = "collection_details_handler_tests.rs"] @@ -108,7 +108,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for CollectionDetailsHan ); self.app.data.radarr_data.selected_block = BlockSelectionState::new(&ADD_MOVIE_SELECTION_BLOCKS); - self.app.data.radarr_data.populate_preferences_lists(); + self.app.data.radarr_data.add_movie_modal = Some((&self.app.data.radarr_data).into()); } } } @@ -116,8 +116,8 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for CollectionDetailsHan fn handle_esc(&mut self) { match self.active_radarr_block { ActiveRadarrBlock::CollectionDetails => { + self.app.data.radarr_data.collection_movies = StatefulTable::default(); self.app.pop_navigation_stack(); - self.app.data.radarr_data.reset_movie_collection_table(); } ActiveRadarrBlock::ViewMovieOverview => self.app.pop_navigation_stack(), _ => (), @@ -135,7 +135,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for CollectionDetailsHan ) .into(), ); - self.app.data.radarr_data.populate_edit_collection_fields(); + self.app.data.radarr_data.edit_collection_modal = Some((&self.app.data.radarr_data).into()); self.app.data.radarr_data.selected_block = BlockSelectionState::new(&EDIT_COLLECTION_SELECTION_BLOCKS); } diff --git a/src/handlers/radarr_handlers/collections/collection_details_handler_tests.rs b/src/handlers/radarr_handlers/collections/collection_details_handler_tests.rs index 103b404..e626456 100644 --- a/src/handlers/radarr_handlers/collections/collection_details_handler_tests.rs +++ b/src/handlers/radarr_handlers/collections/collection_details_handler_tests.rs @@ -9,7 +9,9 @@ mod tests { use crate::handlers::radarr_handlers::collections::collection_details_handler::CollectionDetailsHandler; use crate::handlers::KeyEventHandler; use crate::models::radarr_models::CollectionMovie; - use crate::models::servarr_data::radarr_data::{ActiveRadarrBlock, COLLECTION_DETAILS_BLOCKS}; + use crate::models::servarr_data::radarr::radarr_data::{ + ActiveRadarrBlock, COLLECTION_DETAILS_BLOCKS, + }; use crate::models::HorizontallyScrollableText; mod test_handle_scroll_up_and_down { @@ -53,7 +55,7 @@ mod tests { use pretty_assertions::assert_eq; use crate::models::radarr_models::Movie; - use crate::models::servarr_data::radarr_data::ADD_MOVIE_SELECTION_BLOCKS; + use crate::models::servarr_data::radarr::radarr_data::ADD_MOVIE_SELECTION_BLOCKS; use crate::models::BlockSelectionState; use super::*; @@ -93,7 +95,15 @@ mod tests { ) .into() ); - assert!(!app.data.radarr_data.monitor_list.items.is_empty()); + assert!(!app + .data + .radarr_data + .add_movie_modal + .as_ref() + .unwrap() + .monitor_list + .items + .is_empty()); assert_eq!( app.data.radarr_data.selected_block.get_active_block(), &ActiveRadarrBlock::AddMovieSelectRootFolder @@ -101,14 +111,28 @@ mod tests { assert!(!app .data .radarr_data + .add_movie_modal + .as_ref() + .unwrap() .minimum_availability_list .items .is_empty()); - assert!(!app.data.radarr_data.quality_profile_list.items.is_empty()); + assert!(!app + .data + .radarr_data + .add_movie_modal + .as_ref() + .unwrap() + .quality_profile_list + .items + .is_empty()); assert_str_eq!( app .data .radarr_data + .add_movie_modal + .as_ref() + .unwrap() .quality_profile_list .current_selection(), "A - Test 1" @@ -205,9 +229,11 @@ mod tests { use strum::IntoEnumIterator; use crate::models::radarr_models::{Collection, MinimumAvailability}; - use crate::models::servarr_data::radarr_data::radarr_test_utils::utils::create_test_radarr_data; - use crate::models::servarr_data::radarr_data::{RadarrData, EDIT_COLLECTION_SELECTION_BLOCKS}; - use crate::models::HorizontallyScrollableText; + use crate::models::servarr_data::radarr::radarr_data::radarr_test_utils::utils::create_test_radarr_data; + use crate::models::servarr_data::radarr::radarr_data::{ + RadarrData, EDIT_COLLECTION_SELECTION_BLOCKS, + }; + use crate::models::StatefulTable; use crate::test_edit_collection_key; diff --git a/src/handlers/radarr_handlers/collections/collections_handler_tests.rs b/src/handlers/radarr_handlers/collections/collections_handler_tests.rs index 7753e21..b21df8a 100644 --- a/src/handlers/radarr_handlers/collections/collections_handler_tests.rs +++ b/src/handlers/radarr_handlers/collections/collections_handler_tests.rs @@ -10,7 +10,7 @@ mod tests { use crate::handlers::radarr_handlers::collections::CollectionsHandler; use crate::handlers::KeyEventHandler; use crate::models::radarr_models::Collection; - use crate::models::servarr_data::radarr_data::{ + use crate::models::servarr_data::radarr::radarr_data::{ ActiveRadarrBlock, COLLECTIONS_BLOCKS, COLLECTION_DETAILS_BLOCKS, EDIT_COLLECTION_BLOCKS, }; use crate::models::HorizontallyScrollableText; @@ -375,7 +375,7 @@ mod tests { mod test_handle_esc { use pretty_assertions::assert_eq; - use crate::models::servarr_data::radarr_data::radarr_test_utils::utils::create_test_radarr_data; + use crate::models::servarr_data::radarr::radarr_data::radarr_test_utils::utils::create_test_radarr_data; use crate::{assert_filter_reset, assert_search_reset}; use super::*; @@ -479,9 +479,11 @@ mod tests { use strum::IntoEnumIterator; use crate::models::radarr_models::MinimumAvailability; - use crate::models::servarr_data::radarr_data::radarr_test_utils::utils::create_test_radarr_data; - use crate::models::servarr_data::radarr_data::{RadarrData, EDIT_COLLECTION_SELECTION_BLOCKS}; - use crate::models::HorizontallyScrollableText; + use crate::models::servarr_data::radarr::radarr_data::radarr_test_utils::utils::create_test_radarr_data; + use crate::models::servarr_data::radarr::radarr_data::{ + RadarrData, EDIT_COLLECTION_SELECTION_BLOCKS, + }; + use crate::models::StatefulTable; use crate::{assert_refresh_key, test_edit_collection_key}; diff --git a/src/handlers/radarr_handlers/collections/edit_collection_handler.rs b/src/handlers/radarr_handlers/collections/edit_collection_handler.rs index 25c46b5..465d1dd 100644 --- a/src/handlers/radarr_handlers/collections/edit_collection_handler.rs +++ b/src/handlers/radarr_handlers/collections/edit_collection_handler.rs @@ -2,7 +2,7 @@ use crate::app::key_binding::DEFAULT_KEYBINDINGS; use crate::app::App; use crate::event::Key; use crate::handlers::{handle_prompt_toggle, KeyEventHandler}; -use crate::models::servarr_data::radarr_data::{ActiveRadarrBlock, EDIT_COLLECTION_BLOCKS}; +use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, EDIT_COLLECTION_BLOCKS}; use crate::models::Scrollable; use crate::network::radarr_network::RadarrEvent; use crate::{handle_text_box_keys, handle_text_box_left_right_keys}; @@ -47,11 +47,20 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for EditCollectionHandle .app .data .radarr_data + .edit_collection_modal + .as_mut() + .unwrap() .minimum_availability_list .scroll_up(), - ActiveRadarrBlock::EditCollectionSelectQualityProfile => { - self.app.data.radarr_data.quality_profile_list.scroll_up() - } + ActiveRadarrBlock::EditCollectionSelectQualityProfile => self + .app + .data + .radarr_data + .edit_collection_modal + .as_mut() + .unwrap() + .quality_profile_list + .scroll_up(), ActiveRadarrBlock::EditCollectionPrompt => { self.app.data.radarr_data.selected_block.previous() } @@ -65,11 +74,20 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for EditCollectionHandle .app .data .radarr_data + .edit_collection_modal + .as_mut() + .unwrap() .minimum_availability_list .scroll_down(), - ActiveRadarrBlock::EditCollectionSelectQualityProfile => { - self.app.data.radarr_data.quality_profile_list.scroll_down() - } + ActiveRadarrBlock::EditCollectionSelectQualityProfile => self + .app + .data + .radarr_data + .edit_collection_modal + .as_mut() + .unwrap() + .quality_profile_list + .scroll_down(), ActiveRadarrBlock::EditCollectionPrompt => self.app.data.radarr_data.selected_block.next(), _ => (), } @@ -81,17 +99,29 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for EditCollectionHandle .app .data .radarr_data + .edit_collection_modal + .as_mut() + .unwrap() .minimum_availability_list .scroll_to_top(), ActiveRadarrBlock::EditCollectionSelectQualityProfile => self .app .data .radarr_data + .edit_collection_modal + .as_mut() + .unwrap() .quality_profile_list .scroll_to_top(), - ActiveRadarrBlock::EditCollectionRootFolderPathInput => { - self.app.data.radarr_data.edit_path.scroll_home() - } + ActiveRadarrBlock::EditCollectionRootFolderPathInput => self + .app + .data + .radarr_data + .edit_collection_modal + .as_mut() + .unwrap() + .path + .scroll_home(), _ => (), } } @@ -102,17 +132,29 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for EditCollectionHandle .app .data .radarr_data + .edit_collection_modal + .as_mut() + .unwrap() .minimum_availability_list .scroll_to_bottom(), ActiveRadarrBlock::EditCollectionSelectQualityProfile => self .app .data .radarr_data + .edit_collection_modal + .as_mut() + .unwrap() .quality_profile_list .scroll_to_bottom(), - ActiveRadarrBlock::EditCollectionRootFolderPathInput => { - self.app.data.radarr_data.edit_path.reset_offset() - } + ActiveRadarrBlock::EditCollectionRootFolderPathInput => self + .app + .data + .radarr_data + .edit_collection_modal + .as_mut() + .unwrap() + .path + .reset_offset(), _ => (), } } @@ -123,7 +165,18 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for EditCollectionHandle match self.active_radarr_block { ActiveRadarrBlock::EditCollectionPrompt => handle_prompt_toggle(self.app, self.key), ActiveRadarrBlock::EditCollectionRootFolderPathInput => { - handle_text_box_left_right_keys!(self, self.key, self.app.data.radarr_data.edit_path) + handle_text_box_left_right_keys!( + self, + self.key, + self + .app + .data + .radarr_data + .edit_collection_modal + .as_mut() + .unwrap() + .path + ) } _ => (), } @@ -162,16 +215,42 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for EditCollectionHandle self.app.should_ignore_quit_key = true; } ActiveRadarrBlock::EditCollectionToggleMonitored => { - self.app.data.radarr_data.edit_monitored = - Some(!self.app.data.radarr_data.edit_monitored.unwrap_or_default()) - } - ActiveRadarrBlock::EditCollectionToggleSearchOnAdd => { - self.app.data.radarr_data.edit_search_on_add = Some( + self + .app + .data + .radarr_data + .edit_collection_modal + .as_mut() + .unwrap() + .monitored = Some( !self .app .data .radarr_data - .edit_search_on_add + .edit_collection_modal + .as_mut() + .unwrap() + .monitored + .unwrap_or_default(), + ) + } + ActiveRadarrBlock::EditCollectionToggleSearchOnAdd => { + self + .app + .data + .radarr_data + .edit_collection_modal + .as_mut() + .unwrap() + .search_on_add = Some( + !self + .app + .data + .radarr_data + .edit_collection_modal + .as_mut() + .unwrap() + .search_on_add .unwrap_or_default(), ) } @@ -196,7 +275,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for EditCollectionHandle } ActiveRadarrBlock::EditCollectionPrompt => { self.app.pop_navigation_stack(); - self.app.data.radarr_data.reset_add_edit_media_fields(); + self.app.data.radarr_data.edit_collection_modal = None; self.app.data.radarr_data.prompt_confirm = false; } ActiveRadarrBlock::EditCollectionSelectMinimumAvailability @@ -208,7 +287,18 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for EditCollectionHandle fn handle_char_key_event(&mut self) { let key = self.key; if self.active_radarr_block == &ActiveRadarrBlock::EditCollectionRootFolderPathInput { - handle_text_box_keys!(self, key, self.app.data.radarr_data.edit_path) + handle_text_box_keys!( + self, + key, + self + .app + .data + .radarr_data + .edit_collection_modal + .as_mut() + .unwrap() + .path + ) } } } diff --git a/src/handlers/radarr_handlers/collections/edit_collection_handler_tests.rs b/src/handlers/radarr_handlers/collections/edit_collection_handler_tests.rs index 92f5916..fed1ec8 100644 --- a/src/handlers/radarr_handlers/collections/edit_collection_handler_tests.rs +++ b/src/handlers/radarr_handlers/collections/edit_collection_handler_tests.rs @@ -9,35 +9,139 @@ mod tests { use crate::handlers::radarr_handlers::collections::edit_collection_handler::EditCollectionHandler; use crate::handlers::KeyEventHandler; use crate::models::radarr_models::MinimumAvailability; - use crate::models::servarr_data::radarr_data::{ActiveRadarrBlock, EDIT_COLLECTION_BLOCKS}; + use crate::models::servarr_data::radarr::radarr_data::{ + ActiveRadarrBlock, EDIT_COLLECTION_BLOCKS, + }; mod test_handle_scroll_up_and_down { use pretty_assertions::assert_eq; use rstest::rstest; use strum::IntoEnumIterator; - use crate::models::servarr_data::radarr_data::EDIT_COLLECTION_SELECTION_BLOCKS; + use crate::models::servarr_data::radarr::modals::EditCollectionModal; + use crate::models::servarr_data::radarr::radarr_data::EDIT_COLLECTION_SELECTION_BLOCKS; use crate::models::BlockSelectionState; - use crate::{test_enum_scroll, test_iterable_scroll}; use super::*; - test_enum_scroll!( - test_edit_collection_select_minimum_availability_scroll, - EditCollectionHandler, - MinimumAvailability, - minimum_availability_list, - ActiveRadarrBlock::EditCollectionSelectMinimumAvailability, - None - ); + #[rstest] + fn test_edit_collection_select_minimum_availability_scroll( + #[values(DEFAULT_KEYBINDINGS.up.key, DEFAULT_KEYBINDINGS.down.key)] key: Key, + ) { + let minimum_availability_vec = Vec::from_iter(MinimumAvailability::iter()); + let mut app = App::default(); + app.data.radarr_data.edit_collection_modal = Some(EditCollectionModal::default()); + app + .data + .radarr_data + .edit_collection_modal + .as_mut() + .unwrap() + .minimum_availability_list + .set_items(minimum_availability_vec.clone()); - test_iterable_scroll!( - test_edit_collection_select_quality_profile_scroll, - EditCollectionHandler, - quality_profile_list, - ActiveRadarrBlock::EditCollectionSelectQualityProfile, - None - ); + if key == Key::Up { + for i in (0..minimum_availability_vec.len()).rev() { + EditCollectionHandler::with( + &key, + &mut app, + &ActiveRadarrBlock::EditCollectionSelectMinimumAvailability, + &None, + ) + .handle(); + + assert_eq!( + app + .data + .radarr_data + .edit_collection_modal + .as_ref() + .unwrap() + .minimum_availability_list + .current_selection(), + &minimum_availability_vec[i] + ); + } + } else { + for i in 0..minimum_availability_vec.len() { + EditCollectionHandler::with( + &key, + &mut app, + &ActiveRadarrBlock::EditCollectionSelectMinimumAvailability, + &None, + ) + .handle(); + + assert_eq!( + app + .data + .radarr_data + .edit_collection_modal + .as_ref() + .unwrap() + .minimum_availability_list + .current_selection(), + &minimum_availability_vec[(i + 1) % minimum_availability_vec.len()] + ); + } + } + } + + #[rstest] + fn test_edit_collection_select_quality_profile_scroll( + #[values(DEFAULT_KEYBINDINGS.up.key, DEFAULT_KEYBINDINGS.down.key)] key: Key, + ) { + let mut app = App::default(); + app.data.radarr_data.edit_collection_modal = Some(EditCollectionModal::default()); + app + .data + .radarr_data + .edit_collection_modal + .as_mut() + .unwrap() + .quality_profile_list + .set_items(vec!["Test 1".to_owned(), "Test 2".to_owned()]); + + EditCollectionHandler::with( + &key, + &mut app, + &ActiveRadarrBlock::EditCollectionSelectQualityProfile, + &None, + ) + .handle(); + + assert_str_eq!( + app + .data + .radarr_data + .edit_collection_modal + .as_ref() + .unwrap() + .quality_profile_list + .current_selection(), + "Test 2" + ); + + EditCollectionHandler::with( + &key, + &mut app, + &ActiveRadarrBlock::EditCollectionSelectQualityProfile, + &None, + ) + .handle(); + + assert_str_eq!( + app + .data + .radarr_data + .edit_collection_modal + .as_ref() + .unwrap() + .quality_profile_list + .current_selection(), + "Test 1" + ); + } #[rstest] fn test_edit_collection_prompt_scroll(#[values(Key::Up, Key::Down)] key: Key) { @@ -69,44 +173,182 @@ mod tests { } mod test_handle_home_end { + use pretty_assertions::assert_eq; use strum::IntoEnumIterator; - use crate::{test_enum_home_and_end, test_iterable_home_and_end, test_text_box_home_end_keys}; + use crate::models::servarr_data::radarr::modals::EditCollectionModal; use super::*; - test_enum_home_and_end!( - test_edit_collection_select_minimum_availability_home_end, - EditCollectionHandler, - MinimumAvailability, - minimum_availability_list, - ActiveRadarrBlock::EditCollectionSelectMinimumAvailability, - None - ); + #[test] + fn test_edit_collection_select_minimum_availability_home_end() { + let minimum_availability_vec = Vec::from_iter(MinimumAvailability::iter()); + let mut app = App::default(); + app.data.radarr_data.edit_collection_modal = Some(EditCollectionModal::default()); + app + .data + .radarr_data + .edit_collection_modal + .as_mut() + .unwrap() + .minimum_availability_list + .set_items(minimum_availability_vec.clone()); - test_iterable_home_and_end!( - test_edit_collection_select_quality_profile_scroll, - EditCollectionHandler, - quality_profile_list, - ActiveRadarrBlock::EditCollectionSelectQualityProfile, - None - ); + EditCollectionHandler::with( + &DEFAULT_KEYBINDINGS.end.key, + &mut app, + &ActiveRadarrBlock::EditCollectionSelectMinimumAvailability, + &None, + ) + .handle(); + + assert_eq!( + app + .data + .radarr_data + .edit_collection_modal + .as_ref() + .unwrap() + .minimum_availability_list + .current_selection(), + &minimum_availability_vec[minimum_availability_vec.len() - 1] + ); + + EditCollectionHandler::with( + &DEFAULT_KEYBINDINGS.home.key, + &mut app, + &ActiveRadarrBlock::EditCollectionSelectMinimumAvailability, + &None, + ) + .handle(); + + assert_eq!( + app + .data + .radarr_data + .edit_collection_modal + .as_ref() + .unwrap() + .minimum_availability_list + .current_selection(), + &minimum_availability_vec[0] + ); + } + + #[test] + fn test_edit_collection_select_quality_profile_scroll() { + let mut app = App::default(); + app.data.radarr_data.edit_collection_modal = Some(EditCollectionModal::default()); + app + .data + .radarr_data + .edit_collection_modal + .as_mut() + .unwrap() + .quality_profile_list + .set_items(vec![ + "Test 1".to_owned(), + "Test 2".to_owned(), + "Test 3".to_owned(), + ]); + + EditCollectionHandler::with( + &DEFAULT_KEYBINDINGS.end.key, + &mut app, + &ActiveRadarrBlock::EditCollectionSelectQualityProfile, + &None, + ) + .handle(); + + assert_str_eq!( + app + .data + .radarr_data + .edit_collection_modal + .as_ref() + .unwrap() + .quality_profile_list + .current_selection(), + "Test 3" + ); + + EditCollectionHandler::with( + &DEFAULT_KEYBINDINGS.home.key, + &mut app, + &ActiveRadarrBlock::EditCollectionSelectQualityProfile, + &None, + ) + .handle(); + + assert_str_eq!( + app + .data + .radarr_data + .edit_collection_modal + .as_ref() + .unwrap() + .quality_profile_list + .current_selection(), + "Test 1" + ); + } #[test] fn test_edit_collection_root_folder_path_input_home_end_keys() { - test_text_box_home_end_keys!( - EditCollectionHandler, - ActiveRadarrBlock::EditCollectionRootFolderPathInput, - edit_path + let mut app = App::default(); + app.data.radarr_data.edit_collection_modal = Some(EditCollectionModal { + path: "Test".into(), + ..EditCollectionModal::default() + }); + + EditCollectionHandler::with( + &DEFAULT_KEYBINDINGS.home.key, + &mut app, + &ActiveRadarrBlock::EditCollectionRootFolderPathInput, + &None, + ) + .handle(); + + assert_eq!( + *app + .data + .radarr_data + .edit_collection_modal + .as_ref() + .unwrap() + .path + .offset + .borrow(), + 4 + ); + + EditCollectionHandler::with( + &DEFAULT_KEYBINDINGS.end.key, + &mut app, + &ActiveRadarrBlock::EditCollectionRootFolderPathInput, + &None, + ) + .handle(); + + assert_eq!( + *app + .data + .radarr_data + .edit_collection_modal + .as_ref() + .unwrap() + .path + .offset + .borrow(), + 0 ); } } mod test_handle_left_right_action { + use crate::models::servarr_data::radarr::modals::EditCollectionModal; use rstest::rstest; - use crate::test_text_box_left_right_keys; - use super::*; #[rstest] @@ -136,10 +378,52 @@ mod tests { #[test] fn test_edit_collection_root_folder_path_input_left_right_keys() { - test_text_box_left_right_keys!( - EditCollectionHandler, - ActiveRadarrBlock::EditCollectionRootFolderPathInput, - edit_path + let mut app = App::default(); + app.data.radarr_data.edit_collection_modal = Some(EditCollectionModal { + path: "Test".into(), + ..EditCollectionModal::default() + }); + + EditCollectionHandler::with( + &DEFAULT_KEYBINDINGS.left.key, + &mut app, + &ActiveRadarrBlock::EditCollectionRootFolderPathInput, + &None, + ) + .handle(); + + assert_eq!( + *app + .data + .radarr_data + .edit_collection_modal + .as_ref() + .unwrap() + .path + .offset + .borrow(), + 1 + ); + + EditCollectionHandler::with( + &DEFAULT_KEYBINDINGS.right.key, + &mut app, + &ActiveRadarrBlock::EditCollectionRootFolderPathInput, + &None, + ) + .handle(); + + assert_eq!( + *app + .data + .radarr_data + .edit_collection_modal + .as_ref() + .unwrap() + .path + .offset + .borrow(), + 0 ); } } @@ -148,7 +432,8 @@ mod tests { use pretty_assertions::assert_eq; use rstest::rstest; - use crate::models::servarr_data::radarr_data::EDIT_COLLECTION_SELECTION_BLOCKS; + use crate::models::servarr_data::radarr::modals::EditCollectionModal; + use crate::models::servarr_data::radarr::radarr_data::EDIT_COLLECTION_SELECTION_BLOCKS; use crate::models::{BlockSelectionState, Route}; use crate::network::radarr_network::RadarrEvent; @@ -248,6 +533,7 @@ mod tests { Some(ActiveRadarrBlock::Collections), )); let mut app = App::default(); + app.data.radarr_data.edit_collection_modal = Some(EditCollectionModal::default()); app.data.radarr_data.selected_block = BlockSelectionState::new(&EDIT_COLLECTION_SELECTION_BLOCKS); app.push_navigation_stack(current_route); @@ -261,7 +547,16 @@ mod tests { .handle(); assert_eq!(app.get_current_route(), ¤t_route); - assert_eq!(app.data.radarr_data.edit_monitored, Some(true)); + assert_eq!( + app + .data + .radarr_data + .edit_collection_modal + .as_ref() + .unwrap() + .monitored, + Some(true) + ); EditCollectionHandler::with( &SUBMIT_KEY, @@ -272,7 +567,16 @@ mod tests { .handle(); assert_eq!(app.get_current_route(), ¤t_route); - assert_eq!(app.data.radarr_data.edit_monitored, Some(false)); + assert_eq!( + app + .data + .radarr_data + .edit_collection_modal + .as_ref() + .unwrap() + .monitored, + Some(false) + ); } #[test] @@ -282,6 +586,7 @@ mod tests { Some(ActiveRadarrBlock::Collections), )); let mut app = App::default(); + app.data.radarr_data.edit_collection_modal = Some(EditCollectionModal::default()); app.data.radarr_data.selected_block = BlockSelectionState::new(&EDIT_COLLECTION_SELECTION_BLOCKS); app @@ -300,7 +605,16 @@ mod tests { .handle(); assert_eq!(app.get_current_route(), ¤t_route); - assert_eq!(app.data.radarr_data.edit_search_on_add, Some(true)); + assert_eq!( + app + .data + .radarr_data + .edit_collection_modal + .as_ref() + .unwrap() + .search_on_add, + Some(true) + ); EditCollectionHandler::with( &SUBMIT_KEY, @@ -311,7 +625,16 @@ mod tests { .handle(); assert_eq!(app.get_current_route(), ¤t_route); - assert_eq!(app.data.radarr_data.edit_search_on_add, Some(false)); + assert_eq!( + app + .data + .radarr_data + .edit_collection_modal + .as_ref() + .unwrap() + .search_on_add, + Some(false) + ); } #[rstest] @@ -389,8 +712,7 @@ mod tests { use pretty_assertions::assert_eq; use rstest::rstest; - use crate::models::servarr_data::radarr_data::radarr_test_utils::utils::create_test_radarr_data; - use crate::{assert_edit_media_reset, assert_preferences_selections_reset}; + use crate::models::servarr_data::radarr::radarr_data::radarr_test_utils::utils::create_test_radarr_data; use super::*; @@ -440,8 +762,7 @@ mod tests { ); let radarr_data = &app.data.radarr_data; - assert_preferences_selections_reset!(radarr_data); - assert_edit_media_reset!(radarr_data); + assert!(radarr_data.edit_collection_modal.is_none()); assert!(!radarr_data.prompt_confirm); } @@ -469,11 +790,15 @@ mod tests { mod test_handle_key_char { use super::*; + use crate::models::servarr_data::radarr::modals::EditCollectionModal; #[test] fn test_edit_collection_root_folder_path_input_backspace() { let mut app = App::default(); - app.data.radarr_data.edit_path = "Test".to_owned().into(); + app.data.radarr_data.edit_collection_modal = Some(EditCollectionModal { + path: "Test".into(), + ..EditCollectionModal::default() + }); EditCollectionHandler::with( &DEFAULT_KEYBINDINGS.backspace.key, @@ -483,12 +808,23 @@ mod tests { ) .handle(); - assert_str_eq!(app.data.radarr_data.edit_path.text, "Tes"); + assert_str_eq!( + app + .data + .radarr_data + .edit_collection_modal + .as_ref() + .unwrap() + .path + .text, + "Tes" + ); } #[test] fn test_edit_collection_root_folder_path_input_char_key() { let mut app = App::default(); + app.data.radarr_data.edit_collection_modal = Some(EditCollectionModal::default()); EditCollectionHandler::with( &Key::Char('h'), @@ -498,7 +834,17 @@ mod tests { ) .handle(); - assert_str_eq!(app.data.radarr_data.edit_path.text, "h"); + assert_str_eq!( + app + .data + .radarr_data + .edit_collection_modal + .as_ref() + .unwrap() + .path + .text, + "h" + ); } } diff --git a/src/handlers/radarr_handlers/collections/mod.rs b/src/handlers/radarr_handlers/collections/mod.rs index 39d747a..5350626 100644 --- a/src/handlers/radarr_handlers/collections/mod.rs +++ b/src/handlers/radarr_handlers/collections/mod.rs @@ -7,7 +7,7 @@ use crate::handlers::radarr_handlers::{ filter_table, handle_change_tab_left_right_keys, search_table, }; use crate::handlers::{handle_clear_errors, handle_prompt_toggle, KeyEventHandler}; -use crate::models::servarr_data::radarr_data::{ +use crate::models::servarr_data::radarr::radarr_data::{ ActiveRadarrBlock, COLLECTIONS_BLOCKS, EDIT_COLLECTION_SELECTION_BLOCKS, }; use crate::models::{BlockSelectionState, Scrollable}; @@ -287,7 +287,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for CollectionsHandler<' ) .into(), ); - self.app.data.radarr_data.populate_edit_collection_fields(); + self.app.data.radarr_data.edit_collection_modal = Some((&self.app.data.radarr_data).into()); self.app.data.radarr_data.selected_block = BlockSelectionState::new(&EDIT_COLLECTION_SELECTION_BLOCKS); } diff --git a/src/handlers/radarr_handlers/downloads/downloads_handler_tests.rs b/src/handlers/radarr_handlers/downloads/downloads_handler_tests.rs index 744d12f..40de244 100644 --- a/src/handlers/radarr_handlers/downloads/downloads_handler_tests.rs +++ b/src/handlers/radarr_handlers/downloads/downloads_handler_tests.rs @@ -8,7 +8,7 @@ mod tests { use crate::event::Key; use crate::handlers::radarr_handlers::downloads::DownloadsHandler; use crate::handlers::KeyEventHandler; - use crate::models::servarr_data::radarr_data::{ActiveRadarrBlock, DOWNLOADS_BLOCKS}; + use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, DOWNLOADS_BLOCKS}; mod test_handle_scroll_up_and_down { use rstest::rstest; diff --git a/src/handlers/radarr_handlers/downloads/mod.rs b/src/handlers/radarr_handlers/downloads/mod.rs index 5530fa7..57a773d 100644 --- a/src/handlers/radarr_handlers/downloads/mod.rs +++ b/src/handlers/radarr_handlers/downloads/mod.rs @@ -3,7 +3,7 @@ use crate::app::App; use crate::event::Key; use crate::handlers::radarr_handlers::handle_change_tab_left_right_keys; use crate::handlers::{handle_clear_errors, handle_prompt_toggle, KeyEventHandler}; -use crate::models::servarr_data::radarr_data::{ActiveRadarrBlock, DOWNLOADS_BLOCKS}; +use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, DOWNLOADS_BLOCKS}; use crate::models::Scrollable; use crate::network::radarr_network::RadarrEvent; diff --git a/src/handlers/radarr_handlers/indexers/edit_indexer_settings_handler.rs b/src/handlers/radarr_handlers/indexers/edit_indexer_settings_handler.rs index 5637dc3..f957877 100644 --- a/src/handlers/radarr_handlers/indexers/edit_indexer_settings_handler.rs +++ b/src/handlers/radarr_handlers/indexers/edit_indexer_settings_handler.rs @@ -1,7 +1,9 @@ use crate::app::App; use crate::event::Key; use crate::handlers::KeyEventHandler; -use crate::models::servarr_data::radarr_data::{ActiveRadarrBlock, INDEXER_SETTINGS_BLOCKS}; +use crate::models::servarr_data::radarr::radarr_data::{ + ActiveRadarrBlock, INDEXER_SETTINGS_BLOCKS, +}; #[cfg(test)] #[path = "./edit_indexer_settings_handler_tests.rs"] diff --git a/src/handlers/radarr_handlers/indexers/edit_indexer_settings_handler_tests.rs b/src/handlers/radarr_handlers/indexers/edit_indexer_settings_handler_tests.rs index 87af7de..9e6f9fb 100644 --- a/src/handlers/radarr_handlers/indexers/edit_indexer_settings_handler_tests.rs +++ b/src/handlers/radarr_handlers/indexers/edit_indexer_settings_handler_tests.rs @@ -7,13 +7,15 @@ mod tests { use crate::event::Key; use crate::handlers::radarr_handlers::indexers::edit_indexer_settings_handler::IndexerSettingsHandler; use crate::handlers::KeyEventHandler; - use crate::models::servarr_data::radarr_data::{ActiveRadarrBlock, INDEXER_SETTINGS_BLOCKS}; + use crate::models::servarr_data::radarr::radarr_data::{ + ActiveRadarrBlock, INDEXER_SETTINGS_BLOCKS, + }; mod test_handle_scroll_up_and_down { use pretty_assertions::assert_eq; use rstest::rstest; - use crate::models::servarr_data::radarr_data::INDEXER_SETTINGS_SELECTION_BLOCKS; + use crate::models::servarr_data::radarr::radarr_data::INDEXER_SETTINGS_SELECTION_BLOCKS; use crate::models::BlockSelectionState; use super::*; @@ -56,7 +58,7 @@ mod tests { mod test_handle_esc { use pretty_assertions::assert_eq; - use crate::models::servarr_data::radarr_data::radarr_test_utils::utils::create_test_radarr_data; + use crate::models::servarr_data::radarr::radarr_data::radarr_test_utils::utils::create_test_radarr_data; use super::*; diff --git a/src/handlers/radarr_handlers/indexers/indexers_handler_tests.rs b/src/handlers/radarr_handlers/indexers/indexers_handler_tests.rs index fd21060..2fb5f20 100644 --- a/src/handlers/radarr_handlers/indexers/indexers_handler_tests.rs +++ b/src/handlers/radarr_handlers/indexers/indexers_handler_tests.rs @@ -9,7 +9,7 @@ mod tests { use crate::event::Key; use crate::handlers::radarr_handlers::indexers::IndexersHandler; use crate::handlers::KeyEventHandler; - use crate::models::servarr_data::radarr_data::{ + use crate::models::servarr_data::radarr::radarr_data::{ ActiveRadarrBlock, INDEXERS_BLOCKS, INDEXER_SETTINGS_BLOCKS, }; use crate::test_handler_delegation; @@ -254,7 +254,7 @@ mod tests { use pretty_assertions::assert_eq; use crate::assert_refresh_key; - use crate::models::servarr_data::radarr_data::INDEXER_SETTINGS_SELECTION_BLOCKS; + use crate::models::servarr_data::radarr::radarr_data::INDEXER_SETTINGS_SELECTION_BLOCKS; use super::*; diff --git a/src/handlers/radarr_handlers/indexers/mod.rs b/src/handlers/radarr_handlers/indexers/mod.rs index e6577d5..7cf2caf 100644 --- a/src/handlers/radarr_handlers/indexers/mod.rs +++ b/src/handlers/radarr_handlers/indexers/mod.rs @@ -4,7 +4,7 @@ use crate::event::Key; use crate::handlers::radarr_handlers::handle_change_tab_left_right_keys; use crate::handlers::radarr_handlers::indexers::edit_indexer_settings_handler::IndexerSettingsHandler; use crate::handlers::{handle_clear_errors, handle_prompt_toggle, KeyEventHandler}; -use crate::models::servarr_data::radarr_data::{ +use crate::models::servarr_data::radarr::radarr_data::{ ActiveRadarrBlock, INDEXERS_BLOCKS, INDEXER_SETTINGS_SELECTION_BLOCKS, }; use crate::models::{BlockSelectionState, Scrollable}; diff --git a/src/handlers/radarr_handlers/library/add_movie_handler.rs b/src/handlers/radarr_handlers/library/add_movie_handler.rs index 2e47039..3ab212f 100644 --- a/src/handlers/radarr_handlers/library/add_movie_handler.rs +++ b/src/handlers/radarr_handlers/library/add_movie_handler.rs @@ -1,6 +1,6 @@ use crate::app::key_binding::DEFAULT_KEYBINDINGS; use crate::handlers::{handle_prompt_toggle, KeyEventHandler}; -use crate::models::servarr_data::radarr_data::{ +use crate::models::servarr_data::radarr::radarr_data::{ ActiveRadarrBlock, ADD_MOVIE_BLOCKS, ADD_MOVIE_SELECTION_BLOCKS, }; use crate::models::{BlockSelectionState, Scrollable, StatefulTable}; @@ -46,21 +46,42 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for AddMovieHandler<'a, ActiveRadarrBlock::AddMovieSearchResults => { self.app.data.radarr_data.add_searched_movies.scroll_up() } - ActiveRadarrBlock::AddMovieSelectMonitor => { - self.app.data.radarr_data.monitor_list.scroll_up() - } + ActiveRadarrBlock::AddMovieSelectMonitor => self + .app + .data + .radarr_data + .add_movie_modal + .as_mut() + .unwrap() + .monitor_list + .scroll_up(), ActiveRadarrBlock::AddMovieSelectMinimumAvailability => self .app .data .radarr_data + .add_movie_modal + .as_mut() + .unwrap() .minimum_availability_list .scroll_up(), - ActiveRadarrBlock::AddMovieSelectQualityProfile => { - self.app.data.radarr_data.quality_profile_list.scroll_up() - } - ActiveRadarrBlock::AddMovieSelectRootFolder => { - self.app.data.radarr_data.root_folder_list.scroll_up() - } + ActiveRadarrBlock::AddMovieSelectQualityProfile => self + .app + .data + .radarr_data + .add_movie_modal + .as_mut() + .unwrap() + .quality_profile_list + .scroll_up(), + ActiveRadarrBlock::AddMovieSelectRootFolder => self + .app + .data + .radarr_data + .add_movie_modal + .as_mut() + .unwrap() + .root_folder_list + .scroll_up(), ActiveRadarrBlock::AddMoviePrompt => self.app.data.radarr_data.selected_block.previous(), _ => (), } @@ -71,21 +92,42 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for AddMovieHandler<'a, ActiveRadarrBlock::AddMovieSearchResults => { self.app.data.radarr_data.add_searched_movies.scroll_down() } - ActiveRadarrBlock::AddMovieSelectMonitor => { - self.app.data.radarr_data.monitor_list.scroll_down() - } + ActiveRadarrBlock::AddMovieSelectMonitor => self + .app + .data + .radarr_data + .add_movie_modal + .as_mut() + .unwrap() + .monitor_list + .scroll_down(), ActiveRadarrBlock::AddMovieSelectMinimumAvailability => self .app .data .radarr_data + .add_movie_modal + .as_mut() + .unwrap() .minimum_availability_list .scroll_down(), - ActiveRadarrBlock::AddMovieSelectQualityProfile => { - self.app.data.radarr_data.quality_profile_list.scroll_down() - } - ActiveRadarrBlock::AddMovieSelectRootFolder => { - self.app.data.radarr_data.root_folder_list.scroll_down() - } + ActiveRadarrBlock::AddMovieSelectQualityProfile => self + .app + .data + .radarr_data + .add_movie_modal + .as_mut() + .unwrap() + .quality_profile_list + .scroll_down(), + ActiveRadarrBlock::AddMovieSelectRootFolder => self + .app + .data + .radarr_data + .add_movie_modal + .as_mut() + .unwrap() + .root_folder_list + .scroll_down(), ActiveRadarrBlock::AddMoviePrompt => self.app.data.radarr_data.selected_block.next(), _ => (), } @@ -99,26 +141,52 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for AddMovieHandler<'a, .radarr_data .add_searched_movies .scroll_to_top(), - ActiveRadarrBlock::AddMovieSelectMonitor => { - self.app.data.radarr_data.monitor_list.scroll_to_top() - } + ActiveRadarrBlock::AddMovieSelectMonitor => self + .app + .data + .radarr_data + .add_movie_modal + .as_mut() + .unwrap() + .monitor_list + .scroll_to_top(), ActiveRadarrBlock::AddMovieSelectMinimumAvailability => self .app .data .radarr_data + .add_movie_modal + .as_mut() + .unwrap() .minimum_availability_list .scroll_to_top(), ActiveRadarrBlock::AddMovieSelectQualityProfile => self .app .data .radarr_data + .add_movie_modal + .as_mut() + .unwrap() .quality_profile_list .scroll_to_top(), - ActiveRadarrBlock::AddMovieSelectRootFolder => { - self.app.data.radarr_data.root_folder_list.scroll_to_top() - } + ActiveRadarrBlock::AddMovieSelectRootFolder => self + .app + .data + .radarr_data + .add_movie_modal + .as_mut() + .unwrap() + .root_folder_list + .scroll_to_top(), ActiveRadarrBlock::AddMovieSearchInput => self.app.data.radarr_data.search.scroll_home(), - ActiveRadarrBlock::AddMovieTagsInput => self.app.data.radarr_data.edit_tags.scroll_home(), + ActiveRadarrBlock::AddMovieTagsInput => self + .app + .data + .radarr_data + .add_movie_modal + .as_mut() + .unwrap() + .tags + .scroll_home(), _ => (), } } @@ -131,29 +199,52 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for AddMovieHandler<'a, .radarr_data .add_searched_movies .scroll_to_bottom(), - ActiveRadarrBlock::AddMovieSelectMonitor => { - self.app.data.radarr_data.monitor_list.scroll_to_bottom() - } + ActiveRadarrBlock::AddMovieSelectMonitor => self + .app + .data + .radarr_data + .add_movie_modal + .as_mut() + .unwrap() + .monitor_list + .scroll_to_bottom(), ActiveRadarrBlock::AddMovieSelectMinimumAvailability => self .app .data .radarr_data + .add_movie_modal + .as_mut() + .unwrap() .minimum_availability_list .scroll_to_bottom(), ActiveRadarrBlock::AddMovieSelectQualityProfile => self .app .data .radarr_data + .add_movie_modal + .as_mut() + .unwrap() .quality_profile_list .scroll_to_bottom(), ActiveRadarrBlock::AddMovieSelectRootFolder => self .app .data .radarr_data + .add_movie_modal + .as_mut() + .unwrap() .root_folder_list .scroll_to_bottom(), ActiveRadarrBlock::AddMovieSearchInput => self.app.data.radarr_data.search.reset_offset(), - ActiveRadarrBlock::AddMovieTagsInput => self.app.data.radarr_data.edit_tags.reset_offset(), + ActiveRadarrBlock::AddMovieTagsInput => self + .app + .data + .radarr_data + .add_movie_modal + .as_mut() + .unwrap() + .tags + .reset_offset(), _ => (), } } @@ -167,7 +258,18 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for AddMovieHandler<'a, handle_text_box_left_right_keys!(self, self.key, self.app.data.radarr_data.search) } ActiveRadarrBlock::AddMovieTagsInput => { - handle_text_box_left_right_keys!(self, self.key, self.app.data.radarr_data.edit_tags) + handle_text_box_left_right_keys!( + self, + self.key, + self + .app + .data + .radarr_data + .add_movie_modal + .as_mut() + .unwrap() + .tags + ) } _ => (), } @@ -175,7 +277,9 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for AddMovieHandler<'a, fn handle_submit(&mut self) { match self.active_radarr_block { - ActiveRadarrBlock::AddMovieSearchInput => { + _ if *self.active_radarr_block == ActiveRadarrBlock::AddMovieSearchInput + && !self.app.data.radarr_data.search.text.is_empty() => + { self .app .push_navigation_stack(ActiveRadarrBlock::AddMovieSearchResults.into()); @@ -215,7 +319,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for AddMovieHandler<'a, self .app .push_navigation_stack(ActiveRadarrBlock::AddMoviePrompt.into()); - self.app.data.radarr_data.populate_preferences_lists(); + self.app.data.radarr_data.add_movie_modal = Some((&self.app.data.radarr_data).into()); self.app.data.radarr_data.selected_block = BlockSelectionState::new(&ADD_MOVIE_SELECTION_BLOCKS); } @@ -278,7 +382,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for AddMovieHandler<'a, } ActiveRadarrBlock::AddMoviePrompt => { self.app.pop_navigation_stack(); - self.app.data.radarr_data.reset_add_edit_media_fields(); + self.app.data.radarr_data.add_movie_modal = None; self.app.data.radarr_data.prompt_confirm = false; } ActiveRadarrBlock::AddMovieSelectMonitor @@ -301,7 +405,18 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for AddMovieHandler<'a, handle_text_box_keys!(self, key, self.app.data.radarr_data.search) } ActiveRadarrBlock::AddMovieTagsInput => { - handle_text_box_keys!(self, key, self.app.data.radarr_data.edit_tags) + handle_text_box_keys!( + self, + key, + self + .app + .data + .radarr_data + .add_movie_modal + .as_mut() + .unwrap() + .tags + ) } _ => (), } diff --git a/src/handlers/radarr_handlers/library/add_movie_handler_tests.rs b/src/handlers/radarr_handlers/library/add_movie_handler_tests.rs index f9d26fa..4cdd1b6 100644 --- a/src/handlers/radarr_handlers/library/add_movie_handler_tests.rs +++ b/src/handlers/radarr_handlers/library/add_movie_handler_tests.rs @@ -11,7 +11,7 @@ mod tests { use crate::models::radarr_models::{ AddMovieSearchResult, MinimumAvailability, Monitor, RootFolder, }; - use crate::models::servarr_data::radarr_data::{ActiveRadarrBlock, ADD_MOVIE_BLOCKS}; + use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, ADD_MOVIE_BLOCKS}; use crate::models::HorizontallyScrollableText; mod test_handle_scroll_up_and_down { @@ -19,9 +19,10 @@ mod tests { use rstest::rstest; use strum::IntoEnumIterator; - use crate::models::servarr_data::radarr_data::ADD_MOVIE_SELECTION_BLOCKS; + use crate::models::servarr_data::radarr::modals::AddMovieModal; + use crate::models::servarr_data::radarr::radarr_data::ADD_MOVIE_SELECTION_BLOCKS; use crate::models::BlockSelectionState; - use crate::{simple_stateful_iterable_vec, test_enum_scroll, test_iterable_scroll}; + use crate::{simple_stateful_iterable_vec, test_iterable_scroll}; use super::*; @@ -36,41 +37,245 @@ mod tests { to_string ); - test_enum_scroll!( - test_add_movie_select_monitor_scroll, - AddMovieHandler, - Monitor, - monitor_list, - ActiveRadarrBlock::AddMovieSelectMonitor, - None - ); + #[rstest] + fn test_add_movie_select_monitor_scroll( + #[values(DEFAULT_KEYBINDINGS.up.key, DEFAULT_KEYBINDINGS.down.key)] key: Key, + ) { + let monitor_vec = Vec::from_iter(Monitor::iter()); + let mut app = App::default(); + app.data.radarr_data.add_movie_modal = Some(AddMovieModal::default()); + app + .data + .radarr_data + .add_movie_modal + .as_mut() + .unwrap() + .monitor_list + .set_items(monitor_vec.clone()); - test_enum_scroll!( - test_add_movie_select_minimum_availability_scroll, - AddMovieHandler, - MinimumAvailability, - minimum_availability_list, - ActiveRadarrBlock::AddMovieSelectMinimumAvailability, - None - ); + if key == Key::Up { + for i in (0..monitor_vec.len()).rev() { + AddMovieHandler::with( + &key, + &mut app, + &ActiveRadarrBlock::AddMovieSelectMonitor, + &None, + ) + .handle(); - test_iterable_scroll!( - test_add_movie_select_quality_profile_scroll, - AddMovieHandler, - quality_profile_list, - ActiveRadarrBlock::AddMovieSelectQualityProfile, - None - ); + assert_eq!( + app + .data + .radarr_data + .add_movie_modal + .as_ref() + .unwrap() + .monitor_list + .current_selection(), + &monitor_vec[i] + ); + } + } else { + for i in 0..monitor_vec.len() { + AddMovieHandler::with( + &key, + &mut app, + &ActiveRadarrBlock::AddMovieSelectMonitor, + &None, + ) + .handle(); - test_iterable_scroll!( - test_add_movie_select_root_folder_scroll, - AddMovieHandler, - root_folder_list, - simple_stateful_iterable_vec!(RootFolder, String, path), - ActiveRadarrBlock::AddMovieSelectRootFolder, - None, - path - ); + assert_eq!( + app + .data + .radarr_data + .add_movie_modal + .as_ref() + .unwrap() + .monitor_list + .current_selection(), + &monitor_vec[(i + 1) % monitor_vec.len()] + ); + } + } + } + + #[rstest] + fn test_add_movie_select_minimum_availability_scroll( + #[values(DEFAULT_KEYBINDINGS.up.key, DEFAULT_KEYBINDINGS.down.key)] key: Key, + ) { + let minimum_availability_vec = Vec::from_iter(MinimumAvailability::iter()); + let mut app = App::default(); + app.data.radarr_data.add_movie_modal = Some(AddMovieModal::default()); + app + .data + .radarr_data + .add_movie_modal + .as_mut() + .unwrap() + .minimum_availability_list + .set_items(minimum_availability_vec.clone()); + + if key == Key::Up { + for i in (0..minimum_availability_vec.len()).rev() { + AddMovieHandler::with( + &key, + &mut app, + &ActiveRadarrBlock::AddMovieSelectMinimumAvailability, + &None, + ) + .handle(); + + assert_eq!( + app + .data + .radarr_data + .add_movie_modal + .as_ref() + .unwrap() + .minimum_availability_list + .current_selection(), + &minimum_availability_vec[i] + ); + } + } else { + for i in 0..minimum_availability_vec.len() { + AddMovieHandler::with( + &key, + &mut app, + &ActiveRadarrBlock::AddMovieSelectMinimumAvailability, + &None, + ) + .handle(); + + assert_eq!( + app + .data + .radarr_data + .add_movie_modal + .as_ref() + .unwrap() + .minimum_availability_list + .current_selection(), + &minimum_availability_vec[(i + 1) % minimum_availability_vec.len()] + ); + } + } + } + + #[rstest] + fn test_add_movie_select_quality_profile_scroll( + #[values(DEFAULT_KEYBINDINGS.up.key, DEFAULT_KEYBINDINGS.down.key)] key: Key, + ) { + let mut app = App::default(); + app.data.radarr_data.add_movie_modal = Some(AddMovieModal::default()); + app + .data + .radarr_data + .add_movie_modal + .as_mut() + .unwrap() + .quality_profile_list + .set_items(vec!["Test 1".to_owned(), "Test 2".to_owned()]); + + AddMovieHandler::with( + &key, + &mut app, + &ActiveRadarrBlock::AddMovieSelectQualityProfile, + &None, + ) + .handle(); + + assert_str_eq!( + app + .data + .radarr_data + .add_movie_modal + .as_ref() + .unwrap() + .quality_profile_list + .current_selection(), + "Test 2" + ); + + AddMovieHandler::with( + &key, + &mut app, + &ActiveRadarrBlock::AddMovieSelectQualityProfile, + &None, + ) + .handle(); + + assert_str_eq!( + app + .data + .radarr_data + .add_movie_modal + .as_ref() + .unwrap() + .quality_profile_list + .current_selection(), + "Test 1" + ); + } + + #[rstest] + fn test_add_movie_select_root_folder_scroll( + #[values(DEFAULT_KEYBINDINGS.up.key, DEFAULT_KEYBINDINGS.down.key)] key: Key, + ) { + let mut app = App::default(); + app.data.radarr_data.add_movie_modal = Some(AddMovieModal::default()); + app + .data + .radarr_data + .add_movie_modal + .as_mut() + .unwrap() + .root_folder_list + .set_items(simple_stateful_iterable_vec!(RootFolder, String, path)); + + AddMovieHandler::with( + &key, + &mut app, + &ActiveRadarrBlock::AddMovieSelectRootFolder, + &None, + ) + .handle(); + + assert_str_eq!( + app + .data + .radarr_data + .add_movie_modal + .as_ref() + .unwrap() + .root_folder_list + .current_selection() + .path, + "Test 2" + ); + + AddMovieHandler::with( + &key, + &mut app, + &ActiveRadarrBlock::AddMovieSelectRootFolder, + &None, + ) + .handle(); + + assert_str_eq!( + app + .data + .radarr_data + .add_movie_modal + .as_ref() + .unwrap() + .root_folder_list + .current_selection() + .path, + "Test 1" + ); + } #[rstest] fn test_add_movie_prompt_scroll(#[values(Key::Up, Key::Down)] key: Key) { @@ -97,9 +302,9 @@ mod tests { mod test_handle_home_end { use strum::IntoEnumIterator; + use crate::models::servarr_data::radarr::modals::AddMovieModal; use crate::{ - extended_stateful_iterable_vec, test_enum_home_and_end, test_iterable_home_and_end, - test_text_box_home_end_keys, + extended_stateful_iterable_vec, test_iterable_home_and_end, test_text_box_home_end_keys, }; use super::*; @@ -115,41 +320,229 @@ mod tests { to_string ); - test_enum_home_and_end!( - test_add_movie_select_monitor_home_end, - AddMovieHandler, - Monitor, - monitor_list, - ActiveRadarrBlock::AddMovieSelectMonitor, - None - ); + #[test] + fn test_add_movie_select_monitor_home_end() { + let monitor_vec = Vec::from_iter(Monitor::iter()); + let mut app = App::default(); + app.data.radarr_data.add_movie_modal = Some(AddMovieModal::default()); + app + .data + .radarr_data + .add_movie_modal + .as_mut() + .unwrap() + .monitor_list + .set_items(monitor_vec.clone()); - test_enum_home_and_end!( - test_add_movie_select_minimum_availability_home_end, - AddMovieHandler, - MinimumAvailability, - minimum_availability_list, - ActiveRadarrBlock::AddMovieSelectMinimumAvailability, - None - ); + AddMovieHandler::with( + &DEFAULT_KEYBINDINGS.end.key, + &mut app, + &ActiveRadarrBlock::AddMovieSelectMonitor, + &None, + ) + .handle(); - test_iterable_home_and_end!( - test_add_movie_select_quality_profile_home_end, - AddMovieHandler, - quality_profile_list, - ActiveRadarrBlock::AddMovieSelectQualityProfile, - None - ); + assert_eq!( + app + .data + .radarr_data + .add_movie_modal + .as_ref() + .unwrap() + .monitor_list + .current_selection(), + &monitor_vec[monitor_vec.len() - 1] + ); - test_iterable_home_and_end!( - test_add_movie_select_root_folder_home_end, - AddMovieHandler, - root_folder_list, - extended_stateful_iterable_vec!(RootFolder, String, path), - ActiveRadarrBlock::AddMovieSelectRootFolder, - None, - path - ); + AddMovieHandler::with( + &DEFAULT_KEYBINDINGS.home.key, + &mut app, + &ActiveRadarrBlock::AddMovieSelectMonitor, + &None, + ) + .handle(); + + assert_eq!( + app + .data + .radarr_data + .add_movie_modal + .as_ref() + .unwrap() + .monitor_list + .current_selection(), + &monitor_vec[0] + ); + } + + #[test] + fn test_add_movie_select_minimum_availability_home_end() { + let minimum_availability_vec = Vec::from_iter(MinimumAvailability::iter()); + let mut app = App::default(); + app.data.radarr_data.add_movie_modal = Some(AddMovieModal::default()); + app + .data + .radarr_data + .add_movie_modal + .as_mut() + .unwrap() + .minimum_availability_list + .set_items(minimum_availability_vec.clone()); + + AddMovieHandler::with( + &DEFAULT_KEYBINDINGS.end.key, + &mut app, + &ActiveRadarrBlock::AddMovieSelectMinimumAvailability, + &None, + ) + .handle(); + + assert_eq!( + app + .data + .radarr_data + .add_movie_modal + .as_ref() + .unwrap() + .minimum_availability_list + .current_selection(), + &minimum_availability_vec[minimum_availability_vec.len() - 1] + ); + + AddMovieHandler::with( + &DEFAULT_KEYBINDINGS.home.key, + &mut app, + &ActiveRadarrBlock::AddMovieSelectMinimumAvailability, + &None, + ) + .handle(); + + assert_eq!( + app + .data + .radarr_data + .add_movie_modal + .as_ref() + .unwrap() + .minimum_availability_list + .current_selection(), + &minimum_availability_vec[0] + ); + } + + #[test] + fn test_add_movie_select_quality_profile_home_end() { + let mut app = App::default(); + app.data.radarr_data.add_movie_modal = Some(AddMovieModal::default()); + app + .data + .radarr_data + .add_movie_modal + .as_mut() + .unwrap() + .quality_profile_list + .set_items(vec![ + "Test 1".to_owned(), + "Test 2".to_owned(), + "Test 3".to_owned(), + ]); + + AddMovieHandler::with( + &DEFAULT_KEYBINDINGS.end.key, + &mut app, + &ActiveRadarrBlock::AddMovieSelectQualityProfile, + &None, + ) + .handle(); + + assert_str_eq!( + app + .data + .radarr_data + .add_movie_modal + .as_ref() + .unwrap() + .quality_profile_list + .current_selection(), + "Test 3" + ); + + AddMovieHandler::with( + &DEFAULT_KEYBINDINGS.home.key, + &mut app, + &ActiveRadarrBlock::AddMovieSelectQualityProfile, + &None, + ) + .handle(); + + assert_str_eq!( + app + .data + .radarr_data + .add_movie_modal + .as_ref() + .unwrap() + .quality_profile_list + .current_selection(), + "Test 1" + ); + } + + #[test] + fn test_add_movie_select_root_folder_home_end() { + let mut app = App::default(); + app.data.radarr_data.add_movie_modal = Some(AddMovieModal::default()); + app + .data + .radarr_data + .add_movie_modal + .as_mut() + .unwrap() + .root_folder_list + .set_items(extended_stateful_iterable_vec!(RootFolder, String, path)); + + AddMovieHandler::with( + &DEFAULT_KEYBINDINGS.end.key, + &mut app, + &ActiveRadarrBlock::AddMovieSelectRootFolder, + &None, + ) + .handle(); + + assert_str_eq!( + app + .data + .radarr_data + .add_movie_modal + .as_ref() + .unwrap() + .root_folder_list + .current_selection() + .path, + "Test 3" + ); + + AddMovieHandler::with( + &DEFAULT_KEYBINDINGS.home.key, + &mut app, + &ActiveRadarrBlock::AddMovieSelectRootFolder, + &None, + ) + .handle(); + + assert_str_eq!( + app + .data + .radarr_data + .add_movie_modal + .as_ref() + .unwrap() + .root_folder_list + .current_selection() + .path, + "Test 1" + ); + } #[test] fn test_add_movie_search_input_home_end_keys() { @@ -162,15 +555,58 @@ mod tests { #[test] fn test_add_movie_tags_input_home_end_keys() { - test_text_box_home_end_keys!( - AddMovieHandler, - ActiveRadarrBlock::AddMovieTagsInput, - edit_tags + let mut app = App::default(); + app.data.radarr_data.add_movie_modal = Some(AddMovieModal { + tags: "Test".into(), + ..AddMovieModal::default() + }); + + AddMovieHandler::with( + &DEFAULT_KEYBINDINGS.home.key, + &mut app, + &ActiveRadarrBlock::AddMovieTagsInput, + &None, + ) + .handle(); + + assert_eq!( + *app + .data + .radarr_data + .add_movie_modal + .as_ref() + .unwrap() + .tags + .offset + .borrow(), + 4 + ); + + AddMovieHandler::with( + &DEFAULT_KEYBINDINGS.end.key, + &mut app, + &ActiveRadarrBlock::AddMovieTagsInput, + &None, + ) + .handle(); + + assert_eq!( + *app + .data + .radarr_data + .add_movie_modal + .as_ref() + .unwrap() + .tags + .offset + .borrow(), + 0 ); } } mod test_handle_left_right_action { + use crate::models::servarr_data::radarr::modals::AddMovieModal; use rstest::rstest; use crate::test_text_box_left_right_keys; @@ -201,10 +637,52 @@ mod tests { #[test] fn test_add_movie_tags_input_left_right_keys() { - test_text_box_left_right_keys!( - AddMovieHandler, - ActiveRadarrBlock::AddMovieTagsInput, - edit_tags + let mut app = App::default(); + app.data.radarr_data.add_movie_modal = Some(AddMovieModal { + tags: "Test".into(), + ..AddMovieModal::default() + }); + + AddMovieHandler::with( + &DEFAULT_KEYBINDINGS.left.key, + &mut app, + &ActiveRadarrBlock::AddMovieTagsInput, + &None, + ) + .handle(); + + assert_eq!( + *app + .data + .radarr_data + .add_movie_modal + .as_ref() + .unwrap() + .tags + .offset + .borrow(), + 1 + ); + + AddMovieHandler::with( + &DEFAULT_KEYBINDINGS.right.key, + &mut app, + &ActiveRadarrBlock::AddMovieTagsInput, + &None, + ) + .handle(); + + assert_eq!( + *app + .data + .radarr_data + .add_movie_modal + .as_ref() + .unwrap() + .tags + .offset + .borrow(), + 0 ); } } @@ -215,7 +693,8 @@ mod tests { use rstest::rstest; use crate::models::radarr_models::Movie; - use crate::models::servarr_data::radarr_data::ADD_MOVIE_SELECTION_BLOCKS; + use crate::models::servarr_data::radarr::modals::AddMovieModal; + use crate::models::servarr_data::radarr::radarr_data::ADD_MOVIE_SELECTION_BLOCKS; use crate::models::BlockSelectionState; use crate::network::radarr_network::RadarrEvent; @@ -227,6 +706,7 @@ mod tests { fn test_add_movie_search_input_submit() { let mut app = App::default(); app.should_ignore_quit_key = true; + app.data.radarr_data.search = "test".into(); AddMovieHandler::with( &SUBMIT_KEY, @@ -243,6 +723,27 @@ mod tests { ); } + #[test] + fn test_add_movie_search_input_submit_noop_on_empty_search() { + let mut app = App::default(); + app.push_navigation_stack(ActiveRadarrBlock::AddMovieSearchInput.into()); + app.should_ignore_quit_key = true; + + AddMovieHandler::with( + &SUBMIT_KEY, + &mut app, + &ActiveRadarrBlock::AddMovieSearchInput, + &None, + ) + .handle(); + + assert!(app.should_ignore_quit_key); + assert_eq!( + app.get_current_route(), + &ActiveRadarrBlock::AddMovieSearchInput.into() + ); + } + #[test] fn test_add_movie_search_results_submit() { let mut app = App::default(); @@ -270,18 +771,41 @@ mod tests { app.data.radarr_data.selected_block.get_active_block(), &ActiveRadarrBlock::AddMovieSelectRootFolder ); - assert!(!app.data.radarr_data.monitor_list.items.is_empty()); + assert!(app.data.radarr_data.add_movie_modal.is_some()); assert!(!app .data .radarr_data + .add_movie_modal + .as_ref() + .unwrap() + .monitor_list + .items + .is_empty()); + assert!(!app + .data + .radarr_data + .add_movie_modal + .as_ref() + .unwrap() .minimum_availability_list .items .is_empty()); - assert!(!app.data.radarr_data.quality_profile_list.items.is_empty()); + assert!(!app + .data + .radarr_data + .add_movie_modal + .as_ref() + .unwrap() + .quality_profile_list + .items + .is_empty()); assert_str_eq!( app .data .radarr_data + .add_movie_modal + .as_ref() + .unwrap() .quality_profile_list .current_selection(), "A - Test 1" @@ -361,6 +885,7 @@ mod tests { #[test] fn test_add_movie_confirm_prompt_prompt_confirmation_submit() { let mut app = App::default(); + app.data.radarr_data.add_movie_modal = Some(AddMovieModal::default()); app.push_navigation_stack(ActiveRadarrBlock::Movies.into()); app.push_navigation_stack(ActiveRadarrBlock::AddMoviePrompt.into()); app.data.radarr_data.prompt_confirm = true; @@ -384,6 +909,7 @@ mod tests { app.data.radarr_data.prompt_confirm_action, Some(RadarrEvent::AddMovie) ); + assert!(app.data.radarr_data.add_movie_modal.is_some()); } #[rstest] @@ -464,11 +990,9 @@ mod tests { use pretty_assertions::assert_eq; use rstest::rstest; - use crate::models::servarr_data::radarr_data::radarr_test_utils::utils::create_test_radarr_data; - use crate::{ - assert_edit_media_reset, assert_preferences_selections_reset, assert_search_reset, - simple_stateful_iterable_vec, - }; + use crate::models::servarr_data::radarr::modals::AddMovieModal; + use crate::models::servarr_data::radarr::radarr_data::radarr_test_utils::utils::create_test_radarr_data; + use crate::{assert_search_reset, simple_stateful_iterable_vec}; use super::*; @@ -571,6 +1095,7 @@ mod tests { #[test] fn test_add_movie_prompt_esc() { let mut app = App::default(); + app.data.radarr_data.add_movie_modal = Some(AddMovieModal::default()); app.data.radarr_data = create_test_radarr_data(); app.push_navigation_stack(ActiveRadarrBlock::AddMovieSearchResults.into()); app.push_navigation_stack(ActiveRadarrBlock::AddMoviePrompt.into()); @@ -588,8 +1113,7 @@ mod tests { app.get_current_route(), &ActiveRadarrBlock::AddMovieSearchResults.into() ); - assert_preferences_selections_reset!(app.data.radarr_data); - assert_edit_media_reset!(app.data.radarr_data); + assert!(app.data.radarr_data.add_movie_modal.is_none()); } #[test] @@ -662,6 +1186,7 @@ mod tests { mod test_handle_key_char { use super::*; + use crate::models::servarr_data::radarr::modals::AddMovieModal; #[test] fn test_add_movie_search_input_backspace() { @@ -682,7 +1207,10 @@ mod tests { #[test] fn test_add_movie_tags_input_backspace() { let mut app = App::default(); - app.data.radarr_data.edit_tags = "Test".to_owned().into(); + app.data.radarr_data.add_movie_modal = Some(AddMovieModal { + tags: "Test".into(), + ..AddMovieModal::default() + }); AddMovieHandler::with( &DEFAULT_KEYBINDINGS.backspace.key, @@ -692,7 +1220,17 @@ mod tests { ) .handle(); - assert_str_eq!(app.data.radarr_data.edit_tags.text, "Tes"); + assert_str_eq!( + app + .data + .radarr_data + .add_movie_modal + .as_ref() + .unwrap() + .tags + .text, + "Tes" + ); } #[test] @@ -713,6 +1251,7 @@ mod tests { #[test] fn test_add_movie_tags_input_char_key() { let mut app = App::default(); + app.data.radarr_data.add_movie_modal = Some(AddMovieModal::default()); AddMovieHandler::with( &Key::Char('h'), @@ -722,7 +1261,17 @@ mod tests { ) .handle(); - assert_str_eq!(app.data.radarr_data.edit_tags.text, "h"); + assert_str_eq!( + app + .data + .radarr_data + .add_movie_modal + .as_ref() + .unwrap() + .tags + .text, + "h" + ); } } diff --git a/src/handlers/radarr_handlers/library/delete_movie_handler.rs b/src/handlers/radarr_handlers/library/delete_movie_handler.rs index 6f7d422..8317f4a 100644 --- a/src/handlers/radarr_handlers/library/delete_movie_handler.rs +++ b/src/handlers/radarr_handlers/library/delete_movie_handler.rs @@ -1,7 +1,7 @@ use crate::app::App; use crate::event::Key; use crate::handlers::{handle_prompt_toggle, KeyEventHandler}; -use crate::models::servarr_data::radarr_data::{ActiveRadarrBlock, DELETE_MOVIE_BLOCKS}; +use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, DELETE_MOVIE_BLOCKS}; use crate::network::radarr_network::RadarrEvent; #[cfg(test)] diff --git a/src/handlers/radarr_handlers/library/delete_movie_handler_tests.rs b/src/handlers/radarr_handlers/library/delete_movie_handler_tests.rs index 91bb8d8..9619fad 100644 --- a/src/handlers/radarr_handlers/library/delete_movie_handler_tests.rs +++ b/src/handlers/radarr_handlers/library/delete_movie_handler_tests.rs @@ -7,13 +7,13 @@ mod tests { use crate::event::Key; use crate::handlers::radarr_handlers::library::delete_movie_handler::DeleteMovieHandler; use crate::handlers::KeyEventHandler; - use crate::models::servarr_data::radarr_data::{ActiveRadarrBlock, DELETE_MOVIE_BLOCKS}; + use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, DELETE_MOVIE_BLOCKS}; mod test_handle_scroll_up_and_down { use pretty_assertions::assert_eq; use rstest::rstest; - use crate::models::servarr_data::radarr_data::DELETE_MOVIE_SELECTION_BLOCKS; + use crate::models::servarr_data::radarr::radarr_data::DELETE_MOVIE_SELECTION_BLOCKS; use crate::models::BlockSelectionState; use super::*; @@ -66,7 +66,7 @@ mod tests { mod test_handle_submit { use pretty_assertions::assert_eq; - use crate::models::servarr_data::radarr_data::DELETE_MOVIE_SELECTION_BLOCKS; + use crate::models::servarr_data::radarr::radarr_data::DELETE_MOVIE_SELECTION_BLOCKS; use crate::models::BlockSelectionState; use crate::network::radarr_network::RadarrEvent; diff --git a/src/handlers/radarr_handlers/library/edit_movie_handler.rs b/src/handlers/radarr_handlers/library/edit_movie_handler.rs index 25e2e6e..5dffc26 100644 --- a/src/handlers/radarr_handlers/library/edit_movie_handler.rs +++ b/src/handlers/radarr_handlers/library/edit_movie_handler.rs @@ -2,7 +2,7 @@ use crate::app::key_binding::DEFAULT_KEYBINDINGS; use crate::app::App; use crate::event::Key; use crate::handlers::{handle_prompt_toggle, KeyEventHandler}; -use crate::models::servarr_data::radarr_data::{ActiveRadarrBlock, EDIT_MOVIE_BLOCKS}; +use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, EDIT_MOVIE_BLOCKS}; use crate::models::Scrollable; use crate::network::radarr_network::RadarrEvent; use crate::{handle_text_box_keys, handle_text_box_left_right_keys}; @@ -47,11 +47,20 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for EditMovieHandler<'a, .app .data .radarr_data + .edit_movie_modal + .as_mut() + .unwrap() .minimum_availability_list .scroll_up(), - ActiveRadarrBlock::EditMovieSelectQualityProfile => { - self.app.data.radarr_data.quality_profile_list.scroll_up() - } + ActiveRadarrBlock::EditMovieSelectQualityProfile => self + .app + .data + .radarr_data + .edit_movie_modal + .as_mut() + .unwrap() + .quality_profile_list + .scroll_up(), ActiveRadarrBlock::EditMoviePrompt => self.app.data.radarr_data.selected_block.previous(), _ => (), } @@ -63,11 +72,20 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for EditMovieHandler<'a, .app .data .radarr_data + .edit_movie_modal + .as_mut() + .unwrap() .minimum_availability_list .scroll_down(), - ActiveRadarrBlock::EditMovieSelectQualityProfile => { - self.app.data.radarr_data.quality_profile_list.scroll_down() - } + ActiveRadarrBlock::EditMovieSelectQualityProfile => self + .app + .data + .radarr_data + .edit_movie_modal + .as_mut() + .unwrap() + .quality_profile_list + .scroll_down(), ActiveRadarrBlock::EditMoviePrompt => self.app.data.radarr_data.selected_block.next(), _ => (), } @@ -79,16 +97,38 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for EditMovieHandler<'a, .app .data .radarr_data + .edit_movie_modal + .as_mut() + .unwrap() .minimum_availability_list .scroll_to_top(), ActiveRadarrBlock::EditMovieSelectQualityProfile => self .app .data .radarr_data + .edit_movie_modal + .as_mut() + .unwrap() .quality_profile_list .scroll_to_top(), - ActiveRadarrBlock::EditMoviePathInput => self.app.data.radarr_data.edit_path.scroll_home(), - ActiveRadarrBlock::EditMovieTagsInput => self.app.data.radarr_data.edit_tags.scroll_home(), + ActiveRadarrBlock::EditMoviePathInput => self + .app + .data + .radarr_data + .edit_movie_modal + .as_mut() + .unwrap() + .path + .scroll_home(), + ActiveRadarrBlock::EditMovieTagsInput => self + .app + .data + .radarr_data + .edit_movie_modal + .as_mut() + .unwrap() + .tags + .scroll_home(), _ => (), } } @@ -99,16 +139,38 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for EditMovieHandler<'a, .app .data .radarr_data + .edit_movie_modal + .as_mut() + .unwrap() .minimum_availability_list .scroll_to_bottom(), ActiveRadarrBlock::EditMovieSelectQualityProfile => self .app .data .radarr_data + .edit_movie_modal + .as_mut() + .unwrap() .quality_profile_list .scroll_to_bottom(), - ActiveRadarrBlock::EditMoviePathInput => self.app.data.radarr_data.edit_path.reset_offset(), - ActiveRadarrBlock::EditMovieTagsInput => self.app.data.radarr_data.edit_tags.reset_offset(), + ActiveRadarrBlock::EditMoviePathInput => self + .app + .data + .radarr_data + .edit_movie_modal + .as_mut() + .unwrap() + .path + .reset_offset(), + ActiveRadarrBlock::EditMovieTagsInput => self + .app + .data + .radarr_data + .edit_movie_modal + .as_mut() + .unwrap() + .tags + .reset_offset(), _ => (), } } @@ -119,10 +181,32 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for EditMovieHandler<'a, match self.active_radarr_block { ActiveRadarrBlock::EditMoviePrompt => handle_prompt_toggle(self.app, self.key), ActiveRadarrBlock::EditMoviePathInput => { - handle_text_box_left_right_keys!(self, self.key, self.app.data.radarr_data.edit_path) + handle_text_box_left_right_keys!( + self, + self.key, + self + .app + .data + .radarr_data + .edit_movie_modal + .as_mut() + .unwrap() + .path + ) } ActiveRadarrBlock::EditMovieTagsInput => { - handle_text_box_left_right_keys!(self, self.key, self.app.data.radarr_data.edit_tags) + handle_text_box_left_right_keys!( + self, + self.key, + self + .app + .data + .radarr_data + .edit_movie_modal + .as_mut() + .unwrap() + .tags + ) } _ => (), } @@ -159,8 +243,24 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for EditMovieHandler<'a, self.app.should_ignore_quit_key = true; } ActiveRadarrBlock::EditMovieToggleMonitored => { - self.app.data.radarr_data.edit_monitored = - Some(!self.app.data.radarr_data.edit_monitored.unwrap_or_default()) + self + .app + .data + .radarr_data + .edit_movie_modal + .as_mut() + .unwrap() + .monitored = Some( + !self + .app + .data + .radarr_data + .edit_movie_modal + .as_mut() + .unwrap() + .monitored + .unwrap_or_default(), + ) } _ => (), } @@ -183,7 +283,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for EditMovieHandler<'a, } ActiveRadarrBlock::EditMoviePrompt => { self.app.pop_navigation_stack(); - self.app.data.radarr_data.reset_add_edit_media_fields(); + self.app.data.radarr_data.edit_movie_modal = None; self.app.data.radarr_data.prompt_confirm = false; } ActiveRadarrBlock::EditMovieSelectMinimumAvailability @@ -196,10 +296,32 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for EditMovieHandler<'a, let key = self.key; match self.active_radarr_block { ActiveRadarrBlock::EditMoviePathInput => { - handle_text_box_keys!(self, key, self.app.data.radarr_data.edit_path) + handle_text_box_keys!( + self, + key, + self + .app + .data + .radarr_data + .edit_movie_modal + .as_mut() + .unwrap() + .path + ) } ActiveRadarrBlock::EditMovieTagsInput => { - handle_text_box_keys!(self, key, self.app.data.radarr_data.edit_tags) + handle_text_box_keys!( + self, + key, + self + .app + .data + .radarr_data + .edit_movie_modal + .as_mut() + .unwrap() + .tags + ) } _ => (), } diff --git a/src/handlers/radarr_handlers/library/edit_movie_handler_tests.rs b/src/handlers/radarr_handlers/library/edit_movie_handler_tests.rs index 5151c43..0163f4c 100644 --- a/src/handlers/radarr_handlers/library/edit_movie_handler_tests.rs +++ b/src/handlers/radarr_handlers/library/edit_movie_handler_tests.rs @@ -9,35 +9,137 @@ mod tests { use crate::handlers::radarr_handlers::library::edit_movie_handler::EditMovieHandler; use crate::handlers::KeyEventHandler; use crate::models::radarr_models::MinimumAvailability; - use crate::models::servarr_data::radarr_data::{ActiveRadarrBlock, EDIT_MOVIE_BLOCKS}; + use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, EDIT_MOVIE_BLOCKS}; mod test_handle_scroll_up_and_down { use pretty_assertions::assert_eq; use rstest::rstest; use strum::IntoEnumIterator; - use crate::models::servarr_data::radarr_data::EDIT_MOVIE_SELECTION_BLOCKS; + use crate::models::servarr_data::radarr::modals::EditMovieModal; + use crate::models::servarr_data::radarr::radarr_data::EDIT_MOVIE_SELECTION_BLOCKS; use crate::models::BlockSelectionState; - use crate::{test_enum_scroll, test_iterable_scroll}; use super::*; - test_enum_scroll!( - test_edit_movie_select_minimum_availability_scroll, - EditMovieHandler, - MinimumAvailability, - minimum_availability_list, - ActiveRadarrBlock::EditMovieSelectMinimumAvailability, - None - ); + #[rstest] + fn test_edit_movie_select_minimum_availability_scroll( + #[values(DEFAULT_KEYBINDINGS.up.key, DEFAULT_KEYBINDINGS.down.key)] key: Key, + ) { + let minimum_availability_vec = Vec::from_iter(MinimumAvailability::iter()); + let mut app = App::default(); + app.data.radarr_data.edit_movie_modal = Some(EditMovieModal::default()); + app + .data + .radarr_data + .edit_movie_modal + .as_mut() + .unwrap() + .minimum_availability_list + .set_items(minimum_availability_vec.clone()); - test_iterable_scroll!( - test_edit_movie_select_quality_profile_scroll, - EditMovieHandler, - quality_profile_list, - ActiveRadarrBlock::EditMovieSelectQualityProfile, - None - ); + if key == Key::Up { + for i in (0..minimum_availability_vec.len()).rev() { + EditMovieHandler::with( + &key, + &mut app, + &ActiveRadarrBlock::EditMovieSelectMinimumAvailability, + &None, + ) + .handle(); + + assert_eq!( + app + .data + .radarr_data + .edit_movie_modal + .as_ref() + .unwrap() + .minimum_availability_list + .current_selection(), + &minimum_availability_vec[i] + ); + } + } else { + for i in 0..minimum_availability_vec.len() { + EditMovieHandler::with( + &key, + &mut app, + &ActiveRadarrBlock::EditMovieSelectMinimumAvailability, + &None, + ) + .handle(); + + assert_eq!( + app + .data + .radarr_data + .edit_movie_modal + .as_ref() + .unwrap() + .minimum_availability_list + .current_selection(), + &minimum_availability_vec[(i + 1) % minimum_availability_vec.len()] + ); + } + } + } + + #[rstest] + fn test_edit_movie_select_quality_profile_scroll( + #[values(DEFAULT_KEYBINDINGS.up.key, DEFAULT_KEYBINDINGS.down.key)] key: Key, + ) { + let mut app = App::default(); + app.data.radarr_data.edit_movie_modal = Some(EditMovieModal::default()); + app + .data + .radarr_data + .edit_movie_modal + .as_mut() + .unwrap() + .quality_profile_list + .set_items(vec!["Test 1".to_owned(), "Test 2".to_owned()]); + + EditMovieHandler::with( + &key, + &mut app, + &ActiveRadarrBlock::EditMovieSelectQualityProfile, + &None, + ) + .handle(); + + assert_str_eq!( + app + .data + .radarr_data + .edit_movie_modal + .as_ref() + .unwrap() + .quality_profile_list + .current_selection(), + "Test 2" + ); + + EditMovieHandler::with( + &key, + &mut app, + &ActiveRadarrBlock::EditMovieSelectQualityProfile, + &None, + ) + .handle(); + + assert_str_eq!( + app + .data + .radarr_data + .edit_movie_modal + .as_ref() + .unwrap() + .quality_profile_list + .current_selection(), + "Test 1" + ); + } #[rstest] fn test_edit_movie_prompt_scroll(#[values(Key::Up, Key::Down)] key: Key) { @@ -64,51 +166,230 @@ mod tests { mod test_handle_home_end { use strum::IntoEnumIterator; - use crate::{test_enum_home_and_end, test_iterable_home_and_end, test_text_box_home_end_keys}; + use crate::models::servarr_data::radarr::modals::EditMovieModal; use super::*; - test_enum_home_and_end!( - test_edit_movie_select_minimum_availability_home_end, - EditMovieHandler, - MinimumAvailability, - minimum_availability_list, - ActiveRadarrBlock::EditMovieSelectMinimumAvailability, - None - ); + #[test] + fn test_edit_movie_select_minimum_availability_home_end() { + let minimum_availability_vec = Vec::from_iter(MinimumAvailability::iter()); + let mut app = App::default(); + app.data.radarr_data.edit_movie_modal = Some(EditMovieModal::default()); + app + .data + .radarr_data + .edit_movie_modal + .as_mut() + .unwrap() + .minimum_availability_list + .set_items(minimum_availability_vec.clone()); - test_iterable_home_and_end!( - test_edit_movie_select_quality_profile_scroll, - EditMovieHandler, - quality_profile_list, - ActiveRadarrBlock::EditMovieSelectQualityProfile, - None - ); + EditMovieHandler::with( + &DEFAULT_KEYBINDINGS.end.key, + &mut app, + &ActiveRadarrBlock::EditMovieSelectMinimumAvailability, + &None, + ) + .handle(); + + assert_eq!( + app + .data + .radarr_data + .edit_movie_modal + .as_ref() + .unwrap() + .minimum_availability_list + .current_selection(), + &minimum_availability_vec[minimum_availability_vec.len() - 1] + ); + + EditMovieHandler::with( + &DEFAULT_KEYBINDINGS.home.key, + &mut app, + &ActiveRadarrBlock::EditMovieSelectMinimumAvailability, + &None, + ) + .handle(); + + assert_eq!( + app + .data + .radarr_data + .edit_movie_modal + .as_ref() + .unwrap() + .minimum_availability_list + .current_selection(), + &minimum_availability_vec[0] + ); + } + + #[test] + fn test_edit_movie_select_quality_profile_scroll() { + let mut app = App::default(); + app.data.radarr_data.edit_movie_modal = Some(EditMovieModal::default()); + app + .data + .radarr_data + .edit_movie_modal + .as_mut() + .unwrap() + .quality_profile_list + .set_items(vec![ + "Test 1".to_owned(), + "Test 2".to_owned(), + "Test 3".to_owned(), + ]); + + EditMovieHandler::with( + &DEFAULT_KEYBINDINGS.end.key, + &mut app, + &ActiveRadarrBlock::EditMovieSelectQualityProfile, + &None, + ) + .handle(); + + assert_str_eq!( + app + .data + .radarr_data + .edit_movie_modal + .as_ref() + .unwrap() + .quality_profile_list + .current_selection(), + "Test 3" + ); + + EditMovieHandler::with( + &DEFAULT_KEYBINDINGS.home.key, + &mut app, + &ActiveRadarrBlock::EditMovieSelectQualityProfile, + &None, + ) + .handle(); + + assert_str_eq!( + app + .data + .radarr_data + .edit_movie_modal + .as_ref() + .unwrap() + .quality_profile_list + .current_selection(), + "Test 1" + ); + } #[test] fn test_edit_movie_path_input_home_end_keys() { - test_text_box_home_end_keys!( - EditMovieHandler, - ActiveRadarrBlock::EditMoviePathInput, - edit_path + let mut app = App::default(); + app.data.radarr_data.edit_movie_modal = Some(EditMovieModal { + path: "Test".into(), + ..EditMovieModal::default() + }); + + EditMovieHandler::with( + &DEFAULT_KEYBINDINGS.home.key, + &mut app, + &ActiveRadarrBlock::EditMoviePathInput, + &None, + ) + .handle(); + + assert_eq!( + *app + .data + .radarr_data + .edit_movie_modal + .as_ref() + .unwrap() + .path + .offset + .borrow(), + 4 + ); + + EditMovieHandler::with( + &DEFAULT_KEYBINDINGS.end.key, + &mut app, + &ActiveRadarrBlock::EditMoviePathInput, + &None, + ) + .handle(); + + assert_eq!( + *app + .data + .radarr_data + .edit_movie_modal + .as_ref() + .unwrap() + .path + .offset + .borrow(), + 0 ); } #[test] fn test_edit_movie_tags_input_home_end_keys() { - test_text_box_home_end_keys!( - EditMovieHandler, - ActiveRadarrBlock::EditMovieTagsInput, - edit_tags + let mut app = App::default(); + app.data.radarr_data.edit_movie_modal = Some(EditMovieModal { + tags: "Test".into(), + ..EditMovieModal::default() + }); + + EditMovieHandler::with( + &DEFAULT_KEYBINDINGS.home.key, + &mut app, + &ActiveRadarrBlock::EditMovieTagsInput, + &None, + ) + .handle(); + + assert_eq!( + *app + .data + .radarr_data + .edit_movie_modal + .as_ref() + .unwrap() + .tags + .offset + .borrow(), + 4 + ); + + EditMovieHandler::with( + &DEFAULT_KEYBINDINGS.end.key, + &mut app, + &ActiveRadarrBlock::EditMovieTagsInput, + &None, + ) + .handle(); + + assert_eq!( + *app + .data + .radarr_data + .edit_movie_modal + .as_ref() + .unwrap() + .tags + .offset + .borrow(), + 0 ); } } mod test_handle_left_right_action { + use crate::models::servarr_data::radarr::modals::EditMovieModal; use rstest::rstest; - use crate::test_text_box_left_right_keys; - use super::*; #[rstest] @@ -126,19 +407,103 @@ mod tests { #[test] fn test_edit_movie_path_input_left_right_keys() { - test_text_box_left_right_keys!( - EditMovieHandler, - ActiveRadarrBlock::EditMoviePathInput, - edit_path + let mut app = App::default(); + app.data.radarr_data.edit_movie_modal = Some(EditMovieModal { + path: "Test".into(), + ..EditMovieModal::default() + }); + + EditMovieHandler::with( + &DEFAULT_KEYBINDINGS.left.key, + &mut app, + &ActiveRadarrBlock::EditMoviePathInput, + &None, + ) + .handle(); + + assert_eq!( + *app + .data + .radarr_data + .edit_movie_modal + .as_ref() + .unwrap() + .path + .offset + .borrow(), + 1 + ); + + EditMovieHandler::with( + &DEFAULT_KEYBINDINGS.right.key, + &mut app, + &ActiveRadarrBlock::EditMoviePathInput, + &None, + ) + .handle(); + + assert_eq!( + *app + .data + .radarr_data + .edit_movie_modal + .as_ref() + .unwrap() + .path + .offset + .borrow(), + 0 ); } #[test] fn test_edit_movie_tags_input_left_right_keys() { - test_text_box_left_right_keys!( - EditMovieHandler, - ActiveRadarrBlock::EditMovieTagsInput, - edit_tags + let mut app = App::default(); + app.data.radarr_data.edit_movie_modal = Some(EditMovieModal { + tags: "Test".into(), + ..EditMovieModal::default() + }); + + EditMovieHandler::with( + &DEFAULT_KEYBINDINGS.left.key, + &mut app, + &ActiveRadarrBlock::EditMovieTagsInput, + &None, + ) + .handle(); + + assert_eq!( + *app + .data + .radarr_data + .edit_movie_modal + .as_ref() + .unwrap() + .tags + .offset + .borrow(), + 1 + ); + + EditMovieHandler::with( + &DEFAULT_KEYBINDINGS.right.key, + &mut app, + &ActiveRadarrBlock::EditMovieTagsInput, + &None, + ) + .handle(); + + assert_eq!( + *app + .data + .radarr_data + .edit_movie_modal + .as_ref() + .unwrap() + .tags + .offset + .borrow(), + 0 ); } } @@ -147,7 +512,8 @@ mod tests { use pretty_assertions::assert_eq; use rstest::rstest; - use crate::models::servarr_data::radarr_data::{ + use crate::models::servarr_data::radarr::modals::EditMovieModal; + use crate::models::servarr_data::radarr::radarr_data::{ EDIT_COLLECTION_SELECTION_BLOCKS, EDIT_MOVIE_SELECTION_BLOCKS, }; use crate::models::{BlockSelectionState, Route}; @@ -161,7 +527,10 @@ mod tests { fn test_edit_movie_path_input_submit() { let mut app = App::default(); app.should_ignore_quit_key = true; - app.data.radarr_data.edit_path = "Test Path".to_owned().into(); + app.data.radarr_data.edit_movie_modal = Some(EditMovieModal { + path: "Test Path".into(), + ..EditMovieModal::default() + }); app.push_navigation_stack(ActiveRadarrBlock::EditMoviePrompt.into()); app.push_navigation_stack(ActiveRadarrBlock::EditMoviePathInput.into()); @@ -174,7 +543,15 @@ mod tests { .handle(); assert!(!app.should_ignore_quit_key); - assert!(!app.data.radarr_data.edit_path.text.is_empty()); + assert!(!app + .data + .radarr_data + .edit_movie_modal + .as_ref() + .unwrap() + .path + .text + .is_empty()); assert_eq!( app.get_current_route(), &ActiveRadarrBlock::EditMoviePrompt.into() @@ -185,7 +562,10 @@ mod tests { fn test_edit_movie_tags_input_submit() { let mut app = App::default(); app.should_ignore_quit_key = true; - app.data.radarr_data.edit_tags = "Test Tags".to_owned().into(); + app.data.radarr_data.edit_movie_modal = Some(EditMovieModal { + tags: "Test Tags".into(), + ..EditMovieModal::default() + }); app.push_navigation_stack(ActiveRadarrBlock::EditMoviePrompt.into()); app.push_navigation_stack(ActiveRadarrBlock::EditMoviePathInput.into()); @@ -198,7 +578,15 @@ mod tests { .handle(); assert!(!app.should_ignore_quit_key); - assert!(!app.data.radarr_data.edit_tags.text.is_empty()); + assert!(!app + .data + .radarr_data + .edit_movie_modal + .as_mut() + .unwrap() + .tags + .text + .is_empty()); assert_eq!( app.get_current_route(), &ActiveRadarrBlock::EditMoviePrompt.into() @@ -232,6 +620,7 @@ mod tests { #[test] fn test_edit_movie_confirm_prompt_prompt_confirmation_submit() { let mut app = App::default(); + app.data.radarr_data.edit_movie_modal = Some(EditMovieModal::default()); app.push_navigation_stack(ActiveRadarrBlock::Movies.into()); app.push_navigation_stack(ActiveRadarrBlock::EditMoviePrompt.into()); app.data.radarr_data.prompt_confirm = true; @@ -255,6 +644,7 @@ mod tests { app.data.radarr_data.prompt_confirm_action, Some(RadarrEvent::EditMovie) ); + assert!(app.data.radarr_data.edit_movie_modal.is_some()); assert!(app.should_refresh); } @@ -265,6 +655,7 @@ mod tests { Some(ActiveRadarrBlock::Movies), )); let mut app = App::default(); + app.data.radarr_data.edit_movie_modal = Some(EditMovieModal::default()); app.data.radarr_data.selected_block = BlockSelectionState::new(&EDIT_MOVIE_SELECTION_BLOCKS); app.push_navigation_stack(current_route); @@ -277,7 +668,16 @@ mod tests { .handle(); assert_eq!(app.get_current_route(), ¤t_route); - assert_eq!(app.data.radarr_data.edit_monitored, Some(true)); + assert_eq!( + app + .data + .radarr_data + .edit_movie_modal + .as_ref() + .unwrap() + .monitored, + Some(true) + ); EditMovieHandler::with( &SUBMIT_KEY, @@ -288,7 +688,16 @@ mod tests { .handle(); assert_eq!(app.get_current_route(), ¤t_route); - assert_eq!(app.data.radarr_data.edit_monitored, Some(false)); + assert_eq!( + app + .data + .radarr_data + .edit_movie_modal + .as_ref() + .unwrap() + .monitored, + Some(false) + ); } #[rstest] @@ -371,8 +780,8 @@ mod tests { use pretty_assertions::assert_eq; use rstest::rstest; - use crate::models::servarr_data::radarr_data::radarr_test_utils::utils::create_test_radarr_data; - use crate::{assert_edit_media_reset, assert_preferences_selections_reset}; + use crate::models::servarr_data::radarr::modals::EditMovieModal; + use crate::models::servarr_data::radarr::radarr_data::radarr_test_utils::utils::create_test_radarr_data; use super::*; @@ -406,6 +815,7 @@ mod tests { let mut app = App::default(); app.push_navigation_stack(ActiveRadarrBlock::EditMoviePrompt.into()); app.data.radarr_data = create_test_radarr_data(); + app.data.radarr_data.edit_movie_modal = Some(EditMovieModal::default()); EditMovieHandler::with( &ESC_KEY, @@ -416,11 +826,9 @@ mod tests { .handle(); assert_eq!(app.get_current_route(), &ActiveRadarrBlock::Movies.into()); - let radarr_data = &app.data.radarr_data; - assert_preferences_selections_reset!(radarr_data); - assert_edit_media_reset!(radarr_data); - assert!(!radarr_data.prompt_confirm); + assert!(app.data.radarr_data.edit_movie_modal.is_none()); + assert!(!app.data.radarr_data.prompt_confirm); } #[rstest] @@ -443,11 +851,15 @@ mod tests { mod test_handle_key_char { use super::*; + use crate::models::servarr_data::radarr::modals::EditMovieModal; #[test] fn test_edit_movie_path_input_backspace() { let mut app = App::default(); - app.data.radarr_data.edit_path = "Test".to_owned().into(); + app.data.radarr_data.edit_movie_modal = Some(EditMovieModal { + path: "Test".into(), + ..EditMovieModal::default() + }); EditMovieHandler::with( &DEFAULT_KEYBINDINGS.backspace.key, @@ -457,13 +869,26 @@ mod tests { ) .handle(); - assert_str_eq!(app.data.radarr_data.edit_path.text, "Tes"); + assert_str_eq!( + app + .data + .radarr_data + .edit_movie_modal + .as_ref() + .unwrap() + .path + .text, + "Tes" + ); } #[test] fn test_edit_movie_tags_input_backspace() { let mut app = App::default(); - app.data.radarr_data.edit_tags = "Test".to_owned().into(); + app.data.radarr_data.edit_movie_modal = Some(EditMovieModal { + tags: "Test".into(), + ..EditMovieModal::default() + }); EditMovieHandler::with( &DEFAULT_KEYBINDINGS.backspace.key, @@ -473,12 +898,23 @@ mod tests { ) .handle(); - assert_str_eq!(app.data.radarr_data.edit_tags.text, "Tes"); + assert_str_eq!( + app + .data + .radarr_data + .edit_movie_modal + .as_ref() + .unwrap() + .tags + .text, + "Tes" + ); } #[test] fn test_edit_movie_path_input_char_key() { let mut app = App::default(); + app.data.radarr_data.edit_movie_modal = Some(EditMovieModal::default()); EditMovieHandler::with( &Key::Char('h'), @@ -488,12 +924,23 @@ mod tests { ) .handle(); - assert_str_eq!(app.data.radarr_data.edit_path.text, "h"); + assert_str_eq!( + app + .data + .radarr_data + .edit_movie_modal + .as_ref() + .unwrap() + .path + .text, + "h" + ); } #[test] fn test_edit_movie_tags_input_char_key() { let mut app = App::default(); + app.data.radarr_data.edit_movie_modal = Some(EditMovieModal::default()); EditMovieHandler::with( &Key::Char('h'), @@ -503,7 +950,17 @@ mod tests { ) .handle(); - assert_str_eq!(app.data.radarr_data.edit_tags.text, "h"); + assert_str_eq!( + app + .data + .radarr_data + .edit_movie_modal + .as_ref() + .unwrap() + .tags + .text, + "h" + ); } } diff --git a/src/handlers/radarr_handlers/library/library_handler_tests.rs b/src/handlers/radarr_handlers/library/library_handler_tests.rs index d5d1ba6..924f877 100644 --- a/src/handlers/radarr_handlers/library/library_handler_tests.rs +++ b/src/handlers/radarr_handlers/library/library_handler_tests.rs @@ -10,7 +10,7 @@ mod tests { use crate::handlers::radarr_handlers::library::LibraryHandler; use crate::handlers::KeyEventHandler; use crate::models::radarr_models::Movie; - use crate::models::servarr_data::radarr_data::{ + use crate::models::servarr_data::radarr::radarr_data::{ ActiveRadarrBlock, ADD_MOVIE_BLOCKS, DELETE_MOVIE_BLOCKS, EDIT_MOVIE_BLOCKS, LIBRARY_BLOCKS, MOVIE_DETAILS_BLOCKS, }; @@ -91,7 +91,7 @@ mod tests { use pretty_assertions::assert_eq; use crate::assert_delete_prompt; - use crate::models::servarr_data::radarr_data::DELETE_MOVIE_SELECTION_BLOCKS; + use crate::models::servarr_data::radarr::radarr_data::DELETE_MOVIE_SELECTION_BLOCKS; use super::*; @@ -365,7 +365,7 @@ mod tests { mod test_handle_esc { use pretty_assertions::assert_eq; - use crate::models::servarr_data::radarr_data::radarr_test_utils::utils::create_test_radarr_data; + use crate::models::servarr_data::radarr::radarr_data::radarr_test_utils::utils::create_test_radarr_data; use crate::{assert_filter_reset, assert_search_reset}; use super::*; @@ -445,9 +445,11 @@ mod tests { use strum::IntoEnumIterator; use crate::models::radarr_models::MinimumAvailability; - use crate::models::servarr_data::radarr_data::radarr_test_utils::utils::create_test_radarr_data; - use crate::models::servarr_data::radarr_data::{RadarrData, EDIT_MOVIE_SELECTION_BLOCKS}; - use crate::models::HorizontallyScrollableText; + use crate::models::servarr_data::radarr::radarr_data::radarr_test_utils::utils::create_test_radarr_data; + use crate::models::servarr_data::radarr::radarr_data::{ + RadarrData, EDIT_MOVIE_SELECTION_BLOCKS, + }; + use crate::models::StatefulTable; use crate::{assert_refresh_key, test_edit_movie_key}; diff --git a/src/handlers/radarr_handlers/library/mod.rs b/src/handlers/radarr_handlers/library/mod.rs index ee196e7..7da2949 100644 --- a/src/handlers/radarr_handlers/library/mod.rs +++ b/src/handlers/radarr_handlers/library/mod.rs @@ -9,7 +9,7 @@ use crate::handlers::radarr_handlers::{ filter_table, handle_change_tab_left_right_keys, search_table, }; use crate::handlers::{handle_clear_errors, handle_prompt_toggle, KeyEventHandler}; -use crate::models::servarr_data::radarr_data::{ +use crate::models::servarr_data::radarr::radarr_data::{ ActiveRadarrBlock, DELETE_MOVIE_SELECTION_BLOCKS, EDIT_MOVIE_SELECTION_BLOCKS, LIBRARY_BLOCKS, }; use crate::models::{BlockSelectionState, Scrollable}; @@ -266,7 +266,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for LibraryHandler<'a, ' ) .into(), ); - self.app.data.radarr_data.populate_edit_movie_fields(); + self.app.data.radarr_data.edit_movie_modal = Some((&self.app.data.radarr_data).into()); self.app.data.radarr_data.selected_block = BlockSelectionState::new(&EDIT_MOVIE_SELECTION_BLOCKS); } diff --git a/src/handlers/radarr_handlers/library/movie_details_handler.rs b/src/handlers/radarr_handlers/library/movie_details_handler.rs index d5a4742..b3f2734 100644 --- a/src/handlers/radarr_handlers/library/movie_details_handler.rs +++ b/src/handlers/radarr_handlers/library/movie_details_handler.rs @@ -8,7 +8,7 @@ use crate::app::App; use crate::event::Key; use crate::handlers::{handle_prompt_toggle, KeyEventHandler}; use crate::models::radarr_models::{Language, Release, ReleaseField}; -use crate::models::servarr_data::radarr_data::{ +use crate::models::servarr_data::radarr::radarr_data::{ ActiveRadarrBlock, EDIT_MOVIE_SELECTION_BLOCKS, MOVIE_DETAILS_BLOCKS, }; use crate::models::{BlockSelectionState, Scrollable}; @@ -243,7 +243,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for MovieDetailsHandler< ) .into(), ); - self.app.data.radarr_data.populate_edit_movie_fields(); + self.app.data.radarr_data.edit_movie_modal = Some((&self.app.data.radarr_data).into()); self.app.data.radarr_data.selected_block = BlockSelectionState::new(&EDIT_MOVIE_SELECTION_BLOCKS); } diff --git a/src/handlers/radarr_handlers/library/movie_details_handler_tests.rs b/src/handlers/radarr_handlers/library/movie_details_handler_tests.rs index d317084..0b67eb5 100644 --- a/src/handlers/radarr_handlers/library/movie_details_handler_tests.rs +++ b/src/handlers/radarr_handlers/library/movie_details_handler_tests.rs @@ -15,7 +15,7 @@ mod tests { use crate::models::radarr_models::{ Credit, Language, MovieHistoryItem, Quality, QualityWrapper, Release, ReleaseField, }; - use crate::models::servarr_data::radarr_data::{ActiveRadarrBlock, MOVIE_DETAILS_BLOCKS}; + use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, MOVIE_DETAILS_BLOCKS}; use crate::models::{HorizontallyScrollableText, ScrollableText}; mod test_handle_scroll_up_and_down { @@ -24,10 +24,7 @@ mod tests { use strum::IntoEnumIterator; use crate::models::radarr_models::ReleaseField; - use crate::{ - simple_stateful_iterable_vec, test_enum_scroll, test_iterable_scroll, - test_scrollable_text_scroll, - }; + use crate::{simple_stateful_iterable_vec, test_iterable_scroll, test_scrollable_text_scroll}; use super::*; @@ -82,14 +79,50 @@ mod tests { to_string ); - test_enum_scroll!( - test_manual_search_sort_scroll, - MovieDetailsHandler, - ReleaseField, - movie_releases_sort, - ActiveRadarrBlock::ManualSearchSortPrompt, - None - ); + #[rstest] + fn test_manual_search_sort_scroll( + #[values(DEFAULT_KEYBINDINGS.up.key, DEFAULT_KEYBINDINGS.down.key)] key: Key, + ) { + let release_field_vec = Vec::from_iter(ReleaseField::iter()); + let mut app = App::default(); + app + .data + .radarr_data + .movie_releases_sort + .set_items(release_field_vec.clone()); + + if key == Key::Up { + for i in (0..release_field_vec.len()).rev() { + MovieDetailsHandler::with( + &key, + &mut app, + &ActiveRadarrBlock::ManualSearchSortPrompt, + &None, + ) + .handle(); + + assert_eq!( + app.data.radarr_data.movie_releases_sort.current_selection(), + &release_field_vec[i] + ); + } + } else { + for i in 0..release_field_vec.len() { + MovieDetailsHandler::with( + &key, + &mut app, + &ActiveRadarrBlock::ManualSearchSortPrompt, + &None, + ) + .handle(); + + assert_eq!( + app.data.radarr_data.movie_releases_sort.current_selection(), + &release_field_vec[(i + 1) % release_field_vec.len()] + ); + } + } + } } mod test_handle_home_end { @@ -97,8 +130,7 @@ mod tests { use crate::models::radarr_models::ReleaseField; use crate::{ - extended_stateful_iterable_vec, test_enum_home_and_end, test_iterable_home_and_end, - test_scrollable_text_home_and_end, + extended_stateful_iterable_vec, test_iterable_home_and_end, test_scrollable_text_home_and_end, }; use super::*; @@ -154,14 +186,42 @@ mod tests { to_string ); - test_enum_home_and_end!( - test_manual_search_sort_home_end, - MovieDetailsHandler, - ReleaseField, - movie_releases_sort, - ActiveRadarrBlock::ManualSearchSortPrompt, - None - ); + #[test] + fn test_manual_search_sort_home_end() { + let release_field_vec = Vec::from_iter(ReleaseField::iter()); + let mut app = App::default(); + app + .data + .radarr_data + .movie_releases_sort + .set_items(release_field_vec.clone()); + + MovieDetailsHandler::with( + &DEFAULT_KEYBINDINGS.end.key, + &mut app, + &ActiveRadarrBlock::ManualSearchSortPrompt, + &None, + ) + .handle(); + + assert_eq!( + app.data.radarr_data.movie_releases_sort.current_selection(), + &release_field_vec[release_field_vec.len() - 1] + ); + + MovieDetailsHandler::with( + &DEFAULT_KEYBINDINGS.home.key, + &mut app, + &ActiveRadarrBlock::ManualSearchSortPrompt, + &None, + ) + .handle(); + + assert_eq!( + app.data.radarr_data.movie_releases_sort.current_selection(), + &release_field_vec[0] + ); + } } mod test_handle_left_right_action { @@ -355,7 +415,7 @@ mod tests { use rstest::rstest; use crate::assert_movie_info_tabs_reset; - use crate::models::servarr_data::radarr_data::radarr_test_utils::utils::create_test_radarr_data; + use crate::models::servarr_data::radarr::radarr_data::radarr_test_utils::utils::create_test_radarr_data; use super::*; @@ -413,9 +473,10 @@ mod tests { use strum::IntoEnumIterator; use crate::models::radarr_models::{MinimumAvailability, Movie}; - use crate::models::servarr_data::radarr_data::radarr_test_utils::utils::create_test_radarr_data; - use crate::models::servarr_data::radarr_data::{RadarrData, EDIT_MOVIE_SELECTION_BLOCKS}; - use crate::models::HorizontallyScrollableText; + use crate::models::servarr_data::radarr::radarr_data::radarr_test_utils::utils::create_test_radarr_data; + use crate::models::servarr_data::radarr::radarr_data::{ + RadarrData, EDIT_MOVIE_SELECTION_BLOCKS, + }; use crate::models::StatefulTable; use crate::test_edit_movie_key; diff --git a/src/handlers/radarr_handlers/mod.rs b/src/handlers/radarr_handlers/mod.rs index c07405d..3c8a26c 100644 --- a/src/handlers/radarr_handlers/mod.rs +++ b/src/handlers/radarr_handlers/mod.rs @@ -6,7 +6,7 @@ use crate::handlers::radarr_handlers::library::LibraryHandler; use crate::handlers::radarr_handlers::root_folders::RootFoldersHandler; use crate::handlers::radarr_handlers::system::SystemHandler; use crate::handlers::KeyEventHandler; -use crate::models::servarr_data::radarr_data::ActiveRadarrBlock; +use crate::models::servarr_data::radarr::radarr_data::ActiveRadarrBlock; use crate::utils::strip_non_search_characters; use crate::{App, Key}; diff --git a/src/handlers/radarr_handlers/radarr_handler_test_utils.rs b/src/handlers/radarr_handlers/radarr_handler_test_utils.rs index a8dae82..b0a4b35 100644 --- a/src/handlers/radarr_handlers/radarr_handler_test_utils.rs +++ b/src/handlers/radarr_handlers/radarr_handler_test_utils.rs @@ -6,10 +6,6 @@ mod utils { ($handler:ident, $block:expr, $context:expr) => { let mut app = App::default(); let mut radarr_data = RadarrData { - edit_path: HorizontallyScrollableText::default(), - edit_tags: HorizontallyScrollableText::default(), - edit_monitored: None, - edit_search_on_add: None, quality_profile_map: BiMap::from_iter([ (2222, "HD - 1080p".to_owned()), (1111, "Any".to_owned()), @@ -39,32 +35,81 @@ mod utils { &ActiveRadarrBlock::EditMovieToggleMonitored ); assert_eq!( - app.data.radarr_data.minimum_availability_list.items, + app + .data + .radarr_data + .edit_movie_modal + .as_ref() + .unwrap() + .minimum_availability_list + .items, Vec::from_iter(MinimumAvailability::iter()) ); assert_eq!( app .data .radarr_data + .edit_movie_modal + .as_ref() + .unwrap() .minimum_availability_list .current_selection(), &MinimumAvailability::Released ); assert_eq!( - app.data.radarr_data.quality_profile_list.items, + app + .data + .radarr_data + .edit_movie_modal + .as_ref() + .unwrap() + .quality_profile_list + .items, vec!["Any".to_owned(), "HD - 1080p".to_owned()] ); assert_str_eq!( app .data .radarr_data + .edit_movie_modal + .as_ref() + .unwrap() .quality_profile_list .current_selection(), "HD - 1080p" ); - assert_str_eq!(app.data.radarr_data.edit_path.text, "/nfs/movies/Test"); - assert_str_eq!(app.data.radarr_data.edit_tags.text, "test"); - assert_eq!(app.data.radarr_data.edit_monitored, Some(true)); + assert_str_eq!( + app + .data + .radarr_data + .edit_movie_modal + .as_ref() + .unwrap() + .path + .text, + "/nfs/movies/Test" + ); + assert_str_eq!( + app + .data + .radarr_data + .edit_movie_modal + .as_ref() + .unwrap() + .tags + .text, + "test" + ); + assert_eq!( + app + .data + .radarr_data + .edit_movie_modal + .as_ref() + .unwrap() + .monitored, + Some(true) + ); assert_eq!( app.data.radarr_data.selected_block.blocks, &EDIT_MOVIE_SELECTION_BLOCKS @@ -77,10 +122,6 @@ mod utils { ($handler:ident, $block:expr, $context:expr) => { let mut app = App::default(); let mut radarr_data = RadarrData { - edit_path: HorizontallyScrollableText::default(), - edit_tags: HorizontallyScrollableText::default(), - edit_monitored: None, - edit_search_on_add: None, quality_profile_map: BiMap::from_iter([ (2222, "HD - 1080p".to_owned()), (1111, "Any".to_owned()), @@ -109,32 +150,80 @@ mod utils { &ActiveRadarrBlock::EditCollectionToggleMonitored ); assert_eq!( - app.data.radarr_data.minimum_availability_list.items, + app + .data + .radarr_data + .edit_collection_modal + .as_ref() + .unwrap() + .minimum_availability_list + .items, Vec::from_iter(MinimumAvailability::iter()) ); assert_eq!( app .data .radarr_data + .edit_collection_modal + .as_ref() + .unwrap() .minimum_availability_list .current_selection(), &MinimumAvailability::Released ); assert_eq!( - app.data.radarr_data.quality_profile_list.items, + app + .data + .radarr_data + .edit_collection_modal + .as_ref() + .unwrap() + .quality_profile_list + .items, vec!["Any".to_owned(), "HD - 1080p".to_owned()] ); assert_str_eq!( app .data .radarr_data + .edit_collection_modal + .as_ref() + .unwrap() .quality_profile_list .current_selection(), "HD - 1080p" ); - assert_str_eq!(app.data.radarr_data.edit_path.text, "/nfs/movies/Test"); - assert_eq!(app.data.radarr_data.edit_monitored, Some(true)); - assert_eq!(app.data.radarr_data.edit_search_on_add, Some(true)); + assert_str_eq!( + app + .data + .radarr_data + .edit_collection_modal + .as_ref() + .unwrap() + .path + .text, + "/nfs/movies/Test" + ); + assert_eq!( + app + .data + .radarr_data + .edit_collection_modal + .as_ref() + .unwrap() + .monitored, + Some(true) + ); + assert_eq!( + app + .data + .radarr_data + .edit_collection_modal + .as_ref() + .unwrap() + .search_on_add, + Some(true) + ); assert_eq!( app.data.radarr_data.selected_block.blocks, &EDIT_COLLECTION_SELECTION_BLOCKS diff --git a/src/handlers/radarr_handlers/radarr_handler_tests.rs b/src/handlers/radarr_handlers/radarr_handler_tests.rs index d684982..c7339be 100644 --- a/src/handlers/radarr_handlers/radarr_handler_tests.rs +++ b/src/handlers/radarr_handlers/radarr_handler_tests.rs @@ -11,7 +11,7 @@ mod tests { }; use crate::handlers::KeyEventHandler; use crate::models::radarr_models::Movie; - use crate::models::servarr_data::radarr_data::ActiveRadarrBlock; + use crate::models::servarr_data::radarr::radarr_data::ActiveRadarrBlock; use crate::models::HorizontallyScrollableText; use crate::{extended_stateful_iterable_vec, test_handler_delegation}; diff --git a/src/handlers/radarr_handlers/root_folders/mod.rs b/src/handlers/radarr_handlers/root_folders/mod.rs index 0a65b0b..cfa21c9 100644 --- a/src/handlers/radarr_handlers/root_folders/mod.rs +++ b/src/handlers/radarr_handlers/root_folders/mod.rs @@ -3,7 +3,7 @@ use crate::app::App; use crate::event::Key; use crate::handlers::radarr_handlers::handle_change_tab_left_right_keys; use crate::handlers::{handle_clear_errors, handle_prompt_toggle, KeyEventHandler}; -use crate::models::servarr_data::radarr_data::{ActiveRadarrBlock, ROOT_FOLDERS_BLOCKS}; +use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, ROOT_FOLDERS_BLOCKS}; use crate::models::{HorizontallyScrollableText, Scrollable}; use crate::network::radarr_network::RadarrEvent; use crate::{handle_text_box_keys, handle_text_box_left_right_keys}; diff --git a/src/handlers/radarr_handlers/root_folders/root_folders_handler_tests.rs b/src/handlers/radarr_handlers/root_folders/root_folders_handler_tests.rs index e5efce9..5c35f3e 100644 --- a/src/handlers/radarr_handlers/root_folders/root_folders_handler_tests.rs +++ b/src/handlers/radarr_handlers/root_folders/root_folders_handler_tests.rs @@ -8,7 +8,7 @@ mod tests { use crate::event::Key; use crate::handlers::radarr_handlers::root_folders::RootFoldersHandler; use crate::handlers::KeyEventHandler; - use crate::models::servarr_data::radarr_data::{ActiveRadarrBlock, ROOT_FOLDERS_BLOCKS}; + use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, ROOT_FOLDERS_BLOCKS}; use crate::models::HorizontallyScrollableText; mod test_handle_scroll_up_and_down { diff --git a/src/handlers/radarr_handlers/system/mod.rs b/src/handlers/radarr_handlers/system/mod.rs index 7b92d48..d940317 100644 --- a/src/handlers/radarr_handlers/system/mod.rs +++ b/src/handlers/radarr_handlers/system/mod.rs @@ -4,7 +4,7 @@ use crate::event::Key; use crate::handlers::radarr_handlers::handle_change_tab_left_right_keys; use crate::handlers::radarr_handlers::system::system_details_handler::SystemDetailsHandler; use crate::handlers::{handle_clear_errors, KeyEventHandler}; -use crate::models::servarr_data::radarr_data::ActiveRadarrBlock; +use crate::models::servarr_data::radarr::radarr_data::ActiveRadarrBlock; use crate::models::Scrollable; mod system_details_handler; diff --git a/src/handlers/radarr_handlers/system/system_details_handler.rs b/src/handlers/radarr_handlers/system/system_details_handler.rs index e1bb248..47e9cdf 100644 --- a/src/handlers/radarr_handlers/system/system_details_handler.rs +++ b/src/handlers/radarr_handlers/system/system_details_handler.rs @@ -2,8 +2,8 @@ use crate::app::key_binding::DEFAULT_KEYBINDINGS; use crate::app::App; use crate::event::Key; use crate::handlers::{handle_prompt_toggle, KeyEventHandler}; -use crate::models::servarr_data::radarr_data::{ActiveRadarrBlock, SYSTEM_DETAILS_BLOCKS}; -use crate::models::Scrollable; +use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, SYSTEM_DETAILS_BLOCKS}; +use crate::models::{Scrollable, StatefulList}; use crate::network::radarr_network::RadarrEvent; #[cfg(test)] @@ -141,7 +141,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for SystemDetailsHandler fn handle_esc(&mut self) { match self.active_radarr_block { ActiveRadarrBlock::SystemLogs => { - self.app.data.radarr_data.reset_log_details_list(); + self.app.data.radarr_data.log_details = StatefulList::default(); self.app.pop_navigation_stack() } ActiveRadarrBlock::SystemQueuedEvents diff --git a/src/handlers/radarr_handlers/system/system_details_handler_tests.rs b/src/handlers/radarr_handlers/system/system_details_handler_tests.rs index 7d8c7bd..6216f99 100644 --- a/src/handlers/radarr_handlers/system/system_details_handler_tests.rs +++ b/src/handlers/radarr_handlers/system/system_details_handler_tests.rs @@ -9,7 +9,9 @@ mod tests { use crate::handlers::radarr_handlers::system::system_details_handler::SystemDetailsHandler; use crate::handlers::KeyEventHandler; use crate::models::radarr_models::{QueueEvent, Task}; - use crate::models::servarr_data::radarr_data::{ActiveRadarrBlock, SYSTEM_DETAILS_BLOCKS}; + use crate::models::servarr_data::radarr::radarr_data::{ + ActiveRadarrBlock, SYSTEM_DETAILS_BLOCKS, + }; mod test_handle_scroll_up_and_down { use rstest::rstest; diff --git a/src/handlers/radarr_handlers/system/system_handler_tests.rs b/src/handlers/radarr_handlers/system/system_handler_tests.rs index 5e9b558..566c4bf 100644 --- a/src/handlers/radarr_handlers/system/system_handler_tests.rs +++ b/src/handlers/radarr_handlers/system/system_handler_tests.rs @@ -9,7 +9,9 @@ mod tests { use crate::event::Key; use crate::handlers::radarr_handlers::system::SystemHandler; use crate::handlers::KeyEventHandler; - use crate::models::servarr_data::radarr_data::{ActiveRadarrBlock, SYSTEM_DETAILS_BLOCKS}; + use crate::models::servarr_data::radarr::radarr_data::{ + ActiveRadarrBlock, SYSTEM_DETAILS_BLOCKS, + }; use crate::test_handler_delegation; mod test_handle_left_right_action { diff --git a/src/models/mod.rs b/src/models/mod.rs index 93ff44f..f35768d 100644 --- a/src/models/mod.rs +++ b/src/models/mod.rs @@ -1,7 +1,7 @@ use std::cell::RefCell; use std::fmt::{Debug, Display, Formatter}; -use crate::models::servarr_data::radarr_data::ActiveRadarrBlock; +use crate::models::servarr_data::radarr::radarr_data::ActiveRadarrBlock; use serde::Deserialize; use tui::widgets::{ListState, TableState}; diff --git a/src/models/model_tests.rs b/src/models/model_tests.rs index da45919..4584ada 100644 --- a/src/models/model_tests.rs +++ b/src/models/model_tests.rs @@ -4,7 +4,7 @@ mod tests { use pretty_assertions::{assert_eq, assert_str_eq}; - use crate::models::servarr_data::radarr_data::ActiveRadarrBlock; + use crate::models::servarr_data::radarr::radarr_data::ActiveRadarrBlock; use crate::models::{ BlockSelectionState, HorizontallyScrollableText, Scrollable, ScrollableText, StatefulList, StatefulTable, TabRoute, TabState, diff --git a/src/models/servarr_data/mod.rs b/src/models/servarr_data/mod.rs index f6d800f..c430c1a 100644 --- a/src/models/servarr_data/mod.rs +++ b/src/models/servarr_data/mod.rs @@ -1 +1 @@ -pub mod radarr_data; +pub mod radarr; diff --git a/src/models/servarr_data/radarr/mod.rs b/src/models/servarr_data/radarr/mod.rs new file mode 100644 index 0000000..8594793 --- /dev/null +++ b/src/models/servarr_data/radarr/mod.rs @@ -0,0 +1,2 @@ +pub mod modals; +pub mod radarr_data; diff --git a/src/models/servarr_data/radarr/modals.rs b/src/models/servarr_data/radarr/modals.rs new file mode 100644 index 0000000..358ee09 --- /dev/null +++ b/src/models/servarr_data/radarr/modals.rs @@ -0,0 +1,193 @@ +use crate::models::radarr_models::{Collection, MinimumAvailability, Monitor, Movie, RootFolder}; +use crate::models::servarr_data::radarr::radarr_data::RadarrData; +use crate::models::{HorizontallyScrollableText, StatefulList}; +use strum::IntoEnumIterator; + +#[cfg(test)] +#[path = "modals_tests.rs"] +mod modals_tests; + +#[derive(Default)] +pub struct EditMovieModal { + pub minimum_availability_list: StatefulList, + pub quality_profile_list: StatefulList, + pub monitored: Option, + pub path: HorizontallyScrollableText, + pub tags: HorizontallyScrollableText, +} + +impl From<&RadarrData<'_>> for EditMovieModal { + fn from(radarr_data: &RadarrData<'_>) -> EditMovieModal { + let mut edit_movie_modal = EditMovieModal::default(); + let Movie { + path, + tags, + monitored, + minimum_availability, + quality_profile_id, + .. + } = if radarr_data.filtered_movies.items.is_empty() { + radarr_data.movies.current_selection() + } else { + radarr_data.filtered_movies.current_selection() + }; + + edit_movie_modal + .minimum_availability_list + .set_items(Vec::from_iter(MinimumAvailability::iter())); + edit_movie_modal.path = path.clone().into(); + edit_movie_modal.tags = tags + .iter() + .map(|tag_id| { + radarr_data + .tags_map + .get_by_left(&tag_id.as_u64().unwrap()) + .unwrap() + .clone() + }) + .collect::>() + .join(", ") + .into(); + + edit_movie_modal.monitored = Some(*monitored); + + let minimum_availability_index = edit_movie_modal + .minimum_availability_list + .items + .iter() + .position(|ma| ma == minimum_availability); + edit_movie_modal + .minimum_availability_list + .state + .select(minimum_availability_index); + + let mut quality_profile_names: Vec = radarr_data + .quality_profile_map + .right_values() + .cloned() + .collect(); + quality_profile_names.sort(); + edit_movie_modal + .quality_profile_list + .set_items(quality_profile_names); + let quality_profile_name = radarr_data + .quality_profile_map + .get_by_left(&quality_profile_id.as_u64().unwrap()) + .unwrap(); + let quality_profile_index = edit_movie_modal + .quality_profile_list + .items + .iter() + .position(|profile| profile == quality_profile_name); + edit_movie_modal + .quality_profile_list + .state + .select(quality_profile_index); + + edit_movie_modal + } +} + +#[derive(Default)] +pub struct AddMovieModal { + pub root_folder_list: StatefulList, + pub monitor_list: StatefulList, + pub minimum_availability_list: StatefulList, + pub quality_profile_list: StatefulList, + pub tags: HorizontallyScrollableText, +} + +impl From<&RadarrData<'_>> for AddMovieModal { + fn from(radarr_data: &RadarrData<'_>) -> AddMovieModal { + let mut add_movie_modal = AddMovieModal::default(); + add_movie_modal + .monitor_list + .set_items(Vec::from_iter(Monitor::iter())); + add_movie_modal + .minimum_availability_list + .set_items(Vec::from_iter(MinimumAvailability::iter())); + let mut quality_profile_names: Vec = radarr_data + .quality_profile_map + .right_values() + .cloned() + .collect(); + quality_profile_names.sort(); + add_movie_modal + .quality_profile_list + .set_items(quality_profile_names); + add_movie_modal + .root_folder_list + .set_items(radarr_data.root_folders.items.to_vec()); + + add_movie_modal + } +} + +#[derive(Default)] +pub struct EditCollectionModal { + pub monitored: Option, + pub minimum_availability_list: StatefulList, + pub quality_profile_list: StatefulList, + pub path: HorizontallyScrollableText, + pub search_on_add: Option, +} + +impl From<&RadarrData<'_>> for EditCollectionModal { + fn from(radarr_data: &RadarrData<'_>) -> EditCollectionModal { + let mut edit_collection_modal = EditCollectionModal::default(); + let Collection { + root_folder_path, + monitored, + search_on_add, + minimum_availability, + quality_profile_id, + .. + } = if radarr_data.filtered_collections.items.is_empty() { + radarr_data.collections.current_selection() + } else { + radarr_data.filtered_collections.current_selection() + }; + + edit_collection_modal.path = root_folder_path.clone().unwrap_or_default().into(); + edit_collection_modal.monitored = Some(*monitored); + edit_collection_modal.search_on_add = Some(*search_on_add); + edit_collection_modal + .minimum_availability_list + .set_items(Vec::from_iter(MinimumAvailability::iter())); + let mut quality_profile_names: Vec = radarr_data + .quality_profile_map + .right_values() + .cloned() + .collect(); + quality_profile_names.sort(); + edit_collection_modal + .quality_profile_list + .set_items(quality_profile_names); + + let minimum_availability_index = edit_collection_modal + .minimum_availability_list + .items + .iter() + .position(|ma| ma == minimum_availability); + edit_collection_modal + .minimum_availability_list + .state + .select(minimum_availability_index); + + let quality_profile_name = radarr_data + .quality_profile_map + .get_by_left(&quality_profile_id.as_u64().unwrap()) + .unwrap(); + let quality_profile_index = edit_collection_modal + .quality_profile_list + .items + .iter() + .position(|profile| profile == quality_profile_name); + edit_collection_modal + .quality_profile_list + .state + .select(quality_profile_index); + + edit_collection_modal + } +} diff --git a/src/models/servarr_data/radarr/modals_tests.rs b/src/models/servarr_data/radarr/modals_tests.rs new file mode 100644 index 0000000..bc4f27d --- /dev/null +++ b/src/models/servarr_data/radarr/modals_tests.rs @@ -0,0 +1,161 @@ +#[cfg(test)] +mod test { + use crate::models::radarr_models::{Collection, MinimumAvailability, Monitor, Movie, RootFolder}; + use crate::models::servarr_data::radarr::modals::{ + AddMovieModal, EditCollectionModal, EditMovieModal, + }; + use crate::models::servarr_data::radarr::radarr_data::radarr_test_utils::utils::create_test_radarr_data; + use crate::models::servarr_data::radarr::radarr_data::RadarrData; + use crate::models::{HorizontallyScrollableText, StatefulTable}; + use bimap::BiMap; + use pretty_assertions::{assert_eq, assert_str_eq}; + use rstest::rstest; + use serde_json::Number; + use strum::IntoEnumIterator; + + #[rstest] + fn test_edit_movie_modal_from_radarr_data(#[values(true, false)] test_filtered_movies: bool) { + let mut radarr_data = RadarrData { + edit_path: HorizontallyScrollableText::default(), + edit_tags: HorizontallyScrollableText::default(), + edit_monitored: None, + quality_profile_map: BiMap::from_iter([ + (2222, "HD - 1080p".to_owned()), + (1111, "Any".to_owned()), + ]), + tags_map: BiMap::from_iter([(1, "usenet".to_owned()), (2, "test".to_owned())]), + filtered_movies: StatefulTable::default(), + ..create_test_radarr_data() + }; + let movie = Movie { + path: "/nfs/movies/Test".to_owned(), + monitored: true, + quality_profile_id: Number::from(2222), + minimum_availability: MinimumAvailability::Released, + tags: vec![Number::from(1), Number::from(2)], + ..Movie::default() + }; + + if test_filtered_movies { + radarr_data.filtered_movies.set_items(vec![movie]); + } else { + radarr_data.movies.set_items(vec![movie]); + } + + let edit_movie_modal = EditMovieModal::from(&radarr_data); + + assert_eq!( + edit_movie_modal.minimum_availability_list.items, + Vec::from_iter(MinimumAvailability::iter()) + ); + assert_eq!( + edit_movie_modal + .minimum_availability_list + .current_selection(), + &MinimumAvailability::Released + ); + assert_eq!( + edit_movie_modal.quality_profile_list.items, + vec!["Any".to_owned(), "HD - 1080p".to_owned()] + ); + assert_str_eq!( + edit_movie_modal.quality_profile_list.current_selection(), + "HD - 1080p" + ); + assert_str_eq!(edit_movie_modal.path.text, "/nfs/movies/Test"); + assert_str_eq!(edit_movie_modal.tags.text, "usenet, test"); + assert_eq!(edit_movie_modal.monitored, Some(true)); + } + + #[test] + fn test_add_movie_modal_from_radarr_data() { + let root_folder = RootFolder { + id: Number::from(1), + path: "/nfs".to_owned(), + accessible: true, + free_space: Number::from(219902325555200u64), + unmapped_folders: None, + }; + let mut radarr_data = RadarrData { + quality_profile_map: BiMap::from_iter([ + (2222, "HD - 1080p".to_owned()), + (1111, "Any".to_owned()), + ]), + ..RadarrData::default() + }; + radarr_data + .root_folders + .set_items(vec![root_folder.clone()]); + + let add_movie_modal = AddMovieModal::from(&radarr_data); + + assert_eq!( + add_movie_modal.monitor_list.items, + Vec::from_iter(Monitor::iter()) + ); + assert_eq!( + add_movie_modal.minimum_availability_list.items, + Vec::from_iter(MinimumAvailability::iter()) + ); + assert_eq!( + add_movie_modal.quality_profile_list.items, + vec!["Any".to_owned(), "HD - 1080p".to_owned()] + ); + assert_eq!(add_movie_modal.root_folder_list.items, vec![root_folder]); + assert!(add_movie_modal.tags.text.is_empty()); + } + + #[rstest] + fn test_edit_collection_modal_from_radarr_data( + #[values(true, false)] test_filtered_collections: bool, + ) { + let mut radarr_data = RadarrData { + quality_profile_map: BiMap::from_iter([ + (2222, "HD - 1080p".to_owned()), + (1111, "Any".to_owned()), + ]), + filtered_collections: StatefulTable::default(), + ..create_test_radarr_data() + }; + let collection = Collection { + root_folder_path: Some("/nfs/movies/Test".to_owned()), + monitored: true, + search_on_add: true, + quality_profile_id: Number::from(2222), + minimum_availability: MinimumAvailability::Released, + ..Collection::default() + }; + + if test_filtered_collections { + radarr_data.filtered_collections.set_items(vec![collection]); + } else { + radarr_data.collections.set_items(vec![collection]); + } + + let edit_collection_modal = EditCollectionModal::from(&radarr_data); + + assert_eq!( + edit_collection_modal.minimum_availability_list.items, + Vec::from_iter(MinimumAvailability::iter()) + ); + assert_eq!( + edit_collection_modal + .minimum_availability_list + .current_selection(), + &MinimumAvailability::Released + ); + assert_eq!( + edit_collection_modal.quality_profile_list.items, + vec!["Any".to_owned(), "HD - 1080p".to_owned()] + ); + assert_str_eq!( + edit_collection_modal + .quality_profile_list + .current_selection(), + "HD - 1080p" + ); + assert_str_eq!(edit_collection_modal.path.text, "/nfs/movies/Test"); + assert_eq!(edit_collection_modal.monitored, Some(true)); + assert_eq!(edit_collection_modal.search_on_add, Some(true)); + } +} diff --git a/src/models/servarr_data/radarr_data.rs b/src/models/servarr_data/radarr/radarr_data.rs similarity index 82% rename from src/models/servarr_data/radarr_data.rs rename to src/models/servarr_data/radarr/radarr_data.rs index 792f1ef..9a9d7bf 100644 --- a/src/models/servarr_data/radarr_data.rs +++ b/src/models/servarr_data/radarr/radarr_data.rs @@ -10,6 +10,9 @@ use crate::models::radarr_models::{ IndexerSettings, MinimumAvailability, Monitor, Movie, MovieHistoryItem, QueueEvent, Release, ReleaseField, RootFolder, Task, }; +use crate::models::servarr_data::radarr::modals::{ + AddMovieModal, EditCollectionModal, EditMovieModal, +}; use crate::models::{ BlockSelectionState, HorizontallyScrollableText, Route, ScrollableText, StatefulList, StatefulTable, TabRoute, TabState, @@ -17,7 +20,7 @@ use crate::models::{ use crate::network::radarr_network::RadarrEvent; use bimap::BiMap; use chrono::{DateTime, Utc}; -use strum::{EnumIter, IntoEnumIterator}; +use strum::EnumIter; #[cfg(test)] #[path = "radarr_data_tests.rs"] @@ -67,6 +70,9 @@ pub struct RadarrData<'a> { pub movie_info_tabs: TabState, pub search: HorizontallyScrollableText, pub filter: HorizontallyScrollableText, + pub add_movie_modal: Option, + pub edit_movie_modal: Option, + pub edit_collection_modal: Option, pub edit_path: HorizontallyScrollableText, pub edit_tags: HorizontallyScrollableText, pub edit_monitored: Option, @@ -80,14 +86,6 @@ pub struct RadarrData<'a> { } impl<'a> RadarrData<'a> { - pub fn reset_movie_collection_table(&mut self) { - self.collection_movies = StatefulTable::default(); - } - - pub fn reset_log_details_list(&mut self) { - self.log_details = StatefulList::default(); - } - pub fn reset_delete_movie_preferences(&mut self) { self.delete_movie_files = false; self.add_list_exclusion = false; @@ -109,14 +107,6 @@ impl<'a> RadarrData<'a> { self.filtered_collections = StatefulTable::default(); } - pub fn reset_add_edit_media_fields(&mut self) { - self.edit_monitored = None; - self.edit_search_on_add = None; - self.edit_path = HorizontallyScrollableText::default(); - self.edit_tags = HorizontallyScrollableText::default(); - self.reset_preferences_selections(); - } - pub fn reset_movie_info_tabs(&mut self) { self.file_details = String::default(); self.audio_details = String::default(); @@ -130,126 +120,6 @@ impl<'a> RadarrData<'a> { self.sort_ascending = None; self.movie_info_tabs.index = 0; } - - pub fn reset_preferences_selections(&mut self) { - self.monitor_list = StatefulList::default(); - self.minimum_availability_list = StatefulList::default(); - self.quality_profile_list = StatefulList::default(); - self.root_folder_list = StatefulList::default(); - } - - pub fn populate_preferences_lists(&mut self) { - self.monitor_list.set_items(Vec::from_iter(Monitor::iter())); - self - .minimum_availability_list - .set_items(Vec::from_iter(MinimumAvailability::iter())); - let mut quality_profile_names: Vec = - self.quality_profile_map.right_values().cloned().collect(); - quality_profile_names.sort(); - self.quality_profile_list.set_items(quality_profile_names); - self - .root_folder_list - .set_items(self.root_folders.items.to_vec()); - } - - pub fn populate_edit_movie_fields(&mut self) { - self.populate_preferences_lists(); - let Movie { - path, - tags, - monitored, - minimum_availability, - quality_profile_id, - .. - } = if self.filtered_movies.items.is_empty() { - self.movies.current_selection() - } else { - self.filtered_movies.current_selection() - }; - - self.edit_path = path.clone().into(); - self.edit_tags = tags - .iter() - .map(|tag_id| { - self - .tags_map - .get_by_left(&tag_id.as_u64().unwrap()) - .unwrap() - .clone() - }) - .collect::>() - .join(", ") - .into(); - self.edit_monitored = Some(*monitored); - - let minimum_availability_index = self - .minimum_availability_list - .items - .iter() - .position(|ma| ma == minimum_availability); - self - .minimum_availability_list - .state - .select(minimum_availability_index); - - let quality_profile_name = self - .quality_profile_map - .get_by_left(&quality_profile_id.as_u64().unwrap()) - .unwrap(); - let quality_profile_index = self - .quality_profile_list - .items - .iter() - .position(|profile| profile == quality_profile_name); - self - .quality_profile_list - .state - .select(quality_profile_index); - } - - pub fn populate_edit_collection_fields(&mut self) { - self.populate_preferences_lists(); - let Collection { - root_folder_path, - monitored, - search_on_add, - minimum_availability, - quality_profile_id, - .. - } = if self.filtered_collections.items.is_empty() { - self.collections.current_selection() - } else { - self.filtered_collections.current_selection() - }; - - self.edit_path = root_folder_path.clone().unwrap_or_default().into(); - self.edit_monitored = Some(*monitored); - self.edit_search_on_add = Some(*search_on_add); - - let minimum_availability_index = self - .minimum_availability_list - .items - .iter() - .position(|ma| ma == minimum_availability); - self - .minimum_availability_list - .state - .select(minimum_availability_index); - - let quality_profile_name = self - .quality_profile_map - .get_by_left(&quality_profile_id.as_u64().unwrap()) - .unwrap(); - let quality_profile_index = self - .quality_profile_list - .items - .iter() - .position(|profile| profile == quality_profile_name); - self - .quality_profile_list - .state - .select(quality_profile_index); - } } impl<'a> Default for RadarrData<'a> { @@ -292,6 +162,9 @@ impl<'a> Default for RadarrData<'a> { prompt_confirm_action: None, search: HorizontallyScrollableText::default(), filter: HorizontallyScrollableText::default(), + add_movie_modal: None, + edit_movie_modal: None, + edit_collection_modal: None, edit_path: HorizontallyScrollableText::default(), edit_tags: HorizontallyScrollableText::default(), edit_monitored: None, @@ -623,3 +496,15 @@ impl From<(ActiveRadarrBlock, Option)> for Route { Route::Radarr(value.0, value.1) } } + +pub struct EditIndexerSettings { + pub allow_hardcoded_subs: bool, + pub availability_delay: HorizontallyScrollableText, + pub id: HorizontallyScrollableText, + pub maximum_size: HorizontallyScrollableText, + pub minimum_age: HorizontallyScrollableText, + pub prefer_indexer_flags: bool, + pub retention: HorizontallyScrollableText, + pub rss_sync_interval: HorizontallyScrollableText, + pub whitelisted_hardcoded_subs: HorizontallyScrollableText, +} diff --git a/src/models/servarr_data/radarr_data_tests.rs b/src/models/servarr_data/radarr/radarr_data_tests.rs similarity index 78% rename from src/models/servarr_data/radarr_data_tests.rs rename to src/models/servarr_data/radarr/radarr_data_tests.rs index 57eff39..35d3eab 100644 --- a/src/models/servarr_data/radarr_data_tests.rs +++ b/src/models/servarr_data/radarr/radarr_data_tests.rs @@ -1,12 +1,9 @@ #[cfg(test)] mod tests { mod radarr_data_tests { - use bimap::BiMap; + use chrono::{DateTime, Utc}; use pretty_assertions::{assert_eq, assert_str_eq}; - use rstest::rstest; - use serde_json::Number; - use strum::IntoEnumIterator; use crate::app::context_clues::build_context_clue_string; use crate::app::radarr::radarr_context_clues::{ @@ -15,18 +12,13 @@ mod tests { MANUAL_MOVIE_SEARCH_CONTEXT_CLUES, MOVIE_DETAILS_CONTEXT_CLUES, ROOT_FOLDERS_CONTEXT_CLUES, SYSTEM_CONTEXT_CLUES, }; - use crate::models::radarr_models::{ - Collection, MinimumAvailability, Monitor, Movie, RootFolder, - }; - use crate::models::servarr_data::radarr_data::radarr_test_utils::utils; - use crate::models::servarr_data::radarr_data::{ActiveRadarrBlock, RadarrData}; + + use crate::models::servarr_data::radarr::radarr_data::radarr_test_utils::utils; + use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, RadarrData}; use crate::models::Route; - use crate::models::StatefulTable; - use crate::models::{BlockSelectionState, HorizontallyScrollableText}; - use crate::{ - assert_edit_media_reset, assert_filter_reset, assert_movie_info_tabs_reset, - assert_preferences_selections_reset, assert_search_reset, - }; + + use crate::models::BlockSelectionState; + use crate::{assert_filter_reset, assert_movie_info_tabs_reset, assert_search_reset}; #[test] fn test_from_tuple_to_route_with_context() { @@ -42,24 +34,6 @@ mod tests { ); } - #[test] - fn test_reset_movie_collection_table() { - let mut radarr_data = utils::create_test_radarr_data(); - - radarr_data.reset_movie_collection_table(); - - assert!(radarr_data.collection_movies.items.is_empty()); - } - - #[test] - fn test_reset_log_details_list() { - let mut radarr_data = utils::create_test_radarr_data(); - - radarr_data.reset_log_details_list(); - - assert!(radarr_data.log_details.items.is_empty()); - } - #[test] fn test_reset_delete_movie_preferences() { let mut radarr_data = utils::create_test_radarr_data(); @@ -97,172 +71,6 @@ mod tests { assert_movie_info_tabs_reset!(radarr_data); } - #[test] - fn test_reset_add_edit_media_fields() { - let mut radarr_data = RadarrData { - edit_monitored: Some(true), - edit_search_on_add: Some(true), - edit_path: "test path".to_owned().into(), - edit_tags: "test tag".to_owned().into(), - ..RadarrData::default() - }; - - radarr_data.reset_add_edit_media_fields(); - - assert_edit_media_reset!(radarr_data); - } - - #[test] - fn test_reset_preferences_selections() { - let mut radarr_data = utils::create_test_radarr_data(); - - radarr_data.reset_preferences_selections(); - - assert_preferences_selections_reset!(radarr_data); - } - - #[test] - fn test_populate_preferences_lists() { - let root_folder = RootFolder { - id: Number::from(1), - path: "/nfs".to_owned(), - accessible: true, - free_space: Number::from(219902325555200u64), - unmapped_folders: None, - }; - let mut radarr_data = RadarrData { - quality_profile_map: BiMap::from_iter([ - (2222, "HD - 1080p".to_owned()), - (1111, "Any".to_owned()), - ]), - ..RadarrData::default() - }; - radarr_data - .root_folders - .set_items(vec![root_folder.clone()]); - - radarr_data.populate_preferences_lists(); - - assert_eq!( - radarr_data.monitor_list.items, - Vec::from_iter(Monitor::iter()) - ); - assert_eq!( - radarr_data.minimum_availability_list.items, - Vec::from_iter(MinimumAvailability::iter()) - ); - assert_eq!( - radarr_data.quality_profile_list.items, - vec!["Any".to_owned(), "HD - 1080p".to_owned()] - ); - assert_eq!(radarr_data.root_folder_list.items, vec![root_folder]); - } - - #[rstest] - fn test_populate_edit_movie_fields(#[values(true, false)] test_filtered_movies: bool) { - let mut radarr_data = RadarrData { - edit_path: HorizontallyScrollableText::default(), - edit_tags: HorizontallyScrollableText::default(), - edit_monitored: None, - quality_profile_map: BiMap::from_iter([ - (2222, "HD - 1080p".to_owned()), - (1111, "Any".to_owned()), - ]), - tags_map: BiMap::from_iter([(1, "usenet".to_owned()), (2, "test".to_owned())]), - filtered_movies: StatefulTable::default(), - ..utils::create_test_radarr_data() - }; - let movie = Movie { - path: "/nfs/movies/Test".to_owned(), - monitored: true, - quality_profile_id: Number::from(2222), - minimum_availability: MinimumAvailability::Released, - tags: vec![Number::from(1), Number::from(2)], - ..Movie::default() - }; - - if test_filtered_movies { - radarr_data.filtered_movies.set_items(vec![movie]); - } else { - radarr_data.movies.set_items(vec![movie]); - } - - radarr_data.populate_edit_movie_fields(); - - assert_eq!( - radarr_data.minimum_availability_list.items, - Vec::from_iter(MinimumAvailability::iter()) - ); - assert_eq!( - radarr_data.minimum_availability_list.current_selection(), - &MinimumAvailability::Released - ); - assert_eq!( - radarr_data.quality_profile_list.items, - vec!["Any".to_owned(), "HD - 1080p".to_owned()] - ); - assert_str_eq!( - radarr_data.quality_profile_list.current_selection(), - "HD - 1080p" - ); - assert_str_eq!(radarr_data.edit_path.text, "/nfs/movies/Test"); - assert_str_eq!(radarr_data.edit_tags.text, "usenet, test"); - assert_eq!(radarr_data.edit_monitored, Some(true)); - } - - #[rstest] - fn test_populate_edit_collection_fields( - #[values(true, false)] test_filtered_collections: bool, - ) { - let mut radarr_data = RadarrData { - edit_path: HorizontallyScrollableText::default(), - edit_monitored: None, - edit_search_on_add: None, - quality_profile_map: BiMap::from_iter([ - (2222, "HD - 1080p".to_owned()), - (1111, "Any".to_owned()), - ]), - filtered_collections: StatefulTable::default(), - ..utils::create_test_radarr_data() - }; - let collection = Collection { - root_folder_path: Some("/nfs/movies/Test".to_owned()), - monitored: true, - search_on_add: true, - quality_profile_id: Number::from(2222), - minimum_availability: MinimumAvailability::Released, - ..Collection::default() - }; - - if test_filtered_collections { - radarr_data.filtered_collections.set_items(vec![collection]); - } else { - radarr_data.collections.set_items(vec![collection]); - } - - radarr_data.populate_edit_collection_fields(); - - assert_eq!( - radarr_data.minimum_availability_list.items, - Vec::from_iter(MinimumAvailability::iter()) - ); - assert_eq!( - radarr_data.minimum_availability_list.current_selection(), - &MinimumAvailability::Released - ); - assert_eq!( - radarr_data.quality_profile_list.items, - vec!["Any".to_owned(), "HD - 1080p".to_owned()] - ); - assert_str_eq!( - radarr_data.quality_profile_list.current_selection(), - "HD - 1080p" - ); - assert_str_eq!(radarr_data.edit_path.text, "/nfs/movies/Test"); - assert_eq!(radarr_data.edit_monitored, Some(true)); - assert_eq!(radarr_data.edit_search_on_add, Some(true)); - } - #[test] fn test_radarr_data_defaults() { let radarr_data = RadarrData::default(); @@ -304,6 +112,9 @@ mod tests { assert!(radarr_data.prompt_confirm_action.is_none()); assert!(radarr_data.search.text.is_empty()); assert!(radarr_data.filter.text.is_empty()); + assert!(radarr_data.add_movie_modal.is_none()); + assert!(radarr_data.edit_movie_modal.is_none()); + assert!(radarr_data.edit_collection_modal.is_none()); assert!(radarr_data.edit_path.text.is_empty()); assert!(radarr_data.edit_tags.text.is_empty()); assert!(radarr_data.edit_monitored.is_none()); @@ -471,7 +282,7 @@ mod tests { mod active_radarr_block_tests { use pretty_assertions::assert_eq; - use crate::models::servarr_data::radarr_data::{ + use crate::models::servarr_data::radarr::radarr_data::{ ActiveRadarrBlock, ADD_MOVIE_BLOCKS, ADD_MOVIE_SELECTION_BLOCKS, COLLECTIONS_BLOCKS, COLLECTION_DETAILS_BLOCKS, DELETE_MOVIE_BLOCKS, DELETE_MOVIE_SELECTION_BLOCKS, DOWNLOADS_BLOCKS, EDIT_COLLECTION_BLOCKS, EDIT_COLLECTION_SELECTION_BLOCKS, diff --git a/src/models/servarr_data/radarr_test_utils.rs b/src/models/servarr_data/radarr/radarr_test_utils.rs similarity index 83% rename from src/models/servarr_data/radarr_test_utils.rs rename to src/models/servarr_data/radarr/radarr_test_utils.rs index ef5180f..19024bc 100644 --- a/src/models/servarr_data/radarr_test_utils.rs +++ b/src/models/servarr_data/radarr/radarr_test_utils.rs @@ -4,7 +4,7 @@ pub mod utils { AddMovieSearchResult, Collection, CollectionMovie, Credit, MinimumAvailability, Monitor, Movie, MovieHistoryItem, Release, ReleaseField, RootFolder, }; - use crate::models::servarr_data::radarr_data::RadarrData; + use crate::models::servarr_data::radarr::radarr_data::RadarrData; use crate::models::{HorizontallyScrollableText, ScrollableText}; pub fn create_test_radarr_data<'a>() -> RadarrData<'a> { @@ -79,16 +79,6 @@ pub mod utils { }; } - #[macro_export] - macro_rules! assert_edit_media_reset { - ($radarr_data:expr) => { - assert!($radarr_data.edit_monitored.is_none()); - assert!($radarr_data.edit_search_on_add.is_none()); - assert!($radarr_data.edit_path.text.is_empty()); - assert!($radarr_data.edit_tags.text.is_empty()); - }; - } - #[macro_export] macro_rules! assert_filter_reset { ($radarr_data:expr) => { @@ -115,14 +105,4 @@ pub mod utils { assert_eq!($radarr_data.movie_info_tabs.index, 0); }; } - - #[macro_export] - macro_rules! assert_preferences_selections_reset { - ($radarr_data:expr) => { - assert!($radarr_data.monitor_list.items.is_empty()); - assert!($radarr_data.minimum_availability_list.items.is_empty()); - assert!($radarr_data.quality_profile_list.items.is_empty()); - assert!($radarr_data.root_folder_list.items.is_empty()); - }; - } } diff --git a/src/network/radarr_network.rs b/src/network/radarr_network.rs index a523523..08a6041 100644 --- a/src/network/radarr_network.rs +++ b/src/network/radarr_network.rs @@ -13,7 +13,10 @@ use crate::models::radarr_models::{ IndexerSettings, LogResponse, Movie, MovieCommandBody, MovieHistoryItem, QualityProfile, QueueEvent, Release, ReleaseDownloadBody, RootFolder, SystemStatus, Tag, Task, Update, }; -use crate::models::servarr_data::radarr_data::ActiveRadarrBlock; +use crate::models::servarr_data::radarr::modals::{ + AddMovieModal, EditCollectionModal, EditMovieModal, +}; +use crate::models::servarr_data::radarr::radarr_data::ActiveRadarrBlock; use crate::models::{HorizontallyScrollableText, Route, Scrollable, ScrollableText}; use crate::network::{Network, NetworkEvent, RequestMethod, RequestProps}; use crate::utils::{convert_runtime, convert_to_gb}; @@ -151,55 +154,76 @@ impl<'a, 'b> Network<'a, 'b> { async fn add_movie(&mut self) { info!("Adding new movie to Radarr"); let body = { - let quality_profile_id = self.extract_quality_profile_id().await; - let tag_ids_vec = self.extract_and_add_tag_ids_vec().await; - let app = self.app.lock().await; - let root_folders = app.data.radarr_data.root_folders.items.to_vec(); - let (tmdb_id, title) = if let Route::Radarr(active_radarr_block, _) = app.get_current_route() + let tags = self + .app + .lock() + .await + .data + .radarr_data + .add_movie_modal + .as_ref() + .unwrap() + .tags + .text + .clone(); + let tag_ids_vec = self.extract_and_add_tag_ids_vec(tags).await; + let mut app = self.app.lock().await; + let AddMovieModal { + root_folder_list, + monitor_list, + minimum_availability_list, + quality_profile_list, + .. + } = app.data.radarr_data.add_movie_modal.as_ref().unwrap(); + let (tmdb_id, title) = if let Route::Radarr(active_radarr_block, _) = *app.get_current_route() { - if *active_radarr_block == ActiveRadarrBlock::CollectionDetails { - let CollectionMovie { tmdb_id, title, .. } = - app.data.radarr_data.collection_movies.current_selection(); + if active_radarr_block == ActiveRadarrBlock::CollectionDetails { + let CollectionMovie { tmdb_id, title, .. } = app + .data + .radarr_data + .collection_movies + .current_selection() + .clone(); (tmdb_id, title.text.clone()) } else { - let AddMovieSearchResult { tmdb_id, title, .. } = - app.data.radarr_data.add_searched_movies.current_selection(); + let AddMovieSearchResult { tmdb_id, title, .. } = app + .data + .radarr_data + .add_searched_movies + .current_selection() + .clone(); (tmdb_id, title.text.clone()) } } else { - let AddMovieSearchResult { tmdb_id, title, .. } = - app.data.radarr_data.add_searched_movies.current_selection(); + let AddMovieSearchResult { tmdb_id, title, .. } = app + .data + .radarr_data + .add_searched_movies + .current_selection() + .clone(); (tmdb_id, title.text.clone()) }; - - let RootFolder { path, .. } = root_folders + let quality_profile = quality_profile_list.current_selection(); + let quality_profile_id = *app + .data + .radarr_data + .quality_profile_map .iter() - .filter(|folder| folder.accessible) - .reduce(|a, b| { - if a.free_space.as_u64().unwrap() > b.free_space.as_u64().unwrap() { - a - } else { - b - } - }) + .filter(|(_, value)| *value == quality_profile) + .map(|(key, _)| key) + .next() .unwrap(); - let monitor = app - .data - .radarr_data - .monitor_list - .current_selection() - .to_string(); - let minimum_availability = app - .data - .radarr_data - .minimum_availability_list - .current_selection() - .to_string(); + + let path = root_folder_list.current_selection().path.clone(); + let monitor = monitor_list.current_selection().to_string(); + let minimum_availability = minimum_availability_list.current_selection().to_string(); + + app.data.radarr_data.add_movie_modal = None; AddMovieBody { tmdb_id: tmdb_id.as_u64().unwrap(), title, - root_folder_path: path.to_owned(), + root_folder_path: path, minimum_availability, monitored: true, quality_profile_id, @@ -462,21 +486,31 @@ impl<'a, 'b> Network<'a, 'b> { info!("Constructing edit collection body"); let body = { - let quality_profile_id = self.extract_quality_profile_id().await; let mut app = self.app.lock().await; let response = app.response.drain(..).collect::(); let mut detailed_collection_body: Value = serde_json::from_str(&response).unwrap(); - - let root_folder_path: String = app.data.radarr_data.edit_path.drain(); - - let monitored = app.data.radarr_data.edit_monitored.unwrap_or_default(); - let search_on_add = app.data.radarr_data.edit_search_on_add.unwrap_or_default(); - let minimum_availability = app + let EditCollectionModal { + path, + search_on_add, + minimum_availability_list, + monitored, + quality_profile_list, + } = app.data.radarr_data.edit_collection_modal.as_ref().unwrap(); + let quality_profile = quality_profile_list.current_selection(); + let quality_profile_id = *app .data .radarr_data - .minimum_availability_list - .current_selection() - .to_string(); + .quality_profile_map + .iter() + .filter(|(_, value)| *value == quality_profile) + .map(|(key, _)| key) + .next() + .unwrap(); + + let root_folder_path: String = path.text.clone(); + let monitored = monitored.unwrap_or_default(); + let search_on_add = search_on_add.unwrap_or_default(); + let minimum_availability = minimum_availability_list.current_selection().to_string(); *detailed_collection_body.get_mut("monitored").unwrap() = json!(monitored); *detailed_collection_body @@ -488,6 +522,8 @@ impl<'a, 'b> Network<'a, 'b> { *detailed_collection_body.get_mut("rootFolderPath").unwrap() = json!(root_folder_path); *detailed_collection_body.get_mut("searchOnAdd").unwrap() = json!(search_on_add); + app.data.radarr_data.edit_collection_modal = None; + detailed_collection_body }; @@ -533,28 +569,50 @@ impl<'a, 'b> Network<'a, 'b> { info!("Constructing edit movie body"); let body = { - let quality_profile_id = self.extract_quality_profile_id().await; - let tag_ids_vec = self.extract_and_add_tag_ids_vec().await; + let tags = self + .app + .lock() + .await + .data + .radarr_data + .edit_movie_modal + .as_ref() + .unwrap() + .tags + .text + .clone(); + let tag_ids_vec = self.extract_and_add_tag_ids_vec(tags).await; let mut app = self.app.lock().await; let response = app.response.drain(..).collect::(); let mut detailed_movie_body: Value = serde_json::from_str(&response).unwrap(); - let path: String = app.data.radarr_data.edit_path.drain(); - - let monitored = app.data.radarr_data.edit_monitored.unwrap_or_default(); - let minimum_availability = app + let EditMovieModal { + monitored, + path, + minimum_availability_list, + quality_profile_list, + .. + } = app.data.radarr_data.edit_movie_modal.as_ref().unwrap(); + let quality_profile = quality_profile_list.current_selection(); + let quality_profile_id = *app .data .radarr_data - .minimum_availability_list - .current_selection() - .to_string(); + .quality_profile_map + .iter() + .filter(|(_, value)| *value == quality_profile) + .map(|(key, _)| key) + .next() + .unwrap(); - *detailed_movie_body.get_mut("monitored").unwrap() = json!(monitored); - *detailed_movie_body.get_mut("minimumAvailability").unwrap() = json!(minimum_availability); + *detailed_movie_body.get_mut("monitored").unwrap() = json!(monitored.unwrap_or_default()); + *detailed_movie_body.get_mut("minimumAvailability").unwrap() = + json!(minimum_availability_list.current_selection().to_string()); *detailed_movie_body.get_mut("qualityProfileId").unwrap() = json!(quality_profile_id); - *detailed_movie_body.get_mut("path").unwrap() = json!(path); + *detailed_movie_body.get_mut("path").unwrap() = json!(path.text.clone()); *detailed_movie_body.get_mut("tags").unwrap() = json!(tag_ids_vec); + app.data.radarr_data.edit_movie_modal = None; + detailed_movie_body }; @@ -1408,27 +1466,8 @@ impl<'a, 'b> Network<'a, 'b> { } } - async fn extract_quality_profile_id(&mut self) -> u64 { - let app = self.app.lock().await; - let quality_profile = app - .data - .radarr_data - .quality_profile_list - .current_selection(); - *app - .data - .radarr_data - .quality_profile_map - .iter() - .filter(|(_, value)| *value == quality_profile) - .map(|(key, _)| key) - .next() - .unwrap() - } - - async fn extract_and_add_tag_ids_vec(&mut self) -> Vec { + async fn extract_and_add_tag_ids_vec(&mut self, edit_tags: String) -> Vec { let tags_map = self.app.lock().await.data.radarr_data.tags_map.clone(); - let edit_tags = self.app.lock().await.data.radarr_data.edit_tags.drain(); let tags = edit_tags.clone(); let missing_tags_vec = edit_tags .split(',') diff --git a/src/network/radarr_network_tests.rs b/src/network/radarr_network_tests.rs index 33b298e..3251cb9 100644 --- a/src/network/radarr_network_tests.rs +++ b/src/network/radarr_network_tests.rs @@ -16,7 +16,7 @@ mod test { CollectionMovie, IndexerField, IndexerSelectOption, Language, MediaInfo, MinimumAvailability, Monitor, MovieFile, Quality, QualityWrapper, Rating, RatingsList, }; - use crate::models::servarr_data::radarr_data::ActiveRadarrBlock; + use crate::models::servarr_data::radarr::radarr_data::ActiveRadarrBlock; use crate::models::HorizontallyScrollableText; use crate::App; @@ -1481,7 +1481,7 @@ mod test { Some(json!({ "tmdbId": 1234, "title": "Test", - "rootFolderPath": "/nfs", + "rootFolderPath": "/nfs2", "minimumAvailability": "announced", "monitored": true, "qualityProfileId": 2222, @@ -1498,7 +1498,11 @@ mod test { { let mut app = app_arc.lock().await; - app.data.radarr_data.root_folders.set_items(vec![ + let mut add_movie_modal = AddMovieModal { + tags: "usenet, testing".into(), + ..AddMovieModal::default() + }; + add_movie_modal.root_folder_list.set_items(vec![ RootFolder { id: Number::from(1), path: "/nfs".to_owned(), @@ -1514,26 +1518,21 @@ mod test { unmapped_folders: None, }, ]); + add_movie_modal.root_folder_list.state.select(Some(1)); + add_movie_modal + .quality_profile_list + .set_items(vec!["HD - 1080p".to_owned()]); + add_movie_modal + .monitor_list + .set_items(Vec::from_iter(Monitor::iter())); + add_movie_modal + .minimum_availability_list + .set_items(Vec::from_iter(MinimumAvailability::iter())); + app.data.radarr_data.add_movie_modal = Some(add_movie_modal); app.data.radarr_data.quality_profile_map = BiMap::from_iter([(2222, "HD - 1080p".to_owned())]); app.data.radarr_data.tags_map = BiMap::from_iter([(1, "usenet".to_owned()), (2, "testing".to_owned())]); - app.data.radarr_data.edit_tags = "usenet, testing".to_owned().into(); - app - .data - .radarr_data - .quality_profile_list - .set_items(vec!["HD - 1080p".to_owned()]); - app - .data - .radarr_data - .monitor_list - .set_items(Vec::from_iter(Monitor::iter())); - app - .data - .radarr_data - .minimum_availability_list - .set_items(Vec::from_iter(MinimumAvailability::iter())); if movie_details_context { app .data @@ -1554,6 +1553,13 @@ mod test { network.handle_radarr_event(RadarrEvent::AddMovie).await; async_server.assert_async().await; + assert!(app_arc + .lock() + .await + .data + .radarr_data + .add_movie_modal + .is_none()); } #[tokio::test] @@ -1617,19 +1623,19 @@ mod test { let mut app = app_arc.lock().await; app.data.radarr_data.tags_map = BiMap::from_iter([(1, "usenet".to_owned()), (2, "testing".to_owned())]); - app.data.radarr_data.edit_tags = "usenet, testing".to_owned().into(); - app.data.radarr_data.edit_path = "/nfs/Test Path".to_owned().into(); - app.data.radarr_data.edit_monitored = Some(false); - app - .data - .radarr_data + let mut edit_movie = EditMovieModal { + tags: "usenet, testing".to_owned().into(), + path: "/nfs/Test Path".to_owned().into(), + monitored: Some(false), + ..EditMovieModal::default() + }; + edit_movie .quality_profile_list .set_items(vec!["Any".to_owned(), "HD - 1080p".to_owned()]); - app - .data - .radarr_data + edit_movie .minimum_availability_list .set_items(Vec::from_iter(MinimumAvailability::iter())); + app.data.radarr_data.edit_movie_modal = Some(edit_movie); app.data.radarr_data.movies.set_items(vec![Movie { monitored: false, ..movie() @@ -1646,8 +1652,7 @@ mod test { let app = app_arc.lock().await; assert!(app.response.is_empty()); - assert!(app.data.radarr_data.edit_path.text.is_empty()); - assert!(app.data.radarr_data.edit_tags.text.is_empty()); + assert!(app.data.radarr_data.edit_movie_modal.is_none()); assert!(app.data.radarr_data.movie_details.items.is_empty()); } @@ -1711,19 +1716,19 @@ mod test { .await; { let mut app = app_arc.lock().await; - app.data.radarr_data.edit_path = "/nfs/Test Path".to_owned().into(); - app.data.radarr_data.edit_monitored = Some(false); - app.data.radarr_data.edit_search_on_add = Some(false); - app - .data - .radarr_data + let mut edit_collection_modal = EditCollectionModal { + path: "/nfs/Test Path".into(), + monitored: Some(false), + search_on_add: Some(false), + ..EditCollectionModal::default() + }; + edit_collection_modal .quality_profile_list .set_items(vec!["Any".to_owned(), "HD - 1080p".to_owned()]); - app - .data - .radarr_data + edit_collection_modal .minimum_availability_list .set_items(Vec::from_iter(MinimumAvailability::iter())); + app.data.radarr_data.edit_collection_modal = Some(edit_collection_modal); app.data.radarr_data.collections.set_items(vec![Collection { monitored: false, search_on_add: false, @@ -1743,7 +1748,7 @@ mod test { let app = app_arc.lock().await; assert!(app.response.is_empty()); - assert!(app.data.radarr_data.edit_path.text.is_empty()); + assert!(app.data.radarr_data.edit_collection_modal.is_none()); assert!(app.data.radarr_data.movie_details.items.is_empty()); } @@ -1775,30 +1780,12 @@ mod test { async_server.assert_async().await; } - #[tokio::test] - async fn test_extract_quality_profile_id() { - let app_arc = Arc::new(Mutex::new(App::default())); - { - let mut app = app_arc.lock().await; - app - .data - .radarr_data - .quality_profile_list - .set_items(vec!["Any".to_owned(), "HD - 1080p".to_owned()]); - app.data.radarr_data.quality_profile_map = - BiMap::from_iter([(1, "Any".to_owned()), (2, "HD - 1080p".to_owned())]); - } - let mut network = Network::new(&app_arc, CancellationToken::new()); - - assert_eq!(network.extract_quality_profile_id().await, 1); - } - #[tokio::test] async fn test_extract_and_add_tag_ids_vec() { let app_arc = Arc::new(Mutex::new(App::default())); + let tags = " test,hi ,, usenet ".to_owned(); { let mut app = app_arc.lock().await; - app.data.radarr_data.edit_tags = " test,hi ,, usenet ".to_owned().into(); app.data.radarr_data.tags_map = BiMap::from_iter([ (1, "usenet".to_owned()), (2, "test".to_owned()), @@ -1807,7 +1794,10 @@ mod test { } let mut network = Network::new(&app_arc, CancellationToken::new()); - assert_eq!(network.extract_and_add_tag_ids_vec().await, vec![2, 3, 1]); + assert_eq!( + network.extract_and_add_tag_ids_vec(tags).await, + vec![2, 3, 1] + ); } #[tokio::test] @@ -1819,15 +1809,19 @@ mod test { RadarrEvent::GetTags.resource(), ) .await; + let tags = "usenet, test, testing".to_owned(); { let mut app = app_arc.lock().await; - app.data.radarr_data.edit_tags = "usenet, test, testing".to_owned().into(); + app.data.radarr_data.edit_movie_modal = Some(EditMovieModal { + tags: tags.clone().into(), + ..EditMovieModal::default() + }); app.data.radarr_data.tags_map = BiMap::from_iter([(1, "usenet".to_owned()), (2, "test".to_owned())]); } let mut network = Network::new(&app_arc, CancellationToken::new()); - let tag_ids_vec = network.extract_and_add_tag_ids_vec().await; + let tag_ids_vec = network.extract_and_add_tag_ids_vec(tags).await; async_server.assert_async().await; assert_eq!(tag_ids_vec, vec![1, 2, 3]); diff --git a/src/ui/mod.rs b/src/ui/mod.rs index e387eaa..c6f0c6d 100644 --- a/src/ui/mod.rs +++ b/src/ui/mod.rs @@ -497,7 +497,11 @@ pub fn draw_checkbox_with_label( is_selected: bool, ) { let horizontal_chunks = horizontal_chunks( - vec![Constraint::Percentage(50), Constraint::Percentage(50)], + vec![ + Constraint::Percentage(48), + Constraint::Percentage(48), + Constraint::Percentage(4), + ], area, ); @@ -528,7 +532,11 @@ pub fn draw_button_with_icon( let icon_paragraph = layout_button_paragraph_borderless(is_selected, icon, Alignment::Right); let horizontal_chunks = horizontal_chunks_with_margin( - vec![Constraint::Percentage(50), Constraint::Percentage(50)], + vec![ + Constraint::Percentage(50), + Constraint::Percentage(49), + Constraint::Percentage(1), + ], area, 1, ); @@ -549,7 +557,11 @@ pub fn draw_drop_down_menu_button( is_selected: bool, ) { let horizontal_chunks = horizontal_chunks( - vec![Constraint::Percentage(50), Constraint::Percentage(50)], + vec![ + Constraint::Percentage(48), + Constraint::Percentage(48), + Constraint::Percentage(4), + ], area, ); @@ -679,7 +691,11 @@ pub fn draw_text_box_with_label( should_show_cursor: bool, ) { let horizontal_chunks = horizontal_chunks( - vec![Constraint::Percentage(50), Constraint::Percentage(50)], + vec![ + Constraint::Percentage(48), + Constraint::Percentage(48), + Constraint::Percentage(4), + ], area, ); diff --git a/src/ui/radarr_ui/collections/collection_details_ui.rs b/src/ui/radarr_ui/collections/collection_details_ui.rs index 97f2d90..e09ca9b 100644 --- a/src/ui/radarr_ui/collections/collection_details_ui.rs +++ b/src/ui/radarr_ui/collections/collection_details_ui.rs @@ -8,7 +8,9 @@ use crate::app::context_clues::{build_context_clue_string, BARE_POPUP_CONTEXT_CL use crate::app::radarr::radarr_context_clues::COLLECTION_DETAILS_CONTEXT_CLUES; use crate::app::App; use crate::models::radarr_models::CollectionMovie; -use crate::models::servarr_data::radarr_data::{ActiveRadarrBlock, COLLECTION_DETAILS_BLOCKS}; +use crate::models::servarr_data::radarr::radarr_data::{ + ActiveRadarrBlock, COLLECTION_DETAILS_BLOCKS, +}; use crate::models::Route; use crate::ui::radarr_ui::collections::draw_collections; use crate::ui::utils::{ diff --git a/src/ui/radarr_ui/collections/collection_details_ui_tests.rs b/src/ui/radarr_ui/collections/collection_details_ui_tests.rs index 48a0dca..440fdf8 100644 --- a/src/ui/radarr_ui/collections/collection_details_ui_tests.rs +++ b/src/ui/radarr_ui/collections/collection_details_ui_tests.rs @@ -2,7 +2,9 @@ mod tests { use strum::IntoEnumIterator; - use crate::models::servarr_data::radarr_data::{ActiveRadarrBlock, COLLECTION_DETAILS_BLOCKS}; + use crate::models::servarr_data::radarr::radarr_data::{ + ActiveRadarrBlock, COLLECTION_DETAILS_BLOCKS, + }; use crate::ui::radarr_ui::collections::collection_details_ui::CollectionDetailsUi; use crate::ui::DrawUi; diff --git a/src/ui/radarr_ui/collections/collections_ui_tests.rs b/src/ui/radarr_ui/collections/collections_ui_tests.rs index 94a7996..1f66677 100644 --- a/src/ui/radarr_ui/collections/collections_ui_tests.rs +++ b/src/ui/radarr_ui/collections/collections_ui_tests.rs @@ -2,7 +2,7 @@ mod tests { use strum::IntoEnumIterator; - use crate::models::servarr_data::radarr_data::{ + use crate::models::servarr_data::radarr::radarr_data::{ ActiveRadarrBlock, COLLECTIONS_BLOCKS, COLLECTION_DETAILS_BLOCKS, EDIT_COLLECTION_BLOCKS, }; use crate::ui::radarr_ui::collections::CollectionsUi; diff --git a/src/ui/radarr_ui/collections/edit_collection_ui.rs b/src/ui/radarr_ui/collections/edit_collection_ui.rs index ab7fe7c..3d7aca6 100644 --- a/src/ui/radarr_ui/collections/edit_collection_ui.rs +++ b/src/ui/radarr_ui/collections/edit_collection_ui.rs @@ -1,24 +1,23 @@ use tui::backend::Backend; use tui::layout::{Constraint, Rect}; +use tui::widgets::ListItem; use tui::Frame; use crate::app::App; -use crate::models::servarr_data::radarr_data::{ +use crate::models::servarr_data::radarr::modals::EditCollectionModal; +use crate::models::servarr_data::radarr::radarr_data::{ ActiveRadarrBlock, COLLECTION_DETAILS_BLOCKS, EDIT_COLLECTION_BLOCKS, }; use crate::models::Route; use crate::ui::radarr_ui::collections::collection_details_ui::CollectionDetailsUi; use crate::ui::radarr_ui::collections::draw_collections; -use crate::ui::radarr_ui::{ - draw_select_minimum_availability_popup, draw_select_quality_profile_popup, -}; use crate::ui::utils::{ horizontal_chunks, layout_paragraph_borderless, title_block_centered, vertical_chunks_with_margin, }; use crate::ui::{ draw_button, draw_checkbox_with_label, draw_drop_down_menu_button, draw_drop_down_popup, draw_large_popup_over_background_fn_with_ui, draw_medium_popup_over, draw_popup, - draw_text_box_with_label, DrawUi, + draw_selectable_list, draw_text_box_with_label, DrawUi, }; #[cfg(test)] @@ -46,7 +45,7 @@ impl DrawUi for EditCollectionUi { app, prompt_area, draw_edit_collection_confirmation_prompt, - draw_select_minimum_availability_popup, + draw_edit_collection_select_minimum_availability_popup, ); } ActiveRadarrBlock::EditCollectionSelectQualityProfile => { @@ -55,7 +54,7 @@ impl DrawUi for EditCollectionUi { app, prompt_area, draw_edit_collection_confirmation_prompt, - draw_select_quality_profile_popup, + draw_edit_collection_select_quality_profile_popup, ); } ActiveRadarrBlock::EditCollectionPrompt @@ -141,17 +140,16 @@ fn draw_edit_collection_confirmation_prompt( let yes_no_value = app.data.radarr_data.prompt_confirm; let selected_block = app.data.radarr_data.selected_block.get_active_block(); let highlight_yes_no = selected_block == &ActiveRadarrBlock::EditCollectionConfirmPrompt; + let EditCollectionModal { + minimum_availability_list, + quality_profile_list, + monitored, + search_on_add, + path, + } = app.data.radarr_data.edit_collection_modal.as_ref().unwrap(); - let selected_minimum_availability = app - .data - .radarr_data - .minimum_availability_list - .current_selection(); - let selected_quality_profile = app - .data - .radarr_data - .quality_profile_list - .current_selection(); + let selected_minimum_availability = minimum_availability_list.current_selection(); + let selected_quality_profile = quality_profile_list.current_selection(); f.render_widget(title_block_centered(&title), prompt_area); @@ -182,7 +180,7 @@ fn draw_edit_collection_confirmation_prompt( f, chunks[1], "Monitored", - app.data.radarr_data.edit_monitored.unwrap_or_default(), + monitored.unwrap_or_default(), selected_block == &ActiveRadarrBlock::EditCollectionToggleMonitored, ); @@ -206,8 +204,8 @@ fn draw_edit_collection_confirmation_prompt( f, chunks[4], "Root Folder", - &app.data.radarr_data.edit_path.text, - *app.data.radarr_data.edit_path.offset.borrow(), + &path.text, + *path.offset.borrow(), selected_block == &ActiveRadarrBlock::EditCollectionRootFolderPathInput, active_radarr_block == ActiveRadarrBlock::EditCollectionRootFolderPathInput, ); @@ -217,7 +215,7 @@ fn draw_edit_collection_confirmation_prompt( f, chunks[5], "Search on Add", - app.data.radarr_data.edit_search_on_add.unwrap_or_default(), + search_on_add.unwrap_or_default(), selected_block == &ActiveRadarrBlock::EditCollectionToggleSearchOnAdd, ); @@ -234,3 +232,41 @@ fn draw_edit_collection_confirmation_prompt( !yes_no_value && highlight_yes_no, ); } + +fn draw_edit_collection_select_minimum_availability_popup( + f: &mut Frame<'_, B>, + app: &mut App<'_>, + popup_area: Rect, +) { + draw_selectable_list( + f, + popup_area, + &mut app + .data + .radarr_data + .edit_collection_modal + .as_mut() + .unwrap() + .minimum_availability_list, + |minimum_availability| ListItem::new(minimum_availability.to_display_str().to_owned()), + ); +} + +fn draw_edit_collection_select_quality_profile_popup( + f: &mut Frame<'_, B>, + app: &mut App<'_>, + popup_area: Rect, +) { + draw_selectable_list( + f, + popup_area, + &mut app + .data + .radarr_data + .edit_collection_modal + .as_mut() + .unwrap() + .quality_profile_list, + |quality_profile| ListItem::new(quality_profile.clone()), + ); +} diff --git a/src/ui/radarr_ui/collections/edit_collection_ui_tests.rs b/src/ui/radarr_ui/collections/edit_collection_ui_tests.rs index 32c9ec7..be9fbc4 100644 --- a/src/ui/radarr_ui/collections/edit_collection_ui_tests.rs +++ b/src/ui/radarr_ui/collections/edit_collection_ui_tests.rs @@ -2,7 +2,9 @@ mod tests { use strum::IntoEnumIterator; - use crate::models::servarr_data::radarr_data::{ActiveRadarrBlock, EDIT_COLLECTION_BLOCKS}; + use crate::models::servarr_data::radarr::radarr_data::{ + ActiveRadarrBlock, EDIT_COLLECTION_BLOCKS, + }; use crate::ui::radarr_ui::collections::edit_collection_ui::EditCollectionUi; use crate::ui::DrawUi; diff --git a/src/ui/radarr_ui/collections/mod.rs b/src/ui/radarr_ui/collections/mod.rs index ee7e39e..b8dc22d 100644 --- a/src/ui/radarr_ui/collections/mod.rs +++ b/src/ui/radarr_ui/collections/mod.rs @@ -7,7 +7,7 @@ pub(super) use collection_details_ui::draw_collection_details; use crate::app::App; use crate::models::radarr_models::Collection; -use crate::models::servarr_data::radarr_data::{ActiveRadarrBlock, COLLECTIONS_BLOCKS}; +use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, COLLECTIONS_BLOCKS}; use crate::models::Route; use crate::ui::radarr_ui::collections::collection_details_ui::CollectionDetailsUi; use crate::ui::radarr_ui::collections::edit_collection_ui::EditCollectionUi; diff --git a/src/ui/radarr_ui/downloads/downloads_ui_tests.rs b/src/ui/radarr_ui/downloads/downloads_ui_tests.rs index 596a596..c6b6bc0 100644 --- a/src/ui/radarr_ui/downloads/downloads_ui_tests.rs +++ b/src/ui/radarr_ui/downloads/downloads_ui_tests.rs @@ -2,7 +2,7 @@ mod tests { use strum::IntoEnumIterator; - use crate::models::servarr_data::radarr_data::{ActiveRadarrBlock, DOWNLOADS_BLOCKS}; + use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, DOWNLOADS_BLOCKS}; use crate::ui::radarr_ui::downloads::DownloadsUi; use crate::ui::DrawUi; diff --git a/src/ui/radarr_ui/downloads/mod.rs b/src/ui/radarr_ui/downloads/mod.rs index ddcf209..b2ca8b6 100644 --- a/src/ui/radarr_ui/downloads/mod.rs +++ b/src/ui/radarr_ui/downloads/mod.rs @@ -5,7 +5,7 @@ use tui::Frame; use crate::app::App; use crate::models::radarr_models::DownloadRecord; -use crate::models::servarr_data::radarr_data::{ActiveRadarrBlock, DOWNLOADS_BLOCKS}; +use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, DOWNLOADS_BLOCKS}; use crate::models::{HorizontallyScrollableText, Route}; use crate::ui::utils::{get_width_from_percentage, layout_block_top_border, style_primary}; use crate::ui::{draw_prompt_box, draw_prompt_popup_over, draw_table, DrawUi, TableProps}; diff --git a/src/ui/radarr_ui/indexers/indexer_settings_ui.rs b/src/ui/radarr_ui/indexers/indexer_settings_ui.rs index 774ea38..b9a37c3 100644 --- a/src/ui/radarr_ui/indexers/indexer_settings_ui.rs +++ b/src/ui/radarr_ui/indexers/indexer_settings_ui.rs @@ -1,11 +1,21 @@ +use std::iter; use tui::backend::Backend; -use tui::layout::Rect; +use tui::layout::{Constraint, Rect}; use tui::Frame; use crate::app::App; -use crate::models::servarr_data::radarr_data::INDEXER_SETTINGS_BLOCKS; +use crate::models::servarr_data::radarr::radarr_data::{ + ActiveRadarrBlock, INDEXER_SETTINGS_BLOCKS, +}; use crate::models::Route; -use crate::ui::DrawUi; +use crate::ui::radarr_ui::indexers::draw_indexers; +use crate::ui::utils::{ + horizontal_chunks, horizontal_chunks_with_margin, title_block_centered, vertical_chunks, + vertical_chunks_with_margin, +}; +use crate::ui::{ + draw_button, draw_checkbox_with_label, draw_popup_over, draw_text_box_with_label, loading, DrawUi, +}; #[cfg(test)] #[path = "indexer_settings_ui_tests.rs"] @@ -22,5 +32,159 @@ impl DrawUi for IndexerSettingsUi { false } - fn draw(_f: &mut Frame<'_, B>, _app: &mut App<'_>, _content_rect: Rect) {} + fn draw(f: &mut Frame<'_, B>, app: &mut App<'_>, content_rect: Rect) { + draw_popup_over( + f, + app, + content_rect, + draw_indexers, + draw_edit_indexer_settings_prompt, + 60, + 40, + ); + } +} + +fn draw_edit_indexer_settings_prompt( + f: &mut Frame<'_, B>, + app: &mut App<'_>, + prompt_area: Rect, +) { + let block = title_block_centered("Configure All Indexer Settings"); + let yes_no_value = app.data.radarr_data.prompt_confirm; + let selected_block = app.data.radarr_data.selected_block.get_active_block(); + let highlight_yes_no = selected_block == &ActiveRadarrBlock::IndexerSettingsConfirmPrompt; + let indexer_settings_option = &app.data.radarr_data.indexer_settings; + + if indexer_settings_option.is_some() { + let indexer_settings = indexer_settings_option.as_ref().unwrap(); + f.render_widget(block, prompt_area); + + let chunks = vertical_chunks_with_margin( + vec![Constraint::Min(0), Constraint::Length(3)], + prompt_area, + 1, + ); + + let split_chunks = horizontal_chunks_with_margin( + vec![Constraint::Ratio(1, 2), Constraint::Ratio(1, 2)], + chunks[0], + 1, + ); + + let left_chunks = vertical_chunks( + vec![ + Constraint::Length(3), + Constraint::Length(3), + Constraint::Length(3), + Constraint::Length(3), + Constraint::Min(0), + ], + split_chunks[0], + ); + let right_chunks = vertical_chunks( + vec![ + Constraint::Length(3), + Constraint::Length(3), + Constraint::Length(3), + Constraint::Length(3), + Constraint::Min(0), + ], + split_chunks[1], + ); + + if let Route::Radarr(active_radarr_block, _) = *app.get_current_route() { + draw_text_box_with_label( + f, + left_chunks[0], + "Minimum Age", + &indexer_settings.minimum_age.to_string(), + 0, + selected_block == &ActiveRadarrBlock::IndexerSettingsMinimumAgeInput, + active_radarr_block == ActiveRadarrBlock::IndexerSettingsMinimumAgeInput, + ); + draw_text_box_with_label( + f, + left_chunks[1], + "Retention", + &indexer_settings.retention.to_string(), + 0, + selected_block == &ActiveRadarrBlock::IndexerSettingsRetentionInput, + active_radarr_block == ActiveRadarrBlock::IndexerSettingsRetentionInput, + ); + draw_text_box_with_label( + f, + left_chunks[2], + "Maximum Size", + &indexer_settings.maximum_size.to_string(), + 0, + selected_block == &ActiveRadarrBlock::IndexerSettingsMaximumSizeInput, + active_radarr_block == ActiveRadarrBlock::IndexerSettingsMaximumSizeInput, + ); + draw_text_box_with_label( + f, + right_chunks[0], + "Availability Delay", + &indexer_settings.availability_delay.to_string(), + 0, + selected_block == &ActiveRadarrBlock::IndexerSettingsAvailabilityDelayInput, + active_radarr_block == ActiveRadarrBlock::IndexerSettingsAvailabilityDelayInput, + ); + draw_text_box_with_label( + f, + right_chunks[1], + "RSS Sync Interval", + &indexer_settings.rss_sync_interval.to_string(), + 0, + selected_block == &ActiveRadarrBlock::IndexerSettingsRssSyncIntervalInput, + active_radarr_block == ActiveRadarrBlock::IndexerSettingsRssSyncIntervalInput, + ); + draw_text_box_with_label( + f, + right_chunks[2], + "Whitelisted Subtitle Tags", + &indexer_settings.whitelisted_hardcoded_subs.to_string(), + 0, + selected_block == &ActiveRadarrBlock::IndexerSettingsWhitelistedSubtitleTagsInput, + active_radarr_block == ActiveRadarrBlock::IndexerSettingsWhitelistedSubtitleTagsInput, + ); + } + + draw_checkbox_with_label( + f, + left_chunks[3], + "Prefer Indexer Flags", + indexer_settings.prefer_indexer_flags, + selected_block == &ActiveRadarrBlock::IndexerSettingsTogglePreferIndexerFlags, + ); + + draw_checkbox_with_label( + f, + right_chunks[3], + "Allow Hardcoded Subs", + indexer_settings.allow_hardcoded_subs, + selected_block == &ActiveRadarrBlock::IndexerSettingsToggleAllowHardcodedSubs, + ); + + let button_chunks = horizontal_chunks( + iter::repeat(Constraint::Ratio(1, 4)).take(4).collect(), + // vec![Constraint::Percentage(50), Constraint::Percentage(50)], + chunks[1], + ); + + draw_button( + f, + button_chunks[1], + "Save", + yes_no_value && highlight_yes_no, + ); + draw_button( + f, + button_chunks[2], + "Cancel", + !yes_no_value && highlight_yes_no, + ); + } else { + loading(f, block, prompt_area, app.is_loading); + } } diff --git a/src/ui/radarr_ui/indexers/indexer_settings_ui_tests.rs b/src/ui/radarr_ui/indexers/indexer_settings_ui_tests.rs index 8877b37..bef1814 100644 --- a/src/ui/radarr_ui/indexers/indexer_settings_ui_tests.rs +++ b/src/ui/radarr_ui/indexers/indexer_settings_ui_tests.rs @@ -2,7 +2,9 @@ mod tests { use strum::IntoEnumIterator; - use crate::models::servarr_data::radarr_data::{ActiveRadarrBlock, INDEXER_SETTINGS_BLOCKS}; + use crate::models::servarr_data::radarr::radarr_data::{ + ActiveRadarrBlock, INDEXER_SETTINGS_BLOCKS, + }; use crate::ui::radarr_ui::indexers::indexer_settings_ui::IndexerSettingsUi; use crate::ui::DrawUi; diff --git a/src/ui/radarr_ui/indexers/indexers_ui_tests.rs b/src/ui/radarr_ui/indexers/indexers_ui_tests.rs index 89edd2b..7b6a135 100644 --- a/src/ui/radarr_ui/indexers/indexers_ui_tests.rs +++ b/src/ui/radarr_ui/indexers/indexers_ui_tests.rs @@ -2,7 +2,7 @@ mod tests { use strum::IntoEnumIterator; - use crate::models::servarr_data::radarr_data::{ + use crate::models::servarr_data::radarr::radarr_data::{ ActiveRadarrBlock, INDEXERS_BLOCKS, INDEXER_SETTINGS_BLOCKS, }; use crate::ui::radarr_ui::indexers::IndexersUi; diff --git a/src/ui/radarr_ui/indexers/mod.rs b/src/ui/radarr_ui/indexers/mod.rs index ef314f5..3be49e8 100644 --- a/src/ui/radarr_ui/indexers/mod.rs +++ b/src/ui/radarr_ui/indexers/mod.rs @@ -6,7 +6,7 @@ use tui::Frame; use crate::app::App; use crate::models::radarr_models::Indexer; -use crate::models::servarr_data::radarr_data::{ActiveRadarrBlock, INDEXERS_BLOCKS}; +use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, INDEXERS_BLOCKS}; use crate::models::Route; use crate::ui::radarr_ui::indexers::indexer_settings_ui::IndexerSettingsUi; use crate::ui::utils::{layout_block_top_border, style_failure, style_primary, style_success}; diff --git a/src/ui/radarr_ui/library/add_movie_ui.rs b/src/ui/radarr_ui/library/add_movie_ui.rs index 4980984..e4b083d 100644 --- a/src/ui/radarr_ui/library/add_movie_ui.rs +++ b/src/ui/radarr_ui/library/add_movie_ui.rs @@ -7,14 +7,11 @@ use tui::Frame; use crate::app::context_clues::{build_context_clue_string, BARE_POPUP_CONTEXT_CLUES}; use crate::app::radarr::radarr_context_clues::ADD_MOVIE_SEARCH_RESULTS_CONTEXT_CLUES; use crate::models::radarr_models::AddMovieSearchResult; -use crate::models::servarr_data::radarr_data::{ActiveRadarrBlock, ADD_MOVIE_BLOCKS}; +use crate::models::servarr_data::radarr::modals::AddMovieModal; +use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, ADD_MOVIE_BLOCKS}; use crate::models::Route; use crate::ui::radarr_ui::collections::{draw_collection_details, draw_collections}; use crate::ui::radarr_ui::library::draw_library; -use crate::ui::radarr_ui::{ - draw_select_minimum_availability_popup, draw_select_quality_profile_popup, - draw_select_root_folder_popup, -}; use crate::ui::utils::{ borderless_block, get_width_from_percentage, horizontal_chunks, layout_block, layout_paragraph_borderless, style_help, style_primary, title_block_centered, @@ -284,7 +281,7 @@ fn draw_confirmation_popup(f: &mut Frame<'_, B>, app: &mut App<'_>, app, prompt_area, draw_confirmation_prompt, - draw_select_monitor_popup, + draw_add_movie_select_monitor_popup, ); } ActiveRadarrBlock::AddMovieSelectMinimumAvailability => { @@ -293,7 +290,7 @@ fn draw_confirmation_popup(f: &mut Frame<'_, B>, app: &mut App<'_>, app, prompt_area, draw_confirmation_prompt, - draw_select_minimum_availability_popup, + draw_add_movie_select_minimum_availability_popup, ); } ActiveRadarrBlock::AddMovieSelectQualityProfile => { @@ -302,7 +299,7 @@ fn draw_confirmation_popup(f: &mut Frame<'_, B>, app: &mut App<'_>, app, prompt_area, draw_confirmation_prompt, - draw_select_quality_profile_popup, + draw_add_movie_select_quality_profile_popup, ); } ActiveRadarrBlock::AddMovieSelectRootFolder => { @@ -311,7 +308,7 @@ fn draw_confirmation_popup(f: &mut Frame<'_, B>, app: &mut App<'_>, app, prompt_area, draw_confirmation_prompt, - draw_select_root_folder_popup, + draw_add_movie_select_root_folder_popup, ); } ActiveRadarrBlock::AddMoviePrompt | ActiveRadarrBlock::AddMovieTagsInput => { @@ -322,19 +319,6 @@ fn draw_confirmation_popup(f: &mut Frame<'_, B>, app: &mut App<'_>, } } -fn draw_select_monitor_popup( - f: &mut Frame<'_, B>, - app: &mut App<'_>, - popup_area: Rect, -) { - draw_selectable_list( - f, - popup_area, - &mut app.data.radarr_data.monitor_list, - |monitor| ListItem::new(monitor.to_display_str().to_owned()), - ); -} - fn draw_confirmation_prompt( f: &mut Frame<'_, B>, app: &mut App<'_>, @@ -380,19 +364,19 @@ fn draw_confirmation_prompt( let yes_no_value = app.data.radarr_data.prompt_confirm; let selected_block = app.data.radarr_data.selected_block.get_active_block(); let highlight_yes_no = selected_block == &ActiveRadarrBlock::AddMovieConfirmPrompt; + let AddMovieModal { + monitor_list, + minimum_availability_list, + quality_profile_list, + root_folder_list, + tags, + .. + } = app.data.radarr_data.add_movie_modal.as_ref().unwrap(); - let selected_monitor = app.data.radarr_data.monitor_list.current_selection(); - let selected_minimum_availability = app - .data - .radarr_data - .minimum_availability_list - .current_selection(); - let selected_quality_profile = app - .data - .radarr_data - .quality_profile_list - .current_selection(); - let selected_root_folder = app.data.radarr_data.root_folder_list.current_selection(); + let selected_monitor = monitor_list.current_selection(); + let selected_minimum_availability = minimum_availability_list.current_selection(); + let selected_quality_profile = quality_profile_list.current_selection(); + let selected_root_folder = root_folder_list.current_selection(); f.render_widget(title_block_centered(&title), prompt_area); @@ -455,8 +439,8 @@ fn draw_confirmation_prompt( f, chunks[5], "Tags", - &app.data.radarr_data.edit_tags.text, - *app.data.radarr_data.edit_tags.offset.borrow(), + &tags.text, + *tags.offset.borrow(), selected_block == &ActiveRadarrBlock::AddMovieTagsInput, active_radarr_block == ActiveRadarrBlock::AddMovieTagsInput, ); @@ -475,3 +459,79 @@ fn draw_confirmation_prompt( !yes_no_value && highlight_yes_no, ); } + +fn draw_add_movie_select_monitor_popup( + f: &mut Frame<'_, B>, + app: &mut App<'_>, + popup_area: Rect, +) { + draw_selectable_list( + f, + popup_area, + &mut app + .data + .radarr_data + .add_movie_modal + .as_mut() + .unwrap() + .monitor_list, + |monitor| ListItem::new(monitor.to_display_str().to_owned()), + ); +} + +fn draw_add_movie_select_minimum_availability_popup( + f: &mut Frame<'_, B>, + app: &mut App<'_>, + popup_area: Rect, +) { + draw_selectable_list( + f, + popup_area, + &mut app + .data + .radarr_data + .add_movie_modal + .as_mut() + .unwrap() + .minimum_availability_list, + |minimum_availability| ListItem::new(minimum_availability.to_display_str().to_owned()), + ); +} + +fn draw_add_movie_select_quality_profile_popup( + f: &mut Frame<'_, B>, + app: &mut App<'_>, + popup_area: Rect, +) { + draw_selectable_list( + f, + popup_area, + &mut app + .data + .radarr_data + .add_movie_modal + .as_mut() + .unwrap() + .quality_profile_list, + |quality_profile| ListItem::new(quality_profile.clone()), + ); +} + +fn draw_add_movie_select_root_folder_popup( + f: &mut Frame<'_, B>, + app: &mut App<'_>, + popup_area: Rect, +) { + draw_selectable_list( + f, + popup_area, + &mut app + .data + .radarr_data + .add_movie_modal + .as_mut() + .unwrap() + .root_folder_list, + |root_folder| ListItem::new(root_folder.path.to_owned()), + ); +} diff --git a/src/ui/radarr_ui/library/add_movie_ui_tests.rs b/src/ui/radarr_ui/library/add_movie_ui_tests.rs index 4b9c360..ff24d30 100644 --- a/src/ui/radarr_ui/library/add_movie_ui_tests.rs +++ b/src/ui/radarr_ui/library/add_movie_ui_tests.rs @@ -2,7 +2,7 @@ mod tests { use strum::IntoEnumIterator; - use crate::models::servarr_data::radarr_data::{ActiveRadarrBlock, ADD_MOVIE_BLOCKS}; + use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, ADD_MOVIE_BLOCKS}; use crate::ui::radarr_ui::library::add_movie_ui::AddMovieUi; use crate::ui::DrawUi; diff --git a/src/ui/radarr_ui/library/delete_movie_ui.rs b/src/ui/radarr_ui/library/delete_movie_ui.rs index a30a1ff..34cfbc9 100644 --- a/src/ui/radarr_ui/library/delete_movie_ui.rs +++ b/src/ui/radarr_ui/library/delete_movie_ui.rs @@ -3,7 +3,7 @@ use tui::layout::Rect; use tui::Frame; use crate::app::App; -use crate::models::servarr_data::radarr_data::{ActiveRadarrBlock, DELETE_MOVIE_BLOCKS}; +use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, DELETE_MOVIE_BLOCKS}; use crate::models::Route; use crate::ui::radarr_ui::library::draw_library; use crate::ui::{draw_prompt_box_with_checkboxes, draw_prompt_popup_over, DrawUi}; diff --git a/src/ui/radarr_ui/library/delete_movie_ui_tests.rs b/src/ui/radarr_ui/library/delete_movie_ui_tests.rs index 6837d3f..625ce88 100644 --- a/src/ui/radarr_ui/library/delete_movie_ui_tests.rs +++ b/src/ui/radarr_ui/library/delete_movie_ui_tests.rs @@ -2,7 +2,7 @@ mod tests { use strum::IntoEnumIterator; - use crate::models::servarr_data::radarr_data::{ActiveRadarrBlock, DELETE_MOVIE_BLOCKS}; + use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, DELETE_MOVIE_BLOCKS}; use crate::ui::radarr_ui::library::delete_movie_ui::DeleteMovieUi; use crate::ui::DrawUi; diff --git a/src/ui/radarr_ui/library/edit_movie_ui.rs b/src/ui/radarr_ui/library/edit_movie_ui.rs index f8cfbf0..1d020bd 100644 --- a/src/ui/radarr_ui/library/edit_movie_ui.rs +++ b/src/ui/radarr_ui/library/edit_movie_ui.rs @@ -1,24 +1,24 @@ use tui::backend::Backend; use tui::layout::{Constraint, Rect}; +use tui::widgets::ListItem; use tui::Frame; use crate::app::App; -use crate::models::servarr_data::radarr_data::{ +use crate::models::servarr_data::radarr::modals::EditMovieModal; +use crate::models::servarr_data::radarr::radarr_data::{ ActiveRadarrBlock, EDIT_MOVIE_BLOCKS, MOVIE_DETAILS_BLOCKS, }; use crate::models::Route; use crate::ui::radarr_ui::library::draw_library; use crate::ui::radarr_ui::library::movie_details_ui::MovieDetailsUi; -use crate::ui::radarr_ui::{ - draw_select_minimum_availability_popup, draw_select_quality_profile_popup, -}; + use crate::ui::utils::{ horizontal_chunks, layout_paragraph_borderless, title_block_centered, vertical_chunks_with_margin, }; use crate::ui::{ draw_button, draw_checkbox_with_label, draw_drop_down_menu_button, draw_drop_down_popup, draw_large_popup_over_background_fn_with_ui, draw_medium_popup_over, draw_popup, - draw_text_box_with_label, DrawUi, + draw_selectable_list, draw_text_box_with_label, DrawUi, }; #[cfg(test)] @@ -46,7 +46,7 @@ impl DrawUi for EditMovieUi { app, prompt_area, draw_edit_movie_confirmation_prompt, - draw_select_minimum_availability_popup, + draw_edit_movie_select_minimum_availability_popup, ); } ActiveRadarrBlock::EditMovieSelectQualityProfile => { @@ -55,7 +55,7 @@ impl DrawUi for EditMovieUi { app, prompt_area, draw_edit_movie_confirmation_prompt, - draw_select_quality_profile_popup, + draw_edit_movie_select_quality_profile_popup, ); } ActiveRadarrBlock::EditMoviePrompt @@ -134,17 +134,16 @@ fn draw_edit_movie_confirmation_prompt( let yes_no_value = app.data.radarr_data.prompt_confirm; let selected_block = app.data.radarr_data.selected_block.get_active_block(); let highlight_yes_no = selected_block == &ActiveRadarrBlock::EditMovieConfirmPrompt; + let EditMovieModal { + minimum_availability_list, + quality_profile_list, + monitored, + path, + tags, + } = app.data.radarr_data.edit_movie_modal.as_ref().unwrap(); - let selected_minimum_availability = app - .data - .radarr_data - .minimum_availability_list - .current_selection(); - let selected_quality_profile = app - .data - .radarr_data - .quality_profile_list - .current_selection(); + let selected_minimum_availability = minimum_availability_list.current_selection(); + let selected_quality_profile = quality_profile_list.current_selection(); f.render_widget(title_block_centered(&title), prompt_area); @@ -175,7 +174,7 @@ fn draw_edit_movie_confirmation_prompt( f, chunks[1], "Monitored", - app.data.radarr_data.edit_monitored.unwrap_or_default(), + monitored.unwrap_or_default(), selected_block == &ActiveRadarrBlock::EditMovieToggleMonitored, ); @@ -199,8 +198,8 @@ fn draw_edit_movie_confirmation_prompt( f, chunks[4], "Path", - &app.data.radarr_data.edit_path.text, - *app.data.radarr_data.edit_path.offset.borrow(), + &path.text, + *path.offset.borrow(), selected_block == &ActiveRadarrBlock::EditMoviePathInput, active_radarr_block == ActiveRadarrBlock::EditMoviePathInput, ); @@ -208,8 +207,8 @@ fn draw_edit_movie_confirmation_prompt( f, chunks[5], "Tags", - &app.data.radarr_data.edit_tags.text, - *app.data.radarr_data.edit_tags.offset.borrow(), + &tags.text, + *tags.offset.borrow(), selected_block == &ActiveRadarrBlock::EditMovieTagsInput, active_radarr_block == ActiveRadarrBlock::EditMovieTagsInput, ); @@ -228,3 +227,41 @@ fn draw_edit_movie_confirmation_prompt( !yes_no_value && highlight_yes_no, ); } + +fn draw_edit_movie_select_minimum_availability_popup( + f: &mut Frame<'_, B>, + app: &mut App<'_>, + popup_area: Rect, +) { + draw_selectable_list( + f, + popup_area, + &mut app + .data + .radarr_data + .edit_movie_modal + .as_mut() + .unwrap() + .minimum_availability_list, + |minimum_availability| ListItem::new(minimum_availability.to_display_str().to_owned()), + ); +} + +fn draw_edit_movie_select_quality_profile_popup( + f: &mut Frame<'_, B>, + app: &mut App<'_>, + popup_area: Rect, +) { + draw_selectable_list( + f, + popup_area, + &mut app + .data + .radarr_data + .edit_movie_modal + .as_mut() + .unwrap() + .quality_profile_list, + |quality_profile| ListItem::new(quality_profile.clone()), + ); +} diff --git a/src/ui/radarr_ui/library/edit_movie_ui_tests.rs b/src/ui/radarr_ui/library/edit_movie_ui_tests.rs index 47cdc9c..ccaf1ac 100644 --- a/src/ui/radarr_ui/library/edit_movie_ui_tests.rs +++ b/src/ui/radarr_ui/library/edit_movie_ui_tests.rs @@ -2,7 +2,7 @@ mod tests { use strum::IntoEnumIterator; - use crate::models::servarr_data::radarr_data::{ActiveRadarrBlock, EDIT_MOVIE_BLOCKS}; + use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, EDIT_MOVIE_BLOCKS}; use crate::ui::radarr_ui::library::edit_movie_ui::EditMovieUi; use crate::ui::DrawUi; diff --git a/src/ui/radarr_ui/library/library_ui_tests.rs b/src/ui/radarr_ui/library/library_ui_tests.rs index c37708a..357def9 100644 --- a/src/ui/radarr_ui/library/library_ui_tests.rs +++ b/src/ui/radarr_ui/library/library_ui_tests.rs @@ -2,7 +2,7 @@ mod tests { use strum::IntoEnumIterator; - use crate::models::servarr_data::radarr_data::{ + use crate::models::servarr_data::radarr::radarr_data::{ ActiveRadarrBlock, ADD_MOVIE_BLOCKS, DELETE_MOVIE_BLOCKS, EDIT_MOVIE_BLOCKS, LIBRARY_BLOCKS, MOVIE_DETAILS_BLOCKS, }; diff --git a/src/ui/radarr_ui/library/mod.rs b/src/ui/radarr_ui/library/mod.rs index 07b0e2a..bf58b8f 100644 --- a/src/ui/radarr_ui/library/mod.rs +++ b/src/ui/radarr_ui/library/mod.rs @@ -5,7 +5,7 @@ use tui::Frame; use crate::app::App; use crate::models::radarr_models::Movie; -use crate::models::servarr_data::radarr_data::{ActiveRadarrBlock, LIBRARY_BLOCKS}; +use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, LIBRARY_BLOCKS}; use crate::models::Route; use crate::ui::radarr_ui::library::add_movie_ui::AddMovieUi; use crate::ui::radarr_ui::library::delete_movie_ui::DeleteMovieUi; diff --git a/src/ui/radarr_ui/library/movie_details_ui.rs b/src/ui/radarr_ui/library/movie_details_ui.rs index f420287..72d3aaf 100644 --- a/src/ui/radarr_ui/library/movie_details_ui.rs +++ b/src/ui/radarr_ui/library/movie_details_ui.rs @@ -9,7 +9,7 @@ use tui::Frame; use crate::app::App; use crate::models::radarr_models::{Credit, MovieHistoryItem, Release, ReleaseField}; -use crate::models::servarr_data::radarr_data::{ActiveRadarrBlock, MOVIE_DETAILS_BLOCKS}; +use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, MOVIE_DETAILS_BLOCKS}; use crate::models::Route; use crate::ui::radarr_ui::library::draw_library; use crate::ui::utils::{ diff --git a/src/ui/radarr_ui/library/movie_details_ui_tests.rs b/src/ui/radarr_ui/library/movie_details_ui_tests.rs index d7d1cb1..15f1077 100644 --- a/src/ui/radarr_ui/library/movie_details_ui_tests.rs +++ b/src/ui/radarr_ui/library/movie_details_ui_tests.rs @@ -2,7 +2,7 @@ mod tests { use strum::IntoEnumIterator; - use crate::models::servarr_data::radarr_data::{ActiveRadarrBlock, MOVIE_DETAILS_BLOCKS}; + use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, MOVIE_DETAILS_BLOCKS}; use crate::ui::radarr_ui::library::movie_details_ui::MovieDetailsUi; use crate::ui::DrawUi; diff --git a/src/ui/radarr_ui/mod.rs b/src/ui/radarr_ui/mod.rs index a3010d5..f3974d2 100644 --- a/src/ui/radarr_ui/mod.rs +++ b/src/ui/radarr_ui/mod.rs @@ -5,18 +5,16 @@ use tui::backend::Backend; use tui::layout::{Alignment, Constraint, Rect}; use tui::style::{Color, Style}; use tui::text::Text; -use tui::widgets::ListItem; use tui::widgets::Paragraph; use tui::Frame; use crate::app::App; use crate::logos::RADARR_LOGO; use crate::models::radarr_models::{DiskSpace, DownloadRecord, Movie, RootFolder}; -use crate::models::servarr_data::radarr_data::{ +use crate::models::servarr_data::radarr::radarr_data::{ ActiveRadarrBlock, RadarrData, FILTER_BLOCKS, SEARCH_BLOCKS, }; use crate::models::Route; -use crate::ui::draw_selectable_list; use crate::ui::draw_tabs; use crate::ui::loading; use crate::ui::radarr_ui::collections::CollectionsUi; @@ -232,45 +230,6 @@ fn determine_row_style(downloads_vec: &[DownloadRecord], movie: &Movie) -> Style } } -fn draw_select_minimum_availability_popup( - f: &mut Frame<'_, B>, - app: &mut App<'_>, - popup_area: Rect, -) { - draw_selectable_list( - f, - popup_area, - &mut app.data.radarr_data.minimum_availability_list, - |minimum_availability| ListItem::new(minimum_availability.to_display_str().to_owned()), - ); -} - -fn draw_select_quality_profile_popup( - f: &mut Frame<'_, B>, - app: &mut App<'_>, - popup_area: Rect, -) { - draw_selectable_list( - f, - popup_area, - &mut app.data.radarr_data.quality_profile_list, - |quality_profile| ListItem::new(quality_profile.clone()), - ); -} - -fn draw_select_root_folder_popup( - f: &mut Frame<'_, B>, - app: &mut App<'_>, - popup_area: Rect, -) { - draw_selectable_list( - f, - popup_area, - &mut app.data.radarr_data.root_folder_list, - |root_folder| ListItem::new(root_folder.path.to_owned()), - ); -} - fn draw_search_box(f: &mut Frame<'_, B>, app: &mut App<'_>, area: Rect) { let chunks = vertical_chunks_with_margin(vec![Constraint::Length(3), Constraint::Min(0)], area, 1); diff --git a/src/ui/radarr_ui/radarr_ui_tests.rs b/src/ui/radarr_ui/radarr_ui_tests.rs index d89b78c..a388794 100644 --- a/src/ui/radarr_ui/radarr_ui_tests.rs +++ b/src/ui/radarr_ui/radarr_ui_tests.rs @@ -2,7 +2,7 @@ mod tests { use strum::IntoEnumIterator; - use crate::models::servarr_data::radarr_data::ActiveRadarrBlock; + use crate::models::servarr_data::radarr::radarr_data::ActiveRadarrBlock; use crate::ui::radarr_ui::RadarrUi; use crate::ui::DrawUi; diff --git a/src/ui/radarr_ui/root_folders/mod.rs b/src/ui/radarr_ui/root_folders/mod.rs index 1871761..afe2d52 100644 --- a/src/ui/radarr_ui/root_folders/mod.rs +++ b/src/ui/radarr_ui/root_folders/mod.rs @@ -5,7 +5,7 @@ use tui::Frame; use crate::app::App; use crate::models::radarr_models::RootFolder; -use crate::models::servarr_data::radarr_data::{ActiveRadarrBlock, ROOT_FOLDERS_BLOCKS}; +use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, ROOT_FOLDERS_BLOCKS}; use crate::models::Route; use crate::ui::utils::{ borderless_block, layout_block_top_border, show_cursor, style_default, style_help, style_primary, diff --git a/src/ui/radarr_ui/root_folders/root_folders_ui_tests.rs b/src/ui/radarr_ui/root_folders/root_folders_ui_tests.rs index e5a3b8d..5a312c4 100644 --- a/src/ui/radarr_ui/root_folders/root_folders_ui_tests.rs +++ b/src/ui/radarr_ui/root_folders/root_folders_ui_tests.rs @@ -2,7 +2,7 @@ mod tests { use strum::IntoEnumIterator; - use crate::models::servarr_data::radarr_data::{ActiveRadarrBlock, ROOT_FOLDERS_BLOCKS}; + use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, ROOT_FOLDERS_BLOCKS}; use crate::ui::radarr_ui::root_folders::RootFoldersUi; use crate::ui::DrawUi; diff --git a/src/ui/radarr_ui/system/mod.rs b/src/ui/radarr_ui/system/mod.rs index 7cbb3ce..84e4bb9 100644 --- a/src/ui/radarr_ui/system/mod.rs +++ b/src/ui/radarr_ui/system/mod.rs @@ -13,7 +13,7 @@ use tui::{ use crate::app::App; use crate::models::radarr_models::Task; -use crate::models::servarr_data::radarr_data::ActiveRadarrBlock; +use crate::models::servarr_data::radarr::radarr_data::ActiveRadarrBlock; use crate::ui::radarr_ui::radarr_ui_utils::{ convert_to_minutes_hours_days, determine_log_style_by_level, }; diff --git a/src/ui/radarr_ui/system/system_details_ui.rs b/src/ui/radarr_ui/system/system_details_ui.rs index 28cc537..a076a01 100644 --- a/src/ui/radarr_ui/system/system_details_ui.rs +++ b/src/ui/radarr_ui/system/system_details_ui.rs @@ -7,7 +7,7 @@ use tui::Frame; use crate::app::context_clues::{build_context_clue_string, BARE_POPUP_CONTEXT_CLUES}; use crate::app::radarr::radarr_context_clues::SYSTEM_TASKS_CONTEXT_CLUES; use crate::app::App; -use crate::models::servarr_data::radarr_data::{ActiveRadarrBlock, SYSTEM_DETAILS_BLOCKS}; +use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, SYSTEM_DETAILS_BLOCKS}; use crate::models::Route; use crate::ui::radarr_ui::radarr_ui_utils::determine_log_style_by_level; use crate::ui::radarr_ui::system::{ diff --git a/src/ui/radarr_ui/system/system_details_ui_tests.rs b/src/ui/radarr_ui/system/system_details_ui_tests.rs index 6792558..0690fb7 100644 --- a/src/ui/radarr_ui/system/system_details_ui_tests.rs +++ b/src/ui/radarr_ui/system/system_details_ui_tests.rs @@ -2,7 +2,9 @@ mod tests { use strum::IntoEnumIterator; - use crate::models::servarr_data::radarr_data::{ActiveRadarrBlock, SYSTEM_DETAILS_BLOCKS}; + use crate::models::servarr_data::radarr::radarr_data::{ + ActiveRadarrBlock, SYSTEM_DETAILS_BLOCKS, + }; use crate::ui::radarr_ui::system::system_details_ui::SystemDetailsUi; use crate::ui::DrawUi; diff --git a/src/ui/radarr_ui/system/system_ui_tests.rs b/src/ui/radarr_ui/system/system_ui_tests.rs index f7886f3..797e1b0 100644 --- a/src/ui/radarr_ui/system/system_ui_tests.rs +++ b/src/ui/radarr_ui/system/system_ui_tests.rs @@ -2,7 +2,9 @@ mod tests { use strum::IntoEnumIterator; - use crate::models::servarr_data::radarr_data::{ActiveRadarrBlock, SYSTEM_DETAILS_BLOCKS}; + use crate::models::servarr_data::radarr::radarr_data::{ + ActiveRadarrBlock, SYSTEM_DETAILS_BLOCKS, + }; use crate::ui::radarr_ui::system::SystemUi; use crate::ui::DrawUi;