use super::super::app::App;
use ratatui::{
Frame,
layout::Rect,
style::{Color, Modifier, Style},
text::{Line, Span},
widgets::{Block, Borders, Paragraph, Wrap},
};
pub(super) fn render_session_files(f: &mut Frame, app: &App, area: Rect) {
let mut lines: Vec<Line> = Vec::new();
lines.push(Line::from(vec![
Span::styled(
" [↑↓] ",
Style::default()
.fg(Color::Rgb(120, 120, 120))
.add_modifier(Modifier::BOLD),
),
Span::styled("Navigate ", Style::default().fg(Color::Reset)),
Span::styled(
"[Enter] ",
Style::default()
.fg(Color::Rgb(120, 120, 120))
.add_modifier(Modifier::BOLD),
),
Span::styled("Open ", Style::default().fg(Color::Reset)),
Span::styled(
"[D] ",
Style::default().fg(Color::Red).add_modifier(Modifier::BOLD),
),
Span::styled("Remove ", Style::default().fg(Color::Reset)),
Span::styled(
"[O] ",
Style::default()
.fg(Color::Rgb(215, 100, 20))
.add_modifier(Modifier::BOLD),
),
Span::styled("Folder ", Style::default().fg(Color::Reset)),
Span::styled(
"[Esc] ",
Style::default().fg(Color::Red).add_modifier(Modifier::BOLD),
),
Span::styled("Back", Style::default().fg(Color::Reset)),
]));
lines.push(Line::from(""));
if app.session_files.is_empty() {
lines.push(Line::from(Span::styled(
" No files tracked for this session.",
Style::default().fg(Color::DarkGray),
)));
lines.push(Line::from(""));
lines.push(Line::from(Span::styled(
" Files are auto-tracked when the agent writes or edits them,",
Style::default().fg(Color::DarkGray),
)));
lines.push(Line::from(Span::styled(
" or when you paste images from the clipboard.",
Style::default().fg(Color::DarkGray),
)));
} else {
let count = app.session_files.len();
lines.push(Line::from(Span::styled(
format!(
" {} file{} tracked",
count,
if count == 1 { "" } else { "s" }
),
Style::default().fg(Color::Rgb(100, 140, 180)),
)));
lines.push(Line::from(""));
for (idx, file) in app.session_files.iter().enumerate() {
let is_selected = idx == app.selected_file_index;
let prefix = if is_selected { " > " } else { " " };
let path_display = file.path.display().to_string();
let home_dir = dirs::home_dir()
.map(|h| h.to_string_lossy().to_string())
.unwrap_or_default();
let short_path = if !home_dir.is_empty() && path_display.starts_with(&home_dir) {
format!("~{}", &path_display[home_dir.len()..])
} else {
path_display
};
let name_style = if is_selected {
Style::default()
.fg(Color::Rgb(215, 100, 20))
.add_modifier(Modifier::BOLD)
} else {
Style::default().fg(Color::Reset)
};
let mut spans = vec![Span::styled(
format!("{}{}", prefix, short_path),
name_style,
)];
if let Some(size) = file.size {
let size_str = format_size(size);
spans.push(Span::styled(
format!(" ({})", size_str),
Style::default().fg(Color::Rgb(100, 100, 100)),
));
}
let created = file.created_at.format("%Y-%m-%d %H:%M");
spans.push(Span::styled(
format!(" {}", created),
Style::default().fg(Color::DarkGray),
));
if file.content.is_some() {
spans.push(Span::styled(" [stored]", Style::default().fg(Color::Cyan)));
}
lines.push(Line::from(spans));
}
}
let para = Paragraph::new(lines)
.block(
Block::default()
.borders(Borders::ALL)
.title(Span::styled(
" Session Files ",
Style::default()
.fg(Color::Rgb(215, 100, 20))
.add_modifier(Modifier::BOLD),
))
.border_style(Style::default().fg(Color::Rgb(120, 120, 120))),
)
.wrap(Wrap { trim: false });
f.render_widget(para, area);
}
fn format_size(bytes: i64) -> String {
if bytes < 1024 {
format!("{} B", bytes)
} else if bytes < 1024 * 1024 {
format!("{:.1} KB", bytes as f64 / 1024.0)
} else if bytes < 1024 * 1024 * 1024 {
format!("{:.1} MB", bytes as f64 / (1024.0 * 1024.0))
} else {
format!("{:.1} GB", bytes as f64 / (1024.0 * 1024.0 * 1024.0))
}
}