Handle absent media and selection state safely
This commit is contained in:
@@ -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
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user