use ratatui::{ layout::{Constraint, Direction, Layout, Rect}, style::{Color, Modifier, Style}, widgets::{Block, Borders, List, ListItem, Paragraph}, Frame, }; use crate::app::App; use crate::tdlib::UserOnlineStatus; pub fn render(f: &mut Frame, area: Rect, app: &mut App) { let chat_chunks = Layout::default() .direction(Direction::Vertical) .constraints([ Constraint::Length(3), // Search box Constraint::Min(0), // Chat list Constraint::Length(3), // User status ]) .split(area); // Search box let search_text = if app.is_searching { if app.search_query.is_empty() { "🔍 Введите для поиска...".to_string() } else { format!("🔍 {}", app.search_query) } } else { "🔍 Ctrl+S для поиска".to_string() }; let search_style = if app.is_searching { Style::default().fg(Color::Yellow) } else { Style::default().fg(Color::DarkGray) }; let search = Paragraph::new(search_text) .block(Block::default().borders(Borders::ALL)) .style(search_style); f.render_widget(search, chat_chunks[0]); // Chat list (filtered if searching) let filtered_chats = app.get_filtered_chats(); let items: Vec = filtered_chats .iter() .map(|chat| { let is_selected = app.selected_chat_id == Some(chat.id); let pin_icon = if chat.is_pinned { "📌 " } else { "" }; let mute_icon = if chat.is_muted { "🔇 " } else { "" }; // Онлайн-статус (зелёная точка для онлайн) let status_icon = match app.td_client.get_user_status_by_chat_id(chat.id) { Some(UserOnlineStatus::Online) => "● ", _ => " ", }; let prefix = if is_selected { "▌" } else { " " }; let username_text = chat.username.as_ref() .map(|u| format!(" {}", u)) .unwrap_or_default(); // Индикатор упоминаний @ let mention_badge = if chat.unread_mention_count > 0 { " @".to_string() } else { String::new() }; // Индикатор черновика ✎ let draft_badge = if chat.draft_text.is_some() { " ✎".to_string() } else { String::new() }; let unread_badge = if chat.unread_count > 0 { format!(" ({})", chat.unread_count) } else { String::new() }; let content = format!("{}{}{}{}{}{}{}{}{}", prefix, status_icon, pin_icon, mute_icon, chat.title, username_text, mention_badge, draft_badge, unread_badge); // Цвет: онлайн — зелёные, остальные — белые let style = match app.td_client.get_user_status_by_chat_id(chat.id) { Some(UserOnlineStatus::Online) => Style::default().fg(Color::Green), _ => Style::default().fg(Color::White), }; ListItem::new(content).style(style) }) .collect(); // Заголовок блока: обычный или режим пересылки let block = if app.is_forwarding() { Block::default() .title(" ↪ Выберите чат ") .borders(Borders::ALL) .border_style(Style::default().fg(Color::Cyan)) } else { Block::default().borders(Borders::ALL) }; let chats_list = List::new(items) .block(block) .highlight_style( Style::default() .add_modifier(Modifier::ITALIC) .fg(Color::Yellow), ); f.render_stateful_widget(chats_list, chat_chunks[1], &mut app.chat_list_state); // User status - показываем статус выбранного чата let (status_text, status_color) = if let Some(chat_id) = app.selected_chat_id { match app.td_client.get_user_status_by_chat_id(chat_id) { Some(UserOnlineStatus::Online) => ("● онлайн".to_string(), Color::Green), Some(UserOnlineStatus::Recently) => ("был(а) недавно".to_string(), Color::Yellow), Some(UserOnlineStatus::Offline(was_online)) => { let formatted = format_was_online(*was_online); (formatted, Color::Gray) } Some(UserOnlineStatus::LastWeek) => ("был(а) на этой неделе".to_string(), Color::DarkGray), Some(UserOnlineStatus::LastMonth) => ("был(а) в этом месяце".to_string(), Color::DarkGray), Some(UserOnlineStatus::LongTimeAgo) => ("был(а) давно".to_string(), Color::DarkGray), None => ("".to_string(), Color::DarkGray), // Для групп/каналов } } else { // Показываем статус выделенного в списке чата let filtered = app.get_filtered_chats(); if let Some(i) = app.chat_list_state.selected() { if let Some(chat) = filtered.get(i) { match app.td_client.get_user_status_by_chat_id(chat.id) { Some(UserOnlineStatus::Online) => ("● онлайн".to_string(), Color::Green), Some(UserOnlineStatus::Recently) => ("был(а) недавно".to_string(), Color::Yellow), Some(UserOnlineStatus::Offline(was_online)) => { let formatted = format_was_online(*was_online); (formatted, Color::Gray) } Some(UserOnlineStatus::LastWeek) => ("был(а) на этой неделе".to_string(), Color::DarkGray), Some(UserOnlineStatus::LastMonth) => ("был(а) в этом месяце".to_string(), Color::DarkGray), Some(UserOnlineStatus::LongTimeAgo) => ("был(а) давно".to_string(), Color::DarkGray), None => ("".to_string(), Color::DarkGray), } } else { ("".to_string(), Color::DarkGray) } } else { ("".to_string(), Color::DarkGray) } }; let status = Paragraph::new(status_text) .block(Block::default().borders(Borders::ALL)) .style(Style::default().fg(status_color)); f.render_widget(status, chat_chunks[2]); } /// Форматирование времени "был(а) в ..." fn format_was_online(timestamp: i32) -> String { crate::utils::format_was_online(timestamp) }