Files
telegram-tui/src/ui/components/emoji_picker.rs
Mikhail Kilin d4e1ed1376
Some checks failed
ci/woodpecker/pr/check Pipeline failed
CI / Check (pull_request) Has been cancelled
CI / Format (pull_request) Has been cancelled
CI / Clippy (pull_request) Has been cancelled
CI / Build (macos-latest) (pull_request) Has been cancelled
CI / Build (ubuntu-latest) (pull_request) Has been cancelled
CI / Build (windows-latest) (pull_request) Has been cancelled
fix: resolve all 23 clippy warnings
2026-02-22 17:28:50 +03:00

105 lines
3.6 KiB
Rust

use ratatui::{
layout::{Alignment, Rect},
style::{Color, Modifier, Style},
text::{Line, Span},
widgets::{Block, Borders, Clear, Paragraph},
Frame,
};
/// Рендерит модалку выбора реакций (emoji picker)
///
/// # Параметры
/// - `f`: Frame для рендеринга
/// - `area`: Область экрана
/// - `available_reactions`: Список доступных эмодзи
/// - `selected_index`: Индекс выбранного эмодзи
pub fn render_emoji_picker(
f: &mut Frame,
area: Rect,
available_reactions: &[String],
selected_index: usize,
) {
// Размеры модалки (зависят от количества реакций)
let emojis_per_row = 8;
let rows = available_reactions.len().div_ceil(emojis_per_row);
let modal_width = 50u16;
let modal_height = (rows + 4) as u16; // +4 для заголовка, отступов и подсказки
// Центрируем модалку
let x = area.x + (area.width.saturating_sub(modal_width)) / 2;
let y = area.y + (area.height.saturating_sub(modal_height)) / 2;
let modal_area = Rect::new(x, y, modal_width.min(area.width), modal_height.min(area.height));
// Очищаем область под модалкой
f.render_widget(Clear, modal_area);
// Формируем содержимое - сетка эмодзи
let mut text_lines = vec![Line::from("")]; // Пустая строка сверху
for row in 0..rows {
let mut row_spans = vec![Span::raw(" ")]; // Отступ слева
for col in 0..emojis_per_row {
let idx = row * emojis_per_row + col;
if idx >= available_reactions.len() {
break;
}
let emoji = &available_reactions[idx];
let is_selected = idx == selected_index;
let style = if is_selected {
Style::default()
.fg(Color::Yellow)
.add_modifier(Modifier::BOLD)
.add_modifier(Modifier::REVERSED)
} else {
Style::default().fg(Color::White)
};
row_spans.push(Span::styled(format!(" {} ", emoji), style));
row_spans.push(Span::raw(" ")); // Пробел между эмодзи
}
text_lines.push(Line::from(row_spans));
}
// Добавляем пустую строку и подсказку
text_lines.push(Line::from(""));
text_lines.push(Line::from(vec![
Span::styled(
" [←/→/↑/↓] ",
Style::default()
.fg(Color::Cyan)
.add_modifier(Modifier::BOLD),
),
Span::raw("Выбор "),
Span::styled(
" [Enter] ",
Style::default()
.fg(Color::Green)
.add_modifier(Modifier::BOLD),
),
Span::raw("Добавить "),
Span::styled(" [Esc] ", Style::default().fg(Color::Red).add_modifier(Modifier::BOLD)),
Span::raw("Отмена"),
]));
let modal = Paragraph::new(text_lines)
.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),
),
)
.alignment(Alignment::Center);
f.render_widget(modal, modal_area);
}