use ratatui::Frame;
use ratatui::style::{Modifier, Style};
use ratatui::text::{Line, Span};
use ratatui::widgets::{Block, Borders, Clear, Paragraph, Wrap};
use tmprl_core::mutation::Confirm;
use crate::theme::Theme;
const LISTED: usize = 8;
pub fn render(frame: &mut Frame, confirm: &Confirm, t: &Theme) {
let m = confirm.first();
let accent = if m.destroys_history() {
t.err
} else if m.is_destructive() {
t.warn
} else {
t.accent
};
let heading = if confirm.is_batch() {
format!(" {} {} {}", m.verb(), confirm.len(), m.subject_plural())
} else {
format!(" {} {}", m.verb(), m.workflow_id())
};
let mut lines = vec![
Line::from(Span::styled(
heading,
Style::new().fg(t.fg).add_modifier(Modifier::BOLD),
)),
Line::from(Span::styled(
format!(" in {}", m.namespace()),
Style::new().fg(t.dim),
)),
];
if confirm.is_batch() {
lines.push(Line::raw(""));
for target in confirm.mutations.iter().take(LISTED) {
lines.push(Line::from(Span::styled(
format!(" {}", target.workflow_id()),
Style::new().fg(t.dim),
)));
}
if confirm.len() > LISTED {
lines.push(Line::from(Span::styled(
format!(" and {} more", confirm.len() - LISTED),
Style::new().fg(t.faint),
)));
}
}
lines.push(Line::raw(""));
lines.push(Line::from(Span::styled(
if confirm.is_batch() {
" the equivalent command, for the first:"
} else {
" the equivalent command:"
},
Style::new().fg(t.faint),
)));
for chunk in wrap(&m.cli(), 66) {
lines.push(Line::from(Span::styled(
format!(" {chunk}"),
Style::new().fg(t.ok),
)));
}
lines.push(Line::raw(""));
if let Some(word) = &confirm.typed_word {
lines.push(Line::from(vec![
Span::styled(" ", Style::new()),
Span::styled(
format!("{} ", confirm.caution().unwrap_or_default()),
Style::new().fg(t.err).add_modifier(Modifier::BOLD),
),
Span::styled(format!("type `{word}`:"), Style::new().fg(t.fg)),
]));
lines.push(Line::from(vec![
Span::styled(" ", Style::new()),
Span::styled(confirm.entered.clone(), Style::new().fg(t.fg)),
Span::styled("█", Style::new().fg(accent)),
]));
lines.push(Line::raw(""));
}
lines.push(Line::from(Span::styled(
format!(" {}", confirm.prompt()),
Style::new().fg(t.faint),
)));
let height = (lines.len() as u16 + 2).min(frame.area().height);
let area = super::centered(frame.area(), 74, height);
if area.height < 3 || area.width < 20 {
return;
}
frame.render_widget(Clear, area);
frame.render_widget(
Paragraph::new(lines).wrap(Wrap { trim: false }).block(
Block::bordered()
.borders(Borders::ALL)
.title(Span::styled(
format!(" confirm, {} ", m.verb().to_lowercase()),
Style::new().fg(accent).add_modifier(Modifier::BOLD),
))
.border_style(Style::new().fg(accent)),
),
area,
);
}
fn wrap(s: &str, width: usize) -> Vec<String> {
let mut out = Vec::new();
let mut line = String::new();
for word in s.split(' ') {
if !line.is_empty() && line.chars().count() + 1 + word.chars().count() > width {
out.push(std::mem::take(&mut line));
}
if !line.is_empty() {
line.push(' ');
}
line.push_str(word);
}
if !line.is_empty() {
out.push(line);
}
out
}