mirror of
https://github.com/chatmail/core.git
synced 2026-04-17 21:46:35 +03:00
Emit DC_EVENT_MSGS_CHANGED for DC_CHAT_ID_ARCHIVED_LINK when the number of archived chats with
unread messages increases (#3940)
This commit is contained in:
@@ -4,6 +4,8 @@
|
||||
|
||||
### Fixes
|
||||
- Securejoin: Fix adding and handling Autocrypt-Gossip headers #3914
|
||||
- Emit DC_EVENT_MSGS_CHANGED for DC_CHAT_ID_ARCHIVED_LINK when the number of archived chats with
|
||||
unread messages increases #3959
|
||||
|
||||
### API-Changes
|
||||
- jsonrpc: add verified-by information to `Contact`-Object
|
||||
|
||||
@@ -2261,6 +2261,39 @@ def test_aeap_flow_verified(acfactory, lp):
|
||||
assert ac1new.get_config("addr") in [contact.addr for contact in msg_in_2.chat.get_contacts()]
|
||||
|
||||
|
||||
def test_archived_muted_chat(acfactory, lp):
|
||||
"""If an archived and muted chat receives a new message, DC_EVENT_MSGS_CHANGED for
|
||||
DC_CHAT_ID_ARCHIVED_LINK must be generated if the chat had only seen messages previously.
|
||||
"""
|
||||
ac1, ac2 = acfactory.get_online_accounts(2)
|
||||
chat = acfactory.get_accepted_chat(ac1, ac2)
|
||||
|
||||
lp.sec("ac1: send message to ac2")
|
||||
chat.send_text("message0")
|
||||
|
||||
lp.sec("wait for ac2 to receive message")
|
||||
msg2 = ac2._evtracker.wait_next_incoming_message()
|
||||
assert msg2.text == "message0"
|
||||
msg2.mark_seen()
|
||||
|
||||
chat2 = msg2.chat
|
||||
chat2.archive()
|
||||
chat2.mute()
|
||||
|
||||
lp.sec("ac1: send another message to ac2")
|
||||
chat.send_text("message1")
|
||||
|
||||
lp.sec("wait for ac2 to receive DC_EVENT_MSGS_CHANGED for DC_CHAT_ID_ARCHIVED_LINK")
|
||||
while 1:
|
||||
ev = ac2._evtracker.get_matching("DC_EVENT_MSGS_CHANGED")
|
||||
if ev.data1 == const.DC_CHAT_ID_ARCHIVED_LINK:
|
||||
assert ev.data2 == 0
|
||||
archive = ac2.get_chat_by_id(const.DC_CHAT_ID_ARCHIVED_LINK)
|
||||
assert archive.count_fresh_messages() == 1
|
||||
assert chat2.count_fresh_messages() == 1
|
||||
break
|
||||
|
||||
|
||||
class TestOnlineConfigureFails:
|
||||
def test_invalid_password(self, acfactory):
|
||||
configdict = acfactory.get_next_liveconfig()
|
||||
|
||||
65
src/chat.rs
65
src/chat.rs
@@ -531,16 +531,50 @@ impl ChatId {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Unarchives a chat that is archived and not muted.
|
||||
// Needed when a message is added to a chat so that the chat gets a normal visibility again.
|
||||
// Sending an appropriate event is up to the caller.
|
||||
pub async fn unarchive_if_not_muted(self, context: &Context) -> Result<()> {
|
||||
/// Unarchives a chat that is archived and not muted.
|
||||
/// Needed after a message is added to a chat so that the chat gets a normal visibility again.
|
||||
/// `msg_state` is the state of the message. Matters only for incoming messages currently. For
|
||||
/// multiple outgoing messages the function may be called once with MessageState::Undefined.
|
||||
/// Sending an appropriate event is up to the caller.
|
||||
/// Also emits DC_EVENT_MSGS_CHANGED for DC_CHAT_ID_ARCHIVED_LINK when the number of archived
|
||||
/// chats with unread messages increases (which is possible if the chat is muted).
|
||||
pub async fn unarchive_if_not_muted(
|
||||
self,
|
||||
context: &Context,
|
||||
msg_state: MessageState,
|
||||
) -> Result<()> {
|
||||
if msg_state != MessageState::InFresh {
|
||||
context.sql.execute(
|
||||
"UPDATE chats SET archived=0 WHERE id=? AND NOT(muted_until=-1 OR muted_until>?)",
|
||||
paramsv![self, time()],
|
||||
).await?;
|
||||
return Ok(());
|
||||
}
|
||||
let chat = Chat::load_from_db(context, self).await?;
|
||||
if chat.visibility != ChatVisibility::Archived {
|
||||
return Ok(());
|
||||
}
|
||||
if chat.is_muted() {
|
||||
let unread_cnt = context
|
||||
.sql
|
||||
.count(
|
||||
"SELECT COUNT(*)
|
||||
FROM msgs
|
||||
WHERE state=?
|
||||
AND hidden=0
|
||||
AND chat_id=?",
|
||||
paramsv![MessageState::InFresh, self],
|
||||
)
|
||||
.await?;
|
||||
if unread_cnt == 1 {
|
||||
// Added the first unread message in the chat.
|
||||
context.emit_msgs_changed(DC_CHAT_ID_ARCHIVED_LINK, MsgId::new(0));
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
context
|
||||
.sql
|
||||
.execute(
|
||||
"UPDATE chats SET archived=0 WHERE id=? AND archived=1 AND NOT(muted_until=-1 OR muted_until>?)",
|
||||
paramsv![self, time()],
|
||||
)
|
||||
.execute("UPDATE chats SET archived=0 WHERE id=?", paramsv![self])
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
@@ -2019,7 +2053,9 @@ async fn prepare_msg_common(
|
||||
msg.state = change_state_to;
|
||||
|
||||
prepare_msg_blob(context, msg).await?;
|
||||
chat_id.unarchive_if_not_muted(context).await?;
|
||||
if !msg.hidden {
|
||||
chat_id.unarchive_if_not_muted(context, msg.state).await?;
|
||||
}
|
||||
msg.id = chat
|
||||
.prepare_msg_raw(
|
||||
context,
|
||||
@@ -3211,7 +3247,9 @@ pub async fn forward_msgs(context: &Context, msg_ids: &[MsgId], chat_id: ChatId)
|
||||
let mut created_msgs: Vec<MsgId> = Vec::new();
|
||||
let mut curr_timestamp: i64;
|
||||
|
||||
chat_id.unarchive_if_not_muted(context).await?;
|
||||
chat_id
|
||||
.unarchive_if_not_muted(context, MessageState::Undefined)
|
||||
.await?;
|
||||
if let Ok(mut chat) = Chat::load_from_db(context, chat_id).await {
|
||||
if let Some(reason) = chat.why_cant_send(context).await? {
|
||||
bail!("cannot send to {}: {}", chat_id, reason);
|
||||
@@ -3414,7 +3452,6 @@ pub async fn add_device_msg_with_importance(
|
||||
let rfc724_mid = create_outgoing_rfc724_mid(None, "@device");
|
||||
msg.try_calc_and_set_dimensions(context).await.ok();
|
||||
prepare_msg_blob(context, msg).await?;
|
||||
chat_id.unarchive_if_not_muted(context).await?;
|
||||
|
||||
let timestamp_sent = create_smeared_timestamp(context).await;
|
||||
|
||||
@@ -3434,6 +3471,7 @@ pub async fn add_device_msg_with_importance(
|
||||
}
|
||||
}
|
||||
|
||||
let state = MessageState::InFresh;
|
||||
let row_id = context
|
||||
.sql
|
||||
.insert(
|
||||
@@ -3457,7 +3495,7 @@ pub async fn add_device_msg_with_importance(
|
||||
timestamp_sent,
|
||||
timestamp_sent, // timestamp_sent equals timestamp_rcvd
|
||||
msg.viewtype,
|
||||
MessageState::InFresh,
|
||||
state,
|
||||
msg.text.as_ref().cloned().unwrap_or_default(),
|
||||
msg.param.to_string(),
|
||||
rfc724_mid,
|
||||
@@ -3466,6 +3504,9 @@ pub async fn add_device_msg_with_importance(
|
||||
.await?;
|
||||
|
||||
msg_id = MsgId::new(u32::try_from(row_id)?);
|
||||
if !msg.hidden {
|
||||
chat_id.unarchive_if_not_muted(context, state).await?;
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(label) = label {
|
||||
|
||||
@@ -1235,7 +1235,7 @@ SET rfc724_mid=excluded.rfc724_mid, chat_id=excluded.chat_id,
|
||||
replace_msg_id.delete_from_db(context).await?;
|
||||
}
|
||||
|
||||
chat_id.unarchive_if_not_muted(context).await?;
|
||||
chat_id.unarchive_if_not_muted(context, state).await?;
|
||||
|
||||
info!(
|
||||
context,
|
||||
|
||||
Reference in New Issue
Block a user