use super::super::app::ChatApp;
use super::components::{cursor_spans, help_key_row, section_header, separator_line};
use ratatui::{
layout::Rect,
style::{Modifier, Style},
text::{Line, Span},
widgets::{Block, Borders, List, ListItem, ListState, Paragraph},
};
#[allow(clippy::vec_init_then_push)]
pub fn draw_archive_confirm(f: &mut ratatui::Frame, area: Rect, app: &ChatApp) {
let t = &app.ui.theme;
let mut lines: Vec<Line> = Vec::new();
lines.push(Line::from(""));
lines.push(section_header(
"\u{1f5c2}\u{fe0f}",
"\u{5f52}\u{6863}\u{5f53}\u{524d}\u{5bf9}\u{8bdd}",
t,
));
lines.push(Line::from(""));
lines.push(separator_line(area.width, t));
lines.push(Line::from(""));
lines.push(Line::from(Span::styled(
" \u{5373}\u{5c06}\u{5f52}\u{6863}\u{5f53}\u{524d}\u{5bf9}\u{8bdd}\u{ff0c}\u{5f52}\u{6863}\u{540e}\u{5f53}\u{524d}\u{4f1a}\u{8bdd}\u{5c06}\u{88ab}\u{6e05}\u{7a7a}\u{3002}",
Style::default().fg(t.text_dim),
)));
lines.push(Line::from(""));
if app.ui.archive_editing_name {
lines.push(Line::from(Span::styled(
" \u{8bf7}\u{8f93}\u{5165}\u{5f52}\u{6863}\u{540d}\u{79f0}\u{ff1a}",
Style::default().fg(t.text_white),
)));
lines.push(Line::from(""));
let value_style = Style::default().fg(t.text_white);
let name_with_cursor = if app.ui.archive_custom_name.is_empty() {
vec![Span::styled(
" ",
Style::default().fg(t.cursor_fg).bg(t.cursor_bg),
)]
} else {
cursor_spans(
&app.ui.archive_custom_name,
app.ui.archive_edit_cursor,
value_style,
t,
)
.into_iter()
.filter(|s| s.content != " \u{270f}\u{fe0f}") .collect()
};
lines.push(Line::from(vec![
Span::styled(" ", Style::default()),
Span::styled(
format!("archive-{}", chrono::Local::now().format("%Y-%m-%d")),
Style::default().fg(t.text_dim),
),
]));
lines.push(Line::from(
std::iter::once(Span::styled(" ", Style::default()))
.chain(name_with_cursor)
.collect::<Vec<_>>(),
));
lines.push(Line::from(""));
lines.push(Line::from(Span::styled(
" \u{63d0}\u{793a}\u{ff1a}\u{7559}\u{7a7a}\u{5219}\u{4f7f}\u{7528}\u{9ed8}\u{8ba4}\u{540d}\u{79f0}\u{ff08}\u{5982} archive-2026-02-25\u{ff09}",
Style::default().fg(t.text_dim),
)));
lines.push(Line::from(""));
lines.push(separator_line(area.width, t));
lines.push(Line::from(""));
lines.push(help_key_row(
"Enter",
"\u{786e}\u{8ba4}\u{5f52}\u{6863}",
7,
t,
));
lines.push(help_key_row("Esc", "\u{53d6}\u{6d88}", 7, t));
} else {
lines.push(Line::from(vec![
Span::styled(
" \u{9ed8}\u{8ba4}\u{540d}\u{79f0}\u{ff1a}",
Style::default().fg(t.text_dim),
),
Span::styled(
&app.ui.archive_default_name,
Style::default()
.fg(t.config_toggle_on)
.add_modifier(Modifier::BOLD),
),
]));
lines.push(Line::from(""));
lines.push(separator_line(area.width, t));
lines.push(Line::from(""));
lines.push(help_key_row(
"Enter",
"\u{4f7f}\u{7528}\u{9ed8}\u{8ba4}\u{540d}\u{79f0}\u{5f52}\u{6863}",
7,
t,
));
lines.push(help_key_row(
"n",
"\u{81ea}\u{5b9a}\u{4e49}\u{540d}\u{79f0}",
7,
t,
));
lines.push(help_key_row(
"d",
"\u{4ec5}\u{6e05}\u{7a7a}\u{4e0d}\u{5f52}\u{6863}",
7,
t,
));
lines.push(help_key_row("Esc", "\u{53d6}\u{6d88}", 7, t));
}
let block = Block::default()
.borders(Borders::ALL)
.border_type(ratatui::widgets::BorderType::Rounded)
.border_style(Style::default().fg(t.border_title))
.title(Span::styled(
" \u{5f52}\u{6863}\u{786e}\u{8ba4} ",
Style::default().fg(t.text_dim),
))
.style(Style::default().bg(t.help_bg));
let widget = Paragraph::new(lines).block(block);
f.render_widget(widget, area);
}
#[allow(clippy::vec_init_then_push)]
pub fn draw_archive_list(f: &mut ratatui::Frame, area: Rect, app: &ChatApp) {
let t = &app.ui.theme;
if app.ui.restore_confirm_needed {
let mut lines: Vec<Line> = Vec::new();
lines.push(Line::from(""));
lines.push(section_header(
"\u{26a0}\u{fe0f}",
"\u{786e}\u{8ba4}\u{8fd8}\u{539f}",
t,
));
lines.push(Line::from(""));
lines.push(Line::from(Span::styled(
" \u{5f53}\u{524d}\u{5bf9}\u{8bdd}\u{672a}\u{5f52}\u{6863}\u{ff0c}\u{8fd8}\u{539f}\u{5c06}\u{4e22}\u{5931}\u{5f53}\u{524d}\u{5bf9}\u{8bdd}\u{5185}\u{5bb9}\u{ff01}",
Style::default().fg(t.text_white),
)));
lines.push(Line::from(""));
lines.push(separator_line(area.width, t));
lines.push(Line::from(""));
if let Some(archive) = app.ui.archives.get(app.ui.archive_list_index) {
lines.push(Line::from(vec![
Span::styled(
" \u{5c06}\u{8fd8}\u{539f}\u{5f52}\u{6863}\u{ff1a}",
Style::default().fg(t.text_dim),
),
Span::styled(
&archive.name,
Style::default()
.fg(t.config_toggle_on)
.add_modifier(Modifier::BOLD),
),
]));
}
lines.push(Line::from(""));
lines.push(help_key_row(
"y/Enter",
"\u{786e}\u{8ba4}\u{8fd8}\u{539f}",
8,
t,
));
lines.push(help_key_row("Esc", "\u{53d6}\u{6d88}", 8, t));
let block = Block::default()
.borders(Borders::ALL)
.border_type(ratatui::widgets::BorderType::Rounded)
.border_style(Style::default().fg(t.toast_error_border))
.title(Span::styled(
" \u{8fd8}\u{539f}\u{786e}\u{8ba4} ",
Style::default().fg(t.text_dim),
))
.style(Style::default().bg(t.help_bg));
let widget = Paragraph::new(lines).block(block);
f.render_widget(widget, area);
return;
}
if app.ui.archives.is_empty() {
let lines = vec![
Line::from(""),
Line::from(""),
Line::from(Span::styled(
" \u{1f4e6} \u{6682}\u{65e0}\u{5f52}\u{6863}\u{5bf9}\u{8bdd}",
Style::default().fg(t.text_dim).add_modifier(Modifier::BOLD),
)),
Line::from(""),
Line::from(Span::styled(
" \u{6309} Ctrl+L \u{5f52}\u{6863}\u{5f53}\u{524d}\u{5bf9}\u{8bdd}",
Style::default().fg(t.text_dim),
)),
Line::from(""),
Line::from(Span::styled(
" \u{6309} Esc \u{8fd4}\u{56de}\u{804a}\u{5929}",
Style::default().fg(t.text_dim),
)),
];
let block = Block::default()
.borders(Borders::ALL)
.border_type(ratatui::widgets::BorderType::Rounded)
.border_style(Style::default().fg(t.border_title))
.title(Span::styled(
" \u{5f52}\u{6863}\u{5217}\u{8868} ",
Style::default().fg(t.text_dim),
))
.style(Style::default().bg(t.help_bg));
let widget = Paragraph::new(lines).block(block);
f.render_widget(widget, area);
return;
}
let items: Vec<ListItem> = app
.ui
.archives
.iter()
.enumerate()
.map(|(i, archive)| {
let is_selected = i == app.ui.archive_list_index;
let marker = if is_selected {
super::components::POINTER_SELECTED
} else {
super::components::POINTER_EMPTY
};
let msg_count = archive.messages.len();
let created_at = archive
.created_at
.split('T')
.next()
.unwrap_or(&archive.created_at);
let style = if is_selected {
Style::default()
.fg(t.model_sel_active)
.add_modifier(Modifier::BOLD)
} else {
Style::default().fg(t.model_sel_inactive)
};
let detail = format!(
"{}{} \u{1f4e8} {} \u{6761}\u{6d88}\u{606f} \u{1f4c5} {}",
marker, archive.name, msg_count, created_at
);
ListItem::new(Line::from(Span::styled(detail, style)))
})
.collect();
let list = List::new(items)
.block(
Block::default()
.borders(Borders::ALL)
.border_type(ratatui::widgets::BorderType::Rounded)
.border_style(Style::default().fg(t.model_sel_border))
.title(Span::styled(
" \u{1f4e6} \u{5f52}\u{6863}\u{5217}\u{8868} (Enter \u{8fd8}\u{539f}, d \u{5220}\u{9664}, Esc \u{8fd4}\u{56de}) ",
Style::default()
.fg(t.model_sel_title)
.add_modifier(Modifier::BOLD),
))
.style(Style::default().bg(t.bg_title)),
)
.highlight_style(
Style::default()
.bg(t.model_sel_highlight_bg)
.fg(t.text_white)
.add_modifier(Modifier::BOLD),
)
.highlight_symbol("");
let mut list_state = ListState::default();
list_state.select(Some(app.ui.archive_list_index));
f.render_stateful_widget(list, area, &mut list_state);
}