//! Message search modal use crate::app::App; use crate::tdlib::TdClientTrait; use crate::ui::components::{calculate_scroll_offset, render_help_bar, render_message_item}; use ratatui::{ layout::{Constraint, Direction, Layout, Rect}, style::{Color, Modifier, Style}, text::{Line, Span}, widgets::{Block, Borders, Paragraph}, Frame, }; /// Renders message search mode pub fn render(f: &mut Frame, area: Rect, app: &App) { // Извлекаем данные из ChatState let (query, results, selected_index) = if let crate::app::ChatState::SearchInChat { query, results, selected_index } = &app.chat_state { (query.as_str(), results.as_slice(), *selected_index) } else { return; // Некорректное состояние, не рендерим }; let chunks = Layout::default() .direction(Direction::Vertical) .constraints([ Constraint::Length(3), // Search input Constraint::Min(0), // Search results Constraint::Length(3), // Help bar ]) .split(area); // Search input let total = results.len(); let current = if total > 0 { selected_index + 1 } else { 0 }; let input_line = if query.is_empty() { Line::from(vec![ Span::styled("🔍 ", Style::default().fg(Color::Yellow)), Span::styled("█", Style::default().fg(Color::Yellow)), Span::styled(" Введите текст для поиска...", Style::default().fg(Color::Gray)), ]) } else { Line::from(vec![ Span::styled("🔍 ", Style::default().fg(Color::Yellow)), Span::styled(query, Style::default().fg(Color::White)), Span::styled("█", Style::default().fg(Color::Yellow)), Span::styled(format!(" ({}/{})", current, total), Style::default().fg(Color::Gray)), ]) }; let search_input = Paragraph::new(input_line).block( Block::default() .borders(Borders::ALL) .border_style(Style::default().fg(Color::Yellow)) .title(" Поиск по сообщениям ") .title_style( Style::default() .fg(Color::Yellow) .add_modifier(Modifier::BOLD), ), ); f.render_widget(search_input, chunks[0]); // Search results let content_width = chunks[1].width.saturating_sub(2) as usize; let mut lines: Vec = Vec::new(); if results.is_empty() { if !query.is_empty() { lines.push(Line::from(Span::styled( "Ничего не найдено", Style::default().fg(Color::Gray), ))); } } else { for (idx, msg) in results.iter().enumerate() { if idx > 0 { lines.push(Line::from("")); } lines.extend(render_message_item(msg, idx == selected_index, content_width, 2)); } } // Скролл к выбранному результату let scroll_offset = calculate_scroll_offset(selected_index, 4, chunks[1].height); let results_widget = Paragraph::new(lines) .block( Block::default() .borders(Borders::ALL) .border_style(Style::default().fg(Color::Yellow)), ) .scroll((scroll_offset, 0)); f.render_widget(results_widget, chunks[1]); // Help bar let help = render_help_bar( &[ ("↑↓", "навигация", Color::Yellow), ("n/N", "след./пред.", Color::Yellow), ("Enter", "перейти", Color::Green), ("Esc", "выход", Color::Red), ], Color::Yellow, ); f.render_widget(help, chunks[2]); }