From 1eb44328f071aebeb0fc46a90a77d6ebdf339999 Mon Sep 17 00:00:00 2001 From: iequidoo Date: Wed, 15 Oct 2025 02:04:30 -0300 Subject: [PATCH] feat: calc_sort_timestamp(): Don't look at existing messages' timestamp_sent This makes `calc_sort_timestamp()` a continuous function of the message timestamp, simplifies the SQL query and prepares for creation of a db index for it so that it's fast. Currently it doesn't uses indexes effectively; if a chat has many messages, it's slow, i.e. O(n). --- src/chat.rs | 30 +++++++++----------- test-data/golden/test_outgoing_encrypted_msg | 2 +- 2 files changed, 15 insertions(+), 17 deletions(-) diff --git a/src/chat.rs b/src/chat.rs index 0526eed3d..c010e9268 100644 --- a/src/chat.rs +++ b/src/chat.rs @@ -1211,12 +1211,11 @@ impl ChatId { ) .await? } else if received { - // Received messages shouldn't mingle with just sent ones and appear somewhere in the - // middle of the chat, so we go after the newest non fresh message. - // - // But if a received outgoing message is older than some seen message, better sort the - // received message purely by timestamp. We could place it just before that seen - // message, but anyway the user may not notice it. + // Received incoming messages shouldn't mingle with just sent ones and appear somewhere + // in the middle of the chat, so we go after the newest non fresh message. Received + // outgoing messages are allowed to mingle with seen messages though to avoid seen + // replies appearing before messages sent from another device (cases like the user + // sharing the account with others or bots are rare, so let them break sometimes). // // NB: Received outgoing messages may break sorting of fresh incoming ones, but this // shouldn't happen frequently. Seen incoming messages don't really break sorting of @@ -1224,24 +1223,23 @@ impl ChatId { context .sql .query_row_optional( - "SELECT MAX(timestamp), MAX(IIF(state=?,timestamp_sent,0)) + "SELECT MAX(timestamp) FROM msgs WHERE chat_id=? AND hidden=0 AND state>? HAVING COUNT(*) > 0", - (MessageState::InSeen, self, MessageState::InFresh), + ( + self, + match incoming { + true => MessageState::InFresh, + false => MessageState::InSeen, + }, + ), |row| { let ts: i64 = row.get(0)?; - let ts_sent_seen: i64 = row.get(1)?; - Ok((ts, ts_sent_seen)) + Ok(ts) }, ) .await? - .and_then(|(ts, ts_sent_seen)| { - match incoming || ts_sent_seen <= message_timestamp { - true => Some(ts), - false => None, - } - }) } else { None }; diff --git a/test-data/golden/test_outgoing_encrypted_msg b/test-data/golden/test_outgoing_encrypted_msg index 4b26297c2..984032e74 100644 --- a/test-data/golden/test_outgoing_encrypted_msg +++ b/test-data/golden/test_outgoing_encrypted_msg @@ -1,5 +1,5 @@ Single#Chat#1001: bob@example.net [KEY bob@example.net] -------------------------------------------------------------------------------- -Msg#1001: info (Contact#Contact#Info): Messages are end-to-end encrypted. [NOTICED][INFO] Msg#1002🔒: Me (Contact#Contact#Self): Test – This is encrypted, signed, and has an Autocrypt Header without prefer-encrypt=mutual. √ +Msg#1001: info (Contact#Contact#Info): Messages are end-to-end encrypted. [NOTICED][INFO] --------------------------------------------------------------------------------