fixes
This commit is contained in:
113
src/app/mod.rs
113
src/app/mod.rs
@@ -3,7 +3,7 @@ mod state;
|
||||
pub use state::AppScreen;
|
||||
|
||||
use ratatui::widgets::ListState;
|
||||
use crate::tdlib::client::{ChatInfo, MessageInfo};
|
||||
use crate::tdlib::client::ChatInfo;
|
||||
use crate::tdlib::TdClient;
|
||||
|
||||
pub struct App {
|
||||
@@ -19,8 +19,9 @@ pub struct App {
|
||||
pub chats: Vec<ChatInfo>,
|
||||
pub chat_list_state: ListState,
|
||||
pub selected_chat_id: Option<i64>,
|
||||
pub current_messages: Vec<MessageInfo>,
|
||||
pub message_input: String,
|
||||
/// Позиция курсора в message_input (в символах)
|
||||
pub cursor_position: usize,
|
||||
pub message_scroll_offset: usize,
|
||||
/// None = All (основной список), Some(id) = папка с id
|
||||
pub selected_folder_id: Option<i32>,
|
||||
@@ -30,6 +31,14 @@ pub struct App {
|
||||
pub search_query: String,
|
||||
/// Флаг для оптимизации рендеринга - перерисовывать только при изменениях
|
||||
pub needs_redraw: bool,
|
||||
// Edit message state
|
||||
/// ID сообщения, которое редактируется (None = режим отправки нового)
|
||||
pub editing_message_id: Option<i64>,
|
||||
/// Индекс выбранного сообщения для навигации (снизу вверх, 0 = последнее)
|
||||
pub selected_message_index: Option<usize>,
|
||||
// Delete confirmation
|
||||
/// ID сообщения для подтверждения удаления (показывает модалку)
|
||||
pub confirm_delete_message_id: Option<i64>,
|
||||
}
|
||||
|
||||
impl App {
|
||||
@@ -48,22 +57,20 @@ impl App {
|
||||
chats: Vec::new(),
|
||||
chat_list_state: state,
|
||||
selected_chat_id: None,
|
||||
current_messages: Vec::new(),
|
||||
message_input: String::new(),
|
||||
cursor_position: 0,
|
||||
message_scroll_offset: 0,
|
||||
selected_folder_id: None, // None = All
|
||||
is_loading: true,
|
||||
is_searching: false,
|
||||
search_query: String::new(),
|
||||
needs_redraw: true,
|
||||
editing_message_id: None,
|
||||
selected_message_index: None,
|
||||
confirm_delete_message_id: None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Помечает UI как требующий перерисовки
|
||||
pub fn mark_dirty(&mut self) {
|
||||
self.needs_redraw = true;
|
||||
}
|
||||
|
||||
pub fn next_chat(&mut self) {
|
||||
let filtered = self.get_filtered_chats();
|
||||
if filtered.is_empty() {
|
||||
@@ -111,18 +118,95 @@ impl App {
|
||||
|
||||
pub fn close_chat(&mut self) {
|
||||
self.selected_chat_id = None;
|
||||
self.current_messages.clear();
|
||||
self.message_input.clear();
|
||||
self.cursor_position = 0;
|
||||
self.message_scroll_offset = 0;
|
||||
self.editing_message_id = None;
|
||||
self.selected_message_index = None;
|
||||
// Очищаем данные в TdClient
|
||||
self.td_client.current_chat_id = None;
|
||||
self.td_client.current_chat_messages.clear();
|
||||
}
|
||||
|
||||
pub fn select_first_chat(&mut self) {
|
||||
if !self.chats.is_empty() {
|
||||
self.chat_list_state.select(Some(0));
|
||||
/// Начать выбор сообщения для редактирования (при стрелке вверх в пустом инпуте)
|
||||
pub fn start_message_selection(&mut self) {
|
||||
if self.td_client.current_chat_messages.is_empty() {
|
||||
return;
|
||||
}
|
||||
// Начинаем с последнего сообщения (индекс 0 = самое новое снизу)
|
||||
self.selected_message_index = Some(0);
|
||||
}
|
||||
|
||||
/// Выбрать предыдущее сообщение (вверх по списку = увеличить индекс)
|
||||
pub fn select_previous_message(&mut self) {
|
||||
let total = self.td_client.current_chat_messages.len();
|
||||
if total == 0 {
|
||||
return;
|
||||
}
|
||||
self.selected_message_index = Some(
|
||||
self.selected_message_index
|
||||
.map(|i| (i + 1).min(total - 1))
|
||||
.unwrap_or(0)
|
||||
);
|
||||
}
|
||||
|
||||
/// Выбрать следующее сообщение (вниз по списку = уменьшить индекс)
|
||||
pub fn select_next_message(&mut self) {
|
||||
self.selected_message_index = self.selected_message_index
|
||||
.map(|i| if i > 0 { Some(i - 1) } else { None })
|
||||
.flatten();
|
||||
}
|
||||
|
||||
/// Получить выбранное сообщение
|
||||
pub fn get_selected_message(&self) -> Option<&crate::tdlib::client::MessageInfo> {
|
||||
self.selected_message_index.and_then(|idx| {
|
||||
let total = self.td_client.current_chat_messages.len();
|
||||
if total == 0 || idx >= total {
|
||||
return None;
|
||||
}
|
||||
// idx=0 это последнее сообщение (total-1), idx=1 это предпоследнее (total-2), и т.д.
|
||||
self.td_client.current_chat_messages.get(total - 1 - idx)
|
||||
})
|
||||
}
|
||||
|
||||
/// Начать редактирование выбранного сообщения
|
||||
pub fn start_editing_selected(&mut self) -> bool {
|
||||
// Сначала извлекаем данные из сообщения
|
||||
let msg_data = self.get_selected_message().and_then(|msg| {
|
||||
if msg.can_be_edited && msg.is_outgoing {
|
||||
Some((msg.id, msg.content.clone()))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
});
|
||||
|
||||
// Затем присваиваем
|
||||
if let Some((id, content)) = msg_data {
|
||||
self.editing_message_id = Some(id);
|
||||
self.cursor_position = content.chars().count();
|
||||
self.message_input = content;
|
||||
self.selected_message_index = None;
|
||||
return true;
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
/// Отменить редактирование
|
||||
pub fn cancel_editing(&mut self) {
|
||||
self.editing_message_id = None;
|
||||
self.selected_message_index = None;
|
||||
self.message_input.clear();
|
||||
self.cursor_position = 0;
|
||||
}
|
||||
|
||||
/// Проверить, находимся ли в режиме редактирования
|
||||
pub fn is_editing(&self) -> bool {
|
||||
self.editing_message_id.is_some()
|
||||
}
|
||||
|
||||
/// Проверить, находимся ли в режиме выбора сообщения
|
||||
pub fn is_selecting_message(&self) -> bool {
|
||||
self.selected_message_index.is_some()
|
||||
}
|
||||
|
||||
pub fn get_selected_chat_id(&self) -> Option<i64> {
|
||||
@@ -217,4 +301,9 @@ impl App {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Проверить, показывается ли модалка подтверждения удаления
|
||||
pub fn is_confirm_delete_shown(&self) -> bool {
|
||||
self.confirm_delete_message_id.is_some()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user