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:
iequidoo
2023-01-13 15:58:52 -03:00
committed by iequidoo
parent badbf766bb
commit 3cf78749df
4 changed files with 89 additions and 13 deletions

View File

@@ -4,6 +4,8 @@
### Fixes ### Fixes
- Securejoin: Fix adding and handling Autocrypt-Gossip headers #3914 - 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 ### API-Changes
- jsonrpc: add verified-by information to `Contact`-Object - jsonrpc: add verified-by information to `Contact`-Object

View File

@@ -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()] 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: class TestOnlineConfigureFails:
def test_invalid_password(self, acfactory): def test_invalid_password(self, acfactory):
configdict = acfactory.get_next_liveconfig() configdict = acfactory.get_next_liveconfig()

View File

@@ -531,16 +531,50 @@ impl ChatId {
Ok(()) Ok(())
} }
// Unarchives a chat that is archived and not muted. /// 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. /// Needed after 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. /// `msg_state` is the state of the message. Matters only for incoming messages currently. For
pub async fn unarchive_if_not_muted(self, context: &Context) -> Result<()> { /// 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 context
.sql .sql
.execute( .execute("UPDATE chats SET archived=0 WHERE id=?", paramsv![self])
"UPDATE chats SET archived=0 WHERE id=? AND archived=1 AND NOT(muted_until=-1 OR muted_until>?)",
paramsv![self, time()],
)
.await?; .await?;
Ok(()) Ok(())
} }
@@ -2019,7 +2053,9 @@ async fn prepare_msg_common(
msg.state = change_state_to; msg.state = change_state_to;
prepare_msg_blob(context, msg).await?; 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 msg.id = chat
.prepare_msg_raw( .prepare_msg_raw(
context, 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 created_msgs: Vec<MsgId> = Vec::new();
let mut curr_timestamp: i64; 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 Ok(mut chat) = Chat::load_from_db(context, chat_id).await {
if let Some(reason) = chat.why_cant_send(context).await? { if let Some(reason) = chat.why_cant_send(context).await? {
bail!("cannot send to {}: {}", chat_id, reason); 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"); let rfc724_mid = create_outgoing_rfc724_mid(None, "@device");
msg.try_calc_and_set_dimensions(context).await.ok(); msg.try_calc_and_set_dimensions(context).await.ok();
prepare_msg_blob(context, msg).await?; prepare_msg_blob(context, msg).await?;
chat_id.unarchive_if_not_muted(context).await?;
let timestamp_sent = create_smeared_timestamp(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 let row_id = context
.sql .sql
.insert( .insert(
@@ -3457,7 +3495,7 @@ pub async fn add_device_msg_with_importance(
timestamp_sent, timestamp_sent,
timestamp_sent, // timestamp_sent equals timestamp_rcvd timestamp_sent, // timestamp_sent equals timestamp_rcvd
msg.viewtype, msg.viewtype,
MessageState::InFresh, state,
msg.text.as_ref().cloned().unwrap_or_default(), msg.text.as_ref().cloned().unwrap_or_default(),
msg.param.to_string(), msg.param.to_string(),
rfc724_mid, rfc724_mid,
@@ -3466,6 +3504,9 @@ pub async fn add_device_msg_with_importance(
.await?; .await?;
msg_id = MsgId::new(u32::try_from(row_id)?); 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 { if let Some(label) = label {

View File

@@ -1235,7 +1235,7 @@ SET rfc724_mid=excluded.rfc724_mid, chat_id=excluded.chat_id,
replace_msg_id.delete_from_db(context).await?; 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!( info!(
context, context,