aboutsummaryrefslogtreecommitdiff
path: root/src/main
diff options
context:
space:
mode:
Diffstat (limited to 'src/main')
-rw-r--r--src/main/rust/ui.rs67
1 files changed, 64 insertions, 3 deletions
diff --git a/src/main/rust/ui.rs b/src/main/rust/ui.rs
index daf00d4..1632623 100644
--- a/src/main/rust/ui.rs
+++ b/src/main/rust/ui.rs
@@ -1,15 +1,25 @@
use crate::app::App;
+use miette::ErrReport;
use ratatui::{
Frame,
- style::Stylize,
+ layout::{Constraint, Direction, Layout, Rect},
+ style::{Style, Stylize},
symbols::border,
- text::{Line, Text},
- widgets::{Block, Paragraph, Widget},
+ text::{Line, Span, Text},
+ widgets::{Block, Clear, Paragraph, Widget},
};
pub fn draw(frame: &mut Frame, app: &App) {
let rect = draw_layout(app);
frame.render_widget(rect, frame.area());
+
+ if let Some(error) = app.get_error() {
+ let popup = error_popup(error);
+
+ let area = centered_rect(40, 25, frame.area());
+ frame.render_widget(Clear, area);
+ frame.render_widget(popup, area);
+ }
}
fn draw_layout(app: &App) -> impl Widget {
@@ -35,6 +45,57 @@ fn draw_layout(app: &App) -> impl Widget {
Paragraph::new(counter_text).centered().block(block)
}
+/// helper function to create a centered rect using up certain percentage of the available rect `r`
+fn centered_rect(percent_x: u16, percent_y: u16, r: Rect) -> Rect {
+ // Cut the given rectangle into three vertical pieces
+ let popup_layout = Layout::default()
+ .direction(Direction::Vertical)
+ .constraints([
+ Constraint::Percentage((100 - percent_y) / 2),
+ Constraint::Percentage(percent_y),
+ Constraint::Percentage((100 - percent_y) / 2),
+ ])
+ .split(r);
+ // Then cut the middle vertical piece into three width-wise pieces
+ Layout::default()
+ .direction(Direction::Horizontal)
+ .constraints([
+ Constraint::Percentage((100 - percent_x) / 2),
+ Constraint::Percentage(percent_x),
+ Constraint::Percentage((100 - percent_x) / 2),
+ ])
+ .split(popup_layout[1])[1] // Return the middle chunk
+}
+
+fn error_popup(error: &ErrReport) -> impl Widget {
+ let title = Line::from("Error").bold();
+ let popup = Block::bordered()
+ .title(title.centered())
+ .border_set(border::DOUBLE);
+
+ let error_text = error_text(error);
+
+ Paragraph::new(error_text).block(popup)
+}
+
+fn error_text(error: &ErrReport) -> Text<'_> {
+ let errname_spans = vec![
+ Span::raw("Error "),
+ Span::styled("x", Style::new().red()),
+ Span::raw(" "),
+ Span::raw(error.to_string()),
+ ];
+
+ let line1 = Line::default().spans(errname_spans);
+ let help_spans = vec![
+ Span::styled(" help: ", Style::new().cyan()),
+ Span::raw(error.help().map_or("".into(), |x| x.to_string())),
+ ];
+ let line2 = Line::default().spans(help_spans);
+
+ Text::from(vec![line1, line2])
+}
+
#[cfg(test)]
mod tests {