fixes
This commit is contained in:
101
src/input/auth.rs
Normal file
101
src/input/auth.rs
Normal file
@@ -0,0 +1,101 @@
|
||||
use crossterm::event::KeyCode;
|
||||
use std::time::Duration;
|
||||
use tokio::time::timeout;
|
||||
use crate::app::App;
|
||||
use crate::tdlib::client::AuthState;
|
||||
|
||||
pub async fn handle(app: &mut App, key_code: KeyCode) {
|
||||
match &app.td_client.auth_state {
|
||||
AuthState::WaitPhoneNumber => match key_code {
|
||||
KeyCode::Char(c) => {
|
||||
app.phone_input.push(c);
|
||||
app.error_message = None;
|
||||
}
|
||||
KeyCode::Backspace => {
|
||||
app.phone_input.pop();
|
||||
app.error_message = None;
|
||||
}
|
||||
KeyCode::Enter => {
|
||||
if !app.phone_input.is_empty() {
|
||||
app.status_message = Some("Отправка номера...".to_string());
|
||||
match timeout(Duration::from_secs(10), app.td_client.send_phone_number(app.phone_input.clone())).await {
|
||||
Ok(Ok(_)) => {
|
||||
app.error_message = None;
|
||||
app.status_message = None;
|
||||
}
|
||||
Ok(Err(e)) => {
|
||||
app.error_message = Some(e);
|
||||
app.status_message = None;
|
||||
}
|
||||
Err(_) => {
|
||||
app.error_message = Some("Таймаут".to_string());
|
||||
app.status_message = None;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
},
|
||||
AuthState::WaitCode => match key_code {
|
||||
KeyCode::Char(c) if c.is_numeric() => {
|
||||
app.code_input.push(c);
|
||||
app.error_message = None;
|
||||
}
|
||||
KeyCode::Backspace => {
|
||||
app.code_input.pop();
|
||||
app.error_message = None;
|
||||
}
|
||||
KeyCode::Enter => {
|
||||
if !app.code_input.is_empty() {
|
||||
app.status_message = Some("Проверка кода...".to_string());
|
||||
match timeout(Duration::from_secs(10), app.td_client.send_code(app.code_input.clone())).await {
|
||||
Ok(Ok(_)) => {
|
||||
app.error_message = None;
|
||||
app.status_message = None;
|
||||
}
|
||||
Ok(Err(e)) => {
|
||||
app.error_message = Some(e);
|
||||
app.status_message = None;
|
||||
}
|
||||
Err(_) => {
|
||||
app.error_message = Some("Таймаут".to_string());
|
||||
app.status_message = None;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
},
|
||||
AuthState::WaitPassword => match key_code {
|
||||
KeyCode::Char(c) => {
|
||||
app.password_input.push(c);
|
||||
app.error_message = None;
|
||||
}
|
||||
KeyCode::Backspace => {
|
||||
app.password_input.pop();
|
||||
app.error_message = None;
|
||||
}
|
||||
KeyCode::Enter => {
|
||||
if !app.password_input.is_empty() {
|
||||
app.status_message = Some("Проверка пароля...".to_string());
|
||||
match timeout(Duration::from_secs(10), app.td_client.send_password(app.password_input.clone())).await {
|
||||
Ok(Ok(_)) => {
|
||||
app.error_message = None;
|
||||
app.status_message = None;
|
||||
}
|
||||
Ok(Err(e)) => {
|
||||
app.error_message = Some(e);
|
||||
app.status_message = None;
|
||||
}
|
||||
Err(_) => {
|
||||
app.error_message = Some("Таймаут".to_string());
|
||||
app.status_message = None;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
174
src/input/main_input.rs
Normal file
174
src/input/main_input.rs
Normal file
@@ -0,0 +1,174 @@
|
||||
use crossterm::event::{KeyCode, KeyEvent, KeyModifiers};
|
||||
use std::time::Duration;
|
||||
use tokio::time::timeout;
|
||||
use crate::app::App;
|
||||
|
||||
pub async fn handle(app: &mut App, key: KeyEvent) {
|
||||
let has_super = key.modifiers.contains(KeyModifiers::SUPER);
|
||||
let has_ctrl = key.modifiers.contains(KeyModifiers::CONTROL);
|
||||
|
||||
// Глобальные команды (работают всегда)
|
||||
match key.code {
|
||||
KeyCode::Char('r') if has_ctrl => {
|
||||
app.status_message = Some("Обновление чатов...".to_string());
|
||||
let _ = timeout(Duration::from_secs(5), app.td_client.load_chats(50)).await;
|
||||
app.status_message = None;
|
||||
return;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
// Cmd+j/k - навигация (работает и в списке чатов, и для скролла сообщений)
|
||||
if has_super {
|
||||
match key.code {
|
||||
// Cmd+j - вниз (следующий чат ИЛИ скролл вниз)
|
||||
KeyCode::Char('j') | KeyCode::Char('д') | KeyCode::Down => {
|
||||
if app.selected_chat_id.is_some() {
|
||||
// В открытом чате - скролл вниз (к новым сообщениям)
|
||||
if app.message_scroll_offset > 0 {
|
||||
app.message_scroll_offset = app.message_scroll_offset.saturating_sub(3);
|
||||
}
|
||||
} else {
|
||||
// В списке чатов - следующий чат
|
||||
app.next_chat();
|
||||
}
|
||||
}
|
||||
// Cmd+k - вверх (предыдущий чат ИЛИ скролл вверх)
|
||||
KeyCode::Char('k') | KeyCode::Char('л') | KeyCode::Up => {
|
||||
if app.selected_chat_id.is_some() {
|
||||
// В открытом чате - скролл вверх (к старым сообщениям)
|
||||
app.message_scroll_offset += 3;
|
||||
|
||||
// Проверяем, нужно ли подгрузить старые сообщения
|
||||
if !app.current_messages.is_empty() {
|
||||
let oldest_msg_id = app.current_messages.first().map(|m| m.id).unwrap_or(0);
|
||||
if let Some(chat_id) = app.get_selected_chat_id() {
|
||||
// Подгружаем больше сообщений если скролл близко к верху
|
||||
if app.message_scroll_offset > app.current_messages.len().saturating_sub(10) {
|
||||
if let Ok(Ok(older)) = timeout(
|
||||
Duration::from_secs(3),
|
||||
app.td_client.load_older_messages(chat_id, oldest_msg_id, 20)
|
||||
).await {
|
||||
if !older.is_empty() {
|
||||
// Добавляем старые сообщения в начало
|
||||
let mut new_messages = older;
|
||||
new_messages.extend(app.current_messages.drain(..));
|
||||
app.current_messages = new_messages;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// В списке чатов - предыдущий чат
|
||||
app.previous_chat();
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Ctrl+k - в первый чат (только в режиме списка)
|
||||
if has_ctrl && matches!(key.code, KeyCode::Char('k') | KeyCode::Char('л')) {
|
||||
if app.selected_chat_id.is_none() {
|
||||
app.select_first_chat();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Enter - открыть чат или отправить сообщение
|
||||
if key.code == KeyCode::Enter {
|
||||
if app.selected_chat_id.is_some() {
|
||||
// Отправка сообщения
|
||||
if !app.message_input.is_empty() {
|
||||
if let Some(chat_id) = app.get_selected_chat_id() {
|
||||
let text = app.message_input.clone();
|
||||
app.message_input.clear();
|
||||
|
||||
match timeout(Duration::from_secs(5), app.td_client.send_message(chat_id, text.clone())).await {
|
||||
Ok(Ok(sent_msg)) => {
|
||||
// Добавляем отправленное сообщение в список
|
||||
app.current_messages.push(sent_msg);
|
||||
// Сбрасываем скролл чтобы видеть новое сообщение
|
||||
app.message_scroll_offset = 0;
|
||||
}
|
||||
Ok(Err(e)) => {
|
||||
app.error_message = Some(e);
|
||||
}
|
||||
Err(_) => {
|
||||
app.error_message = Some("Таймаут отправки".to_string());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Открываем чат
|
||||
let prev_selected = app.selected_chat_id;
|
||||
app.select_current_chat();
|
||||
|
||||
if app.selected_chat_id != prev_selected {
|
||||
if let Some(chat_id) = app.get_selected_chat_id() {
|
||||
app.status_message = Some("Загрузка сообщений...".to_string());
|
||||
app.message_scroll_offset = 0;
|
||||
match timeout(Duration::from_secs(5), app.td_client.get_chat_history(chat_id, 50)).await {
|
||||
Ok(Ok(messages)) => {
|
||||
app.current_messages = messages;
|
||||
app.status_message = None;
|
||||
}
|
||||
Ok(Err(e)) => {
|
||||
app.error_message = Some(e);
|
||||
app.status_message = None;
|
||||
}
|
||||
Err(_) => {
|
||||
app.error_message = Some("Таймаут загрузки сообщений".to_string());
|
||||
app.status_message = None;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Esc - закрыть чат
|
||||
if key.code == KeyCode::Esc {
|
||||
if app.selected_chat_id.is_some() {
|
||||
app.close_chat();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Ввод текста в режиме открытого чата
|
||||
if app.selected_chat_id.is_some() {
|
||||
match key.code {
|
||||
KeyCode::Backspace => {
|
||||
app.message_input.pop();
|
||||
}
|
||||
KeyCode::Char(c) => {
|
||||
app.message_input.push(c);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
} else {
|
||||
// В режиме списка чатов - навигация j/k и переключение папок
|
||||
match key.code {
|
||||
// j или д - следующий чат
|
||||
KeyCode::Char('j') | KeyCode::Char('д') | KeyCode::Down => {
|
||||
app.next_chat();
|
||||
}
|
||||
// k или л - предыдущий чат
|
||||
KeyCode::Char('k') | KeyCode::Char('л') | KeyCode::Up => {
|
||||
app.previous_chat();
|
||||
}
|
||||
// Цифры - переключение папок
|
||||
KeyCode::Char(c) if c >= '1' && c <= '9' => {
|
||||
let folder_idx = (c as usize) - ('1' as usize);
|
||||
if folder_idx < app.folders.len() {
|
||||
app.selected_folder = folder_idx;
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
5
src/input/mod.rs
Normal file
5
src/input/mod.rs
Normal file
@@ -0,0 +1,5 @@
|
||||
mod auth;
|
||||
mod main_input;
|
||||
|
||||
pub use auth::handle as handle_auth_input;
|
||||
pub use main_input::handle as handle_main_input;
|
||||
Reference in New Issue
Block a user