add typings in/out
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
use std::env;
|
||||
use std::collections::HashMap;
|
||||
use tdlib_rs::enums::{AuthorizationState, ChatList, ChatType, ConnectionState, MessageContent, Update, User, UserStatus};
|
||||
use std::time::Instant;
|
||||
use tdlib_rs::enums::{AuthorizationState, ChatAction, ChatList, ChatType, ConnectionState, MessageContent, MessageSender, Update, User, UserStatus};
|
||||
use tdlib_rs::types::TextEntity;
|
||||
|
||||
/// Максимальный размер кэшей пользователей
|
||||
@@ -129,7 +130,8 @@ pub struct ReplyInfo {
|
||||
pub struct ForwardInfo {
|
||||
/// Имя оригинального отправителя
|
||||
pub sender_name: String,
|
||||
/// Дата оригинального сообщения
|
||||
/// Дата оригинального сообщения (для будущего использования)
|
||||
#[allow(dead_code)]
|
||||
pub date: i32,
|
||||
}
|
||||
|
||||
@@ -222,6 +224,8 @@ pub struct TdClient {
|
||||
user_statuses: LruCache<UserOnlineStatus>,
|
||||
/// Состояние сетевого соединения
|
||||
pub network_state: NetworkState,
|
||||
/// Typing status для текущего чата: (user_id, action_text, timestamp)
|
||||
pub typing_status: Option<(i64, String, Instant)>,
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
@@ -252,6 +256,7 @@ impl TdClient {
|
||||
main_chat_list_position: 0,
|
||||
user_statuses: LruCache::new(MAX_USER_CACHE_SIZE),
|
||||
network_state: NetworkState::Connecting,
|
||||
typing_status: None,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -290,6 +295,30 @@ impl TdClient {
|
||||
.and_then(|user_id| self.user_statuses.peek(user_id))
|
||||
}
|
||||
|
||||
/// Очищает typing status если прошло более 6 секунд
|
||||
/// Возвращает true если статус был очищен (нужна перерисовка)
|
||||
pub fn clear_stale_typing_status(&mut self) -> bool {
|
||||
if let Some((_, _, timestamp)) = &self.typing_status {
|
||||
if timestamp.elapsed().as_secs() > 6 {
|
||||
self.typing_status = None;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
/// Возвращает текст typing status с именем пользователя
|
||||
/// Например: "Вася печатает..."
|
||||
pub fn get_typing_text(&self) -> Option<String> {
|
||||
self.typing_status.as_ref().map(|(user_id, action, _)| {
|
||||
let name = self.user_names
|
||||
.peek(user_id)
|
||||
.cloned()
|
||||
.unwrap_or_else(|| "Кто-то".to_string());
|
||||
format!("{} {}", name, action)
|
||||
})
|
||||
}
|
||||
|
||||
/// Инициализация TDLib с параметрами
|
||||
pub async fn init(&mut self) -> Result<(), String> {
|
||||
let result = functions::set_tdlib_parameters(
|
||||
@@ -525,6 +554,41 @@ impl TdClient {
|
||||
ConnectionState::Ready => NetworkState::Ready,
|
||||
};
|
||||
}
|
||||
Update::ChatAction(update) => {
|
||||
// Обрабатываем только для текущего открытого чата
|
||||
if Some(update.chat_id) == self.current_chat_id {
|
||||
// Извлекаем user_id из sender_id
|
||||
let user_id = match update.sender_id {
|
||||
MessageSender::User(user) => Some(user.user_id),
|
||||
MessageSender::Chat(_) => None, // Игнорируем действия от имени чата
|
||||
};
|
||||
|
||||
if let Some(user_id) = user_id {
|
||||
// Определяем текст действия
|
||||
let action_text = match update.action {
|
||||
ChatAction::Typing => Some("печатает...".to_string()),
|
||||
ChatAction::RecordingVideo => Some("записывает видео...".to_string()),
|
||||
ChatAction::UploadingVideo(_) => Some("отправляет видео...".to_string()),
|
||||
ChatAction::RecordingVoiceNote => Some("записывает голосовое...".to_string()),
|
||||
ChatAction::UploadingVoiceNote(_) => Some("отправляет голосовое...".to_string()),
|
||||
ChatAction::UploadingPhoto(_) => Some("отправляет фото...".to_string()),
|
||||
ChatAction::UploadingDocument(_) => Some("отправляет файл...".to_string()),
|
||||
ChatAction::ChoosingSticker => Some("выбирает стикер...".to_string()),
|
||||
ChatAction::RecordingVideoNote => Some("записывает видеосообщение...".to_string()),
|
||||
ChatAction::UploadingVideoNote(_) => Some("отправляет видеосообщение...".to_string()),
|
||||
ChatAction::Cancel => None, // Отмена — сбрасываем статус
|
||||
_ => None,
|
||||
};
|
||||
|
||||
if let Some(text) = action_text {
|
||||
self.typing_status = Some((user_id, text, Instant::now()));
|
||||
} else {
|
||||
// Cancel или неизвестное действие — сбрасываем
|
||||
self.typing_status = None;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
@@ -1104,6 +1168,16 @@ impl TdClient {
|
||||
}
|
||||
}
|
||||
|
||||
/// Отправка статуса действия в чат (typing, cancel и т.д.)
|
||||
pub async fn send_chat_action(&self, chat_id: i64, action: ChatAction) {
|
||||
let _ = functions::send_chat_action(
|
||||
chat_id,
|
||||
0, // message_thread_id
|
||||
Some(action),
|
||||
self.client_id,
|
||||
).await;
|
||||
}
|
||||
|
||||
/// Отправка текстового сообщения с поддержкой Markdown и reply
|
||||
pub async fn send_message(&self, chat_id: i64, text: String, reply_to_message_id: Option<i64>, reply_info: Option<ReplyInfo>) -> Result<MessageInfo, String> {
|
||||
use tdlib_rs::types::{FormattedText, InputMessageText, TextParseModeMarkdown, InputMessageReplyToMessage};
|
||||
|
||||
Reference in New Issue
Block a user