use bimap::BiMap; use chrono::{DateTime, Utc}; use strum::EnumIter; use crate::{ app::{ context_clues::{ BLOCKLIST_CONTEXT_CLUES, DOWNLOADS_CONTEXT_CLUES, INDEXERS_CONTEXT_CLUES, ROOT_FOLDERS_CONTEXT_CLUES, SYSTEM_CONTEXT_CLUES, }, sonarr::sonarr_context_clues::{ HISTORY_CONTEXT_CLUES, SERIES_CONTEXT_CLUES, SERIES_DETAILS_CONTEXT_CLUES, SERIES_HISTORY_CONTEXT_CLUES, }, }, models::{ BlockSelectionState, HorizontallyScrollableText, Route, ScrollableText, TabRoute, TabState, servarr_data::modals::{EditIndexerModal, IndexerTestResultModalItem}, servarr_models::{DiskSpace, Indexer, QueueEvent, RootFolder}, sonarr_models::{ AddSeriesSearchResult, BlocklistItem, DownloadRecord, IndexerSettings, Season, Series, SonarrHistoryItem, SonarrTask, }, stateful_list::StatefulList, stateful_table::StatefulTable, }, network::sonarr_network::SonarrEvent, }; use super::modals::{AddSeriesModal, EditSeriesModal, SeasonDetailsModal}; #[cfg(test)] #[path = "sonarr_data_tests.rs"] mod sonarr_data_tests; #[cfg(test)] #[path = "sonarr_test_utils.rs"] pub mod sonarr_test_utils; pub struct SonarrData<'a> { pub add_list_exclusion: bool, pub add_searched_series: Option>, pub add_series_modal: Option, pub add_series_search: Option, pub blocklist: StatefulTable, pub delete_series_files: bool, pub downloads: StatefulTable, pub disk_space_vec: Vec, pub edit_indexer_modal: Option, pub edit_root_folder: Option, pub edit_series_modal: Option, pub history: StatefulTable, pub indexers: StatefulTable, pub indexer_settings: Option, pub indexer_test_all_results: Option>, pub indexer_test_errors: Option, pub language_profiles_map: BiMap, pub logs: StatefulList, pub log_details: StatefulList, pub main_tabs: TabState, pub prompt_confirm: bool, pub prompt_confirm_action: Option, pub quality_profile_map: BiMap, pub queued_events: StatefulTable, pub root_folders: StatefulTable, pub seasons: StatefulTable, pub season_details_modal: Option, pub selected_block: BlockSelectionState<'a, ActiveSonarrBlock>, pub series: StatefulTable, pub series_history: Option>, pub series_info_tabs: TabState, pub start_time: DateTime, pub tags_map: BiMap, pub tasks: StatefulTable, pub updates: ScrollableText, pub version: String, } impl SonarrData<'_> { pub fn reset_delete_series_preferences(&mut self) { self.delete_series_files = false; self.add_list_exclusion = false; } pub fn reset_series_info_tabs(&mut self) { self.series_history = None; self.seasons = StatefulTable::default(); self.series_info_tabs.index = 0; } } impl<'a> Default for SonarrData<'a> { fn default() -> SonarrData<'a> { SonarrData { add_list_exclusion: false, add_searched_series: None, add_series_search: None, add_series_modal: None, blocklist: StatefulTable::default(), downloads: StatefulTable::default(), delete_series_files: false, disk_space_vec: Vec::new(), edit_indexer_modal: None, edit_root_folder: None, edit_series_modal: None, history: StatefulTable::default(), indexers: StatefulTable::default(), indexer_settings: None, indexer_test_errors: None, indexer_test_all_results: None, language_profiles_map: BiMap::new(), logs: StatefulList::default(), log_details: StatefulList::default(), prompt_confirm: false, prompt_confirm_action: None, quality_profile_map: BiMap::new(), queued_events: StatefulTable::default(), root_folders: StatefulTable::default(), seasons: StatefulTable::default(), season_details_modal: None, selected_block: BlockSelectionState::default(), series: StatefulTable::default(), series_history: None, start_time: DateTime::default(), tags_map: BiMap::default(), tasks: StatefulTable::default(), updates: ScrollableText::default(), version: String::new(), main_tabs: TabState::new(vec![ TabRoute { title: "Library".to_string(), route: ActiveSonarrBlock::Series.into(), contextual_help: Some(&SERIES_CONTEXT_CLUES), config: None, }, TabRoute { title: "Downloads".to_string(), route: ActiveSonarrBlock::Downloads.into(), contextual_help: Some(&DOWNLOADS_CONTEXT_CLUES), config: None, }, TabRoute { title: "Blocklist".to_string(), route: ActiveSonarrBlock::Blocklist.into(), contextual_help: Some(&BLOCKLIST_CONTEXT_CLUES), config: None, }, TabRoute { title: "History".to_string(), route: ActiveSonarrBlock::History.into(), contextual_help: Some(&HISTORY_CONTEXT_CLUES), config: None, }, TabRoute { title: "Root Folders".to_string(), route: ActiveSonarrBlock::RootFolders.into(), contextual_help: Some(&ROOT_FOLDERS_CONTEXT_CLUES), config: None, }, TabRoute { title: "Indexers".to_string(), route: ActiveSonarrBlock::Indexers.into(), contextual_help: Some(&INDEXERS_CONTEXT_CLUES), config: None, }, TabRoute { title: "System".to_string(), route: ActiveSonarrBlock::System.into(), contextual_help: Some(&SYSTEM_CONTEXT_CLUES), config: None, }, ]), series_info_tabs: TabState::new(vec![ TabRoute { title: "Seasons".to_string(), route: ActiveSonarrBlock::SeriesDetails.into(), contextual_help: Some(&SERIES_DETAILS_CONTEXT_CLUES), config: None, }, TabRoute { title: "History".to_string(), route: ActiveSonarrBlock::SeriesHistory.into(), contextual_help: Some(&SERIES_HISTORY_CONTEXT_CLUES), config: None, }, ]), } } } #[derive(Clone, Copy, PartialEq, Eq, Debug, Default, EnumIter)] pub enum ActiveSonarrBlock { AddRootFolderPrompt, AddSeriesAlreadyInLibrary, AddSeriesConfirmPrompt, AddSeriesEmptySearchResults, AddSeriesPrompt, AddSeriesSearchInput, AddSeriesSearchResults, AddSeriesSelectLanguageProfile, AddSeriesSelectMonitor, AddSeriesSelectQualityProfile, AddSeriesSelectRootFolder, AddSeriesSelectSeriesType, AddSeriesTagsInput, AddSeriesToggleUseSeasonFolder, AllIndexerSettingsPrompt, AutomaticallySearchEpisodePrompt, AutomaticallySearchSeasonPrompt, AutomaticallySearchSeriesPrompt, Blocklist, BlocklistClearAllItemsPrompt, BlocklistItemDetails, BlocklistSortPrompt, DeleteBlocklistItemPrompt, DeleteDownloadPrompt, DeleteEpisodeFilePrompt, DeleteIndexerPrompt, DeleteRootFolderPrompt, DeleteSeriesConfirmPrompt, DeleteSeriesPrompt, DeleteSeriesToggleAddListExclusion, DeleteSeriesToggleDeleteFile, Downloads, EditIndexerPrompt, EditIndexerConfirmPrompt, EditIndexerApiKeyInput, EditIndexerNameInput, EditIndexerSeedRatioInput, EditIndexerToggleEnableRss, EditIndexerToggleEnableAutomaticSearch, EditIndexerToggleEnableInteractiveSearch, EditIndexerUrlInput, EditIndexerPriorityInput, EditIndexerTagsInput, EditSeriesPrompt, EditSeriesConfirmPrompt, EditSeriesPathInput, EditSeriesSelectSeriesType, EditSeriesSelectQualityProfile, EditSeriesSelectLanguageProfile, EditSeriesTagsInput, EditSeriesToggleMonitored, EditSeriesToggleSeasonFolder, EpisodeDetails, EpisodeFile, EpisodeHistory, EpisodeHistoryDetails, EpisodesSortPrompt, FilterEpisodes, FilterEpisodesError, FilterHistory, FilterHistoryError, FilterSeries, FilterSeriesError, FilterSeriesHistory, FilterSeriesHistoryError, FilterSeasonHistory, FilterSeasonHistoryError, History, HistoryItemDetails, HistorySortPrompt, Indexers, IndexerSettingsConfirmPrompt, IndexerSettingsMaximumSizeInput, IndexerSettingsMinimumAgeInput, IndexerSettingsRetentionInput, IndexerSettingsRssSyncIntervalInput, ManualEpisodeSearch, ManualEpisodeSearchConfirmPrompt, ManualEpisodeSearchSortPrompt, ManualSeasonSearch, ManualSeasonSearchConfirmPrompt, ManualSeasonSearchSortPrompt, RootFolders, SearchEpisodes, SearchEpisodesError, SearchHistory, SearchHistoryError, SearchSeason, SearchSeasonError, SearchSeries, SearchSeriesError, SearchSeriesHistory, SearchSeriesHistoryError, SearchSeasonHistory, SearchSeasonHistoryError, SeasonDetails, SeasonHistory, SeasonHistoryDetails, SeasonHistorySortPrompt, #[default] Series, SeriesDetails, SeriesHistory, SeriesHistoryDetails, SeriesHistorySortPrompt, SeriesSortPrompt, System, SystemLogs, SystemQueuedEvents, SystemTasks, SystemTaskStartConfirmPrompt, SystemUpdates, TestAllIndexers, TestIndexer, UpdateAllSeriesPrompt, UpdateAndScanSeriesPrompt, UpdateDownloadsPrompt, } pub static LIBRARY_BLOCKS: [ActiveSonarrBlock; 7] = [ ActiveSonarrBlock::Series, ActiveSonarrBlock::SeriesSortPrompt, ActiveSonarrBlock::SearchSeries, ActiveSonarrBlock::SearchSeriesError, ActiveSonarrBlock::FilterSeries, ActiveSonarrBlock::FilterSeriesError, ActiveSonarrBlock::UpdateAllSeriesPrompt, ]; pub static SERIES_DETAILS_BLOCKS: [ActiveSonarrBlock; 12] = [ ActiveSonarrBlock::SeriesDetails, ActiveSonarrBlock::SeriesHistory, ActiveSonarrBlock::SearchSeason, ActiveSonarrBlock::SearchSeasonError, ActiveSonarrBlock::UpdateAndScanSeriesPrompt, ActiveSonarrBlock::AutomaticallySearchSeriesPrompt, ActiveSonarrBlock::SearchSeriesHistory, ActiveSonarrBlock::SearchSeriesHistoryError, ActiveSonarrBlock::FilterSeriesHistory, ActiveSonarrBlock::FilterSeriesHistoryError, ActiveSonarrBlock::SeriesHistorySortPrompt, ActiveSonarrBlock::SeriesHistoryDetails, ]; pub static SEASON_DETAILS_BLOCKS: [ActiveSonarrBlock; 15] = [ ActiveSonarrBlock::SeasonDetails, ActiveSonarrBlock::SeasonHistory, ActiveSonarrBlock::SearchEpisodes, ActiveSonarrBlock::SearchEpisodesError, ActiveSonarrBlock::AutomaticallySearchSeasonPrompt, ActiveSonarrBlock::SearchSeasonHistory, ActiveSonarrBlock::SearchSeasonHistoryError, ActiveSonarrBlock::FilterSeasonHistory, ActiveSonarrBlock::FilterSeasonHistoryError, ActiveSonarrBlock::SeasonHistorySortPrompt, ActiveSonarrBlock::SeasonHistoryDetails, ActiveSonarrBlock::ManualSeasonSearch, ActiveSonarrBlock::ManualSeasonSearchConfirmPrompt, ActiveSonarrBlock::ManualSeasonSearchSortPrompt, ActiveSonarrBlock::DeleteEpisodeFilePrompt, ]; pub static EPISODE_DETAILS_BLOCKS: [ActiveSonarrBlock; 8] = [ ActiveSonarrBlock::EpisodeDetails, ActiveSonarrBlock::EpisodeHistory, ActiveSonarrBlock::EpisodeHistoryDetails, ActiveSonarrBlock::EpisodeFile, ActiveSonarrBlock::ManualEpisodeSearch, ActiveSonarrBlock::ManualEpisodeSearchConfirmPrompt, ActiveSonarrBlock::ManualEpisodeSearchSortPrompt, ActiveSonarrBlock::AutomaticallySearchEpisodePrompt, ]; pub static ADD_SERIES_BLOCKS: [ActiveSonarrBlock; 13] = [ ActiveSonarrBlock::AddSeriesAlreadyInLibrary, ActiveSonarrBlock::AddSeriesConfirmPrompt, ActiveSonarrBlock::AddSeriesEmptySearchResults, ActiveSonarrBlock::AddSeriesPrompt, ActiveSonarrBlock::AddSeriesSearchInput, ActiveSonarrBlock::AddSeriesSearchResults, ActiveSonarrBlock::AddSeriesSelectLanguageProfile, ActiveSonarrBlock::AddSeriesSelectMonitor, ActiveSonarrBlock::AddSeriesSelectQualityProfile, ActiveSonarrBlock::AddSeriesSelectRootFolder, ActiveSonarrBlock::AddSeriesSelectSeriesType, ActiveSonarrBlock::AddSeriesTagsInput, ActiveSonarrBlock::AddSeriesToggleUseSeasonFolder, ]; pub const ADD_SERIES_SELECTION_BLOCKS: &[&[ActiveSonarrBlock]] = &[ &[ActiveSonarrBlock::AddSeriesSelectRootFolder], &[ActiveSonarrBlock::AddSeriesSelectMonitor], &[ActiveSonarrBlock::AddSeriesSelectQualityProfile], &[ActiveSonarrBlock::AddSeriesSelectLanguageProfile], &[ActiveSonarrBlock::AddSeriesSelectSeriesType], &[ActiveSonarrBlock::AddSeriesToggleUseSeasonFolder], &[ActiveSonarrBlock::AddSeriesTagsInput], &[ActiveSonarrBlock::AddSeriesConfirmPrompt], ]; pub static BLOCKLIST_BLOCKS: [ActiveSonarrBlock; 5] = [ ActiveSonarrBlock::Blocklist, ActiveSonarrBlock::BlocklistItemDetails, ActiveSonarrBlock::DeleteBlocklistItemPrompt, ActiveSonarrBlock::BlocklistClearAllItemsPrompt, ActiveSonarrBlock::BlocklistSortPrompt, ]; pub static EDIT_SERIES_BLOCKS: [ActiveSonarrBlock; 9] = [ ActiveSonarrBlock::EditSeriesPrompt, ActiveSonarrBlock::EditSeriesConfirmPrompt, ActiveSonarrBlock::EditSeriesPathInput, ActiveSonarrBlock::EditSeriesSelectSeriesType, ActiveSonarrBlock::EditSeriesSelectQualityProfile, ActiveSonarrBlock::EditSeriesSelectLanguageProfile, ActiveSonarrBlock::EditSeriesTagsInput, ActiveSonarrBlock::EditSeriesToggleMonitored, ActiveSonarrBlock::EditSeriesToggleSeasonFolder, ]; pub static EDIT_SERIES_SELECTION_BLOCKS: &[&[ActiveSonarrBlock]] = &[ &[ActiveSonarrBlock::EditSeriesToggleMonitored], &[ActiveSonarrBlock::EditSeriesToggleSeasonFolder], &[ActiveSonarrBlock::EditSeriesSelectQualityProfile], &[ActiveSonarrBlock::EditSeriesSelectLanguageProfile], &[ActiveSonarrBlock::EditSeriesSelectSeriesType], &[ActiveSonarrBlock::EditSeriesPathInput], &[ActiveSonarrBlock::EditSeriesTagsInput], &[ActiveSonarrBlock::EditSeriesConfirmPrompt], ]; pub static DOWNLOADS_BLOCKS: [ActiveSonarrBlock; 3] = [ ActiveSonarrBlock::Downloads, ActiveSonarrBlock::DeleteDownloadPrompt, ActiveSonarrBlock::UpdateDownloadsPrompt, ]; pub static DELETE_SERIES_BLOCKS: [ActiveSonarrBlock; 4] = [ ActiveSonarrBlock::DeleteSeriesPrompt, ActiveSonarrBlock::DeleteSeriesConfirmPrompt, ActiveSonarrBlock::DeleteSeriesToggleDeleteFile, ActiveSonarrBlock::DeleteSeriesToggleAddListExclusion, ]; pub const DELETE_SERIES_SELECTION_BLOCKS: &[&[ActiveSonarrBlock]] = &[ &[ActiveSonarrBlock::DeleteSeriesToggleDeleteFile], &[ActiveSonarrBlock::DeleteSeriesToggleAddListExclusion], &[ActiveSonarrBlock::DeleteSeriesConfirmPrompt], ]; pub static EDIT_INDEXER_BLOCKS: [ActiveSonarrBlock; 11] = [ ActiveSonarrBlock::EditIndexerPrompt, ActiveSonarrBlock::EditIndexerConfirmPrompt, ActiveSonarrBlock::EditIndexerApiKeyInput, ActiveSonarrBlock::EditIndexerNameInput, ActiveSonarrBlock::EditIndexerSeedRatioInput, ActiveSonarrBlock::EditIndexerToggleEnableRss, ActiveSonarrBlock::EditIndexerToggleEnableAutomaticSearch, ActiveSonarrBlock::EditIndexerToggleEnableInteractiveSearch, ActiveSonarrBlock::EditIndexerPriorityInput, ActiveSonarrBlock::EditIndexerUrlInput, ActiveSonarrBlock::EditIndexerTagsInput, ]; pub const EDIT_INDEXER_TORRENT_SELECTION_BLOCKS: &[&[ActiveSonarrBlock]] = &[ &[ ActiveSonarrBlock::EditIndexerNameInput, ActiveSonarrBlock::EditIndexerUrlInput, ], &[ ActiveSonarrBlock::EditIndexerToggleEnableRss, ActiveSonarrBlock::EditIndexerApiKeyInput, ], &[ ActiveSonarrBlock::EditIndexerToggleEnableAutomaticSearch, ActiveSonarrBlock::EditIndexerSeedRatioInput, ], &[ ActiveSonarrBlock::EditIndexerToggleEnableInteractiveSearch, ActiveSonarrBlock::EditIndexerTagsInput, ], &[ ActiveSonarrBlock::EditIndexerPriorityInput, ActiveSonarrBlock::EditIndexerConfirmPrompt, ], &[ ActiveSonarrBlock::EditIndexerConfirmPrompt, ActiveSonarrBlock::EditIndexerConfirmPrompt, ], ]; pub const EDIT_INDEXER_NZB_SELECTION_BLOCKS: &[&[ActiveSonarrBlock]] = &[ &[ ActiveSonarrBlock::EditIndexerNameInput, ActiveSonarrBlock::EditIndexerUrlInput, ], &[ ActiveSonarrBlock::EditIndexerToggleEnableRss, ActiveSonarrBlock::EditIndexerApiKeyInput, ], &[ ActiveSonarrBlock::EditIndexerToggleEnableAutomaticSearch, ActiveSonarrBlock::EditIndexerTagsInput, ], &[ ActiveSonarrBlock::EditIndexerToggleEnableInteractiveSearch, ActiveSonarrBlock::EditIndexerPriorityInput, ], &[ ActiveSonarrBlock::EditIndexerConfirmPrompt, ActiveSonarrBlock::EditIndexerConfirmPrompt, ], ]; pub static INDEXER_SETTINGS_BLOCKS: [ActiveSonarrBlock; 6] = [ ActiveSonarrBlock::AllIndexerSettingsPrompt, ActiveSonarrBlock::IndexerSettingsConfirmPrompt, ActiveSonarrBlock::IndexerSettingsMaximumSizeInput, ActiveSonarrBlock::IndexerSettingsMinimumAgeInput, ActiveSonarrBlock::IndexerSettingsRetentionInput, ActiveSonarrBlock::IndexerSettingsRssSyncIntervalInput, ]; pub const INDEXER_SETTINGS_SELECTION_BLOCKS: &[&[ActiveSonarrBlock]] = &[ &[ActiveSonarrBlock::IndexerSettingsMinimumAgeInput], &[ActiveSonarrBlock::IndexerSettingsRetentionInput], &[ActiveSonarrBlock::IndexerSettingsMaximumSizeInput], &[ActiveSonarrBlock::IndexerSettingsRssSyncIntervalInput], &[ActiveSonarrBlock::IndexerSettingsConfirmPrompt], ]; pub static HISTORY_BLOCKS: [ActiveSonarrBlock; 7] = [ ActiveSonarrBlock::History, ActiveSonarrBlock::HistoryItemDetails, ActiveSonarrBlock::HistorySortPrompt, ActiveSonarrBlock::FilterHistory, ActiveSonarrBlock::FilterHistoryError, ActiveSonarrBlock::SearchHistory, ActiveSonarrBlock::SearchHistoryError, ]; pub static ROOT_FOLDERS_BLOCKS: [ActiveSonarrBlock; 3] = [ ActiveSonarrBlock::RootFolders, ActiveSonarrBlock::AddRootFolderPrompt, ActiveSonarrBlock::DeleteRootFolderPrompt, ]; pub static INDEXERS_BLOCKS: [ActiveSonarrBlock; 3] = [ ActiveSonarrBlock::DeleteIndexerPrompt, ActiveSonarrBlock::Indexers, ActiveSonarrBlock::TestIndexer, ]; pub static SYSTEM_DETAILS_BLOCKS: [ActiveSonarrBlock; 5] = [ ActiveSonarrBlock::SystemLogs, ActiveSonarrBlock::SystemQueuedEvents, ActiveSonarrBlock::SystemTasks, ActiveSonarrBlock::SystemTaskStartConfirmPrompt, ActiveSonarrBlock::SystemUpdates, ]; impl From for Route { fn from(active_sonarr_block: ActiveSonarrBlock) -> Route { Route::Sonarr(active_sonarr_block, None) } } impl From<(ActiveSonarrBlock, Option)> for Route { fn from(value: (ActiveSonarrBlock, Option)) -> Route { Route::Sonarr(value.0, value.1) } }