From 435926f6f0a158cdc4a3e50ff2024a9c9a861f5e Mon Sep 17 00:00:00 2001 From: Dark-Alex-17 Date: Tue, 8 Aug 2023 10:50:06 -0600 Subject: [PATCH] Added two new checkboxes to the delete movie UI that allows users to specify to delete the file and/or add an exclusion for the selected film on deletion. Also fixed the refresh bug in the root folders UI where you have to manually refresh to get the changes to show before 20 seconds. Also cleaned up code a bit and removed some unnecessary clone calls and references-dereferences since the types were copyable and not necessary to be referenced since they were all dereferenced anyway and copied. Made sense to just cut out the middleman on the copies. --- Cargo.toml | 2 +- src/app/radarr.rs | 124 +++++++- .../radarr_handlers/add_movie_handler.rs | 7 +- .../radarr_handlers/delete_movie_handler.rs | 283 ++++++++++++++++++ .../edit_collection_handler.rs | 13 +- .../radarr_handlers/edit_movie_handler.rs | 11 +- src/handlers/radarr_handlers/mod.rs | 60 ++-- src/network/radarr_network.rs | 45 ++- src/ui/mod.rs | 62 +++- src/ui/radarr_ui/add_movie_ui.rs | 20 +- src/ui/radarr_ui/delete_movie_ui.rs | 45 +++ src/ui/radarr_ui/edit_collection_ui.rs | 20 +- src/ui/radarr_ui/edit_movie_ui.rs | 20 +- src/ui/radarr_ui/mod.rs | 30 +- src/ui/radarr_ui/movie_details_ui.rs | 8 +- 15 files changed, 618 insertions(+), 132 deletions(-) create mode 100644 src/handlers/radarr_handlers/delete_movie_handler.rs create mode 100644 src/ui/radarr_ui/delete_movie_ui.rs diff --git a/Cargo.toml b/Cargo.toml index bbc4ce0..25969d2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "managarr" -version = "0.0.15" +version = "0.0.16" authors = ["Alex Clarke "] description = "A TUI for managing *arr servers" keywords = ["managarr", "tui-rs", "dashboard", "servarr"] diff --git a/src/app/radarr.rs b/src/app/radarr.rs index bbb28de..45c8b1a 100644 --- a/src/app/radarr.rs +++ b/src/app/radarr.rs @@ -51,6 +51,8 @@ pub struct RadarrData { pub edit_search_on_add: Option, pub sort_ascending: Option, pub prompt_confirm: bool, + pub delete_movie_files: bool, + pub add_list_exclusion: bool, pub is_searching: bool, pub is_filtering: bool, } @@ -60,6 +62,11 @@ impl RadarrData { self.collection_movies = StatefulTable::default(); } + pub fn reset_delete_movie_preferences(&mut self) { + self.delete_movie_files = false; + self.add_list_exclusion = false; + } + pub fn reset_search(&mut self) { self.is_searching = false; self.search = HorizontallyScrollableText::default(); @@ -260,6 +267,8 @@ impl Default for RadarrData { is_searching: false, is_filtering: false, prompt_confirm: false, + delete_movie_files: false, + add_list_exclusion: false, main_tabs: TabState::new(vec![ TabRoute { title: "Library".to_owned(), @@ -350,6 +359,9 @@ pub enum ActiveRadarrBlock { Cast, Crew, DeleteMoviePrompt, + DeleteMovieConfirmPrompt, + DeleteMovieToggleDeleteFile, + DeleteMovieToggleAddListExclusion, DeleteDownloadPrompt, DeleteRootFolderPrompt, Downloads, @@ -440,6 +452,12 @@ pub const FILTER_BLOCKS: [ActiveRadarrBlock; 2] = [ ActiveRadarrBlock::FilterMovies, ActiveRadarrBlock::FilterCollections, ]; +pub const DELETE_MOVIE_BLOCKS: [ActiveRadarrBlock; 4] = [ + ActiveRadarrBlock::DeleteMoviePrompt, + ActiveRadarrBlock::DeleteMovieConfirmPrompt, + ActiveRadarrBlock::DeleteMovieToggleDeleteFile, + ActiveRadarrBlock::DeleteMovieToggleAddListExclusion, +]; impl ActiveRadarrBlock { pub fn next_add_movie_prompt_block(&self) -> Self { @@ -493,6 +511,19 @@ impl ActiveRadarrBlock { } } + pub fn next_delete_movie_prompt_block(&self) -> Self { + match self { + ActiveRadarrBlock::DeleteMovieToggleDeleteFile => { + ActiveRadarrBlock::DeleteMovieToggleAddListExclusion + } + ActiveRadarrBlock::DeleteMovieToggleAddListExclusion => { + ActiveRadarrBlock::DeleteMovieConfirmPrompt + } + ActiveRadarrBlock::DeleteMovieConfirmPrompt => ActiveRadarrBlock::DeleteMovieToggleDeleteFile, + _ => ActiveRadarrBlock::DeleteMovieToggleDeleteFile, + } + } + pub fn previous_add_movie_prompt_block(&self) -> Self { match self { ActiveRadarrBlock::AddMovieSelectRootFolder => ActiveRadarrBlock::AddMovieConfirmPrompt, @@ -548,6 +579,19 @@ impl ActiveRadarrBlock { _ => ActiveRadarrBlock::EditCollectionToggleMonitored, } } + + pub fn previous_delete_movie_prompt_block(&self) -> Self { + match self { + ActiveRadarrBlock::DeleteMovieToggleDeleteFile => ActiveRadarrBlock::DeleteMovieConfirmPrompt, + ActiveRadarrBlock::DeleteMovieToggleAddListExclusion => { + ActiveRadarrBlock::DeleteMovieToggleDeleteFile + } + ActiveRadarrBlock::DeleteMovieConfirmPrompt => { + ActiveRadarrBlock::DeleteMovieToggleAddListExclusion + } + _ => ActiveRadarrBlock::DeleteMovieToggleDeleteFile, + } + } } impl From for Route { @@ -683,6 +727,9 @@ impl App { self .dispatch_network_event(RadarrEvent::GetTags.into()) .await; + self + .dispatch_network_event(RadarrEvent::GetRootFolders.into()) + .await; self .dispatch_network_event(RadarrEvent::GetDownloads.into()) .await; @@ -730,6 +777,8 @@ pub mod radarr_test_utils { let mut radarr_data = RadarrData { is_searching: true, is_filtering: true, + delete_movie_files: true, + add_list_exclusion: true, search: "test search".to_owned().into(), filter: "test filter".to_owned().into(), edit_path: "test path".to_owned().into(), @@ -781,13 +830,6 @@ pub mod radarr_test_utils { radarr_data } - #[macro_export] - macro_rules! assert_movie_collection_table_reset { - ($radarr_data:expr) => { - assert!($radarr_data.collection_movies.items.is_empty()); - }; - } - #[macro_export] macro_rules! assert_search_reset { ($radarr_data:expr) => { @@ -887,7 +929,17 @@ mod tests { radarr_data.reset_movie_collection_table(); - assert_movie_collection_table_reset!(radarr_data); + assert!(radarr_data.collection_movies.items.is_empty()); + } + + #[test] + fn test_reset_delete_movie_preferences() { + let mut radarr_data = create_test_radarr_data(); + + radarr_data.reset_delete_movie_preferences(); + + assert!(!radarr_data.delete_movie_files); + assert!(!radarr_data.add_list_exclusion); } #[test] @@ -1128,6 +1180,8 @@ mod tests { assert!(!radarr_data.is_searching); assert!(!radarr_data.is_filtering); assert!(!radarr_data.prompt_confirm); + assert!(!radarr_data.delete_movie_files); + assert!(!radarr_data.add_list_exclusion); assert_eq!(radarr_data.main_tabs.tabs.len(), 4); @@ -1368,6 +1422,25 @@ mod tests { ); } + #[test] + fn test_next_delete_movie_prompt_block() { + let active_block = + ActiveRadarrBlock::DeleteMovieToggleDeleteFile.next_delete_movie_prompt_block(); + + assert_eq!( + active_block, + ActiveRadarrBlock::DeleteMovieToggleAddListExclusion + ); + + let active_block = active_block.next_delete_movie_prompt_block(); + + assert_eq!(active_block, ActiveRadarrBlock::DeleteMovieConfirmPrompt); + + let active_block = active_block.next_delete_movie_prompt_block(); + + assert_eq!(active_block, ActiveRadarrBlock::DeleteMovieToggleDeleteFile); + } + #[test] fn test_previous_add_movie_prompt_block() { let active_block = @@ -1478,6 +1551,25 @@ mod tests { ActiveRadarrBlock::EditCollectionToggleMonitored ); } + + #[test] + fn test_previous_delete_movie_prompt_block() { + let active_block = + ActiveRadarrBlock::DeleteMovieToggleDeleteFile.previous_delete_movie_prompt_block(); + + assert_eq!(active_block, ActiveRadarrBlock::DeleteMovieConfirmPrompt); + + let active_block = active_block.previous_delete_movie_prompt_block(); + + assert_eq!( + active_block, + ActiveRadarrBlock::DeleteMovieToggleAddListExclusion + ); + + let active_block = active_block.previous_delete_movie_prompt_block(); + + assert_eq!(active_block, ActiveRadarrBlock::DeleteMovieToggleDeleteFile); + } } mod radarr_tests { @@ -1857,6 +1949,14 @@ mod tests { sync_network_rx.recv().await.unwrap(), RadarrEvent::GetTags.into() ); + assert_eq!( + sync_network_rx.recv().await.unwrap(), + RadarrEvent::GetRootFolders.into() + ); + assert_eq!( + sync_network_rx.recv().await.unwrap(), + RadarrEvent::GetDownloads.into() + ); assert!(app.is_loading); } @@ -1926,6 +2026,10 @@ mod tests { sync_network_rx.recv().await.unwrap(), RadarrEvent::GetTags.into() ); + assert_eq!( + sync_network_rx.recv().await.unwrap(), + RadarrEvent::GetRootFolders.into() + ); assert_eq!( sync_network_rx.recv().await.unwrap(), RadarrEvent::GetDownloads.into() @@ -1974,6 +2078,10 @@ mod tests { sync_network_rx.recv().await.unwrap(), RadarrEvent::GetTags.into() ); + assert_eq!( + sync_network_rx.recv().await.unwrap(), + RadarrEvent::GetRootFolders.into() + ); assert_eq!( sync_network_rx.recv().await.unwrap(), RadarrEvent::GetDownloads.into() diff --git a/src/handlers/radarr_handlers/add_movie_handler.rs b/src/handlers/radarr_handlers/add_movie_handler.rs index 7b9be02..4d9aa42 100644 --- a/src/handlers/radarr_handlers/add_movie_handler.rs +++ b/src/handlers/radarr_handlers/add_movie_handler.rs @@ -57,7 +57,6 @@ impl<'a> KeyEventHandler<'a, ActiveRadarrBlock> for AddMovieHandler<'a> { .data .radarr_data .selected_block - .clone() .previous_add_movie_prompt_block() } _ => (), @@ -228,10 +227,9 @@ impl<'a> KeyEventHandler<'a, ActiveRadarrBlock> for AddMovieHandler<'a> { ActiveRadarrBlock::AddMovieConfirmPrompt => { if self.app.data.radarr_data.prompt_confirm { self.app.data.radarr_data.prompt_confirm_action = Some(RadarrEvent::AddMovie); - self.app.pop_navigation_stack(); - } else { - self.app.pop_navigation_stack(); } + + self.app.pop_navigation_stack(); } ActiveRadarrBlock::AddMovieSelectMonitor | ActiveRadarrBlock::AddMovieSelectMinimumAvailability @@ -515,7 +513,6 @@ mod tests { use pretty_assertions::{assert_eq, assert_str_eq}; use rstest::rstest; - use crate::app::key_binding::DEFAULT_KEYBINDINGS; use crate::models::radarr_models::Movie; use crate::network::radarr_network::RadarrEvent; diff --git a/src/handlers/radarr_handlers/delete_movie_handler.rs b/src/handlers/radarr_handlers/delete_movie_handler.rs new file mode 100644 index 0000000..1adecd3 --- /dev/null +++ b/src/handlers/radarr_handlers/delete_movie_handler.rs @@ -0,0 +1,283 @@ +use crate::app::radarr::ActiveRadarrBlock; +use crate::app::App; +use crate::event::Key; +use crate::handlers::{handle_prompt_toggle, KeyEventHandler}; +use crate::network::radarr_network::RadarrEvent; + +pub(super) struct DeleteMovieHandler<'a> { + key: &'a Key, + app: &'a mut App, + active_radarr_block: &'a ActiveRadarrBlock, + _context: &'a Option, +} + +impl<'a> KeyEventHandler<'a, ActiveRadarrBlock> for DeleteMovieHandler<'a> { + fn with( + key: &'a Key, + app: &'a mut App, + active_block: &'a ActiveRadarrBlock, + _context: &'a Option, + ) -> Self { + DeleteMovieHandler { + key, + app, + active_radarr_block: active_block, + _context, + } + } + + fn get_key(&self) -> &Key { + self.key + } + + fn handle_scroll_up(&mut self) { + if *self.active_radarr_block == ActiveRadarrBlock::DeleteMoviePrompt { + self.app.data.radarr_data.selected_block = self + .app + .data + .radarr_data + .selected_block + .previous_delete_movie_prompt_block(); + } + } + + fn handle_scroll_down(&mut self) { + if *self.active_radarr_block == ActiveRadarrBlock::DeleteMoviePrompt { + self.app.data.radarr_data.selected_block = self + .app + .data + .radarr_data + .selected_block + .next_delete_movie_prompt_block(); + } + } + + fn handle_home(&mut self) {} + + fn handle_end(&mut self) {} + + fn handle_delete(&mut self) {} + + fn handle_left_right_action(&mut self) { + if *self.active_radarr_block == ActiveRadarrBlock::DeleteMoviePrompt { + handle_prompt_toggle(self.app, self.key); + } + } + + fn handle_submit(&mut self) { + if self.active_radarr_block == &ActiveRadarrBlock::DeleteMoviePrompt { + match self.app.data.radarr_data.selected_block { + ActiveRadarrBlock::DeleteMovieConfirmPrompt => { + if self.app.data.radarr_data.prompt_confirm { + self.app.data.radarr_data.prompt_confirm_action = Some(RadarrEvent::DeleteMovie); + self.app.should_refresh = true; + } else { + self.app.data.radarr_data.reset_delete_movie_preferences(); + } + + self.app.pop_navigation_stack(); + } + ActiveRadarrBlock::DeleteMovieToggleDeleteFile => { + self.app.data.radarr_data.delete_movie_files = + !self.app.data.radarr_data.delete_movie_files; + } + ActiveRadarrBlock::DeleteMovieToggleAddListExclusion => { + self.app.data.radarr_data.add_list_exclusion = + !self.app.data.radarr_data.add_list_exclusion; + } + _ => (), + } + } + } + + fn handle_esc(&mut self) { + if *self.active_radarr_block == ActiveRadarrBlock::DeleteMoviePrompt { + self.app.pop_navigation_stack(); + self.app.data.radarr_data.reset_delete_movie_preferences(); + self.app.data.radarr_data.prompt_confirm = false; + } + } + + fn handle_char_key_event(&mut self) {} +} + +#[cfg(test)] +mod tests { + use crate::app::key_binding::DEFAULT_KEYBINDINGS; + use crate::app::radarr::ActiveRadarrBlock; + use crate::app::App; + use crate::event::Key; + use crate::handlers::radarr_handlers::delete_movie_handler::DeleteMovieHandler; + use crate::handlers::KeyEventHandler; + + mod test_handle_scroll_up_and_down { + use pretty_assertions::assert_eq; + use rstest::rstest; + + use super::*; + + #[rstest] + fn test_delete_movie_prompt_scroll(#[values(Key::Up, Key::Down)] key: Key) { + let mut app = App::default(); + app.data.radarr_data.selected_block = ActiveRadarrBlock::DeleteMovieToggleAddListExclusion; + + DeleteMovieHandler::with(&key, &mut app, &ActiveRadarrBlock::DeleteMoviePrompt, &None) + .handle(); + + if key == Key::Up { + assert_eq!( + app.data.radarr_data.selected_block, + ActiveRadarrBlock::DeleteMovieToggleDeleteFile + ); + } else { + assert_eq!( + app.data.radarr_data.selected_block, + ActiveRadarrBlock::DeleteMovieConfirmPrompt + ); + } + } + } + + mod test_handle_left_right_action { + use rstest::rstest; + + use super::*; + + #[rstest] + fn test_left_right_prompt_toggle(#[values(Key::Left, Key::Right)] key: Key) { + let mut app = App::default(); + + DeleteMovieHandler::with(&key, &mut app, &ActiveRadarrBlock::DeleteMoviePrompt, &None) + .handle(); + + assert!(app.data.radarr_data.prompt_confirm); + + DeleteMovieHandler::with(&key, &mut app, &ActiveRadarrBlock::DeleteMoviePrompt, &None) + .handle(); + + assert!(!app.data.radarr_data.prompt_confirm); + } + } + + mod test_handle_submit { + use pretty_assertions::assert_eq; + + use crate::network::radarr_network::RadarrEvent; + + use super::*; + + const SUBMIT_KEY: Key = DEFAULT_KEYBINDINGS.submit.key; + + #[test] + fn test_delete_movie_prompt_prompt_decline_submit() { + let mut app = App::default(); + app.push_navigation_stack(ActiveRadarrBlock::Movies.into()); + app.push_navigation_stack(ActiveRadarrBlock::DeleteMoviePrompt.into()); + app.data.radarr_data.selected_block = ActiveRadarrBlock::DeleteMovieConfirmPrompt; + app.data.radarr_data.delete_movie_files = true; + app.data.radarr_data.add_list_exclusion = true; + + DeleteMovieHandler::with( + &SUBMIT_KEY, + &mut app, + &ActiveRadarrBlock::DeleteMoviePrompt, + &None, + ) + .handle(); + + assert_eq!(app.get_current_route(), &ActiveRadarrBlock::Movies.into()); + assert_eq!(app.data.radarr_data.prompt_confirm_action, None); + assert!(!app.data.radarr_data.prompt_confirm); + assert!(!app.data.radarr_data.delete_movie_files); + assert!(!app.data.radarr_data.add_list_exclusion); + } + + #[test] + fn test_delete_movie_confirm_prompt_prompt_confirmation_submit() { + let mut app = App::default(); + app.push_navigation_stack(ActiveRadarrBlock::Movies.into()); + app.push_navigation_stack(ActiveRadarrBlock::DeleteMoviePrompt.into()); + app.data.radarr_data.prompt_confirm = true; + app.data.radarr_data.delete_movie_files = true; + app.data.radarr_data.add_list_exclusion = true; + app.data.radarr_data.selected_block = ActiveRadarrBlock::DeleteMovieConfirmPrompt; + + DeleteMovieHandler::with( + &SUBMIT_KEY, + &mut app, + &ActiveRadarrBlock::DeleteMoviePrompt, + &None, + ) + .handle(); + + assert_eq!(app.get_current_route(), &ActiveRadarrBlock::Movies.into()); + assert_eq!( + app.data.radarr_data.prompt_confirm_action, + Some(RadarrEvent::DeleteMovie) + ); + assert!(app.should_refresh); + assert!(app.data.radarr_data.prompt_confirm); + assert!(app.data.radarr_data.delete_movie_files); + assert!(app.data.radarr_data.add_list_exclusion); + } + + #[test] + fn test_delete_movie_toggle_delete_files_submit() { + let current_route = ActiveRadarrBlock::DeleteMoviePrompt.into(); + let mut app = App::default(); + app.data.radarr_data.selected_block = ActiveRadarrBlock::DeleteMovieToggleDeleteFile; + app.push_navigation_stack(ActiveRadarrBlock::DeleteMoviePrompt.into()); + + DeleteMovieHandler::with( + &SUBMIT_KEY, + &mut app, + &ActiveRadarrBlock::DeleteMoviePrompt, + &None, + ) + .handle(); + + assert_eq!(app.get_current_route(), ¤t_route); + assert_eq!(app.data.radarr_data.delete_movie_files, true); + + DeleteMovieHandler::with( + &SUBMIT_KEY, + &mut app, + &ActiveRadarrBlock::DeleteMoviePrompt, + &None, + ) + .handle(); + + assert_eq!(app.get_current_route(), ¤t_route); + assert_eq!(app.data.radarr_data.delete_movie_files, false); + } + } + + mod test_handle_esc { + use super::*; + + const ESC_KEY: Key = DEFAULT_KEYBINDINGS.esc.key; + + #[test] + fn test_delete_movie_prompt_esc() { + let mut app = App::default(); + app.push_navigation_stack(ActiveRadarrBlock::Movies.into()); + app.push_navigation_stack(ActiveRadarrBlock::DeleteMoviePrompt.into()); + app.data.radarr_data.prompt_confirm = true; + app.data.radarr_data.delete_movie_files = true; + app.data.radarr_data.add_list_exclusion = true; + + DeleteMovieHandler::with( + &ESC_KEY, + &mut app, + &ActiveRadarrBlock::DeleteMoviePrompt, + &None, + ) + .handle(); + + assert_eq!(app.get_current_route(), &ActiveRadarrBlock::Movies.into()); + assert!(!app.data.radarr_data.prompt_confirm); + assert!(!app.data.radarr_data.delete_movie_files); + assert!(!app.data.radarr_data.add_list_exclusion); + } + } +} diff --git a/src/handlers/radarr_handlers/edit_collection_handler.rs b/src/handlers/radarr_handlers/edit_collection_handler.rs index f7893e1..fd9ce21 100644 --- a/src/handlers/radarr_handlers/edit_collection_handler.rs +++ b/src/handlers/radarr_handlers/edit_collection_handler.rs @@ -50,7 +50,6 @@ impl<'a> KeyEventHandler<'a, ActiveRadarrBlock> for EditCollectionHandler<'a> { .data .radarr_data .selected_block - .clone() .previous_edit_collection_prompt_block() } _ => (), @@ -140,11 +139,10 @@ impl<'a> KeyEventHandler<'a, ActiveRadarrBlock> for EditCollectionHandler<'a> { ActiveRadarrBlock::EditCollectionConfirmPrompt => { if self.app.data.radarr_data.prompt_confirm { self.app.data.radarr_data.prompt_confirm_action = Some(RadarrEvent::EditCollection); - self.app.pop_navigation_stack(); self.app.should_refresh = true; - } else { - self.app.pop_navigation_stack(); } + + self.app.pop_navigation_stack(); } ActiveRadarrBlock::EditCollectionSelectMinimumAvailability | ActiveRadarrBlock::EditCollectionSelectQualityProfile => self @@ -193,9 +191,7 @@ impl<'a> KeyEventHandler<'a, ActiveRadarrBlock> for EditCollectionHandler<'a> { self.app.data.radarr_data.reset_add_edit_media_fields(); self.app.data.radarr_data.prompt_confirm = false; } - ActiveRadarrBlock::EditCollectionToggleMonitored - | ActiveRadarrBlock::EditCollectionToggleSearchOnAdd - | ActiveRadarrBlock::EditCollectionSelectMinimumAvailability + ActiveRadarrBlock::EditCollectionSelectMinimumAvailability | ActiveRadarrBlock::EditCollectionSelectQualityProfile => self.app.pop_navigation_stack(), _ => (), } @@ -355,7 +351,6 @@ mod tests { use pretty_assertions::assert_eq; use rstest::rstest; - use crate::app::key_binding::DEFAULT_KEYBINDINGS; use crate::models::Route; use crate::network::radarr_network::RadarrEvent; @@ -635,8 +630,6 @@ mod tests { #[rstest] fn test_edit_collection_esc( #[values( - ActiveRadarrBlock::EditCollectionToggleMonitored, - ActiveRadarrBlock::EditCollectionToggleSearchOnAdd, ActiveRadarrBlock::EditCollectionSelectMinimumAvailability, ActiveRadarrBlock::EditCollectionSelectQualityProfile )] diff --git a/src/handlers/radarr_handlers/edit_movie_handler.rs b/src/handlers/radarr_handlers/edit_movie_handler.rs index cd80a46..0ac5a2c 100644 --- a/src/handlers/radarr_handlers/edit_movie_handler.rs +++ b/src/handlers/radarr_handlers/edit_movie_handler.rs @@ -50,7 +50,6 @@ impl<'a> KeyEventHandler<'a, ActiveRadarrBlock> for EditMovieHandler<'a> { .data .radarr_data .selected_block - .clone() .previous_edit_movie_prompt_block() } _ => (), @@ -141,11 +140,10 @@ impl<'a> KeyEventHandler<'a, ActiveRadarrBlock> for EditMovieHandler<'a> { ActiveRadarrBlock::EditMovieConfirmPrompt => { if self.app.data.radarr_data.prompt_confirm { self.app.data.radarr_data.prompt_confirm_action = Some(RadarrEvent::EditMovie); - self.app.pop_navigation_stack(); self.app.should_refresh = true; - } else { - self.app.pop_navigation_stack(); } + + self.app.pop_navigation_stack(); } ActiveRadarrBlock::EditMovieSelectMinimumAvailability | ActiveRadarrBlock::EditMovieSelectQualityProfile => self @@ -184,8 +182,7 @@ impl<'a> KeyEventHandler<'a, ActiveRadarrBlock> for EditMovieHandler<'a> { self.app.data.radarr_data.reset_add_edit_media_fields(); self.app.data.radarr_data.prompt_confirm = false; } - ActiveRadarrBlock::EditMovieToggleMonitored - | ActiveRadarrBlock::EditMovieSelectMinimumAvailability + ActiveRadarrBlock::EditMovieSelectMinimumAvailability | ActiveRadarrBlock::EditMovieSelectQualityProfile => self.app.pop_navigation_stack(), _ => (), } @@ -350,7 +347,6 @@ mod tests { use pretty_assertions::assert_eq; use rstest::rstest; - use crate::app::key_binding::DEFAULT_KEYBINDINGS; use crate::models::Route; use crate::network::radarr_network::RadarrEvent; @@ -617,7 +613,6 @@ mod tests { #[rstest] fn test_edit_movie_esc( #[values( - ActiveRadarrBlock::EditMovieToggleMonitored, ActiveRadarrBlock::EditMovieSelectMinimumAvailability, ActiveRadarrBlock::EditMovieSelectQualityProfile )] diff --git a/src/handlers/radarr_handlers/mod.rs b/src/handlers/radarr_handlers/mod.rs index c170ab9..6966dc2 100644 --- a/src/handlers/radarr_handlers/mod.rs +++ b/src/handlers/radarr_handlers/mod.rs @@ -1,10 +1,11 @@ use crate::app::key_binding::DEFAULT_KEYBINDINGS; use crate::app::radarr::{ - ActiveRadarrBlock, ADD_MOVIE_BLOCKS, COLLECTION_DETAILS_BLOCKS, EDIT_COLLECTION_BLOCKS, - EDIT_MOVIE_BLOCKS, FILTER_BLOCKS, MOVIE_DETAILS_BLOCKS, SEARCH_BLOCKS, + ActiveRadarrBlock, ADD_MOVIE_BLOCKS, COLLECTION_DETAILS_BLOCKS, DELETE_MOVIE_BLOCKS, + EDIT_COLLECTION_BLOCKS, EDIT_MOVIE_BLOCKS, FILTER_BLOCKS, MOVIE_DETAILS_BLOCKS, SEARCH_BLOCKS, }; use crate::handlers::radarr_handlers::add_movie_handler::AddMovieHandler; use crate::handlers::radarr_handlers::collection_details_handler::CollectionDetailsHandler; +use crate::handlers::radarr_handlers::delete_movie_handler::DeleteMovieHandler; use crate::handlers::radarr_handlers::edit_collection_handler::EditCollectionHandler; use crate::handlers::radarr_handlers::edit_movie_handler::EditMovieHandler; use crate::handlers::radarr_handlers::movie_details_handler::MovieDetailsHandler; @@ -16,6 +17,7 @@ use crate::{handle_text_box_keys, handle_text_box_left_right_keys, App, Key}; mod add_movie_handler; mod collection_details_handler; +mod delete_movie_handler; mod edit_collection_handler; mod edit_movie_handler; mod movie_details_handler; @@ -44,6 +46,10 @@ impl<'a> KeyEventHandler<'a, ActiveRadarrBlock> for RadarrHandler<'a> { _ if EDIT_MOVIE_BLOCKS.contains(self.active_radarr_block) => { EditMovieHandler::with(self.key, self.app, self.active_radarr_block, self.context).handle() } + _ if DELETE_MOVIE_BLOCKS.contains(self.active_radarr_block) => { + DeleteMovieHandler::with(self.key, self.app, self.active_radarr_block, self.context) + .handle() + } _ if EDIT_COLLECTION_BLOCKS.contains(self.active_radarr_block) => { EditCollectionHandler::with(self.key, self.app, self.active_radarr_block, self.context) .handle() @@ -212,9 +218,12 @@ impl<'a> KeyEventHandler<'a, ActiveRadarrBlock> for RadarrHandler<'a> { fn handle_delete(&mut self) { match self.active_radarr_block { - ActiveRadarrBlock::Movies => self - .app - .push_navigation_stack(ActiveRadarrBlock::DeleteMoviePrompt.into()), + ActiveRadarrBlock::Movies => { + self + .app + .push_navigation_stack(ActiveRadarrBlock::DeleteMoviePrompt.into()); + self.app.data.radarr_data.selected_block = ActiveRadarrBlock::DeleteMovieToggleDeleteFile; + } ActiveRadarrBlock::Downloads => self .app .push_navigation_stack(ActiveRadarrBlock::DeleteDownloadPrompt.into()), @@ -245,8 +254,7 @@ impl<'a> KeyEventHandler<'a, ActiveRadarrBlock> for RadarrHandler<'a> { } _ => (), }, - ActiveRadarrBlock::DeleteMoviePrompt - | ActiveRadarrBlock::DeleteDownloadPrompt + ActiveRadarrBlock::DeleteDownloadPrompt | ActiveRadarrBlock::DeleteRootFolderPrompt | ActiveRadarrBlock::UpdateAllMoviesPrompt | ActiveRadarrBlock::UpdateAllCollectionsPrompt @@ -359,13 +367,6 @@ impl<'a> KeyEventHandler<'a, ActiveRadarrBlock> for RadarrHandler<'a> { .set_items(filtered_collections); } } - ActiveRadarrBlock::DeleteMoviePrompt => { - if self.app.data.radarr_data.prompt_confirm { - self.app.data.radarr_data.prompt_confirm_action = Some(RadarrEvent::DeleteMovie); - } - - self.app.pop_navigation_stack(); - } ActiveRadarrBlock::DeleteDownloadPrompt => { if self.app.data.radarr_data.prompt_confirm { self.app.data.radarr_data.prompt_confirm_action = Some(RadarrEvent::DeleteDownload); @@ -429,8 +430,7 @@ impl<'a> KeyEventHandler<'a, ActiveRadarrBlock> for RadarrHandler<'a> { self.app.data.radarr_data.prompt_confirm = false; self.app.should_ignore_quit_key = false; } - ActiveRadarrBlock::DeleteMoviePrompt - | ActiveRadarrBlock::DeleteDownloadPrompt + ActiveRadarrBlock::DeleteDownloadPrompt | ActiveRadarrBlock::DeleteRootFolderPrompt | ActiveRadarrBlock::UpdateAllMoviesPrompt | ActiveRadarrBlock::UpdateAllCollectionsPrompt @@ -950,6 +950,10 @@ mod tests { app.get_current_route(), &ActiveRadarrBlock::DeleteMoviePrompt.into() ); + assert_eq!( + app.data.radarr_data.selected_block, + ActiveRadarrBlock::DeleteMovieToggleDeleteFile + ); } #[test] @@ -1050,7 +1054,6 @@ mod tests { #[rstest] fn test_left_right_prompt_toggle( #[values( - ActiveRadarrBlock::DeleteMoviePrompt, ActiveRadarrBlock::DeleteDownloadPrompt, ActiveRadarrBlock::DeleteRootFolderPrompt, ActiveRadarrBlock::UpdateAllMoviesPrompt, @@ -1344,11 +1347,6 @@ mod tests { } #[rstest] - #[case( - ActiveRadarrBlock::Movies, - ActiveRadarrBlock::DeleteMoviePrompt, - RadarrEvent::DeleteMovie - )] #[case( ActiveRadarrBlock::Downloads, ActiveRadarrBlock::DeleteDownloadPrompt, @@ -1395,7 +1393,6 @@ mod tests { } #[rstest] - #[case(ActiveRadarrBlock::Movies, ActiveRadarrBlock::DeleteMoviePrompt)] #[case(ActiveRadarrBlock::Downloads, ActiveRadarrBlock::DeleteDownloadPrompt)] #[case(ActiveRadarrBlock::Movies, ActiveRadarrBlock::UpdateAllMoviesPrompt)] #[case(ActiveRadarrBlock::Downloads, ActiveRadarrBlock::UpdateDownloadsPrompt)] @@ -1471,7 +1468,6 @@ mod tests { } #[rstest] - #[case(ActiveRadarrBlock::Movies, ActiveRadarrBlock::DeleteMoviePrompt)] #[case(ActiveRadarrBlock::Movies, ActiveRadarrBlock::UpdateAllMoviesPrompt)] #[case( ActiveRadarrBlock::RootFolders, @@ -1551,7 +1547,6 @@ mod tests { use serde_json::Number; use strum::IntoEnumIterator; - use crate::app::key_binding::DEFAULT_KEYBINDINGS; use crate::app::radarr::radarr_test_utils::create_test_radarr_data; use crate::app::radarr::RadarrData; use crate::models::radarr_models::MinimumAvailability; @@ -1996,23 +1991,28 @@ mod tests { ActiveRadarrBlock::EditMoviePathInput, ActiveRadarrBlock::EditMovieSelectMinimumAvailability, ActiveRadarrBlock::EditMovieSelectQualityProfile, - ActiveRadarrBlock::EditMovieTagsInput, - ActiveRadarrBlock::EditMovieToggleMonitored + ActiveRadarrBlock::EditMovieTagsInput )] active_radarr_block: ActiveRadarrBlock, ) { test_handler_delegation!(ActiveRadarrBlock::Movies, active_radarr_block); } + #[test] + fn test_delegate_delete_movie_blocks_to_delete_movie_handler() { + test_handler_delegation!( + ActiveRadarrBlock::Movies, + ActiveRadarrBlock::DeleteMoviePrompt + ); + } + #[rstest] fn test_delegate_edit_collection_blocks_to_edit_collection_handler( #[values( ActiveRadarrBlock::EditCollectionPrompt, ActiveRadarrBlock::EditCollectionRootFolderPathInput, ActiveRadarrBlock::EditCollectionSelectMinimumAvailability, - ActiveRadarrBlock::EditCollectionSelectQualityProfile, - ActiveRadarrBlock::EditCollectionToggleSearchOnAdd, - ActiveRadarrBlock::EditCollectionToggleMonitored + ActiveRadarrBlock::EditCollectionSelectQualityProfile )] active_radarr_block: ActiveRadarrBlock, ) { diff --git a/src/network/radarr_network.rs b/src/network/radarr_network.rs index 0f42c35..2187009 100644 --- a/src/network/radarr_network.rs +++ b/src/network/radarr_network.rs @@ -686,12 +686,24 @@ impl<'a> Network<'a> { async fn delete_movie(&self) { let movie_id = self.extract_movie_id().await; + let delete_files = self.app.lock().await.data.radarr_data.delete_movie_files; + let add_import_exclusion = self.app.lock().await.data.radarr_data.add_list_exclusion; - info!("Deleting Radarr movie with id: {}", movie_id); + info!( + "Deleting Radarr movie with id: {} with deleteFiles={} and addImportExclusion={}", + movie_id, delete_files, add_import_exclusion + ); let request_props = self .radarr_request_props_from( - format!("{}/{}", RadarrEvent::DeleteMovie.resource(), movie_id).as_str(), + format!( + "{}/{}?deleteFiles={}&addImportExclusion={}", + RadarrEvent::DeleteMovie.resource(), + movie_id, + delete_files, + add_import_exclusion + ) + .as_str(), RequestMethod::Delete, None::<()>, ) @@ -700,6 +712,14 @@ impl<'a> Network<'a> { self .handle_request::<(), ()>(request_props, |_, _| ()) .await; + + self + .app + .lock() + .await + .data + .radarr_data + .reset_delete_movie_preferences(); } async fn delete_download(&self) { @@ -2200,21 +2220,26 @@ mod test { RequestMethod::Delete, None, None, - format!("{}/1", RadarrEvent::DeleteMovie.resource()).as_str(), + format!( + "{}/1?deleteFiles=true&addImportExclusion=true", + RadarrEvent::DeleteMovie.resource() + ) + .as_str(), ) .await; - app_arc - .lock() - .await - .data - .radarr_data - .movies - .set_items(vec![movie()]); + { + let mut app = app_arc.lock().await; + app.data.radarr_data.movies.set_items(vec![movie()]); + app.data.radarr_data.delete_movie_files = true; + app.data.radarr_data.add_list_exclusion = true; + } let network = Network::new(reqwest::Client::new(), &app_arc); network.handle_radarr_event(RadarrEvent::DeleteMovie).await; async_server.assert_async().await; + assert!(!app_arc.lock().await.data.radarr_data.delete_movie_files); + assert!(!app_arc.lock().await.data.radarr_data.add_list_exclusion); } #[tokio::test] diff --git a/src/ui/mod.rs b/src/ui/mod.rs index 98ca4ba..9b3437e 100644 --- a/src/ui/mod.rs +++ b/src/ui/mod.rs @@ -1,3 +1,5 @@ +use std::iter; + use tui::backend::Backend; use tui::layout::{Alignment, Constraint, Rect}; use tui::style::Modifier; @@ -141,7 +143,7 @@ pub fn draw_prompt_popup_over( background_fn: fn(&mut Frame<'_, B>, &mut App, Rect), popup_fn: fn(&mut Frame<'_, B>, &mut App, Rect), ) { - draw_popup_over(f, app, area, background_fn, popup_fn, 30, 30); + draw_popup_over(f, app, area, background_fn, popup_fn, 35, 35); } pub fn draw_small_popup_over( @@ -334,7 +336,7 @@ pub fn draw_prompt_box( prompt_area: Rect, title: &str, prompt: &str, - yes_no_value: &bool, + yes_no_value: bool, ) { draw_prompt_box_with_content(f, prompt_area, title, prompt, None, yes_no_value); } @@ -345,7 +347,7 @@ pub fn draw_prompt_box_with_content( title: &str, prompt: &str, content: Option>, - yes_no_value: &bool, + yes_no_value: bool, ) { f.render_widget(title_block_centered(title), prompt_area); @@ -384,8 +386,58 @@ pub fn draw_prompt_box_with_content( chunks[2], ); - draw_button(f, horizontal_chunks[0], "Yes", *yes_no_value); - draw_button(f, horizontal_chunks[1], "No", !*yes_no_value); + draw_button(f, horizontal_chunks[0], "Yes", yes_no_value); + draw_button(f, horizontal_chunks[1], "No", !yes_no_value); +} + +pub fn draw_prompt_box_with_checkboxes( + f: &mut Frame<'_, B>, + prompt_area: Rect, + title: &str, + prompt: &str, + checkboxes: Vec<(&str, bool, bool)>, + highlight_yes_no: bool, + yes_no_value: bool, +) { + f.render_widget(title_block_centered(title), prompt_area); + let mut constraints = vec![ + Constraint::Length(4), + Constraint::Min(0), + Constraint::Length(3), + ]; + + constraints.splice( + 1..1, + iter::repeat(Constraint::Length(3)).take(checkboxes.len()), + ); + + let chunks = vertical_chunks_with_margin(constraints, prompt_area, 1); + + let prompt_paragraph = layout_paragraph_borderless(prompt); + f.render_widget(prompt_paragraph, chunks[0]); + + for i in 0..checkboxes.len() { + let (label, is_checked, is_selected) = checkboxes[i]; + draw_checkbox_with_label(f, chunks[i + 1], label, is_checked, is_selected); + } + + let horizontal_chunks = horizontal_chunks( + vec![Constraint::Percentage(50), Constraint::Percentage(50)], + chunks[checkboxes.len() + 2], + ); + + draw_button( + f, + horizontal_chunks[0], + "Yes", + highlight_yes_no && yes_no_value, + ); + draw_button( + f, + horizontal_chunks[1], + "No", + highlight_yes_no && !yes_no_value, + ); } pub fn draw_checkbox( diff --git a/src/ui/radarr_ui/add_movie_ui.rs b/src/ui/radarr_ui/add_movie_ui.rs index 6a169da..6e1e314 100644 --- a/src/ui/radarr_ui/add_movie_ui.rs +++ b/src/ui/radarr_ui/add_movie_ui.rs @@ -327,9 +327,9 @@ fn draw_confirmation_prompt(f: &mut Frame<'_, B>, app: &mut App, pro }; let title = format!("Add Movie - {}", movie_title); let prompt = movie_overview; - let yes_no_value = &app.data.radarr_data.prompt_confirm; - let selected_block = &app.data.radarr_data.selected_block; - let highlight_yes_no = *selected_block == ActiveRadarrBlock::AddMovieConfirmPrompt; + let yes_no_value = app.data.radarr_data.prompt_confirm; + let selected_block = app.data.radarr_data.selected_block; + let highlight_yes_no = selected_block == ActiveRadarrBlock::AddMovieConfirmPrompt; let selected_monitor = app.data.radarr_data.monitor_list.current_selection(); let selected_minimum_availability = app @@ -374,7 +374,7 @@ fn draw_confirmation_prompt(f: &mut Frame<'_, B>, app: &mut App, pro chunks[1], "Root Folder", &selected_root_folder.path, - *selected_block == ActiveRadarrBlock::AddMovieSelectRootFolder, + selected_block == ActiveRadarrBlock::AddMovieSelectRootFolder, ); draw_drop_down_menu_button( @@ -382,7 +382,7 @@ fn draw_confirmation_prompt(f: &mut Frame<'_, B>, app: &mut App, pro chunks[2], "Monitor", selected_monitor.to_display_str(), - *selected_block == ActiveRadarrBlock::AddMovieSelectMonitor, + selected_block == ActiveRadarrBlock::AddMovieSelectMonitor, ); draw_drop_down_menu_button( @@ -390,14 +390,14 @@ fn draw_confirmation_prompt(f: &mut Frame<'_, B>, app: &mut App, pro chunks[3], "Minimum Availability", selected_minimum_availability.to_display_str(), - *selected_block == ActiveRadarrBlock::AddMovieSelectMinimumAvailability, + selected_block == ActiveRadarrBlock::AddMovieSelectMinimumAvailability, ); draw_drop_down_menu_button( f, chunks[4], "Quality Profile", selected_quality_profile, - *selected_block == ActiveRadarrBlock::AddMovieSelectQualityProfile, + selected_block == ActiveRadarrBlock::AddMovieSelectQualityProfile, ); if let Route::Radarr(active_radarr_block, _) = *app.get_current_route() { @@ -407,7 +407,7 @@ fn draw_confirmation_prompt(f: &mut Frame<'_, B>, app: &mut App, pro "Tags", &app.data.radarr_data.edit_tags.text, *app.data.radarr_data.edit_tags.offset.borrow(), - *selected_block == ActiveRadarrBlock::AddMovieTagsInput, + selected_block == ActiveRadarrBlock::AddMovieTagsInput, active_radarr_block == ActiveRadarrBlock::AddMovieTagsInput, ); } @@ -416,12 +416,12 @@ fn draw_confirmation_prompt(f: &mut Frame<'_, B>, app: &mut App, pro f, horizontal_chunks[0], "Add", - *yes_no_value && highlight_yes_no, + yes_no_value && highlight_yes_no, ); draw_button( f, horizontal_chunks[1], "Cancel", - !*yes_no_value && highlight_yes_no, + !yes_no_value && highlight_yes_no, ); } diff --git a/src/ui/radarr_ui/delete_movie_ui.rs b/src/ui/radarr_ui/delete_movie_ui.rs new file mode 100644 index 0000000..0552107 --- /dev/null +++ b/src/ui/radarr_ui/delete_movie_ui.rs @@ -0,0 +1,45 @@ +use tui::backend::Backend; +use tui::layout::Rect; +use tui::Frame; + +use crate::app::radarr::ActiveRadarrBlock; +use crate::app::App; +use crate::models::Route; +use crate::ui::draw_prompt_box_with_checkboxes; + +pub(super) fn draw_delete_movie_prompt( + f: &mut Frame<'_, B>, + app: &mut App, + prompt_area: Rect, +) { + if matches!( + *app.get_current_route(), + Route::Radarr(ActiveRadarrBlock::DeleteMoviePrompt, _) + ) { + let selected_block = app.data.radarr_data.selected_block; + draw_prompt_box_with_checkboxes( + f, + prompt_area, + "Delete Movie", + format!( + "Do you really want to delete: {}?", + app.data.radarr_data.movies.current_selection().title + ) + .as_str(), + vec![ + ( + "Delete Movie Files", + app.data.radarr_data.delete_movie_files, + selected_block == ActiveRadarrBlock::DeleteMovieToggleDeleteFile, + ), + ( + "Add List Exclusion", + app.data.radarr_data.add_list_exclusion, + selected_block == ActiveRadarrBlock::DeleteMovieToggleAddListExclusion, + ), + ], + selected_block == ActiveRadarrBlock::DeleteMovieConfirmPrompt, + app.data.radarr_data.prompt_confirm, + ) + } +} diff --git a/src/ui/radarr_ui/edit_collection_ui.rs b/src/ui/radarr_ui/edit_collection_ui.rs index 09032c2..24508ee 100644 --- a/src/ui/radarr_ui/edit_collection_ui.rs +++ b/src/ui/radarr_ui/edit_collection_ui.rs @@ -96,9 +96,9 @@ fn draw_edit_collection_confirmation_prompt( ) }; let title = format!("Edit - {}", collection_title); - let yes_no_value = &app.data.radarr_data.prompt_confirm; - let selected_block = &app.data.radarr_data.selected_block; - let highlight_yes_no = *selected_block == ActiveRadarrBlock::EditCollectionConfirmPrompt; + let yes_no_value = app.data.radarr_data.prompt_confirm; + let selected_block = app.data.radarr_data.selected_block; + let highlight_yes_no = selected_block == ActiveRadarrBlock::EditCollectionConfirmPrompt; let selected_minimum_availability = app .data @@ -141,7 +141,7 @@ fn draw_edit_collection_confirmation_prompt( chunks[1], "Monitored", app.data.radarr_data.edit_monitored.unwrap_or_default(), - *selected_block == ActiveRadarrBlock::EditCollectionToggleMonitored, + selected_block == ActiveRadarrBlock::EditCollectionToggleMonitored, ); draw_drop_down_menu_button( @@ -149,14 +149,14 @@ fn draw_edit_collection_confirmation_prompt( chunks[2], "Minimum Availability", selected_minimum_availability.to_display_str(), - *selected_block == ActiveRadarrBlock::EditCollectionSelectMinimumAvailability, + selected_block == ActiveRadarrBlock::EditCollectionSelectMinimumAvailability, ); draw_drop_down_menu_button( f, chunks[3], "Quality Profile", selected_quality_profile, - *selected_block == ActiveRadarrBlock::EditCollectionSelectQualityProfile, + selected_block == ActiveRadarrBlock::EditCollectionSelectQualityProfile, ); if let Route::Radarr(active_radarr_block, _) = *app.get_current_route() { @@ -166,7 +166,7 @@ fn draw_edit_collection_confirmation_prompt( "Root Folder", &app.data.radarr_data.edit_path.text, *app.data.radarr_data.edit_path.offset.borrow(), - *selected_block == ActiveRadarrBlock::EditCollectionRootFolderPathInput, + selected_block == ActiveRadarrBlock::EditCollectionRootFolderPathInput, active_radarr_block == ActiveRadarrBlock::EditCollectionRootFolderPathInput, ); } @@ -176,19 +176,19 @@ fn draw_edit_collection_confirmation_prompt( chunks[5], "Search on Add", app.data.radarr_data.edit_search_on_add.unwrap_or_default(), - *selected_block == ActiveRadarrBlock::EditCollectionToggleSearchOnAdd, + selected_block == ActiveRadarrBlock::EditCollectionToggleSearchOnAdd, ); draw_button( f, horizontal_chunks[0], "Save", - *yes_no_value && highlight_yes_no, + yes_no_value && highlight_yes_no, ); draw_button( f, horizontal_chunks[1], "Cancel", - !*yes_no_value && highlight_yes_no, + !yes_no_value && highlight_yes_no, ); } diff --git a/src/ui/radarr_ui/edit_movie_ui.rs b/src/ui/radarr_ui/edit_movie_ui.rs index 868e70f..2c24dd0 100644 --- a/src/ui/radarr_ui/edit_movie_ui.rs +++ b/src/ui/radarr_ui/edit_movie_ui.rs @@ -93,9 +93,9 @@ fn draw_edit_movie_confirmation_prompt( ) }; let title = format!("Edit - {}", movie_title); - let yes_no_value = &app.data.radarr_data.prompt_confirm; - let selected_block = &app.data.radarr_data.selected_block; - let highlight_yes_no = *selected_block == ActiveRadarrBlock::EditMovieConfirmPrompt; + let yes_no_value = app.data.radarr_data.prompt_confirm; + let selected_block = app.data.radarr_data.selected_block; + let highlight_yes_no = selected_block == ActiveRadarrBlock::EditMovieConfirmPrompt; let selected_minimum_availability = app .data @@ -138,7 +138,7 @@ fn draw_edit_movie_confirmation_prompt( chunks[1], "Monitored", app.data.radarr_data.edit_monitored.unwrap_or_default(), - *selected_block == ActiveRadarrBlock::EditMovieToggleMonitored, + selected_block == ActiveRadarrBlock::EditMovieToggleMonitored, ); draw_drop_down_menu_button( @@ -146,14 +146,14 @@ fn draw_edit_movie_confirmation_prompt( chunks[2], "Minimum Availability", selected_minimum_availability.to_display_str(), - *selected_block == ActiveRadarrBlock::EditMovieSelectMinimumAvailability, + selected_block == ActiveRadarrBlock::EditMovieSelectMinimumAvailability, ); draw_drop_down_menu_button( f, chunks[3], "Quality Profile", selected_quality_profile, - *selected_block == ActiveRadarrBlock::EditMovieSelectQualityProfile, + selected_block == ActiveRadarrBlock::EditMovieSelectQualityProfile, ); if let Route::Radarr(active_radarr_block, _) = *app.get_current_route() { @@ -163,7 +163,7 @@ fn draw_edit_movie_confirmation_prompt( "Path", &app.data.radarr_data.edit_path.text, *app.data.radarr_data.edit_path.offset.borrow(), - *selected_block == ActiveRadarrBlock::EditMoviePathInput, + selected_block == ActiveRadarrBlock::EditMoviePathInput, active_radarr_block == ActiveRadarrBlock::EditMoviePathInput, ); draw_text_box_with_label( @@ -172,7 +172,7 @@ fn draw_edit_movie_confirmation_prompt( "Tags", &app.data.radarr_data.edit_tags.text, *app.data.radarr_data.edit_tags.offset.borrow(), - *selected_block == ActiveRadarrBlock::EditMovieTagsInput, + selected_block == ActiveRadarrBlock::EditMovieTagsInput, active_radarr_block == ActiveRadarrBlock::EditMovieTagsInput, ); } @@ -181,12 +181,12 @@ fn draw_edit_movie_confirmation_prompt( f, horizontal_chunks[0], "Save", - *yes_no_value && highlight_yes_no, + yes_no_value && highlight_yes_no, ); draw_button( f, horizontal_chunks[1], "Cancel", - !*yes_no_value && highlight_yes_no, + !yes_no_value && highlight_yes_no, ); } diff --git a/src/ui/radarr_ui/mod.rs b/src/ui/radarr_ui/mod.rs index 2cab7f6..b1a01f6 100644 --- a/src/ui/radarr_ui/mod.rs +++ b/src/ui/radarr_ui/mod.rs @@ -10,7 +10,7 @@ use tui::widgets::{Cell, ListItem, Paragraph, Row}; use tui::Frame; use crate::app::radarr::{ - ActiveRadarrBlock, RadarrData, ADD_MOVIE_BLOCKS, COLLECTION_DETAILS_BLOCKS, + ActiveRadarrBlock, RadarrData, ADD_MOVIE_BLOCKS, COLLECTION_DETAILS_BLOCKS, DELETE_MOVIE_BLOCKS, EDIT_COLLECTION_BLOCKS, EDIT_MOVIE_BLOCKS, FILTER_BLOCKS, MOVIE_DETAILS_BLOCKS, SEARCH_BLOCKS, }; use crate::app::App; @@ -19,6 +19,7 @@ use crate::models::radarr_models::{Collection, DiskSpace, DownloadRecord, Movie, use crate::models::{HorizontallyScrollableText, Route}; use crate::ui::radarr_ui::add_movie_ui::draw_add_movie_search_popup; use crate::ui::radarr_ui::collection_details_ui::draw_collection_details_popup; +use crate::ui::radarr_ui::delete_movie_ui::draw_delete_movie_prompt; use crate::ui::radarr_ui::edit_collection_ui::draw_edit_collection_prompt; use crate::ui::radarr_ui::edit_movie_ui::draw_edit_movie_prompt; use crate::ui::radarr_ui::movie_details_ui::draw_movie_info_popup; @@ -37,6 +38,7 @@ use crate::utils::{convert_runtime, convert_to_gb}; mod add_movie_ui; mod collection_details_ui; +mod delete_movie_ui; mod edit_collection_ui; mod edit_movie_ui; mod movie_details_ui; @@ -150,7 +152,7 @@ pub(super) fn draw_radarr_ui(f: &mut Frame<'_, B>, app: &mut App, ar } } } - ActiveRadarrBlock::DeleteMoviePrompt => { + _ if DELETE_MOVIE_BLOCKS.contains(&active_radarr_block) => { draw_prompt_popup_over(f, app, content_rect, draw_library, draw_delete_movie_prompt) } ActiveRadarrBlock::DeleteDownloadPrompt => draw_prompt_popup_over( @@ -320,7 +322,7 @@ fn draw_update_all_movies_prompt( prompt_area, "Update All Movies", "Do you want to update info and scan your disks for all of your movies?", - &app.data.radarr_data.prompt_confirm, + app.data.radarr_data.prompt_confirm, ); } @@ -334,7 +336,7 @@ fn draw_update_downloads_prompt( prompt_area, "Update Downloads", "Do you want to update your downloads?", - &app.data.radarr_data.prompt_confirm, + app.data.radarr_data.prompt_confirm, ); } @@ -348,21 +350,7 @@ fn draw_update_all_collections_prompt( prompt_area, "Update All Collections", "Do you want to update all of your collections?", - &app.data.radarr_data.prompt_confirm, - ); -} - -fn draw_delete_movie_prompt(f: &mut Frame<'_, B>, app: &mut App, prompt_area: Rect) { - draw_prompt_box( - f, - prompt_area, - "Delete Movie", - format!( - "Do you really want to delete: {}?", - app.data.radarr_data.movies.current_selection().title - ) - .as_str(), - &app.data.radarr_data.prompt_confirm, + app.data.radarr_data.prompt_confirm, ); } @@ -376,7 +364,7 @@ fn draw_delete_download_prompt(f: &mut Frame<'_, B>, app: &mut App, app.data.radarr_data.downloads.current_selection().title ) .as_str(), - &app.data.radarr_data.prompt_confirm, + app.data.radarr_data.prompt_confirm, ); } @@ -394,7 +382,7 @@ fn draw_delete_root_folder_prompt( app.data.radarr_data.root_folders.current_selection().path ) .as_str(), - &app.data.radarr_data.prompt_confirm, + app.data.radarr_data.prompt_confirm, ); } diff --git a/src/ui/radarr_ui/movie_details_ui.rs b/src/ui/radarr_ui/movie_details_ui.rs index 38989d3..8ac93fa 100644 --- a/src/ui/radarr_ui/movie_details_ui.rs +++ b/src/ui/radarr_ui/movie_details_ui.rs @@ -93,7 +93,7 @@ fn draw_search_movie_prompt(f: &mut Frame<'_, B>, app: &mut App, pro app.data.radarr_data.movies.current_selection().title ) .as_str(), - &app.data.radarr_data.prompt_confirm, + app.data.radarr_data.prompt_confirm, ); } @@ -107,7 +107,7 @@ fn draw_update_and_scan_prompt(f: &mut Frame<'_, B>, app: &mut App, app.data.radarr_data.movies.current_selection().title ) .as_str(), - &app.data.radarr_data.prompt_confirm, + app.data.radarr_data.prompt_confirm, ); } @@ -521,7 +521,7 @@ fn draw_manual_search_confirm_prompt( title, &prompt, Some(content_paragraph), - &app.data.radarr_data.prompt_confirm, + app.data.radarr_data.prompt_confirm, ); } else { draw_prompt_box( @@ -529,7 +529,7 @@ fn draw_manual_search_confirm_prompt( prompt_area, title, &prompt, - &app.data.radarr_data.prompt_confirm, + app.data.radarr_data.prompt_confirm, ); } }