Refactored the UI module and the handlers module to do a more chain-of-responsibility method to manage the UI's and handlers for different key events. Also, initial work for indexer settings as well

This commit is contained in:
2023-08-08 10:50:07 -06:00
parent 718613d59f
commit cf11527fef
67 changed files with 5255 additions and 2216 deletions
+2 -1
View File
@@ -31,6 +31,7 @@ mod utils;
static HIGHLIGHT_SYMBOL: &str = "=> ";
pub trait DrawUi {
fn accepts(route: Route) -> bool;
fn draw<B: Backend>(f: &mut Frame<'_, B>, app: &mut App<'_>, content_rect: Rect);
fn draw_context_row<B: Backend>(_f: &mut Frame<'_, B>, _app: &App<'_>, _area: Rect) {}
}
@@ -66,7 +67,7 @@ pub fn ui<B: Backend>(f: &mut Frame<'_, B>, app: &mut App<'_>) {
draw_header_row(f, app, main_chunks[0]);
if let Route::Radarr(_, _) = *app.get_current_route() {
if RadarrUi::accepts(*app.get_current_route()) {
RadarrUi::draw_context_row(f, app, main_chunks[1]);
RadarrUi::draw(f, app, main_chunks[2]);
}
@@ -4,11 +4,11 @@ use tui::text::Text;
use tui::widgets::{Cell, Paragraph, Row, Wrap};
use tui::Frame;
use crate::app::radarr::ActiveRadarrBlock;
use crate::app::radarr::{ActiveRadarrBlock, COLLECTION_DETAILS_BLOCKS};
use crate::app::App;
use crate::models::radarr_models::CollectionMovie;
use crate::models::Route;
use crate::ui::radarr_ui::collections_ui::draw_collections;
use crate::ui::radarr_ui::collections::draw_collections;
use crate::ui::utils::{
borderless_block, get_width_from_percentage, layout_block_top_border_with_title,
line_info_primary, style_default, style_help, style_primary, title_block, title_style,
@@ -17,9 +17,21 @@ use crate::ui::utils::{
use crate::ui::{draw_large_popup_over, draw_small_popup_over, draw_table, DrawUi, TableProps};
use crate::utils::convert_runtime;
#[cfg(test)]
#[path = "collection_details_ui_tests.rs"]
mod collection_details_ui_tests;
pub(super) struct CollectionDetailsUi {}
impl DrawUi for CollectionDetailsUi {
fn accepts(route: Route) -> bool {
if let Route::Radarr(active_radarr_block, _) = route {
return COLLECTION_DETAILS_BLOCKS.contains(&active_radarr_block);
}
false
}
fn draw<B: Backend>(f: &mut Frame<'_, B>, app: &mut App<'_>, content_rect: Rect) {
if let Route::Radarr(active_radarr_block, context_option) = *app.get_current_route() {
let draw_collection_details_popup =
@@ -50,7 +62,7 @@ impl DrawUi for CollectionDetailsUi {
}
}
pub(super) fn draw_collection_details<B: Backend>(
pub fn draw_collection_details<B: Backend>(
f: &mut Frame<'_, B>,
app: &mut App<'_>,
content_area: Rect,
@@ -0,0 +1,19 @@
#[cfg(test)]
mod tests {
use strum::IntoEnumIterator;
use crate::app::radarr::{ActiveRadarrBlock, COLLECTION_DETAILS_BLOCKS};
use crate::ui::radarr_ui::collections::collection_details_ui::CollectionDetailsUi;
use crate::ui::DrawUi;
#[test]
fn test_collection_details_ui_accepts() {
ActiveRadarrBlock::iter().for_each(|active_radarr_block| {
if COLLECTION_DETAILS_BLOCKS.contains(&active_radarr_block) {
assert!(CollectionDetailsUi::accepts(active_radarr_block.into()));
} else {
assert!(!CollectionDetailsUi::accepts(active_radarr_block.into()));
}
});
}
}
@@ -0,0 +1,26 @@
#[cfg(test)]
mod tests {
use strum::IntoEnumIterator;
use crate::app::radarr::{
ActiveRadarrBlock, COLLECTIONS_BLOCKS, COLLECTION_DETAILS_BLOCKS, EDIT_COLLECTION_BLOCKS,
};
use crate::ui::radarr_ui::collections::CollectionsUi;
use crate::ui::DrawUi;
#[test]
fn test_collections_ui_accepts() {
let mut collections_ui_blocks = Vec::new();
collections_ui_blocks.extend(COLLECTIONS_BLOCKS);
collections_ui_blocks.extend(COLLECTION_DETAILS_BLOCKS);
collections_ui_blocks.extend(EDIT_COLLECTION_BLOCKS);
ActiveRadarrBlock::iter().for_each(|active_radarr_block| {
if collections_ui_blocks.contains(&active_radarr_block) {
assert!(CollectionsUi::accepts(active_radarr_block.into()));
} else {
assert!(!CollectionsUi::accepts(active_radarr_block.into()));
}
});
}
}
@@ -2,11 +2,11 @@ use tui::backend::Backend;
use tui::layout::{Constraint, Rect};
use tui::Frame;
use crate::app::radarr::{ActiveRadarrBlock, COLLECTION_DETAILS_BLOCKS};
use crate::app::radarr::{ActiveRadarrBlock, COLLECTION_DETAILS_BLOCKS, EDIT_COLLECTION_BLOCKS};
use crate::app::App;
use crate::models::Route;
use crate::ui::radarr_ui::collection_details_ui::CollectionDetailsUi;
use crate::ui::radarr_ui::collections_ui::draw_collections;
use crate::ui::radarr_ui::collections::collection_details_ui::CollectionDetailsUi;
use crate::ui::radarr_ui::collections::draw_collections;
use crate::ui::radarr_ui::{
draw_select_minimum_availability_popup, draw_select_quality_profile_popup,
};
@@ -19,9 +19,21 @@ use crate::ui::{
draw_text_box_with_label, DrawUi,
};
#[cfg(test)]
#[path = "edit_collection_ui_tests.rs"]
mod edit_collection_ui_tests;
pub(super) struct EditCollectionUi {}
impl DrawUi for EditCollectionUi {
fn accepts(route: Route) -> bool {
if let Route::Radarr(active_radarr_block, _) = route {
return EDIT_COLLECTION_BLOCKS.contains(&active_radarr_block);
}
false
}
fn draw<B: Backend>(f: &mut Frame<'_, B>, app: &mut App<'_>, content_rect: Rect) {
if let Route::Radarr(active_radarr_block, context_option) = *app.get_current_route() {
let draw_edit_collection_prompt =
@@ -0,0 +1,19 @@
#[cfg(test)]
mod tests {
use strum::IntoEnumIterator;
use crate::app::radarr::{ActiveRadarrBlock, EDIT_COLLECTION_BLOCKS};
use crate::ui::radarr_ui::collections::edit_collection_ui::EditCollectionUi;
use crate::ui::DrawUi;
#[test]
fn test_edit_collection_ui_accepts() {
ActiveRadarrBlock::iter().for_each(|active_radarr_block| {
if EDIT_COLLECTION_BLOCKS.contains(&active_radarr_block) {
assert!(EditCollectionUi::accepts(active_radarr_block.into()));
} else {
assert!(!EditCollectionUi::accepts(active_radarr_block.into()));
}
})
}
}
@@ -3,50 +3,80 @@ use tui::layout::{Constraint, Rect};
use tui::widgets::{Cell, Row};
use tui::Frame;
use crate::app::radarr::ActiveRadarrBlock;
pub(super) use collection_details_ui::draw_collection_details;
use crate::app::radarr::{ActiveRadarrBlock, COLLECTIONS_BLOCKS};
use crate::app::App;
use crate::models::radarr_models::Collection;
use crate::models::Route;
use crate::ui::radarr_ui::collections::collection_details_ui::CollectionDetailsUi;
use crate::ui::radarr_ui::collections::edit_collection_ui::EditCollectionUi;
use crate::ui::radarr_ui::{draw_filter_box, draw_search_box};
use crate::ui::utils::{get_width_from_percentage, layout_block_top_border, style_primary};
use crate::ui::{
draw_popup_over, draw_prompt_box, draw_prompt_popup_over, draw_table, DrawUi, TableProps,
};
mod collection_details_ui;
#[cfg(test)]
#[path = "collections_ui_tests.rs"]
mod collections_ui_tests;
mod edit_collection_ui;
pub(super) struct CollectionsUi {}
impl DrawUi for CollectionsUi {
fn accepts(route: Route) -> bool {
if let Route::Radarr(active_radarr_block, _) = route {
return CollectionDetailsUi::accepts(route)
|| EditCollectionUi::accepts(route)
|| COLLECTIONS_BLOCKS.contains(&active_radarr_block);
}
false
}
fn draw<B: Backend>(f: &mut Frame<'_, B>, app: &mut App<'_>, content_rect: Rect) {
if let Route::Radarr(active_radarr_block, _) = *app.get_current_route() {
match active_radarr_block {
ActiveRadarrBlock::Collections => draw_collections(f, app, content_rect),
ActiveRadarrBlock::SearchCollection => draw_popup_over(
f,
app,
content_rect,
draw_collections,
draw_search_box,
30,
11,
),
ActiveRadarrBlock::FilterCollections => draw_popup_over(
f,
app,
content_rect,
draw_collections,
draw_filter_box,
30,
11,
),
ActiveRadarrBlock::UpdateAllCollectionsPrompt => draw_prompt_popup_over(
f,
app,
content_rect,
draw_collections,
draw_update_all_collections_prompt,
),
_ => (),
let route = *app.get_current_route();
let mut collections_ui_matcher = |active_radarr_block| match active_radarr_block {
ActiveRadarrBlock::Collections => draw_collections(f, app, content_rect),
ActiveRadarrBlock::SearchCollection => draw_popup_over(
f,
app,
content_rect,
draw_collections,
draw_search_box,
30,
11,
),
ActiveRadarrBlock::FilterCollections => draw_popup_over(
f,
app,
content_rect,
draw_collections,
draw_filter_box,
30,
11,
),
ActiveRadarrBlock::UpdateAllCollectionsPrompt => draw_prompt_popup_over(
f,
app,
content_rect,
draw_collections,
draw_update_all_collections_prompt,
),
_ => (),
};
match route {
_ if CollectionDetailsUi::accepts(route) => CollectionDetailsUi::draw(f, app, content_rect),
_ if EditCollectionUi::accepts(route) => EditCollectionUi::draw(f, app, content_rect),
Route::Radarr(active_radarr_block, _)
if COLLECTIONS_BLOCKS.contains(&active_radarr_block) =>
{
collections_ui_matcher(active_radarr_block)
}
_ => (),
}
}
}
@@ -0,0 +1,19 @@
#[cfg(test)]
mod tests {
use strum::IntoEnumIterator;
use crate::app::radarr::{ActiveRadarrBlock, DOWNLOADS_BLOCKS};
use crate::ui::radarr_ui::downloads::DownloadsUi;
use crate::ui::DrawUi;
#[test]
fn test_downloads_ui_accepts() {
ActiveRadarrBlock::iter().for_each(|active_radarr_block| {
if DOWNLOADS_BLOCKS.contains(&active_radarr_block) {
assert!(DownloadsUi::accepts(active_radarr_block.into()));
} else {
assert!(!DownloadsUi::accepts(active_radarr_block.into()));
}
});
}
}
@@ -3,7 +3,7 @@ use tui::layout::{Constraint, Rect};
use tui::widgets::{Cell, Row};
use tui::Frame;
use crate::app::radarr::ActiveRadarrBlock;
use crate::app::radarr::{ActiveRadarrBlock, DOWNLOADS_BLOCKS};
use crate::app::App;
use crate::models::radarr_models::DownloadRecord;
use crate::models::{HorizontallyScrollableText, Route};
@@ -11,9 +11,21 @@ use crate::ui::utils::{get_width_from_percentage, layout_block_top_border, style
use crate::ui::{draw_prompt_box, draw_prompt_popup_over, draw_table, DrawUi, TableProps};
use crate::utils::convert_to_gb;
#[cfg(test)]
#[path = "downloads_ui_tests.rs"]
mod downloads_ui_tests;
pub(super) struct DownloadsUi {}
impl DrawUi for DownloadsUi {
fn accepts(route: Route) -> bool {
if let Route::Radarr(active_radarr_block, _) = route {
return DOWNLOADS_BLOCKS.contains(&active_radarr_block);
}
false
}
fn draw<B: Backend>(f: &mut Frame<'_, B>, app: &mut App<'_>, content_rect: Rect) {
if let Route::Radarr(active_radarr_block, _) = *app.get_current_route() {
match active_radarr_block {
@@ -0,0 +1,26 @@
use tui::backend::Backend;
use tui::layout::Rect;
use tui::Frame;
use crate::app::radarr::INDEXER_SETTINGS_BLOCKS;
use crate::app::App;
use crate::models::Route;
use crate::ui::DrawUi;
#[cfg(test)]
#[path = "indexer_settings_ui_tests.rs"]
mod indexer_settings_ui_tests;
pub(super) struct IndexerSettingsUi {}
impl DrawUi for IndexerSettingsUi {
fn accepts(route: Route) -> bool {
if let Route::Radarr(active_radarr_block, _) = route {
return INDEXER_SETTINGS_BLOCKS.contains(&active_radarr_block);
}
false
}
fn draw<B: Backend>(_f: &mut Frame<'_, B>, _app: &mut App<'_>, _content_rect: Rect) {}
}
@@ -0,0 +1,19 @@
#[cfg(test)]
mod tests {
use strum::IntoEnumIterator;
use crate::app::radarr::{ActiveRadarrBlock, INDEXER_SETTINGS_BLOCKS};
use crate::ui::radarr_ui::indexers::indexer_settings_ui::IndexerSettingsUi;
use crate::ui::DrawUi;
#[test]
fn test_indexer_settings_ui_accepts() {
ActiveRadarrBlock::iter().for_each(|active_radarr_block| {
if INDEXER_SETTINGS_BLOCKS.contains(&active_radarr_block) {
assert!(IndexerSettingsUi::accepts(active_radarr_block.into()));
} else {
assert!(!IndexerSettingsUi::accepts(active_radarr_block.into()));
}
});
}
}
@@ -0,0 +1,23 @@
#[cfg(test)]
mod tests {
use strum::IntoEnumIterator;
use crate::app::radarr::{ActiveRadarrBlock, INDEXERS_BLOCKS, INDEXER_SETTINGS_BLOCKS};
use crate::ui::radarr_ui::indexers::IndexersUi;
use crate::ui::DrawUi;
#[test]
fn test_indexers_ui_accepts() {
let mut indexers_blocks = Vec::new();
indexers_blocks.extend(INDEXERS_BLOCKS);
indexers_blocks.extend(INDEXER_SETTINGS_BLOCKS);
ActiveRadarrBlock::iter().for_each(|active_radarr_block| {
if indexers_blocks.contains(&active_radarr_block) {
assert!(IndexersUi::accepts(active_radarr_block.into()));
} else {
assert!(!IndexersUi::accepts(active_radarr_block.into()));
}
});
}
}
@@ -4,29 +4,51 @@ use tui::text::Text;
use tui::widgets::{Cell, Row};
use tui::Frame;
use crate::app::radarr::ActiveRadarrBlock;
use crate::app::radarr::{ActiveRadarrBlock, INDEXERS_BLOCKS};
use crate::app::App;
use crate::models::radarr_models::Indexer;
use crate::models::Route;
use crate::ui::radarr_ui::indexers::indexer_settings_ui::IndexerSettingsUi;
use crate::ui::utils::{layout_block_top_border, style_failure, style_primary, style_success};
use crate::ui::{draw_prompt_box, draw_prompt_popup_over, draw_table, DrawUi, TableProps};
mod indexer_settings_ui;
#[cfg(test)]
#[path = "indexers_ui_tests.rs"]
mod indexers_ui_tests;
pub(super) struct IndexersUi {}
impl DrawUi for IndexersUi {
fn accepts(route: Route) -> bool {
if let Route::Radarr(active_radarr_block, _) = route {
return IndexerSettingsUi::accepts(route) || INDEXERS_BLOCKS.contains(&active_radarr_block);
}
false
}
fn draw<B: Backend>(f: &mut Frame<'_, B>, app: &mut App<'_>, content_rect: Rect) {
if let Route::Radarr(active_radarr_block, _) = *app.get_current_route() {
match active_radarr_block {
ActiveRadarrBlock::Indexers => draw_indexers(f, app, content_rect),
ActiveRadarrBlock::DeleteIndexerPrompt => draw_prompt_popup_over(
f,
app,
content_rect,
draw_indexers,
draw_delete_indexer_prompt,
),
_ => (),
let route = *app.get_current_route();
let mut indexers_matchers = |active_radarr_block| match active_radarr_block {
ActiveRadarrBlock::Indexers => draw_indexers(f, app, content_rect),
ActiveRadarrBlock::DeleteIndexerPrompt => draw_prompt_popup_over(
f,
app,
content_rect,
draw_indexers,
draw_delete_indexer_prompt,
),
_ => (),
};
match route {
_ if IndexerSettingsUi::accepts(route) => IndexerSettingsUi::draw(f, app, content_rect),
Route::Radarr(active_radarr_block, _) if INDEXERS_BLOCKS.contains(&active_radarr_block) => {
indexers_matchers(active_radarr_block)
}
_ => (),
}
}
}
@@ -7,9 +7,8 @@ use tui::Frame;
use crate::app::radarr::{ActiveRadarrBlock, ADD_MOVIE_BLOCKS};
use crate::models::radarr_models::AddMovieSearchResult;
use crate::models::Route;
use crate::ui::radarr_ui::collection_details_ui::draw_collection_details;
use crate::ui::radarr_ui::collections_ui::draw_collections;
use crate::ui::radarr_ui::library_ui::draw_library;
use crate::ui::radarr_ui::collections::{draw_collection_details, draw_collections};
use crate::ui::radarr_ui::library::draw_library;
use crate::ui::radarr_ui::{
draw_select_minimum_availability_popup, draw_select_quality_profile_popup,
draw_select_root_folder_popup,
@@ -27,9 +26,21 @@ use crate::ui::{
use crate::utils::convert_runtime;
use crate::App;
pub(super) struct AddMoviesUi {}
#[cfg(test)]
#[path = "add_movie_ui_tests.rs"]
mod add_movie_ui_tests;
pub(super) struct AddMovieUi {}
impl DrawUi for AddMovieUi {
fn accepts(route: Route) -> bool {
if let Route::Radarr(active_radarr_block, _) = route {
return ADD_MOVIE_BLOCKS.contains(&active_radarr_block);
}
false
}
impl DrawUi for AddMoviesUi {
fn draw<B: Backend>(f: &mut Frame<'_, B>, app: &mut App<'_>, content_rect: Rect) {
if let Route::Radarr(active_radarr_block, context_option) = *app.get_current_route() {
let draw_add_movie_search_popup =
@@ -0,0 +1,19 @@
#[cfg(test)]
mod tests {
use strum::IntoEnumIterator;
use crate::app::radarr::{ActiveRadarrBlock, ADD_MOVIE_BLOCKS};
use crate::ui::radarr_ui::library::add_movie_ui::AddMovieUi;
use crate::ui::DrawUi;
#[test]
fn test_add_movie_ui_accepts() {
ActiveRadarrBlock::iter().for_each(|active_radarr_block| {
if ADD_MOVIE_BLOCKS.contains(&active_radarr_block) {
assert!(AddMovieUi::accepts(active_radarr_block.into()));
} else {
assert!(!AddMovieUi::accepts(active_radarr_block.into()));
}
});
}
}
@@ -2,15 +2,27 @@ use tui::backend::Backend;
use tui::layout::Rect;
use tui::Frame;
use crate::app::radarr::ActiveRadarrBlock;
use crate::app::radarr::{ActiveRadarrBlock, DELETE_MOVIE_BLOCKS};
use crate::app::App;
use crate::models::Route;
use crate::ui::radarr_ui::library_ui::draw_library;
use crate::ui::radarr_ui::library::draw_library;
use crate::ui::{draw_prompt_box_with_checkboxes, draw_prompt_popup_over, DrawUi};
#[cfg(test)]
#[path = "delete_movie_ui_tests.rs"]
mod delete_movie_ui_tests;
pub(super) struct DeleteMovieUi {}
impl DrawUi for DeleteMovieUi {
fn accepts(route: Route) -> bool {
if let Route::Radarr(active_radarr_block, _) = route {
return DELETE_MOVIE_BLOCKS.contains(&active_radarr_block);
}
false
}
fn draw<B: Backend>(f: &mut Frame<'_, B>, app: &mut App<'_>, content_rect: Rect) {
if matches!(
*app.get_current_route(),
@@ -0,0 +1,19 @@
#[cfg(test)]
mod tests {
use strum::IntoEnumIterator;
use crate::app::radarr::{ActiveRadarrBlock, DELETE_MOVIE_BLOCKS};
use crate::ui::radarr_ui::library::delete_movie_ui::DeleteMovieUi;
use crate::ui::DrawUi;
#[test]
fn test_delete_movie_ui_accepts() {
ActiveRadarrBlock::iter().for_each(|active_radarr_block| {
if DELETE_MOVIE_BLOCKS.contains(&active_radarr_block) {
assert!(DeleteMovieUi::accepts(active_radarr_block.into()));
} else {
assert!(!DeleteMovieUi::accepts(active_radarr_block.into()));
}
});
}
}
@@ -2,11 +2,11 @@ use tui::backend::Backend;
use tui::layout::{Constraint, Rect};
use tui::Frame;
use crate::app::radarr::{ActiveRadarrBlock, MOVIE_DETAILS_BLOCKS};
use crate::app::radarr::{ActiveRadarrBlock, EDIT_MOVIE_BLOCKS, MOVIE_DETAILS_BLOCKS};
use crate::app::App;
use crate::models::Route;
use crate::ui::radarr_ui::library_ui::draw_library;
use crate::ui::radarr_ui::movie_details_ui::MovieDetailsUi;
use crate::ui::radarr_ui::library::draw_library;
use crate::ui::radarr_ui::library::movie_details_ui::MovieDetailsUi;
use crate::ui::radarr_ui::{
draw_select_minimum_availability_popup, draw_select_quality_profile_popup,
};
@@ -19,9 +19,21 @@ use crate::ui::{
draw_text_box_with_label, DrawUi,
};
#[cfg(test)]
#[path = "edit_movie_ui_tests.rs"]
mod edit_movie_ui_tests;
pub(super) struct EditMovieUi {}
impl DrawUi for EditMovieUi {
fn accepts(route: Route) -> bool {
if let Route::Radarr(active_radarr_block, _) = route {
return EDIT_MOVIE_BLOCKS.contains(&active_radarr_block);
}
false
}
fn draw<B: Backend>(f: &mut Frame<'_, B>, app: &mut App<'_>, content_rect: Rect) {
if let Route::Radarr(active_radarr_block, context_option) = *app.get_current_route() {
let draw_edit_movie_prompt =
@@ -0,0 +1,19 @@
#[cfg(test)]
mod tests {
use strum::IntoEnumIterator;
use crate::app::radarr::{ActiveRadarrBlock, EDIT_MOVIE_BLOCKS};
use crate::ui::radarr_ui::library::edit_movie_ui::EditMovieUi;
use crate::ui::DrawUi;
#[test]
fn test_edit_movie_ui_accepts() {
ActiveRadarrBlock::iter().for_each(|active_radarr_block| {
if EDIT_MOVIE_BLOCKS.contains(&active_radarr_block) {
assert!(EditMovieUi::accepts(active_radarr_block.into()));
} else {
assert!(!EditMovieUi::accepts(active_radarr_block.into()));
}
});
}
}
@@ -0,0 +1,29 @@
#[cfg(test)]
mod tests {
use strum::IntoEnumIterator;
use crate::app::radarr::{
ActiveRadarrBlock, ADD_MOVIE_BLOCKS, DELETE_MOVIE_BLOCKS, EDIT_MOVIE_BLOCKS, LIBRARY_BLOCKS,
MOVIE_DETAILS_BLOCKS,
};
use crate::ui::radarr_ui::library::LibraryUi;
use crate::ui::DrawUi;
#[test]
fn test_library_ui_accepts() {
let mut library_ui_blocks = Vec::new();
library_ui_blocks.extend(LIBRARY_BLOCKS);
library_ui_blocks.extend(MOVIE_DETAILS_BLOCKS);
library_ui_blocks.extend(ADD_MOVIE_BLOCKS);
library_ui_blocks.extend(EDIT_MOVIE_BLOCKS);
library_ui_blocks.extend(DELETE_MOVIE_BLOCKS);
ActiveRadarrBlock::iter().for_each(|active_radarr_block| {
if library_ui_blocks.contains(&active_radarr_block) {
assert!(LibraryUi::accepts(active_radarr_block.into()));
} else {
assert!(!LibraryUi::accepts(active_radarr_block.into()));
}
});
}
}
@@ -3,10 +3,14 @@ use tui::layout::{Constraint, Rect};
use tui::widgets::{Cell, Row};
use tui::Frame;
use crate::app::radarr::ActiveRadarrBlock;
use crate::app::radarr::{ActiveRadarrBlock, LIBRARY_BLOCKS};
use crate::app::App;
use crate::models::radarr_models::Movie;
use crate::models::Route;
use crate::ui::radarr_ui::library::add_movie_ui::AddMovieUi;
use crate::ui::radarr_ui::library::delete_movie_ui::DeleteMovieUi;
use crate::ui::radarr_ui::library::edit_movie_ui::EditMovieUi;
use crate::ui::radarr_ui::library::movie_details_ui::MovieDetailsUi;
use crate::ui::radarr_ui::{determine_row_style, draw_filter_box, draw_search_box};
use crate::ui::utils::{get_width_from_percentage, layout_block_top_border};
use crate::ui::{
@@ -14,28 +18,60 @@ use crate::ui::{
};
use crate::utils::{convert_runtime, convert_to_gb};
mod add_movie_ui;
mod delete_movie_ui;
mod edit_movie_ui;
mod movie_details_ui;
#[cfg(test)]
#[path = "library_ui_tests.rs"]
mod library_ui_tests;
pub(super) struct LibraryUi {}
impl DrawUi for LibraryUi {
fn accepts(route: Route) -> bool {
if let Route::Radarr(active_radarr_block, _) = route {
return MovieDetailsUi::accepts(route)
|| AddMovieUi::accepts(route)
|| EditMovieUi::accepts(route)
|| DeleteMovieUi::accepts(route)
|| LIBRARY_BLOCKS.contains(&active_radarr_block);
}
false
}
fn draw<B: Backend>(f: &mut Frame<'_, B>, app: &mut App<'_>, content_rect: Rect) {
if let Route::Radarr(active_radarr_block, _) = app.get_current_route() {
match active_radarr_block {
ActiveRadarrBlock::Movies => draw_library(f, app, content_rect),
ActiveRadarrBlock::SearchMovie => {
draw_popup_over(f, app, content_rect, draw_library, draw_search_box, 30, 11)
}
ActiveRadarrBlock::FilterMovies => {
draw_popup_over(f, app, content_rect, draw_library, draw_filter_box, 30, 11)
}
ActiveRadarrBlock::UpdateAllMoviesPrompt => draw_prompt_popup_over(
f,
app,
content_rect,
draw_library,
draw_update_all_movies_prompt,
),
_ => (),
let route = *app.get_current_route();
let mut library_ui_matchers = |active_radarr_block: ActiveRadarrBlock| match active_radarr_block
{
ActiveRadarrBlock::Movies => draw_library(f, app, content_rect),
ActiveRadarrBlock::SearchMovie => {
draw_popup_over(f, app, content_rect, draw_library, draw_search_box, 30, 11)
}
ActiveRadarrBlock::FilterMovies => {
draw_popup_over(f, app, content_rect, draw_library, draw_filter_box, 30, 11)
}
ActiveRadarrBlock::UpdateAllMoviesPrompt => draw_prompt_popup_over(
f,
app,
content_rect,
draw_library,
draw_update_all_movies_prompt,
),
_ => (),
};
match route {
_ if MovieDetailsUi::accepts(route) => MovieDetailsUi::draw(f, app, content_rect),
_ if AddMovieUi::accepts(route) => AddMovieUi::draw(f, app, content_rect),
_ if EditMovieUi::accepts(route) => EditMovieUi::draw(f, app, content_rect),
_ if DeleteMovieUi::accepts(route) => DeleteMovieUi::draw(f, app, content_rect),
Route::Radarr(active_radarr_block, _) if LIBRARY_BLOCKS.contains(&active_radarr_block) => {
library_ui_matchers(active_radarr_block)
}
_ => (),
}
}
}
@@ -7,11 +7,11 @@ use tui::text::{Line, Span, Text};
use tui::widgets::{Cell, ListItem, Paragraph, Row, Wrap};
use tui::Frame;
use crate::app::radarr::ActiveRadarrBlock;
use crate::app::radarr::{ActiveRadarrBlock, MOVIE_DETAILS_BLOCKS};
use crate::app::App;
use crate::models::radarr_models::{Credit, MovieHistoryItem, Release, ReleaseField};
use crate::models::Route;
use crate::ui::radarr_ui::library_ui::draw_library;
use crate::ui::radarr_ui::library::draw_library;
use crate::ui::utils::{
borderless_block, get_width_from_percentage, layout_block_bottom_border, layout_block_top_border,
line_info_default, style_awaiting_import, style_bold, style_default, style_failure,
@@ -24,9 +24,21 @@ use crate::ui::{
};
use crate::utils::convert_to_gb;
#[cfg(test)]
#[path = "movie_details_ui_tests.rs"]
mod movie_details_ui_tests;
pub(super) struct MovieDetailsUi {}
impl DrawUi for MovieDetailsUi {
fn accepts(route: Route) -> bool {
if let Route::Radarr(active_radarr_block, _) = route {
return MOVIE_DETAILS_BLOCKS.contains(&active_radarr_block);
}
false
}
fn draw<B: Backend>(f: &mut Frame<'_, B>, app: &mut App<'_>, content_rect: Rect) {
if let Route::Radarr(active_radarr_block, context_option) = *app.get_current_route() {
let draw_movie_info_popup = |f: &mut Frame<'_, B>, app: &mut App<'_>, popup_area: Rect| {
@@ -0,0 +1,19 @@
#[cfg(test)]
mod tests {
use strum::IntoEnumIterator;
use crate::app::radarr::{ActiveRadarrBlock, MOVIE_DETAILS_BLOCKS};
use crate::ui::radarr_ui::library::movie_details_ui::MovieDetailsUi;
use crate::ui::DrawUi;
#[test]
fn test_movie_details_ui_accepts() {
ActiveRadarrBlock::iter().for_each(|active_radarr_block| {
if MOVIE_DETAILS_BLOCKS.contains(&active_radarr_block) {
assert!(MovieDetailsUi::accepts(active_radarr_block.into()));
} else {
assert!(!MovieDetailsUi::accepts(active_radarr_block.into()));
}
});
}
}
+30 -72
View File
@@ -9,11 +9,7 @@ use tui::widgets::ListItem;
use tui::widgets::Paragraph;
use tui::Frame;
use crate::app::radarr::{
ActiveRadarrBlock, RadarrData, ADD_MOVIE_BLOCKS, COLLECTION_DETAILS_BLOCKS, DELETE_MOVIE_BLOCKS,
EDIT_COLLECTION_BLOCKS, EDIT_MOVIE_BLOCKS, FILTER_BLOCKS, INDEXER_BLOCKS, MOVIE_DETAILS_BLOCKS,
SEARCH_BLOCKS, SYSTEM_DETAILS_BLOCKS,
};
use crate::app::radarr::{ActiveRadarrBlock, RadarrData, FILTER_BLOCKS, SEARCH_BLOCKS};
use crate::app::App;
use crate::logos::RADARR_LOGO;
use crate::models::radarr_models::{DiskSpace, DownloadRecord, Movie, RootFolder};
@@ -21,15 +17,12 @@ use crate::models::Route;
use crate::ui::draw_selectable_list;
use crate::ui::draw_tabs;
use crate::ui::loading;
use crate::ui::radarr_ui::indexers_ui::IndexersUi;
use crate::ui::radarr_ui::system_details_ui::SystemDetailsUi;
use crate::ui::radarr_ui::system_ui::SystemUi;
use crate::ui::radarr_ui::{
add_movie_ui::AddMoviesUi, collection_details_ui::CollectionDetailsUi,
collections_ui::CollectionsUi, delete_movie_ui::DeleteMovieUi, downloads_ui::DownloadsUi,
edit_collection_ui::EditCollectionUi, edit_movie_ui::EditMovieUi, library_ui::LibraryUi,
movie_details_ui::MovieDetailsUi, root_folders_ui::RootFoldersUi,
};
use crate::ui::radarr_ui::collections::CollectionsUi;
use crate::ui::radarr_ui::downloads::DownloadsUi;
use crate::ui::radarr_ui::indexers::IndexersUi;
use crate::ui::radarr_ui::library::LibraryUi;
use crate::ui::radarr_ui::root_folders::RootFoldersUi;
use crate::ui::radarr_ui::system::SystemUi;
use crate::ui::utils::{
borderless_block, horizontal_chunks, layout_block, line_gauge_with_label, line_gauge_with_title,
show_cursor, style_awaiting_import, style_bold, style_default, style_failure, style_success,
@@ -38,72 +31,37 @@ use crate::ui::utils::{
use crate::ui::DrawUi;
use crate::utils::convert_to_gb;
mod add_movie_ui;
mod collection_details_ui;
mod collections_ui;
mod delete_movie_ui;
mod downloads_ui;
mod edit_collection_ui;
mod edit_movie_ui;
mod indexers_ui;
mod library_ui;
mod movie_details_ui;
mod collections;
mod downloads;
mod indexers;
mod library;
mod radarr_ui_utils;
mod root_folders_ui;
mod system_details_ui;
mod system_ui;
mod root_folders;
mod system;
#[cfg(test)]
#[path = "radarr_ui_tests.rs"]
mod radarr_ui_tests;
pub(super) struct RadarrUi {}
impl DrawUi for RadarrUi {
fn accepts(route: Route) -> bool {
matches!(route, Route::Radarr(_, _))
}
fn draw<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 route = *app.get_current_route();
if let Route::Radarr(active_radarr_block, _) = *app.get_current_route() {
match active_radarr_block {
ActiveRadarrBlock::Movies
| ActiveRadarrBlock::SearchMovie
| ActiveRadarrBlock::FilterMovies
| ActiveRadarrBlock::UpdateAllMoviesPrompt => LibraryUi::draw(f, app, content_rect),
ActiveRadarrBlock::Collections
| ActiveRadarrBlock::SearchCollection
| ActiveRadarrBlock::FilterCollections
| ActiveRadarrBlock::UpdateAllCollectionsPrompt => {
CollectionsUi::draw(f, app, content_rect)
}
ActiveRadarrBlock::Downloads
| ActiveRadarrBlock::DeleteDownloadPrompt
| ActiveRadarrBlock::UpdateDownloadsPrompt => DownloadsUi::draw(f, app, content_rect),
_ if INDEXER_BLOCKS.contains(&active_radarr_block) => {
IndexersUi::draw(f, app, content_rect)
}
ActiveRadarrBlock::RootFolders
| ActiveRadarrBlock::AddRootFolderPrompt
| ActiveRadarrBlock::DeleteRootFolderPrompt => RootFoldersUi::draw(f, app, content_rect),
ActiveRadarrBlock::System => SystemUi::draw(f, app, content_rect),
_ if SYSTEM_DETAILS_BLOCKS.contains(&active_radarr_block) => {
SystemDetailsUi::draw(f, app, content_rect)
}
_ if MOVIE_DETAILS_BLOCKS.contains(&active_radarr_block) => {
MovieDetailsUi::draw(f, app, content_rect)
}
_ if ADD_MOVIE_BLOCKS.contains(&active_radarr_block) => {
AddMoviesUi::draw(f, app, content_rect)
}
_ if COLLECTION_DETAILS_BLOCKS.contains(&active_radarr_block) => {
CollectionDetailsUi::draw(f, app, content_rect)
}
_ if EDIT_MOVIE_BLOCKS.contains(&active_radarr_block) => {
EditMovieUi::draw(f, app, content_rect)
}
_ if EDIT_COLLECTION_BLOCKS.contains(&active_radarr_block) => {
EditCollectionUi::draw(f, app, content_rect)
}
_ if DELETE_MOVIE_BLOCKS.contains(&active_radarr_block) => {
DeleteMovieUi::draw(f, app, content_rect)
}
_ => (),
}
match route {
_ if LibraryUi::accepts(route) => LibraryUi::draw(f, app, content_rect),
_ if CollectionsUi::accepts(route) => CollectionsUi::draw(f, app, content_rect),
_ if DownloadsUi::accepts(route) => DownloadsUi::draw(f, app, content_rect),
_ if IndexersUi::accepts(route) => IndexersUi::draw(f, app, content_rect),
_ if RootFoldersUi::accepts(route) => RootFoldersUi::draw(f, app, content_rect),
_ if SystemUi::accepts(route) => SystemUi::draw(f, app, content_rect),
_ => (),
}
}
+15
View File
@@ -0,0 +1,15 @@
#[cfg(test)]
mod tests {
use strum::IntoEnumIterator;
use crate::app::radarr::ActiveRadarrBlock;
use crate::ui::radarr_ui::RadarrUi;
use crate::ui::DrawUi;
#[test]
fn test_radarr_ui_accepts() {
ActiveRadarrBlock::iter().for_each(|active_radarr_block| {
assert!(RadarrUi::accepts(active_radarr_block.into()));
});
}
}
@@ -3,7 +3,7 @@ use tui::layout::{Alignment, Constraint, Rect};
use tui::widgets::{Cell, Paragraph, Row};
use tui::Frame;
use crate::app::radarr::ActiveRadarrBlock;
use crate::app::radarr::{ActiveRadarrBlock, ROOT_FOLDERS_BLOCKS};
use crate::app::App;
use crate::models::radarr_models::RootFolder;
use crate::models::Route;
@@ -16,9 +16,21 @@ use crate::ui::{
};
use crate::utils::convert_to_gb;
#[cfg(test)]
#[path = "root_folders_ui_tests.rs"]
mod root_folders_ui_tests;
pub(super) struct RootFoldersUi {}
impl DrawUi for RootFoldersUi {
fn accepts(route: Route) -> bool {
if let Route::Radarr(active_radarr_block, _) = route {
return ROOT_FOLDERS_BLOCKS.contains(&active_radarr_block);
}
false
}
fn draw<B: Backend>(f: &mut Frame<'_, B>, app: &mut App<'_>, content_rect: Rect) {
if let Route::Radarr(active_radarr_block, _) = *app.get_current_route() {
match active_radarr_block {
@@ -0,0 +1,19 @@
#[cfg(test)]
mod tests {
use strum::IntoEnumIterator;
use crate::app::radarr::{ActiveRadarrBlock, ROOT_FOLDERS_BLOCKS};
use crate::ui::radarr_ui::root_folders::RootFoldersUi;
use crate::ui::DrawUi;
#[test]
fn test_root_folders_ui_accepts() {
ActiveRadarrBlock::iter().for_each(|active_radarr_block| {
if ROOT_FOLDERS_BLOCKS.contains(&active_radarr_block) {
assert!(RootFoldersUi::accepts(active_radarr_block.into()));
} else {
assert!(!RootFoldersUi::accepts(active_radarr_block.into()));
}
});
}
}
@@ -1,7 +1,21 @@
use std::ops::Sub;
use chrono::Utc;
use tui::layout::Alignment;
use tui::text::{Span, Text};
use tui::widgets::{Cell, Paragraph, Row};
use tui::{
backend::Backend,
layout::{Constraint, Rect},
widgets::ListItem,
Frame,
};
use crate::models::radarr_models::Task;
use crate::ui::radarr_ui::radarr_ui_utils::{
convert_to_minutes_hours_days, determine_log_style_by_level,
};
use crate::ui::radarr_ui::system::system_details_ui::SystemDetailsUi;
use crate::ui::utils::{layout_block_top_border, style_help, style_primary};
use crate::ui::{draw_table, ListProps, TableProps};
use crate::{
@@ -13,17 +27,12 @@ use crate::{
DrawUi,
},
};
use chrono::Utc;
use std::ops::Sub;
use tui::layout::Alignment;
use tui::text::{Span, Text};
use tui::widgets::{Cell, Paragraph, Row};
use tui::{
backend::Backend,
layout::{Constraint, Rect},
widgets::ListItem,
Frame,
};
mod system_details_ui;
#[cfg(test)]
#[path = "system_ui_tests.rs"]
mod system_ui_tests;
pub(super) const TASK_TABLE_HEADERS: [&str; 5] = [
"Name",
@@ -44,12 +53,23 @@ pub(super) const TASK_TABLE_CONSTRAINTS: [Constraint; 5] = [
pub(super) struct SystemUi {}
impl DrawUi for SystemUi {
fn accepts(route: Route) -> bool {
if let Route::Radarr(active_radarr_block, _) = route {
return SystemDetailsUi::accepts(route) || active_radarr_block == ActiveRadarrBlock::System;
}
false
}
fn draw<B: Backend>(f: &mut Frame<'_, B>, app: &mut App<'_>, content_rect: Rect) {
if matches!(
*app.get_current_route(),
Route::Radarr(ActiveRadarrBlock::System, _)
) {
draw_system_ui_layout(f, app, content_rect)
let route = *app.get_current_route();
match route {
_ if SystemDetailsUi::accepts(route) => SystemDetailsUi::draw(f, app, content_rect),
_ if matches!(route, Route::Radarr(ActiveRadarrBlock::System, _)) => {
draw_system_ui_layout(f, app, content_rect)
}
_ => (),
}
}
}
@@ -4,11 +4,11 @@ use tui::text::{Span, Text};
use tui::widgets::{Cell, ListItem, Paragraph, Row};
use tui::Frame;
use crate::app::radarr::ActiveRadarrBlock;
use crate::app::radarr::{ActiveRadarrBlock, SYSTEM_DETAILS_BLOCKS};
use crate::app::App;
use crate::models::Route;
use crate::ui::radarr_ui::radarr_ui_utils::determine_log_style_by_level;
use crate::ui::radarr_ui::system_ui::{
use crate::ui::radarr_ui::system::{
draw_queued_events, draw_system_ui_layout, extract_task_props, TASK_TABLE_CONSTRAINTS,
TASK_TABLE_HEADERS,
};
@@ -18,9 +18,21 @@ use crate::ui::{
draw_prompt_box, draw_prompt_popup_over, draw_table, loading, DrawUi, ListProps, TableProps,
};
#[cfg(test)]
#[path = "system_details_ui_tests.rs"]
mod system_details_ui_tests;
pub(super) struct SystemDetailsUi {}
impl DrawUi for SystemDetailsUi {
fn accepts(route: Route) -> bool {
if let Route::Radarr(active_radarr_block, _) = route {
return SYSTEM_DETAILS_BLOCKS.contains(&active_radarr_block);
}
false
}
fn draw<B: Backend>(f: &mut Frame<'_, B>, app: &mut App<'_>, content_rect: Rect) {
if let Route::Radarr(active_radarr_block, _) = *app.get_current_route() {
match active_radarr_block {
@@ -0,0 +1,19 @@
#[cfg(test)]
mod tests {
use strum::IntoEnumIterator;
use crate::app::radarr::{ActiveRadarrBlock, SYSTEM_DETAILS_BLOCKS};
use crate::ui::radarr_ui::system::system_details_ui::SystemDetailsUi;
use crate::ui::DrawUi;
#[test]
fn test_system_details_ui_accepts() {
ActiveRadarrBlock::iter().for_each(|active_radarr_block| {
if SYSTEM_DETAILS_BLOCKS.contains(&active_radarr_block) {
assert!(SystemDetailsUi::accepts(active_radarr_block.into()));
} else {
assert!(!SystemDetailsUi::accepts(active_radarr_block.into()));
}
});
}
}
@@ -0,0 +1,23 @@
#[cfg(test)]
mod tests {
use strum::IntoEnumIterator;
use crate::app::radarr::{ActiveRadarrBlock, SYSTEM_DETAILS_BLOCKS};
use crate::ui::radarr_ui::system::SystemUi;
use crate::ui::DrawUi;
#[test]
fn test_system_ui_accepts() {
let mut system_ui_blocks = Vec::new();
system_ui_blocks.push(ActiveRadarrBlock::System);
system_ui_blocks.extend(SYSTEM_DETAILS_BLOCKS);
ActiveRadarrBlock::iter().for_each(|active_radarr_block| {
if system_ui_blocks.contains(&active_radarr_block) {
assert!(SystemUi::accepts(active_radarr_block.into()));
} else {
assert!(!SystemUi::accepts(active_radarr_block.into()));
}
});
}
}