use crate::app::agent::agent::loop_::cli::render_execution_indicator;
use crate::app::agent::agent::loop_::cli::theme::{
SURFACE_ELEVATED, TEXT_MUTED, TEXT_PRIMARY, TEXT_SUBTLE, WARNING,
};
use crate::app::agent::agent::loop_::cli::tui_utils::cursor_position;
use ratatui::layout::{Constraint, Direction, Layout};
use ratatui::style::{Modifier, Style};
use ratatui::text::{Line, Span, Text};
use ratatui::widgets::Paragraph;
pub(crate) fn render_input_panel(
f: &mut ratatui::Frame<'_>,
area: ratatui::layout::Rect,
input: &str,
cursor_idx: usize,
busy: bool,
model_name: &str,
spinner_idx: usize,
) {
let panel_rows = Layout::default()
.direction(Direction::Vertical)
.constraints([
Constraint::Length(1),
Constraint::Length(area.height.saturating_sub(2)),
Constraint::Length(1),
])
.split(area);
let status_row = panel_rows[0];
let input_inner_area = panel_rows[1];
let tip_row = panel_rows[2];
let input_text_area = render_input_box(f, input_inner_area, input);
let build_info = Layout::default()
.direction(Direction::Horizontal)
.constraints([Constraint::Length(12), Constraint::Min(1), Constraint::Length(10)])
.split(status_row);
render_execution_indicator(f, build_info[0], busy, spinner_idx);
let esc_line = if busy {
Line::from(vec![
Span::styled("esc", Style::default().fg(WARNING).add_modifier(Modifier::BOLD)),
Span::styled(" 取消", Style::default().fg(TEXT_MUTED)),
])
} else {
Line::from(Span::raw(""))
};
f.render_widget(
Paragraph::new(esc_line).alignment(ratatui::layout::Alignment::Right),
build_info[2],
);
let tip_chunks = Layout::default()
.direction(Direction::Horizontal)
.constraints([Constraint::Min(1), Constraint::Length(44)])
.split(tip_row);
let model_line =
Line::from(vec![Span::styled(model_name.to_string(), Style::default().fg(TEXT_MUTED))]);
f.render_widget(Paragraph::new(model_line), tip_chunks[0]);
let tip_line = Line::from(vec![
Span::styled("● ", Style::default().fg(WARNING)),
Span::styled(
"提示:Shift+Enter 或 Ctrl+J 换行,Enter 发送,Ctrl+Z 挂起",
Style::default().fg(TEXT_MUTED),
),
]);
f.render_widget(
Paragraph::new(tip_line).alignment(ratatui::layout::Alignment::Right),
tip_chunks[1],
);
let safe_cursor = cursor_idx.min(input.chars().count());
let (row, col) = cursor_position(input, safe_cursor);
let max_row = input_text_area.height.saturating_sub(1);
let max_col = input_text_area.width.saturating_sub(1);
let safe_row: u16 = row.min(max_row);
let safe_col: u16 = col.min(max_col);
let cursor_x = input_text_area.x.saturating_add(safe_col);
let cursor_y = input_text_area.y.saturating_add(safe_row);
f.set_cursor_position((cursor_x, cursor_y));
}
pub(crate) fn render_input_box(
f: &mut ratatui::Frame<'_>,
area: ratatui::layout::Rect,
input: &str,
) -> ratatui::layout::Rect {
let input_text = if input.is_empty() {
Text::from(Line::from(Span::styled("随便问点什么...", Style::default().fg(TEXT_SUBTLE))))
} else {
Text::from(input.to_string())
};
let text_area = ratatui::layout::Rect {
x: area.x.saturating_add(1),
y: area.y,
width: area.width.saturating_sub(2),
height: area.height.saturating_sub(1),
};
let bg_widget = Paragraph::new(Text::from(""))
.style(Style::default().fg(TEXT_PRIMARY).bg(SURFACE_ELEVATED));
f.render_widget(bg_widget, area);
let input_widget =
Paragraph::new(input_text).style(Style::default().fg(TEXT_PRIMARY).bg(SURFACE_ELEVATED));
f.render_widget(input_widget, text_area);
text_area
}
#[cfg(test)]
#[path = "input_panel_tests.rs"]
mod input_panel_tests;