From dbcfc77ad43844e080b12b71a27dfae5c512367d Mon Sep 17 00:00:00 2001 From: Alex Clarke Date: Fri, 8 Aug 2025 14:54:28 -0600 Subject: [PATCH] feat: Support toggling Movie monitoring directly from the library view [#43] --- src/app/radarr/radarr_context_clues.rs | 6 +- src/app/radarr/radarr_context_clues_tests.rs | 5 ++ .../library/library_handler_tests.rs | 62 +++++++++++++++++++ src/handlers/radarr_handlers/library/mod.rs | 12 ++++ 4 files changed, 84 insertions(+), 1 deletion(-) diff --git a/src/app/radarr/radarr_context_clues.rs b/src/app/radarr/radarr_context_clues.rs index d35222b..b63cbbb 100644 --- a/src/app/radarr/radarr_context_clues.rs +++ b/src/app/radarr/radarr_context_clues.rs @@ -5,9 +5,13 @@ use crate::app::key_binding::DEFAULT_KEYBINDINGS; #[path = "radarr_context_clues_tests.rs"] mod radarr_context_clues_tests; -pub static LIBRARY_CONTEXT_CLUES: [ContextClue; 10] = [ +pub static LIBRARY_CONTEXT_CLUES: [ContextClue; 11] = [ (DEFAULT_KEYBINDINGS.add, DEFAULT_KEYBINDINGS.add.desc), (DEFAULT_KEYBINDINGS.edit, DEFAULT_KEYBINDINGS.edit.desc), + ( + DEFAULT_KEYBINDINGS.toggle_monitoring, + DEFAULT_KEYBINDINGS.toggle_monitoring.desc, + ), (DEFAULT_KEYBINDINGS.sort, DEFAULT_KEYBINDINGS.sort.desc), (DEFAULT_KEYBINDINGS.delete, DEFAULT_KEYBINDINGS.delete.desc), (DEFAULT_KEYBINDINGS.search, DEFAULT_KEYBINDINGS.search.desc), diff --git a/src/app/radarr/radarr_context_clues_tests.rs b/src/app/radarr/radarr_context_clues_tests.rs index 91c2528..b6fbd19 100644 --- a/src/app/radarr/radarr_context_clues_tests.rs +++ b/src/app/radarr/radarr_context_clues_tests.rs @@ -26,6 +26,11 @@ mod tests { let (key_binding, description) = library_context_clues_iter.next().unwrap(); + assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.toggle_monitoring); + assert_str_eq!(*description, DEFAULT_KEYBINDINGS.toggle_monitoring.desc); + + let (key_binding, description) = library_context_clues_iter.next().unwrap(); + assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.sort); assert_str_eq!(*description, DEFAULT_KEYBINDINGS.sort.desc); diff --git a/src/handlers/radarr_handlers/library/library_handler_tests.rs b/src/handlers/radarr_handlers/library/library_handler_tests.rs index 8667e7a..f6bb55d 100644 --- a/src/handlers/radarr_handlers/library/library_handler_tests.rs +++ b/src/handlers/radarr_handlers/library/library_handler_tests.rs @@ -9,6 +9,7 @@ mod tests { use crate::app::App; use crate::event::Key; use crate::handlers::radarr_handlers::library::{movies_sorting_options, LibraryHandler}; + use crate::handlers::radarr_handlers::radarr_handler_test_utils::utils::movie; use crate::handlers::KeyEventHandler; use crate::models::radarr_models::Movie; use crate::models::servarr_data::radarr::radarr_data::{ @@ -391,6 +392,51 @@ mod tests { assert!(app.data.radarr_data.edit_movie_modal.is_none()); } + #[test] + fn test_toggle_monitoring_key() { + let mut app = App::test_default(); + app.data.radarr_data = create_test_radarr_data(); + app.push_navigation_stack(ActiveRadarrBlock::Movies.into()); + app.is_routing = false; + + LibraryHandler::new( + DEFAULT_KEYBINDINGS.toggle_monitoring.key, + &mut app, + ActiveRadarrBlock::Movies, + None, + ) + .handle(); + + assert_eq!(app.get_current_route(), ActiveRadarrBlock::Movies.into()); + assert!(app.data.radarr_data.prompt_confirm); + assert!(app.is_routing); + assert_eq!( + app.data.radarr_data.prompt_confirm_action, + Some(RadarrEvent::ToggleMovieMonitoring(0)) + ); + } + + #[test] + fn test_toggle_monitoring_key_no_op_when_not_ready() { + let mut app = App::test_default(); + app.is_loading = true; + app.push_navigation_stack(ActiveRadarrBlock::Movies.into()); + app.is_routing = false; + + LibraryHandler::new( + DEFAULT_KEYBINDINGS.toggle_monitoring.key, + &mut app, + ActiveRadarrBlock::Movies, + None, + ) + .handle(); + + assert_eq!(app.get_current_route(), ActiveRadarrBlock::Movies.into()); + assert!(!app.data.radarr_data.prompt_confirm); + assert!(app.data.radarr_data.prompt_confirm_action.is_none()); + assert!(!app.is_routing); + } + #[test] fn test_update_all_movies_key() { let mut app = App::test_default(); @@ -580,6 +626,22 @@ mod tests { ); } + #[test] + fn test_extract_movie_id() { + let mut app = App::test_default(); + app.data.radarr_data.movies.set_items(vec![movie()]); + + let movie_id = LibraryHandler::new( + DEFAULT_KEYBINDINGS.esc.key, + &mut app, + ActiveRadarrBlock::Movies, + None, + ) + .extract_movie_id(); + + assert_eq!(movie_id, 1); + } + #[test] fn test_movies_sorting_options_title() { let expected_cmp_fn: fn(&Movie, &Movie) -> Ordering = |a, b| { diff --git a/src/handlers/radarr_handlers/library/mod.rs b/src/handlers/radarr_handlers/library/mod.rs index 6f83491..3c24f90 100644 --- a/src/handlers/radarr_handlers/library/mod.rs +++ b/src/handlers/radarr_handlers/library/mod.rs @@ -35,6 +35,9 @@ pub(super) struct LibraryHandler<'a, 'b> { impl LibraryHandler<'_, '_> { handle_table_events!(self, movies, self.app.data.radarr_data.movies, Movie); + fn extract_movie_id(&self) -> i64 { + self.app.data.radarr_data.movies.current_selection().id + } } impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for LibraryHandler<'a, 'b> { @@ -183,6 +186,15 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for LibraryHandler<'a, ' self.app.data.radarr_data.add_movie_search = Some(HorizontallyScrollableText::default()); self.app.ignore_special_keys_for_textbox_input = true; } + _ if matches_key!(toggle_monitoring, key) => { + self.app.data.radarr_data.prompt_confirm = true; + self.app.data.radarr_data.prompt_confirm_action = + Some(RadarrEvent::ToggleMovieMonitoring(self.extract_movie_id())); + + self + .app + .pop_and_push_navigation_stack(self.active_radarr_block.into()); + } _ if matches_key!(update, key) => { self .app