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).
This commit is contained in:
iequidoo
2025-10-15 02:04:30 -03:00
committed by link2xt
parent afc74b0829
commit e286d72614
2 changed files with 15 additions and 17 deletions

View File

@@ -1218,12 +1218,11 @@ impl ChatId {
) )
.await? .await?
} else if received { } else if received {
// Received messages shouldn't mingle with just sent ones and appear somewhere in the // Received incoming messages shouldn't mingle with just sent ones and appear somewhere
// middle of the chat, so we go after the newest non fresh message. // 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
// But if a received outgoing message is older than some seen message, better sort the // replies appearing before messages sent from another device (cases like the user
// received message purely by timestamp. We could place it just before that seen // sharing the account with others or bots are rare, so let them break sometimes).
// message, but anyway the user may not notice it.
// //
// NB: Received outgoing messages may break sorting of fresh incoming ones, but this // 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 // shouldn't happen frequently. Seen incoming messages don't really break sorting of
@@ -1231,24 +1230,23 @@ impl ChatId {
context context
.sql .sql
.query_row_optional( .query_row_optional(
"SELECT MAX(timestamp), MAX(IIF(state=?,timestamp_sent,0)) "SELECT MAX(timestamp)
FROM msgs FROM msgs
WHERE chat_id=? AND hidden=0 AND state>? WHERE chat_id=? AND hidden=0 AND state>?
HAVING COUNT(*) > 0", HAVING COUNT(*) > 0",
(MessageState::InSeen, self, MessageState::InFresh), (
self,
match incoming {
true => MessageState::InFresh,
false => MessageState::InSeen,
},
),
|row| { |row| {
let ts: i64 = row.get(0)?; let ts: i64 = row.get(0)?;
let ts_sent_seen: i64 = row.get(1)?; Ok(ts)
Ok((ts, ts_sent_seen))
}, },
) )
.await? .await?
.and_then(|(ts, ts_sent_seen)| {
match incoming || ts_sent_seen <= message_timestamp {
true => Some(ts),
false => None,
}
})
} else { } else {
None None
}; };

View File

@@ -1,5 +1,5 @@
Single#Chat#10: bob@example.net [KEY bob@example.net] Single#Chat#10: bob@example.net [KEY bob@example.net]
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
Msg#10: info (Contact#Contact#Info): Messages are end-to-end encrypted. [NOTICED][INFO]
Msg#11🔒: Me (Contact#Contact#Self): Test This is encrypted, signed, and has an Autocrypt Header without prefer-encrypt=mutual. √ Msg#11🔒: Me (Contact#Contact#Self): Test This is encrypted, signed, and has an Autocrypt Header without prefer-encrypt=mutual. √
Msg#10: info (Contact#Contact#Info): Messages are end-to-end encrypted. [NOTICED][INFO]
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------