From 97ce258a8d347e304119525519bf06ec9c29429d Mon Sep 17 00:00:00 2001 From: Alex Clarke Date: Tue, 2 Sep 2025 15:49:36 -0600 Subject: [PATCH] fix: Fixed UI bugs introduced as part of the hotkey refactor --- .../collections/collection_details_ui.rs | 3 +- .../indexers/test_all_indexers_ui.rs | 3 +- src/ui/radarr_ui/system/system_details_ui.rs | 17 +++++--- .../indexers/test_all_indexers_ui.rs | 3 +- src/ui/sonarr_ui/system/system_details_ui.rs | 17 +++++--- src/ui/widgets/managarr_table.rs | 40 +++++-------------- src/ui/widgets/managarr_table_tests.rs | 12 +----- src/ui/widgets/popup.rs | 15 ++++++- src/ui/widgets/popup_tests.rs | 15 +++++++ 9 files changed, 63 insertions(+), 62 deletions(-) diff --git a/src/ui/radarr_ui/collections/collection_details_ui.rs b/src/ui/radarr_ui/collections/collection_details_ui.rs index 34118f4..7b9337e 100644 --- a/src/ui/radarr_ui/collections/collection_details_ui.rs +++ b/src/ui/radarr_ui/collections/collection_details_ui.rs @@ -1,4 +1,4 @@ -use ratatui::layout::{Alignment, Constraint, Flex, Layout, Rect}; +use ratatui::layout::{Constraint, Flex, Layout, Rect}; use ratatui::style::Stylize; use ratatui::text::{Line, Text}; use ratatui::widgets::{Cell, Paragraph, Row, Wrap}; @@ -184,7 +184,6 @@ pub fn draw_collection_details(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) ) .block(layout_block_top_border_with_title(title_style("Movies"))) .loading(app.is_loading) - .footer_alignment(Alignment::Center) .headers([ "✔", "Title", diff --git a/src/ui/radarr_ui/indexers/test_all_indexers_ui.rs b/src/ui/radarr_ui/indexers/test_all_indexers_ui.rs index e2b70aa..b24375c 100644 --- a/src/ui/radarr_ui/indexers/test_all_indexers_ui.rs +++ b/src/ui/radarr_ui/indexers/test_all_indexers_ui.rs @@ -7,7 +7,7 @@ use crate::ui::utils::{get_width_from_percentage, title_block}; use crate::ui::widgets::managarr_table::ManagarrTable; use crate::ui::widgets::popup::Size; use crate::ui::{draw_popup, DrawUi}; -use ratatui::layout::{Alignment, Constraint, Rect}; +use ratatui::layout::{Constraint, Rect}; use ratatui::widgets::{Cell, Row}; use ratatui::Frame; @@ -67,7 +67,6 @@ fn draw_test_all_indexers_test_results(f: &mut Frame<'_>, app: &mut App<'_>, are test_results_row_mapping, ) .loading(is_loading) - .footer_alignment(Alignment::Center) .margin(1) .headers(["Indexer", "Pass/Fail", "Failure Messages"]) .constraints([ diff --git a/src/ui/radarr_ui/system/system_details_ui.rs b/src/ui/radarr_ui/system/system_details_ui.rs index db1e538..bdd6afd 100644 --- a/src/ui/radarr_ui/system/system_details_ui.rs +++ b/src/ui/radarr_ui/system/system_details_ui.rs @@ -1,4 +1,4 @@ -use ratatui::layout::{Alignment, Rect}; +use ratatui::layout::Rect; use ratatui::text::{Span, Text}; use ratatui::widgets::{Cell, ListItem, Paragraph, Row}; use ratatui::Frame; @@ -60,7 +60,7 @@ fn draw_logs_popup(f: &mut Frame<'_>, app: &mut App<'_>) { if app.data.radarr_data.log_details.items.is_empty() { let loading = LoadingBlock::new(app.is_loading, borderless_block()); - let popup = Popup::new(loading).size(Size::Large).block(block); + let popup = Popup::new(loading).size(Size::Large).block(block).margin(1); f.render_widget(popup, f.area()); return; @@ -73,7 +73,10 @@ fn draw_logs_popup(f: &mut Frame<'_>, app: &mut App<'_>) { style_log_list_item(ListItem::new(Text::from(Span::raw(log_line))), level) }) .block(borderless_block()); - let popup = Popup::new(logs_list).size(Size::Large).block(block); + let popup = Popup::new(logs_list) + .size(Size::Large) + .block(block) + .margin(1); f.render_widget(popup, f.area()); } @@ -94,7 +97,6 @@ fn draw_tasks_popup(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) { let tasks_table = ManagarrTable::new(Some(&mut app.data.radarr_data.tasks), tasks_row_mapping) .loading(app.is_loading) .margin(1) - .footer_alignment(Alignment::Center) .headers(TASK_TABLE_HEADERS) .constraints(TASK_TABLE_CONSTRAINTS); @@ -129,12 +131,15 @@ fn draw_updates_popup(f: &mut Frame<'_>, app: &mut App<'_>) { let updates_paragraph = Paragraph::new(Text::from(updates)) .block(borderless_block()) .scroll((app.data.radarr_data.updates.offset, 0)); - let popup = Popup::new(updates_paragraph).size(Size::Large).block(block); + let popup = Popup::new(updates_paragraph) + .size(Size::Large) + .block(block) + .margin(1); f.render_widget(popup, f.area()); } else { let loading = LoadingBlock::new(app.is_loading, borderless_block()); - let popup = Popup::new(loading).size(Size::Large).block(block); + let popup = Popup::new(loading).size(Size::Large).block(block).margin(1); f.render_widget(popup, f.area()); } diff --git a/src/ui/sonarr_ui/indexers/test_all_indexers_ui.rs b/src/ui/sonarr_ui/indexers/test_all_indexers_ui.rs index e6c5c05..1712a2e 100644 --- a/src/ui/sonarr_ui/indexers/test_all_indexers_ui.rs +++ b/src/ui/sonarr_ui/indexers/test_all_indexers_ui.rs @@ -7,7 +7,7 @@ use crate::ui::utils::{get_width_from_percentage, title_block}; use crate::ui::widgets::managarr_table::ManagarrTable; use crate::ui::widgets::popup::Size; use crate::ui::{draw_popup, DrawUi}; -use ratatui::layout::{Alignment, Constraint, Rect}; +use ratatui::layout::{Constraint, Rect}; use ratatui::widgets::{Cell, Row}; use ratatui::Frame; @@ -65,7 +65,6 @@ fn draw_test_all_indexers_test_results(f: &mut Frame<'_>, app: &mut App<'_>, are test_results_row_mapping, ) .loading(is_loading) - .footer_alignment(Alignment::Center) .margin(1) .headers(["Indexer", "Pass/Fail", "Failure Messages"]) .constraints([ diff --git a/src/ui/sonarr_ui/system/system_details_ui.rs b/src/ui/sonarr_ui/system/system_details_ui.rs index 45cad02..ffdfd47 100644 --- a/src/ui/sonarr_ui/system/system_details_ui.rs +++ b/src/ui/sonarr_ui/system/system_details_ui.rs @@ -1,4 +1,4 @@ -use ratatui::layout::{Alignment, Rect}; +use ratatui::layout::Rect; use ratatui::text::{Span, Text}; use ratatui::widgets::{Cell, ListItem, Paragraph, Row}; use ratatui::Frame; @@ -60,7 +60,7 @@ fn draw_logs_popup(f: &mut Frame<'_>, app: &mut App<'_>) { if app.data.sonarr_data.log_details.items.is_empty() { let loading = LoadingBlock::new(app.is_loading, borderless_block()); - let popup = Popup::new(loading).size(Size::Large).block(block); + let popup = Popup::new(loading).size(Size::Large).block(block).margin(1); f.render_widget(popup, f.area()); return; @@ -73,7 +73,10 @@ fn draw_logs_popup(f: &mut Frame<'_>, app: &mut App<'_>) { style_log_list_item(ListItem::new(Text::from(Span::raw(log_line))), level) }) .block(borderless_block()); - let popup = Popup::new(logs_list).size(Size::Large).block(block); + let popup = Popup::new(logs_list) + .size(Size::Large) + .block(block) + .margin(1); f.render_widget(popup, f.area()); } @@ -93,7 +96,6 @@ fn draw_tasks_popup(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) { let tasks_table = ManagarrTable::new(Some(&mut app.data.sonarr_data.tasks), tasks_row_mapping) .loading(app.is_loading) .margin(1) - .footer_alignment(Alignment::Center) .headers(TASK_TABLE_HEADERS) .constraints(TASK_TABLE_CONSTRAINTS); @@ -128,12 +130,15 @@ fn draw_updates_popup(f: &mut Frame<'_>, app: &mut App<'_>) { let updates_paragraph = Paragraph::new(Text::from(updates)) .block(borderless_block()) .scroll((app.data.sonarr_data.updates.offset, 0)); - let popup = Popup::new(updates_paragraph).size(Size::Large).block(block); + let popup = Popup::new(updates_paragraph) + .size(Size::Large) + .block(block) + .margin(1); f.render_widget(popup, f.area()); } else { let loading = LoadingBlock::new(app.is_loading, borderless_block()); - let popup = Popup::new(loading).size(Size::Large).block(block); + let popup = Popup::new(loading).size(Size::Large).block(block).margin(1); f.render_widget(popup, f.area()); } diff --git a/src/ui/widgets/managarr_table.rs b/src/ui/widgets/managarr_table.rs index 2b5e643..169fdcd 100644 --- a/src/ui/widgets/managarr_table.rs +++ b/src/ui/widgets/managarr_table.rs @@ -3,18 +3,16 @@ use super::message::Message; use super::popup::Size; use crate::models::stateful_table::StatefulTable; use crate::ui::styles::ManagarrStyle; -use crate::ui::utils::{ - borderless_block, centered_rect, layout_block_top_border, title_block_centered, -}; +use crate::ui::utils::{borderless_block, centered_rect, title_block_centered}; use crate::ui::widgets::loading_block::LoadingBlock; use crate::ui::widgets::popup::Popup; use crate::ui::widgets::selectable_list::SelectableList; use crate::ui::HIGHLIGHT_SYMBOL; use derive_setters::Setters; use ratatui::buffer::Buffer; -use ratatui::layout::{Alignment, Constraint, Layout, Position, Rect}; +use ratatui::layout::{Constraint, Layout, Position, Rect}; use ratatui::prelude::{Style, Stylize, Text}; -use ratatui::widgets::{Block, ListItem, Paragraph, Row, StatefulWidget, Table, Widget, WidgetRef}; +use ratatui::widgets::{Block, ListItem, Row, StatefulWidget, Table, Widget, WidgetRef}; use ratatui::Frame; use std::fmt::Debug; use std::sync::atomic::Ordering; @@ -36,8 +34,6 @@ where #[setters(skip)] constraints: Vec, row_mapper: F, - footer: Option, - footer_alignment: Alignment, block: Block<'a>, margin: u16, #[setters(rename = "loading")] @@ -68,8 +64,6 @@ where table_headers: Vec::new(), constraints: Vec::new(), row_mapper, - footer: None, - footer_alignment: Alignment::Left, block: borderless_block(), margin: 0, is_loading: false, @@ -119,20 +113,12 @@ where fn render_table(self, area: Rect, buf: &mut Buffer) { let table_headers = self.parse_headers(); - let table_area = if let Some(ref footer) = self.footer { - let [content_area, footer_area] = - Layout::vertical([Constraint::Fill(0), Constraint::Length(2)]) - .margin(self.margin) - .areas(area); - - Paragraph::new(Text::from(format!(" {footer}").help())) - .block(layout_block_top_border()) - .alignment(self.footer_alignment) - .render(footer_area, buf); + let table_area = { + let [content_area, _] = Layout::vertical([Constraint::Fill(1), Constraint::Fill(0)]) + .margin(self.margin) + .areas(area); content_area - } else { - area }; let loading_block = LoadingBlock::new(self.is_loading, self.block.clone()); @@ -230,19 +216,11 @@ where pub fn show_cursor(&self, f: &mut Frame<'_>, area: Rect) { let mut draw_cursor = |length: usize, offset: usize| { - let table_area = if self.footer.is_some() { - let [content_area, _] = Layout::vertical([Constraint::Fill(0), Constraint::Length(2)]) - .margin(self.margin) - .areas(area); - content_area - } else { - area - }; let popup_area = Rect { height: 7, - ..centered_rect(30, 20, table_area) + ..centered_rect(30, 20, area) }; - let [text_box_area, _] = Layout::vertical([Constraint::Length(3), Constraint::Length(1)]) + let [text_box_area, _] = Layout::vertical([Constraint::Fill(1), Constraint::Fill(0)]) .margin(1) .areas(popup_area); f.set_cursor_position(Position { diff --git a/src/ui/widgets/managarr_table_tests.rs b/src/ui/widgets/managarr_table_tests.rs index f4178f7..199100f 100644 --- a/src/ui/widgets/managarr_table_tests.rs +++ b/src/ui/widgets/managarr_table_tests.rs @@ -6,7 +6,7 @@ mod tests { use crate::ui::utils::borderless_block; use crate::ui::widgets::managarr_table::ManagarrTable; use pretty_assertions::assert_eq; - use ratatui::layout::{Alignment, Constraint}; + use ratatui::layout::Constraint; use ratatui::text::Text; use ratatui::widgets::{Cell, Row}; use std::sync::atomic::AtomicUsize; @@ -25,8 +25,6 @@ mod tests { assert_eq!(row_mapper(&"item1"), Row::new(vec![Cell::new("item1")])); assert_eq!(managarr_table.table_headers, Vec::::new()); assert_eq!(managarr_table.constraints, Vec::new()); - assert_eq!(managarr_table.footer, None); - assert_eq!(managarr_table.footer_alignment, Alignment::Left); assert_eq!(managarr_table.block, borderless_block()); assert_eq!(managarr_table.margin, 0); assert!(!managarr_table.is_loading); @@ -61,8 +59,6 @@ mod tests { assert_eq!(row_mapper(&"item1"), Row::new(vec![Cell::new("item1")])); assert_eq!(managarr_table.table_headers, Vec::::new()); assert_eq!(managarr_table.constraints, Vec::new()); - assert_eq!(managarr_table.footer, None); - assert_eq!(managarr_table.footer_alignment, Alignment::Left); assert_eq!(managarr_table.block, borderless_block()); assert_eq!(managarr_table.margin, 0); assert!(!managarr_table.is_loading); @@ -97,8 +93,6 @@ mod tests { assert_eq!(row_mapper(&"item1"), Row::new(vec![Cell::new("item1")])); assert_eq!(managarr_table.table_headers, Vec::::new()); assert_eq!(managarr_table.constraints, Vec::new()); - assert_eq!(managarr_table.footer, None); - assert_eq!(managarr_table.footer_alignment, Alignment::Left); assert_eq!(managarr_table.block, borderless_block()); assert_eq!(managarr_table.margin, 0); assert!(!managarr_table.is_loading); @@ -130,8 +124,6 @@ mod tests { assert_eq!(managarr_table.content.unwrap().items, items); assert_eq!(row_mapper(&"item1"), Row::new(vec![Cell::new("item1")])); assert_eq!(managarr_table.constraints, Vec::new()); - assert_eq!(managarr_table.footer, None); - assert_eq!(managarr_table.footer_alignment, Alignment::Left); assert_eq!(managarr_table.block, borderless_block()); assert_eq!(managarr_table.margin, 0); assert!(!managarr_table.is_loading); @@ -163,8 +155,6 @@ mod tests { assert_eq!(managarr_table.content.unwrap().items, items); assert_eq!(row_mapper(&"item1"), Row::new(vec![Cell::new("item1")])); assert_eq!(managarr_table.table_headers, Vec::::new()); - assert_eq!(managarr_table.footer, None); - assert_eq!(managarr_table.footer_alignment, Alignment::Left); assert_eq!(managarr_table.block, borderless_block()); assert_eq!(managarr_table.margin, 0); assert!(!managarr_table.is_loading); diff --git a/src/ui/widgets/popup.rs b/src/ui/widgets/popup.rs index 0534b95..b08fe60 100644 --- a/src/ui/widgets/popup.rs +++ b/src/ui/widgets/popup.rs @@ -1,6 +1,6 @@ use crate::ui::utils::{background_block, centered_rect}; use ratatui::buffer::Buffer; -use ratatui::layout::Rect; +use ratatui::layout::{Constraint, Layout, Rect}; use ratatui::widgets::{Block, Clear, Widget}; #[cfg(test)] @@ -51,6 +51,7 @@ impl Size { pub struct Popup<'a, T: Widget> { widget: T, + margin: u16, percent_x: u16, percent_y: u16, block: Option>, @@ -62,6 +63,7 @@ impl<'a, T: Widget> Popup<'a, T> { widget, percent_x: 0, percent_y: 0, + margin: 0, block: None, } } @@ -84,6 +86,11 @@ impl<'a, T: Widget> Popup<'a, T> { self } + pub fn margin(mut self, margin: u16) -> Self { + self.margin = margin; + self + } + fn render_popup(self, area: Rect, buf: &mut Buffer) { let mut popup_area = centered_rect(self.percent_x, self.percent_y, area); let height = if popup_area.height < 3 { @@ -102,7 +109,11 @@ impl<'a, T: Widget> Popup<'a, T> { block.render(popup_area, buf); } - self.widget.render(popup_area, buf); + let [content_area, _] = Layout::vertical([Constraint::Fill(1), Constraint::Fill(0)]) + .margin(self.margin) + .areas(popup_area); + + self.widget.render(content_area, buf); } } diff --git a/src/ui/widgets/popup_tests.rs b/src/ui/widgets/popup_tests.rs index 3c0fedb..b285a78 100644 --- a/src/ui/widgets/popup_tests.rs +++ b/src/ui/widgets/popup_tests.rs @@ -32,6 +32,7 @@ mod tests { assert_eq!(popup.percent_x, 0); assert_eq!(popup.percent_y, 0); assert_eq!(popup.block, None); + assert_eq!(popup.margin, 0); } #[test] @@ -42,6 +43,7 @@ mod tests { assert_eq!(popup.percent_y, 40); assert_eq!(popup.widget, Block::new()); assert_eq!(popup.block, None); + assert_eq!(popup.margin, 0); } #[test] @@ -52,6 +54,7 @@ mod tests { assert_eq!(popup.percent_y, 50); assert_eq!(popup.widget, Block::new()); assert_eq!(popup.block, None); + assert_eq!(popup.margin, 0); } #[test] @@ -62,5 +65,17 @@ mod tests { assert_eq!(popup.widget, Block::new()); assert_eq!(popup.percent_x, 0); assert_eq!(popup.percent_y, 0); + assert_eq!(popup.margin, 0); + } + + #[test] + fn test_popup_margin() { + let popup = Popup::new(Block::new()).margin(5); + + assert_eq!(popup.margin, 5); + assert_eq!(popup.widget, Block::new()); + assert_eq!(popup.percent_x, 0); + assert_eq!(popup.percent_y, 0); + assert_eq!(popup.block, None); } }