mirror of
https://github.com/chatmail/core.git
synced 2026-04-17 13:36:30 +03:00
Set timestamps for system messages
Previously system messages were always added to the end of the chat, even if the message triggering them was sent earlier. This is especially important for messages about disappearing timer reset triggered by classic email messages, as they should be placed right after the message resetting the timer.
This commit is contained in:
27
src/chat.rs
27
src/chat.rs
@@ -381,7 +381,14 @@ impl ChatId {
|
||||
msg.param.set_cmd(cmd);
|
||||
send_msg(context, self, &mut msg).await?;
|
||||
} else {
|
||||
add_info_msg_with_cmd(context, self, msg_text, cmd).await?;
|
||||
add_info_msg_with_cmd(
|
||||
context,
|
||||
self,
|
||||
msg_text,
|
||||
cmd,
|
||||
dc_create_smeared_timestamp(context).await,
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@@ -2981,6 +2988,7 @@ pub(crate) async fn add_info_msg_with_cmd(
|
||||
chat_id: ChatId,
|
||||
text: impl AsRef<str>,
|
||||
cmd: SystemMessage,
|
||||
timestamp: i64,
|
||||
) -> Result<MsgId> {
|
||||
let rfc724_mid = dc_create_outgoing_rfc724_mid(None, "@device");
|
||||
let ephemeral_timer = chat_id.get_ephemeral_timer(context).await?;
|
||||
@@ -2997,7 +3005,7 @@ pub(crate) async fn add_info_msg_with_cmd(
|
||||
chat_id,
|
||||
DC_CONTACT_ID_INFO,
|
||||
DC_CONTACT_ID_INFO,
|
||||
dc_create_smeared_timestamp(context).await,
|
||||
timestamp,
|
||||
Viewtype::Text,
|
||||
MessageState::InNoticed,
|
||||
text.as_ref().to_string(),
|
||||
@@ -3012,8 +3020,16 @@ pub(crate) async fn add_info_msg_with_cmd(
|
||||
Ok(msg_id)
|
||||
}
|
||||
|
||||
pub(crate) async fn add_info_msg(context: &Context, chat_id: ChatId, text: impl AsRef<str>) {
|
||||
if let Err(e) = add_info_msg_with_cmd(context, chat_id, text, SystemMessage::Unknown).await {
|
||||
/// Adds info message with a given text and `timestamp` to the chat.
|
||||
pub(crate) async fn add_info_msg(
|
||||
context: &Context,
|
||||
chat_id: ChatId,
|
||||
text: impl AsRef<str>,
|
||||
timestamp: i64,
|
||||
) {
|
||||
if let Err(e) =
|
||||
add_info_msg_with_cmd(context, chat_id, text, SystemMessage::Unknown, timestamp).await
|
||||
{
|
||||
warn!(context, "Could not add info msg: {}", e);
|
||||
}
|
||||
}
|
||||
@@ -3637,7 +3653,7 @@ mod tests {
|
||||
let chat_id = create_group_chat(&t, ProtectionStatus::Unprotected, "foo")
|
||||
.await
|
||||
.unwrap();
|
||||
add_info_msg(&t, chat_id, "foo info").await;
|
||||
add_info_msg(&t, chat_id, "foo info", 200000).await;
|
||||
|
||||
let msg = t.get_last_msg_in(chat_id).await;
|
||||
assert_eq!(msg.get_chat_id(), chat_id);
|
||||
@@ -3658,6 +3674,7 @@ mod tests {
|
||||
chat_id,
|
||||
"foo bar info",
|
||||
SystemMessage::EphemeralTimerChanged,
|
||||
10000,
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
@@ -798,6 +798,12 @@ async fn add_parts(
|
||||
|
||||
let location_kml_is = mime_parser.location_kml.is_some();
|
||||
|
||||
// correct message_timestamp, it should not be used before,
|
||||
// however, we cannot do this earlier as we need from_id to be set
|
||||
let in_fresh = state == MessageState::InFresh;
|
||||
let rcvd_timestamp = time();
|
||||
let sort_timestamp = calc_sort_timestamp(context, *sent_timestamp, chat_id, in_fresh).await?;
|
||||
|
||||
// Apply ephemeral timer changes to the chat.
|
||||
//
|
||||
// Only non-hidden timers are applied now. Timers from hidden
|
||||
@@ -825,6 +831,7 @@ async fn add_parts(
|
||||
context,
|
||||
chat_id,
|
||||
stock_ephemeral_timer_changed(context, ephemeral_timer, from_id).await,
|
||||
sort_timestamp,
|
||||
)
|
||||
.await;
|
||||
}
|
||||
@@ -868,6 +875,7 @@ async fn add_parts(
|
||||
context,
|
||||
chat_id,
|
||||
format!("Cannot set protection: {}", e),
|
||||
sort_timestamp,
|
||||
)
|
||||
.await;
|
||||
return Ok(chat_id); // do not return an error as this would result in retrying the message
|
||||
@@ -883,12 +891,6 @@ async fn add_parts(
|
||||
}
|
||||
}
|
||||
|
||||
// correct message_timestamp, it should not be used before,
|
||||
// however, we cannot do this earlier as we need from_id to be set
|
||||
let in_fresh = state == MessageState::InFresh;
|
||||
let rcvd_timestamp = time();
|
||||
let sort_timestamp = calc_sort_timestamp(context, *sent_timestamp, chat_id, in_fresh).await?;
|
||||
|
||||
// Ensure replies to messages are sorted after the parent message.
|
||||
//
|
||||
// This is useful in a case where sender clocks are not
|
||||
|
||||
@@ -178,7 +178,9 @@ pub async fn try_decrypt(
|
||||
let mut signatures = HashSet::default();
|
||||
|
||||
if let Some(ref mut peerstate) = peerstate {
|
||||
peerstate.handle_fingerprint_change(context).await?;
|
||||
peerstate
|
||||
.handle_fingerprint_change(context, message_time)
|
||||
.await?;
|
||||
if let Some(key) = &peerstate.public_key {
|
||||
public_keyring_for_validate.add(key.clone());
|
||||
} else if let Some(key) = &peerstate.gossip_key {
|
||||
|
||||
@@ -190,7 +190,7 @@ impl Kml {
|
||||
}
|
||||
}
|
||||
|
||||
// location streaming
|
||||
/// Enables location streaming in chat identified by `chat_id` for `seconds` seconds.
|
||||
pub async fn send_locations_to_chat(context: &Context, chat_id: ChatId, seconds: i64) {
|
||||
let now = time();
|
||||
if !(seconds < 0 || chat_id.is_special()) {
|
||||
@@ -221,7 +221,7 @@ pub async fn send_locations_to_chat(context: &Context, chat_id: ChatId, seconds:
|
||||
.unwrap_or_default();
|
||||
} else if 0 == seconds && is_sending_locations_before {
|
||||
let stock_str = stock_str::msg_location_disabled(context).await;
|
||||
chat::add_info_msg(context, chat_id, stock_str).await;
|
||||
chat::add_info_msg(context, chat_id, stock_str, now).await;
|
||||
}
|
||||
context.emit_event(EventType::ChatModified(chat_id));
|
||||
if 0 != seconds {
|
||||
@@ -716,7 +716,8 @@ pub(crate) async fn job_maybe_send_locations_ended(
|
||||
.await
|
||||
);
|
||||
|
||||
if !(send_begin != 0 && time() <= send_until) {
|
||||
let now = time();
|
||||
if !(send_begin != 0 && now <= send_until) {
|
||||
// still streaming -
|
||||
// may happen as several calls to dc_send_locations_to_chat()
|
||||
// do not un-schedule pending DC_MAYBE_SEND_LOC_ENDED jobs
|
||||
@@ -735,7 +736,7 @@ pub(crate) async fn job_maybe_send_locations_ended(
|
||||
);
|
||||
|
||||
let stock_str = stock_str::msg_location_disabled(context).await;
|
||||
chat::add_info_msg(context, chat_id, stock_str).await;
|
||||
chat::add_info_msg(context, chat_id, stock_str, now).await;
|
||||
context.emit_event(EventType::ChatModified(chat_id));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,8 +19,8 @@ use crate::constants::{
|
||||
use crate::contact::{Contact, Origin};
|
||||
use crate::context::Context;
|
||||
use crate::dc_tools::{
|
||||
dc_get_filebytes, dc_get_filemeta, dc_gm2local_offset, dc_read_file, dc_timestamp_to_str,
|
||||
dc_truncate, time,
|
||||
dc_create_smeared_timestamp, dc_get_filebytes, dc_get_filemeta, dc_gm2local_offset,
|
||||
dc_read_file, dc_timestamp_to_str, dc_truncate, time,
|
||||
};
|
||||
use crate::ephemeral::Timer as EphemeralTimer;
|
||||
use crate::events::EventType;
|
||||
@@ -1805,7 +1805,13 @@ async fn ndn_maybe_add_info_msg(
|
||||
// Tell the user which of the recipients failed if we know that (because in
|
||||
// a group, this might otherwise be unclear)
|
||||
let text = stock_str::failed_sending_to(context, contact.get_display_name()).await;
|
||||
chat::add_info_msg(context, chat_id, text).await;
|
||||
chat::add_info_msg(
|
||||
context,
|
||||
chat_id,
|
||||
text,
|
||||
dc_create_smeared_timestamp(context).await,
|
||||
)
|
||||
.await;
|
||||
context.emit_event(EventType::ChatModified(chat_id));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1347,7 +1347,9 @@ async fn update_gossip_peerstates(
|
||||
peerstate = Some(p);
|
||||
}
|
||||
if let Some(peerstate) = peerstate {
|
||||
peerstate.handle_fingerprint_change(context).await?;
|
||||
peerstate
|
||||
.handle_fingerprint_change(context, message_time)
|
||||
.await?;
|
||||
}
|
||||
|
||||
gossipped_addr.insert(header.addr.clone());
|
||||
|
||||
@@ -260,7 +260,11 @@ impl Peerstate {
|
||||
}
|
||||
|
||||
/// Adds a warning to the chat corresponding to peerstate if fingerprint has changed.
|
||||
pub(crate) async fn handle_fingerprint_change(&self, context: &Context) -> Result<()> {
|
||||
pub(crate) async fn handle_fingerprint_change(
|
||||
&self,
|
||||
context: &Context,
|
||||
timestamp: i64,
|
||||
) -> Result<()> {
|
||||
if self.fingerprint_changed {
|
||||
if let Some(contact_id) = context
|
||||
.sql
|
||||
@@ -273,7 +277,7 @@ impl Peerstate {
|
||||
|
||||
let msg = stock_str::contact_setup_changed(context, self.addr.clone()).await;
|
||||
|
||||
chat::add_info_msg(context, chat_id, msg).await;
|
||||
chat::add_info_msg(context, chat_id, msg, timestamp).await;
|
||||
emit_event!(context, EventType::ChatModified(chat_id));
|
||||
} else {
|
||||
bail!("contact with peerstate.addr {:?} not found", &self.addr);
|
||||
|
||||
@@ -11,6 +11,7 @@ use crate::config::Config;
|
||||
use crate::constants::Blocked;
|
||||
use crate::contact::{addr_normalize, may_be_valid_addr, Contact, Origin};
|
||||
use crate::context::Context;
|
||||
use crate::dc_tools::time;
|
||||
use crate::key::Fingerprint;
|
||||
use crate::log::LogExt;
|
||||
use crate::lot::{Lot, LotState};
|
||||
@@ -160,7 +161,13 @@ async fn decode_openpgp(context: &Context, qr: &str) -> Lot {
|
||||
.await
|
||||
.log_err(context, "Failed to create (new) chat for contact")
|
||||
{
|
||||
chat::add_info_msg(context, chat.id, format!("{} verified.", peerstate.addr)).await;
|
||||
chat::add_info_msg(
|
||||
context,
|
||||
chat.id,
|
||||
format!("{} verified.", peerstate.addr),
|
||||
time(),
|
||||
)
|
||||
.await;
|
||||
}
|
||||
} else if let Some(addr) = addr {
|
||||
lot.state = LotState::QrFprMismatch;
|
||||
|
||||
@@ -14,6 +14,7 @@ use crate::config::Config;
|
||||
use crate::constants::{Blocked, Viewtype, DC_CONTACT_ID_LAST_SPECIAL};
|
||||
use crate::contact::{Contact, Origin, VerifiedStatus};
|
||||
use crate::context::Context;
|
||||
use crate::dc_tools::time;
|
||||
use crate::e2ee::ensure_secret_key_exists;
|
||||
use crate::events::EventType;
|
||||
use crate::headerdef::HeaderDef;
|
||||
@@ -859,7 +860,7 @@ async fn secure_connection_established(
|
||||
"?"
|
||||
};
|
||||
let msg = stock_str::contact_verified(context, addr).await;
|
||||
chat::add_info_msg(context, contact_chat_id, msg).await;
|
||||
chat::add_info_msg(context, contact_chat_id, msg, time()).await;
|
||||
emit_event!(context, EventType::ChatModified(contact_chat_id));
|
||||
info!(context, "StockMessage::ContactVerified posted to 1:1 chat");
|
||||
|
||||
@@ -883,7 +884,7 @@ async fn could_not_establish_secure_connection(
|
||||
)
|
||||
.await;
|
||||
|
||||
chat::add_info_msg(context, contact_chat_id, &msg).await;
|
||||
chat::add_info_msg(context, contact_chat_id, &msg, time()).await;
|
||||
error!(
|
||||
context,
|
||||
"StockMessage::ContactNotVerified posted to 1:1 chat ({})", details
|
||||
|
||||
Reference in New Issue
Block a user