use ratatui::Frame;
use ratatui::layout::Rect;
use ratatui::text::{Line, Span, Text};
use ratatui::widgets::{Block, Borders, Paragraph};
use crate::shared::i18n::Locale;
use crate::shared::theme::Palette;
use crate::shared::ui::fit_title;
use crate::shared::wrap::wrap_ranges;
pub struct Preview<'a> {
pub text: &'a str,
pub spinner: char,
pub done: bool,
pub bare: bool,
}
impl Preview<'_> {
pub fn text_width(area_width: u16) -> usize {
usize::from(area_width.saturating_sub(2))
}
}
pub fn render(
frame: &mut Frame,
area: Rect,
preview: &Preview,
palette: &Palette,
loc: &'static Locale,
) {
let inner_w = Preview::text_width(area.width);
let mut rows: Vec<Line<'static>> = Vec::new();
for logical in preview.text.split('\n') {
let chars: Vec<char> = logical.chars().collect();
for (s, e) in wrap_ranges(&chars, inner_w) {
rows.push(Line::from(chars[s..e].iter().collect::<String>()));
}
}
if preview.bare {
if !preview.done && area.width > 0 && area.height > 0 {
let prompt = Rect {
width: 1,
height: 1,
..area
};
frame.render_widget(
Paragraph::new(Span::styled(
preview.spinner.to_string(),
palette.accent_style(),
)),
prompt,
);
}
let inner = Rect {
x: area.x + area.width.min(2),
width: area.width.saturating_sub(2),
..area
};
let scroll = (rows.len().saturating_sub(usize::from(inner.height))) as u16;
frame.render_widget(Paragraph::new(Text::from(rows)).scroll((scroll, 0)), inner);
return;
}
let hint = if preview.done {
loc.t("ui.impersonation.done").to_string()
} else {
loc.tf(
"ui.impersonation.active",
&[("spinner", &preview.spinner.to_string())],
)
};
let hint = fit_title(&hint, usize::from(area.width.saturating_sub(2)));
let block = Block::default()
.borders(Borders::ALL)
.border_type(palette.glyphs().border)
.border_style(palette.accent_style())
.title(Line::from(hint).style(palette.accent_style()));
let inner_h = area.height.saturating_sub(2) as usize;
let scroll = (rows.len().saturating_sub(inner_h)) as u16;
let para = Paragraph::new(Text::from(rows))
.block(block)
.scroll((scroll, 0));
frame.render_widget(para, area);
}