Implemented the ability to edit collections and fixed a refresh bug so screens will automatically refresh when users edit movies or collections

This commit is contained in:
2023-08-08 10:50:06 -06:00
parent 173e81fc17
commit bf5ecbd5a6
18 changed files with 2040 additions and 273 deletions
+4 -4
View File
@@ -272,7 +272,7 @@ fn draw_select_monitor_popup<B: Backend>(f: &mut Frame<'_, B>, app: &mut App, po
draw_drop_down_list(
f,
popup_area,
&mut app.data.radarr_data.movie_monitor_list,
&mut app.data.radarr_data.monitor_list,
|monitor| ListItem::new(monitor.to_display_str().to_owned()),
);
}
@@ -319,16 +319,16 @@ fn draw_confirmation_prompt<B: Backend>(f: &mut Frame<'_, B>, app: &mut App, pro
let selected_block = &app.data.radarr_data.selected_block;
let highlight_yes_no = *selected_block == ActiveRadarrBlock::AddMovieConfirmPrompt;
let selected_monitor = app.data.radarr_data.movie_monitor_list.current_selection();
let selected_monitor = app.data.radarr_data.monitor_list.current_selection();
let selected_minimum_availability = app
.data
.radarr_data
.movie_minimum_availability_list
.minimum_availability_list
.current_selection();
let selected_quality_profile = app
.data
.radarr_data
.movie_quality_profile_list
.quality_profile_list
.current_selection();
f.render_widget(title_block_centered(title), prompt_area);
+21 -8
View File
@@ -21,8 +21,8 @@ pub(super) fn draw_collection_details_popup<B: Backend>(
app: &mut App,
content_area: Rect,
) {
if let Route::Radarr(active_radarr_block, _) = app.get_current_route() {
match active_radarr_block {
if let Route::Radarr(active_radarr_block, context_option) = app.get_current_route() {
match context_option.as_ref().unwrap_or(active_radarr_block) {
ActiveRadarrBlock::ViewMovieOverview => {
draw_small_popup_over(
f,
@@ -45,8 +45,8 @@ pub(super) fn draw_collection_details<B: Backend>(
) {
let chunks = vertical_chunks_with_margin(
vec![
Constraint::Percentage(20),
Constraint::Percentage(75),
Constraint::Percentage(25),
Constraint::Percentage(70),
Constraint::Percentage(5),
],
content_area,
@@ -81,6 +81,17 @@ pub(super) fn draw_collection_details<B: Backend>(
let mut help_text =
Text::from("<↑↓> scroll table | <enter> show overview/add movie | <esc> close");
help_text.patch_style(style_help());
let monitored = if collection_selection.monitored {
"Yes"
} else {
"No"
};
let search_on_add = if collection_selection.search_on_add {
"Yes"
} else {
"No"
};
let minimum_availability = collection_selection.minimum_availability.to_display_str();
let collection_description = Text::from(vec![
spans_info_primary(
@@ -94,11 +105,13 @@ pub(super) fn draw_collection_details<B: Backend>(
.clone()
.unwrap_or_default(),
),
spans_info_primary(
"Search on Add: ".to_owned(),
collection_selection.search_on_add.to_string(),
),
spans_info_primary("Quality Profile: ".to_owned(), quality_profile),
spans_info_primary(
"Minimum Availability: ".to_owned(),
minimum_availability.to_owned(),
),
spans_info_primary("Monitored: ".to_owned(), monitored.to_owned()),
spans_info_primary("Search on Add: ".to_owned(), search_on_add.to_owned()),
]);
let description_paragraph = Paragraph::new(collection_description)
+194
View File
@@ -0,0 +1,194 @@
use tui::backend::Backend;
use tui::layout::{Constraint, Rect};
use tui::Frame;
use crate::app::radarr::ActiveRadarrBlock;
use crate::app::App;
use crate::models::Route;
use crate::ui::radarr_ui::{
draw_select_minimum_availability_popup, draw_select_quality_profile_popup,
};
use crate::ui::utils::{
horizontal_chunks, layout_paragraph_borderless, title_block_centered, vertical_chunks_with_margin,
};
use crate::ui::{
draw_button, draw_checkbox_with_label, draw_drop_down_menu_button, draw_drop_down_popup,
draw_text_box_with_label,
};
pub(super) fn draw_edit_collection_prompt<B: Backend>(
f: &mut Frame<'_, B>,
app: &mut App,
prompt_area: Rect,
) {
if let Route::Radarr(active_radarr_block, _) = *app.get_current_route() {
match active_radarr_block {
ActiveRadarrBlock::EditCollectionSelectMinimumAvailability => {
draw_drop_down_popup(
f,
app,
prompt_area,
draw_edit_collection_confirmation_prompt,
draw_select_minimum_availability_popup,
);
}
ActiveRadarrBlock::EditCollectionSelectQualityProfile => {
draw_drop_down_popup(
f,
app,
prompt_area,
draw_edit_collection_confirmation_prompt,
draw_select_quality_profile_popup,
);
}
ActiveRadarrBlock::EditCollectionPrompt
| ActiveRadarrBlock::EditCollectionToggleMonitored
| ActiveRadarrBlock::EditCollectionRootFolderPathInput
| ActiveRadarrBlock::EditCollectionToggleSearchOnAdd => {
draw_edit_collection_confirmation_prompt(f, app, prompt_area)
}
_ => (),
}
}
}
fn draw_edit_collection_confirmation_prompt<B: Backend>(
f: &mut Frame<'_, B>,
app: &mut App,
prompt_area: Rect,
) {
let (collection_title, collection_overview) =
if app.data.radarr_data.filtered_collections.items.is_empty() {
(
app
.data
.radarr_data
.collections
.current_selection()
.title
.to_string(),
app
.data
.radarr_data
.collections
.current_selection()
.overview
.clone()
.unwrap_or_default(),
)
} else {
(
app
.data
.radarr_data
.filtered_collections
.current_selection()
.title
.to_string(),
app
.data
.radarr_data
.filtered_collections
.current_selection()
.overview
.clone()
.unwrap_or_default(),
)
};
let title = format!("Edit - {}", collection_title);
let yes_no_value = &app.data.radarr_data.prompt_confirm;
let selected_block = &app.data.radarr_data.selected_block;
let highlight_yes_no = *selected_block == ActiveRadarrBlock::EditCollectionConfirmPrompt;
let selected_minimum_availability = app
.data
.radarr_data
.minimum_availability_list
.current_selection();
let selected_quality_profile = app
.data
.radarr_data
.quality_profile_list
.current_selection();
f.render_widget(title_block_centered(&title), prompt_area);
let chunks = vertical_chunks_with_margin(
vec![
Constraint::Percentage(35),
Constraint::Length(3),
Constraint::Length(3),
Constraint::Length(3),
Constraint::Length(3),
Constraint::Length(3),
Constraint::Min(0),
Constraint::Length(3),
],
prompt_area,
1,
);
let prompt_paragraph = layout_paragraph_borderless(&collection_overview);
f.render_widget(prompt_paragraph, chunks[0]);
let horizontal_chunks = horizontal_chunks(
vec![Constraint::Percentage(50), Constraint::Percentage(50)],
chunks[7],
);
draw_checkbox_with_label(
f,
chunks[1],
"Monitored",
app.data.radarr_data.edit_monitored.unwrap_or_default(),
*selected_block == ActiveRadarrBlock::EditCollectionToggleMonitored,
);
draw_drop_down_menu_button(
f,
chunks[2],
"Minimum Availability",
selected_minimum_availability.to_display_str(),
*selected_block == ActiveRadarrBlock::EditCollectionSelectMinimumAvailability,
);
draw_drop_down_menu_button(
f,
chunks[3],
"Quality Profile",
selected_quality_profile,
*selected_block == ActiveRadarrBlock::EditCollectionSelectQualityProfile,
);
if let Route::Radarr(active_radarr_block, _) = *app.get_current_route() {
draw_text_box_with_label(
f,
chunks[4],
"Root Folder",
&app.data.radarr_data.edit_path.text,
*app.data.radarr_data.edit_path.offset.borrow(),
*selected_block == ActiveRadarrBlock::EditCollectionRootFolderPathInput,
active_radarr_block == ActiveRadarrBlock::EditCollectionRootFolderPathInput,
);
}
draw_checkbox_with_label(
f,
chunks[5],
"Search on Add",
app.data.radarr_data.edit_search_on_add.unwrap_or_default(),
*selected_block == ActiveRadarrBlock::EditCollectionToggleSearchOnAdd,
);
draw_button(
f,
horizontal_chunks[0],
"Save",
*yes_no_value && highlight_yes_no,
);
draw_button(
f,
horizontal_chunks[1],
"Cancel",
!*yes_no_value && highlight_yes_no,
);
}
+43 -22
View File
@@ -28,7 +28,7 @@ pub(super) fn draw_edit_movie_prompt<B: Backend>(
f,
app,
prompt_area,
draw_edit_confirmation_prompt,
draw_edit_movie_confirmation_prompt,
draw_select_minimum_availability_popup,
);
}
@@ -37,40 +37,61 @@ pub(super) fn draw_edit_movie_prompt<B: Backend>(
f,
app,
prompt_area,
draw_edit_confirmation_prompt,
draw_edit_movie_confirmation_prompt,
draw_select_quality_profile_popup,
);
}
ActiveRadarrBlock::EditMoviePrompt
| ActiveRadarrBlock::EditMovieToggleMonitored
| ActiveRadarrBlock::EditMoviePathInput
| ActiveRadarrBlock::EditMovieTagsInput => draw_edit_confirmation_prompt(f, app, prompt_area),
| ActiveRadarrBlock::EditMovieTagsInput => {
draw_edit_movie_confirmation_prompt(f, app, prompt_area)
}
_ => (),
}
}
}
fn draw_edit_confirmation_prompt<B: Backend>(
fn draw_edit_movie_confirmation_prompt<B: Backend>(
f: &mut Frame<'_, B>,
app: &mut App,
prompt_area: Rect,
) {
let (movie_title, movie_overview) = (
app
.data
.radarr_data
.movies
.current_selection()
.title
.to_string(),
app
.data
.radarr_data
.movies
.current_selection()
.overview
.clone(),
);
let (movie_title, movie_overview) = if app.data.radarr_data.filtered_movies.items.is_empty() {
(
app
.data
.radarr_data
.movies
.current_selection()
.title
.to_string(),
app
.data
.radarr_data
.movies
.current_selection()
.overview
.clone(),
)
} else {
(
app
.data
.radarr_data
.filtered_movies
.current_selection()
.title
.to_string(),
app
.data
.radarr_data
.filtered_movies
.current_selection()
.overview
.clone(),
)
};
let title = format!("Edit - {}", movie_title);
let yes_no_value = &app.data.radarr_data.prompt_confirm;
let selected_block = &app.data.radarr_data.selected_block;
@@ -79,12 +100,12 @@ fn draw_edit_confirmation_prompt<B: Backend>(
let selected_minimum_availability = app
.data
.radarr_data
.movie_minimum_availability_list
.minimum_availability_list
.current_selection();
let selected_quality_profile = app
.data
.radarr_data
.movie_quality_profile_list
.quality_profile_list
.current_selection();
f.render_widget(title_block_centered(&title), prompt_area);
+49 -8
View File
@@ -10,8 +10,8 @@ use tui::widgets::{Cell, ListItem, Paragraph, Row};
use tui::Frame;
use crate::app::radarr::{
ActiveRadarrBlock, RadarrData, ADD_MOVIE_BLOCKS, COLLECTION_DETAILS_BLOCKS, EDIT_MOVIE_BLOCKS,
FILTER_BLOCKS, MOVIE_DETAILS_BLOCKS, SEARCH_BLOCKS,
ActiveRadarrBlock, RadarrData, ADD_MOVIE_BLOCKS, COLLECTION_DETAILS_BLOCKS,
EDIT_COLLECTION_BLOCKS, EDIT_MOVIE_BLOCKS, FILTER_BLOCKS, MOVIE_DETAILS_BLOCKS, SEARCH_BLOCKS,
};
use crate::app::App;
use crate::logos::RADARR_LOGO;
@@ -19,6 +19,7 @@ use crate::models::radarr_models::{Collection, DiskSpace, DownloadRecord, Movie}
use crate::models::{HorizontallyScrollableText, Route};
use crate::ui::radarr_ui::add_movie_ui::draw_add_movie_search_popup;
use crate::ui::radarr_ui::collection_details_ui::draw_collection_details_popup;
use crate::ui::radarr_ui::edit_collection_ui::draw_edit_collection_prompt;
use crate::ui::radarr_ui::edit_movie_ui::draw_edit_movie_prompt;
use crate::ui::radarr_ui::movie_details_ui::draw_movie_info_popup;
use crate::ui::utils::{
@@ -35,6 +36,7 @@ use crate::utils::{convert_runtime, convert_to_gb};
mod add_movie_ui;
mod collection_details_ui;
mod edit_collection_ui;
mod edit_movie_ui;
mod movie_details_ui;
@@ -113,6 +115,30 @@ pub(super) fn draw_radarr_ui<B: Backend>(f: &mut Frame<'_, B>, app: &mut App, ar
}
}
}
_ if EDIT_COLLECTION_BLOCKS.contains(&active_radarr_block) => {
if let Some(context) = context_option {
match context {
ActiveRadarrBlock::Collections => draw_medium_popup_over(
f,
app,
content_rect,
draw_collections,
draw_edit_collection_prompt,
),
_ if COLLECTION_DETAILS_BLOCKS.contains(&context) => {
draw_large_popup_over(
f,
app,
content_rect,
draw_collections,
draw_collection_details_popup,
);
draw_popup(f, app, draw_edit_collection_prompt, 60, 60);
}
_ => (),
}
}
}
ActiveRadarrBlock::DeleteMoviePrompt => {
draw_prompt_popup_over(f, app, content_rect, draw_library, draw_delete_movie_prompt)
}
@@ -547,12 +573,20 @@ fn draw_collections<B: Backend>(f: &mut Frame<'_, B>, app: &mut App, area: Rect)
content,
table_headers: vec![
"Collection",
"Search on Add?",
"Number of Movies",
"Root Folder Path",
"Quality Profile",
"Search on Add",
"Monitored",
],
constraints: vec![
Constraint::Percentage(25),
Constraint::Percentage(15),
Constraint::Percentage(15),
Constraint::Percentage(15),
Constraint::Percentage(15),
Constraint::Percentage(15),
],
constraints: iter::repeat(Constraint::Ratio(1, 5)).take(5).collect(),
help: app
.data
.radarr_data
@@ -562,14 +596,19 @@ fn draw_collections<B: Backend>(f: &mut Frame<'_, B>, app: &mut App, area: Rect)
|collection| {
let number_of_movies = collection.movies.clone().unwrap_or_default().len();
collection.title.scroll_left_or_reset(
get_width_from_percentage(area, 100 / 5),
get_width_from_percentage(area, 25),
*collection == current_selection,
app.tick_count % app.ticks_until_scroll == 0,
);
let monitored = if collection.monitored { "🏷" } else { "" };
let search_on_add = if collection.search_on_add {
"Yes"
} else {
"No"
};
Row::new(vec![
Cell::from(collection.title.to_string()),
Cell::from(collection.search_on_add.to_string()),
Cell::from(number_of_movies.to_string()),
Cell::from(collection.root_folder_path.clone().unwrap_or_default()),
Cell::from(
@@ -578,6 +617,8 @@ fn draw_collections<B: Backend>(f: &mut Frame<'_, B>, app: &mut App, area: Rect)
.unwrap()
.to_owned(),
),
Cell::from(search_on_add),
Cell::from(monitored),
])
.style(style_primary())
},
@@ -704,7 +745,7 @@ fn draw_select_minimum_availability_popup<B: Backend>(
draw_drop_down_list(
f,
popup_area,
&mut app.data.radarr_data.movie_minimum_availability_list,
&mut app.data.radarr_data.minimum_availability_list,
|minimum_availability| ListItem::new(minimum_availability.to_display_str().to_owned()),
);
}
@@ -717,7 +758,7 @@ fn draw_select_quality_profile_popup<B: Backend>(
draw_drop_down_list(
f,
popup_area,
&mut app.data.radarr_data.movie_quality_profile_list,
&mut app.data.radarr_data.quality_profile_list,
|quality_profile| ListItem::new(quality_profile.clone()),
);
}
+1 -6
View File
@@ -26,12 +26,7 @@ pub(super) fn draw_movie_info_popup<B: Backend>(f: &mut Frame<'_, B>, app: &mut
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() {
let match_block = if let Some(context) = context_option {
context
} else {
active_radarr_block
};
match match_block {
match context_option.as_ref().unwrap_or(active_radarr_block) {
ActiveRadarrBlock::AutomaticallySearchMoviePrompt => draw_prompt_popup_over(
f,
app,