use bimap::BiMap; use chrono::{DateTime, Utc}; use strum::IntoEnumIterator; use strum_macros::EnumIter; use crate::app::{App, Route}; use crate::models::radarr_models::{ AddMovieSearchResult, Collection, CollectionMovie, Credit, DiskSpace, DownloadRecord, Indexer, IndexerSettings, MinimumAvailability, Monitor, Movie, MovieHistoryItem, QueueEvent, Release, ReleaseField, RootFolder, Task, }; use crate::models::{ BlockSelectionState, HorizontallyScrollableText, ScrollableText, StatefulList, StatefulTable, TabRoute, TabState, }; use crate::network::radarr_network::RadarrEvent; #[cfg(test)] #[path = "radarr_tests.rs"] mod radarr_tests; #[cfg(test)] #[path = "radarr_test_utils.rs"] pub mod radarr_test_utils; pub struct RadarrData<'a> { pub root_folders: StatefulTable, pub disk_space_vec: Vec, pub version: String, pub start_time: DateTime, pub movies: StatefulTable, pub filtered_movies: StatefulTable, pub add_searched_movies: StatefulTable, pub monitor_list: StatefulList, pub minimum_availability_list: StatefulList, pub quality_profile_list: StatefulList, pub root_folder_list: StatefulList, pub selected_block: BlockSelectionState<'a, ActiveRadarrBlock>, pub downloads: StatefulTable, pub indexers: StatefulTable, pub indexer_settings: Option, pub quality_profile_map: BiMap, pub tags_map: BiMap, pub movie_details: ScrollableText, pub file_details: String, pub audio_details: String, pub video_details: String, pub movie_history: StatefulTable, pub movie_cast: StatefulTable, pub movie_crew: StatefulTable, pub movie_releases: StatefulTable, pub movie_releases_sort: StatefulList, pub collections: StatefulTable, pub filtered_collections: StatefulTable, pub collection_movies: StatefulTable, pub logs: StatefulList, pub log_details: StatefulList, pub tasks: StatefulTable, pub queued_events: StatefulTable, pub updates: ScrollableText, pub prompt_confirm_action: Option, pub main_tabs: TabState, pub movie_info_tabs: TabState, pub search: HorizontallyScrollableText, pub filter: HorizontallyScrollableText, pub edit_path: HorizontallyScrollableText, pub edit_tags: HorizontallyScrollableText, pub edit_monitored: Option, pub edit_search_on_add: Option, pub sort_ascending: Option, pub prompt_confirm: bool, pub delete_movie_files: bool, pub add_list_exclusion: bool, pub is_searching: bool, pub is_filtering: bool, } impl<'a> RadarrData<'a> { pub fn reset_movie_collection_table(&mut self) { self.collection_movies = StatefulTable::default(); } pub fn reset_log_details_list(&mut self) { self.log_details = StatefulList::default(); } pub fn reset_delete_movie_preferences(&mut self) { self.delete_movie_files = false; self.add_list_exclusion = false; } pub fn reset_search(&mut self) { self.is_searching = false; self.search = HorizontallyScrollableText::default(); self.filter = HorizontallyScrollableText::default(); self.filtered_movies = StatefulTable::default(); self.filtered_collections = StatefulTable::default(); self.add_searched_movies = StatefulTable::default(); } pub fn reset_filter(&mut self) { self.is_filtering = false; self.filter = HorizontallyScrollableText::default(); self.filtered_movies = StatefulTable::default(); self.filtered_collections = StatefulTable::default(); } pub fn reset_add_edit_media_fields(&mut self) { self.edit_monitored = None; self.edit_search_on_add = None; self.edit_path = HorizontallyScrollableText::default(); self.edit_tags = HorizontallyScrollableText::default(); self.reset_preferences_selections(); } pub fn reset_movie_info_tabs(&mut self) { self.file_details = String::default(); self.audio_details = String::default(); self.video_details = String::default(); self.movie_details = ScrollableText::default(); self.movie_history = StatefulTable::default(); self.movie_cast = StatefulTable::default(); self.movie_crew = StatefulTable::default(); self.movie_releases = StatefulTable::default(); self.movie_releases_sort = StatefulList::default(); self.sort_ascending = None; self.movie_info_tabs.index = 0; } pub fn reset_preferences_selections(&mut self) { self.monitor_list = StatefulList::default(); self.minimum_availability_list = StatefulList::default(); self.quality_profile_list = StatefulList::default(); self.root_folder_list = StatefulList::default(); } pub fn populate_preferences_lists(&mut self) { self.monitor_list.set_items(Vec::from_iter(Monitor::iter())); self .minimum_availability_list .set_items(Vec::from_iter(MinimumAvailability::iter())); let mut quality_profile_names: Vec = self.quality_profile_map.right_values().cloned().collect(); quality_profile_names.sort(); self.quality_profile_list.set_items(quality_profile_names); self .root_folder_list .set_items(self.root_folders.items.to_vec()); } pub fn populate_edit_movie_fields(&mut self) { self.populate_preferences_lists(); let Movie { path, tags, monitored, minimum_availability, quality_profile_id, .. } = if self.filtered_movies.items.is_empty() { self.movies.current_selection() } else { self.filtered_movies.current_selection() }; self.edit_path = path.clone().into(); self.edit_tags = tags .iter() .map(|tag_id| { self .tags_map .get_by_left(&tag_id.as_u64().unwrap()) .unwrap() .clone() }) .collect::>() .join(", ") .into(); self.edit_monitored = Some(*monitored); let minimum_availability_index = self .minimum_availability_list .items .iter() .position(|ma| ma == minimum_availability); self .minimum_availability_list .state .select(minimum_availability_index); let quality_profile_name = self .quality_profile_map .get_by_left(&quality_profile_id.as_u64().unwrap()) .unwrap(); let quality_profile_index = self .quality_profile_list .items .iter() .position(|profile| profile == quality_profile_name); self .quality_profile_list .state .select(quality_profile_index); } pub fn populate_edit_collection_fields(&mut self) { self.populate_preferences_lists(); let Collection { root_folder_path, monitored, search_on_add, minimum_availability, quality_profile_id, .. } = if self.filtered_collections.items.is_empty() { self.collections.current_selection() } else { self.filtered_collections.current_selection() }; self.edit_path = root_folder_path.clone().unwrap_or_default().into(); self.edit_monitored = Some(*monitored); self.edit_search_on_add = Some(*search_on_add); let minimum_availability_index = self .minimum_availability_list .items .iter() .position(|ma| ma == minimum_availability); self .minimum_availability_list .state .select(minimum_availability_index); let quality_profile_name = self .quality_profile_map .get_by_left(&quality_profile_id.as_u64().unwrap()) .unwrap(); let quality_profile_index = self .quality_profile_list .items .iter() .position(|profile| profile == quality_profile_name); self .quality_profile_list .state .select(quality_profile_index); } } impl<'a> Default for RadarrData<'a> { fn default() -> RadarrData<'a> { RadarrData { root_folders: StatefulTable::default(), disk_space_vec: Vec::new(), version: String::default(), start_time: DateTime::default(), movies: StatefulTable::default(), add_searched_movies: StatefulTable::default(), monitor_list: StatefulList::default(), minimum_availability_list: StatefulList::default(), quality_profile_list: StatefulList::default(), root_folder_list: StatefulList::default(), selected_block: BlockSelectionState::default(), filtered_movies: StatefulTable::default(), downloads: StatefulTable::default(), indexers: StatefulTable::default(), indexer_settings: None, quality_profile_map: BiMap::default(), tags_map: BiMap::default(), file_details: String::default(), audio_details: String::default(), video_details: String::default(), movie_details: ScrollableText::default(), movie_history: StatefulTable::default(), movie_cast: StatefulTable::default(), movie_crew: StatefulTable::default(), movie_releases: StatefulTable::default(), movie_releases_sort: StatefulList::default(), collections: StatefulTable::default(), filtered_collections: StatefulTable::default(), collection_movies: StatefulTable::default(), logs: StatefulList::default(), log_details: StatefulList::default(), tasks: StatefulTable::default(), queued_events: StatefulTable::default(), updates: ScrollableText::default(), prompt_confirm_action: None, search: HorizontallyScrollableText::default(), filter: HorizontallyScrollableText::default(), edit_path: HorizontallyScrollableText::default(), edit_tags: HorizontallyScrollableText::default(), edit_monitored: None, edit_search_on_add: None, sort_ascending: None, is_searching: false, is_filtering: false, prompt_confirm: false, delete_movie_files: false, add_list_exclusion: false, main_tabs: TabState::new(vec![ TabRoute { title: "Library", route: ActiveRadarrBlock::Movies.into(), help: "", contextual_help: Some(" add | edit | delete | search | filter | refresh | update all | details | cancel filter"), }, TabRoute { title: "Downloads", route: ActiveRadarrBlock::Downloads.into(), help: "", contextual_help: Some(" refresh | delete"), }, TabRoute { title: "Collections", route: ActiveRadarrBlock::Collections.into(), help: "", contextual_help: Some(" search | edit | filter | refresh | update all | details | cancel filter"), }, TabRoute { title: "Root Folders", route: ActiveRadarrBlock::RootFolders.into(), help: "", contextual_help: Some(" add | delete | refresh"), }, TabRoute { title: "Indexers", route: ActiveRadarrBlock::Indexers.into(), help: "", contextual_help: Some(" add | edit | settings | restrictions | delete | refresh"), }, TabRoute { title: "System", route: ActiveRadarrBlock::System.into(), help: "", contextual_help: Some(" open tasks | open events | open logs | open updates | refresh"), }, ]), movie_info_tabs: TabState::new(vec![ TabRoute { title: "Details", route: ActiveRadarrBlock::MovieDetails.into(), help: " refresh | update | edit | auto search | close", contextual_help: None, }, TabRoute { title: "History", route: ActiveRadarrBlock::MovieHistory.into(), help: " refresh | update | edit | auto search | close", contextual_help: None, }, TabRoute { title: "File", route: ActiveRadarrBlock::FileInfo.into(), help: " refresh | update | edit | auto search | close", contextual_help: None, }, TabRoute { title: "Cast", route: ActiveRadarrBlock::Cast.into(), help: " refresh | update | edit | auto search | close", contextual_help: None, }, TabRoute { title: "Crew", route: ActiveRadarrBlock::Crew.into(), help: " refresh | update | edit | auto search | close", contextual_help: None, }, TabRoute { title: "Manual Search", route: ActiveRadarrBlock::ManualSearch.into(), help: " refresh | update | edit | sort | auto search | close", contextual_help: Some(" details"), }, ]), } } } #[derive(Clone, Copy, PartialEq, Eq, Debug, Default, EnumIter)] pub enum ActiveRadarrBlock { AddIndexer, AddMovieAlreadyInLibrary, AddMovieSearchInput, AddMovieSearchResults, AddMoviePrompt, AddMovieSelectMinimumAvailability, AddMovieSelectQualityProfile, AddMovieSelectMonitor, AddMovieSelectRootFolder, AddMovieConfirmPrompt, AddMovieTagsInput, AddMovieEmptySearchResults, AddRootFolderPrompt, AutomaticallySearchMoviePrompt, Collections, CollectionDetails, Cast, Crew, DeleteDownloadPrompt, DeleteIndexerPrompt, DeleteMoviePrompt, DeleteMovieConfirmPrompt, DeleteMovieToggleDeleteFile, DeleteMovieToggleAddListExclusion, DeleteRootFolderPrompt, Downloads, EditCollectionPrompt, EditCollectionConfirmPrompt, EditCollectionRootFolderPathInput, EditCollectionSelectMinimumAvailability, EditCollectionSelectQualityProfile, EditCollectionToggleSearchOnAdd, EditCollectionToggleMonitored, EditIndexer, EditMoviePrompt, EditMovieConfirmPrompt, EditMoviePathInput, EditMovieSelectMinimumAvailability, EditMovieSelectQualityProfile, EditMovieTagsInput, EditMovieToggleMonitored, FileInfo, FilterCollections, FilterMovies, Indexers, IndexerSettingsPrompt, IndexerSettingsAvailabilityDelayInput, IndexerSettingsConfirmPrompt, IndexerSettingsMaximumSizeInput, IndexerSettingsMinimumAgeInput, IndexerSettingsRetentionInput, IndexerSettingsRssSyncIntervalInput, IndexerSettingsToggleAllowHardcodedSubs, IndexerSettingsTogglePreferIndexerFlags, IndexerSettingsWhitelistedSubtitleTagsInput, ManualSearch, ManualSearchSortPrompt, ManualSearchConfirmPrompt, MovieDetails, MovieHistory, #[default] Movies, RootFolders, System, SystemLogs, SystemQueuedEvents, SystemTasks, SystemTaskStartConfirmPrompt, SystemUpdates, UpdateAndScanPrompt, UpdateAllCollectionsPrompt, UpdateAllMoviesPrompt, UpdateDownloadsPrompt, SearchMovie, SearchCollection, ViewMovieOverview, } pub static LIBRARY_BLOCKS: [ActiveRadarrBlock; 4] = [ ActiveRadarrBlock::Movies, ActiveRadarrBlock::SearchMovie, ActiveRadarrBlock::FilterMovies, ActiveRadarrBlock::UpdateAllMoviesPrompt, ]; pub static COLLECTIONS_BLOCKS: [ActiveRadarrBlock; 4] = [ ActiveRadarrBlock::Collections, ActiveRadarrBlock::SearchCollection, ActiveRadarrBlock::FilterCollections, ActiveRadarrBlock::UpdateAllCollectionsPrompt, ]; pub static INDEXERS_BLOCKS: [ActiveRadarrBlock; 4] = [ ActiveRadarrBlock::AddIndexer, ActiveRadarrBlock::EditIndexer, ActiveRadarrBlock::DeleteIndexerPrompt, ActiveRadarrBlock::Indexers, ]; pub static ROOT_FOLDERS_BLOCKS: [ActiveRadarrBlock; 3] = [ ActiveRadarrBlock::RootFolders, ActiveRadarrBlock::AddRootFolderPrompt, ActiveRadarrBlock::DeleteRootFolderPrompt, ]; pub static ADD_MOVIE_BLOCKS: [ActiveRadarrBlock; 10] = [ ActiveRadarrBlock::AddMovieSearchInput, ActiveRadarrBlock::AddMovieSearchResults, ActiveRadarrBlock::AddMovieEmptySearchResults, ActiveRadarrBlock::AddMoviePrompt, ActiveRadarrBlock::AddMovieSelectMinimumAvailability, ActiveRadarrBlock::AddMovieSelectMonitor, ActiveRadarrBlock::AddMovieSelectQualityProfile, ActiveRadarrBlock::AddMovieSelectRootFolder, ActiveRadarrBlock::AddMovieAlreadyInLibrary, ActiveRadarrBlock::AddMovieTagsInput, ]; pub static ADD_MOVIE_SELECTION_BLOCKS: [ActiveRadarrBlock; 6] = [ ActiveRadarrBlock::AddMovieSelectRootFolder, ActiveRadarrBlock::AddMovieSelectMonitor, ActiveRadarrBlock::AddMovieSelectMinimumAvailability, ActiveRadarrBlock::AddMovieSelectQualityProfile, ActiveRadarrBlock::AddMovieTagsInput, ActiveRadarrBlock::AddMovieConfirmPrompt, ]; pub static EDIT_COLLECTION_BLOCKS: [ActiveRadarrBlock; 7] = [ ActiveRadarrBlock::EditCollectionPrompt, ActiveRadarrBlock::EditCollectionConfirmPrompt, ActiveRadarrBlock::EditCollectionRootFolderPathInput, ActiveRadarrBlock::EditCollectionSelectMinimumAvailability, ActiveRadarrBlock::EditCollectionSelectQualityProfile, ActiveRadarrBlock::EditCollectionToggleSearchOnAdd, ActiveRadarrBlock::EditCollectionToggleMonitored, ]; pub static EDIT_COLLECTION_SELECTION_BLOCKS: [ActiveRadarrBlock; 6] = [ ActiveRadarrBlock::EditCollectionToggleMonitored, ActiveRadarrBlock::EditCollectionSelectMinimumAvailability, ActiveRadarrBlock::EditCollectionSelectQualityProfile, ActiveRadarrBlock::EditCollectionRootFolderPathInput, ActiveRadarrBlock::EditCollectionToggleSearchOnAdd, ActiveRadarrBlock::EditCollectionConfirmPrompt, ]; pub static EDIT_MOVIE_BLOCKS: [ActiveRadarrBlock; 7] = [ ActiveRadarrBlock::EditMoviePrompt, ActiveRadarrBlock::EditMovieConfirmPrompt, ActiveRadarrBlock::EditMoviePathInput, ActiveRadarrBlock::EditMovieSelectMinimumAvailability, ActiveRadarrBlock::EditMovieSelectQualityProfile, ActiveRadarrBlock::EditMovieTagsInput, ActiveRadarrBlock::EditMovieToggleMonitored, ]; pub static EDIT_MOVIE_SELECTION_BLOCKS: [ActiveRadarrBlock; 6] = [ ActiveRadarrBlock::EditMovieToggleMonitored, ActiveRadarrBlock::EditMovieSelectMinimumAvailability, ActiveRadarrBlock::EditMovieSelectQualityProfile, ActiveRadarrBlock::EditMoviePathInput, ActiveRadarrBlock::EditMovieTagsInput, ActiveRadarrBlock::EditMovieConfirmPrompt, ]; pub static DOWNLOADS_BLOCKS: [ActiveRadarrBlock; 3] = [ ActiveRadarrBlock::Downloads, ActiveRadarrBlock::DeleteDownloadPrompt, ActiveRadarrBlock::UpdateDownloadsPrompt, ]; pub static MOVIE_DETAILS_BLOCKS: [ActiveRadarrBlock; 10] = [ ActiveRadarrBlock::MovieDetails, ActiveRadarrBlock::MovieHistory, ActiveRadarrBlock::FileInfo, ActiveRadarrBlock::Cast, ActiveRadarrBlock::Crew, ActiveRadarrBlock::AutomaticallySearchMoviePrompt, ActiveRadarrBlock::UpdateAndScanPrompt, ActiveRadarrBlock::ManualSearch, ActiveRadarrBlock::ManualSearchSortPrompt, ActiveRadarrBlock::ManualSearchConfirmPrompt, ]; pub static COLLECTION_DETAILS_BLOCKS: [ActiveRadarrBlock; 2] = [ ActiveRadarrBlock::CollectionDetails, ActiveRadarrBlock::ViewMovieOverview, ]; pub static SEARCH_BLOCKS: [ActiveRadarrBlock; 2] = [ ActiveRadarrBlock::SearchMovie, ActiveRadarrBlock::SearchCollection, ]; pub static FILTER_BLOCKS: [ActiveRadarrBlock; 2] = [ ActiveRadarrBlock::FilterMovies, ActiveRadarrBlock::FilterCollections, ]; pub static DELETE_MOVIE_BLOCKS: [ActiveRadarrBlock; 4] = [ ActiveRadarrBlock::DeleteMoviePrompt, ActiveRadarrBlock::DeleteMovieConfirmPrompt, ActiveRadarrBlock::DeleteMovieToggleDeleteFile, ActiveRadarrBlock::DeleteMovieToggleAddListExclusion, ]; pub static DELETE_MOVIE_SELECTION_BLOCKS: [ActiveRadarrBlock; 3] = [ ActiveRadarrBlock::DeleteMovieToggleDeleteFile, ActiveRadarrBlock::DeleteMovieToggleAddListExclusion, ActiveRadarrBlock::DeleteMovieConfirmPrompt, ]; pub static INDEXER_SETTINGS_BLOCKS: [ActiveRadarrBlock; 10] = [ ActiveRadarrBlock::IndexerSettingsPrompt, ActiveRadarrBlock::IndexerSettingsAvailabilityDelayInput, ActiveRadarrBlock::IndexerSettingsConfirmPrompt, ActiveRadarrBlock::IndexerSettingsMaximumSizeInput, ActiveRadarrBlock::IndexerSettingsMinimumAgeInput, ActiveRadarrBlock::IndexerSettingsRetentionInput, ActiveRadarrBlock::IndexerSettingsRssSyncIntervalInput, ActiveRadarrBlock::IndexerSettingsToggleAllowHardcodedSubs, ActiveRadarrBlock::IndexerSettingsTogglePreferIndexerFlags, ActiveRadarrBlock::IndexerSettingsWhitelistedSubtitleTagsInput, ]; pub static INDEXER_SETTINGS_SELECTION_BLOCKS: [ActiveRadarrBlock; 9] = [ ActiveRadarrBlock::IndexerSettingsMinimumAgeInput, ActiveRadarrBlock::IndexerSettingsRetentionInput, ActiveRadarrBlock::IndexerSettingsMaximumSizeInput, ActiveRadarrBlock::IndexerSettingsTogglePreferIndexerFlags, ActiveRadarrBlock::IndexerSettingsAvailabilityDelayInput, ActiveRadarrBlock::IndexerSettingsRssSyncIntervalInput, ActiveRadarrBlock::IndexerSettingsWhitelistedSubtitleTagsInput, ActiveRadarrBlock::IndexerSettingsToggleAllowHardcodedSubs, ActiveRadarrBlock::IndexerSettingsConfirmPrompt, ]; pub static SYSTEM_DETAILS_BLOCKS: [ActiveRadarrBlock; 5] = [ ActiveRadarrBlock::SystemLogs, ActiveRadarrBlock::SystemQueuedEvents, ActiveRadarrBlock::SystemTasks, ActiveRadarrBlock::SystemTaskStartConfirmPrompt, ActiveRadarrBlock::SystemUpdates, ]; impl From for Route { fn from(active_radarr_block: ActiveRadarrBlock) -> Route { Route::Radarr(active_radarr_block, None) } } impl From<(ActiveRadarrBlock, Option)> for Route { fn from(value: (ActiveRadarrBlock, Option)) -> Route { Route::Radarr(value.0, value.1) } } impl<'a> App<'a> { pub(super) async fn dispatch_by_radarr_block(&mut self, active_radarr_block: &ActiveRadarrBlock) { match active_radarr_block { ActiveRadarrBlock::Collections => { self .dispatch_network_event(RadarrEvent::GetCollections.into()) .await; } ActiveRadarrBlock::CollectionDetails => { self.is_loading = true; self.populate_movie_collection_table().await; self.is_loading = false; } ActiveRadarrBlock::Downloads => { self .dispatch_network_event(RadarrEvent::GetDownloads.into()) .await; } ActiveRadarrBlock::RootFolders => { self .dispatch_network_event(RadarrEvent::GetRootFolders.into()) .await; } ActiveRadarrBlock::Movies => { self .dispatch_network_event(RadarrEvent::GetMovies.into()) .await; self .dispatch_network_event(RadarrEvent::GetDownloads.into()) .await; } ActiveRadarrBlock::Indexers => { self .dispatch_network_event(RadarrEvent::GetIndexers.into()) .await; } ActiveRadarrBlock::IndexerSettingsPrompt => { self .dispatch_network_event(RadarrEvent::GetIndexerSettings.into()) .await; } ActiveRadarrBlock::System => { self .dispatch_network_event(RadarrEvent::GetTasks.into()) .await; self .dispatch_network_event(RadarrEvent::GetQueuedEvents.into()) .await; self .dispatch_network_event(RadarrEvent::GetLogs.into()) .await; } ActiveRadarrBlock::SystemUpdates => { self .dispatch_network_event(RadarrEvent::GetUpdates.into()) .await; } ActiveRadarrBlock::AddMovieSearchResults => { self .dispatch_network_event(RadarrEvent::SearchNewMovie.into()) .await; } ActiveRadarrBlock::MovieDetails | ActiveRadarrBlock::FileInfo => { self .dispatch_network_event(RadarrEvent::GetMovieDetails.into()) .await; } ActiveRadarrBlock::MovieHistory => { self .dispatch_network_event(RadarrEvent::GetMovieHistory.into()) .await; } ActiveRadarrBlock::Cast | ActiveRadarrBlock::Crew => { if self.data.radarr_data.movie_cast.items.is_empty() || self.data.radarr_data.movie_crew.items.is_empty() { self .dispatch_network_event(RadarrEvent::GetMovieCredits.into()) .await; } } ActiveRadarrBlock::ManualSearch => { if self.data.radarr_data.movie_releases.items.is_empty() { self .dispatch_network_event(RadarrEvent::GetReleases.into()) .await; } } _ => (), } self.check_for_prompt_action().await; self.reset_tick_count(); } async fn check_for_prompt_action(&mut self) { if self.data.radarr_data.prompt_confirm { self.data.radarr_data.prompt_confirm = false; if let Some(radarr_event) = &self.data.radarr_data.prompt_confirm_action { self.dispatch_network_event((*radarr_event).into()).await; self.should_refresh = true; self.data.radarr_data.prompt_confirm_action = None; } } } pub(super) async fn radarr_on_tick( &mut self, active_radarr_block: ActiveRadarrBlock, is_first_render: bool, ) { if is_first_render { self .dispatch_network_event(RadarrEvent::GetQualityProfiles.into()) .await; self .dispatch_network_event(RadarrEvent::GetTags.into()) .await; self .dispatch_network_event(RadarrEvent::GetRootFolders.into()) .await; self .dispatch_network_event(RadarrEvent::GetOverview.into()) .await; self .dispatch_network_event(RadarrEvent::GetStatus.into()) .await; self.dispatch_by_radarr_block(&active_radarr_block).await; } if self.should_refresh { self.dispatch_by_radarr_block(&active_radarr_block).await; } if self.is_routing || self.tick_count % self.tick_until_poll == 0 { self.dispatch_by_radarr_block(&active_radarr_block).await; self.refresh_metadata().await; } } async fn refresh_metadata(&mut self) { self .dispatch_network_event(RadarrEvent::GetQualityProfiles.into()) .await; self .dispatch_network_event(RadarrEvent::GetTags.into()) .await; self .dispatch_network_event(RadarrEvent::GetRootFolders.into()) .await; self .dispatch_network_event(RadarrEvent::GetDownloads.into()) .await; } async fn populate_movie_collection_table(&mut self) { let collection_movies = if !self.data.radarr_data.filtered_collections.items.is_empty() { self .data .radarr_data .filtered_collections .current_selection() .clone() .movies .unwrap_or_default() } else { self .data .radarr_data .collections .current_selection() .clone() .movies .unwrap_or_default() }; self .data .radarr_data .collection_movies .set_items(collection_movies); } }