refactor: extract header and pinned bar rendering (ui/messages.rs)
Извлечены функции из render() (Phase 5 начало): - render_chat_header() - заголовок чата с typing status (~50 строк) - render_pinned_bar() - панель закреплённого сообщения (~30 строк) Результат: - Главная функция render() сокращена на ~65 строк - Применены let-else guards для упрощения - Каждая функция имеет чёткую ответственность Phase 5: Рефакторинг ui/messages.rs (879 строк) Цель: разделить монолитную функцию render() на модули Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -10,6 +10,84 @@ use ratatui::{
|
||||
Frame,
|
||||
};
|
||||
|
||||
/// Рендерит заголовок чата с typing status
|
||||
fn render_chat_header<T: TdClientTrait>(f: &mut Frame, area: Rect, app: &App<T>, chat: &crate::tdlib::ChatInfo) {
|
||||
let typing_action = app
|
||||
.td_client
|
||||
.typing_status()
|
||||
.as_ref()
|
||||
.map(|(_, action, _)| action.clone());
|
||||
|
||||
let header_line = if let Some(action) = typing_action {
|
||||
// Показываем typing status: "👤 Имя @username печатает..."
|
||||
let mut spans = vec![Span::styled(
|
||||
format!("👤 {}", chat.title),
|
||||
Style::default()
|
||||
.fg(Color::Cyan)
|
||||
.add_modifier(Modifier::BOLD),
|
||||
)];
|
||||
if let Some(username) = &chat.username {
|
||||
spans.push(Span::styled(
|
||||
format!(" {}", username),
|
||||
Style::default().fg(Color::Gray),
|
||||
));
|
||||
}
|
||||
spans.push(Span::styled(
|
||||
format!(" {}", action),
|
||||
Style::default()
|
||||
.fg(Color::Yellow)
|
||||
.add_modifier(Modifier::ITALIC),
|
||||
));
|
||||
Line::from(spans)
|
||||
} else {
|
||||
// Показываем username
|
||||
let header_text = match &chat.username {
|
||||
Some(username) => format!("👤 {} {}", chat.title, username),
|
||||
None => format!("👤 {}", chat.title),
|
||||
};
|
||||
Line::from(Span::styled(
|
||||
header_text,
|
||||
Style::default()
|
||||
.fg(Color::Cyan)
|
||||
.add_modifier(Modifier::BOLD),
|
||||
))
|
||||
};
|
||||
|
||||
let header = Paragraph::new(header_line).block(Block::default().borders(Borders::ALL));
|
||||
f.render_widget(header, area);
|
||||
}
|
||||
|
||||
/// Рендерит pinned bar с закреплённым сообщением
|
||||
fn render_pinned_bar<T: TdClientTrait>(f: &mut Frame, area: Rect, app: &App<T>) {
|
||||
let Some(pinned_msg) = app.td_client.current_pinned_message() else {
|
||||
return;
|
||||
};
|
||||
|
||||
let pinned_preview: String = pinned_msg.text().chars().take(40).collect();
|
||||
let ellipsis = if pinned_msg.text().chars().count() > 40 {
|
||||
"..."
|
||||
} else {
|
||||
""
|
||||
};
|
||||
let pinned_datetime = crate::utils::format_datetime(pinned_msg.date());
|
||||
let pinned_text = format!("📌 {} {}{}", pinned_datetime, pinned_preview, ellipsis);
|
||||
let pinned_hint = "Ctrl+P";
|
||||
|
||||
let pinned_bar_width = area.width as usize;
|
||||
let text_len = pinned_text.chars().count();
|
||||
let hint_len = pinned_hint.chars().count();
|
||||
let padding = pinned_bar_width.saturating_sub(text_len + hint_len + 2);
|
||||
|
||||
let pinned_line = Line::from(vec![
|
||||
Span::styled(pinned_text, Style::default().fg(Color::Magenta)),
|
||||
Span::raw(" ".repeat(padding)),
|
||||
Span::styled(pinned_hint, Style::default().fg(Color::Gray)),
|
||||
]);
|
||||
let pinned_bar =
|
||||
Paragraph::new(pinned_line).style(Style::default().bg(Color::Rgb(40, 20, 40)));
|
||||
f.render_widget(pinned_bar, area);
|
||||
}
|
||||
|
||||
fn render_input_with_cursor(
|
||||
prefix: &str,
|
||||
text: &str,
|
||||
@@ -173,72 +251,10 @@ pub fn render<T: TdClientTrait>(f: &mut Frame, area: Rect, app: &App<T>) {
|
||||
};
|
||||
|
||||
// Chat header с typing status
|
||||
let typing_action = app
|
||||
.td_client
|
||||
.typing_status()
|
||||
.as_ref()
|
||||
.map(|(_, action, _)| action.clone());
|
||||
let header_line = if let Some(action) = typing_action {
|
||||
// Показываем typing status: "👤 Имя @username печатает..."
|
||||
let mut spans = vec![Span::styled(
|
||||
format!("👤 {}", chat.title),
|
||||
Style::default()
|
||||
.fg(Color::Cyan)
|
||||
.add_modifier(Modifier::BOLD),
|
||||
)];
|
||||
if let Some(username) = &chat.username {
|
||||
spans
|
||||
.push(Span::styled(format!(" {}", username), Style::default().fg(Color::Gray)));
|
||||
}
|
||||
spans.push(Span::styled(
|
||||
format!(" {}", action),
|
||||
Style::default()
|
||||
.fg(Color::Yellow)
|
||||
.add_modifier(Modifier::ITALIC),
|
||||
));
|
||||
Line::from(spans)
|
||||
} else {
|
||||
// Показываем username
|
||||
let header_text = match &chat.username {
|
||||
Some(username) => format!("👤 {} {}", chat.title, username),
|
||||
None => format!("👤 {}", chat.title),
|
||||
};
|
||||
Line::from(Span::styled(
|
||||
header_text,
|
||||
Style::default()
|
||||
.fg(Color::Cyan)
|
||||
.add_modifier(Modifier::BOLD),
|
||||
))
|
||||
};
|
||||
let header = Paragraph::new(header_line).block(Block::default().borders(Borders::ALL));
|
||||
f.render_widget(header, message_chunks[0]);
|
||||
render_chat_header(f, message_chunks[0], app, chat);
|
||||
|
||||
// Pinned bar (если есть закреплённое сообщение)
|
||||
if let Some(pinned_msg) = app.td_client.current_pinned_message() {
|
||||
let pinned_preview: String = pinned_msg.text().chars().take(40).collect();
|
||||
let ellipsis = if pinned_msg.text().chars().count() > 40 {
|
||||
"..."
|
||||
} else {
|
||||
""
|
||||
};
|
||||
let pinned_datetime = crate::utils::format_datetime(pinned_msg.date());
|
||||
let pinned_text = format!("📌 {} {}{}", pinned_datetime, pinned_preview, ellipsis);
|
||||
let pinned_hint = "Ctrl+P";
|
||||
|
||||
let pinned_bar_width = message_chunks[1].width as usize;
|
||||
let text_len = pinned_text.chars().count();
|
||||
let hint_len = pinned_hint.chars().count();
|
||||
let padding = pinned_bar_width.saturating_sub(text_len + hint_len + 2);
|
||||
|
||||
let pinned_line = Line::from(vec![
|
||||
Span::styled(pinned_text, Style::default().fg(Color::Magenta)),
|
||||
Span::raw(" ".repeat(padding)),
|
||||
Span::styled(pinned_hint, Style::default().fg(Color::Gray)),
|
||||
]);
|
||||
let pinned_bar =
|
||||
Paragraph::new(pinned_line).style(Style::default().bg(Color::Rgb(40, 20, 40)));
|
||||
f.render_widget(pinned_bar, message_chunks[1]);
|
||||
}
|
||||
render_pinned_bar(f, message_chunks[1], app);
|
||||
|
||||
// Ширина области сообщений (без рамок)
|
||||
let content_width = message_chunks[2].width.saturating_sub(2) as usize;
|
||||
|
||||
Reference in New Issue
Block a user