feat(tui): make system/status output height dynamic and refactor rendering
- Introduce `system_status_message` helper to determine the message shown in the system/status pane. - Calculate wrapped line count based on available width, clamp visible rows to 1–5, and set the layout constraint dynamically. - Update `render_system_output` to accept the pre‑computed message, choose color based on error prefix, and render each line individually, defaulting to “Ready” when empty. - Adjust UI layout to use the new dynamic constraint for the system/status section.
This commit is contained in:
@@ -273,6 +273,8 @@ pub fn render_chat(frame: &mut Frame<'_>, app: &mut ChatApp) {
|
||||
0
|
||||
};
|
||||
|
||||
let status_message = system_status_message(app);
|
||||
|
||||
let mut constraints = vec![Constraint::Min(8)]; // Messages
|
||||
|
||||
if thinking_height > 0 {
|
||||
@@ -284,7 +286,12 @@ pub fn render_chat(frame: &mut Frame<'_>, app: &mut ChatApp) {
|
||||
}
|
||||
|
||||
constraints.push(Constraint::Length(input_height)); // Input
|
||||
constraints.push(Constraint::Length(4)); // System/Status output (2 lines content + 2 borders)
|
||||
|
||||
let status_visual_lines = calculate_wrapped_line_count(status_message.lines(), available_width);
|
||||
let status_visible_rows = status_visual_lines.clamp(1, 5);
|
||||
let status_height = status_visible_rows as u16 + 2; // +2 for borders
|
||||
|
||||
constraints.push(Constraint::Length(status_height)); // System/Status output (dynamic)
|
||||
constraints.push(Constraint::Length(3)); // Mode and shortcuts bar
|
||||
|
||||
let layout = Layout::default()
|
||||
@@ -309,7 +316,7 @@ pub fn render_chat(frame: &mut Frame<'_>, app: &mut ChatApp) {
|
||||
render_input(frame, layout[idx], app);
|
||||
idx += 1;
|
||||
|
||||
render_system_output(frame, layout[idx], app);
|
||||
render_system_output(frame, layout[idx], app, &status_message);
|
||||
idx += 1;
|
||||
|
||||
render_status(frame, layout[idx], app);
|
||||
@@ -1865,15 +1872,13 @@ fn render_input(frame: &mut Frame<'_>, area: Rect, app: &mut ChatApp) {
|
||||
}
|
||||
}
|
||||
|
||||
fn render_system_output(frame: &mut Frame<'_>, area: Rect, app: &ChatApp) {
|
||||
let theme = app.theme();
|
||||
fn system_status_message(app: &ChatApp) -> String {
|
||||
let system_status = app.system_status();
|
||||
|
||||
// Priority: system_status > error > status > "Ready"
|
||||
let display_message = if !system_status.is_empty() {
|
||||
if !system_status.is_empty() {
|
||||
system_status.to_string()
|
||||
} else if let Some(error) = app.error_message() {
|
||||
format!("Error: {}", error)
|
||||
format!("Error: {error}")
|
||||
} else {
|
||||
let status = app.status_message();
|
||||
if status.is_empty() || status == "Ready" {
|
||||
@@ -1881,15 +1886,31 @@ fn render_system_output(frame: &mut Frame<'_>, area: Rect, app: &ChatApp) {
|
||||
} else {
|
||||
status.to_string()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn render_system_output(frame: &mut Frame<'_>, area: Rect, app: &ChatApp, message: &str) {
|
||||
let theme = app.theme();
|
||||
|
||||
let color = if message.starts_with("Error:") {
|
||||
theme.error
|
||||
} else {
|
||||
theme.info
|
||||
};
|
||||
|
||||
// Create a simple paragraph with wrapping enabled
|
||||
let line = Line::from(Span::styled(
|
||||
display_message,
|
||||
Style::default().fg(theme.info),
|
||||
));
|
||||
let text_lines: Vec<Line> = if message.is_empty() {
|
||||
vec![Line::from(Span::styled(
|
||||
"Ready",
|
||||
Style::default().fg(color),
|
||||
))]
|
||||
} else {
|
||||
message
|
||||
.lines()
|
||||
.map(|line| Line::from(Span::styled(line.to_string(), Style::default().fg(color))))
|
||||
.collect()
|
||||
};
|
||||
|
||||
let paragraph = Paragraph::new(line)
|
||||
let paragraph = Paragraph::new(text_lines)
|
||||
.style(Style::default().bg(theme.background))
|
||||
.block(
|
||||
Block::default()
|
||||
|
||||
Reference in New Issue
Block a user