Updated Ratatui, created custom deserialization logic for i64s to make life easier, and used string interpolation where possible to reduce the lines needed to write log messages or create formatted text

This commit is contained in:
2023-09-07 17:20:38 -06:00
parent e13d1ece58
commit b16a58deae
43 changed files with 426 additions and 536 deletions
+4 -4
View File
@@ -545,7 +545,7 @@ pub fn draw_checkbox_with_label<B: Backend>(
area,
);
let label_paragraph = Paragraph::new(Text::from(format!("\n{}: ", label)))
let label_paragraph = Paragraph::new(Text::from(format!("\n{label}: ")))
.block(borderless_block())
.alignment(Alignment::Right)
.style(style_primary());
@@ -605,7 +605,7 @@ pub fn draw_drop_down_menu_button<B: Backend>(
area,
);
let description_paragraph = Paragraph::new(Text::from(format!("\n{}: ", description)))
let description_paragraph = Paragraph::new(Text::from(format!("\n{description}: ")))
.block(borderless_block())
.alignment(Alignment::Right)
.style(style_primary());
@@ -676,7 +676,7 @@ fn draw_help_and_get_content_rect<B: Backend>(
let chunks =
vertical_chunks_with_margin(vec![Constraint::Min(0), Constraint::Length(2)], area, 1);
let mut help_test = Text::from(format!(" {}", help_string));
let mut help_test = Text::from(format!(" {help_string}"));
help_test.patch_style(style_help());
let help_paragraph = Paragraph::new(help_test)
.block(layout_block_top_border())
@@ -739,7 +739,7 @@ pub fn draw_text_box_with_label<B: Backend>(
area,
);
let label_paragraph = Paragraph::new(Text::from(format!("\n{}: ", label)))
let label_paragraph = Paragraph::new(Text::from(format!("\n{label}: ")))
.block(borderless_block())
.alignment(Alignment::Right)
.style(style_primary());
@@ -25,7 +25,7 @@ use crate::utils::convert_runtime;
#[path = "collection_details_ui_tests.rs"]
mod collection_details_ui_tests;
pub(super) struct CollectionDetailsUi {}
pub(super) struct CollectionDetailsUi;
impl DrawUi for CollectionDetailsUi {
fn accepts(route: Route) -> bool {
@@ -90,7 +90,7 @@ pub fn draw_collection_details<B: Backend>(
.data
.radarr_data
.quality_profile_map
.get_by_left(&collection_selection.quality_profile_id.as_u64().unwrap())
.get_by_left(&collection_selection.quality_profile_id)
.unwrap()
.to_owned();
let current_selection = if app.data.radarr_data.collection_movies.items.is_empty() {
@@ -198,7 +198,7 @@ pub fn draw_collection_details<B: Backend>(
current_selection == *movie,
app.tick_count % app.ticks_until_scroll == 0,
);
let (hours, minutes) = convert_runtime(movie.runtime.as_u64().unwrap());
let (hours, minutes) = convert_runtime(movie.runtime);
let imdb_rating = movie
.ratings
.imdb
@@ -218,19 +218,19 @@ pub fn draw_collection_details<B: Backend>(
let imdb_rating = if imdb_rating == 0.0 {
String::new()
} else {
format!("{:.1}", imdb_rating)
format!("{imdb_rating:.1}")
};
let rotten_tomatoes_rating = if rotten_tomatoes_rating == 0 {
String::new()
} else {
format!("{}%", rotten_tomatoes_rating)
format!("{rotten_tomatoes_rating}%")
};
Row::new(vec![
Cell::from(in_library),
Cell::from(movie.title.to_string()),
Cell::from(movie.year.as_u64().unwrap().to_string()),
Cell::from(format!("{}h {}m", hours, minutes)),
Cell::from(movie.year.to_string()),
Cell::from(format!("{hours}h {minutes}m")),
Cell::from(imdb_rating),
Cell::from(rotten_tomatoes_rating),
Cell::from(movie.genres.join(", ")),
@@ -24,7 +24,7 @@ use crate::ui::{
#[path = "edit_collection_ui_tests.rs"]
mod edit_collection_ui_tests;
pub(super) struct EditCollectionUi {}
pub(super) struct EditCollectionUi;
impl DrawUi for EditCollectionUi {
fn accepts(route: Route) -> bool {
@@ -126,7 +126,7 @@ fn draw_edit_collection_confirmation_prompt<B: Backend>(
.unwrap_or_default(),
)
};
let title = format!("Edit - {}", collection_title);
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.get_active_block();
let highlight_yes_no = selected_block == &ActiveRadarrBlock::EditCollectionConfirmPrompt;
+2 -2
View File
@@ -23,7 +23,7 @@ mod collection_details_ui;
mod collections_ui_tests;
mod edit_collection_ui;
pub(super) struct CollectionsUi {}
pub(super) struct CollectionsUi;
impl DrawUi for CollectionsUi {
fn accepts(route: Route) -> bool {
@@ -162,7 +162,7 @@ pub(super) fn draw_collections<B: Backend>(f: &mut Frame<'_, B>, app: &mut App<'
Cell::from(collection.root_folder_path.clone().unwrap_or_default()),
Cell::from(
quality_profile_map
.get_by_left(&collection.quality_profile_id.as_u64().unwrap())
.get_by_left(&collection.quality_profile_id)
.unwrap()
.to_owned(),
),
+4 -4
View File
@@ -15,7 +15,7 @@ use crate::utils::convert_to_gb;
#[path = "downloads_ui_tests.rs"]
mod downloads_ui_tests;
pub(super) struct DownloadsUi {}
pub(super) struct DownloadsUi;
impl DrawUi for DownloadsUi {
fn accepts(route: Route) -> bool {
@@ -105,13 +105,13 @@ fn draw_downloads<B: Backend>(f: &mut Frame<'_, B>, app: &mut App<'_>, area: Rec
);
}
let percent = 1f64 - (sizeleft.as_f64().unwrap() / size.as_f64().unwrap());
let file_size: f64 = convert_to_gb(size.as_u64().unwrap());
let percent = 1f64 - (*sizeleft as f64 / *size as f64);
let file_size: f64 = convert_to_gb(*size);
Row::new(vec![
Cell::from(title.to_owned()),
Cell::from(format!("{:.0}%", percent * 100.0)),
Cell::from(format!("{:.2} GB", file_size)),
Cell::from(format!("{file_size:.2} GB")),
Cell::from(
output_path
.as_ref()
@@ -21,7 +21,7 @@ use crate::ui::{
#[path = "indexer_settings_ui_tests.rs"]
mod indexer_settings_ui_tests;
pub(super) struct IndexerSettingsUi {}
pub(super) struct IndexerSettingsUi;
impl DrawUi for IndexerSettingsUi {
fn accepts(route: Route) -> bool {
+2 -2
View File
@@ -18,7 +18,7 @@ mod indexer_settings_ui;
#[path = "indexers_ui_tests.rs"]
mod indexers_ui_tests;
pub(super) struct IndexersUi {}
pub(super) struct IndexersUi;
impl DrawUi for IndexersUi {
fn accepts(route: Route) -> bool {
@@ -116,7 +116,7 @@ fn draw_indexers<B: Backend>(f: &mut Frame<'_, B>, app: &mut App<'_>, area: Rect
Cell::from(rss),
Cell::from(automatic_search),
Cell::from(interactive_search),
Cell::from(priority.as_u64().unwrap().to_string()),
Cell::from(priority.to_string()),
])
.style(style_primary())
},
+7 -7
View File
@@ -29,7 +29,7 @@ use crate::App;
#[path = "add_movie_ui_tests.rs"]
mod add_movie_ui_tests;
pub(super) struct AddMovieUi {}
pub(super) struct AddMovieUi;
impl DrawUi for AddMovieUi {
fn accepts(route: Route) -> bool {
@@ -201,7 +201,7 @@ fn draw_add_movie_search<B: Backend>(f: &mut Frame<'_, B>, app: &mut App<'_>, ar
help: None,
},
|movie| {
let (hours, minutes) = convert_runtime(movie.runtime.as_u64().unwrap());
let (hours, minutes) = convert_runtime(movie.runtime);
let imdb_rating = movie
.ratings
.imdb
@@ -221,12 +221,12 @@ fn draw_add_movie_search<B: Backend>(f: &mut Frame<'_, B>, app: &mut App<'_>, ar
let imdb_rating = if imdb_rating == 0.0 {
String::new()
} else {
format!("{:.1}", imdb_rating)
format!("{imdb_rating:.1}")
};
let rotten_tomatoes_rating = if rotten_tomatoes_rating == 0 {
String::new()
} else {
format!("{}%", rotten_tomatoes_rating)
format!("{rotten_tomatoes_rating}%")
};
let in_library = if app
.data
@@ -250,8 +250,8 @@ fn draw_add_movie_search<B: Backend>(f: &mut Frame<'_, B>, app: &mut App<'_>, ar
Row::new(vec![
Cell::from(in_library),
Cell::from(movie.title.to_string()),
Cell::from(movie.year.as_u64().unwrap().to_string()),
Cell::from(format!("{}h {}m", hours, minutes)),
Cell::from(movie.year.to_string()),
Cell::from(format!("{hours}h {minutes}m")),
Cell::from(imdb_rating),
Cell::from(rotten_tomatoes_rating),
Cell::from(movie.genres.join(", ")),
@@ -368,7 +368,7 @@ fn draw_confirmation_prompt<B: Backend>(
.clone(),
)
};
let title = format!("Add Movie - {}", movie_title);
let title = format!("Add Movie - {movie_title}");
let prompt = movie_overview;
let yes_no_value = app.data.radarr_data.prompt_confirm;
let selected_block = app.data.radarr_data.selected_block.get_active_block();
+1 -1
View File
@@ -12,7 +12,7 @@ use crate::ui::{draw_prompt_box_with_checkboxes, draw_prompt_popup_over, DrawUi}
#[path = "delete_movie_ui_tests.rs"]
mod delete_movie_ui_tests;
pub(super) struct DeleteMovieUi {}
pub(super) struct DeleteMovieUi;
impl DrawUi for DeleteMovieUi {
fn accepts(route: Route) -> bool {
+2 -2
View File
@@ -25,7 +25,7 @@ use crate::ui::{
#[path = "edit_movie_ui_tests.rs"]
mod edit_movie_ui_tests;
pub(super) struct EditMovieUi {}
pub(super) struct EditMovieUi;
impl DrawUi for EditMovieUi {
fn accepts(route: Route) -> bool {
@@ -118,7 +118,7 @@ fn draw_edit_movie_confirmation_prompt<B: Backend>(
.clone(),
)
};
let title = format!("Edit - {}", movie_title);
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.get_active_block();
let highlight_yes_no = selected_block == &ActiveRadarrBlock::EditMovieConfirmPrompt;
+8 -8
View File
@@ -28,7 +28,7 @@ mod movie_details_ui;
#[path = "library_ui_tests.rs"]
mod library_ui_tests;
pub(super) struct LibraryUi {}
pub(super) struct LibraryUi;
impl DrawUi for LibraryUi {
fn accepts(route: Route) -> bool {
@@ -168,11 +168,11 @@ pub(super) fn draw_library<B: Backend>(f: &mut Frame<'_, B>, app: &mut App<'_>,
app.tick_count % app.ticks_until_scroll == 0,
);
let monitored = if movie.monitored { "🏷" } else { "" };
let (hours, minutes) = convert_runtime(movie.runtime.as_u64().unwrap());
let file_size: f64 = convert_to_gb(movie.size_on_disk.as_u64().unwrap());
let certification = movie.certification.clone().unwrap_or_else(|| "".to_owned());
let (hours, minutes) = convert_runtime(movie.runtime);
let file_size: f64 = convert_to_gb(movie.size_on_disk);
let certification = movie.certification.clone().unwrap_or_default();
let quality_profile = quality_profile_map
.get_by_left(&movie.quality_profile_id.as_u64().unwrap())
.get_by_left(&movie.quality_profile_id)
.unwrap()
.to_owned();
let tags = movie
@@ -180,7 +180,7 @@ pub(super) fn draw_library<B: Backend>(f: &mut Frame<'_, B>, app: &mut App<'_>,
.iter()
.map(|tag_id| {
tags_map
.get_by_left(&tag_id.as_u64().unwrap())
.get_by_left(&tag_id.as_i64().unwrap())
.unwrap()
.clone()
})
@@ -191,10 +191,10 @@ pub(super) fn draw_library<B: Backend>(f: &mut Frame<'_, B>, app: &mut App<'_>,
Cell::from(movie.title.to_string()),
Cell::from(movie.year.to_string()),
Cell::from(movie.studio.to_string()),
Cell::from(format!("{}h {}m", hours, minutes)),
Cell::from(format!("{hours}h {minutes}m")),
Cell::from(certification),
Cell::from(movie.original_language.name.to_owned()),
Cell::from(format!("{:.2} GB", file_size)),
Cell::from(format!("{file_size:.2} GB")),
Cell::from(quality_profile),
Cell::from(monitored.to_owned()),
Cell::from(tags),
+6 -6
View File
@@ -28,7 +28,7 @@ use crate::utils::convert_to_gb;
#[path = "movie_details_ui_tests.rs"]
mod movie_details_ui_tests;
pub(super) struct MovieDetailsUi {}
pub(super) struct MovieDetailsUi;
impl DrawUi for MovieDetailsUi {
fn accepts(route: Route) -> bool {
@@ -504,21 +504,21 @@ fn draw_movie_releases<B: Backend>(f: &mut Frame<'_, B>, app: &mut App<'_>, cont
quality,
..
} = release;
let age = format!("{} days", age.as_u64().unwrap_or(0));
let age = format!("{age} days");
title.scroll_left_or_reset(
get_width_from_percentage(content_area, 30),
current_selection == *release
&& current_route != ActiveRadarrBlock::ManualSearchConfirmPrompt.into(),
app.tick_count % app.ticks_until_scroll == 0,
);
let size = convert_to_gb(size.as_u64().unwrap());
let size = convert_to_gb(*size);
let rejected_str = if *rejected { "" } else { "" };
let peers = if seeders.is_none() || leechers.is_none() {
Text::default()
} else {
let seeders = seeders.clone().unwrap().as_u64().unwrap();
let leechers = leechers.clone().unwrap().as_u64().unwrap();
let mut text = Text::from(format!("{} / {}", seeders, leechers));
let mut text = Text::from(format!("{seeders} / {leechers}"));
text.patch_style(determine_peer_style(seeders, leechers));
text
@@ -537,7 +537,7 @@ fn draw_movie_releases<B: Backend>(f: &mut Frame<'_, B>, app: &mut App<'_>, cont
Cell::from(rejected_str),
Cell::from(title.to_string()),
Cell::from(indexer.clone()),
Cell::from(format!("{:.1} GB", size)),
Cell::from(format!("{size:.1} GB")),
Cell::from(peers),
Cell::from(language),
Cell::from(quality),
@@ -589,7 +589,7 @@ fn draw_manual_search_confirm_prompt<B: Backend>(
.clone()
.unwrap_or_default()
.iter()
.map(|item| Line::from(vec![Span::styled(format!("{}", item), style_primary())]))
.map(|item| Line::from(vec![Span::styled(format!("{item}"), style_primary())]))
.collect::<Vec<Line<'_>>>();
lines_vec.append(&mut rejections_spans);
+7 -11
View File
@@ -41,7 +41,7 @@ mod system;
#[path = "radarr_ui_tests.rs"]
mod radarr_ui_tests;
pub(super) struct RadarrUi {}
pub(super) struct RadarrUi;
impl DrawUi for RadarrUi {
fn accepts(route: Route) -> bool {
@@ -119,11 +119,7 @@ fn draw_stats_context<B: Backend>(f: &mut Frame<'_, B>, app: &App<'_>, area: Rec
let seconds = (hour_difference - Duration::minutes(minutes)).num_seconds();
let uptime_paragraph = Paragraph::new(Text::from(format!(
"Uptime: {}d {:0width$}:{:0width$}:{:0width$}",
days,
hours,
minutes,
seconds,
"Uptime: {days}d {hours:0width$}:{minutes:0width$}:{seconds:0width$}",
width = 2
)))
.block(borderless_block())
@@ -144,10 +140,10 @@ fn draw_stats_context<B: Backend>(f: &mut Frame<'_, B>, app: &App<'_>, area: Rec
total_space,
} = &disk_space_vec[i];
let title = format!("Disk {}", i + 1);
let ratio = if total_space.as_u64().unwrap() == 0 {
let ratio = if *total_space == 0 {
0f64
} else {
1f64 - (free_space.as_u64().unwrap() as f64 / total_space.as_u64().unwrap() as f64)
1f64 - (*free_space as f64 / *total_space as f64)
};
let space_gauge = line_gauge_with_label(title.as_str(), ratio);
@@ -161,8 +157,8 @@ fn draw_stats_context<B: Backend>(f: &mut Frame<'_, B>, app: &App<'_>, area: Rec
let RootFolder {
path, free_space, ..
} = &root_folders.items[i];
let space: f64 = convert_to_gb(free_space.as_u64().unwrap());
let root_folder_space = Paragraph::new(format!("{}: {:.2} GB free", path.to_owned(), space))
let space: f64 = convert_to_gb(*free_space);
let root_folder_space = Paragraph::new(format!("{path}: {space:.2} GB free"))
.block(borderless_block())
.style(style_default());
@@ -193,7 +189,7 @@ fn draw_downloads_context<B: Backend>(f: &mut Frame<'_, B>, app: &App<'_>, area:
size,
..
} = &downloads_vec[i];
let percent = 1f64 - (sizeleft.as_f64().unwrap() / size.as_f64().unwrap());
let percent = 1f64 - (*sizeleft as f64 / *size as f64);
let download_gauge = line_gauge_with_title(title, percent);
f.render_widget(download_gauge, chunks[i]);
+6 -6
View File
@@ -22,23 +22,23 @@ pub(super) fn convert_to_minutes_hours_days(time: i64) -> String {
if time == 0 {
"now".to_owned()
} else if time == 1 {
format!("{} minute", time)
format!("{time} minute")
} else {
format!("{} minutes", time)
format!("{time} minutes")
}
} else if time / 60 < 24 {
let hours = time / 60;
if hours == 1 {
format!("{} hour", hours)
format!("{hours} hour")
} else {
format!("{} hours", hours)
format!("{hours} hours")
}
} else {
let days = time / (60 * 24);
if days == 1 {
format!("{} day", days)
format!("{days} day")
} else {
format!("{} days", days)
format!("{days} days")
}
}
}
+3 -3
View File
@@ -18,7 +18,7 @@ use crate::utils::convert_to_gb;
#[path = "root_folders_ui_tests.rs"]
mod root_folders_ui_tests;
pub(super) struct RootFoldersUi {}
pub(super) struct RootFoldersUi;
impl DrawUi for RootFoldersUi {
fn accepts(route: Route) -> bool {
@@ -83,11 +83,11 @@ fn draw_root_folders<B: Backend>(f: &mut Frame<'_, B>, app: &mut App<'_>, area:
..
} = root_folders;
let space: f64 = convert_to_gb(free_space.as_u64().unwrap());
let space: f64 = convert_to_gb(*free_space);
Row::new(vec![
Cell::from(path.to_owned()),
Cell::from(format!("{:.2} GB", space)),
Cell::from(format!("{space:.2} GB")),
Cell::from(
unmapped_folders
.as_ref()
+5 -5
View File
@@ -51,7 +51,7 @@ pub(super) const TASK_TABLE_CONSTRAINTS: [Constraint; 5] = [
Constraint::Percentage(22),
];
pub(super) struct SystemUi {}
pub(super) struct SystemUi;
impl DrawUi for SystemUi {
fn accepts(route: Route) -> bool {
@@ -151,7 +151,7 @@ pub(super) fn draw_queued_events<B: Backend>(f: &mut Frame<'_, B>, app: &mut App
|event| {
let queued = convert_to_minutes_hours_days(Utc::now().sub(event.queued).num_minutes());
let queued_string = if queued != "now" {
format!("{} ago", queued)
format!("{queued} ago")
} else {
queued
};
@@ -160,7 +160,7 @@ pub(super) fn draw_queued_events<B: Backend>(f: &mut Frame<'_, B>, app: &mut App
convert_to_minutes_hours_days(Utc::now().sub(event.started.unwrap()).num_minutes());
if started != "now" {
format!("{} ago", started)
format!("{started} ago")
} else {
started
}
@@ -237,14 +237,14 @@ pub(super) struct TaskProps {
}
pub(super) fn extract_task_props(task: &Task) -> TaskProps {
let interval = convert_to_minutes_hours_days(*task.interval.as_i64().as_ref().unwrap());
let interval = convert_to_minutes_hours_days(task.interval);
let last_duration = &task.last_duration[..8];
let next_execution =
convert_to_minutes_hours_days((task.next_execution - Utc::now()).num_minutes());
let last_execution =
convert_to_minutes_hours_days((Utc::now() - task.last_execution).num_minutes());
let last_execution_string = if last_execution != "now" {
format!("{} ago", last_execution)
format!("{last_execution} ago")
} else {
last_execution
};
+1 -1
View File
@@ -24,7 +24,7 @@ use crate::ui::{
#[path = "system_details_ui_tests.rs"]
mod system_details_ui_tests;
pub(super) struct SystemDetailsUi {}
pub(super) struct SystemDetailsUi;
impl DrawUi for SystemDetailsUi {
fn accepts(route: Route) -> bool {
+2 -2
View File
@@ -206,7 +206,7 @@ pub fn style_block_highlight(is_selected: bool) -> Style {
}
pub fn title_style(title: &str) -> Span<'_> {
Span::styled(format!(" {} ", title), style_bold())
Span::styled(format!(" {title} "), style_bold())
}
pub fn title_block(title: &str) -> Block<'_> {
@@ -265,7 +265,7 @@ pub fn line_gauge_with_label(title: &str, ratio: f64) -> LineGauge<'_> {
.gauge_style(Style::default().fg(COLOR_CYAN))
.line_set(symbols::line::THICK)
.ratio(ratio)
.label(Line::from(format!("{}: {:.0}%", title, ratio * 100.0)))
.label(Line::from(format!("{title}: {:.0}%", ratio * 100.0)))
}
pub fn show_cursor<B: Backend>(f: &mut Frame<'_, B>, area: Rect, offset: usize, string: &str) {