fixes
This commit is contained in:
70
src/main.rs
70
src/main.rs
@@ -65,6 +65,7 @@ struct App {
|
|||||||
chat_list_state: ListState,
|
chat_list_state: ListState,
|
||||||
selected_chat: Option<usize>,
|
selected_chat: Option<usize>,
|
||||||
current_messages: Vec<MessageInfo>,
|
current_messages: Vec<MessageInfo>,
|
||||||
|
message_input: String, // Input for new message
|
||||||
folders: Vec<String>,
|
folders: Vec<String>,
|
||||||
selected_folder: usize,
|
selected_folder: usize,
|
||||||
is_loading: bool,
|
is_loading: bool,
|
||||||
@@ -87,6 +88,7 @@ impl App {
|
|||||||
chat_list_state: state,
|
chat_list_state: state,
|
||||||
selected_chat: None,
|
selected_chat: None,
|
||||||
current_messages: Vec::new(),
|
current_messages: Vec::new(),
|
||||||
|
message_input: String::new(),
|
||||||
folders: vec!["All".to_string()],
|
folders: vec!["All".to_string()],
|
||||||
selected_folder: 0,
|
selected_folder: 0,
|
||||||
is_loading: true,
|
is_loading: true,
|
||||||
@@ -138,6 +140,7 @@ impl App {
|
|||||||
fn close_chat(&mut self) {
|
fn close_chat(&mut self) {
|
||||||
self.selected_chat = None;
|
self.selected_chat = None;
|
||||||
self.current_messages.clear();
|
self.current_messages.clear();
|
||||||
|
self.message_input.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn select_first_chat(&mut self) {
|
fn select_first_chat(&mut self) {
|
||||||
@@ -372,6 +375,38 @@ async fn handle_main_input(app: &mut App, key: event::KeyEvent) {
|
|||||||
let has_super = key.modifiers.contains(KeyModifiers::SUPER);
|
let has_super = key.modifiers.contains(KeyModifiers::SUPER);
|
||||||
let has_ctrl = key.modifiers.contains(KeyModifiers::CONTROL);
|
let has_ctrl = key.modifiers.contains(KeyModifiers::CONTROL);
|
||||||
|
|
||||||
|
// Если чат открыт - режим ввода сообщения
|
||||||
|
if app.selected_chat.is_some() {
|
||||||
|
match key.code {
|
||||||
|
KeyCode::Esc => {
|
||||||
|
app.close_chat();
|
||||||
|
}
|
||||||
|
KeyCode::Char('r') if has_ctrl => {
|
||||||
|
// Обновить список чатов работает и в режиме чата
|
||||||
|
app.status_message = Some("Обновление чатов...".to_string());
|
||||||
|
if let Err(e) = app.td_client.load_chats(50).await {
|
||||||
|
app.error_message = Some(e);
|
||||||
|
}
|
||||||
|
app.status_message = None;
|
||||||
|
}
|
||||||
|
KeyCode::Backspace => {
|
||||||
|
app.message_input.pop();
|
||||||
|
}
|
||||||
|
KeyCode::Enter => {
|
||||||
|
// TODO: отправка сообщения
|
||||||
|
// Пока просто очищаем инпут
|
||||||
|
if !app.message_input.is_empty() {
|
||||||
|
app.message_input.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
KeyCode::Char(c) => {
|
||||||
|
// Вводим символы в инпут сообщения
|
||||||
|
app.message_input.push(c);
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Режим навигации по списку чатов
|
||||||
match key.code {
|
match key.code {
|
||||||
// Navigate down: j, Down, д (Russian)
|
// Navigate down: j, Down, д (Russian)
|
||||||
KeyCode::Char('j') | KeyCode::Char('д') | KeyCode::Down if !has_super && !has_ctrl => {
|
KeyCode::Char('j') | KeyCode::Char('д') | KeyCode::Down if !has_super && !has_ctrl => {
|
||||||
@@ -410,7 +445,7 @@ async fn handle_main_input(app: &mut App, key: event::KeyEvent) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
KeyCode::Esc => {
|
KeyCode::Esc => {
|
||||||
app.close_chat();
|
// Ничего не делаем, чат и так не открыт
|
||||||
}
|
}
|
||||||
KeyCode::Char('r') if has_ctrl => {
|
KeyCode::Char('r') if has_ctrl => {
|
||||||
// Обновить список чатов
|
// Обновить список чатов
|
||||||
@@ -428,6 +463,7 @@ async fn handle_main_input(app: &mut App, key: event::KeyEvent) {
|
|||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ui(f: &mut Frame, app: &mut App) {
|
fn ui(f: &mut Frame, app: &mut App) {
|
||||||
@@ -773,14 +809,34 @@ fn render_messages(f: &mut Frame, area: Rect, app: &App) {
|
|||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
let messages_widget =
|
// Вычисляем скролл, чтобы показать последние сообщения
|
||||||
Paragraph::new(lines).block(Block::default().borders(Borders::ALL));
|
let visible_height = message_chunks[1].height.saturating_sub(2) as usize; // -2 для borders
|
||||||
|
let total_lines = lines.len();
|
||||||
|
let scroll_offset = if total_lines > visible_height {
|
||||||
|
(total_lines - visible_height) as u16
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
|
let messages_widget = Paragraph::new(lines)
|
||||||
|
.block(Block::default().borders(Borders::ALL))
|
||||||
|
.scroll((scroll_offset, 0));
|
||||||
f.render_widget(messages_widget, message_chunks[1]);
|
f.render_widget(messages_widget, message_chunks[1]);
|
||||||
|
|
||||||
// Input box
|
// Input box
|
||||||
let input = Paragraph::new("> ...")
|
let input_text = if app.message_input.is_empty() {
|
||||||
|
"> Введите сообщение...".to_string()
|
||||||
|
} else {
|
||||||
|
format!("> {}", app.message_input)
|
||||||
|
};
|
||||||
|
let input_style = if app.message_input.is_empty() {
|
||||||
|
Style::default().fg(Color::DarkGray)
|
||||||
|
} else {
|
||||||
|
Style::default().fg(Color::Yellow)
|
||||||
|
};
|
||||||
|
let input = Paragraph::new(input_text)
|
||||||
.block(Block::default().borders(Borders::ALL))
|
.block(Block::default().borders(Borders::ALL))
|
||||||
.style(Style::default().fg(Color::Yellow));
|
.style(input_style);
|
||||||
f.render_widget(input, message_chunks[2]);
|
f.render_widget(input, message_chunks[2]);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -796,7 +852,11 @@ fn render_footer(f: &mut Frame, area: Rect, app: &App) {
|
|||||||
format!(" {} ", msg)
|
format!(" {} ", msg)
|
||||||
} else if let Some(err) = &app.error_message {
|
} else if let Some(err) = &app.error_message {
|
||||||
format!(" Error: {} ", err)
|
format!(" Error: {} ", err)
|
||||||
|
} else if app.selected_chat.is_some() {
|
||||||
|
// Режим ввода сообщения
|
||||||
|
" Enter: Send | Esc: Close chat | Ctrl+R: Refresh | Ctrl+C: Quit ".to_string()
|
||||||
} else {
|
} else {
|
||||||
|
// Режим навигации
|
||||||
" j/k: Navigate | Ctrl+k: First | Enter: Open | Esc: Close | Ctrl+R: Refresh | Ctrl+C: Quit ".to_string()
|
" j/k: Navigate | Ctrl+k: First | Enter: Open | Esc: Close | Ctrl+R: Refresh | Ctrl+C: Quit ".to_string()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ pub struct ChatInfo {
|
|||||||
pub id: i64,
|
pub id: i64,
|
||||||
pub title: String,
|
pub title: String,
|
||||||
pub last_message: String,
|
pub last_message: String,
|
||||||
|
pub last_message_date: i32,
|
||||||
pub unread_count: i32,
|
pub unread_count: i32,
|
||||||
pub is_pinned: bool,
|
pub is_pinned: bool,
|
||||||
pub order: i64,
|
pub order: i64,
|
||||||
@@ -105,15 +106,19 @@ impl TdClient {
|
|||||||
}
|
}
|
||||||
Update::ChatLastMessage(update) => {
|
Update::ChatLastMessage(update) => {
|
||||||
let chat_id = update.chat_id;
|
let chat_id = update.chat_id;
|
||||||
let last_message_text = update
|
let (last_message_text, last_message_date) = update
|
||||||
.last_message
|
.last_message
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|msg| extract_message_text_static(msg))
|
.map(|msg| (extract_message_text_static(msg), msg.date))
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
|
|
||||||
if let Some(chat) = self.chats.iter_mut().find(|c| c.id == chat_id) {
|
if let Some(chat) = self.chats.iter_mut().find(|c| c.id == chat_id) {
|
||||||
chat.last_message = last_message_text;
|
chat.last_message = last_message_text;
|
||||||
|
chat.last_message_date = last_message_date;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Пересортируем после обновления
|
||||||
|
self.chats.sort_by(|a, b| b.last_message_date.cmp(&a.last_message_date));
|
||||||
}
|
}
|
||||||
Update::ChatReadInbox(update) => {
|
Update::ChatReadInbox(update) => {
|
||||||
if let Some(chat) = self.chats.iter_mut().find(|c| c.id == update.chat_id) {
|
if let Some(chat) = self.chats.iter_mut().find(|c| c.id == update.chat_id) {
|
||||||
@@ -140,16 +145,17 @@ impl TdClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn add_or_update_chat(&mut self, td_chat: &TdChat) {
|
fn add_or_update_chat(&mut self, td_chat: &TdChat) {
|
||||||
let last_message = td_chat
|
let (last_message, last_message_date) = td_chat
|
||||||
.last_message
|
.last_message
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|m| extract_message_text_static(m))
|
.map(|m| (extract_message_text_static(m), m.date))
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
|
|
||||||
let chat_info = ChatInfo {
|
let chat_info = ChatInfo {
|
||||||
id: td_chat.id,
|
id: td_chat.id,
|
||||||
title: td_chat.title.clone(),
|
title: td_chat.title.clone(),
|
||||||
last_message,
|
last_message,
|
||||||
|
last_message_date,
|
||||||
unread_count: td_chat.unread_count,
|
unread_count: td_chat.unread_count,
|
||||||
is_pinned: false,
|
is_pinned: false,
|
||||||
order: 0,
|
order: 0,
|
||||||
@@ -158,10 +164,14 @@ impl TdClient {
|
|||||||
if let Some(existing) = self.chats.iter_mut().find(|c| c.id == td_chat.id) {
|
if let Some(existing) = self.chats.iter_mut().find(|c| c.id == td_chat.id) {
|
||||||
existing.title = chat_info.title;
|
existing.title = chat_info.title;
|
||||||
existing.last_message = chat_info.last_message;
|
existing.last_message = chat_info.last_message;
|
||||||
|
existing.last_message_date = chat_info.last_message_date;
|
||||||
existing.unread_count = chat_info.unread_count;
|
existing.unread_count = chat_info.unread_count;
|
||||||
} else {
|
} else {
|
||||||
self.chats.push(chat_info);
|
self.chats.push(chat_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Сортируем чаты по дате последнего сообщения (новые сверху)
|
||||||
|
self.chats.sort_by(|a, b| b.last_message_date.cmp(&a.last_message_date));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn convert_message(&self, message: &TdMessage) -> MessageInfo {
|
fn convert_message(&self, message: &TdMessage) -> MessageInfo {
|
||||||
|
|||||||
Reference in New Issue
Block a user