use super::lidarr_data::{ActiveLidarrBlock, LidarrData}; use crate::app::lidarr::lidarr_context_clues::{ ALBUM_DETAILS_CONTEXT_CLUES, ALBUM_HISTORY_CONTEXT_CLUES, MANUAL_ALBUM_SEARCH_CONTEXT_CLUES, TRACK_DETAILS_CONTEXT_CLUES, TRACK_HISTORY_CONTEXT_CLUES, }; use crate::models::lidarr_models::{LidarrHistoryItem, LidarrRelease, Track, TrackFile}; use crate::models::servarr_data::modals::EditIndexerModal; use crate::models::servarr_models::Indexer; use crate::models::stateful_table::StatefulTable; use crate::models::{ HorizontallyScrollableText, ScrollableText, TabRoute, TabState, lidarr_models::{MonitorType, NewItemMonitorType}, servarr_models::RootFolder, stateful_list::StatefulList, }; use strum::IntoEnumIterator; #[cfg(test)] #[path = "modals_tests.rs"] mod modals_tests; #[derive(Default)] #[cfg_attr(test, derive(Debug))] pub struct AddArtistModal { pub root_folder_list: StatefulList, pub monitor_list: StatefulList, pub monitor_new_items_list: StatefulList, pub quality_profile_list: StatefulList, pub metadata_profile_list: StatefulList, pub tags: HorizontallyScrollableText, } impl From<&LidarrData<'_>> for AddArtistModal { fn from(lidarr_data: &LidarrData<'_>) -> AddArtistModal { let mut add_artist_modal = AddArtistModal::default(); add_artist_modal .monitor_list .set_items(Vec::from_iter(MonitorType::iter())); add_artist_modal .monitor_new_items_list .set_items(Vec::from_iter(NewItemMonitorType::iter())); add_artist_modal .quality_profile_list .set_items(lidarr_data.sorted_quality_profile_names()); add_artist_modal .metadata_profile_list .set_items(lidarr_data.sorted_metadata_profile_names()); add_artist_modal .root_folder_list .set_items(lidarr_data.root_folders.items.to_vec()); add_artist_modal } } #[derive(Default)] #[cfg_attr(test, derive(Debug))] pub struct EditArtistModal { pub monitor_list: StatefulList, pub quality_profile_list: StatefulList, pub metadata_profile_list: StatefulList, pub monitored: Option, pub path: HorizontallyScrollableText, pub tags: HorizontallyScrollableText, } impl From<&LidarrData<'_>> for EditArtistModal { fn from(lidarr_data: &LidarrData<'_>) -> EditArtistModal { let mut edit_artist_modal = EditArtistModal::default(); let artist = lidarr_data.artists.current_selection(); edit_artist_modal .monitor_list .set_items(Vec::from_iter(NewItemMonitorType::iter())); edit_artist_modal.path = artist.path.clone().into(); edit_artist_modal.tags = lidarr_data.tag_ids_to_display(&artist.tags).into(); edit_artist_modal.monitored = Some(artist.monitored); let monitor_index = edit_artist_modal .monitor_list .items .iter() .position(|m| *m == artist.monitor_new_items); edit_artist_modal.monitor_list.state.select(monitor_index); edit_artist_modal .quality_profile_list .set_items(lidarr_data.sorted_quality_profile_names()); let quality_profile_name = lidarr_data .quality_profile_map .get_by_left(&artist.quality_profile_id) .unwrap(); let quality_profile_index = edit_artist_modal .quality_profile_list .items .iter() .position(|profile| profile == quality_profile_name); edit_artist_modal .quality_profile_list .state .select(quality_profile_index); edit_artist_modal .metadata_profile_list .set_items(lidarr_data.sorted_metadata_profile_names()); let metadata_profile_name = lidarr_data .metadata_profile_map .get_by_left(&artist.metadata_profile_id) .unwrap(); let metadata_profile_index = edit_artist_modal .metadata_profile_list .items .iter() .position(|profile| profile == metadata_profile_name); edit_artist_modal .metadata_profile_list .state .select(metadata_profile_index); edit_artist_modal } } impl From<&LidarrData<'_>> for EditIndexerModal { fn from(lidarr_data: &LidarrData<'_>) -> EditIndexerModal { let mut edit_indexer_modal = EditIndexerModal::default(); let Indexer { name, enable_rss, enable_automatic_search, enable_interactive_search, tags, fields, priority, .. } = lidarr_data.indexers.current_selection(); let seed_ratio_field_option = fields .as_ref() .expect("indexer fields must exist") .iter() .find(|field| { field.name.as_ref().expect("indexer field name must exist") == "seedCriteria.seedRatio" }); let seed_ratio_value_option = if let Some(seed_ratio_field) = seed_ratio_field_option { seed_ratio_field.value.clone() } else { None }; edit_indexer_modal.name = name.clone().expect("indexer name must exist").into(); edit_indexer_modal.enable_rss = Some(*enable_rss); edit_indexer_modal.enable_automatic_search = Some(*enable_automatic_search); edit_indexer_modal.enable_interactive_search = Some(*enable_interactive_search); edit_indexer_modal.priority = *priority; edit_indexer_modal.url = fields .as_ref() .expect("indexer fields must exist") .iter() .find(|field| field.name.as_ref().expect("indexer field name must exist") == "baseUrl") .expect("baseUrl field must exist") .value .clone() .expect("baseUrl field value must exist") .as_str() .expect("baseUrl field value must be a string") .into(); edit_indexer_modal.api_key = fields .as_ref() .expect("indexer fields must exist") .iter() .find(|field| field.name.as_ref().expect("indexer field name must exist") == "apiKey") .expect("apiKey field must exist") .value .clone() .expect("apiKey field value must exist") .as_str() .expect("apiKey field value must be a string") .into(); if let Some(seed_ratio_value) = seed_ratio_value_option { edit_indexer_modal.seed_ratio = seed_ratio_value .as_f64() .expect("Seed ratio value must be a valid f64") .to_string() .into(); } edit_indexer_modal.tags = lidarr_data.tag_ids_to_display(tags).into(); edit_indexer_modal } } #[derive(Default)] #[cfg_attr(test, derive(Debug))] pub struct AddRootFolderModal { pub name: HorizontallyScrollableText, pub path: HorizontallyScrollableText, pub monitor_list: StatefulList, pub monitor_new_items_list: StatefulList, pub quality_profile_list: StatefulList, pub metadata_profile_list: StatefulList, pub tags: HorizontallyScrollableText, } impl From<&LidarrData<'_>> for AddRootFolderModal { fn from(lidarr_data: &LidarrData<'_>) -> AddRootFolderModal { let mut add_root_folder_modal = AddRootFolderModal::default(); add_root_folder_modal .monitor_list .set_items(Vec::from_iter(MonitorType::iter())); add_root_folder_modal .monitor_new_items_list .set_items(Vec::from_iter(NewItemMonitorType::iter())); add_root_folder_modal .quality_profile_list .set_items(lidarr_data.sorted_quality_profile_names()); add_root_folder_modal .metadata_profile_list .set_items(lidarr_data.sorted_metadata_profile_names()); add_root_folder_modal } } #[cfg_attr(test, derive(Debug))] pub struct AlbumDetailsModal { pub tracks: StatefulTable, pub track_files: StatefulTable, pub track_details_modal: Option, pub album_history: StatefulTable, pub album_releases: StatefulTable, pub album_details_tabs: TabState, } impl Default for AlbumDetailsModal { fn default() -> AlbumDetailsModal { AlbumDetailsModal { tracks: StatefulTable::default(), track_details_modal: None, track_files: StatefulTable::default(), album_releases: StatefulTable::default(), album_history: StatefulTable::default(), album_details_tabs: TabState::new(vec![ TabRoute { title: "Tracks".to_string(), route: ActiveLidarrBlock::AlbumDetails.into(), contextual_help: Some(&ALBUM_DETAILS_CONTEXT_CLUES), config: None, }, TabRoute { title: "History".to_string(), route: ActiveLidarrBlock::AlbumHistory.into(), contextual_help: Some(&ALBUM_HISTORY_CONTEXT_CLUES), config: None, }, TabRoute { title: "Manual Search".to_string(), route: ActiveLidarrBlock::ManualAlbumSearch.into(), contextual_help: Some(&MANUAL_ALBUM_SEARCH_CONTEXT_CLUES), config: None, }, ]), } } } #[cfg_attr(test, derive(Debug))] pub struct TrackDetailsModal { pub track_details: ScrollableText, pub track_history: StatefulTable, pub track_details_tabs: TabState, } impl Default for TrackDetailsModal { fn default() -> Self { TrackDetailsModal { track_details: ScrollableText::default(), track_history: StatefulTable::default(), track_details_tabs: TabState::new(vec![ TabRoute { title: "Track Details".to_string(), route: ActiveLidarrBlock::TrackDetails.into(), contextual_help: Some(&TRACK_DETAILS_CONTEXT_CLUES), config: None, }, TabRoute { title: "History".to_string(), route: ActiveLidarrBlock::TrackHistory.into(), contextual_help: Some(&TRACK_HISTORY_CONTEXT_CLUES), config: None, }, ]), } } }