Skip to content

Commit c23ff46

Browse files
iequidoolink2xt
authored andcommitted
fix: Make calc_sort_timestamp() a continuous function of message timestamp
This also simplifies the SQL query in `calc_sort_timestamp()` 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 as well fixes ordering of delayed encrypted outgoing messages; before, they could be sorted above "Messages are end-to-end encrypted."
1 parent 5051240 commit c23ff46

File tree

4 files changed

+59
-27
lines changed

4 files changed

+59
-27
lines changed

src/chat.rs

Lines changed: 37 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -298,7 +298,10 @@ impl ChatId {
298298
let chat = Chat::load_from_db(context, chat_id).await?;
299299

300300
if chat.is_encrypted(context).await? {
301-
chat_id.add_encrypted_msg(context, timestamp).await?;
301+
let respect_delayed_msgs = true;
302+
chat_id
303+
.add_encrypted_msg(context, timestamp, respect_delayed_msgs)
304+
.await?;
302305
}
303306

304307
info!(
@@ -459,15 +462,23 @@ impl ChatId {
459462
}
460463

461464
/// Adds message "Messages are end-to-end encrypted".
462-
async fn add_encrypted_msg(self, context: &Context, timestamp_sort: i64) -> Result<()> {
465+
async fn add_encrypted_msg(
466+
self,
467+
context: &Context,
468+
timestamp_sent: i64,
469+
respect_delayed_msgs: bool,
470+
) -> Result<()> {
463471
let text = stock_str::messages_e2e_encrypted(context).await;
464472
add_info_msg_with_cmd(
465473
context,
466474
self,
467475
&text,
468476
SystemMessage::ChatE2ee,
469-
timestamp_sort,
470-
None,
477+
// Create a time window for delayed encrypted messages so that they are sorted under
478+
// "Messages are end-to-end encrypted." This way time still monotonically increases and
479+
// there's no magic "N years ago" which should be adjusted in the future.
480+
timestamp_sent / if respect_delayed_msgs { 2 } else { 1 },
481+
Some(timestamp_sent),
471482
None,
472483
None,
473484
None,
@@ -1220,37 +1231,35 @@ impl ChatId {
12201231
)
12211232
.await?
12221233
} else if received {
1223-
// Received messages shouldn't mingle with just sent ones and appear somewhere in the
1224-
// middle of the chat, so we go after the newest non fresh message.
1225-
//
1226-
// But if a received outgoing message is older than some seen message, better sort the
1227-
// received message purely by timestamp. We could place it just before that seen
1228-
// message, but anyway the user may not notice it.
1234+
// Received incoming messages shouldn't mingle with just sent ones and appear somewhere
1235+
// in the middle of the chat, so we go after the newest non fresh message. Received
1236+
// outgoing messages are allowed to mingle with seen messages though to avoid seen
1237+
// replies appearing before messages sent from another device (cases like the user
1238+
// sharing the account with others or bots are rare, so let them break sometimes).
12291239
//
12301240
// NB: Received outgoing messages may break sorting of fresh incoming ones, but this
12311241
// shouldn't happen frequently. Seen incoming messages don't really break sorting of
12321242
// fresh ones, they rather mean that older incoming messages are actually seen as well.
12331243
context
12341244
.sql
12351245
.query_row_optional(
1236-
"SELECT MAX(timestamp), MAX(IIF(state=?,timestamp_sent,0))
1246+
"SELECT MAX(timestamp)
12371247
FROM msgs
12381248
WHERE chat_id=? AND hidden=0 AND state>?
12391249
HAVING COUNT(*) > 0",
1240-
(MessageState::InSeen, self, MessageState::InFresh),
1250+
(
1251+
self,
1252+
match incoming {
1253+
true => MessageState::InFresh,
1254+
false => MessageState::InSeen,
1255+
},
1256+
),
12411257
|row| {
12421258
let ts: i64 = row.get(0)?;
1243-
let ts_sent_seen: i64 = row.get(1)?;
1244-
Ok((ts, ts_sent_seen))
1259+
Ok(ts)
12451260
},
12461261
)
12471262
.await?
1248-
.and_then(|(ts, ts_sent_seen)| {
1249-
match incoming || ts_sent_seen <= message_timestamp {
1250-
true => Some(ts),
1251-
false => None,
1252-
}
1253-
})
12541263
} else {
12551264
None
12561265
};
@@ -2425,7 +2434,10 @@ impl ChatIdBlocked {
24252434
&& !chat.param.exists(Param::Devicetalk)
24262435
&& !chat.param.exists(Param::Selftalk)
24272436
{
2428-
chat_id.add_encrypted_msg(context, smeared_time).await?;
2437+
let respect_delayed_msgs = true;
2438+
chat_id
2439+
.add_encrypted_msg(context, smeared_time, respect_delayed_msgs)
2440+
.await?;
24292441
}
24302442

24312443
Ok(Self {
@@ -3487,8 +3499,10 @@ pub(crate) async fn create_group_ex(
34873499
chatlist_events::emit_chatlist_item_changed(context, chat_id);
34883500

34893501
if is_encrypted {
3490-
// Add "Messages are end-to-end encrypted." message.
3491-
chat_id.add_encrypted_msg(context, timestamp).await?;
3502+
let respect_delayed_msgs = false;
3503+
chat_id
3504+
.add_encrypted_msg(context, timestamp, respect_delayed_msgs)
3505+
.await?;
34923506
}
34933507

34943508
if !context.get_config_bool(Config::Bot).await?

src/tests/verified_chats.rs

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -217,9 +217,11 @@ async fn test_degrade_verified_oneonone_chat() -> Result<()> {
217217
/// This test tests that the messages are still in the right order.
218218
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
219219
async fn test_old_message_4() -> Result<()> {
220-
let alice = TestContext::new_alice().await;
220+
let mut tcm = TestContextManager::new();
221+
let alice = &tcm.alice().await;
222+
let bob = &tcm.bob().await;
221223
let msg_incoming = receive_imf(
222-
&alice,
224+
alice,
223225
b"From: Bob <[email protected]>\n\
224226
225227
Message-ID: <[email protected]>\n\
@@ -232,7 +234,7 @@ async fn test_old_message_4() -> Result<()> {
232234
.unwrap();
233235

234236
let msg_sent = receive_imf(
235-
&alice,
237+
alice,
236238
b"From: [email protected]\n\
237239
To: Bob <[email protected]>\n\
238240
Message-ID: <[email protected]>\n\
@@ -247,6 +249,16 @@ async fn test_old_message_4() -> Result<()> {
247249
// The "Happy birthday" message should be shown first, and then the "Thanks" message
248250
assert!(msg_sent.sort_timestamp < msg_incoming.sort_timestamp);
249251

252+
// And now the same for encrypted messages.
253+
let msg_incoming = tcm.send_recv(bob, alice, "Thanks, Alice!").await;
254+
message::markseen_msgs(alice, vec![msg_incoming.id]).await?;
255+
let raw = include_bytes!("../../test-data/message/thunderbird_with_autocrypt.eml");
256+
let msg_sent = receive_imf(alice, raw, true).await?.unwrap();
257+
assert_eq!(msg_sent.chat_id, msg_incoming.chat_id);
258+
assert!(msg_sent.sort_timestamp < msg_incoming.timestamp_sort);
259+
alice
260+
.golden_test_chat(msg_sent.chat_id, "test_old_message_4")
261+
.await;
250262
Ok(())
251263
}
252264

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
2+
--------------------------------------------------------------------------------
3+
Msg#12: info (Contact#Contact#Info): Messages are end-to-end encrypted. [NOTICED][INFO]
4+
Msg#14🔒: Me (Contact#Contact#Self): Test – This is encrypted, signed, and has an Autocrypt Header without prefer-encrypt=mutual. √
5+
Msg#13🔒: (Contact#Contact#11): Thanks, Alice! [SEEN]
6+
--------------------------------------------------------------------------------
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
Group#Chat#11: Group [3 member(s)]
22
--------------------------------------------------------------------------------
3+
Msg#12: info (Contact#Contact#Info): Messages are end-to-end encrypted. [NOTICED][INFO]
34
Msg#13: info (Contact#Contact#Info): [email protected] invited you to join this group.
45

56
Waiting for the device of [email protected] to reply… [NOTICED][INFO]
67
Msg#15: info (Contact#Contact#Info): [email protected] replied, waiting for being added to the group… [NOTICED][INFO]
7-
Msg#12: info (Contact#Contact#Info): Messages are end-to-end encrypted. [NOTICED][INFO]
88
Msg#17🔒: (Contact#Contact#10): Member Me added by [email protected]. [FRESH][INFO]
99
--------------------------------------------------------------------------------

0 commit comments

Comments
 (0)