From db7b7be60ebff9a8c756fffe7055687f786a63b6 Mon Sep 17 00:00:00 2001 From: iequidoo Date: Sat, 4 Apr 2026 19:57:48 -0300 Subject: [PATCH] fix: Ensure that message being sent is added to the bottom (#8027) Before, if the user fixed their clock incorrectly set to the future, they needed to delete previously sent messages or wait until this future comes again so that new sent messages are added to the bottom. Strictly speaking, the problem isn't fixable because we don't know if messages were incorrectly timestamped into the future or they are timestamped correctly and the clock is now incorrectly set to the past. Anyway, adding messages to the middle of the chat isn't a good way to inform the user about the problem. --- src/chat.rs | 15 ++++++++++++++- src/chat/chat_tests.rs | 25 +++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/src/chat.rs b/src/chat.rs index 8691e1074..8b98f51fa 100644 --- a/src/chat.rs +++ b/src/chat.rs @@ -2931,11 +2931,24 @@ pub(crate) async fn create_send_msg_jobs(context: &Context, msg: &mut Message) - msg.param.remove(Param::GuaranteeE2ee); } msg.subject.clone_from(&rendered_msg.subject); + // Sort the message to the bottom. Employ `msgs_index7` to compute `timestamp`. context .sql .execute( - "UPDATE msgs SET pre_rfc724_mid=?, subject=?, param=? WHERE id=?", + " +UPDATE msgs SET + timestamp=( + SELECT MAX(timestamp) FROM msgs WHERE + -- From `InFresh` to `OutMdnRcvd` inclusive except `OutDraft`. + state IN(10,13,16,18,20,24,26,28) AND + hidden IN(0,1) AND + chat_id=? + ), + pre_rfc724_mid=?, subject=?, param=? +WHERE id=? + ", ( + msg.chat_id, &msg.pre_rfc724_mid, &msg.subject, msg.param.to_string(), diff --git a/src/chat/chat_tests.rs b/src/chat/chat_tests.rs index d6cd5c10c..75f8b5532 100644 --- a/src/chat/chat_tests.rs +++ b/src/chat/chat_tests.rs @@ -5027,6 +5027,31 @@ async fn test_do_not_overwrite_draft() -> Result<()> { Ok(()) } +#[tokio::test(flavor = "multi_thread", worker_threads = 2)] +async fn test_outgoing_msg_after_another_from_future() -> Result<()> { + let mut tcm = TestContextManager::new(); + let t = &tcm.alice().await; + let chat_id = t.get_self_chat().await.id; + + // Simulate sending a message with clock set to the future. + SystemTime::shift(Duration::from_secs(3600)); + let msg_id = send_text_msg(t, chat_id, "test".to_string()).await?; + SystemTime::shift_back(Duration::from_secs(3600)); + + let timestamp_sent: i64 = t + .sql + .query_get_value("SELECT timestamp_sent FROM msgs WHERE id=?", (msg_id,)) + .await? + .unwrap(); + // Let's have a check here that locally sent messages have zero `timestamp_sent`, it can be a + // useful invariant. + assert_eq!(timestamp_sent, 0); + + let msg_id = send_text_msg(t, chat_id, "Fixed my clock".to_string()).await?; + assert_eq!(t.get_last_msg_in(chat_id).await.id, msg_id); + Ok(()) +} + #[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn test_info_contact_id() -> Result<()> { let mut tcm = TestContextManager::new();