Handle absent media and selection state safely

This commit is contained in:
Mikhail Kilin
2026-05-17 18:41:52 +03:00
parent 679892beca
commit 91e4f118f3
7 changed files with 68 additions and 36 deletions

View File

@@ -132,9 +132,9 @@ impl<T: TdClientTrait> MessageMethods<T> for App<T> {
_ => None,
};
if selected_idx.is_none() {
let Some(selected_idx) = selected_idx else {
return false;
}
};
// Сначала извлекаем данные из сообщения
let msg_data = self.get_selected_message().and_then(|msg| {
@@ -143,7 +143,7 @@ impl<T: TdClientTrait> MessageMethods<T> for App<T> {
// 2. Это исходящее сообщение
// 3. ID не временный (временные ID в TDLib отрицательные)
if msg.can_be_edited() && msg.is_outgoing() && msg.id().as_i64() > 0 {
Some((msg.id(), msg.text().to_string(), selected_idx.unwrap()))
Some((msg.id(), msg.text().to_string(), selected_idx))
} else {
None
}

View File

@@ -91,10 +91,13 @@ pub async fn handle_message_selection<T: TdClientTrait>(
media::handle_voice_seek(app, -5.0);
}
Some(crate::config::Command::ReactMessage) => {
let Some(chat_id) = app.selected_chat_id else {
app.error_message = Some("Чат не выбран".to_string());
return;
};
let Some(msg) = app.get_selected_message() else {
return;
};
let chat_id = app.selected_chat_id.unwrap();
let message_id = msg.id();
app.status_message = Some("Загрузка реакций...".to_string());

View File

@@ -112,7 +112,10 @@ async fn handle_view_image<T: TdClientTrait>(app: &mut App<T>) {
return;
}
let photo = msg.photo_info().unwrap();
let Some(photo) = msg.photo_info() else {
app.status_message = Some("Сообщение не содержит фото".to_string());
return;
};
let msg_id = msg.id();
let file_id = photo.file_id;
let photo_width = photo.width;
@@ -238,7 +241,10 @@ async fn handle_play_voice<T: TdClientTrait>(app: &mut App<T>) {
return;
}
let voice = msg.voice_info().unwrap();
let Some(voice) = msg.voice_info() else {
app.status_message = Some("Сообщение не содержит голосовое".to_string());
return;
};
let file_id = voice.file_id;
match &voice.download_state {

View File

@@ -433,24 +433,20 @@ pub fn render_message_bubble(
// Отображаем индикатор воспроизведения голосового
if msg.has_voice() {
if let Some(voice) = msg.voice_info() {
let is_this_playing = playback_state
.map(|ps| ps.message_id == msg.id())
.unwrap_or(false);
let status_line = if is_this_playing {
let ps = playback_state.unwrap();
let icon = match ps.status {
PlaybackStatus::Playing => "",
PlaybackStatus::Paused => "",
PlaybackStatus::Loading => "",
_ => "",
let status_line =
if let Some(ps) = playback_state.filter(|ps| ps.message_id == msg.id()) {
let icon = match ps.status {
PlaybackStatus::Playing => "",
PlaybackStatus::Paused => "",
PlaybackStatus::Loading => "",
_ => "",
};
let bar = render_progress_bar(ps.position, ps.duration, 20);
format!("{} {} {:.0}s/{:.0}s", icon, bar, ps.position, ps.duration)
} else {
let waveform = render_waveform(&voice.waveform, 20);
format!(" {} {:.0}s", waveform, voice.duration)
};
let bar = render_progress_bar(ps.position, ps.duration, 20);
format!("{} {} {:.0}s/{:.0}s", icon, bar, ps.position, ps.duration)
} else {
let waveform = render_waveform(&voice.waveform, 20);
format!(" {} {:.0}s", waveform, voice.duration)
};
let status_len = status_line.chars().count();
if msg.is_outgoing() {
@@ -670,7 +666,9 @@ pub fn render_album_bubble(
};
// Timestamp из последнего сообщения
let last_msg = messages.last().unwrap();
let Some(last_msg) = messages.last() else {
return (lines, deferred);
};
let time = format_timestamp(last_msg.date());
if !captions.is_empty() {

View File

@@ -9,15 +9,17 @@ extern "C" {
/// Отключаем логи TDLib синхронно, до создания клиента
pub fn disable_tdlib_logs() {
let request = r#"{"@type":"setLogVerbosityLevel","new_verbosity_level":0}"#;
let c_request = CString::new(request).unwrap();
unsafe {
let _ = td_execute(c_request.as_ptr());
if let Ok(c_request) = CString::new(request) {
unsafe {
let _ = td_execute(c_request.as_ptr());
}
}
// Также перенаправляем логи в никуда
let request2 = r#"{"@type":"setLogStream","log_stream":{"@type":"logStreamEmpty"}}"#;
let c_request2 = CString::new(request2).unwrap();
unsafe {
let _ = td_execute(c_request2.as_ptr());
if let Ok(c_request2) = CString::new(request2) {
unsafe {
let _ = td_execute(c_request2.as_ptr());
}
}
}