refactor: reduce nesting with early returns and guard clauses

Применены паттерны упрощения вложенности:
- handle_profile_mode: упрощён блок Enter с let-else
- handle_profile_open: применён early return guard
- handle_enter_key: разделена на 3 функции + early returns
  - edit_message() - редактирование сообщения
  - send_new_message() - отправка нового сообщения
  - Сокращено с ~130 до ~40 строк
- handle_message_search_mode: извлечена функция perform_message_search()
  - Упрощены блоки Backspace и Char с let-else

Результат: код стал более линейным, уменьшена глубина вложенности с 6+ до 2-3 уровней

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
Mikhail Kilin
2026-02-03 20:34:19 +03:00
parent 7e372bffef
commit 67fd7506b3

View File

@@ -73,18 +73,24 @@ async fn handle_profile_mode<T: TdClientTrait>(app: &mut App<T>, key: KeyEvent)
}
KeyCode::Enter => {
// Выполнить выбранное действие
if let Some(profile) = app.get_profile_info() {
let Some(profile) = app.get_profile_info() else {
return;
};
let actions = get_available_actions_count(profile);
let action_index = app.get_selected_profile_action().unwrap_or(0);
if action_index < actions {
// Guard: проверяем, что индекс действия валидный
if action_index >= actions {
return;
}
// Определяем какое действие выбрано
let mut current_idx = 0;
// Действие: Открыть в браузере
if profile.username.is_some() {
if action_index == current_idx {
if let Some(username) = &profile.username {
if action_index == current_idx {
let url = format!(
"https://t.me/{}",
username.trim_start_matches('@')
@@ -107,7 +113,6 @@ async fn handle_profile_mode<T: TdClientTrait>(app: &mut App<T>, key: KeyEvent)
"Открытие URL недоступно (требуется feature 'url-open')".to_string()
);
}
}
return;
}
current_idx += 1;
@@ -115,8 +120,7 @@ async fn handle_profile_mode<T: TdClientTrait>(app: &mut App<T>, key: KeyEvent)
// Действие: Скопировать ID
if action_index == current_idx {
app.status_message =
Some(format!("ID скопирован: {}", profile.chat_id));
app.status_message = Some(format!("ID скопирован: {}", profile.chat_id));
return;
}
current_idx += 1;
@@ -126,8 +130,6 @@ async fn handle_profile_mode<T: TdClientTrait>(app: &mut App<T>, key: KeyEvent)
app.show_leave_group_confirmation();
}
}
}
}
_ => {}
}
}
@@ -136,7 +138,10 @@ async fn handle_profile_mode<T: TdClientTrait>(app: &mut App<T>, key: KeyEvent)
///
/// Загружает информацию о профиле и переключает в режим просмотра профиля
async fn handle_profile_open<T: TdClientTrait>(app: &mut App<T>) {
if let Some(chat_id) = app.selected_chat_id {
let Some(chat_id) = app.selected_chat_id else {
return;
};
app.status_message = Some("Загрузка профиля...".to_string());
match with_timeout_msg(
Duration::from_secs(5),
@@ -154,7 +159,6 @@ async fn handle_profile_open<T: TdClientTrait>(app: &mut App<T>) {
app.status_message = None;
}
}
}
}
/// Обработка режима выбора сообщения для действий
@@ -284,34 +288,8 @@ async fn handle_escape_key<T: TdClientTrait>(app: &mut App<T>) {
}
}
/// Обработка клавиши Enter
///
/// Обрабатывает три сценария:
/// 1. В режиме выбора сообщения: начать редактирование
/// 2. В открытом чате: отправить новое или редактировать существующее сообщение
/// 3. В списке чатов: открыть выбранный чат
async fn handle_enter_key<T: TdClientTrait>(app: &mut App<T>) {
if app.selected_chat_id.is_some() {
// Режим выбора сообщения
if app.is_selecting_message() {
// Начать редактирование выбранного сообщения
if app.start_editing_selected() {
// Редактирование начато
} else {
// Нельзя редактировать это сообщение
app.chat_state = crate::app::ChatState::Normal;
}
return;
}
// Отправка или редактирование сообщения
if is_non_empty(&app.message_input) {
if let Some(chat_id) = app.get_selected_chat_id() {
let text = app.message_input.clone();
if app.is_editing() {
// Режим редактирования
if let Some(msg_id) = app.chat_state.selected_message_id() {
/// Редактирование существующего сообщения
async fn edit_message<T: TdClientTrait>(app: &mut App<T>, chat_id: i64, msg_id: MessageId, text: String) {
// Проверяем, что сообщение есть в локальном кэше
let msg_exists = app.td_client.current_chat_messages()
.iter()
@@ -354,20 +332,22 @@ async fn handle_enter_key<T: TdClientTrait>(app: &mut App<T>) {
app.message_input.clear();
app.cursor_position = 0;
app.chat_state = crate::app::ChatState::Normal;
app.needs_redraw = true; // ВАЖНО: перерисовываем UI
app.needs_redraw = true;
}
Err(e) => {
app.error_message = Some(e);
}
}
}
} else {
// Обычная отправка (или reply)
}
/// Отправка нового сообщения (с опциональным reply)
async fn send_new_message<T: TdClientTrait>(app: &mut App<T>, chat_id: i64, text: String) {
let reply_to_id = if app.is_replying() {
app.chat_state.selected_message_id()
} else {
None
};
// Создаём ReplyInfo ДО отправки, пока сообщение точно доступно
let reply_info = app.get_replying_to_message().map(|m| {
crate::tdlib::ReplyInfo {
@@ -376,6 +356,7 @@ async fn handle_enter_key<T: TdClientTrait>(app: &mut App<T>) {
text: m.text().to_string(),
}
});
app.message_input.clear();
app.cursor_position = 0;
// Сбрасываем режим reply если он был активен
@@ -389,8 +370,7 @@ async fn handle_enter_key<T: TdClientTrait>(app: &mut App<T>) {
match with_timeout_msg(
Duration::from_secs(5),
app.td_client
.send_message(ChatId::new(chat_id), text, reply_to_id, reply_info),
app.td_client.send_message(ChatId::new(chat_id), text, reply_to_id, reply_info),
"Таймаут отправки",
)
.await
@@ -405,11 +385,17 @@ async fn handle_enter_key<T: TdClientTrait>(app: &mut App<T>) {
app.error_message = Some(e);
}
}
}
}
}
} else {
// Открываем чат
}
/// Обработка клавиши Enter
///
/// Обрабатывает три сценария:
/// 1. В режиме выбора сообщения: начать редактирование
/// 2. В открытом чате: отправить новое или редактировать существующее сообщение
/// 3. В списке чатов: открыть выбранный чат
async fn handle_enter_key<T: TdClientTrait>(app: &mut App<T>) {
// Сценарий 1: Открытие чата из списка
if app.selected_chat_id.is_none() {
let prev_selected = app.selected_chat_id;
app.select_current_chat();
@@ -418,6 +404,37 @@ async fn handle_enter_key<T: TdClientTrait>(app: &mut App<T>) {
open_chat_and_load_data(app, chat_id).await;
}
}
return;
}
// Сценарий 2: Режим выбора сообщения - начать редактирование
if app.is_selecting_message() {
if !app.start_editing_selected() {
// Нельзя редактировать это сообщение
app.chat_state = crate::app::ChatState::Normal;
}
return;
}
// Сценарий 3: Отправка или редактирование сообщения
if !is_non_empty(&app.message_input) {
return;
}
let Some(chat_id) = app.get_selected_chat_id() else {
return;
};
let text = app.message_input.clone();
if app.is_editing() {
// Редактирование существующего сообщения
if let Some(msg_id) = app.chat_state.selected_message_id() {
edit_message(app, chat_id, msg_id, text).await;
}
} else {
// Отправка нового сообщения
send_new_message(app, chat_id, text).await;
}
}
@@ -698,6 +715,27 @@ async fn handle_pinned_mode<T: TdClientTrait>(app: &mut App<T>, key: KeyEvent) {
}
}
/// Выполняет поиск по сообщениям с обновлением результатов
async fn perform_message_search<T: TdClientTrait>(app: &mut App<T>, query: &str) {
let Some(chat_id) = app.get_selected_chat_id() else {
return;
};
if query.is_empty() {
app.set_search_results(Vec::new());
return;
}
if let Ok(results) = with_timeout(
Duration::from_secs(3),
app.td_client.search_messages(ChatId::new(chat_id), query),
)
.await
{
app.set_search_results(results);
}
}
/// Обработка режима поиска по сообщениям в открытом чате
///
/// Обрабатывает:
@@ -735,43 +773,21 @@ async fn handle_message_search_mode<T: TdClientTrait>(app: &mut App<T>, key: Key
}
KeyCode::Backspace => {
// Удаляем символ из запроса
if let Some(mut query) = app.get_search_query().map(|s| s.to_string()) {
let Some(mut query) = app.get_search_query().map(|s| s.to_string()) else {
return;
};
query.pop();
app.update_search_query(query.clone());
// Выполняем поиск при изменении запроса
if let Some(chat_id) = app.get_selected_chat_id() {
if !query.is_empty() {
if let Ok(results) = with_timeout(
Duration::from_secs(3),
app.td_client.search_messages(ChatId::new(chat_id), &query),
)
.await
{
app.set_search_results(results);
}
} else {
app.set_search_results(Vec::new());
}
}
}
perform_message_search(app, &query).await;
}
KeyCode::Char(c) => {
// Добавляем символ к запросу
if let Some(mut query) = app.get_search_query().map(|s| s.to_string()) {
let Some(mut query) = app.get_search_query().map(|s| s.to_string()) else {
return;
};
query.push(c);
app.update_search_query(query.clone());
// Выполняем поиск при изменении запроса
if let Some(chat_id) = app.get_selected_chat_id() {
if let Ok(results) = with_timeout(
Duration::from_secs(3),
app.td_client.search_messages(ChatId::new(chat_id), &query),
)
.await
{
app.set_search_results(results);
}
}
}
perform_message_search(app, &query).await;
}
_ => {}
}