diff --git a/crates/owlen-tui/src/ui.rs b/crates/owlen-tui/src/ui.rs index 7337b2e..f680a96 100644 --- a/crates/owlen-tui/src/ui.rs +++ b/crates/owlen-tui/src/ui.rs @@ -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 = 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()