diff --git a/src/ui/messages.rs b/src/ui/messages.rs index be1ce67..bad2900 100644 --- a/src/ui/messages.rs +++ b/src/ui/messages.rs @@ -10,6 +10,84 @@ use ratatui::{ Frame, }; +/// Рендерит заголовок чата с typing status +fn render_chat_header(f: &mut Frame, area: Rect, app: &App, 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(f: &mut Frame, area: Rect, app: &App) { + 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(f: &mut Frame, area: Rect, app: &App) { }; // 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;