use ratatui::{
Frame,
layout::Rect,
style::{Modifier, Style},
text::{Line, Span},
widgets::Paragraph,
};
use crate::app::App;
use crate::ui::{markdown, styles};
pub fn render(frame: &mut Frame, app: &mut App, area: Rect) {
let body_width = (area.width as usize).saturating_sub(2).max(1);
let markdown_enabled = app.markdown_rendering_enabled;
let dim_style = styles::dim_style(&app.theme);
let panel_style = styles::panel_style(&app.theme);
let lines = {
let theme = &app.theme;
if let Some(meta) = app.remote().and_then(|r| r.pr_metadata.as_ref()) {
let state_display = meta.state.display();
let draft_marker = if meta.is_draft { " (draft)" } else { "" };
let mut text = vec![
Line::from(Span::styled(
format!(" {} [{}{}]", meta.title, state_display, draft_marker),
Style::default().add_modifier(Modifier::BOLD),
)),
Line::from(format!(
" {} -> {} -> {}",
meta.author, meta.head_branch, meta.base_branch
)),
Line::from(format!(
" Created: {}",
meta.created_at.format("%Y-%m-%d %H:%M")
)),
];
if let Some(ref mergeable) = meta.mergeable {
text.push(Line::from(format!(" Mergeable: {mergeable:?}")));
}
text.push(Line::from(""));
text.push(Line::from(Span::styled(
" Description",
Style::default().add_modifier(Modifier::BOLD | Modifier::UNDERLINED),
)));
text.push(Line::from(""));
if meta.body.is_empty() {
text.push(Line::from(Span::styled(" (no description)", dim_style)));
} else if markdown_enabled {
for mut md_line in markdown::render_markdown(&meta.body, theme, body_width) {
md_line.spans.insert(0, Span::raw(" "));
text.push(md_line);
}
} else {
for line in meta.body.lines() {
text.push(Line::from(format!(" {line}")));
}
}
text
} else {
vec![Line::from(Span::styled(
" No metadata available",
dim_style,
))]
}
};
let total_lines = lines.len();
let viewport_height = area.height as usize;
let max_scroll = total_lines.saturating_sub(viewport_height);
let scroll = if let Some(r) = app.remote_mut() {
if r.description_scroll > max_scroll {
r.description_scroll = max_scroll;
}
r.description_scroll
} else {
0
};
let visible: Vec<Line> = lines
.into_iter()
.skip(scroll)
.take(viewport_height)
.collect();
let paragraph = Paragraph::new(visible).style(panel_style);
frame.render_widget(paragraph, area);
}