Skip to content

Commit

Permalink
Emit DC_EVENT_MSGS_CHANGED for DC_CHAT_ID_ARCHIVED_LINK when the numb…
Browse files Browse the repository at this point in the history
…er of archived chats with

unread messages increases (#3940)
  • Loading branch information
iequidoo committed Jan 15, 2023
1 parent c636652 commit 022ca62
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 10 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 #TODO

### API-Changes
- jsonrpc: add verified-by information to `Contact`-Object
Expand Down
31 changes: 31 additions & 0 deletions python/tests/test_1_online.py
Original file line number Diff line number Diff line change
Expand Up @@ -2261,6 +2261,37 @@ 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()
chat.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")
ev = ac2._evtracker.get_matching("DC_EVENT_MSGS_CHANGED")
assert 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


class TestOnlineConfigureFails:
def test_invalid_password(self, acfactory):
configdict = acfactory.get_next_liveconfig()
Expand Down
53 changes: 44 additions & 9 deletions src/chat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -534,13 +534,45 @@ impl ChatId {
// 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<()> {
// 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 && msg_state != MessageState::InNoticed {
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 nr_unread = context
.sql
.count(
"SELECT COUNT(*)
FROM msgs
WHERE (state=? OR state=?)
AND hidden=0
AND chat_id=?;",
paramsv![MessageState::InFresh, MessageState::InNoticed, self],
)
.await?;
if nr_unread > 0 {
return Ok(());
}
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(())
}
Expand Down Expand Up @@ -2017,7 +2049,7 @@ async fn prepare_msg_common(
msg.state = change_state_to;

prepare_msg_blob(context, msg).await?;
chat_id.unarchive_if_not_muted(context).await?;
chat_id.unarchive_if_not_muted(context, msg.state).await?;
msg.id = chat
.prepare_msg_raw(
context,
Expand Down Expand Up @@ -3209,7 +3241,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);
Expand Down Expand Up @@ -3412,7 +3446,8 @@ 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 state = MessageState::InFresh;
chat_id.unarchive_if_not_muted(context, state).await?;

let timestamp_sent = create_smeared_timestamp(context).await;

Expand Down Expand Up @@ -3455,7 +3490,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,
Expand Down
2 changes: 1 addition & 1 deletion src/receive_imf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down

0 comments on commit 022ca62

Please sign in to comment.