Added some better theming to the UI, enabled clippy to warn on 2018 idioms, and added human_panic hook to report bugs

This commit is contained in:
2023-08-08 10:50:05 -06:00
parent 652dc0f2c4
commit f92042fb21
6 changed files with 141 additions and 57 deletions
+36 -33
View File
@@ -13,12 +13,12 @@ use tui::Frame;
use crate::app::App;
use crate::models::{Route, StatefulList, StatefulTable, TabState};
use crate::ui::utils::{
borderless_block, centered_rect, horizontal_chunks, horizontal_chunks_with_margin, layout_block,
layout_block_top_border, layout_button_paragraph, layout_button_paragraph_borderless,
layout_paragraph_borderless, logo_block, show_cursor, style_block_highlight, style_default,
style_default_bold, style_failure, style_help, style_highlight, style_primary, style_secondary,
style_system_function, title_block, title_block_centered, vertical_chunks,
vertical_chunks_with_margin,
background_block, borderless_block, centered_rect, horizontal_chunks,
horizontal_chunks_with_margin, layout_block, layout_block_top_border, layout_button_paragraph,
layout_button_paragraph_borderless, layout_paragraph_borderless, logo_block, show_cursor,
style_block_highlight, style_default, style_default_bold, style_failure, style_help,
style_highlight, style_primary, style_secondary, style_system_function, title_block,
title_block_centered, vertical_chunks, vertical_chunks_with_margin,
};
mod radarr_ui;
@@ -26,7 +26,8 @@ mod utils;
static HIGHLIGHT_SYMBOL: &str = "=> ";
pub fn ui<B: Backend>(f: &mut Frame<B>, app: &mut App) {
pub fn ui<B: Backend>(f: &mut Frame<'_, B>, app: &mut App) {
f.render_widget(background_block(), f.size());
let main_chunks = if !app.error.text.is_empty() {
let chunks = vertical_chunks_with_margin(
vec![
@@ -115,6 +116,7 @@ pub fn draw_popup<B: Backend>(
) {
let popup_area = centered_rect(percent_x, percent_y, f.size());
f.render_widget(Clear, popup_area);
f.render_widget(background_block(), popup_area);
popup_fn(f, app, popup_area);
}
@@ -188,6 +190,31 @@ fn draw_context_row<B: Backend>(f: &mut Frame<'_, B>, app: &App, area: Rect) {
}
}
pub fn draw_error_popup_over<B: Backend>(
f: &mut Frame<'_, B>,
app: &mut App,
area: Rect,
message: &str,
background_fn: fn(&mut Frame<'_, B>, &mut App, Rect),
) {
background_fn(f, app, area);
draw_error_popup(f, message);
}
pub fn draw_error_popup<B: Backend>(f: &mut Frame<'_, B>, message: &str) {
let prompt_area = centered_rect(25, 8, f.size());
f.render_widget(Clear, prompt_area);
f.render_widget(background_block(), prompt_area);
let error_message = Paragraph::new(Text::from(message))
.block(title_block_centered("Error").style(style_failure()))
.style(style_failure().add_modifier(Modifier::BOLD))
.wrap(Wrap { trim: false })
.alignment(Alignment::Center);
f.render_widget(error_message, prompt_area);
}
fn draw_tabs<'a, B: Backend>(
f: &mut Frame<'_, B>,
area: Rect,
@@ -234,7 +261,7 @@ pub struct TableProps<'a, T> {
fn draw_table<'a, B, T, F>(
f: &mut Frame<'_, B>,
content_area: Rect,
block: Block,
block: Block<'_>,
table_props: TableProps<'a, T>,
row_mapper: F,
is_loading: bool,
@@ -302,30 +329,6 @@ pub fn loading<B: Backend>(f: &mut Frame<'_, B>, block: Block<'_>, area: Rect, i
}
}
pub fn draw_error_popup_over<B: Backend>(
f: &mut Frame<'_, B>,
app: &mut App,
area: Rect,
message: &str,
background_fn: fn(&mut Frame<'_, B>, &mut App, Rect),
) {
background_fn(f, app, area);
draw_error_popup(f, message);
}
pub fn draw_error_popup<B: Backend>(f: &mut Frame<'_, B>, message: &str) {
let prompt_area = centered_rect(25, 8, f.size());
f.render_widget(Clear, prompt_area);
let error_message = Paragraph::new(Text::from(message))
.block(title_block_centered("Error").style(style_failure()))
.style(style_failure().add_modifier(Modifier::BOLD))
.wrap(Wrap { trim: false })
.alignment(Alignment::Center);
f.render_widget(error_message, prompt_area);
}
pub fn draw_prompt_box<B: Backend>(
f: &mut Frame<'_, B>,
prompt_area: Rect,
@@ -341,7 +344,7 @@ pub fn draw_prompt_box_with_content<B: Backend>(
prompt_area: Rect,
title: &str,
prompt: &str,
content: Option<Paragraph>,
content: Option<Paragraph<'_>>,
yes_no_value: &bool,
) {
f.render_widget(title_block_centered(title), prompt_area);
+2 -2
View File
@@ -204,7 +204,7 @@ fn draw_movie_details<B: Backend>(f: &mut Frame<'_, B>, app: &App, content_area:
spans_info_default(title, split[1..].join(":"))
})
.collect::<Vec<Spans>>(),
.collect::<Vec<Spans<'_>>>(),
);
text.patch_style(determine_style_from_download_status(download_status));
@@ -508,7 +508,7 @@ fn draw_manual_search_confirm_prompt<B: Backend>(
.unwrap_or_default()
.iter()
.map(|item| Spans::from(vec![Span::styled(format!("{}", item), style_primary())]))
.collect::<Vec<Spans>>();
.collect::<Vec<Spans<'_>>>();
spans_vec.append(&mut rejections_spans);
let content_paragraph = Paragraph::new(spans_vec)
+48 -18
View File
@@ -5,6 +5,23 @@ use tui::text::{Span, Spans, Text};
use tui::widgets::{Block, BorderType, Borders, LineGauge, Paragraph, Wrap};
use tui::{symbols, Frame};
pub const COLOR_TEAL: Color = Color::Rgb(35, 50, 55);
// pub const COLOR_CYAN: Color = Color::Rgb(0, 230, 230);
pub const COLOR_CYAN: Color = Color::Cyan;
// pub const COLOR_LIGHT_BLUE: Color = Color::Rgb(138, 196, 255);
pub const COLOR_LIGHT_BLUE: Color = Color::LightBlue;
// pub const COLOR_YELLOW: Color = Color::Rgb(249, 229, 113);
pub const COLOR_YELLOW: Color = Color::Yellow;
// pub const COLOR_GREEN: Color = Color::Rgb(72, 213, 150);
pub const COLOR_GREEN: Color = Color::Green;
// pub const COLOR_RED: Color = Color::Rgb(249, 140, 164);
pub const COLOR_RED: Color = Color::Red;
// pub const COLOR_ORANGE: Color = Color::Rgb(255, 170, 66);
// pub const COLOR_WHITE: Color = Color::Rgb(255, 255, 255);
pub const COLOR_WHITE: Color = Color::White;
// pub const COLOR_MAGENTA: Color = Color::Rgb(139, 0, 139);
pub const COLOR_MAGENTA: Color = Color::Magenta;
pub fn horizontal_chunks(constraints: Vec<Constraint>, area: Rect) -> Vec<Rect> {
layout_with_constraints(constraints)
.direction(Direction::Horizontal)
@@ -45,6 +62,10 @@ fn layout_with_constraints(constraints: Vec<Constraint>) -> Layout {
))
}
pub fn background_block<'a>() -> Block<'a> {
Block::default().style(Style::default().bg(COLOR_TEAL).fg(COLOR_WHITE))
}
pub fn layout_block<'a>() -> Block<'a> {
Block::default()
.borders(Borders::ALL)
@@ -67,7 +88,11 @@ pub fn layout_block_bottom_border<'a>() -> Block<'a> {
Block::default().borders(Borders::BOTTOM)
}
pub fn layout_button_paragraph(is_selected: bool, label: &str, alignment: Alignment) -> Paragraph {
pub fn layout_button_paragraph(
is_selected: bool,
label: &str,
alignment: Alignment,
) -> Paragraph<'_> {
Paragraph::new(Text::from(label))
.block(layout_block())
.alignment(alignment)
@@ -78,14 +103,14 @@ pub fn layout_button_paragraph_borderless(
is_selected: bool,
label: &str,
alignment: Alignment,
) -> Paragraph {
) -> Paragraph<'_> {
Paragraph::new(Text::from(label))
.block(borderless_block())
.alignment(alignment)
.style(style_block_highlight(is_selected))
}
pub fn layout_paragraph_borderless(string: &str) -> Paragraph {
pub fn layout_paragraph_borderless(string: &str) -> Paragraph<'_> {
Paragraph::new(Text::from(string))
.block(borderless_block())
.style(style_primary().add_modifier(Modifier::BOLD))
@@ -131,7 +156,7 @@ pub fn style_highlight() -> Style {
}
pub fn style_default() -> Style {
Style::default().fg(Color::White)
Style::default().fg(COLOR_WHITE)
}
pub fn style_default_bold() -> Style {
@@ -139,35 +164,35 @@ pub fn style_default_bold() -> Style {
}
pub fn style_primary() -> Style {
Style::default().fg(Color::Cyan)
Style::default().fg(COLOR_CYAN)
}
pub fn style_secondary() -> Style {
Style::default().fg(Color::Yellow)
Style::default().fg(COLOR_YELLOW)
}
pub fn style_system_function() -> Style {
Style::default().fg(Color::Yellow)
Style::default().fg(COLOR_YELLOW)
}
pub fn style_unmonitored() -> Style {
Style::default().fg(Color::Rgb(91, 87, 87))
Style::default().fg(COLOR_WHITE)
}
pub fn style_success() -> Style {
Style::default().fg(Color::Green)
Style::default().fg(COLOR_GREEN)
}
pub fn style_warning() -> Style {
Style::default().fg(Color::Magenta)
Style::default().fg(COLOR_MAGENTA)
}
pub fn style_failure() -> Style {
Style::default().fg(Color::Red)
Style::default().fg(COLOR_RED)
}
pub fn style_help() -> Style {
Style::default().fg(Color::LightBlue)
Style::default().fg(COLOR_LIGHT_BLUE)
}
pub fn style_block_highlight(is_selected: bool) -> Style {
@@ -223,19 +248,19 @@ pub fn centered_rect(percent_x: u16, percent_y: u16, r: Rect) -> Rect {
.split(popup_layout[1])[1]
}
pub fn line_gauge_with_title(title: &str, ratio: f64) -> LineGauge {
pub fn line_gauge_with_title(title: &str, ratio: f64) -> LineGauge<'_> {
LineGauge::default()
.block(Block::default().title(title))
.gauge_style(Style::default().fg(Color::Cyan))
.gauge_style(Style::default().fg(COLOR_CYAN))
.line_set(symbols::line::THICK)
.ratio(ratio)
.label(Spans::from(format!("{:.0}%", ratio * 100.0)))
}
pub fn line_gauge_with_label(title: &str, ratio: f64) -> LineGauge {
pub fn line_gauge_with_label(title: &str, ratio: f64) -> LineGauge<'_> {
LineGauge::default()
.block(Block::default())
.gauge_style(Style::default().fg(Color::Cyan))
.gauge_style(Style::default().fg(COLOR_CYAN))
.line_set(symbols::line::THICK)
.ratio(ratio)
.label(Spans::from(format!("{}: {:.0}%", title, ratio * 100.0)))
@@ -264,8 +289,8 @@ mod test {
layout_with_constraints, logo_block, spans_info_default, spans_info_primary,
spans_info_with_style, style_block_highlight, style_bold, style_default, style_default_bold,
style_failure, style_help, style_highlight, style_primary, style_secondary, style_success,
style_system_function, style_warning, title_block, title_block_centered, title_style,
vertical_chunks, vertical_chunks_with_margin,
style_system_function, style_unmonitored, style_warning, title_block, title_block_centered,
title_style, vertical_chunks, vertical_chunks_with_margin,
};
#[test]
@@ -498,6 +523,11 @@ mod test {
);
}
#[test]
fn test_style_unmonitored() {
assert_eq!(style_unmonitored(), Style::default().fg(Color::White));
}
#[test]
fn test_style_default() {
assert_eq!(style_default(), Style::default().fg(Color::White));