mirror of
https://github.com/chatmail/core.git
synced 2026-04-23 00:16:34 +03:00
fix: Fix info-message orderings of verified 1:1 chats (#4545)
Correctly handle messages with old timestamps for verified chats:
* They must not be sorted over a protection-changed info message
* If they change the protection, then they must not be sorted over existing other messages, because then the protection-changed info message would also be above these existing messages.
This PR fixes this:
1. Even seen messages can't be sorted into already-noticed messages anymore. **This also changes DC's behavior in the absence of verified 1:1 chats**. Before this PR, messages that are marked as seen when they are downloaded will always be sorted by their timestamp, even if it's very old.
2. protection-changed info messages are always sorted to the bottom.
**Edit:**
3. There is an exception to rule 1: Outgoing messages are still allowed to be sorted purely by their timestamp, and don't influence old messages. This is to the problem described at [*].
Together, these rules also make sure that the protection-changed info message is always right above the message causing the change.
[*] If we receive messages from two different folders, e.g. `Sent` and `Inbox`, then this will lead to wrong message ordering in many cases. I need to think about this more, or maybe someone else has an idea. One new idea that came to my mind is:
* Always sort noticed messages under the newest info message (this PR sorts them under the newest noticed message, master sorts them purely by their sent timestamp)
* Always sort unnoticed messages under the newest noticed message (that's the same behavior as in this PR and on master)
* Always sort protection-changed info messages to the bottom (as in this PR)
However, after a talk with @link2xt we instead decided to add rule 3. (see above) because it seemed a little bit easier.
This commit is contained in:
@@ -754,8 +754,12 @@ async fn add_parts(
|
||||
new_protection = ProtectionStatus::ProtectionBroken;
|
||||
}
|
||||
|
||||
// The message itself will be sorted under the device message since the device
|
||||
// message is `MessageState::InNoticed`, which means that all following
|
||||
// messages are sorted under it.
|
||||
let sort_timestamp =
|
||||
calc_sort_timestamp(context, sent_timestamp, chat_id, true).await?;
|
||||
calc_sort_timestamp(context, sent_timestamp, chat_id, true, incoming)
|
||||
.await?;
|
||||
chat_id
|
||||
.set_protection(context, new_protection, sort_timestamp, Some(from_id))
|
||||
.await?;
|
||||
@@ -948,7 +952,8 @@ async fn add_parts(
|
||||
};
|
||||
|
||||
let in_fresh = state == MessageState::InFresh;
|
||||
let sort_timestamp = calc_sort_timestamp(context, sent_timestamp, chat_id, in_fresh).await?;
|
||||
let sort_timestamp =
|
||||
calc_sort_timestamp(context, sent_timestamp, chat_id, false, incoming).await?;
|
||||
|
||||
// Apply ephemeral timer changes to the chat.
|
||||
//
|
||||
@@ -1376,25 +1381,41 @@ async fn calc_sort_timestamp(
|
||||
context: &Context,
|
||||
message_timestamp: i64,
|
||||
chat_id: ChatId,
|
||||
is_fresh_msg: bool,
|
||||
always_sort_to_bottom: bool,
|
||||
incoming: bool,
|
||||
) -> Result<i64> {
|
||||
let mut sort_timestamp = message_timestamp;
|
||||
|
||||
// get newest non fresh message for this chat
|
||||
// update sort_timestamp if less than that
|
||||
if is_fresh_msg {
|
||||
let last_msg_time: Option<i64> = context
|
||||
let last_msg_time: Option<i64> = if always_sort_to_bottom {
|
||||
// get newest message for this chat
|
||||
context
|
||||
.sql
|
||||
.query_get_value(
|
||||
"SELECT MAX(timestamp) FROM msgs WHERE chat_id=? AND state>?",
|
||||
(chat_id, MessageState::InFresh),
|
||||
"SELECT MAX(timestamp) FROM msgs WHERE chat_id=?",
|
||||
(chat_id,),
|
||||
)
|
||||
.await?;
|
||||
.await?
|
||||
} else if incoming {
|
||||
// get newest incoming non fresh message for this chat.
|
||||
|
||||
if let Some(last_msg_time) = last_msg_time {
|
||||
if last_msg_time > sort_timestamp {
|
||||
sort_timestamp = last_msg_time;
|
||||
}
|
||||
// If a user hasn't been online for some time, the Inbox is
|
||||
// fetched first and then the Sentbox. In order for Inbox
|
||||
// and Sent messages to be allowed to mingle,
|
||||
// outgoing messages are purely sorted by their sent timestamp.
|
||||
context
|
||||
.sql
|
||||
.query_get_value(
|
||||
"SELECT MAX(timestamp) FROM msgs WHERE chat_id=? AND state>? AND from_id!=?",
|
||||
(chat_id, MessageState::InFresh, ContactId::SELF),
|
||||
)
|
||||
.await?
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
if let Some(last_msg_time) = last_msg_time {
|
||||
if last_msg_time > sort_timestamp {
|
||||
sort_timestamp = last_msg_time;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user