build: Upgraded to Ratatui v0.30.0 and fixed a new security vulnerability [#13]

This commit is contained in:
2026-01-07 17:15:54 -07:00
parent 243de47cae
commit f0ed71b436
43 changed files with 1532 additions and 828 deletions
+3 -3
View File
@@ -3,7 +3,7 @@ use crate::models::Route;
use crate::models::radarr_models::BlocklistItem;
use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, BLOCKLIST_BLOCKS};
use crate::ui::DrawUi;
use crate::ui::styles::ManagarrStyle;
use crate::ui::styles::{ManagarrStyle, secondary_style};
use crate::ui::utils::{get_width_from_percentage, layout_block_top_border};
use crate::ui::widgets::confirmation_prompt::ConfirmationPrompt;
use crate::ui::widgets::managarr_table::ManagarrTable;
@@ -11,7 +11,7 @@ use crate::ui::widgets::message::Message;
use crate::ui::widgets::popup::{Popup, Size};
use ratatui::Frame;
use ratatui::layout::{Alignment, Constraint, Rect};
use ratatui::style::{Style, Stylize};
use ratatui::style::Stylize;
use ratatui::text::{Line, Text};
use ratatui::widgets::{Cell, Row};
@@ -186,7 +186,7 @@ fn draw_blocklist_item_details_popup(f: &mut Frame<'_>, app: &mut App<'_>) {
let message = Message::new(text)
.title("Details")
.style(Style::new().secondary())
.style(secondary_style())
.alignment(Alignment::Left);
f.render_widget(Popup::new(message).size(Size::NarrowMessage), f.area());
@@ -150,7 +150,7 @@ pub fn draw_collection_details(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect)
.overview
.clone()
.unwrap_or_default()
.default(),
.default_color(),
]),
Line::from(vec![
"Root Folder Path: ".primary().bold(),
@@ -158,20 +158,23 @@ pub fn draw_collection_details(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect)
.root_folder_path
.clone()
.unwrap_or_default()
.default(),
.default_color(),
]),
Line::from(vec![
"Quality Profile: ".primary().bold(),
quality_profile.default(),
quality_profile.default_color(),
]),
Line::from(vec![
"Minimum Availability: ".primary().bold(),
minimum_availability.default(),
minimum_availability.default_color(),
]),
Line::from(vec![
"Monitored: ".primary().bold(),
monitored.default_color(),
]),
Line::from(vec!["Monitored: ".primary().bold(), monitored.default()]),
Line::from(vec![
"Search on Add: ".primary().bold(),
search_on_add.default(),
search_on_add.default_color(),
]),
]);
@@ -225,7 +228,7 @@ fn draw_movie_overview(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) {
.clone()
.overview,
)
.default();
.default_color();
let paragraph = Paragraph::new(overview)
.block(borderless_block())
@@ -11,7 +11,6 @@ use crate::models::servarr_data::radarr::radarr_data::{
};
use crate::render_selectable_input_box;
use crate::ui::radarr_ui::collections::collection_details_ui::CollectionDetailsUi;
use crate::ui::styles::ManagarrStyle;
use crate::ui::utils::{layout_paragraph_borderless, title_block_centered};
use crate::ui::widgets::button::Button;
use crate::ui::widgets::checkbox::Checkbox;
@@ -129,12 +128,12 @@ fn draw_edit_collection_confirmation_prompt(f: &mut Frame<'_>, app: &mut App<'_>
let monitored_checkbox = Checkbox::new("Monitored")
.highlighted(selected_block == ActiveRadarrBlock::EditCollectionToggleMonitored)
.checked(monitored.unwrap_or_default());
let min_availability_drop_down_button = Button::new()
let min_availability_drop_down_button = Button::default()
.title(selected_minimum_availability.to_display_str())
.label("Minimum Availability")
.icon("")
.selected(selected_block == ActiveRadarrBlock::EditCollectionSelectMinimumAvailability);
let quality_profile_drop_down_button = Button::new()
let quality_profile_drop_down_button = Button::default()
.title(selected_quality_profile)
.label("Quality Profile")
.icon("")
@@ -152,10 +151,10 @@ fn draw_edit_collection_confirmation_prompt(f: &mut Frame<'_>, app: &mut App<'_>
let search_on_add_checkbox = Checkbox::new("Search on Add")
.highlighted(selected_block == ActiveRadarrBlock::EditCollectionToggleSearchOnAdd)
.checked(search_on_add.unwrap_or_default());
let save_button = Button::new()
let save_button = Button::default()
.title("Save")
.selected(yes_no_value && highlight_yes_no);
let cancel_button = Button::new()
let cancel_button = Button::default()
.title("Cancel")
.selected(!yes_no_value && highlight_yes_no);
+2 -3
View File
@@ -4,7 +4,6 @@ use crate::app::App;
use crate::models::Route;
use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, EDIT_INDEXER_BLOCKS};
use crate::render_selectable_input_box;
use crate::ui::styles::ManagarrStyle;
use crate::ui::utils::title_block_centered;
use crate::ui::widgets::button::Button;
use crate::ui::widgets::checkbox::Checkbox;
@@ -152,10 +151,10 @@ fn draw_edit_indexer_prompt(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) {
.flex(Flex::Center)
.areas(buttons_area);
let save_button = Button::new()
let save_button = Button::default()
.title("Save")
.selected(yes_no_value && highlight_yes_no);
let cancel_button = Button::new()
let cancel_button = Button::default()
.title("Cancel")
.selected(!yes_no_value && highlight_yes_no);
@@ -9,7 +9,6 @@ use crate::models::servarr_data::radarr::radarr_data::{
ActiveRadarrBlock, INDEXER_SETTINGS_BLOCKS,
};
use crate::render_selectable_input_box;
use crate::ui::styles::ManagarrStyle;
use crate::ui::utils::title_block_centered;
use crate::ui::widgets::button::Button;
use crate::ui::widgets::checkbox::Checkbox;
@@ -154,10 +153,10 @@ fn draw_edit_indexer_settings_prompt(f: &mut Frame<'_>, app: &mut App<'_>, area:
.flex(Flex::Center)
.areas(buttons_area);
let save_button = Button::new()
let save_button = Button::default()
.title("Save")
.selected(yes_no_value && highlight_yes_no);
let cancel_button = Button::new()
let cancel_button = Button::default()
.title("Cancel")
.selected(!yes_no_value && highlight_yes_no);
+2 -2
View File
@@ -1,6 +1,6 @@
use crate::ui::styles::success_style;
use ratatui::Frame;
use ratatui::layout::{Constraint, Rect};
use ratatui::style::{Style, Stylize};
use ratatui::text::Text;
use ratatui::widgets::{Cell, Row};
@@ -73,7 +73,7 @@ impl DrawUi for IndexersUi {
} else {
let message = Message::new("Indexer test succeeded!")
.title("Success")
.style(Style::new().success().bold());
.style(success_style().bold());
Popup::new(message).size(Size::Message)
}
};
+9 -9
View File
@@ -164,14 +164,14 @@ fn draw_add_movie_search(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) {
.block(title_block_centered("Add Movie"));
search_box.show_cursor(f, search_box_area);
f.render_widget(layout_block().default(), results_area);
f.render_widget(layout_block().default_color(), results_area);
f.render_widget(search_box, search_box_area);
}
ActiveRadarrBlock::AddMovieEmptySearchResults => {
let error_message = Message::new("No movies found matching your query!");
let error_message_popup = Popup::new(error_message).size(Size::Message);
f.render_widget(layout_block().default(), results_area);
f.render_widget(layout_block().default_color(), results_area);
f.render_widget(error_message_popup, f.area());
}
ActiveRadarrBlock::AddMovieSearchResults
@@ -187,7 +187,7 @@ fn draw_add_movie_search(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) {
search_results_row_mapping,
)
.loading(is_loading)
.block(layout_block().default())
.block(layout_block().default_color())
.headers([
"",
"Title",
@@ -338,22 +338,22 @@ fn draw_confirmation_prompt(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) {
Layout::horizontal([Constraint::Percentage(50), Constraint::Percentage(50)])
.areas(buttons_area);
let root_folder_drop_down_button = Button::new()
let root_folder_drop_down_button = Button::default()
.title(&selected_root_folder.path)
.label("Root Folder")
.icon("")
.selected(selected_block == ActiveRadarrBlock::AddMovieSelectRootFolder);
let monitor_drop_down_button = Button::new()
let monitor_drop_down_button = Button::default()
.title(selected_monitor.to_display_str())
.label("Monitor")
.icon("")
.selected(selected_block == ActiveRadarrBlock::AddMovieSelectMonitor);
let min_availability_drop_down_button = Button::new()
let min_availability_drop_down_button = Button::default()
.title(selected_minimum_availability.to_display_str())
.label("Minimum Availability")
.icon("")
.selected(selected_block == ActiveRadarrBlock::AddMovieSelectMinimumAvailability);
let quality_profile_drop_down_button = Button::new()
let quality_profile_drop_down_button = Button::default()
.title(selected_quality_profile)
.label("Quality Profile")
.icon("")
@@ -373,10 +373,10 @@ fn draw_confirmation_prompt(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) {
render_selectable_input_box!(tags_input_box, f, tags_area);
}
let add_button = Button::new()
let add_button = Button::default()
.title("Add")
.selected(yes_no_value && highlight_yes_no);
let cancel_button = Button::new()
let cancel_button = Button::default()
.title("Cancel")
.selected(!yes_no_value && highlight_yes_no);
+4 -5
View File
@@ -14,7 +14,6 @@ use crate::models::servarr_data::radarr::radarr_data::{
use crate::render_selectable_input_box;
use crate::ui::radarr_ui::library::movie_details_ui::MovieDetailsUi;
use crate::ui::styles::ManagarrStyle;
use crate::ui::utils::{layout_paragraph_borderless, title_block_centered};
use crate::ui::widgets::button::Button;
use crate::ui::widgets::checkbox::Checkbox;
@@ -125,12 +124,12 @@ fn draw_edit_movie_confirmation_prompt(f: &mut Frame<'_>, app: &mut App<'_>, are
let monitored_checkbox = Checkbox::new("Monitored")
.checked(monitored.unwrap_or_default())
.highlighted(selected_block == ActiveRadarrBlock::EditMovieToggleMonitored);
let min_availability_drop_down_button = Button::new()
let min_availability_drop_down_button = Button::default()
.title(selected_minimum_availability.to_display_str())
.label("Minimum Availability")
.icon("")
.selected(selected_block == ActiveRadarrBlock::EditMovieSelectMinimumAvailability);
let quality_profile_drop_down_button = Button::new()
let quality_profile_drop_down_button = Button::default()
.title(selected_quality_profile)
.label("Quality Profile")
.icon("")
@@ -158,10 +157,10 @@ fn draw_edit_movie_confirmation_prompt(f: &mut Frame<'_>, app: &mut App<'_>, are
render_selectable_input_box!(tags_input_box, f, tags_area);
}
let save_button = Button::new()
let save_button = Button::default()
.title("Save")
.selected(yes_no_value && highlight_yes_no);
let cancel_button = Button::new()
let cancel_button = Button::default()
.title("Cancel")
.selected(!yes_no_value && highlight_yes_no);
+11 -7
View File
@@ -1,3 +1,7 @@
use crate::ui::styles::{
awaiting_import_style, downloaded_style, downloading_style, missing_style,
unmonitored_missing_style, unreleased_style,
};
use std::iter;
use ratatui::Frame;
@@ -529,12 +533,12 @@ fn draw_manual_search_confirm_prompt(f: &mut Frame<'_>, app: &mut App<'_>) {
fn style_from_download_status(download_status: &str, is_monitored: bool, status: String) -> Style {
match download_status {
"Downloaded" => Style::new().downloaded(),
"Awaiting Import" => Style::new().awaiting_import(),
"Downloading" => Style::new().downloading(),
_ if !is_monitored && download_status == "Missing" => Style::new().unmonitored_missing(),
_ if status != "released" && download_status == "Missing" => Style::new().unreleased(),
"Missing" => Style::new().missing(),
_ => Style::new().downloaded(),
"Downloaded" => downloaded_style(),
"Awaiting Import" => awaiting_import_style(),
"Downloading" => downloading_style(),
_ if !is_monitored && download_status == "Missing" => unmonitored_missing_style(),
_ if status != "released" && download_status == "Missing" => unreleased_style(),
"Missing" => missing_style(),
_ => downloaded_style(),
}
}
@@ -11,7 +11,10 @@ mod tests {
use crate::ui::radarr_ui::library::movie_details_ui::{
MovieDetailsUi, style_from_download_status,
};
use crate::ui::styles::ManagarrStyle;
use crate::ui::styles::{
awaiting_import_style, downloaded_style, downloading_style, missing_style,
unmonitored_missing_style,
};
use crate::ui::ui_test_utils::test_utils::{TerminalSize, render_to_string_with_app};
#[test]
@@ -26,13 +29,13 @@ mod tests {
}
#[rstest]
#[case("Downloading", true, "", Style::new().downloading())]
#[case("Downloaded", true, "", Style::new().downloaded())]
#[case("Awaiting Import", true, "", Style::new().awaiting_import())]
#[case("Missing", false, "", Style::new().unmonitored_missing())]
#[case("Missing", false, "", Style::new().unmonitored_missing())]
#[case("Missing", true, "released", Style::new().missing())]
#[case("", true, "", Style::new().downloaded())]
#[case("Downloading", true, "", downloading_style())]
#[case("Downloaded", true, "", downloaded_style())]
#[case("Awaiting Import", true, "", awaiting_import_style())]
#[case("Missing", false, "", unmonitored_missing_style())]
#[case("Missing", false, "", unmonitored_missing_style())]
#[case("Missing", true, "released", missing_style())]
#[case("", true, "", downloaded_style())]
fn test_style_from_download_status(
#[case] download_status: &str,
#[case] is_monitored: bool,
+2 -2
View File
@@ -161,7 +161,7 @@ fn draw_stats_context(f: &mut Frame<'_>, app: &App<'_>, area: Rect) {
let space: f64 = convert_to_gb(*free_space);
let root_folder_space = Paragraph::new(format!("{path}: {space:.2} GB free"))
.block(borderless_block())
.default();
.default_color();
f.render_widget(
root_folder_space,
@@ -249,7 +249,7 @@ fn draw_radarr_logo(f: &mut Frame<'_>, area: Rect) {
let logo_text = Text::from(RADARR_LOGO);
let logo = Paragraph::new(logo_text)
.light_yellow()
.block(layout_block().default())
.block(layout_block().default_color())
.centered();
f.render_widget(logo, area);
}
+2 -2
View File
@@ -1,3 +1,4 @@
use crate::ui::styles::default_style;
use std::ops::Sub;
#[cfg(test)]
@@ -5,7 +6,6 @@ use crate::ui::ui_test_utils::test_utils::Utc;
#[cfg(not(test))]
use chrono::Utc;
use ratatui::layout::Layout;
use ratatui::style::Style;
use ratatui::text::{Span, Text};
use ratatui::widgets::{Cell, Row};
use ratatui::{
@@ -178,7 +178,7 @@ fn draw_logs(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) {
style_log_list_item(ListItem::new(Text::from(Span::raw(log_line))), level)
})
.block(block)
.highlight_style(Style::new().default());
.highlight_style(default_style());
f.render_widget(logs_box, area);
}