use ratatui::layout::{Constraint, Direction, Layout, Rect};
use ratatui::style::Style;
use ratatui::text::{Line, Span};
use ratatui::widgets::Paragraph;
use ratatui::Frame;
use crate::tui::action::LensData;
use crate::tui::panes::{tld::TLDS, Panes};
use crate::tui::theme::Theme;
use crate::tui::widgets::{kv, panel};
pub fn render(f: &mut Frame, area: Rect, theme: &Theme, data: &LensData, panes: &Panes) {
let LensData::Tld(t) = data else {
return;
};
let block = panel::block(theme, "TLD Info", theme.maroon, false);
let inner = block.inner(area);
f.render_widget(block, area);
let chunks = Layout::default()
.direction(Direction::Vertical)
.constraints([
Constraint::Length(1),
Constraint::Length(1),
Constraint::Min(0),
])
.split(inner);
let selected = panes.tld.idx;
let mut spans: Vec<Span> = Vec::new();
for (i, tld) in TLDS.iter().enumerate() {
if i > 0 {
spans.push(Span::raw(" "));
}
let style = if i == selected {
Style::default().fg(theme.base).bg(theme.mauve)
} else {
Style::default().fg(theme.subtext).bg(theme.surface0)
};
spans.push(Span::styled(format!(" {tld} "), style));
}
f.render_widget(Paragraph::new(Line::from(spans)), chunks[0]);
f.render_widget(
Paragraph::new(Line::from(Span::styled(
"h/l switch TLD",
Style::default().fg(theme.overlay0),
))),
chunks[1],
);
let dash = || "—".to_string();
let rows: Vec<(String, String)> = vec![
("tld".into(), t.tld.clone()),
("type".into(), t.tld_type.clone()),
("whois".into(), t.whois_server.clone().unwrap_or_else(dash)),
("rdap".into(), t.rdap_url.clone().unwrap_or_else(dash)),
(
"registry".into(),
t.registry_url.clone().unwrap_or_else(dash),
),
];
kv::render(f, chunks[2], theme, theme.maroon, &rows);
}
#[cfg(test)]
mod tests {
use super::*;
use crate::tui::panes::Panes;
use ratatui::backend::TestBackend;
use ratatui::Terminal;
use seer_core::TldInfo;
fn buf_text(buf: &ratatui::buffer::Buffer) -> String {
let a = buf.area();
let mut s = String::new();
for y in 0..a.height {
for x in 0..a.width {
s.push_str(buf[(x, y)].symbol());
}
}
s
}
fn tld_fixture() -> seer_core::TldInfo {
TldInfo {
tld: ".com".into(),
whois_server: Some("whois.verisign-grs.com".into()),
rdap_url: None,
registry_url: None,
tld_type: "gTLD".into(),
}
}
#[test]
fn renders_whois_server() {
let theme = Theme::frappe();
let data = LensData::Tld(Box::new(tld_fixture()));
let panes = Panes::default();
let backend = TestBackend::new(70, 12);
let mut terminal = Terminal::new(backend).unwrap();
terminal
.draw(|f| render(f, f.area(), &theme, &data, &panes))
.unwrap();
assert!(buf_text(terminal.backend().buffer()).contains("whois.verisign-grs.com"));
}
#[test]
fn renders_chip_row_with_all_tlds() {
let theme = Theme::frappe();
let data = LensData::Tld(Box::new(tld_fixture()));
let panes = Panes::default();
let backend = TestBackend::new(80, 12);
let mut terminal = Terminal::new(backend).unwrap();
terminal
.draw(|f| render(f, f.area(), &theme, &data, &panes))
.unwrap();
let text = buf_text(terminal.backend().buffer());
assert!(text.contains(".com"), "chip row should contain .com");
assert!(text.contains(".net"), "chip row should contain .net");
assert!(text.contains(".io"), "chip row should contain .io");
}
#[test]
fn selected_chip_matches_pane_idx() {
let theme = Theme::frappe();
let data = LensData::Tld(Box::new(tld_fixture()));
let mut panes = Panes::default();
panes.tld.idx = 2; let backend = TestBackend::new(80, 12);
let mut terminal = Terminal::new(backend).unwrap();
terminal
.draw(|f| render(f, f.area(), &theme, &data, &panes))
.unwrap();
let text = buf_text(terminal.backend().buffer());
assert!(
text.contains(".org"),
"selected chip .org should be visible"
);
}
}