Files
telegram-tui/src/app/methods/messages.rs
2026-05-17 18:41:52 +03:00

176 lines
6.7 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//! Message methods for App
//!
//! Handles message selection, editing, and operations
use crate::app::{App, ChatState};
use crate::tdlib::{MessageInfo, TdClientTrait};
/// Message operation methods
pub trait MessageMethods<T: TdClientTrait> {
/// Start message selection mode (triggered by Up arrow in empty input)
fn start_message_selection(&mut self);
/// Select previous message (up in history = older)
fn select_previous_message(&mut self);
/// Select next message (down in history = newer)
fn select_next_message(&mut self);
/// Get currently selected message
fn get_selected_message(&self) -> Option<MessageInfo>;
/// Start editing the selected message
/// Returns true if editing started, false if message cannot be edited
fn start_editing_selected(&mut self) -> bool;
/// Cancel message editing and clear input
fn cancel_editing(&mut self);
/// Check if currently in editing mode
fn is_editing(&self) -> bool;
/// Check if currently in message selection mode
fn is_selecting_message(&self) -> bool;
}
impl<T: TdClientTrait> MessageMethods<T> for App<T> {
fn start_message_selection(&mut self) {
let messages = self.td_client.current_chat_messages();
let total = messages.len();
if total == 0 {
return;
}
// Начинаем с последнего сообщения (индекс len-1 = самое новое внизу)
// Если оно часть альбома — перемещаемся к первому элементу альбома
let mut idx = total - 1;
let album_id = messages[idx].media_album_id();
if album_id != 0 {
while idx > 0 && messages[idx - 1].media_album_id() == album_id {
idx -= 1;
}
}
self.chat_state = ChatState::MessageSelection { selected_index: idx };
}
fn select_previous_message(&mut self) {
if let ChatState::MessageSelection { selected_index } = &mut self.chat_state {
if *selected_index > 0 {
let messages = self.td_client.current_chat_messages();
let current_album_id = messages[*selected_index].media_album_id();
// Перескакиваем через все сообщения текущего альбома назад
let mut new_index = *selected_index - 1;
if current_album_id != 0 {
while new_index > 0 && messages[new_index].media_album_id() == current_album_id
{
new_index -= 1;
}
}
// Если попали в середину другого альбома — перемещаемся к его первому элементу
let target_album_id = messages[new_index].media_album_id();
if target_album_id != 0 {
while new_index > 0
&& messages[new_index - 1].media_album_id() == target_album_id
{
new_index -= 1;
}
}
*selected_index = new_index;
self.stop_playback();
}
}
}
fn select_next_message(&mut self) {
let total = self.td_client.current_chat_messages().len();
if total == 0 {
return;
}
if let ChatState::MessageSelection { selected_index } = &mut self.chat_state {
if *selected_index < total - 1 {
let messages = self.td_client.current_chat_messages();
let current_album_id = messages[*selected_index].media_album_id();
// Перескакиваем через все сообщения текущего альбома вперёд
let mut new_index = *selected_index + 1;
if current_album_id != 0 {
while new_index < total - 1
&& messages[new_index].media_album_id() == current_album_id
{
new_index += 1;
}
// Если мы ещё на последнем элементе альбома — нужно шагнуть на следующее
if messages[new_index].media_album_id() == current_album_id
&& new_index < total - 1
{
new_index += 1;
}
}
if new_index < total {
*selected_index = new_index;
self.stop_playback();
}
// Если new_index >= total — остаёмся на текущем
}
// Если уже на последнем — ничего не делаем, остаёмся на месте
}
}
fn get_selected_message(&self) -> Option<MessageInfo> {
self.chat_state
.selected_message_index()
.and_then(|idx| self.td_client.current_chat_messages().get(idx).cloned())
}
fn start_editing_selected(&mut self) -> bool {
// Получаем selected_index из текущего состояния
let selected_idx = match &self.chat_state {
ChatState::MessageSelection { selected_index } => Some(*selected_index),
_ => None,
};
let Some(selected_idx) = selected_idx else {
return false;
};
// Сначала извлекаем данные из сообщения
let msg_data = self.get_selected_message().and_then(|msg| {
// Проверяем:
// 1. Можно редактировать
// 2. Это исходящее сообщение
// 3. ID не временный (временные ID в TDLib отрицательные)
if msg.can_be_edited() && msg.is_outgoing() && msg.id().as_i64() > 0 {
Some((msg.id(), msg.text().to_string(), selected_idx))
} else {
None
}
});
// Затем присваиваем
if let Some((id, content, idx)) = msg_data {
self.cursor_position = content.chars().count();
self.message_input = content;
self.chat_state = ChatState::Editing { message_id: id, selected_index: idx };
return true;
}
false
}
fn cancel_editing(&mut self) {
self.chat_state = ChatState::Normal;
self.message_input.clear();
self.cursor_position = 0;
}
fn is_editing(&self) -> bool {
self.chat_state.is_editing()
}
fn is_selecting_message(&self) -> bool {
self.chat_state.is_message_selection()
}
}