This commit is contained in:
Mikhail Kilin
2026-01-18 20:06:17 +03:00
parent 7540a30e06
commit dfce86d3db
11 changed files with 268 additions and 58 deletions

View File

@@ -65,6 +65,7 @@ struct App {
chat_list_state: ListState,
selected_chat: Option<usize>,
current_messages: Vec<MessageInfo>,
message_input: String, // Input for new message
folders: Vec<String>,
selected_folder: usize,
is_loading: bool,
@@ -87,6 +88,7 @@ impl App {
chat_list_state: state,
selected_chat: None,
current_messages: Vec::new(),
message_input: String::new(),
folders: vec!["All".to_string()],
selected_folder: 0,
is_loading: true,
@@ -138,6 +140,7 @@ impl App {
fn close_chat(&mut self) {
self.selected_chat = None;
self.current_messages.clear();
self.message_input.clear();
}
fn select_first_chat(&mut self) {
@@ -372,61 +375,94 @@ async fn handle_main_input(app: &mut App, key: event::KeyEvent) {
let has_super = key.modifiers.contains(KeyModifiers::SUPER);
let has_ctrl = key.modifiers.contains(KeyModifiers::CONTROL);
match key.code {
// Navigate down: j, Down, д (Russian)
KeyCode::Char('j') | KeyCode::Char('д') | KeyCode::Down if !has_super && !has_ctrl => {
app.next_chat();
// Если чат открыт - режим ввода сообщения
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);
}
_ => {}
}
// Navigate up: k, Up, л (Russian)
KeyCode::Char('k') | KeyCode::Char('л') | KeyCode::Up if !has_super && !has_ctrl => {
app.previous_chat();
}
// Jump to first chat: Cmd+Up or Ctrl+k/л
KeyCode::Up if has_super => {
app.select_first_chat();
}
KeyCode::Char('k') | KeyCode::Char('л') if has_ctrl => {
app.select_first_chat();
}
KeyCode::Enter => {
let prev_selected = app.selected_chat;
app.select_current_chat();
} else {
// Режим навигации по списку чатов
match key.code {
// Navigate down: j, Down, д (Russian)
KeyCode::Char('j') | KeyCode::Char('д') | KeyCode::Down if !has_super && !has_ctrl => {
app.next_chat();
}
// Navigate up: k, Up, л (Russian)
KeyCode::Char('k') | KeyCode::Char('л') | KeyCode::Up if !has_super && !has_ctrl => {
app.previous_chat();
}
// Jump to first chat: Cmd+Up or Ctrl+k/л
KeyCode::Up if has_super => {
app.select_first_chat();
}
KeyCode::Char('k') | KeyCode::Char('л') if has_ctrl => {
app.select_first_chat();
}
KeyCode::Enter => {
let prev_selected = app.selected_chat;
app.select_current_chat();
// Если выбрали новый чат, загружаем историю
if app.selected_chat != prev_selected {
if let Some(chat_id) = app.get_selected_chat_id() {
app.status_message = Some("Загрузка сообщений...".to_string());
match app.td_client.get_chat_history(chat_id, 30).await {
Ok(messages) => {
app.current_messages = messages;
app.status_message = None;
}
Err(e) => {
app.error_message = Some(e);
app.status_message = None;
// Если выбрали новый чат, загружаем историю
if app.selected_chat != prev_selected {
if let Some(chat_id) = app.get_selected_chat_id() {
app.status_message = Some("Загрузка сообщений...".to_string());
match app.td_client.get_chat_history(chat_id, 30).await {
Ok(messages) => {
app.current_messages = messages;
app.status_message = None;
}
Err(e) => {
app.error_message = Some(e);
app.status_message = None;
}
}
}
}
}
}
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);
KeyCode::Esc => {
// Ничего не делаем, чат и так не открыт
}
app.status_message = None;
}
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;
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::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;
}
}
_ => {}
}
_ => {}
}
}
@@ -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]);
// 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))
.style(Style::default().fg(Color::Yellow));
.style(input_style);
f.render_widget(input, message_chunks[2]);
}
} else {
@@ -796,7 +852,11 @@ fn render_footer(f: &mut Frame, area: Rect, app: &App) {
format!(" {} ", msg)
} else if let Some(err) = &app.error_message {
format!(" Error: {} ", err)
} else if app.selected_chat.is_some() {
// Режим ввода сообщения
" Enter: Send | Esc: Close chat | Ctrl+R: Refresh | Ctrl+C: Quit ".to_string()
} else {
// Режим навигации
" j/k: Navigate | Ctrl+k: First | Enter: Open | Esc: Close | Ctrl+R: Refresh | Ctrl+C: Quit ".to_string()
};