Cleaned up the block selection logic to use the new BlockSelectionState struct

This commit is contained in:
2023-08-08 10:50:06 -06:00
parent 2561e7e9b2
commit 4fb83c114a
23 changed files with 840 additions and 882 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "managarr" name = "managarr"
version = "0.0.16" version = "0.0.17"
authors = ["Alex Clarke <alex.j.tusa@gmail.com>"] authors = ["Alex Clarke <alex.j.tusa@gmail.com>"]
description = "A TUI for managing *arr servers" description = "A TUI for managing *arr servers"
keywords = ["managarr", "tui-rs", "dashboard", "servarr"] keywords = ["managarr", "tui-rs", "dashboard", "servarr"]
+15 -15
View File
@@ -14,7 +14,7 @@ pub(crate) mod radarr;
const DEFAULT_ROUTE: Route = Route::Radarr(ActiveRadarrBlock::Movies, None); const DEFAULT_ROUTE: Route = Route::Radarr(ActiveRadarrBlock::Movies, None);
pub struct App { pub struct App<'a> {
navigation_stack: Vec<Route>, navigation_stack: Vec<Route>,
network_tx: Option<Sender<NetworkEvent>>, network_tx: Option<Sender<NetworkEvent>>,
pub server_tabs: TabState, pub server_tabs: TabState,
@@ -31,10 +31,10 @@ pub struct App {
pub should_refresh: bool, pub should_refresh: bool,
pub should_ignore_quit_key: bool, pub should_ignore_quit_key: bool,
pub config: AppConfig, pub config: AppConfig,
pub data: Data, pub data: Data<'a>,
} }
impl App { impl<'a> App<'a> {
pub fn new(network_tx: Sender<NetworkEvent>, config: AppConfig) -> Self { pub fn new(network_tx: Sender<NetworkEvent>, config: AppConfig) -> Self {
App { App {
network_tx: Some(network_tx), network_tx: Some(network_tx),
@@ -106,12 +106,12 @@ impl App {
self.push_navigation_stack(route); self.push_navigation_stack(route);
} }
pub fn get_current_route(&self) -> &Route { pub fn get_current_route(&'a self) -> &'a Route {
self.navigation_stack.last().unwrap_or(&DEFAULT_ROUTE) self.navigation_stack.last().unwrap_or(&DEFAULT_ROUTE)
} }
} }
impl Default for App { impl<'a> Default for App<'a> {
fn default() -> Self { fn default() -> Self {
App { App {
navigation_stack: vec![DEFAULT_ROUTE], navigation_stack: vec![DEFAULT_ROUTE],
@@ -120,15 +120,15 @@ impl Default for App {
response: String::default(), response: String::default(),
server_tabs: TabState::new(vec![ server_tabs: TabState::new(vec![
TabRoute { TabRoute {
title: "Radarr".to_owned(), title: "Radarr",
route: ActiveRadarrBlock::Movies.into(), route: ActiveRadarrBlock::Movies.into(),
help: "<↑↓> scroll | ←→ change tab | <tab> change servarr | <q> quit ".to_owned(), help: "<↑↓> scroll | ←→ change tab | <tab> change servarr | <q> quit ",
contextual_help: None, contextual_help: None,
}, },
TabRoute { TabRoute {
title: "Sonarr".to_owned(), title: "Sonarr",
route: Route::Sonarr, route: Route::Sonarr,
help: "<tab> change servarr | <q> quit ".to_owned(), help: "<tab> change servarr | <q> quit ",
contextual_help: None, contextual_help: None,
}, },
]), ]),
@@ -149,8 +149,8 @@ impl Default for App {
} }
#[derive(Default)] #[derive(Default)]
pub struct Data { pub struct Data<'a> {
pub radarr_data: RadarrData, pub radarr_data: RadarrData<'a>,
} }
#[derive(Debug, Deserialize, Serialize, Default)] #[derive(Debug, Deserialize, Serialize, Default)]
@@ -200,15 +200,15 @@ mod tests {
app.server_tabs.tabs, app.server_tabs.tabs,
vec![ vec![
TabRoute { TabRoute {
title: "Radarr".to_owned(), title: "Radarr",
route: ActiveRadarrBlock::Movies.into(), route: ActiveRadarrBlock::Movies.into(),
help: "<↑↓> scroll | ←→ change tab | <tab> change servarr | <q> quit ".to_owned(), help: "<↑↓> scroll | ←→ change tab | <tab> change servarr | <q> quit ",
contextual_help: None, contextual_help: None,
}, },
TabRoute { TabRoute {
title: "Sonarr".to_owned(), title: "Sonarr",
route: Route::Sonarr, route: Route::Sonarr,
help: "<tab> change servarr | <q> quit ".to_owned(), help: "<tab> change servarr | <q> quit ",
contextual_help: None, contextual_help: None,
} }
] ]
+165 -404
View File
@@ -8,11 +8,12 @@ use crate::models::radarr_models::{
MinimumAvailability, Monitor, Movie, MovieHistoryItem, Release, ReleaseField, RootFolder, MinimumAvailability, Monitor, Movie, MovieHistoryItem, Release, ReleaseField, RootFolder,
}; };
use crate::models::{ use crate::models::{
HorizontallyScrollableText, ScrollableText, StatefulList, StatefulTable, TabRoute, TabState, BlockSelectionState, HorizontallyScrollableText, ScrollableText, StatefulList, StatefulTable,
TabRoute, TabState,
}; };
use crate::network::radarr_network::RadarrEvent; use crate::network::radarr_network::RadarrEvent;
pub struct RadarrData { pub struct RadarrData<'a> {
pub root_folders: StatefulTable<RootFolder>, pub root_folders: StatefulTable<RootFolder>,
pub disk_space_vec: Vec<DiskSpace>, pub disk_space_vec: Vec<DiskSpace>,
pub version: String, pub version: String,
@@ -24,7 +25,7 @@ pub struct RadarrData {
pub minimum_availability_list: StatefulList<MinimumAvailability>, pub minimum_availability_list: StatefulList<MinimumAvailability>,
pub quality_profile_list: StatefulList<String>, pub quality_profile_list: StatefulList<String>,
pub root_folder_list: StatefulList<RootFolder>, pub root_folder_list: StatefulList<RootFolder>,
pub selected_block: ActiveRadarrBlock, pub selected_block: BlockSelectionState<'a, ActiveRadarrBlock>,
pub downloads: StatefulTable<DownloadRecord>, pub downloads: StatefulTable<DownloadRecord>,
pub quality_profile_map: BiMap<u64, String>, pub quality_profile_map: BiMap<u64, String>,
pub tags_map: BiMap<u64, String>, pub tags_map: BiMap<u64, String>,
@@ -57,7 +58,7 @@ pub struct RadarrData {
pub is_filtering: bool, pub is_filtering: bool,
} }
impl RadarrData { impl<'a> RadarrData<'a> {
pub fn reset_movie_collection_table(&mut self) { pub fn reset_movie_collection_table(&mut self) {
self.collection_movies = StatefulTable::default(); self.collection_movies = StatefulTable::default();
} }
@@ -226,8 +227,8 @@ impl RadarrData {
} }
} }
impl Default for RadarrData { impl<'a> Default for RadarrData<'a> {
fn default() -> RadarrData { fn default() -> RadarrData<'a> {
RadarrData { RadarrData {
root_folders: StatefulTable::default(), root_folders: StatefulTable::default(),
disk_space_vec: Vec::new(), disk_space_vec: Vec::new(),
@@ -239,7 +240,7 @@ impl Default for RadarrData {
minimum_availability_list: StatefulList::default(), minimum_availability_list: StatefulList::default(),
quality_profile_list: StatefulList::default(), quality_profile_list: StatefulList::default(),
root_folder_list: StatefulList::default(), root_folder_list: StatefulList::default(),
selected_block: ActiveRadarrBlock::AddMovieSelectRootFolder, selected_block: BlockSelectionState::default(),
filtered_movies: StatefulTable::default(), filtered_movies: StatefulTable::default(),
downloads: StatefulTable::default(), downloads: StatefulTable::default(),
quality_profile_map: BiMap::default(), quality_profile_map: BiMap::default(),
@@ -271,75 +272,79 @@ impl Default for RadarrData {
add_list_exclusion: false, add_list_exclusion: false,
main_tabs: TabState::new(vec![ main_tabs: TabState::new(vec![
TabRoute { TabRoute {
title: "Library".to_owned(), title: "Library",
route: ActiveRadarrBlock::Movies.into(), route: ActiveRadarrBlock::Movies.into(),
help: String::default(), help: "",
contextual_help: Some("<a> add | <e> edit | <del> delete | <s> search | <f> filter | <r> refresh | <u> update all | <enter> details | <esc> cancel filter" contextual_help: Some("<a> add | <e> edit | <del> delete | <s> search | <f> filter | <r> refresh | <u> update all | <enter> details | <esc> cancel filter"),
.to_owned()),
}, },
TabRoute { TabRoute {
title: "Downloads".to_owned(), title: "Downloads",
route: ActiveRadarrBlock::Downloads.into(), route: ActiveRadarrBlock::Downloads.into(),
help: String::default(), help: "",
contextual_help: Some("<r> refresh | <del> delete".to_owned()), contextual_help: Some("<r> refresh | <del> delete"),
}, },
TabRoute { TabRoute {
title: "Collections".to_owned(), title: "Collections",
route: ActiveRadarrBlock::Collections.into(), route: ActiveRadarrBlock::Collections.into(),
help: String::default(), help: "",
contextual_help: Some("<s> search | <e> edit | <f> filter | <r> refresh | <u> update all | <enter> details | <esc> cancel filter" contextual_help: Some("<s> search | <e> edit | <f> filter | <r> refresh | <u> update all | <enter> details | <esc> cancel filter"),
.to_owned()),
}, },
TabRoute { TabRoute {
title: "Root Folders".to_owned(), title: "Root Folders",
route: ActiveRadarrBlock::RootFolders.into(), route: ActiveRadarrBlock::RootFolders.into(),
help: String::default(), help: "",
contextual_help: Some("<a> add | <del> delete | <r> refresh".to_owned()), contextual_help: Some("<a> add | <del> delete | <r> refresh"),
}, },
TabRoute {
title: "System",
route: ActiveRadarrBlock::System.into(),
help: "",
contextual_help: Some("<enter> select menu item | <esc> go back to menu selection")
}
]), ]),
movie_info_tabs: TabState::new(vec![ movie_info_tabs: TabState::new(vec![
TabRoute { TabRoute {
title: "Details".to_owned(), title: "Details",
route: ActiveRadarrBlock::MovieDetails.into(), route: ActiveRadarrBlock::MovieDetails.into(),
help: "<r> refresh | <u> update | <e> edit | <s> auto search | <esc> close".to_owned(), help: "<r> refresh | <u> update | <e> edit | <s> auto search | <esc> close",
contextual_help: None contextual_help: None
}, },
TabRoute { TabRoute {
title: "History".to_owned(), title: "History",
route: ActiveRadarrBlock::MovieHistory.into(), route: ActiveRadarrBlock::MovieHistory.into(),
help: "<r> refresh | <u> update | <e> edit | <s> auto search | <esc> close".to_owned(), help: "<r> refresh | <u> update | <e> edit | <s> auto search | <esc> close",
contextual_help: None contextual_help: None
}, },
TabRoute { TabRoute {
title: "File".to_owned(), title: "File",
route: ActiveRadarrBlock::FileInfo.into(), route: ActiveRadarrBlock::FileInfo.into(),
help: "<r> refresh | <u> update | <e> edit | <s> auto search | <esc> close".to_owned(), help: "<r> refresh | <u> update | <e> edit | <s> auto search | <esc> close",
contextual_help: None, contextual_help: None,
}, },
TabRoute { TabRoute {
title: "Cast".to_owned(), title: "Cast",
route: ActiveRadarrBlock::Cast.into(), route: ActiveRadarrBlock::Cast.into(),
help: "<r> refresh | <u> update | <e> edit | <s> auto search | <esc> close".to_owned(), help: "<r> refresh | <u> update | <e> edit | <s> auto search | <esc> close",
contextual_help: None, contextual_help: None,
}, },
TabRoute { TabRoute {
title: "Crew".to_owned(), title: "Crew",
route: ActiveRadarrBlock::Crew.into(), route: ActiveRadarrBlock::Crew.into(),
help: "<r> refresh | <u> update | <e> edit | <s> auto search | <esc> close".to_owned(), help: "<r> refresh | <u> update | <e> edit | <s> auto search | <esc> close",
contextual_help: None, contextual_help: None,
}, },
TabRoute { TabRoute {
title: "Manual Search".to_owned(), title: "Manual Search",
route: ActiveRadarrBlock::ManualSearch.into(), route: ActiveRadarrBlock::ManualSearch.into(),
help: "<r> refresh | <u> update | <e> edit | <o> sort | <s> auto search | <esc> close".to_owned(), help: "<r> refresh | <u> update | <e> edit | <o> sort | <s> auto search | <esc> close",
contextual_help: Some("<enter> details".to_owned()) contextual_help: Some("<enter> details")
} }
]), ]),
} }
} }
} }
#[derive(Clone, Copy, PartialEq, Eq, Debug)] #[derive(Clone, Copy, PartialEq, Eq, Debug, Default)]
pub enum ActiveRadarrBlock { pub enum ActiveRadarrBlock {
AddMovieAlreadyInLibrary, AddMovieAlreadyInLibrary,
AddMovieSearchInput, AddMovieSearchInput,
@@ -387,8 +392,10 @@ pub enum ActiveRadarrBlock {
ManualSearchConfirmPrompt, ManualSearchConfirmPrompt,
MovieDetails, MovieDetails,
MovieHistory, MovieHistory,
#[default]
Movies, Movies,
RootFolders, RootFolders,
System,
UpdateAndScanPrompt, UpdateAndScanPrompt,
UpdateAllCollectionsPrompt, UpdateAllCollectionsPrompt,
UpdateAllMoviesPrompt, UpdateAllMoviesPrompt,
@@ -410,6 +417,14 @@ pub const ADD_MOVIE_BLOCKS: [ActiveRadarrBlock; 10] = [
ActiveRadarrBlock::AddMovieAlreadyInLibrary, ActiveRadarrBlock::AddMovieAlreadyInLibrary,
ActiveRadarrBlock::AddMovieTagsInput, ActiveRadarrBlock::AddMovieTagsInput,
]; ];
pub const ADD_MOVIE_SELECTION_BLOCKS: [ActiveRadarrBlock; 6] = [
ActiveRadarrBlock::AddMovieSelectRootFolder,
ActiveRadarrBlock::AddMovieSelectMonitor,
ActiveRadarrBlock::AddMovieSelectMinimumAvailability,
ActiveRadarrBlock::AddMovieSelectQualityProfile,
ActiveRadarrBlock::AddMovieTagsInput,
ActiveRadarrBlock::AddMovieConfirmPrompt,
];
pub const EDIT_COLLECTION_BLOCKS: [ActiveRadarrBlock; 7] = [ pub const EDIT_COLLECTION_BLOCKS: [ActiveRadarrBlock; 7] = [
ActiveRadarrBlock::EditCollectionPrompt, ActiveRadarrBlock::EditCollectionPrompt,
ActiveRadarrBlock::EditCollectionConfirmPrompt, ActiveRadarrBlock::EditCollectionConfirmPrompt,
@@ -419,6 +434,14 @@ pub const EDIT_COLLECTION_BLOCKS: [ActiveRadarrBlock; 7] = [
ActiveRadarrBlock::EditCollectionToggleSearchOnAdd, ActiveRadarrBlock::EditCollectionToggleSearchOnAdd,
ActiveRadarrBlock::EditCollectionToggleMonitored, ActiveRadarrBlock::EditCollectionToggleMonitored,
]; ];
pub const EDIT_COLLECTION_SELECTION_BLOCKS: [ActiveRadarrBlock; 6] = [
ActiveRadarrBlock::EditCollectionToggleMonitored,
ActiveRadarrBlock::EditCollectionSelectMinimumAvailability,
ActiveRadarrBlock::EditCollectionSelectQualityProfile,
ActiveRadarrBlock::EditCollectionRootFolderPathInput,
ActiveRadarrBlock::EditCollectionToggleSearchOnAdd,
ActiveRadarrBlock::EditCollectionConfirmPrompt,
];
pub const EDIT_MOVIE_BLOCKS: [ActiveRadarrBlock; 7] = [ pub const EDIT_MOVIE_BLOCKS: [ActiveRadarrBlock; 7] = [
ActiveRadarrBlock::EditMoviePrompt, ActiveRadarrBlock::EditMoviePrompt,
ActiveRadarrBlock::EditMovieConfirmPrompt, ActiveRadarrBlock::EditMovieConfirmPrompt,
@@ -428,6 +451,14 @@ pub const EDIT_MOVIE_BLOCKS: [ActiveRadarrBlock; 7] = [
ActiveRadarrBlock::EditMovieTagsInput, ActiveRadarrBlock::EditMovieTagsInput,
ActiveRadarrBlock::EditMovieToggleMonitored, ActiveRadarrBlock::EditMovieToggleMonitored,
]; ];
pub const EDIT_MOVIE_SELECTION_BLOCKS: [ActiveRadarrBlock; 6] = [
ActiveRadarrBlock::EditMovieToggleMonitored,
ActiveRadarrBlock::EditMovieSelectMinimumAvailability,
ActiveRadarrBlock::EditMovieSelectQualityProfile,
ActiveRadarrBlock::EditMoviePathInput,
ActiveRadarrBlock::EditMovieTagsInput,
ActiveRadarrBlock::EditMovieConfirmPrompt,
];
pub const MOVIE_DETAILS_BLOCKS: [ActiveRadarrBlock; 10] = [ pub const MOVIE_DETAILS_BLOCKS: [ActiveRadarrBlock; 10] = [
ActiveRadarrBlock::MovieDetails, ActiveRadarrBlock::MovieDetails,
ActiveRadarrBlock::MovieHistory, ActiveRadarrBlock::MovieHistory,
@@ -458,141 +489,11 @@ pub const DELETE_MOVIE_BLOCKS: [ActiveRadarrBlock; 4] = [
ActiveRadarrBlock::DeleteMovieToggleDeleteFile, ActiveRadarrBlock::DeleteMovieToggleDeleteFile,
ActiveRadarrBlock::DeleteMovieToggleAddListExclusion, ActiveRadarrBlock::DeleteMovieToggleAddListExclusion,
]; ];
pub const DELETE_MOVIE_SELECTION_BLOCKS: [ActiveRadarrBlock; 3] = [
impl ActiveRadarrBlock { ActiveRadarrBlock::DeleteMovieToggleDeleteFile,
pub fn next_add_movie_prompt_block(&self) -> Self { ActiveRadarrBlock::DeleteMovieToggleAddListExclusion,
match self { ActiveRadarrBlock::DeleteMovieConfirmPrompt,
ActiveRadarrBlock::AddMovieSelectRootFolder => ActiveRadarrBlock::AddMovieSelectMonitor, ];
ActiveRadarrBlock::AddMovieSelectMonitor => {
ActiveRadarrBlock::AddMovieSelectMinimumAvailability
}
ActiveRadarrBlock::AddMovieSelectMinimumAvailability => {
ActiveRadarrBlock::AddMovieSelectQualityProfile
}
ActiveRadarrBlock::AddMovieSelectQualityProfile => ActiveRadarrBlock::AddMovieTagsInput,
ActiveRadarrBlock::AddMovieTagsInput => ActiveRadarrBlock::AddMovieConfirmPrompt,
_ => ActiveRadarrBlock::AddMovieSelectRootFolder,
}
}
pub fn next_edit_movie_prompt_block(&self) -> Self {
match self {
ActiveRadarrBlock::EditMovieToggleMonitored => {
ActiveRadarrBlock::EditMovieSelectMinimumAvailability
}
ActiveRadarrBlock::EditMovieSelectMinimumAvailability => {
ActiveRadarrBlock::EditMovieSelectQualityProfile
}
ActiveRadarrBlock::EditMovieSelectQualityProfile => ActiveRadarrBlock::EditMoviePathInput,
ActiveRadarrBlock::EditMoviePathInput => ActiveRadarrBlock::EditMovieTagsInput,
ActiveRadarrBlock::EditMovieTagsInput => ActiveRadarrBlock::EditMovieConfirmPrompt,
_ => ActiveRadarrBlock::EditMovieToggleMonitored,
}
}
pub fn next_edit_collection_prompt_block(&self) -> Self {
match self {
ActiveRadarrBlock::EditCollectionToggleMonitored => {
ActiveRadarrBlock::EditCollectionSelectMinimumAvailability
}
ActiveRadarrBlock::EditCollectionSelectMinimumAvailability => {
ActiveRadarrBlock::EditCollectionSelectQualityProfile
}
ActiveRadarrBlock::EditCollectionSelectQualityProfile => {
ActiveRadarrBlock::EditCollectionRootFolderPathInput
}
ActiveRadarrBlock::EditCollectionRootFolderPathInput => {
ActiveRadarrBlock::EditCollectionToggleSearchOnAdd
}
ActiveRadarrBlock::EditCollectionToggleSearchOnAdd => {
ActiveRadarrBlock::EditCollectionConfirmPrompt
}
_ => ActiveRadarrBlock::EditCollectionToggleMonitored,
}
}
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,
ActiveRadarrBlock::AddMovieSelectMonitor => ActiveRadarrBlock::AddMovieSelectRootFolder,
ActiveRadarrBlock::AddMovieSelectMinimumAvailability => {
ActiveRadarrBlock::AddMovieSelectMonitor
}
ActiveRadarrBlock::AddMovieSelectQualityProfile => {
ActiveRadarrBlock::AddMovieSelectMinimumAvailability
}
ActiveRadarrBlock::AddMovieTagsInput => ActiveRadarrBlock::AddMovieSelectQualityProfile,
ActiveRadarrBlock::AddMovieConfirmPrompt => ActiveRadarrBlock::AddMovieTagsInput,
_ => ActiveRadarrBlock::AddMovieSelectRootFolder,
}
}
pub fn previous_edit_movie_prompt_block(&self) -> Self {
match self {
ActiveRadarrBlock::EditMovieToggleMonitored => ActiveRadarrBlock::EditMovieConfirmPrompt,
ActiveRadarrBlock::EditMovieSelectMinimumAvailability => {
ActiveRadarrBlock::EditMovieToggleMonitored
}
ActiveRadarrBlock::EditMovieSelectQualityProfile => {
ActiveRadarrBlock::EditMovieSelectMinimumAvailability
}
ActiveRadarrBlock::EditMoviePathInput => ActiveRadarrBlock::EditMovieSelectQualityProfile,
ActiveRadarrBlock::EditMovieTagsInput => ActiveRadarrBlock::EditMoviePathInput,
ActiveRadarrBlock::EditMovieConfirmPrompt => ActiveRadarrBlock::EditMovieTagsInput,
_ => ActiveRadarrBlock::EditMovieToggleMonitored,
}
}
pub fn previous_edit_collection_prompt_block(&self) -> Self {
match self {
ActiveRadarrBlock::EditCollectionToggleMonitored => {
ActiveRadarrBlock::EditCollectionConfirmPrompt
}
ActiveRadarrBlock::EditCollectionSelectMinimumAvailability => {
ActiveRadarrBlock::EditCollectionToggleMonitored
}
ActiveRadarrBlock::EditCollectionSelectQualityProfile => {
ActiveRadarrBlock::EditCollectionSelectMinimumAvailability
}
ActiveRadarrBlock::EditCollectionRootFolderPathInput => {
ActiveRadarrBlock::EditCollectionSelectQualityProfile
}
ActiveRadarrBlock::EditCollectionToggleSearchOnAdd => {
ActiveRadarrBlock::EditCollectionRootFolderPathInput
}
ActiveRadarrBlock::EditCollectionConfirmPrompt => {
ActiveRadarrBlock::EditCollectionToggleSearchOnAdd
}
_ => 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<ActiveRadarrBlock> for Route { impl From<ActiveRadarrBlock> for Route {
fn from(active_radarr_block: ActiveRadarrBlock) -> Route { fn from(active_radarr_block: ActiveRadarrBlock) -> Route {
@@ -606,7 +507,7 @@ impl From<(ActiveRadarrBlock, Option<ActiveRadarrBlock>)> for Route {
} }
} }
impl App { impl<'a> App<'a> {
pub(super) async fn dispatch_by_radarr_block(&mut self, active_radarr_block: &ActiveRadarrBlock) { pub(super) async fn dispatch_by_radarr_block(&mut self, active_radarr_block: &ActiveRadarrBlock) {
match active_radarr_block { match active_radarr_block {
ActiveRadarrBlock::Collections => { ActiveRadarrBlock::Collections => {
@@ -773,7 +674,7 @@ pub mod radarr_test_utils {
}; };
use crate::models::ScrollableText; use crate::models::ScrollableText;
pub fn create_test_radarr_data() -> RadarrData { pub fn create_test_radarr_data<'a>() -> RadarrData<'a> {
let mut radarr_data = RadarrData { let mut radarr_data = RadarrData {
is_searching: true, is_searching: true,
is_filtering: true, is_filtering: true,
@@ -905,9 +806,9 @@ mod tests {
use crate::models::radarr_models::{ use crate::models::radarr_models::{
Collection, MinimumAvailability, Monitor, Movie, RootFolder, Collection, MinimumAvailability, Monitor, Movie, RootFolder,
}; };
use crate::models::HorizontallyScrollableText;
use crate::models::Route; use crate::models::Route;
use crate::models::StatefulTable; use crate::models::StatefulTable;
use crate::models::{BlockSelectionState, HorizontallyScrollableText};
#[test] #[test]
fn test_from_tuple_to_route_with_context() { fn test_from_tuple_to_route_with_context() {
@@ -1149,10 +1050,7 @@ mod tests {
assert!(radarr_data.minimum_availability_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.quality_profile_list.items.is_empty());
assert!(radarr_data.root_folder_list.items.is_empty()); assert!(radarr_data.root_folder_list.items.is_empty());
assert_eq!( assert_eq!(radarr_data.selected_block, BlockSelectionState::default());
radarr_data.selected_block,
ActiveRadarrBlock::AddMovieSelectRootFolder
);
assert!(radarr_data.filtered_movies.items.is_empty()); assert!(radarr_data.filtered_movies.items.is_empty());
assert!(radarr_data.downloads.items.is_empty()); assert!(radarr_data.downloads.items.is_empty());
assert!(radarr_data.quality_profile_map.is_empty()); assert!(radarr_data.quality_profile_map.is_empty());
@@ -1183,7 +1081,7 @@ mod tests {
assert!(!radarr_data.delete_movie_files); assert!(!radarr_data.delete_movie_files);
assert!(!radarr_data.add_list_exclusion); assert!(!radarr_data.add_list_exclusion);
assert_eq!(radarr_data.main_tabs.tabs.len(), 4); assert_eq!(radarr_data.main_tabs.tabs.len(), 5);
assert_str_eq!(radarr_data.main_tabs.tabs[0].title, "Library"); assert_str_eq!(radarr_data.main_tabs.tabs[0].title, "Library");
assert_eq!( assert_eq!(
@@ -1192,7 +1090,7 @@ mod tests {
); );
assert!(radarr_data.main_tabs.tabs[0].help.is_empty()); assert!(radarr_data.main_tabs.tabs[0].help.is_empty());
assert_eq!(radarr_data.main_tabs.tabs[0].contextual_help, assert_eq!(radarr_data.main_tabs.tabs[0].contextual_help,
Some("<a> add | <e> edit | <del> delete | <s> search | <f> filter | <r> refresh | <u> update all | <enter> details | <esc> cancel filter".to_owned())); Some("<a> add | <e> edit | <del> delete | <s> search | <f> filter | <r> refresh | <u> update all | <enter> details | <esc> cancel filter"));
assert_str_eq!(radarr_data.main_tabs.tabs[1].title, "Downloads"); assert_str_eq!(radarr_data.main_tabs.tabs[1].title, "Downloads");
assert_eq!( assert_eq!(
@@ -1202,7 +1100,7 @@ mod tests {
assert!(radarr_data.main_tabs.tabs[1].help.is_empty()); assert!(radarr_data.main_tabs.tabs[1].help.is_empty());
assert_eq!( assert_eq!(
radarr_data.main_tabs.tabs[1].contextual_help, radarr_data.main_tabs.tabs[1].contextual_help,
Some("<r> refresh | <del> delete".to_owned()) Some("<r> refresh | <del> delete")
); );
assert_str_eq!(radarr_data.main_tabs.tabs[2].title, "Collections"); assert_str_eq!(radarr_data.main_tabs.tabs[2].title, "Collections");
@@ -1212,7 +1110,7 @@ mod tests {
); );
assert!(radarr_data.main_tabs.tabs[2].help.is_empty()); assert!(radarr_data.main_tabs.tabs[2].help.is_empty());
assert_eq!(radarr_data.main_tabs.tabs[2].contextual_help, assert_eq!(radarr_data.main_tabs.tabs[2].contextual_help,
Some("<s> search | <e> edit | <f> filter | <r> refresh | <u> update all | <enter> details | <esc> cancel filter".to_owned())); Some("<s> search | <e> edit | <f> filter | <r> refresh | <u> update all | <enter> details | <esc> cancel filter"));
assert_str_eq!(radarr_data.main_tabs.tabs[3].title, "Root Folders"); assert_str_eq!(radarr_data.main_tabs.tabs[3].title, "Root Folders");
assert_eq!( assert_eq!(
@@ -1222,7 +1120,18 @@ mod tests {
assert!(radarr_data.main_tabs.tabs[3].help.is_empty()); assert!(radarr_data.main_tabs.tabs[3].help.is_empty());
assert_eq!( assert_eq!(
radarr_data.main_tabs.tabs[3].contextual_help, radarr_data.main_tabs.tabs[3].contextual_help,
Some("<a> add | <del> delete | <r> refresh".to_owned()) Some("<a> add | <del> delete | <r> refresh")
);
assert_str_eq!(radarr_data.main_tabs.tabs[4].title, "System");
assert_eq!(
radarr_data.main_tabs.tabs[4].route,
ActiveRadarrBlock::System.into()
);
assert!(radarr_data.main_tabs.tabs[4].help.is_empty());
assert_eq!(
radarr_data.main_tabs.tabs[4].contextual_help,
Some("<enter> select menu item | <esc> go back to menu selection")
); );
assert_eq!(radarr_data.movie_info_tabs.tabs.len(), 6); assert_eq!(radarr_data.movie_info_tabs.tabs.len(), 6);
@@ -1303,7 +1212,7 @@ mod tests {
); );
assert_eq!( assert_eq!(
radarr_data.movie_info_tabs.tabs[5].contextual_help, radarr_data.movie_info_tabs.tabs[5].contextual_help,
Some("<enter> details".to_owned()) Some("<enter> details")
); );
} }
} }
@@ -1311,264 +1220,116 @@ mod tests {
mod active_radarr_block_tests { mod active_radarr_block_tests {
use pretty_assertions::assert_eq; use pretty_assertions::assert_eq;
use crate::app::radarr::ActiveRadarrBlock; use crate::app::radarr::{
ActiveRadarrBlock, ADD_MOVIE_SELECTION_BLOCKS, DELETE_MOVIE_SELECTION_BLOCKS,
EDIT_COLLECTION_SELECTION_BLOCKS, EDIT_MOVIE_SELECTION_BLOCKS,
};
#[test] #[test]
fn test_next_add_movie_prompt_block() { fn test_add_movie_prompt_block_order() {
let active_block = ActiveRadarrBlock::AddMovieSelectRootFolder.next_add_movie_prompt_block(); let mut add_movie_block_iter = ADD_MOVIE_SELECTION_BLOCKS.iter();
assert_eq!(active_block, ActiveRadarrBlock::AddMovieSelectMonitor);
let active_block = active_block.next_add_movie_prompt_block();
assert_eq!( assert_eq!(
active_block, add_movie_block_iter.next().unwrap(),
ActiveRadarrBlock::AddMovieSelectMinimumAvailability &ActiveRadarrBlock::AddMovieSelectRootFolder
); );
let active_block = active_block.next_add_movie_prompt_block();
assert_eq!( assert_eq!(
active_block, add_movie_block_iter.next().unwrap(),
ActiveRadarrBlock::AddMovieSelectQualityProfile &ActiveRadarrBlock::AddMovieSelectMonitor
); );
let active_block = active_block.next_add_movie_prompt_block();
assert_eq!(active_block, ActiveRadarrBlock::AddMovieTagsInput);
let active_block = active_block.next_add_movie_prompt_block();
assert_eq!(active_block, ActiveRadarrBlock::AddMovieConfirmPrompt);
let active_block = active_block.next_add_movie_prompt_block();
assert_eq!(active_block, ActiveRadarrBlock::AddMovieSelectRootFolder);
}
#[test]
fn test_next_edit_movie_prompt_block() {
let active_block = ActiveRadarrBlock::EditMovieToggleMonitored.next_edit_movie_prompt_block();
assert_eq!( assert_eq!(
active_block, add_movie_block_iter.next().unwrap(),
ActiveRadarrBlock::EditMovieSelectMinimumAvailability &ActiveRadarrBlock::AddMovieSelectMinimumAvailability
); );
let active_block = active_block.next_edit_movie_prompt_block();
assert_eq!( assert_eq!(
active_block, add_movie_block_iter.next().unwrap(),
ActiveRadarrBlock::EditMovieSelectQualityProfile &ActiveRadarrBlock::AddMovieSelectQualityProfile
); );
let active_block = active_block.next_edit_movie_prompt_block();
assert_eq!(active_block, ActiveRadarrBlock::EditMoviePathInput);
let active_block = active_block.next_edit_movie_prompt_block();
assert_eq!(active_block, ActiveRadarrBlock::EditMovieTagsInput);
let active_block = active_block.next_edit_movie_prompt_block();
assert_eq!(active_block, ActiveRadarrBlock::EditMovieConfirmPrompt);
let active_block = active_block.next_edit_movie_prompt_block();
assert_eq!(active_block, ActiveRadarrBlock::EditMovieToggleMonitored);
}
#[test]
fn test_next_edit_collection_prompt_block() {
let active_block =
ActiveRadarrBlock::EditCollectionToggleMonitored.next_edit_collection_prompt_block();
assert_eq!( assert_eq!(
active_block, add_movie_block_iter.next().unwrap(),
ActiveRadarrBlock::EditCollectionSelectMinimumAvailability &ActiveRadarrBlock::AddMovieTagsInput
); );
let active_block = active_block.next_edit_collection_prompt_block();
assert_eq!( assert_eq!(
active_block, add_movie_block_iter.next().unwrap(),
ActiveRadarrBlock::EditCollectionSelectQualityProfile &ActiveRadarrBlock::AddMovieConfirmPrompt
);
let active_block = active_block.next_edit_collection_prompt_block();
assert_eq!(
active_block,
ActiveRadarrBlock::EditCollectionRootFolderPathInput
);
let active_block = active_block.next_edit_collection_prompt_block();
assert_eq!(
active_block,
ActiveRadarrBlock::EditCollectionToggleSearchOnAdd
);
let active_block = active_block.next_edit_collection_prompt_block();
assert_eq!(active_block, ActiveRadarrBlock::EditCollectionConfirmPrompt);
let active_block = active_block.next_edit_collection_prompt_block();
assert_eq!(
active_block,
ActiveRadarrBlock::EditCollectionToggleMonitored
); );
} }
#[test] #[test]
fn test_next_delete_movie_prompt_block() { fn test_edit_movie_prompt_block_order() {
let active_block = let mut edit_movie_block_iter = EDIT_MOVIE_SELECTION_BLOCKS.iter();
ActiveRadarrBlock::DeleteMovieToggleDeleteFile.next_delete_movie_prompt_block();
assert_eq!( assert_eq!(
active_block, edit_movie_block_iter.next().unwrap(),
ActiveRadarrBlock::DeleteMovieToggleAddListExclusion &ActiveRadarrBlock::EditMovieToggleMonitored
); );
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 =
ActiveRadarrBlock::AddMovieSelectRootFolder.previous_add_movie_prompt_block();
assert_eq!(active_block, ActiveRadarrBlock::AddMovieConfirmPrompt);
let active_block = active_block.previous_add_movie_prompt_block();
assert_eq!(active_block, ActiveRadarrBlock::AddMovieTagsInput);
let active_block = active_block.previous_add_movie_prompt_block();
assert_eq!( assert_eq!(
active_block, edit_movie_block_iter.next().unwrap(),
ActiveRadarrBlock::AddMovieSelectQualityProfile &ActiveRadarrBlock::EditMovieSelectMinimumAvailability
); );
let active_block = active_block.previous_add_movie_prompt_block();
assert_eq!( assert_eq!(
active_block, edit_movie_block_iter.next().unwrap(),
ActiveRadarrBlock::AddMovieSelectMinimumAvailability &ActiveRadarrBlock::EditMovieSelectQualityProfile
); );
let active_block = active_block.previous_add_movie_prompt_block();
assert_eq!(active_block, ActiveRadarrBlock::AddMovieSelectMonitor);
let active_block = active_block.previous_add_movie_prompt_block();
assert_eq!(active_block, ActiveRadarrBlock::AddMovieSelectRootFolder);
}
#[test]
fn test_previous_edit_movie_prompt_block() {
let active_block =
ActiveRadarrBlock::EditMovieToggleMonitored.previous_edit_movie_prompt_block();
assert_eq!(active_block, ActiveRadarrBlock::EditMovieConfirmPrompt);
let active_block = active_block.previous_edit_movie_prompt_block();
assert_eq!(active_block, ActiveRadarrBlock::EditMovieTagsInput);
let active_block = active_block.previous_edit_movie_prompt_block();
assert_eq!(active_block, ActiveRadarrBlock::EditMoviePathInput);
let active_block = active_block.previous_edit_movie_prompt_block();
assert_eq!( assert_eq!(
active_block, edit_movie_block_iter.next().unwrap(),
ActiveRadarrBlock::EditMovieSelectQualityProfile &ActiveRadarrBlock::EditMoviePathInput
); );
let active_block = active_block.previous_edit_movie_prompt_block();
assert_eq!( assert_eq!(
active_block, edit_movie_block_iter.next().unwrap(),
ActiveRadarrBlock::EditMovieSelectMinimumAvailability &ActiveRadarrBlock::EditMovieTagsInput
); );
let active_block = active_block.previous_edit_movie_prompt_block();
assert_eq!(active_block, ActiveRadarrBlock::EditMovieToggleMonitored);
}
#[test]
fn test_previous_edit_collection_prompt_block() {
let active_block =
ActiveRadarrBlock::EditCollectionToggleMonitored.previous_edit_collection_prompt_block();
assert_eq!(active_block, ActiveRadarrBlock::EditCollectionConfirmPrompt);
let active_block = active_block.previous_edit_collection_prompt_block();
assert_eq!( assert_eq!(
active_block, edit_movie_block_iter.next().unwrap(),
ActiveRadarrBlock::EditCollectionToggleSearchOnAdd &ActiveRadarrBlock::EditMovieConfirmPrompt
);
let active_block = active_block.previous_edit_collection_prompt_block();
assert_eq!(
active_block,
ActiveRadarrBlock::EditCollectionRootFolderPathInput
);
let active_block = active_block.previous_edit_collection_prompt_block();
assert_eq!(
active_block,
ActiveRadarrBlock::EditCollectionSelectQualityProfile
);
let active_block = active_block.previous_edit_collection_prompt_block();
assert_eq!(
active_block,
ActiveRadarrBlock::EditCollectionSelectMinimumAvailability
);
let active_block = active_block.previous_edit_collection_prompt_block();
assert_eq!(
active_block,
ActiveRadarrBlock::EditCollectionToggleMonitored
); );
} }
#[test] #[test]
fn test_previous_delete_movie_prompt_block() { fn test_edit_collection_prompt_block_order() {
let active_block = let mut edit_collection_block_iter = EDIT_COLLECTION_SELECTION_BLOCKS.iter();
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!( assert_eq!(
active_block, edit_collection_block_iter.next().unwrap(),
ActiveRadarrBlock::DeleteMovieToggleAddListExclusion &ActiveRadarrBlock::EditCollectionToggleMonitored
); );
assert_eq!(
edit_collection_block_iter.next().unwrap(),
&ActiveRadarrBlock::EditCollectionSelectMinimumAvailability
);
assert_eq!(
edit_collection_block_iter.next().unwrap(),
&ActiveRadarrBlock::EditCollectionSelectQualityProfile
);
assert_eq!(
edit_collection_block_iter.next().unwrap(),
&ActiveRadarrBlock::EditCollectionRootFolderPathInput
);
assert_eq!(
edit_collection_block_iter.next().unwrap(),
&ActiveRadarrBlock::EditCollectionToggleSearchOnAdd
);
assert_eq!(
edit_collection_block_iter.next().unwrap(),
&ActiveRadarrBlock::EditCollectionConfirmPrompt
);
}
let active_block = active_block.previous_delete_movie_prompt_block(); #[test]
fn test_delete_movie_prompt_block_order() {
assert_eq!(active_block, ActiveRadarrBlock::DeleteMovieToggleDeleteFile); let mut delete_movie_block_iter = DELETE_MOVIE_SELECTION_BLOCKS.iter();
assert_eq!(
delete_movie_block_iter.next().unwrap(),
&ActiveRadarrBlock::DeleteMovieToggleDeleteFile
);
assert_eq!(
delete_movie_block_iter.next().unwrap(),
&ActiveRadarrBlock::DeleteMovieToggleAddListExclusion
);
assert_eq!(
delete_movie_block_iter.next().unwrap(),
&ActiveRadarrBlock::DeleteMovieConfirmPrompt
);
} }
} }
@@ -2120,7 +1881,7 @@ mod tests {
assert!(!app.data.radarr_data.collection_movies.items.is_empty()); assert!(!app.data.radarr_data.collection_movies.items.is_empty());
} }
fn construct_app_unit() -> (App, mpsc::Receiver<NetworkEvent>) { fn construct_app_unit<'a>() -> (App<'a>, mpsc::Receiver<NetworkEvent>) {
let (sync_network_tx, sync_network_rx) = mpsc::channel::<NetworkEvent>(500); let (sync_network_tx, sync_network_rx) = mpsc::channel::<NetworkEvent>(500);
let mut app = App { let mut app = App {
network_tx: Some(sync_network_tx), network_tx: Some(sync_network_tx),
+5 -5
View File
@@ -7,7 +7,7 @@ use crate::models::{HorizontallyScrollableText, Route};
mod radarr_handlers; mod radarr_handlers;
pub trait KeyEventHandler<'a, T: Into<Route>> { pub trait KeyEventHandler<'a, 'b, T: Into<Route>> {
fn handle_key_event(&mut self) { fn handle_key_event(&mut self) {
let key = self.get_key(); let key = self.get_key();
match key { match key {
@@ -29,7 +29,7 @@ pub trait KeyEventHandler<'a, T: Into<Route>> {
self.handle_key_event(); self.handle_key_event();
} }
fn with(key: &'a Key, app: &'a mut App, active_block: &'a T, context: &'a Option<T>) -> Self; fn with(key: &'a Key, app: &'a mut App<'b>, active_block: &'a T, context: &'a Option<T>) -> Self;
fn get_key(&self) -> &Key; fn get_key(&self) -> &Key;
fn handle_scroll_up(&mut self); fn handle_scroll_up(&mut self);
fn handle_scroll_down(&mut self); fn handle_scroll_down(&mut self);
@@ -42,19 +42,19 @@ pub trait KeyEventHandler<'a, T: Into<Route>> {
fn handle_char_key_event(&mut self); fn handle_char_key_event(&mut self);
} }
pub fn handle_events(key: Key, app: &mut App) { pub fn handle_events(key: Key, app: &mut App<'_>) {
if let Route::Radarr(active_radarr_block, context) = *app.get_current_route() { if let Route::Radarr(active_radarr_block, context) = *app.get_current_route() {
RadarrHandler::with(&key, app, &active_radarr_block, &context).handle() RadarrHandler::with(&key, app, &active_radarr_block, &context).handle()
} }
} }
fn handle_clear_errors(app: &mut App) { fn handle_clear_errors(app: &mut App<'_>) {
if !app.error.text.is_empty() { if !app.error.text.is_empty() {
app.error = HorizontallyScrollableText::default(); app.error = HorizontallyScrollableText::default();
} }
} }
fn handle_prompt_toggle(app: &mut App, key: &Key) { fn handle_prompt_toggle(app: &mut App<'_>, key: &Key) {
match key { match key {
_ if *key == DEFAULT_KEYBINDINGS.left.key || *key == DEFAULT_KEYBINDINGS.right.key => { _ if *key == DEFAULT_KEYBINDINGS.left.key || *key == DEFAULT_KEYBINDINGS.right.key => {
if let Route::Radarr(_, _) = *app.get_current_route() { if let Route::Radarr(_, _) = *app.get_current_route() {
@@ -1,24 +1,24 @@
use crate::app::key_binding::DEFAULT_KEYBINDINGS; use crate::app::key_binding::DEFAULT_KEYBINDINGS;
use crate::app::radarr::ActiveRadarrBlock; use crate::app::radarr::{ActiveRadarrBlock, ADD_MOVIE_SELECTION_BLOCKS};
use crate::handlers::{handle_prompt_toggle, KeyEventHandler}; use crate::handlers::{handle_prompt_toggle, KeyEventHandler};
use crate::models::{Scrollable, StatefulTable}; use crate::models::{BlockSelectionState, Scrollable, StatefulTable};
use crate::network::radarr_network::RadarrEvent; use crate::network::radarr_network::RadarrEvent;
use crate::{handle_text_box_keys, handle_text_box_left_right_keys, App, Key}; use crate::{handle_text_box_keys, handle_text_box_left_right_keys, App, Key};
pub(super) struct AddMovieHandler<'a> { pub(super) struct AddMovieHandler<'a, 'b> {
key: &'a Key, key: &'a Key,
app: &'a mut App, app: &'a mut App<'b>,
active_radarr_block: &'a ActiveRadarrBlock, active_radarr_block: &'a ActiveRadarrBlock,
context: &'a Option<ActiveRadarrBlock>, context: &'a Option<ActiveRadarrBlock>,
} }
impl<'a> KeyEventHandler<'a, ActiveRadarrBlock> for AddMovieHandler<'a> { impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for AddMovieHandler<'a, 'b> {
fn with( fn with(
key: &'a Key, key: &'a Key,
app: &'a mut App, app: &'a mut App<'b>,
active_block: &'a ActiveRadarrBlock, active_block: &'a ActiveRadarrBlock,
context: &'a Option<ActiveRadarrBlock>, context: &'a Option<ActiveRadarrBlock>,
) -> AddMovieHandler<'a> { ) -> AddMovieHandler<'a, 'b> {
AddMovieHandler { AddMovieHandler {
key, key,
app, app,
@@ -51,14 +51,7 @@ impl<'a> KeyEventHandler<'a, ActiveRadarrBlock> for AddMovieHandler<'a> {
ActiveRadarrBlock::AddMovieSelectRootFolder => { ActiveRadarrBlock::AddMovieSelectRootFolder => {
self.app.data.radarr_data.root_folder_list.scroll_up() self.app.data.radarr_data.root_folder_list.scroll_up()
} }
ActiveRadarrBlock::AddMoviePrompt => { ActiveRadarrBlock::AddMoviePrompt => self.app.data.radarr_data.selected_block.previous(),
self.app.data.radarr_data.selected_block = self
.app
.data
.radarr_data
.selected_block
.previous_add_movie_prompt_block()
}
_ => (), _ => (),
} }
} }
@@ -83,14 +76,7 @@ impl<'a> KeyEventHandler<'a, ActiveRadarrBlock> for AddMovieHandler<'a> {
ActiveRadarrBlock::AddMovieSelectRootFolder => { ActiveRadarrBlock::AddMovieSelectRootFolder => {
self.app.data.radarr_data.root_folder_list.scroll_down() self.app.data.radarr_data.root_folder_list.scroll_down()
} }
ActiveRadarrBlock::AddMoviePrompt => { ActiveRadarrBlock::AddMoviePrompt => self.app.data.radarr_data.selected_block.next(),
self.app.data.radarr_data.selected_block = self
.app
.data
.radarr_data
.selected_block
.next_add_movie_prompt_block()
}
_ => (), _ => (),
} }
} }
@@ -220,31 +206,42 @@ impl<'a> KeyEventHandler<'a, ActiveRadarrBlock> for AddMovieHandler<'a> {
.app .app
.push_navigation_stack(ActiveRadarrBlock::AddMoviePrompt.into()); .push_navigation_stack(ActiveRadarrBlock::AddMoviePrompt.into());
self.app.data.radarr_data.populate_preferences_lists(); self.app.data.radarr_data.populate_preferences_lists();
self.app.data.radarr_data.selected_block = ActiveRadarrBlock::AddMovieSelectRootFolder; self.app.data.radarr_data.selected_block =
BlockSelectionState::new(&ADD_MOVIE_SELECTION_BLOCKS);
} }
} }
ActiveRadarrBlock::AddMoviePrompt => match self.app.data.radarr_data.selected_block { ActiveRadarrBlock::AddMoviePrompt => {
ActiveRadarrBlock::AddMovieConfirmPrompt => { match self.app.data.radarr_data.selected_block.get_active_block() {
if self.app.data.radarr_data.prompt_confirm { ActiveRadarrBlock::AddMovieConfirmPrompt => {
self.app.data.radarr_data.prompt_confirm_action = Some(RadarrEvent::AddMovie); if self.app.data.radarr_data.prompt_confirm {
} self.app.data.radarr_data.prompt_confirm_action = Some(RadarrEvent::AddMovie);
}
self.app.pop_navigation_stack(); self.app.pop_navigation_stack();
}
ActiveRadarrBlock::AddMovieSelectMonitor
| ActiveRadarrBlock::AddMovieSelectMinimumAvailability
| ActiveRadarrBlock::AddMovieSelectQualityProfile
| ActiveRadarrBlock::AddMovieSelectRootFolder => self.app.push_navigation_stack(
(
*self.app.data.radarr_data.selected_block.get_active_block(),
*self.context,
)
.into(),
),
ActiveRadarrBlock::AddMovieTagsInput => {
self.app.push_navigation_stack(
(
*self.app.data.radarr_data.selected_block.get_active_block(),
*self.context,
)
.into(),
);
self.app.should_ignore_quit_key = true;
}
_ => (),
} }
ActiveRadarrBlock::AddMovieSelectMonitor }
| ActiveRadarrBlock::AddMovieSelectMinimumAvailability
| ActiveRadarrBlock::AddMovieSelectQualityProfile
| ActiveRadarrBlock::AddMovieSelectRootFolder => self
.app
.push_navigation_stack((self.app.data.radarr_data.selected_block, *self.context).into()),
ActiveRadarrBlock::AddMovieTagsInput => {
self.app.push_navigation_stack(
(self.app.data.radarr_data.selected_block, *self.context).into(),
);
self.app.should_ignore_quit_key = true;
}
_ => (),
},
ActiveRadarrBlock::AddMovieSelectMonitor ActiveRadarrBlock::AddMovieSelectMonitor
| ActiveRadarrBlock::AddMovieSelectMinimumAvailability | ActiveRadarrBlock::AddMovieSelectMinimumAvailability
| ActiveRadarrBlock::AddMovieSelectQualityProfile | ActiveRadarrBlock::AddMovieSelectQualityProfile
@@ -321,6 +318,8 @@ mod tests {
use rstest::rstest; use rstest::rstest;
use strum::IntoEnumIterator; use strum::IntoEnumIterator;
use crate::app::radarr::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_enum_scroll, test_iterable_scroll};
use super::*; use super::*;
@@ -375,19 +374,20 @@ mod tests {
#[rstest] #[rstest]
fn test_add_movie_prompt_scroll(#[values(Key::Up, Key::Down)] key: Key) { fn test_add_movie_prompt_scroll(#[values(Key::Up, Key::Down)] key: Key) {
let mut app = App::default(); let mut app = App::default();
app.data.radarr_data.selected_block = ActiveRadarrBlock::AddMovieSelectMinimumAvailability; app.data.radarr_data.selected_block = BlockSelectionState::new(&ADD_MOVIE_SELECTION_BLOCKS);
app.data.radarr_data.selected_block.next();
AddMovieHandler::with(&key, &mut app, &ActiveRadarrBlock::AddMoviePrompt, &None).handle(); AddMovieHandler::with(&key, &mut app, &ActiveRadarrBlock::AddMoviePrompt, &None).handle();
if key == Key::Up { if key == Key::Up {
assert_eq!( assert_eq!(
app.data.radarr_data.selected_block, app.data.radarr_data.selected_block.get_active_block(),
ActiveRadarrBlock::AddMovieSelectMonitor &ActiveRadarrBlock::AddMovieSelectRootFolder
); );
} else { } else {
assert_eq!( assert_eq!(
app.data.radarr_data.selected_block, app.data.radarr_data.selected_block.get_active_block(),
ActiveRadarrBlock::AddMovieSelectQualityProfile &ActiveRadarrBlock::AddMovieSelectMinimumAvailability
); );
} }
} }
@@ -513,7 +513,9 @@ mod tests {
use pretty_assertions::{assert_eq, assert_str_eq}; use pretty_assertions::{assert_eq, assert_str_eq};
use rstest::rstest; use rstest::rstest;
use crate::app::radarr::ADD_MOVIE_SELECTION_BLOCKS;
use crate::models::radarr_models::Movie; use crate::models::radarr_models::Movie;
use crate::models::BlockSelectionState;
use crate::network::radarr_network::RadarrEvent; use crate::network::radarr_network::RadarrEvent;
use super::*; use super::*;
@@ -564,8 +566,8 @@ mod tests {
&ActiveRadarrBlock::AddMoviePrompt.into() &ActiveRadarrBlock::AddMoviePrompt.into()
); );
assert_eq!( assert_eq!(
app.data.radarr_data.selected_block, app.data.radarr_data.selected_block.get_active_block(),
ActiveRadarrBlock::AddMovieSelectRootFolder &ActiveRadarrBlock::AddMovieSelectRootFolder
); );
assert!(!app.data.radarr_data.monitor_list.items.is_empty()); assert!(!app.data.radarr_data.monitor_list.items.is_empty());
assert!(!app assert!(!app
@@ -636,7 +638,12 @@ mod tests {
let mut app = App::default(); let mut app = App::default();
app.push_navigation_stack(ActiveRadarrBlock::Movies.into()); app.push_navigation_stack(ActiveRadarrBlock::Movies.into());
app.push_navigation_stack(ActiveRadarrBlock::AddMoviePrompt.into()); app.push_navigation_stack(ActiveRadarrBlock::AddMoviePrompt.into());
app.data.radarr_data.selected_block = ActiveRadarrBlock::AddMovieConfirmPrompt; app.data.radarr_data.selected_block = BlockSelectionState::new(&ADD_MOVIE_SELECTION_BLOCKS);
app
.data
.radarr_data
.selected_block
.set_index(ADD_MOVIE_SELECTION_BLOCKS.len() - 1);
AddMovieHandler::with( AddMovieHandler::with(
&SUBMIT_KEY, &SUBMIT_KEY,
@@ -656,7 +663,12 @@ mod tests {
app.push_navigation_stack(ActiveRadarrBlock::Movies.into()); app.push_navigation_stack(ActiveRadarrBlock::Movies.into());
app.push_navigation_stack(ActiveRadarrBlock::AddMoviePrompt.into()); app.push_navigation_stack(ActiveRadarrBlock::AddMoviePrompt.into());
app.data.radarr_data.prompt_confirm = true; app.data.radarr_data.prompt_confirm = true;
app.data.radarr_data.selected_block = ActiveRadarrBlock::AddMovieConfirmPrompt; app.data.radarr_data.selected_block = BlockSelectionState::new(&ADD_MOVIE_SELECTION_BLOCKS);
app
.data
.radarr_data
.selected_block
.set_index(ADD_MOVIE_SELECTION_BLOCKS.len() - 1);
AddMovieHandler::with( AddMovieHandler::with(
&SUBMIT_KEY, &SUBMIT_KEY,
@@ -674,15 +686,14 @@ mod tests {
} }
#[rstest] #[rstest]
#[case(ActiveRadarrBlock::AddMovieSelectRootFolder, 0)]
#[case(ActiveRadarrBlock::AddMovieSelectMonitor, 1)]
#[case(ActiveRadarrBlock::AddMovieSelectMinimumAvailability, 2)]
#[case(ActiveRadarrBlock::AddMovieSelectQualityProfile, 3)]
#[case(ActiveRadarrBlock::AddMovieTagsInput, 4)]
fn test_add_movie_prompt_selected_block_submit( fn test_add_movie_prompt_selected_block_submit(
#[values( #[case] selected_block: ActiveRadarrBlock,
ActiveRadarrBlock::AddMovieSelectMonitor, #[case] index: usize,
ActiveRadarrBlock::AddMovieSelectMinimumAvailability,
ActiveRadarrBlock::AddMovieSelectQualityProfile,
ActiveRadarrBlock::AddMovieSelectRootFolder,
ActiveRadarrBlock::AddMovieTagsInput
)]
selected_block: ActiveRadarrBlock,
) { ) {
let mut app = App::default(); let mut app = App::default();
app.push_navigation_stack( app.push_navigation_stack(
@@ -692,7 +703,8 @@ mod tests {
) )
.into(), .into(),
); );
app.data.radarr_data.selected_block = selected_block; app.data.radarr_data.selected_block = BlockSelectionState::new(&ADD_MOVIE_SELECTION_BLOCKS);
app.data.radarr_data.selected_block.set_index(index);
AddMovieHandler::with( AddMovieHandler::with(
&SUBMIT_KEY, &SUBMIT_KEY,
@@ -1,24 +1,26 @@
use crate::app::key_binding::DEFAULT_KEYBINDINGS; use crate::app::key_binding::DEFAULT_KEYBINDINGS;
use crate::app::radarr::ActiveRadarrBlock; use crate::app::radarr::{
ActiveRadarrBlock, ADD_MOVIE_SELECTION_BLOCKS, EDIT_COLLECTION_SELECTION_BLOCKS,
};
use crate::app::App; use crate::app::App;
use crate::event::Key; use crate::event::Key;
use crate::handlers::KeyEventHandler; use crate::handlers::KeyEventHandler;
use crate::models::Scrollable; use crate::models::{BlockSelectionState, Scrollable};
pub(super) struct CollectionDetailsHandler<'a> { pub(super) struct CollectionDetailsHandler<'a, 'b> {
key: &'a Key, key: &'a Key,
app: &'a mut App, app: &'a mut App<'b>,
active_radarr_block: &'a ActiveRadarrBlock, active_radarr_block: &'a ActiveRadarrBlock,
_context: &'a Option<ActiveRadarrBlock>, _context: &'a Option<ActiveRadarrBlock>,
} }
impl<'a> KeyEventHandler<'a, ActiveRadarrBlock> for CollectionDetailsHandler<'a> { impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for CollectionDetailsHandler<'a, 'b> {
fn with( fn with(
key: &'a Key, key: &'a Key,
app: &'a mut App, app: &'a mut App<'b>,
active_block: &'a ActiveRadarrBlock, active_block: &'a ActiveRadarrBlock,
_context: &'a Option<ActiveRadarrBlock>, _context: &'a Option<ActiveRadarrBlock>,
) -> CollectionDetailsHandler<'a> { ) -> CollectionDetailsHandler<'a, 'b> {
CollectionDetailsHandler { CollectionDetailsHandler {
key, key,
app, app,
@@ -95,7 +97,8 @@ impl<'a> KeyEventHandler<'a, ActiveRadarrBlock> for CollectionDetailsHandler<'a>
) )
.into(), .into(),
); );
self.app.data.radarr_data.selected_block = ActiveRadarrBlock::AddMovieSelectRootFolder; 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.populate_preferences_lists();
} }
} }
@@ -124,7 +127,8 @@ impl<'a> KeyEventHandler<'a, ActiveRadarrBlock> for CollectionDetailsHandler<'a>
.into(), .into(),
); );
self.app.data.radarr_data.populate_edit_collection_fields(); self.app.data.radarr_data.populate_edit_collection_fields();
self.app.data.radarr_data.selected_block = ActiveRadarrBlock::EditCollectionToggleMonitored; self.app.data.radarr_data.selected_block =
BlockSelectionState::new(&EDIT_COLLECTION_SELECTION_BLOCKS);
} }
} }
} }
@@ -182,7 +186,9 @@ mod tests {
use bimap::BiMap; use bimap::BiMap;
use pretty_assertions::assert_eq; use pretty_assertions::assert_eq;
use crate::app::radarr::ADD_MOVIE_SELECTION_BLOCKS;
use crate::models::radarr_models::Movie; use crate::models::radarr_models::Movie;
use crate::models::BlockSelectionState;
use super::*; use super::*;
@@ -198,7 +204,12 @@ mod tests {
.set_items(vec![CollectionMovie::default()]); .set_items(vec![CollectionMovie::default()]);
app.data.radarr_data.quality_profile_map = app.data.radarr_data.quality_profile_map =
BiMap::from_iter([(1, "B - Test 2".to_owned()), (0, "A - Test 1".to_owned())]); BiMap::from_iter([(1, "B - Test 2".to_owned()), (0, "A - Test 1".to_owned())]);
app.data.radarr_data.selected_block = ActiveRadarrBlock::AddMovieConfirmPrompt; app.data.radarr_data.selected_block = BlockSelectionState::new(&ADD_MOVIE_SELECTION_BLOCKS);
app
.data
.radarr_data
.selected_block
.set_index(ADD_MOVIE_SELECTION_BLOCKS.len() - 1);
CollectionDetailsHandler::with( CollectionDetailsHandler::with(
&SUBMIT_KEY, &SUBMIT_KEY,
@@ -218,8 +229,8 @@ mod tests {
); );
assert!(!app.data.radarr_data.monitor_list.items.is_empty()); assert!(!app.data.radarr_data.monitor_list.items.is_empty());
assert_eq!( assert_eq!(
app.data.radarr_data.selected_block, app.data.radarr_data.selected_block.get_active_block(),
ActiveRadarrBlock::AddMovieSelectRootFolder &ActiveRadarrBlock::AddMovieSelectRootFolder
); );
assert!(!app assert!(!app
.data .data
@@ -329,7 +340,9 @@ mod tests {
use crate::app::radarr::radarr_test_utils::create_test_radarr_data; use crate::app::radarr::radarr_test_utils::create_test_radarr_data;
use crate::app::radarr::RadarrData; use crate::app::radarr::RadarrData;
use crate::app::radarr::EDIT_COLLECTION_SELECTION_BLOCKS;
use crate::models::radarr_models::{Collection, MinimumAvailability}; use crate::models::radarr_models::{Collection, MinimumAvailability};
use crate::models::BlockSelectionState;
use crate::models::HorizontallyScrollableText; use crate::models::HorizontallyScrollableText;
use crate::models::StatefulTable; use crate::models::StatefulTable;
use crate::test_edit_collection_key; use crate::test_edit_collection_key;
@@ -4,17 +4,17 @@ use crate::event::Key;
use crate::handlers::{handle_prompt_toggle, KeyEventHandler}; use crate::handlers::{handle_prompt_toggle, KeyEventHandler};
use crate::network::radarr_network::RadarrEvent; use crate::network::radarr_network::RadarrEvent;
pub(super) struct DeleteMovieHandler<'a> { pub(super) struct DeleteMovieHandler<'a, 'b> {
key: &'a Key, key: &'a Key,
app: &'a mut App, app: &'a mut App<'b>,
active_radarr_block: &'a ActiveRadarrBlock, active_radarr_block: &'a ActiveRadarrBlock,
_context: &'a Option<ActiveRadarrBlock>, _context: &'a Option<ActiveRadarrBlock>,
} }
impl<'a> KeyEventHandler<'a, ActiveRadarrBlock> for DeleteMovieHandler<'a> { impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for DeleteMovieHandler<'a, 'b> {
fn with( fn with(
key: &'a Key, key: &'a Key,
app: &'a mut App, app: &'a mut App<'b>,
active_block: &'a ActiveRadarrBlock, active_block: &'a ActiveRadarrBlock,
_context: &'a Option<ActiveRadarrBlock>, _context: &'a Option<ActiveRadarrBlock>,
) -> Self { ) -> Self {
@@ -32,23 +32,13 @@ impl<'a> KeyEventHandler<'a, ActiveRadarrBlock> for DeleteMovieHandler<'a> {
fn handle_scroll_up(&mut self) { fn handle_scroll_up(&mut self) {
if *self.active_radarr_block == ActiveRadarrBlock::DeleteMoviePrompt { if *self.active_radarr_block == ActiveRadarrBlock::DeleteMoviePrompt {
self.app.data.radarr_data.selected_block = self self.app.data.radarr_data.selected_block.previous();
.app
.data
.radarr_data
.selected_block
.previous_delete_movie_prompt_block();
} }
} }
fn handle_scroll_down(&mut self) { fn handle_scroll_down(&mut self) {
if *self.active_radarr_block == ActiveRadarrBlock::DeleteMoviePrompt { if *self.active_radarr_block == ActiveRadarrBlock::DeleteMoviePrompt {
self.app.data.radarr_data.selected_block = self self.app.data.radarr_data.selected_block.next();
.app
.data
.radarr_data
.selected_block
.next_delete_movie_prompt_block();
} }
} }
@@ -66,7 +56,7 @@ impl<'a> KeyEventHandler<'a, ActiveRadarrBlock> for DeleteMovieHandler<'a> {
fn handle_submit(&mut self) { fn handle_submit(&mut self) {
if self.active_radarr_block == &ActiveRadarrBlock::DeleteMoviePrompt { if self.active_radarr_block == &ActiveRadarrBlock::DeleteMoviePrompt {
match self.app.data.radarr_data.selected_block { match self.app.data.radarr_data.selected_block.get_active_block() {
ActiveRadarrBlock::DeleteMovieConfirmPrompt => { ActiveRadarrBlock::DeleteMovieConfirmPrompt => {
if self.app.data.radarr_data.prompt_confirm { if self.app.data.radarr_data.prompt_confirm {
self.app.data.radarr_data.prompt_confirm_action = Some(RadarrEvent::DeleteMovie); self.app.data.radarr_data.prompt_confirm_action = Some(RadarrEvent::DeleteMovie);
@@ -114,25 +104,30 @@ mod tests {
use pretty_assertions::assert_eq; use pretty_assertions::assert_eq;
use rstest::rstest; use rstest::rstest;
use crate::app::radarr::DELETE_MOVIE_SELECTION_BLOCKS;
use crate::models::BlockSelectionState;
use super::*; use super::*;
#[rstest] #[rstest]
fn test_delete_movie_prompt_scroll(#[values(Key::Up, Key::Down)] key: Key) { fn test_delete_movie_prompt_scroll(#[values(Key::Up, Key::Down)] key: Key) {
let mut app = App::default(); let mut app = App::default();
app.data.radarr_data.selected_block = ActiveRadarrBlock::DeleteMovieToggleAddListExclusion; app.data.radarr_data.selected_block =
BlockSelectionState::new(&DELETE_MOVIE_SELECTION_BLOCKS);
app.data.radarr_data.selected_block.next();
DeleteMovieHandler::with(&key, &mut app, &ActiveRadarrBlock::DeleteMoviePrompt, &None) DeleteMovieHandler::with(&key, &mut app, &ActiveRadarrBlock::DeleteMoviePrompt, &None)
.handle(); .handle();
if key == Key::Up { if key == Key::Up {
assert_eq!( assert_eq!(
app.data.radarr_data.selected_block, app.data.radarr_data.selected_block.get_active_block(),
ActiveRadarrBlock::DeleteMovieToggleDeleteFile &ActiveRadarrBlock::DeleteMovieToggleDeleteFile
); );
} else { } else {
assert_eq!( assert_eq!(
app.data.radarr_data.selected_block, app.data.radarr_data.selected_block.get_active_block(),
ActiveRadarrBlock::DeleteMovieConfirmPrompt &ActiveRadarrBlock::DeleteMovieConfirmPrompt
); );
} }
} }
@@ -162,6 +157,8 @@ mod tests {
mod test_handle_submit { mod test_handle_submit {
use pretty_assertions::assert_eq; use pretty_assertions::assert_eq;
use crate::app::radarr::DELETE_MOVIE_SELECTION_BLOCKS;
use crate::models::BlockSelectionState;
use crate::network::radarr_network::RadarrEvent; use crate::network::radarr_network::RadarrEvent;
use super::*; use super::*;
@@ -173,7 +170,13 @@ mod tests {
let mut app = App::default(); let mut app = App::default();
app.push_navigation_stack(ActiveRadarrBlock::Movies.into()); app.push_navigation_stack(ActiveRadarrBlock::Movies.into());
app.push_navigation_stack(ActiveRadarrBlock::DeleteMoviePrompt.into()); app.push_navigation_stack(ActiveRadarrBlock::DeleteMoviePrompt.into());
app.data.radarr_data.selected_block = ActiveRadarrBlock::DeleteMovieConfirmPrompt; app.data.radarr_data.selected_block =
BlockSelectionState::new(&DELETE_MOVIE_SELECTION_BLOCKS);
app
.data
.radarr_data
.selected_block
.set_index(DELETE_MOVIE_SELECTION_BLOCKS.len() - 1);
app.data.radarr_data.delete_movie_files = true; app.data.radarr_data.delete_movie_files = true;
app.data.radarr_data.add_list_exclusion = true; app.data.radarr_data.add_list_exclusion = true;
@@ -200,7 +203,13 @@ mod tests {
app.data.radarr_data.prompt_confirm = true; app.data.radarr_data.prompt_confirm = true;
app.data.radarr_data.delete_movie_files = true; app.data.radarr_data.delete_movie_files = true;
app.data.radarr_data.add_list_exclusion = true; app.data.radarr_data.add_list_exclusion = true;
app.data.radarr_data.selected_block = ActiveRadarrBlock::DeleteMovieConfirmPrompt; app.data.radarr_data.selected_block =
BlockSelectionState::new(&DELETE_MOVIE_SELECTION_BLOCKS);
app
.data
.radarr_data
.selected_block
.set_index(DELETE_MOVIE_SELECTION_BLOCKS.len() - 1);
DeleteMovieHandler::with( DeleteMovieHandler::with(
&SUBMIT_KEY, &SUBMIT_KEY,
@@ -225,7 +234,8 @@ mod tests {
fn test_delete_movie_toggle_delete_files_submit() { fn test_delete_movie_toggle_delete_files_submit() {
let current_route = ActiveRadarrBlock::DeleteMoviePrompt.into(); let current_route = ActiveRadarrBlock::DeleteMoviePrompt.into();
let mut app = App::default(); let mut app = App::default();
app.data.radarr_data.selected_block = ActiveRadarrBlock::DeleteMovieToggleDeleteFile; app.data.radarr_data.selected_block =
BlockSelectionState::new(&DELETE_MOVIE_SELECTION_BLOCKS);
app.push_navigation_stack(ActiveRadarrBlock::DeleteMoviePrompt.into()); app.push_navigation_stack(ActiveRadarrBlock::DeleteMoviePrompt.into());
DeleteMovieHandler::with( DeleteMovieHandler::with(
@@ -7,20 +7,20 @@ use crate::models::Scrollable;
use crate::network::radarr_network::RadarrEvent; use crate::network::radarr_network::RadarrEvent;
use crate::{handle_text_box_keys, handle_text_box_left_right_keys}; use crate::{handle_text_box_keys, handle_text_box_left_right_keys};
pub(super) struct EditCollectionHandler<'a> { pub(super) struct EditCollectionHandler<'a, 'b> {
key: &'a Key, key: &'a Key,
app: &'a mut App, app: &'a mut App<'b>,
active_radarr_block: &'a ActiveRadarrBlock, active_radarr_block: &'a ActiveRadarrBlock,
context: &'a Option<ActiveRadarrBlock>, context: &'a Option<ActiveRadarrBlock>,
} }
impl<'a> KeyEventHandler<'a, ActiveRadarrBlock> for EditCollectionHandler<'a> { impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for EditCollectionHandler<'a, 'b> {
fn with( fn with(
key: &'a Key, key: &'a Key,
app: &'a mut App, app: &'a mut App<'b>,
active_block: &'a ActiveRadarrBlock, active_block: &'a ActiveRadarrBlock,
context: &'a Option<ActiveRadarrBlock>, context: &'a Option<ActiveRadarrBlock>,
) -> EditCollectionHandler<'a> { ) -> EditCollectionHandler<'a, 'b> {
EditCollectionHandler { EditCollectionHandler {
key, key,
app, app,
@@ -45,12 +45,7 @@ impl<'a> KeyEventHandler<'a, ActiveRadarrBlock> for EditCollectionHandler<'a> {
self.app.data.radarr_data.quality_profile_list.scroll_up() self.app.data.radarr_data.quality_profile_list.scroll_up()
} }
ActiveRadarrBlock::EditCollectionPrompt => { ActiveRadarrBlock::EditCollectionPrompt => {
self.app.data.radarr_data.selected_block = self self.app.data.radarr_data.selected_block.previous()
.app
.data
.radarr_data
.selected_block
.previous_edit_collection_prompt_block()
} }
_ => (), _ => (),
} }
@@ -67,14 +62,7 @@ impl<'a> KeyEventHandler<'a, ActiveRadarrBlock> for EditCollectionHandler<'a> {
ActiveRadarrBlock::EditCollectionSelectQualityProfile => { ActiveRadarrBlock::EditCollectionSelectQualityProfile => {
self.app.data.radarr_data.quality_profile_list.scroll_down() self.app.data.radarr_data.quality_profile_list.scroll_down()
} }
ActiveRadarrBlock::EditCollectionPrompt => { ActiveRadarrBlock::EditCollectionPrompt => self.app.data.radarr_data.selected_block.next(),
self.app.data.radarr_data.selected_block = self
.app
.data
.radarr_data
.selected_block
.next_edit_collection_prompt_block()
}
_ => (), _ => (),
} }
} }
@@ -135,41 +123,53 @@ impl<'a> KeyEventHandler<'a, ActiveRadarrBlock> for EditCollectionHandler<'a> {
fn handle_submit(&mut self) { fn handle_submit(&mut self) {
match self.active_radarr_block { match self.active_radarr_block {
ActiveRadarrBlock::EditCollectionPrompt => match self.app.data.radarr_data.selected_block { ActiveRadarrBlock::EditCollectionPrompt => {
ActiveRadarrBlock::EditCollectionConfirmPrompt => { match self.app.data.radarr_data.selected_block.get_active_block() {
if self.app.data.radarr_data.prompt_confirm { ActiveRadarrBlock::EditCollectionConfirmPrompt => {
self.app.data.radarr_data.prompt_confirm_action = Some(RadarrEvent::EditCollection); if self.app.data.radarr_data.prompt_confirm {
self.app.should_refresh = true; self.app.data.radarr_data.prompt_confirm_action = Some(RadarrEvent::EditCollection);
} self.app.should_refresh = true;
}
self.app.pop_navigation_stack(); self.app.pop_navigation_stack();
}
ActiveRadarrBlock::EditCollectionSelectMinimumAvailability
| ActiveRadarrBlock::EditCollectionSelectQualityProfile => {
self.app.push_navigation_stack(
(
*self.app.data.radarr_data.selected_block.get_active_block(),
*self.context,
)
.into(),
)
}
ActiveRadarrBlock::EditCollectionRootFolderPathInput => {
self.app.push_navigation_stack(
(
*self.app.data.radarr_data.selected_block.get_active_block(),
*self.context,
)
.into(),
);
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_search_on_add
.unwrap_or_default(),
)
}
_ => (),
} }
ActiveRadarrBlock::EditCollectionSelectMinimumAvailability }
| ActiveRadarrBlock::EditCollectionSelectQualityProfile => self
.app
.push_navigation_stack((self.app.data.radarr_data.selected_block, *self.context).into()),
ActiveRadarrBlock::EditCollectionRootFolderPathInput => {
self.app.push_navigation_stack(
(self.app.data.radarr_data.selected_block, *self.context).into(),
);
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_search_on_add
.unwrap_or_default(),
)
}
_ => (),
},
ActiveRadarrBlock::EditCollectionSelectMinimumAvailability ActiveRadarrBlock::EditCollectionSelectMinimumAvailability
| ActiveRadarrBlock::EditCollectionSelectQualityProfile => self.app.pop_navigation_stack(), | ActiveRadarrBlock::EditCollectionSelectQualityProfile => self.app.pop_navigation_stack(),
ActiveRadarrBlock::EditCollectionRootFolderPathInput => { ActiveRadarrBlock::EditCollectionRootFolderPathInput => {
@@ -222,6 +222,8 @@ mod tests {
use rstest::rstest; use rstest::rstest;
use strum::IntoEnumIterator; use strum::IntoEnumIterator;
use crate::app::radarr::EDIT_COLLECTION_SELECTION_BLOCKS;
use crate::models::BlockSelectionState;
use crate::{test_enum_scroll, test_iterable_scroll}; use crate::{test_enum_scroll, test_iterable_scroll};
use super::*; use super::*;
@@ -247,7 +249,8 @@ mod tests {
fn test_edit_collection_prompt_scroll(#[values(Key::Up, Key::Down)] key: Key) { fn test_edit_collection_prompt_scroll(#[values(Key::Up, Key::Down)] key: Key) {
let mut app = App::default(); let mut app = App::default();
app.data.radarr_data.selected_block = app.data.radarr_data.selected_block =
ActiveRadarrBlock::EditCollectionSelectMinimumAvailability; BlockSelectionState::new(&EDIT_COLLECTION_SELECTION_BLOCKS);
app.data.radarr_data.selected_block.next();
EditCollectionHandler::with( EditCollectionHandler::with(
&key, &key,
@@ -259,13 +262,13 @@ mod tests {
if key == Key::Up { if key == Key::Up {
assert_eq!( assert_eq!(
app.data.radarr_data.selected_block, app.data.radarr_data.selected_block.get_active_block(),
ActiveRadarrBlock::EditCollectionToggleMonitored &ActiveRadarrBlock::EditCollectionToggleMonitored
); );
} else { } else {
assert_eq!( assert_eq!(
app.data.radarr_data.selected_block, app.data.radarr_data.selected_block.get_active_block(),
ActiveRadarrBlock::EditCollectionSelectQualityProfile &ActiveRadarrBlock::EditCollectionSelectQualityProfile
); );
} }
} }
@@ -351,7 +354,8 @@ mod tests {
use pretty_assertions::assert_eq; use pretty_assertions::assert_eq;
use rstest::rstest; use rstest::rstest;
use crate::models::Route; use crate::app::radarr::EDIT_COLLECTION_SELECTION_BLOCKS;
use crate::models::{BlockSelectionState, Route};
use crate::network::radarr_network::RadarrEvent; use crate::network::radarr_network::RadarrEvent;
use super::*; use super::*;
@@ -387,7 +391,13 @@ mod tests {
let mut app = App::default(); let mut app = App::default();
app.push_navigation_stack(ActiveRadarrBlock::Collections.into()); app.push_navigation_stack(ActiveRadarrBlock::Collections.into());
app.push_navigation_stack(ActiveRadarrBlock::EditCollectionPrompt.into()); app.push_navigation_stack(ActiveRadarrBlock::EditCollectionPrompt.into());
app.data.radarr_data.selected_block = ActiveRadarrBlock::EditCollectionConfirmPrompt; app.data.radarr_data.selected_block =
BlockSelectionState::new(&EDIT_COLLECTION_SELECTION_BLOCKS);
app
.data
.radarr_data
.selected_block
.set_index(EDIT_COLLECTION_SELECTION_BLOCKS.len() - 1);
EditCollectionHandler::with( EditCollectionHandler::with(
&SUBMIT_KEY, &SUBMIT_KEY,
@@ -410,7 +420,13 @@ mod tests {
app.push_navigation_stack(ActiveRadarrBlock::Collections.into()); app.push_navigation_stack(ActiveRadarrBlock::Collections.into());
app.push_navigation_stack(ActiveRadarrBlock::EditCollectionPrompt.into()); app.push_navigation_stack(ActiveRadarrBlock::EditCollectionPrompt.into());
app.data.radarr_data.prompt_confirm = true; app.data.radarr_data.prompt_confirm = true;
app.data.radarr_data.selected_block = ActiveRadarrBlock::EditCollectionConfirmPrompt; app.data.radarr_data.selected_block =
BlockSelectionState::new(&EDIT_COLLECTION_SELECTION_BLOCKS);
app
.data
.radarr_data
.selected_block
.set_index(EDIT_COLLECTION_SELECTION_BLOCKS.len() - 1);
EditCollectionHandler::with( EditCollectionHandler::with(
&SUBMIT_KEY, &SUBMIT_KEY,
@@ -438,7 +454,8 @@ mod tests {
Some(ActiveRadarrBlock::Collections), Some(ActiveRadarrBlock::Collections),
)); ));
let mut app = App::default(); let mut app = App::default();
app.data.radarr_data.selected_block = ActiveRadarrBlock::EditCollectionToggleMonitored; app.data.radarr_data.selected_block =
BlockSelectionState::new(&EDIT_COLLECTION_SELECTION_BLOCKS);
app.push_navigation_stack(current_route); app.push_navigation_stack(current_route);
EditCollectionHandler::with( EditCollectionHandler::with(
@@ -471,7 +488,13 @@ mod tests {
Some(ActiveRadarrBlock::Collections), Some(ActiveRadarrBlock::Collections),
)); ));
let mut app = App::default(); let mut app = App::default();
app.data.radarr_data.selected_block = ActiveRadarrBlock::EditCollectionToggleSearchOnAdd; app.data.radarr_data.selected_block =
BlockSelectionState::new(&EDIT_COLLECTION_SELECTION_BLOCKS);
app
.data
.radarr_data
.selected_block
.set_index(EDIT_COLLECTION_SELECTION_BLOCKS.len() - 2);
app.push_navigation_stack(current_route); app.push_navigation_stack(current_route);
EditCollectionHandler::with( EditCollectionHandler::with(
@@ -498,13 +521,12 @@ mod tests {
} }
#[rstest] #[rstest]
#[case(ActiveRadarrBlock::EditCollectionSelectMinimumAvailability, 1)]
#[case(ActiveRadarrBlock::EditCollectionSelectQualityProfile, 2)]
#[case(ActiveRadarrBlock::EditCollectionRootFolderPathInput, 3)]
fn test_edit_collection_prompt_selected_block_submit( fn test_edit_collection_prompt_selected_block_submit(
#[values( #[case] selected_block: ActiveRadarrBlock,
ActiveRadarrBlock::EditCollectionSelectMinimumAvailability, #[case] index: usize,
ActiveRadarrBlock::EditCollectionSelectQualityProfile,
ActiveRadarrBlock::EditCollectionRootFolderPathInput
)]
selected_block: ActiveRadarrBlock,
) { ) {
let mut app = App::default(); let mut app = App::default();
app.push_navigation_stack( app.push_navigation_stack(
@@ -514,7 +536,9 @@ mod tests {
) )
.into(), .into(),
); );
app.data.radarr_data.selected_block = selected_block; app.data.radarr_data.selected_block =
BlockSelectionState::new(&EDIT_COLLECTION_SELECTION_BLOCKS);
app.data.radarr_data.selected_block.set_index(index);
EditCollectionHandler::with( EditCollectionHandler::with(
&SUBMIT_KEY, &SUBMIT_KEY,
@@ -7,20 +7,20 @@ use crate::models::Scrollable;
use crate::network::radarr_network::RadarrEvent; use crate::network::radarr_network::RadarrEvent;
use crate::{handle_text_box_keys, handle_text_box_left_right_keys}; use crate::{handle_text_box_keys, handle_text_box_left_right_keys};
pub(super) struct EditMovieHandler<'a> { pub(super) struct EditMovieHandler<'a, 'b> {
key: &'a Key, key: &'a Key,
app: &'a mut App, app: &'a mut App<'b>,
active_radarr_block: &'a ActiveRadarrBlock, active_radarr_block: &'a ActiveRadarrBlock,
context: &'a Option<ActiveRadarrBlock>, context: &'a Option<ActiveRadarrBlock>,
} }
impl<'a> KeyEventHandler<'a, ActiveRadarrBlock> for EditMovieHandler<'a> { impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for EditMovieHandler<'a, 'b> {
fn with( fn with(
key: &'a Key, key: &'a Key,
app: &'a mut App, app: &'a mut App<'b>,
active_block: &'a ActiveRadarrBlock, active_block: &'a ActiveRadarrBlock,
context: &'a Option<ActiveRadarrBlock>, context: &'a Option<ActiveRadarrBlock>,
) -> EditMovieHandler<'a> { ) -> EditMovieHandler<'a, 'b> {
EditMovieHandler { EditMovieHandler {
key, key,
app, app,
@@ -44,14 +44,7 @@ impl<'a> KeyEventHandler<'a, ActiveRadarrBlock> for EditMovieHandler<'a> {
ActiveRadarrBlock::EditMovieSelectQualityProfile => { ActiveRadarrBlock::EditMovieSelectQualityProfile => {
self.app.data.radarr_data.quality_profile_list.scroll_up() self.app.data.radarr_data.quality_profile_list.scroll_up()
} }
ActiveRadarrBlock::EditMoviePrompt => { ActiveRadarrBlock::EditMoviePrompt => self.app.data.radarr_data.selected_block.previous(),
self.app.data.radarr_data.selected_block = self
.app
.data
.radarr_data
.selected_block
.previous_edit_movie_prompt_block()
}
_ => (), _ => (),
} }
} }
@@ -67,14 +60,7 @@ impl<'a> KeyEventHandler<'a, ActiveRadarrBlock> for EditMovieHandler<'a> {
ActiveRadarrBlock::EditMovieSelectQualityProfile => { ActiveRadarrBlock::EditMovieSelectQualityProfile => {
self.app.data.radarr_data.quality_profile_list.scroll_down() self.app.data.radarr_data.quality_profile_list.scroll_down()
} }
ActiveRadarrBlock::EditMoviePrompt => { ActiveRadarrBlock::EditMoviePrompt => self.app.data.radarr_data.selected_block.next(),
self.app.data.radarr_data.selected_block = self
.app
.data
.radarr_data
.selected_block
.next_edit_movie_prompt_block()
}
_ => (), _ => (),
} }
} }
@@ -136,31 +122,41 @@ impl<'a> KeyEventHandler<'a, ActiveRadarrBlock> for EditMovieHandler<'a> {
fn handle_submit(&mut self) { fn handle_submit(&mut self) {
match self.active_radarr_block { match self.active_radarr_block {
ActiveRadarrBlock::EditMoviePrompt => match self.app.data.radarr_data.selected_block { ActiveRadarrBlock::EditMoviePrompt => {
ActiveRadarrBlock::EditMovieConfirmPrompt => { match self.app.data.radarr_data.selected_block.get_active_block() {
if self.app.data.radarr_data.prompt_confirm { ActiveRadarrBlock::EditMovieConfirmPrompt => {
self.app.data.radarr_data.prompt_confirm_action = Some(RadarrEvent::EditMovie); if self.app.data.radarr_data.prompt_confirm {
self.app.should_refresh = true; self.app.data.radarr_data.prompt_confirm_action = Some(RadarrEvent::EditMovie);
} self.app.should_refresh = true;
}
self.app.pop_navigation_stack(); self.app.pop_navigation_stack();
}
ActiveRadarrBlock::EditMovieSelectMinimumAvailability
| ActiveRadarrBlock::EditMovieSelectQualityProfile => self.app.push_navigation_stack(
(
*self.app.data.radarr_data.selected_block.get_active_block(),
*self.context,
)
.into(),
),
ActiveRadarrBlock::EditMoviePathInput | ActiveRadarrBlock::EditMovieTagsInput => {
self.app.push_navigation_stack(
(
*self.app.data.radarr_data.selected_block.get_active_block(),
*self.context,
)
.into(),
);
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())
}
_ => (),
} }
ActiveRadarrBlock::EditMovieSelectMinimumAvailability }
| ActiveRadarrBlock::EditMovieSelectQualityProfile => self
.app
.push_navigation_stack((self.app.data.radarr_data.selected_block, *self.context).into()),
ActiveRadarrBlock::EditMoviePathInput | ActiveRadarrBlock::EditMovieTagsInput => {
self.app.push_navigation_stack(
(self.app.data.radarr_data.selected_block, *self.context).into(),
);
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())
}
_ => (),
},
ActiveRadarrBlock::EditMovieSelectMinimumAvailability ActiveRadarrBlock::EditMovieSelectMinimumAvailability
| ActiveRadarrBlock::EditMovieSelectQualityProfile => self.app.pop_navigation_stack(), | ActiveRadarrBlock::EditMovieSelectQualityProfile => self.app.pop_navigation_stack(),
ActiveRadarrBlock::EditMoviePathInput | ActiveRadarrBlock::EditMovieTagsInput => { ActiveRadarrBlock::EditMoviePathInput | ActiveRadarrBlock::EditMovieTagsInput => {
@@ -219,6 +215,8 @@ mod tests {
use rstest::rstest; use rstest::rstest;
use strum::IntoEnumIterator; use strum::IntoEnumIterator;
use crate::app::radarr::EDIT_MOVIE_SELECTION_BLOCKS;
use crate::models::BlockSelectionState;
use crate::{test_enum_scroll, test_iterable_scroll}; use crate::{test_enum_scroll, test_iterable_scroll};
use super::*; use super::*;
@@ -243,19 +241,20 @@ mod tests {
#[rstest] #[rstest]
fn test_edit_movie_prompt_scroll(#[values(Key::Up, Key::Down)] key: Key) { fn test_edit_movie_prompt_scroll(#[values(Key::Up, Key::Down)] key: Key) {
let mut app = App::default(); let mut app = App::default();
app.data.radarr_data.selected_block = ActiveRadarrBlock::EditMovieSelectMinimumAvailability; app.data.radarr_data.selected_block = BlockSelectionState::new(&EDIT_MOVIE_SELECTION_BLOCKS);
app.data.radarr_data.selected_block.next();
EditMovieHandler::with(&key, &mut app, &ActiveRadarrBlock::EditMoviePrompt, &None).handle(); EditMovieHandler::with(&key, &mut app, &ActiveRadarrBlock::EditMoviePrompt, &None).handle();
if key == Key::Up { if key == Key::Up {
assert_eq!( assert_eq!(
app.data.radarr_data.selected_block, app.data.radarr_data.selected_block.get_active_block(),
ActiveRadarrBlock::EditMovieToggleMonitored &ActiveRadarrBlock::EditMovieToggleMonitored
); );
} else { } else {
assert_eq!( assert_eq!(
app.data.radarr_data.selected_block, app.data.radarr_data.selected_block.get_active_block(),
ActiveRadarrBlock::EditMovieSelectQualityProfile &ActiveRadarrBlock::EditMovieSelectQualityProfile
); );
} }
} }
@@ -347,7 +346,8 @@ mod tests {
use pretty_assertions::assert_eq; use pretty_assertions::assert_eq;
use rstest::rstest; use rstest::rstest;
use crate::models::Route; use crate::app::radarr::{EDIT_COLLECTION_SELECTION_BLOCKS, EDIT_MOVIE_SELECTION_BLOCKS};
use crate::models::{BlockSelectionState, Route};
use crate::network::radarr_network::RadarrEvent; use crate::network::radarr_network::RadarrEvent;
use super::*; use super::*;
@@ -407,7 +407,12 @@ mod tests {
let mut app = App::default(); let mut app = App::default();
app.push_navigation_stack(ActiveRadarrBlock::Movies.into()); app.push_navigation_stack(ActiveRadarrBlock::Movies.into());
app.push_navigation_stack(ActiveRadarrBlock::EditMoviePrompt.into()); app.push_navigation_stack(ActiveRadarrBlock::EditMoviePrompt.into());
app.data.radarr_data.selected_block = ActiveRadarrBlock::EditMovieConfirmPrompt; app.data.radarr_data.selected_block = BlockSelectionState::new(&EDIT_MOVIE_SELECTION_BLOCKS);
app
.data
.radarr_data
.selected_block
.set_index(EDIT_COLLECTION_SELECTION_BLOCKS.len() - 1);
EditMovieHandler::with( EditMovieHandler::with(
&SUBMIT_KEY, &SUBMIT_KEY,
@@ -427,7 +432,12 @@ mod tests {
app.push_navigation_stack(ActiveRadarrBlock::Movies.into()); app.push_navigation_stack(ActiveRadarrBlock::Movies.into());
app.push_navigation_stack(ActiveRadarrBlock::EditMoviePrompt.into()); app.push_navigation_stack(ActiveRadarrBlock::EditMoviePrompt.into());
app.data.radarr_data.prompt_confirm = true; app.data.radarr_data.prompt_confirm = true;
app.data.radarr_data.selected_block = ActiveRadarrBlock::EditMovieConfirmPrompt; app.data.radarr_data.selected_block = BlockSelectionState::new(&EDIT_MOVIE_SELECTION_BLOCKS);
app
.data
.radarr_data
.selected_block
.set_index(EDIT_COLLECTION_SELECTION_BLOCKS.len() - 1);
EditMovieHandler::with( EditMovieHandler::with(
&SUBMIT_KEY, &SUBMIT_KEY,
@@ -452,7 +462,7 @@ mod tests {
Some(ActiveRadarrBlock::Movies), Some(ActiveRadarrBlock::Movies),
)); ));
let mut app = App::default(); let mut app = App::default();
app.data.radarr_data.selected_block = ActiveRadarrBlock::EditMovieToggleMonitored; app.data.radarr_data.selected_block = BlockSelectionState::new(&EDIT_MOVIE_SELECTION_BLOCKS);
app.push_navigation_stack(current_route); app.push_navigation_stack(current_route);
EditMovieHandler::with( EditMovieHandler::with(
@@ -479,14 +489,13 @@ mod tests {
} }
#[rstest] #[rstest]
#[case(ActiveRadarrBlock::EditMovieSelectMinimumAvailability, 1)]
#[case(ActiveRadarrBlock::EditMovieSelectQualityProfile, 2)]
#[case(ActiveRadarrBlock::EditMoviePathInput, 3)]
#[case(ActiveRadarrBlock::EditMovieTagsInput, 4)]
fn test_edit_movie_prompt_selected_block_submit( fn test_edit_movie_prompt_selected_block_submit(
#[values( #[case] selected_block: ActiveRadarrBlock,
ActiveRadarrBlock::EditMovieSelectMinimumAvailability, #[case] index: usize,
ActiveRadarrBlock::EditMovieSelectQualityProfile,
ActiveRadarrBlock::EditMoviePathInput,
ActiveRadarrBlock::EditMovieTagsInput
)]
selected_block: ActiveRadarrBlock,
) { ) {
let mut app = App::default(); let mut app = App::default();
app.push_navigation_stack( app.push_navigation_stack(
@@ -496,7 +505,8 @@ mod tests {
) )
.into(), .into(),
); );
app.data.radarr_data.selected_block = selected_block; app.data.radarr_data.selected_block = BlockSelectionState::new(&EDIT_MOVIE_SELECTION_BLOCKS);
app.data.radarr_data.selected_block.set_index(index);
EditMovieHandler::with( EditMovieHandler::with(
&SUBMIT_KEY, &SUBMIT_KEY,
+34 -22
View File
@@ -1,7 +1,9 @@
use crate::app::key_binding::DEFAULT_KEYBINDINGS; use crate::app::key_binding::DEFAULT_KEYBINDINGS;
use crate::app::radarr::{ use crate::app::radarr::{
ActiveRadarrBlock, ADD_MOVIE_BLOCKS, COLLECTION_DETAILS_BLOCKS, DELETE_MOVIE_BLOCKS, ActiveRadarrBlock, ADD_MOVIE_BLOCKS, COLLECTION_DETAILS_BLOCKS, DELETE_MOVIE_BLOCKS,
EDIT_COLLECTION_BLOCKS, EDIT_MOVIE_BLOCKS, FILTER_BLOCKS, MOVIE_DETAILS_BLOCKS, SEARCH_BLOCKS, DELETE_MOVIE_SELECTION_BLOCKS, EDIT_COLLECTION_BLOCKS, EDIT_COLLECTION_SELECTION_BLOCKS,
EDIT_MOVIE_BLOCKS, EDIT_MOVIE_SELECTION_BLOCKS, FILTER_BLOCKS, MOVIE_DETAILS_BLOCKS,
SEARCH_BLOCKS,
}; };
use crate::handlers::radarr_handlers::add_movie_handler::AddMovieHandler; use crate::handlers::radarr_handlers::add_movie_handler::AddMovieHandler;
use crate::handlers::radarr_handlers::collection_details_handler::CollectionDetailsHandler; use crate::handlers::radarr_handlers::collection_details_handler::CollectionDetailsHandler;
@@ -10,7 +12,7 @@ use crate::handlers::radarr_handlers::edit_collection_handler::EditCollectionHan
use crate::handlers::radarr_handlers::edit_movie_handler::EditMovieHandler; use crate::handlers::radarr_handlers::edit_movie_handler::EditMovieHandler;
use crate::handlers::radarr_handlers::movie_details_handler::MovieDetailsHandler; use crate::handlers::radarr_handlers::movie_details_handler::MovieDetailsHandler;
use crate::handlers::{handle_clear_errors, handle_prompt_toggle, KeyEventHandler}; use crate::handlers::{handle_clear_errors, handle_prompt_toggle, KeyEventHandler};
use crate::models::{HorizontallyScrollableText, Scrollable}; use crate::models::{BlockSelectionState, HorizontallyScrollableText, Scrollable};
use crate::network::radarr_network::RadarrEvent; use crate::network::radarr_network::RadarrEvent;
use crate::utils::strip_non_search_characters; use crate::utils::strip_non_search_characters;
use crate::{handle_text_box_keys, handle_text_box_left_right_keys, App, Key}; use crate::{handle_text_box_keys, handle_text_box_left_right_keys, App, Key};
@@ -22,14 +24,14 @@ mod edit_collection_handler;
mod edit_movie_handler; mod edit_movie_handler;
mod movie_details_handler; mod movie_details_handler;
pub(super) struct RadarrHandler<'a> { pub(super) struct RadarrHandler<'a, 'b> {
key: &'a Key, key: &'a Key,
app: &'a mut App, app: &'a mut App<'b>,
active_radarr_block: &'a ActiveRadarrBlock, active_radarr_block: &'a ActiveRadarrBlock,
context: &'a Option<ActiveRadarrBlock>, context: &'a Option<ActiveRadarrBlock>,
} }
impl<'a> KeyEventHandler<'a, ActiveRadarrBlock> for RadarrHandler<'a> { impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for RadarrHandler<'a, 'b> {
fn handle(&mut self) { fn handle(&mut self) {
match self.active_radarr_block { match self.active_radarr_block {
_ if MOVIE_DETAILS_BLOCKS.contains(self.active_radarr_block) => { _ if MOVIE_DETAILS_BLOCKS.contains(self.active_radarr_block) => {
@@ -60,10 +62,10 @@ impl<'a> KeyEventHandler<'a, ActiveRadarrBlock> for RadarrHandler<'a> {
fn with( fn with(
key: &'a Key, key: &'a Key,
app: &'a mut App, app: &'a mut App<'b>,
active_block: &'a ActiveRadarrBlock, active_block: &'a ActiveRadarrBlock,
context: &'a Option<ActiveRadarrBlock>, context: &'a Option<ActiveRadarrBlock>,
) -> RadarrHandler<'a> { ) -> RadarrHandler<'a, 'b> {
RadarrHandler { RadarrHandler {
key, key,
app, app,
@@ -222,7 +224,8 @@ impl<'a> KeyEventHandler<'a, ActiveRadarrBlock> for RadarrHandler<'a> {
self self
.app .app
.push_navigation_stack(ActiveRadarrBlock::DeleteMoviePrompt.into()); .push_navigation_stack(ActiveRadarrBlock::DeleteMoviePrompt.into());
self.app.data.radarr_data.selected_block = ActiveRadarrBlock::DeleteMovieToggleDeleteFile; self.app.data.radarr_data.selected_block =
BlockSelectionState::new(&DELETE_MOVIE_SELECTION_BLOCKS);
} }
ActiveRadarrBlock::Downloads => self ActiveRadarrBlock::Downloads => self
.app .app
@@ -239,7 +242,8 @@ impl<'a> KeyEventHandler<'a, ActiveRadarrBlock> for RadarrHandler<'a> {
ActiveRadarrBlock::Movies ActiveRadarrBlock::Movies
| ActiveRadarrBlock::Downloads | ActiveRadarrBlock::Downloads
| ActiveRadarrBlock::Collections | ActiveRadarrBlock::Collections
| ActiveRadarrBlock::RootFolders => match self.key { | ActiveRadarrBlock::RootFolders
| ActiveRadarrBlock::System => match self.key {
_ if *self.key == DEFAULT_KEYBINDINGS.left.key => { _ if *self.key == DEFAULT_KEYBINDINGS.left.key => {
self.app.data.radarr_data.main_tabs.previous(); self.app.data.radarr_data.main_tabs.previous();
self self
@@ -473,7 +477,8 @@ impl<'a> KeyEventHandler<'a, ActiveRadarrBlock> for RadarrHandler<'a> {
.into(), .into(),
); );
self.app.data.radarr_data.populate_edit_movie_fields(); self.app.data.radarr_data.populate_edit_movie_fields();
self.app.data.radarr_data.selected_block = ActiveRadarrBlock::EditMovieToggleMonitored; self.app.data.radarr_data.selected_block =
BlockSelectionState::new(&EDIT_MOVIE_SELECTION_BLOCKS);
} }
_ if *key == DEFAULT_KEYBINDINGS.add.key => { _ if *key == DEFAULT_KEYBINDINGS.add.key => {
self self
@@ -527,7 +532,7 @@ impl<'a> KeyEventHandler<'a, ActiveRadarrBlock> for RadarrHandler<'a> {
); );
self.app.data.radarr_data.populate_edit_collection_fields(); self.app.data.radarr_data.populate_edit_collection_fields();
self.app.data.radarr_data.selected_block = self.app.data.radarr_data.selected_block =
ActiveRadarrBlock::EditCollectionToggleMonitored; BlockSelectionState::new(&EDIT_COLLECTION_SELECTION_BLOCKS);
} }
_ if *key == DEFAULT_KEYBINDINGS.update.key => { _ if *key == DEFAULT_KEYBINDINGS.update.key => {
self self
@@ -565,7 +570,7 @@ impl<'a> KeyEventHandler<'a, ActiveRadarrBlock> for RadarrHandler<'a> {
} }
} }
impl RadarrHandler<'_> { impl<'a, 'b> RadarrHandler<'a, 'b> {
fn search_table<T, F>(&mut self, rows: &[T], field_selection_fn: F) -> Option<usize> fn search_table<T, F>(&mut self, rows: &[T], field_selection_fn: F) -> Option<usize>
where where
F: Fn(&T) -> &str, F: Fn(&T) -> &str,
@@ -636,6 +641,7 @@ mod radarr_handler_test_utils {
tags: vec![Number::from(1)], tags: vec![Number::from(1)],
..Movie::default() ..Movie::default()
}]); }]);
radarr_data.selected_block = BlockSelectionState::new(&EDIT_MOVIE_SELECTION_BLOCKS);
app.data.radarr_data = radarr_data; app.data.radarr_data = radarr_data;
$handler::with(&DEFAULT_KEYBINDINGS.edit.key, &mut app, &$block, &None).handle(); $handler::with(&DEFAULT_KEYBINDINGS.edit.key, &mut app, &$block, &None).handle();
@@ -645,8 +651,8 @@ mod radarr_handler_test_utils {
&(ActiveRadarrBlock::EditMoviePrompt, Some($context)).into() &(ActiveRadarrBlock::EditMoviePrompt, Some($context)).into()
); );
assert_eq!( assert_eq!(
app.data.radarr_data.selected_block, app.data.radarr_data.selected_block.get_active_block(),
ActiveRadarrBlock::EditMovieToggleMonitored &ActiveRadarrBlock::EditMovieToggleMonitored
); );
assert_eq!( assert_eq!(
app.data.radarr_data.minimum_availability_list.items, app.data.radarr_data.minimum_availability_list.items,
@@ -702,6 +708,7 @@ mod radarr_handler_test_utils {
minimum_availability: MinimumAvailability::Released, minimum_availability: MinimumAvailability::Released,
..Collection::default() ..Collection::default()
}]); }]);
radarr_data.selected_block = BlockSelectionState::new(&EDIT_COLLECTION_SELECTION_BLOCKS);
app.data.radarr_data = radarr_data; app.data.radarr_data = radarr_data;
$handler::with(&DEFAULT_KEYBINDINGS.edit.key, &mut app, &$block, &None).handle(); $handler::with(&DEFAULT_KEYBINDINGS.edit.key, &mut app, &$block, &None).handle();
@@ -711,8 +718,8 @@ mod radarr_handler_test_utils {
&(ActiveRadarrBlock::EditCollectionPrompt, Some($context)).into() &(ActiveRadarrBlock::EditCollectionPrompt, Some($context)).into()
); );
assert_eq!( assert_eq!(
app.data.radarr_data.selected_block, app.data.radarr_data.selected_block.get_active_block(),
ActiveRadarrBlock::EditCollectionToggleMonitored &ActiveRadarrBlock::EditCollectionToggleMonitored
); );
assert_eq!( assert_eq!(
app.data.radarr_data.minimum_availability_list.items, app.data.radarr_data.minimum_availability_list.items,
@@ -951,8 +958,8 @@ mod tests {
&ActiveRadarrBlock::DeleteMoviePrompt.into() &ActiveRadarrBlock::DeleteMoviePrompt.into()
); );
assert_eq!( assert_eq!(
app.data.radarr_data.selected_block, app.data.radarr_data.selected_block.get_active_block(),
ActiveRadarrBlock::DeleteMovieToggleDeleteFile &ActiveRadarrBlock::DeleteMovieToggleDeleteFile
); );
} }
@@ -996,10 +1003,11 @@ mod tests {
use super::*; use super::*;
#[rstest] #[rstest]
#[case(ActiveRadarrBlock::Movies, 0, ActiveRadarrBlock::RootFolders)] #[case(ActiveRadarrBlock::Movies, 0, ActiveRadarrBlock::System)]
#[case(ActiveRadarrBlock::Downloads, 1, ActiveRadarrBlock::Movies)] #[case(ActiveRadarrBlock::System, 4, ActiveRadarrBlock::RootFolders)]
#[case(ActiveRadarrBlock::Collections, 2, ActiveRadarrBlock::Downloads)]
#[case(ActiveRadarrBlock::RootFolders, 3, ActiveRadarrBlock::Collections)] #[case(ActiveRadarrBlock::RootFolders, 3, ActiveRadarrBlock::Collections)]
#[case(ActiveRadarrBlock::Collections, 2, ActiveRadarrBlock::Downloads)]
#[case(ActiveRadarrBlock::Downloads, 1, ActiveRadarrBlock::Movies)]
fn test_radarr_tab_left( fn test_radarr_tab_left(
#[case] active_radarr_block: ActiveRadarrBlock, #[case] active_radarr_block: ActiveRadarrBlock,
#[case] index: usize, #[case] index: usize,
@@ -1027,7 +1035,8 @@ mod tests {
#[case(ActiveRadarrBlock::Movies, 0, ActiveRadarrBlock::Downloads)] #[case(ActiveRadarrBlock::Movies, 0, ActiveRadarrBlock::Downloads)]
#[case(ActiveRadarrBlock::Downloads, 1, ActiveRadarrBlock::Collections)] #[case(ActiveRadarrBlock::Downloads, 1, ActiveRadarrBlock::Collections)]
#[case(ActiveRadarrBlock::Collections, 2, ActiveRadarrBlock::RootFolders)] #[case(ActiveRadarrBlock::Collections, 2, ActiveRadarrBlock::RootFolders)]
#[case(ActiveRadarrBlock::RootFolders, 3, ActiveRadarrBlock::Movies)] #[case(ActiveRadarrBlock::RootFolders, 3, ActiveRadarrBlock::System)]
#[case(ActiveRadarrBlock::System, 4, ActiveRadarrBlock::Movies)]
fn test_radarr_tab_right( fn test_radarr_tab_right(
#[case] active_radarr_block: ActiveRadarrBlock, #[case] active_radarr_block: ActiveRadarrBlock,
#[case] index: usize, #[case] index: usize,
@@ -1549,7 +1558,10 @@ mod tests {
use crate::app::radarr::radarr_test_utils::create_test_radarr_data; use crate::app::radarr::radarr_test_utils::create_test_radarr_data;
use crate::app::radarr::RadarrData; use crate::app::radarr::RadarrData;
use crate::app::radarr::EDIT_COLLECTION_SELECTION_BLOCKS;
use crate::app::radarr::EDIT_MOVIE_SELECTION_BLOCKS;
use crate::models::radarr_models::MinimumAvailability; use crate::models::radarr_models::MinimumAvailability;
use crate::models::BlockSelectionState;
use crate::models::HorizontallyScrollableText; use crate::models::HorizontallyScrollableText;
use crate::models::StatefulTable; use crate::models::StatefulTable;
@@ -4,28 +4,28 @@ use serde_json::Number;
use strum::IntoEnumIterator; use strum::IntoEnumIterator;
use crate::app::key_binding::DEFAULT_KEYBINDINGS; use crate::app::key_binding::DEFAULT_KEYBINDINGS;
use crate::app::radarr::ActiveRadarrBlock; use crate::app::radarr::{ActiveRadarrBlock, EDIT_MOVIE_SELECTION_BLOCKS};
use crate::app::App; use crate::app::App;
use crate::event::Key; use crate::event::Key;
use crate::handlers::{handle_prompt_toggle, KeyEventHandler}; use crate::handlers::{handle_prompt_toggle, KeyEventHandler};
use crate::models::radarr_models::{Language, Release, ReleaseField}; use crate::models::radarr_models::{Language, Release, ReleaseField};
use crate::models::Scrollable; use crate::models::{BlockSelectionState, Scrollable};
use crate::network::radarr_network::RadarrEvent; use crate::network::radarr_network::RadarrEvent;
pub(super) struct MovieDetailsHandler<'a> { pub(super) struct MovieDetailsHandler<'a, 'b> {
key: &'a Key, key: &'a Key,
app: &'a mut App, app: &'a mut App<'b>,
active_radarr_block: &'a ActiveRadarrBlock, active_radarr_block: &'a ActiveRadarrBlock,
_context: &'a Option<ActiveRadarrBlock>, _context: &'a Option<ActiveRadarrBlock>,
} }
impl<'a> KeyEventHandler<'a, ActiveRadarrBlock> for MovieDetailsHandler<'a> { impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for MovieDetailsHandler<'a, 'b> {
fn with( fn with(
key: &'a Key, key: &'a Key,
app: &'a mut App, app: &'a mut App<'b>,
active_block: &'a ActiveRadarrBlock, active_block: &'a ActiveRadarrBlock,
_context: &'a Option<ActiveRadarrBlock>, _context: &'a Option<ActiveRadarrBlock>,
) -> MovieDetailsHandler<'a> { ) -> MovieDetailsHandler<'a, 'b> {
MovieDetailsHandler { MovieDetailsHandler {
key, key,
app, app,
@@ -234,7 +234,8 @@ impl<'a> KeyEventHandler<'a, ActiveRadarrBlock> for MovieDetailsHandler<'a> {
.into(), .into(),
); );
self.app.data.radarr_data.populate_edit_movie_fields(); self.app.data.radarr_data.populate_edit_movie_fields();
self.app.data.radarr_data.selected_block = ActiveRadarrBlock::EditMovieToggleMonitored; self.app.data.radarr_data.selected_block =
BlockSelectionState::new(&EDIT_MOVIE_SELECTION_BLOCKS);
} }
_ if *key == DEFAULT_KEYBINDINGS.update.key => { _ if *key == DEFAULT_KEYBINDINGS.update.key => {
self self
@@ -779,7 +780,9 @@ mod tests {
use crate::app::radarr::radarr_test_utils::create_test_radarr_data; use crate::app::radarr::radarr_test_utils::create_test_radarr_data;
use crate::app::radarr::RadarrData; use crate::app::radarr::RadarrData;
use crate::app::radarr::EDIT_MOVIE_SELECTION_BLOCKS;
use crate::models::radarr_models::{MinimumAvailability, Movie}; use crate::models::radarr_models::{MinimumAvailability, Movie};
use crate::models::BlockSelectionState;
use crate::models::HorizontallyScrollableText; use crate::models::HorizontallyScrollableText;
use crate::models::StatefulTable; use crate::models::StatefulTable;
use crate::test_edit_movie_key; use crate::test_edit_movie_key;
+2 -2
View File
@@ -57,7 +57,7 @@ async fn main() -> Result<()> {
} }
#[tokio::main] #[tokio::main]
async fn start_networking(mut network_rx: Receiver<NetworkEvent>, app: &Arc<Mutex<App>>) { async fn start_networking(mut network_rx: Receiver<NetworkEvent>, app: &Arc<Mutex<App<'_>>>) {
let network = Network::new(reqwest::Client::new(), app); let network = Network::new(reqwest::Client::new(), app);
while let Some(network_event) = network_rx.recv().await { while let Some(network_event) = network_rx.recv().await {
@@ -65,7 +65,7 @@ async fn start_networking(mut network_rx: Receiver<NetworkEvent>, app: &Arc<Mute
} }
} }
async fn start_ui(app: &Arc<Mutex<App>>) -> Result<()> { async fn start_ui(app: &Arc<Mutex<App<'_>>>) -> Result<()> {
let mut stdout = io::stdout(); let mut stdout = io::stdout();
enable_raw_mode()?; enable_raw_mode()?;
+136 -30
View File
@@ -250,12 +250,12 @@ impl HorizontallyScrollableText {
} }
} }
#[derive(Clone, PartialEq, Eq, Debug)] #[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub struct TabRoute { pub struct TabRoute {
pub title: String, pub title: &'static str,
pub route: Route, pub route: Route,
pub help: String, pub help: &'static str,
pub contextual_help: Option<String>, pub contextual_help: Option<&'static str>,
} }
pub struct TabState { pub struct TabState {
@@ -279,12 +279,12 @@ impl TabState {
&self.tabs[self.index].route &self.tabs[self.index].route
} }
pub fn get_active_tab_help(&self) -> String { pub fn get_active_tab_help(&self) -> &'static str {
self.tabs[self.index].help.clone() self.tabs[self.index].help
} }
pub fn get_active_tab_contextual_help(&self) -> Option<String> { pub fn get_active_tab_contextual_help(&self) -> Option<&'static str> {
self.tabs[self.index].contextual_help.clone() self.tabs[self.index].contextual_help
} }
pub fn next(&mut self) { pub fn next(&mut self) {
@@ -300,6 +300,50 @@ impl TabState {
} }
} }
#[derive(Default, Eq, PartialEq, Debug)]
pub struct BlockSelectionState<'a, T>
where
T: Sized + Clone + Copy + Default,
{
pub blocks: &'a [T],
pub index: usize,
}
impl<'a, T> BlockSelectionState<'a, T>
where
T: Sized + Clone + Copy + Default,
{
pub fn new(blocks: &'a [T]) -> BlockSelectionState<'a, T> {
BlockSelectionState { blocks, index: 0 }
}
pub fn get_active_block(&self) -> &T {
&self.blocks[self.index]
}
pub fn next(&mut self) {
self.index = (self.index + 1) % self.blocks.len();
}
pub fn previous(&mut self) {
if self.index > 0 {
self.index -= 1;
} else {
self.index = self.blocks.len() - 1;
}
}
}
#[cfg(test)]
impl<'a, T> BlockSelectionState<'a, T>
where
T: Sized + Clone + Copy + Default,
{
pub fn set_index(&mut self, index: usize) {
self.index = index;
}
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use std::cell::RefCell; use std::cell::RefCell;
@@ -308,9 +352,19 @@ mod tests {
use crate::app::radarr::ActiveRadarrBlock; use crate::app::radarr::ActiveRadarrBlock;
use crate::models::{ use crate::models::{
HorizontallyScrollableText, Scrollable, ScrollableText, StatefulTable, TabRoute, TabState, BlockSelectionState, HorizontallyScrollableText, Scrollable, ScrollableText, StatefulTable,
TabRoute, TabState,
}; };
const BLOCKS: [ActiveRadarrBlock; 6] = [
ActiveRadarrBlock::AddMovieSelectRootFolder,
ActiveRadarrBlock::AddMovieSelectMonitor,
ActiveRadarrBlock::AddMovieSelectMinimumAvailability,
ActiveRadarrBlock::AddMovieSelectQualityProfile,
ActiveRadarrBlock::AddMovieTagsInput,
ActiveRadarrBlock::AddMovieConfirmPrompt,
];
#[test] #[test]
fn test_stateful_table_scroll() { fn test_stateful_table_scroll() {
let mut stateful_table = create_test_stateful_table(); let mut stateful_table = create_test_stateful_table();
@@ -672,11 +726,9 @@ mod tests {
#[test] #[test]
fn test_tab_state_get_active_route() { fn test_tab_state_get_active_route() {
let second_tab = create_test_tab_routes()[1].clone().route; let tabs = create_test_tab_routes();
let tab_state = TabState { let second_tab = tabs[1].route;
tabs: create_test_tab_routes(), let tab_state = TabState { tabs, index: 1 };
index: 1,
};
let active_route = tab_state.get_active_route(); let active_route = tab_state.get_active_route();
@@ -685,11 +737,9 @@ mod tests {
#[test] #[test]
fn test_tab_state_get_active_tab_help() { fn test_tab_state_get_active_tab_help() {
let second_tab_help = create_test_tab_routes()[1].clone().help; let tabs = create_test_tab_routes();
let tab_state = TabState { let second_tab_help = tabs[1].help;
tabs: create_test_tab_routes(), let tab_state = TabState { tabs, index: 1 };
index: 1,
};
let tab_help = tab_state.get_active_tab_help(); let tab_help = tab_state.get_active_tab_help();
@@ -698,11 +748,9 @@ mod tests {
#[test] #[test]
fn test_tab_state_get_active_tab_contextual_help() { fn test_tab_state_get_active_tab_contextual_help() {
let second_tab_contextual_help = create_test_tab_routes()[1].clone().contextual_help.unwrap(); let tabs = create_test_tab_routes();
let tab_state = TabState { let second_tab_contextual_help = tabs[1].contextual_help.unwrap();
tabs: create_test_tab_routes(), let tab_state = TabState { tabs, index: 1 };
index: 1,
};
let tab_contextual_help = tab_state.get_active_tab_contextual_help(); let tab_contextual_help = tab_state.get_active_tab_contextual_help();
@@ -742,19 +790,77 @@ mod tests {
assert_eq!(tab_state.get_active_route(), &tab_routes[0].route); assert_eq!(tab_state.get_active_route(), &tab_routes[0].route);
} }
#[test]
fn test_block_selection_state_new() {
let block_selection_state = BlockSelectionState::new(&BLOCKS);
assert_eq!(block_selection_state.index, 0);
}
#[test]
fn test_block_selection_state_get_active_block() {
let second_block = BLOCKS[1];
let block_selection_state = BlockSelectionState {
blocks: &BLOCKS,
index: 1,
};
let active_block = block_selection_state.get_active_block();
assert_eq!(active_block, &second_block);
}
#[test]
fn test_block_selection_state_next() {
let blocks = [
ActiveRadarrBlock::AddMovieSelectRootFolder,
ActiveRadarrBlock::AddMovieSelectMonitor,
];
let mut block_selection_state = BlockSelectionState::new(&blocks);
assert_eq!(block_selection_state.get_active_block(), &blocks[0]);
block_selection_state.next();
assert_eq!(block_selection_state.get_active_block(), &blocks[1]);
block_selection_state.next();
assert_eq!(block_selection_state.get_active_block(), &blocks[0]);
}
#[test]
fn test_block_selection_state_previous() {
let blocks = [
ActiveRadarrBlock::AddMovieSelectRootFolder,
ActiveRadarrBlock::AddMovieSelectMonitor,
];
let mut block_selection_state = BlockSelectionState::new(&blocks);
assert_eq!(block_selection_state.get_active_block(), &blocks[0]);
block_selection_state.previous();
assert_eq!(block_selection_state.get_active_block(), &blocks[1]);
block_selection_state.previous();
assert_eq!(block_selection_state.get_active_block(), &blocks[0]);
}
fn create_test_tab_routes() -> Vec<TabRoute> { fn create_test_tab_routes() -> Vec<TabRoute> {
vec![ vec![
TabRoute { TabRoute {
title: "Test 1".to_owned(), title: "Test 1",
route: ActiveRadarrBlock::Movies.into(), route: ActiveRadarrBlock::Movies.into(),
help: "Help for Test 1".to_owned(), help: "Help for Test 1",
contextual_help: Some("Contextual Help for Test 1".to_owned()), contextual_help: Some("Contextual Help for Test 1"),
}, },
TabRoute { TabRoute {
title: "Test 2".to_owned(), title: "Test 2",
route: ActiveRadarrBlock::Collections.into(), route: ActiveRadarrBlock::Collections.into(),
help: "Help for Test 2".to_owned(), help: "Help for Test 2",
contextual_help: Some("Contextual Help for Test 2".to_owned()), contextual_help: Some("Contextual Help for Test 2"),
}, },
] ]
} }
+7 -7
View File
@@ -21,13 +21,13 @@ pub enum NetworkEvent {
Radarr(RadarrEvent), Radarr(RadarrEvent),
} }
pub struct Network<'a> { pub struct Network<'a, 'b> {
pub client: Client, pub client: Client,
pub app: &'a Arc<Mutex<App>>, pub app: &'a Arc<Mutex<App<'b>>>,
} }
impl<'a> Network<'a> { impl<'a, 'b> Network<'a, 'b> {
pub fn new(client: Client, app: &'a Arc<Mutex<App>>) -> Self { pub fn new(client: Client, app: &'a Arc<Mutex<App<'b>>>) -> Self {
Network { client, app } Network { client, app }
} }
@@ -43,7 +43,7 @@ impl<'a> Network<'a> {
pub async fn handle_request<B, R>( pub async fn handle_request<B, R>(
&self, &self,
request_props: RequestProps<B>, request_props: RequestProps<B>,
mut app_update_fn: impl FnMut(R, MutexGuard<'_, App>), mut app_update_fn: impl FnMut(R, MutexGuard<'_, App<'_>>),
) where ) where
B: Serialize + Default + Debug, B: Serialize + Default + Debug,
R: DeserializeOwned, R: DeserializeOwned,
@@ -427,11 +427,11 @@ mod tests {
pub value: String, pub value: String,
} }
async fn mock_api( async fn mock_api<'a>(
method: RequestMethod, method: RequestMethod,
response_status: usize, response_status: usize,
has_response_body: bool, has_response_body: bool,
) -> (Mock, Arc<Mutex<App>>, ServerGuard) { ) -> (Mock, Arc<Mutex<App<'a>>>, ServerGuard) {
let mut server = Server::new_async().await; let mut server = Server::new_async().await;
let mut async_server = server let mut async_server = server
.mock(&method.to_string().to_uppercase(), "/test") .mock(&method.to_string().to_uppercase(), "/test")
+41 -62
View File
@@ -86,7 +86,7 @@ impl From<RadarrEvent> for NetworkEvent {
} }
} }
impl<'a> Network<'a> { impl<'a, 'b> Network<'a, 'b> {
pub async fn handle_radarr_event(&self, radarr_event: RadarrEvent) { pub async fn handle_radarr_event(&self, radarr_event: RadarrEvent) {
match radarr_event { match radarr_event {
RadarrEvent::AddMovie => self.add_movie().await, RadarrEvent::AddMovie => self.add_movie().await,
@@ -1533,13 +1533,9 @@ mod test {
"languages": [ { "name": "English" } ], "languages": [ { "name": "English" } ],
"quality": { "quality": { "name": "HD - 1080p" }} "quality": { "quality": { "name": "HD - 1080p" }}
}]); }]);
let (async_server, app_arc, _server) = mock_radarr_api( let resource = format!("{}?movieId=1", RadarrEvent::GetReleases.resource());
RequestMethod::Get, let (async_server, app_arc, _server) =
None, mock_radarr_api(RequestMethod::Get, None, Some(release_json), &resource).await;
Some(release_json),
format!("{}?movieId=1", RadarrEvent::GetReleases.resource()).as_str(),
)
.await;
app_arc app_arc
.lock() .lock()
.await .await
@@ -1581,15 +1577,15 @@ mod test {
} }
} }
}]); }]);
let resource = format!(
"{}?term=test%20term",
RadarrEvent::SearchNewMovie.resource()
);
let (async_server, app_arc, _server) = mock_radarr_api( let (async_server, app_arc, _server) = mock_radarr_api(
RequestMethod::Get, RequestMethod::Get,
None, None,
Some(add_movie_search_result_json), Some(add_movie_search_result_json),
format!( &resource,
"{}?term=test%20term",
RadarrEvent::SearchNewMovie.resource()
)
.as_str(),
) )
.await; .await;
app_arc.lock().await.data.radarr_data.search = "test term".to_owned().into(); app_arc.lock().await.data.radarr_data.search = "test term".to_owned().into();
@@ -1614,17 +1610,12 @@ mod test {
#[tokio::test] #[tokio::test]
async fn test_handle_search_new_movie_event_no_results() { async fn test_handle_search_new_movie_event_no_results() {
let (async_server, app_arc, _server) = mock_radarr_api( let resource = format!(
RequestMethod::Get, "{}?term=test%20term",
None, RadarrEvent::SearchNewMovie.resource()
Some(json!([])), );
format!( let (async_server, app_arc, _server) =
"{}?term=test%20term", mock_radarr_api(RequestMethod::Get, None, Some(json!([])), &resource).await;
RadarrEvent::SearchNewMovie.resource()
)
.as_str(),
)
.await;
app_arc.lock().await.data.radarr_data.search = "test term".to_owned().into(); app_arc.lock().await.data.radarr_data.search = "test term".to_owned().into();
let network = Network::new(reqwest::Client::new(), &app_arc); let network = Network::new(reqwest::Client::new(), &app_arc);
@@ -1766,11 +1757,12 @@ mod test {
#[tokio::test] #[tokio::test]
async fn test_handle_get_movie_details_event() { async fn test_handle_get_movie_details_event() {
let resource = format!("{}/1", RadarrEvent::GetMovieDetails.resource());
let (async_server, app_arc, _server) = mock_radarr_api( let (async_server, app_arc, _server) = mock_radarr_api(
RequestMethod::Get, RequestMethod::Get,
None, None,
Some(serde_json::from_str(MOVIE_JSON).unwrap()), Some(serde_json::from_str(MOVIE_JSON).unwrap()),
format!("{}/1", RadarrEvent::GetMovieDetails.resource()).as_str(), &resource,
) )
.await; .await;
app_arc app_arc
@@ -1872,11 +1864,12 @@ mod test {
"minimumAvailability": "released", "minimumAvailability": "released",
"ratings": {} "ratings": {}
}); });
let resource = format!("{}/1", RadarrEvent::GetMovieDetails.resource());
let (async_server, app_arc, _server) = mock_radarr_api( let (async_server, app_arc, _server) = mock_radarr_api(
RequestMethod::Get, RequestMethod::Get,
None, None,
Some(movie_json_with_missing_fields), Some(movie_json_with_missing_fields),
format!("{}/1", RadarrEvent::GetMovieDetails.resource()).as_str(), &resource,
) )
.await; .await;
app_arc app_arc
@@ -1953,11 +1946,12 @@ mod test {
"date": "2022-12-30T07:37:56Z", "date": "2022-12-30T07:37:56Z",
"eventType": "grabbed" "eventType": "grabbed"
}]); }]);
let resource = format!("{}?movieId=1", RadarrEvent::GetMovieHistory.resource());
let (async_server, app_arc, _server) = mock_radarr_api( let (async_server, app_arc, _server) = mock_radarr_api(
RequestMethod::Get, RequestMethod::Get,
None, None,
Some(movie_history_item_json), Some(movie_history_item_json),
format!("{}?movieId=1", RadarrEvent::GetMovieHistory.resource()).as_str(), &resource,
) )
.await; .await;
app_arc app_arc
@@ -2183,13 +2177,9 @@ mod test {
"type": "crew", "type": "crew",
} }
]); ]);
let (async_server, app_arc, _server) = mock_radarr_api( let resource = format!("{}?movieId=1", RadarrEvent::GetMovieCredits.resource());
RequestMethod::Get, let (async_server, app_arc, _server) =
None, mock_radarr_api(RequestMethod::Get, None, Some(credits_json), &resource).await;
Some(credits_json),
format!("{}?movieId=1", RadarrEvent::GetMovieCredits.resource()).as_str(),
)
.await;
app_arc app_arc
.lock() .lock()
.await .await
@@ -2216,17 +2206,12 @@ mod test {
#[tokio::test] #[tokio::test]
async fn test_handle_delete_movie_event() { async fn test_handle_delete_movie_event() {
let (async_server, app_arc, _server) = mock_radarr_api( let resource = format!(
RequestMethod::Delete, "{}/1?deleteFiles=true&addImportExclusion=true",
None, RadarrEvent::DeleteMovie.resource()
None, );
format!( let (async_server, app_arc, _server) =
"{}/1?deleteFiles=true&addImportExclusion=true", mock_radarr_api(RequestMethod::Delete, None, None, &resource).await;
RadarrEvent::DeleteMovie.resource()
)
.as_str(),
)
.await;
{ {
let mut app = app_arc.lock().await; let mut app = app_arc.lock().await;
app.data.radarr_data.movies.set_items(vec![movie()]); app.data.radarr_data.movies.set_items(vec![movie()]);
@@ -2244,13 +2229,9 @@ mod test {
#[tokio::test] #[tokio::test]
async fn test_handle_delete_download_event() { async fn test_handle_delete_download_event() {
let (async_server, app_arc, _server) = mock_radarr_api( let resource = format!("{}/1", RadarrEvent::DeleteDownload.resource());
RequestMethod::Delete, let (async_server, app_arc, _server) =
None, mock_radarr_api(RequestMethod::Delete, None, None, &resource).await;
None,
format!("{}/1", RadarrEvent::DeleteDownload.resource()).as_str(),
)
.await;
app_arc app_arc
.lock() .lock()
.await .await
@@ -2269,13 +2250,9 @@ mod test {
#[tokio::test] #[tokio::test]
async fn test_handle_delete_root_folder_event() { async fn test_handle_delete_root_folder_event() {
let (async_server, app_arc, _server) = mock_radarr_api( let resource = format!("{}/1", RadarrEvent::DeleteRootFolder.resource());
RequestMethod::Delete, let (async_server, app_arc, _server) =
None, mock_radarr_api(RequestMethod::Delete, None, None, &resource).await;
None,
format!("{}/1", RadarrEvent::DeleteRootFolder.resource()).as_str(),
)
.await;
app_arc app_arc
.lock() .lock()
.await .await
@@ -2415,11 +2392,12 @@ mod test {
*expected_body.get_mut("path").unwrap() = json!("/nfs/Test Path"); *expected_body.get_mut("path").unwrap() = json!("/nfs/Test Path");
*expected_body.get_mut("tags").unwrap() = json!([1, 2]); *expected_body.get_mut("tags").unwrap() = json!([1, 2]);
let resource = format!("{}/1", RadarrEvent::GetMovieDetails.resource());
let (async_details_server, app_arc, mut server) = mock_radarr_api( let (async_details_server, app_arc, mut server) = mock_radarr_api(
RequestMethod::Get, RequestMethod::Get,
None, None,
Some(serde_json::from_str(MOVIE_JSON).unwrap()), Some(serde_json::from_str(MOVIE_JSON).unwrap()),
format!("{}/1", RadarrEvent::GetMovieDetails.resource()).as_str(), &resource,
) )
.await; .await;
let async_edit_server = server let async_edit_server = server
@@ -2510,11 +2488,12 @@ mod test {
*expected_body.get_mut("rootFolderPath").unwrap() = json!("/nfs/Test Path"); *expected_body.get_mut("rootFolderPath").unwrap() = json!("/nfs/Test Path");
*expected_body.get_mut("searchOnAdd").unwrap() = json!(false); *expected_body.get_mut("searchOnAdd").unwrap() = json!(false);
let resource = format!("{}/123", RadarrEvent::GetCollections.resource());
let (async_details_server, app_arc, mut server) = mock_radarr_api( let (async_details_server, app_arc, mut server) = mock_radarr_api(
RequestMethod::Get, RequestMethod::Get,
None, None,
Some(detailed_collection_body), Some(detailed_collection_body),
format!("{}/123", RadarrEvent::GetCollections.resource()).as_str(), &resource,
) )
.await; .await;
let async_edit_server = server let async_edit_server = server
@@ -2854,7 +2833,7 @@ mod test {
request_body: Option<Value>, request_body: Option<Value>,
response_body: Option<Value>, response_body: Option<Value>,
resource: &str, resource: &str,
) -> (Mock, Arc<Mutex<App>>, ServerGuard) { ) -> (Mock, Arc<Mutex<App<'_>>>, ServerGuard) {
let mut server = Server::new_async().await; let mut server = Server::new_async().await;
let mut async_server = server let mut async_server = server
.mock( .mock(
+29 -29
View File
@@ -29,7 +29,7 @@ mod utils;
static HIGHLIGHT_SYMBOL: &str = "=> "; static HIGHLIGHT_SYMBOL: &str = "=> ";
pub fn ui<B: Backend>(f: &mut Frame<'_, B>, app: &mut App) { pub fn ui<B: Backend>(f: &mut Frame<'_, B>, app: &mut App<'_>) {
f.render_widget(background_block(), f.size()); f.render_widget(background_block(), f.size());
let main_chunks = if !app.error.text.is_empty() { let main_chunks = if !app.error.text.is_empty() {
let chunks = vertical_chunks_with_margin( let chunks = vertical_chunks_with_margin(
@@ -65,7 +65,7 @@ pub fn ui<B: Backend>(f: &mut Frame<'_, B>, app: &mut App) {
} }
} }
fn draw_header_row<B: Backend>(f: &mut Frame<'_, B>, app: &mut App, area: Rect) { fn draw_header_row<B: Backend>(f: &mut Frame<'_, B>, app: &mut App<'_>, area: Rect) {
let chunks = let chunks =
horizontal_chunks_with_margin(vec![Constraint::Length(75), Constraint::Min(0)], area, 1); horizontal_chunks_with_margin(vec![Constraint::Length(75), Constraint::Min(0)], area, 1);
let help_text = Text::from(app.server_tabs.get_active_tab_help()); let help_text = Text::from(app.server_tabs.get_active_tab_help());
@@ -74,7 +74,7 @@ fn draw_header_row<B: Backend>(f: &mut Frame<'_, B>, app: &mut App, area: Rect)
.server_tabs .server_tabs
.tabs .tabs
.iter() .iter()
.map(|tab| Spans::from(Span::styled(&tab.title, style_default_bold()))) .map(|tab| Spans::from(Span::styled(tab.title, style_default_bold())))
.collect(); .collect();
let tabs = Tabs::new(titles) let tabs = Tabs::new(titles)
.block(logo_block()) .block(logo_block())
@@ -89,7 +89,7 @@ fn draw_header_row<B: Backend>(f: &mut Frame<'_, B>, app: &mut App, area: Rect)
f.render_widget(help, chunks[1]); f.render_widget(help, chunks[1]);
} }
fn draw_error<B: Backend>(f: &mut Frame<'_, B>, app: &mut App, area: Rect) { fn draw_error<B: Backend>(f: &mut Frame<'_, B>, app: &mut App<'_>, area: Rect) {
let block = let block =
title_block("Error | <esc> to close").style(style_failure().add_modifier(Modifier::BOLD)); title_block("Error | <esc> to close").style(style_failure().add_modifier(Modifier::BOLD));
@@ -112,8 +112,8 @@ fn draw_error<B: Backend>(f: &mut Frame<'_, B>, app: &mut App, area: Rect) {
pub fn draw_popup<B: Backend>( pub fn draw_popup<B: Backend>(
f: &mut Frame<'_, B>, f: &mut Frame<'_, B>,
app: &mut App, app: &mut App<'_>,
popup_fn: fn(&mut Frame<'_, B>, &mut App, Rect), popup_fn: fn(&mut Frame<'_, B>, &mut App<'_>, Rect),
percent_x: u16, percent_x: u16,
percent_y: u16, percent_y: u16,
) { ) {
@@ -125,10 +125,10 @@ pub fn draw_popup<B: Backend>(
pub fn draw_popup_over<B: Backend>( pub fn draw_popup_over<B: Backend>(
f: &mut Frame<'_, B>, f: &mut Frame<'_, B>,
app: &mut App, app: &mut App<'_>,
area: Rect, area: Rect,
background_fn: fn(&mut Frame<'_, B>, &mut App, Rect), background_fn: fn(&mut Frame<'_, B>, &mut App<'_>, Rect),
popup_fn: fn(&mut Frame<'_, B>, &mut App, Rect), popup_fn: fn(&mut Frame<'_, B>, &mut App<'_>, Rect),
percent_x: u16, percent_x: u16,
percent_y: u16, percent_y: u16,
) { ) {
@@ -139,55 +139,55 @@ pub fn draw_popup_over<B: Backend>(
pub fn draw_prompt_popup_over<B: Backend>( pub fn draw_prompt_popup_over<B: Backend>(
f: &mut Frame<'_, B>, f: &mut Frame<'_, B>,
app: &mut App, app: &mut App<'_>,
area: Rect, area: Rect,
background_fn: fn(&mut Frame<'_, B>, &mut App, Rect), background_fn: fn(&mut Frame<'_, B>, &mut App<'_>, Rect),
popup_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, 35, 35); draw_popup_over(f, app, area, background_fn, popup_fn, 35, 35);
} }
pub fn draw_small_popup_over<B: Backend>( pub fn draw_small_popup_over<B: Backend>(
f: &mut Frame<'_, B>, f: &mut Frame<'_, B>,
app: &mut App, app: &mut App<'_>,
area: Rect, area: Rect,
background_fn: fn(&mut Frame<'_, B>, &mut App, Rect), background_fn: fn(&mut Frame<'_, B>, &mut App<'_>, Rect),
popup_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, 40, 40); draw_popup_over(f, app, area, background_fn, popup_fn, 40, 40);
} }
pub fn draw_medium_popup_over<B: Backend>( pub fn draw_medium_popup_over<B: Backend>(
f: &mut Frame<'_, B>, f: &mut Frame<'_, B>,
app: &mut App, app: &mut App<'_>,
area: Rect, area: Rect,
background_fn: fn(&mut Frame<'_, B>, &mut App, Rect), background_fn: fn(&mut Frame<'_, B>, &mut App<'_>, Rect),
popup_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, 60, 60); draw_popup_over(f, app, area, background_fn, popup_fn, 60, 60);
} }
pub fn draw_large_popup_over<B: Backend>( pub fn draw_large_popup_over<B: Backend>(
f: &mut Frame<'_, B>, f: &mut Frame<'_, B>,
app: &mut App, app: &mut App<'_>,
area: Rect, area: Rect,
background_fn: fn(&mut Frame<'_, B>, &mut App, Rect), background_fn: fn(&mut Frame<'_, B>, &mut App<'_>, Rect),
popup_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, 75, 75); draw_popup_over(f, app, area, background_fn, popup_fn, 75, 75);
} }
pub fn draw_drop_down_popup<B: Backend>( pub fn draw_drop_down_popup<B: Backend>(
f: &mut Frame<'_, B>, f: &mut Frame<'_, B>,
app: &mut App, app: &mut App<'_>,
area: Rect, area: Rect,
background_fn: fn(&mut Frame<'_, B>, &mut App, Rect), background_fn: fn(&mut Frame<'_, B>, &mut App<'_>, Rect),
drop_down_fn: fn(&mut Frame<'_, B>, &mut App, Rect), drop_down_fn: fn(&mut Frame<'_, B>, &mut App<'_>, Rect),
) { ) {
draw_popup_over(f, app, area, background_fn, drop_down_fn, 20, 30); draw_popup_over(f, app, area, background_fn, drop_down_fn, 20, 30);
} }
fn draw_context_row<B: Backend>(f: &mut Frame<'_, B>, app: &App, area: Rect) { fn draw_context_row<B: Backend>(f: &mut Frame<'_, B>, app: &App<'_>, area: Rect) {
if let Route::Radarr(_, _) = app.get_current_route() { if let Route::Radarr(_, _) = app.get_current_route() {
radarr_ui::draw_radarr_context_row(f, app, area) radarr_ui::draw_radarr_context_row(f, app, area)
} }
@@ -195,10 +195,10 @@ fn draw_context_row<B: Backend>(f: &mut Frame<'_, B>, app: &App, area: Rect) {
pub fn draw_error_popup_over<B: Backend>( pub fn draw_error_popup_over<B: Backend>(
f: &mut Frame<'_, B>, f: &mut Frame<'_, B>,
app: &mut App, app: &mut App<'_>,
area: Rect, area: Rect,
message: &str, message: &str,
background_fn: fn(&mut Frame<'_, B>, &mut App, Rect), background_fn: fn(&mut Frame<'_, B>, &mut App<'_>, Rect),
) { ) {
background_fn(f, app, area); background_fn(f, app, area);
draw_error_popup(f, message); draw_error_popup(f, message);
@@ -238,7 +238,7 @@ fn draw_tabs<'a, B: Backend>(
let titles = tab_state let titles = tab_state
.tabs .tabs
.iter() .iter()
.map(|tab_route| Spans::from(Span::styled(&tab_route.title, style_default_bold()))) .map(|tab_route| Spans::from(Span::styled(tab_route.title, style_default_bold())))
.collect(); .collect();
let tabs = Tabs::new(titles) let tabs = Tabs::new(titles)
.block(block) .block(block)
@@ -258,7 +258,7 @@ pub struct TableProps<'a, T> {
pub content: &'a mut StatefulTable<T>, pub content: &'a mut StatefulTable<T>,
pub table_headers: Vec<&'a str>, pub table_headers: Vec<&'a str>,
pub constraints: Vec<Constraint>, pub constraints: Vec<Constraint>,
pub help: Option<String>, pub help: Option<&'static str>,
} }
fn draw_table<'a, B, T, F>( fn draw_table<'a, B, T, F>(
+20 -12
View File
@@ -27,7 +27,7 @@ use crate::App;
pub(super) fn draw_add_movie_search_popup<B: Backend>( pub(super) fn draw_add_movie_search_popup<B: Backend>(
f: &mut Frame<'_, B>, f: &mut Frame<'_, B>,
app: &mut App, app: &mut App<'_>,
area: Rect, area: Rect,
) { ) {
if let Route::Radarr(active_radarr_block, context_option) = *app.get_current_route() { if let Route::Radarr(active_radarr_block, context_option) = *app.get_current_route() {
@@ -67,7 +67,7 @@ pub(super) fn draw_add_movie_search_popup<B: Backend>(
} }
} }
fn draw_add_movie_search<B: Backend>(f: &mut Frame<'_, B>, app: &mut App, area: Rect) { fn draw_add_movie_search<B: Backend>(f: &mut Frame<'_, B>, app: &mut App<'_>, area: Rect) {
let current_selection = if app.data.radarr_data.add_searched_movies.items.is_empty() { let current_selection = if app.data.radarr_data.add_searched_movies.items.is_empty() {
AddMovieSearchResult::default() AddMovieSearchResult::default()
} else { } else {
@@ -233,7 +233,7 @@ fn draw_add_movie_search<B: Backend>(f: &mut Frame<'_, B>, app: &mut App, area:
); );
} }
fn draw_confirmation_popup<B: Backend>(f: &mut Frame<'_, B>, app: &mut App, prompt_area: Rect) { fn draw_confirmation_popup<B: Backend>(f: &mut Frame<'_, B>, app: &mut App<'_>, prompt_area: Rect) {
if let Route::Radarr(active_radarr_block, _) = *app.get_current_route() { if let Route::Radarr(active_radarr_block, _) = *app.get_current_route() {
match active_radarr_block { match active_radarr_block {
ActiveRadarrBlock::AddMovieSelectMonitor => { ActiveRadarrBlock::AddMovieSelectMonitor => {
@@ -280,7 +280,11 @@ fn draw_confirmation_popup<B: Backend>(f: &mut Frame<'_, B>, app: &mut App, prom
} }
} }
fn draw_select_monitor_popup<B: Backend>(f: &mut Frame<'_, B>, app: &mut App, popup_area: Rect) { fn draw_select_monitor_popup<B: Backend>(
f: &mut Frame<'_, B>,
app: &mut App<'_>,
popup_area: Rect,
) {
draw_drop_down_list( draw_drop_down_list(
f, f,
popup_area, popup_area,
@@ -289,7 +293,11 @@ fn draw_select_monitor_popup<B: Backend>(f: &mut Frame<'_, B>, app: &mut App, po
); );
} }
fn draw_confirmation_prompt<B: Backend>(f: &mut Frame<'_, B>, app: &mut App, prompt_area: Rect) { fn draw_confirmation_prompt<B: Backend>(
f: &mut Frame<'_, B>,
app: &mut App<'_>,
prompt_area: Rect,
) {
let (movie_title, movie_overview) = if let Route::Radarr(_, Some(_)) = app.get_current_route() { let (movie_title, movie_overview) = if let Route::Radarr(_, Some(_)) = app.get_current_route() {
( (
&app &app
@@ -328,8 +336,8 @@ fn draw_confirmation_prompt<B: Backend>(f: &mut Frame<'_, B>, app: &mut App, pro
let title = format!("Add Movie - {}", movie_title); let title = format!("Add Movie - {}", movie_title);
let prompt = movie_overview; let prompt = movie_overview;
let yes_no_value = app.data.radarr_data.prompt_confirm; let yes_no_value = app.data.radarr_data.prompt_confirm;
let selected_block = app.data.radarr_data.selected_block; let selected_block = app.data.radarr_data.selected_block.get_active_block();
let highlight_yes_no = selected_block == ActiveRadarrBlock::AddMovieConfirmPrompt; let highlight_yes_no = selected_block == &ActiveRadarrBlock::AddMovieConfirmPrompt;
let selected_monitor = app.data.radarr_data.monitor_list.current_selection(); let selected_monitor = app.data.radarr_data.monitor_list.current_selection();
let selected_minimum_availability = app let selected_minimum_availability = app
@@ -374,7 +382,7 @@ fn draw_confirmation_prompt<B: Backend>(f: &mut Frame<'_, B>, app: &mut App, pro
chunks[1], chunks[1],
"Root Folder", "Root Folder",
&selected_root_folder.path, &selected_root_folder.path,
selected_block == ActiveRadarrBlock::AddMovieSelectRootFolder, selected_block == &ActiveRadarrBlock::AddMovieSelectRootFolder,
); );
draw_drop_down_menu_button( draw_drop_down_menu_button(
@@ -382,7 +390,7 @@ fn draw_confirmation_prompt<B: Backend>(f: &mut Frame<'_, B>, app: &mut App, pro
chunks[2], chunks[2],
"Monitor", "Monitor",
selected_monitor.to_display_str(), selected_monitor.to_display_str(),
selected_block == ActiveRadarrBlock::AddMovieSelectMonitor, selected_block == &ActiveRadarrBlock::AddMovieSelectMonitor,
); );
draw_drop_down_menu_button( draw_drop_down_menu_button(
@@ -390,14 +398,14 @@ fn draw_confirmation_prompt<B: Backend>(f: &mut Frame<'_, B>, app: &mut App, pro
chunks[3], chunks[3],
"Minimum Availability", "Minimum Availability",
selected_minimum_availability.to_display_str(), selected_minimum_availability.to_display_str(),
selected_block == ActiveRadarrBlock::AddMovieSelectMinimumAvailability, selected_block == &ActiveRadarrBlock::AddMovieSelectMinimumAvailability,
); );
draw_drop_down_menu_button( draw_drop_down_menu_button(
f, f,
chunks[4], chunks[4],
"Quality Profile", "Quality Profile",
selected_quality_profile, selected_quality_profile,
selected_block == ActiveRadarrBlock::AddMovieSelectQualityProfile, selected_block == &ActiveRadarrBlock::AddMovieSelectQualityProfile,
); );
if let Route::Radarr(active_radarr_block, _) = *app.get_current_route() { if let Route::Radarr(active_radarr_block, _) = *app.get_current_route() {
@@ -407,7 +415,7 @@ fn draw_confirmation_prompt<B: Backend>(f: &mut Frame<'_, B>, app: &mut App, pro
"Tags", "Tags",
&app.data.radarr_data.edit_tags.text, &app.data.radarr_data.edit_tags.text,
*app.data.radarr_data.edit_tags.offset.borrow(), *app.data.radarr_data.edit_tags.offset.borrow(),
selected_block == ActiveRadarrBlock::AddMovieTagsInput, selected_block == &ActiveRadarrBlock::AddMovieTagsInput,
active_radarr_block == ActiveRadarrBlock::AddMovieTagsInput, active_radarr_block == ActiveRadarrBlock::AddMovieTagsInput,
); );
} }
+3 -3
View File
@@ -18,7 +18,7 @@ use crate::utils::convert_runtime;
pub(super) fn draw_collection_details_popup<B: Backend>( pub(super) fn draw_collection_details_popup<B: Backend>(
f: &mut Frame<'_, B>, f: &mut Frame<'_, B>,
app: &mut App, app: &mut App<'_>,
content_area: Rect, content_area: Rect,
) { ) {
if let Route::Radarr(active_radarr_block, context_option) = app.get_current_route() { if let Route::Radarr(active_radarr_block, context_option) = app.get_current_route() {
@@ -40,7 +40,7 @@ pub(super) fn draw_collection_details_popup<B: Backend>(
pub(super) fn draw_collection_details<B: Backend>( pub(super) fn draw_collection_details<B: Backend>(
f: &mut Frame<'_, B>, f: &mut Frame<'_, B>,
app: &mut App, app: &mut App<'_>,
content_area: Rect, content_area: Rect,
) { ) {
let chunks = vertical_chunks_with_margin( let chunks = vertical_chunks_with_margin(
@@ -213,7 +213,7 @@ pub(super) fn draw_collection_details<B: Backend>(
); );
} }
fn draw_movie_overview<B: Backend>(f: &mut Frame<'_, B>, app: &mut App, content_area: Rect) { fn draw_movie_overview<B: Backend>(f: &mut Frame<'_, B>, app: &mut App<'_>, content_area: Rect) {
let title_block = title_block("Overview"); let title_block = title_block("Overview");
f.render_widget(title_block, content_area); f.render_widget(title_block, content_area);
+5 -5
View File
@@ -9,14 +9,14 @@ use crate::ui::draw_prompt_box_with_checkboxes;
pub(super) fn draw_delete_movie_prompt<B: Backend>( pub(super) fn draw_delete_movie_prompt<B: Backend>(
f: &mut Frame<'_, B>, f: &mut Frame<'_, B>,
app: &mut App, app: &mut App<'_>,
prompt_area: Rect, prompt_area: Rect,
) { ) {
if matches!( if matches!(
*app.get_current_route(), *app.get_current_route(),
Route::Radarr(ActiveRadarrBlock::DeleteMoviePrompt, _) Route::Radarr(ActiveRadarrBlock::DeleteMoviePrompt, _)
) { ) {
let selected_block = app.data.radarr_data.selected_block; let selected_block = app.data.radarr_data.selected_block.get_active_block();
draw_prompt_box_with_checkboxes( draw_prompt_box_with_checkboxes(
f, f,
prompt_area, prompt_area,
@@ -30,15 +30,15 @@ pub(super) fn draw_delete_movie_prompt<B: Backend>(
( (
"Delete Movie Files", "Delete Movie Files",
app.data.radarr_data.delete_movie_files, app.data.radarr_data.delete_movie_files,
selected_block == ActiveRadarrBlock::DeleteMovieToggleDeleteFile, selected_block == &ActiveRadarrBlock::DeleteMovieToggleDeleteFile,
), ),
( (
"Add List Exclusion", "Add List Exclusion",
app.data.radarr_data.add_list_exclusion, app.data.radarr_data.add_list_exclusion,
selected_block == ActiveRadarrBlock::DeleteMovieToggleAddListExclusion, selected_block == &ActiveRadarrBlock::DeleteMovieToggleAddListExclusion,
), ),
], ],
selected_block == ActiveRadarrBlock::DeleteMovieConfirmPrompt, selected_block == &ActiveRadarrBlock::DeleteMovieConfirmPrompt,
app.data.radarr_data.prompt_confirm, app.data.radarr_data.prompt_confirm,
) )
} }
+9 -9
View File
@@ -18,7 +18,7 @@ use crate::ui::{
pub(super) fn draw_edit_collection_prompt<B: Backend>( pub(super) fn draw_edit_collection_prompt<B: Backend>(
f: &mut Frame<'_, B>, f: &mut Frame<'_, B>,
app: &mut App, app: &mut App<'_>,
prompt_area: Rect, prompt_area: Rect,
) { ) {
if let Route::Radarr(active_radarr_block, _) = *app.get_current_route() { if let Route::Radarr(active_radarr_block, _) = *app.get_current_route() {
@@ -54,7 +54,7 @@ pub(super) fn draw_edit_collection_prompt<B: Backend>(
fn draw_edit_collection_confirmation_prompt<B: Backend>( fn draw_edit_collection_confirmation_prompt<B: Backend>(
f: &mut Frame<'_, B>, f: &mut Frame<'_, B>,
app: &mut App, app: &mut App<'_>,
prompt_area: Rect, prompt_area: Rect,
) { ) {
let (collection_title, collection_overview) = let (collection_title, collection_overview) =
@@ -97,8 +97,8 @@ fn draw_edit_collection_confirmation_prompt<B: Backend>(
}; };
let title = format!("Edit - {}", collection_title); let title = format!("Edit - {}", collection_title);
let yes_no_value = app.data.radarr_data.prompt_confirm; let yes_no_value = app.data.radarr_data.prompt_confirm;
let selected_block = app.data.radarr_data.selected_block; let selected_block = app.data.radarr_data.selected_block.get_active_block();
let highlight_yes_no = selected_block == ActiveRadarrBlock::EditCollectionConfirmPrompt; let highlight_yes_no = selected_block == &ActiveRadarrBlock::EditCollectionConfirmPrompt;
let selected_minimum_availability = app let selected_minimum_availability = app
.data .data
@@ -141,7 +141,7 @@ fn draw_edit_collection_confirmation_prompt<B: Backend>(
chunks[1], chunks[1],
"Monitored", "Monitored",
app.data.radarr_data.edit_monitored.unwrap_or_default(), app.data.radarr_data.edit_monitored.unwrap_or_default(),
selected_block == ActiveRadarrBlock::EditCollectionToggleMonitored, selected_block == &ActiveRadarrBlock::EditCollectionToggleMonitored,
); );
draw_drop_down_menu_button( draw_drop_down_menu_button(
@@ -149,14 +149,14 @@ fn draw_edit_collection_confirmation_prompt<B: Backend>(
chunks[2], chunks[2],
"Minimum Availability", "Minimum Availability",
selected_minimum_availability.to_display_str(), selected_minimum_availability.to_display_str(),
selected_block == ActiveRadarrBlock::EditCollectionSelectMinimumAvailability, selected_block == &ActiveRadarrBlock::EditCollectionSelectMinimumAvailability,
); );
draw_drop_down_menu_button( draw_drop_down_menu_button(
f, f,
chunks[3], chunks[3],
"Quality Profile", "Quality Profile",
selected_quality_profile, selected_quality_profile,
selected_block == ActiveRadarrBlock::EditCollectionSelectQualityProfile, selected_block == &ActiveRadarrBlock::EditCollectionSelectQualityProfile,
); );
if let Route::Radarr(active_radarr_block, _) = *app.get_current_route() { if let Route::Radarr(active_radarr_block, _) = *app.get_current_route() {
@@ -166,7 +166,7 @@ fn draw_edit_collection_confirmation_prompt<B: Backend>(
"Root Folder", "Root Folder",
&app.data.radarr_data.edit_path.text, &app.data.radarr_data.edit_path.text,
*app.data.radarr_data.edit_path.offset.borrow(), *app.data.radarr_data.edit_path.offset.borrow(),
selected_block == ActiveRadarrBlock::EditCollectionRootFolderPathInput, selected_block == &ActiveRadarrBlock::EditCollectionRootFolderPathInput,
active_radarr_block == ActiveRadarrBlock::EditCollectionRootFolderPathInput, active_radarr_block == ActiveRadarrBlock::EditCollectionRootFolderPathInput,
); );
} }
@@ -176,7 +176,7 @@ fn draw_edit_collection_confirmation_prompt<B: Backend>(
chunks[5], chunks[5],
"Search on Add", "Search on Add",
app.data.radarr_data.edit_search_on_add.unwrap_or_default(), app.data.radarr_data.edit_search_on_add.unwrap_or_default(),
selected_block == ActiveRadarrBlock::EditCollectionToggleSearchOnAdd, selected_block == &ActiveRadarrBlock::EditCollectionToggleSearchOnAdd,
); );
draw_button( draw_button(
+9 -9
View File
@@ -18,7 +18,7 @@ use crate::ui::{
pub(super) fn draw_edit_movie_prompt<B: Backend>( pub(super) fn draw_edit_movie_prompt<B: Backend>(
f: &mut Frame<'_, B>, f: &mut Frame<'_, B>,
app: &mut App, app: &mut App<'_>,
prompt_area: Rect, prompt_area: Rect,
) { ) {
if let Route::Radarr(active_radarr_block, _) = *app.get_current_route() { if let Route::Radarr(active_radarr_block, _) = *app.get_current_route() {
@@ -54,7 +54,7 @@ pub(super) fn draw_edit_movie_prompt<B: Backend>(
fn draw_edit_movie_confirmation_prompt<B: Backend>( fn draw_edit_movie_confirmation_prompt<B: Backend>(
f: &mut Frame<'_, B>, f: &mut Frame<'_, B>,
app: &mut App, app: &mut App<'_>,
prompt_area: Rect, prompt_area: Rect,
) { ) {
let (movie_title, movie_overview) = if app.data.radarr_data.filtered_movies.items.is_empty() { let (movie_title, movie_overview) = if app.data.radarr_data.filtered_movies.items.is_empty() {
@@ -94,8 +94,8 @@ fn draw_edit_movie_confirmation_prompt<B: Backend>(
}; };
let title = format!("Edit - {}", movie_title); let title = format!("Edit - {}", movie_title);
let yes_no_value = app.data.radarr_data.prompt_confirm; let yes_no_value = app.data.radarr_data.prompt_confirm;
let selected_block = app.data.radarr_data.selected_block; let selected_block = app.data.radarr_data.selected_block.get_active_block();
let highlight_yes_no = selected_block == ActiveRadarrBlock::EditMovieConfirmPrompt; let highlight_yes_no = selected_block == &ActiveRadarrBlock::EditMovieConfirmPrompt;
let selected_minimum_availability = app let selected_minimum_availability = app
.data .data
@@ -138,7 +138,7 @@ fn draw_edit_movie_confirmation_prompt<B: Backend>(
chunks[1], chunks[1],
"Monitored", "Monitored",
app.data.radarr_data.edit_monitored.unwrap_or_default(), app.data.radarr_data.edit_monitored.unwrap_or_default(),
selected_block == ActiveRadarrBlock::EditMovieToggleMonitored, selected_block == &ActiveRadarrBlock::EditMovieToggleMonitored,
); );
draw_drop_down_menu_button( draw_drop_down_menu_button(
@@ -146,14 +146,14 @@ fn draw_edit_movie_confirmation_prompt<B: Backend>(
chunks[2], chunks[2],
"Minimum Availability", "Minimum Availability",
selected_minimum_availability.to_display_str(), selected_minimum_availability.to_display_str(),
selected_block == ActiveRadarrBlock::EditMovieSelectMinimumAvailability, selected_block == &ActiveRadarrBlock::EditMovieSelectMinimumAvailability,
); );
draw_drop_down_menu_button( draw_drop_down_menu_button(
f, f,
chunks[3], chunks[3],
"Quality Profile", "Quality Profile",
selected_quality_profile, selected_quality_profile,
selected_block == ActiveRadarrBlock::EditMovieSelectQualityProfile, selected_block == &ActiveRadarrBlock::EditMovieSelectQualityProfile,
); );
if let Route::Radarr(active_radarr_block, _) = *app.get_current_route() { if let Route::Radarr(active_radarr_block, _) = *app.get_current_route() {
@@ -163,7 +163,7 @@ fn draw_edit_movie_confirmation_prompt<B: Backend>(
"Path", "Path",
&app.data.radarr_data.edit_path.text, &app.data.radarr_data.edit_path.text,
*app.data.radarr_data.edit_path.offset.borrow(), *app.data.radarr_data.edit_path.offset.borrow(),
selected_block == ActiveRadarrBlock::EditMoviePathInput, selected_block == &ActiveRadarrBlock::EditMoviePathInput,
active_radarr_block == ActiveRadarrBlock::EditMoviePathInput, active_radarr_block == ActiveRadarrBlock::EditMoviePathInput,
); );
draw_text_box_with_label( draw_text_box_with_label(
@@ -172,7 +172,7 @@ fn draw_edit_movie_confirmation_prompt<B: Backend>(
"Tags", "Tags",
&app.data.radarr_data.edit_tags.text, &app.data.radarr_data.edit_tags.text,
*app.data.radarr_data.edit_tags.offset.borrow(), *app.data.radarr_data.edit_tags.offset.borrow(),
selected_block == ActiveRadarrBlock::EditMovieTagsInput, selected_block == &ActiveRadarrBlock::EditMovieTagsInput,
active_radarr_block == ActiveRadarrBlock::EditMovieTagsInput, active_radarr_block == ActiveRadarrBlock::EditMovieTagsInput,
); );
} }
+27 -19
View File
@@ -43,7 +43,7 @@ mod edit_collection_ui;
mod edit_movie_ui; mod edit_movie_ui;
mod movie_details_ui; mod movie_details_ui;
pub(super) fn draw_radarr_ui<B: Backend>(f: &mut Frame<'_, B>, app: &mut App, area: Rect) { pub(super) fn draw_radarr_ui<B: Backend>(f: &mut Frame<'_, B>, app: &mut App<'_>, area: Rect) {
let (content_rect, _) = draw_tabs(f, area, "Movies", &app.data.radarr_data.main_tabs); let (content_rect, _) = draw_tabs(f, area, "Movies", &app.data.radarr_data.main_tabs);
if let Route::Radarr(active_radarr_block, context_option) = *app.get_current_route() { if let Route::Radarr(active_radarr_block, context_option) = *app.get_current_route() {
@@ -195,7 +195,7 @@ pub(super) fn draw_radarr_ui<B: Backend>(f: &mut Frame<'_, B>, app: &mut App, ar
} }
} }
pub(super) fn draw_radarr_context_row<B: Backend>(f: &mut Frame<'_, B>, app: &App, area: Rect) { pub(super) fn draw_radarr_context_row<B: Backend>(f: &mut Frame<'_, B>, app: &App<'_>, area: Rect) {
let chunks = horizontal_chunks(vec![Constraint::Min(0), Constraint::Length(20)], area); let chunks = horizontal_chunks(vec![Constraint::Min(0), Constraint::Length(20)], area);
let context_chunks = horizontal_chunks( let context_chunks = horizontal_chunks(
@@ -208,7 +208,7 @@ pub(super) fn draw_radarr_context_row<B: Backend>(f: &mut Frame<'_, B>, app: &Ap
draw_radarr_logo(f, chunks[1]); draw_radarr_logo(f, chunks[1]);
} }
fn draw_library<B: Backend>(f: &mut Frame<'_, B>, app: &mut App, area: Rect) { fn draw_library<B: Backend>(f: &mut Frame<'_, B>, app: &mut App<'_>, area: Rect) {
let current_selection = if !app.data.radarr_data.filtered_movies.items.is_empty() { let current_selection = if !app.data.radarr_data.filtered_movies.items.is_empty() {
app app
.data .data
@@ -314,7 +314,7 @@ fn draw_library<B: Backend>(f: &mut Frame<'_, B>, app: &mut App, area: Rect) {
fn draw_update_all_movies_prompt<B: Backend>( fn draw_update_all_movies_prompt<B: Backend>(
f: &mut Frame<'_, B>, f: &mut Frame<'_, B>,
app: &mut App, app: &mut App<'_>,
prompt_area: Rect, prompt_area: Rect,
) { ) {
draw_prompt_box( draw_prompt_box(
@@ -328,7 +328,7 @@ fn draw_update_all_movies_prompt<B: Backend>(
fn draw_update_downloads_prompt<B: Backend>( fn draw_update_downloads_prompt<B: Backend>(
f: &mut Frame<'_, B>, f: &mut Frame<'_, B>,
app: &mut App, app: &mut App<'_>,
prompt_area: Rect, prompt_area: Rect,
) { ) {
draw_prompt_box( draw_prompt_box(
@@ -342,7 +342,7 @@ fn draw_update_downloads_prompt<B: Backend>(
fn draw_update_all_collections_prompt<B: Backend>( fn draw_update_all_collections_prompt<B: Backend>(
f: &mut Frame<'_, B>, f: &mut Frame<'_, B>,
app: &mut App, app: &mut App<'_>,
prompt_area: Rect, prompt_area: Rect,
) { ) {
draw_prompt_box( draw_prompt_box(
@@ -354,7 +354,11 @@ fn draw_update_all_collections_prompt<B: Backend>(
); );
} }
fn draw_delete_download_prompt<B: Backend>(f: &mut Frame<'_, B>, app: &mut App, prompt_area: Rect) { fn draw_delete_download_prompt<B: Backend>(
f: &mut Frame<'_, B>,
app: &mut App<'_>,
prompt_area: Rect,
) {
draw_prompt_box( draw_prompt_box(
f, f,
prompt_area, prompt_area,
@@ -370,7 +374,7 @@ fn draw_delete_download_prompt<B: Backend>(f: &mut Frame<'_, B>, app: &mut App,
fn draw_delete_root_folder_prompt<B: Backend>( fn draw_delete_root_folder_prompt<B: Backend>(
f: &mut Frame<'_, B>, f: &mut Frame<'_, B>,
app: &mut App, app: &mut App<'_>,
prompt_area: Rect, prompt_area: Rect,
) { ) {
draw_prompt_box( draw_prompt_box(
@@ -386,7 +390,11 @@ fn draw_delete_root_folder_prompt<B: Backend>(
); );
} }
fn draw_add_root_folder_prompt_box<B: Backend>(f: &mut Frame<'_, B>, app: &mut App, area: Rect) { fn draw_add_root_folder_prompt_box<B: Backend>(
f: &mut Frame<'_, B>,
app: &mut App<'_>,
area: Rect,
) {
let chunks = vertical_chunks_with_margin( let chunks = vertical_chunks_with_margin(
vec![ vec![
Constraint::Length(3), Constraint::Length(3),
@@ -413,7 +421,7 @@ fn draw_add_root_folder_prompt_box<B: Backend>(f: &mut Frame<'_, B>, app: &mut A
f.render_widget(help, chunks[1]); f.render_widget(help, chunks[1]);
} }
fn draw_search_box<B: Backend>(f: &mut Frame<'_, B>, app: &mut App, area: Rect) { fn draw_search_box<B: Backend>(f: &mut Frame<'_, B>, app: &mut App<'_>, area: Rect) {
let chunks = let chunks =
vertical_chunks_with_margin(vec![Constraint::Length(3), Constraint::Min(0)], area, 1); vertical_chunks_with_margin(vec![Constraint::Length(3), Constraint::Min(0)], area, 1);
if !app.data.radarr_data.is_searching { if !app.data.radarr_data.is_searching {
@@ -454,7 +462,7 @@ fn draw_search_box<B: Backend>(f: &mut Frame<'_, B>, app: &mut App, area: Rect)
} }
} }
fn draw_filter_box<B: Backend>(f: &mut Frame<'_, B>, app: &mut App, area: Rect) { fn draw_filter_box<B: Backend>(f: &mut Frame<'_, B>, app: &mut App<'_>, area: Rect) {
let chunks = let chunks =
vertical_chunks_with_margin(vec![Constraint::Length(3), Constraint::Min(0)], area, 1); vertical_chunks_with_margin(vec![Constraint::Length(3), Constraint::Min(0)], area, 1);
if !app.data.radarr_data.is_filtering { if !app.data.radarr_data.is_filtering {
@@ -504,7 +512,7 @@ fn draw_radarr_logo<B: Backend>(f: &mut Frame<'_, B>, area: Rect) {
f.render_widget(logo, area); f.render_widget(logo, area);
} }
fn draw_stats_context<B: Backend>(f: &mut Frame<'_, B>, app: &App, area: Rect) { fn draw_stats_context<B: Backend>(f: &mut Frame<'_, B>, app: &App<'_>, area: Rect) {
let block = title_block("Stats"); let block = title_block("Stats");
if !app.data.radarr_data.version.is_empty() { if !app.data.radarr_data.version.is_empty() {
@@ -602,7 +610,7 @@ fn draw_stats_context<B: Backend>(f: &mut Frame<'_, B>, app: &App, area: Rect) {
} }
} }
fn draw_downloads_context<B: Backend>(f: &mut Frame<'_, B>, app: &App, area: Rect) { fn draw_downloads_context<B: Backend>(f: &mut Frame<'_, B>, app: &App<'_>, area: Rect) {
let block = title_block("Downloads"); let block = title_block("Downloads");
let downloads_vec = &app.data.radarr_data.downloads.items; let downloads_vec = &app.data.radarr_data.downloads.items;
@@ -632,7 +640,7 @@ fn draw_downloads_context<B: Backend>(f: &mut Frame<'_, B>, app: &App, area: Rec
} }
} }
fn draw_downloads<B: Backend>(f: &mut Frame<'_, B>, app: &mut App, area: Rect) { fn draw_downloads<B: Backend>(f: &mut Frame<'_, B>, app: &mut App<'_>, area: Rect) {
let current_selection = if app.data.radarr_data.downloads.items.is_empty() { let current_selection = if app.data.radarr_data.downloads.items.is_empty() {
DownloadRecord::default() DownloadRecord::default()
} else { } else {
@@ -708,7 +716,7 @@ fn draw_downloads<B: Backend>(f: &mut Frame<'_, B>, app: &mut App, area: Rect) {
); );
} }
fn draw_collections<B: Backend>(f: &mut Frame<'_, B>, app: &mut App, area: Rect) { fn draw_collections<B: Backend>(f: &mut Frame<'_, B>, app: &mut App<'_>, area: Rect) {
let current_selection = if !app.data.radarr_data.filtered_collections.items.is_empty() { let current_selection = if !app.data.radarr_data.filtered_collections.items.is_empty() {
app app
.data .data
@@ -790,7 +798,7 @@ fn draw_collections<B: Backend>(f: &mut Frame<'_, B>, app: &mut App, area: Rect)
); );
} }
fn draw_root_folders<B: Backend>(f: &mut Frame<'_, B>, app: &mut App, area: Rect) { fn draw_root_folders<B: Backend>(f: &mut Frame<'_, B>, app: &mut App<'_>, area: Rect) {
draw_table( draw_table(
f, f,
area, area,
@@ -863,7 +871,7 @@ fn determine_row_style(downloads_vec: &[DownloadRecord], movie: &Movie) -> Style
fn draw_select_minimum_availability_popup<B: Backend>( fn draw_select_minimum_availability_popup<B: Backend>(
f: &mut Frame<'_, B>, f: &mut Frame<'_, B>,
app: &mut App, app: &mut App<'_>,
popup_area: Rect, popup_area: Rect,
) { ) {
draw_drop_down_list( draw_drop_down_list(
@@ -876,7 +884,7 @@ fn draw_select_minimum_availability_popup<B: Backend>(
fn draw_select_quality_profile_popup<B: Backend>( fn draw_select_quality_profile_popup<B: Backend>(
f: &mut Frame<'_, B>, f: &mut Frame<'_, B>,
app: &mut App, app: &mut App<'_>,
popup_area: Rect, popup_area: Rect,
) { ) {
draw_drop_down_list( draw_drop_down_list(
@@ -889,7 +897,7 @@ fn draw_select_quality_profile_popup<B: Backend>(
fn draw_select_root_folder_popup<B: Backend>( fn draw_select_root_folder_popup<B: Backend>(
f: &mut Frame<'_, B>, f: &mut Frame<'_, B>,
app: &mut App, app: &mut App<'_>,
popup_area: Rect, popup_area: Rect,
) { ) {
draw_drop_down_list( draw_drop_down_list(
+23 -11
View File
@@ -22,7 +22,11 @@ use crate::ui::{
}; };
use crate::utils::convert_to_gb; use crate::utils::convert_to_gb;
pub(super) fn draw_movie_info_popup<B: Backend>(f: &mut Frame<'_, B>, app: &mut App, area: Rect) { pub(super) fn draw_movie_info_popup<B: Backend>(
f: &mut Frame<'_, B>,
app: &mut App<'_>,
area: Rect,
) {
let (content_area, _) = draw_tabs(f, area, "Movie Info", &app.data.radarr_data.movie_info_tabs); let (content_area, _) = draw_tabs(f, area, "Movie Info", &app.data.radarr_data.movie_info_tabs);
if let Route::Radarr(active_radarr_block, context_option) = app.get_current_route() { if let Route::Radarr(active_radarr_block, context_option) = app.get_current_route() {
@@ -67,7 +71,7 @@ pub(super) fn draw_movie_info_popup<B: Backend>(f: &mut Frame<'_, B>, app: &mut
} }
} }
fn draw_movie_info<B: Backend>(f: &mut Frame<'_, B>, app: &mut App, area: Rect) { fn draw_movie_info<B: Backend>(f: &mut Frame<'_, B>, app: &mut App<'_>, area: Rect) {
if let Route::Radarr(active_radarr_block, _) = if let Route::Radarr(active_radarr_block, _) =
app.data.radarr_data.movie_info_tabs.get_active_route() app.data.radarr_data.movie_info_tabs.get_active_route()
{ {
@@ -83,7 +87,11 @@ fn draw_movie_info<B: Backend>(f: &mut Frame<'_, B>, app: &mut App, area: Rect)
} }
} }
fn draw_search_movie_prompt<B: Backend>(f: &mut Frame<'_, B>, app: &mut App, prompt_area: Rect) { fn draw_search_movie_prompt<B: Backend>(
f: &mut Frame<'_, B>,
app: &mut App<'_>,
prompt_area: Rect,
) {
draw_prompt_box( draw_prompt_box(
f, f,
prompt_area, prompt_area,
@@ -97,7 +105,11 @@ fn draw_search_movie_prompt<B: Backend>(f: &mut Frame<'_, B>, app: &mut App, pro
); );
} }
fn draw_update_and_scan_prompt<B: Backend>(f: &mut Frame<'_, B>, app: &mut App, prompt_area: Rect) { fn draw_update_and_scan_prompt<B: Backend>(
f: &mut Frame<'_, B>,
app: &mut App<'_>,
prompt_area: Rect,
) {
draw_prompt_box( draw_prompt_box(
f, f,
prompt_area, prompt_area,
@@ -111,7 +123,7 @@ fn draw_update_and_scan_prompt<B: Backend>(f: &mut Frame<'_, B>, app: &mut App,
); );
} }
fn draw_file_info<B: Backend>(f: &mut Frame<'_, B>, app: &App, content_area: Rect) { fn draw_file_info<B: Backend>(f: &mut Frame<'_, B>, app: &App<'_>, content_area: Rect) {
let file_info = app.data.radarr_data.file_details.to_owned(); let file_info = app.data.radarr_data.file_details.to_owned();
if !file_info.is_empty() { if !file_info.is_empty() {
@@ -167,7 +179,7 @@ fn draw_file_info<B: Backend>(f: &mut Frame<'_, B>, app: &App, content_area: Rec
} }
} }
fn draw_movie_details<B: Backend>(f: &mut Frame<'_, B>, app: &App, content_area: Rect) { fn draw_movie_details<B: Backend>(f: &mut Frame<'_, B>, app: &App<'_>, content_area: Rect) {
let movie_details = app.data.radarr_data.movie_details.get_text(); let movie_details = app.data.radarr_data.movie_details.get_text();
let block = layout_block_top_border(); let block = layout_block_top_border();
@@ -210,7 +222,7 @@ fn draw_movie_details<B: Backend>(f: &mut Frame<'_, B>, app: &App, content_area:
} }
} }
fn draw_movie_history<B: Backend>(f: &mut Frame<'_, B>, app: &mut App, content_area: Rect) { fn draw_movie_history<B: Backend>(f: &mut Frame<'_, B>, app: &mut App<'_>, content_area: Rect) {
let current_selection = if app.data.radarr_data.movie_history.items.is_empty() { let current_selection = if app.data.radarr_data.movie_history.items.is_empty() {
MovieHistoryItem::default() MovieHistoryItem::default()
} else { } else {
@@ -285,7 +297,7 @@ fn draw_movie_history<B: Backend>(f: &mut Frame<'_, B>, app: &mut App, content_a
} }
} }
fn draw_movie_cast<B: Backend>(f: &mut Frame<'_, B>, app: &mut App, content_area: Rect) { fn draw_movie_cast<B: Backend>(f: &mut Frame<'_, B>, app: &mut App<'_>, content_area: Rect) {
draw_table( draw_table(
f, f,
content_area, content_area,
@@ -317,7 +329,7 @@ fn draw_movie_cast<B: Backend>(f: &mut Frame<'_, B>, app: &mut App, content_area
); );
} }
fn draw_movie_crew<B: Backend>(f: &mut Frame<'_, B>, app: &mut App, content_area: Rect) { fn draw_movie_crew<B: Backend>(f: &mut Frame<'_, B>, app: &mut App<'_>, content_area: Rect) {
draw_table( draw_table(
f, f,
content_area, content_area,
@@ -351,7 +363,7 @@ fn draw_movie_crew<B: Backend>(f: &mut Frame<'_, B>, app: &mut App, content_area
); );
} }
fn draw_movie_releases<B: Backend>(f: &mut Frame<'_, B>, app: &mut App, content_area: Rect) { fn draw_movie_releases<B: Backend>(f: &mut Frame<'_, B>, app: &mut App<'_>, content_area: Rect) {
let current_selection = if app.data.radarr_data.movie_releases.items.is_empty() { let current_selection = if app.data.radarr_data.movie_releases.items.is_empty() {
Release::default() Release::default()
} else { } else {
@@ -475,7 +487,7 @@ fn draw_movie_releases<B: Backend>(f: &mut Frame<'_, B>, app: &mut App, content_
fn draw_manual_search_confirm_prompt<B: Backend>( fn draw_manual_search_confirm_prompt<B: Backend>(
f: &mut Frame<'_, B>, f: &mut Frame<'_, B>,
app: &mut App, app: &mut App<'_>,
prompt_area: Rect, prompt_area: Rect,
) { ) {
let current_selection = app.data.radarr_data.movie_releases.current_selection(); let current_selection = app.data.radarr_data.movie_releases.current_selection();