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,
|
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(
|
fn render_input_with_cursor(
|
||||||
prefix: &str,
|
prefix: &str,
|
||||||
text: &str,
|
text: &str,
|
||||||
@@ -173,72 +251,10 @@ pub fn render<T: TdClientTrait>(f: &mut Frame, area: Rect, app: &App<T>) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Chat header с typing status
|
// Chat header с typing status
|
||||||
let typing_action = app
|
render_chat_header(f, message_chunks[0], app, chat);
|
||||||
.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]);
|
|
||||||
|
|
||||||
// Pinned bar (если есть закреплённое сообщение)
|
// Pinned bar (если есть закреплённое сообщение)
|
||||||
if let Some(pinned_msg) = app.td_client.current_pinned_message() {
|
render_pinned_bar(f, message_chunks[1], app);
|
||||||
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]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ширина области сообщений (без рамок)
|
// Ширина области сообщений (без рамок)
|
||||||
let content_width = message_chunks[2].width.saturating_sub(2) as usize;
|
let content_width = message_chunks[2].width.saturating_sub(2) as usize;
|
||||||
|
|||||||
Reference in New Issue
Block a user