refactor: complete nesting simplification (category 3 - 100%)

Simplified deep nesting across the codebase using modern Rust patterns:
let-else guards, early returns, iterator chains, and extracted functions.

**Files improved:**

1. src/tdlib/messages.rs (44 → 28 spaces max indent)
   - fetch_missing_reply_info(): 7 → 2-3 levels
     * Extracted fetch_and_update_reply()
     * Used filter_map and iterator chains
   - get_chat_history() retry loop: 6 → 3 levels
     * Early continue for empty results
     * Used .flatten() instead of nested if-let

2. src/input/main_input.rs (40 → 36 spaces max indent)
   - handle_forward_mode(): 7 → 2-3 levels
     * Extracted forward_selected_message()
   - Reaction picker: 5 → 2-3 levels
     * Extracted send_reaction()
   - Scroll + load older: 6 → 2-3 levels
     * Extracted load_older_messages_if_needed()

3. src/config.rs (36 → 32 spaces max indent)
   - load_credentials(): 7 → 2-3 levels
     * Extracted load_credentials_from_file()
     * Extracted load_credentials_from_env()
     * Used ? operator for Option chains

**Results:**
- Max nesting in entire project: ≤32 spaces (8 levels)
- 8 new functions extracted for better separation of concerns
- All 343 tests passing 

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
Mikhail Kilin
2026-02-04 02:35:56 +03:00
parent 9a04455113
commit c881f74ecb
4 changed files with 305 additions and 193 deletions

View File

@@ -155,30 +155,32 @@ impl MessageManager {
)
.await;
match result {
Ok(tdlib_rs::enums::Messages::Messages(messages_obj)) => {
if !messages_obj.messages.is_empty() {
all_messages.clear(); // Очищаем предыдущие результаты
for msg_opt in messages_obj.messages.iter().rev() {
if let Some(msg) = msg_opt {
if let Some(info) = self.convert_message(msg).await {
all_messages.push(info);
}
}
}
// Если получили непустой результат, прекращаем попытки
// (TDLib вернёт столько сообщений, сколько доступно, до limit)
break;
}
// Если сообщений мало, ждём перед следующей попыткой
if attempt < max_attempts {
sleep(Duration::from_millis(200)).await;
}
}
let messages_obj = match result {
Ok(tdlib_rs::enums::Messages::Messages(obj)) => obj,
Err(e) => return Err(format!("Ошибка загрузки истории: {:?}", e)),
};
// Skip empty results
if messages_obj.messages.is_empty() {
// Ждём перед следующей попыткой
if attempt < max_attempts {
sleep(Duration::from_millis(200)).await;
}
continue;
}
// Convert messages using iterator chains (flatten removes None values)
all_messages.clear(); // Очищаем предыдущие результаты
for msg in messages_obj.messages.iter().rev().flatten() {
if let Some(info) = self.convert_message(msg).await {
all_messages.push(info);
}
}
// Если получили непустой результат, прекращаем попытки
// (TDLib вернёт столько сообщений, сколько доступно, до limit)
break;
}
Ok(all_messages)
@@ -716,41 +718,60 @@ impl MessageManager {
///
/// Вызывайте после загрузки истории чата для заполнения информации о цитируемых сообщениях.
pub async fn fetch_missing_reply_info(&mut self) {
// Collect message IDs that need to be fetched
let mut to_fetch = Vec::new();
for msg in &self.current_chat_messages {
if let Some(ref reply) = msg.interactions.reply_to {
if reply.sender_name == "Unknown" {
to_fetch.push(reply.message_id);
}
}
}
// Early return if no chat selected
let Some(chat_id) = self.current_chat_id else {
return;
};
// Fetch missing messages
if let Some(chat_id) = self.current_chat_id {
for message_id in to_fetch {
if let Ok(original_msg_enum) =
functions::get_message(chat_id.as_i64(), message_id.as_i64(), self.client_id).await
{
let tdlib_rs::enums::Message::Message(original_msg) = original_msg_enum;
if let Some(orig_info) = self.convert_message(&original_msg).await {
// Update the reply info
for msg in &mut self.current_chat_messages {
if let Some(ref mut reply) = msg.interactions.reply_to {
if reply.message_id == message_id {
reply.sender_name = orig_info.metadata.sender_name.clone();
reply.text = orig_info
.content
.text
.chars()
.take(50)
.collect::<String>();
}
}
}
}
}
}
// Collect message IDs with missing reply info using filter_map
let to_fetch: Vec<MessageId> = self
.current_chat_messages
.iter()
.filter_map(|msg| {
msg.interactions
.reply_to
.as_ref()
.filter(|reply| reply.sender_name == "Unknown")
.map(|reply| reply.message_id)
})
.collect();
// Fetch and update each missing message
for message_id in to_fetch {
self.fetch_and_update_reply(chat_id, message_id).await;
}
}
/// Загружает одно сообщение и обновляет reply информацию.
async fn fetch_and_update_reply(&mut self, chat_id: ChatId, message_id: MessageId) {
// Try to fetch the original message
let Ok(original_msg_enum) =
functions::get_message(chat_id.as_i64(), message_id.as_i64(), self.client_id).await
else {
return;
};
let tdlib_rs::enums::Message::Message(original_msg) = original_msg_enum;
let Some(orig_info) = self.convert_message(&original_msg).await else {
return;
};
// Extract text preview (first 50 chars)
let text_preview: String = orig_info
.content
.text
.chars()
.take(50)
.collect();
// Update reply info in all messages that reference this message
self.current_chat_messages
.iter_mut()
.filter_map(|msg| msg.interactions.reply_to.as_mut())
.filter(|reply| reply.message_id == message_id)
.for_each(|reply| {
reply.sender_name = orig_info.metadata.sender_name.clone();
reply.text = text_preview.clone();
});
}
}