Skip to content

Commit a089199

Browse files
committed
feat: Mark reactions as IMAP-seen in marknoticed_chat() (#6210)
When a reaction notification is shown in the UIs, there's an option "Mark Read", but the UIs are unaware of reactions message ids, moreover there are no `msgs` rows for reactions in the core, so the UIs just call `marknoticed_chat()` in this case. We don't want to introduce reactions message ids to the UIs (at least currently), but let's make reactions usual messages, just hidden, so that the existing `\Seen` flag synchronisation mechanism works for them, and mark all reactions in the chat as seen in marknoticed_chat().
1 parent e117efa commit a089199

File tree

4 files changed

+73
-33
lines changed

4 files changed

+73
-33
lines changed

src/chat.rs

Lines changed: 36 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3295,10 +3295,10 @@ pub async fn marknoticed_chat(context: &Context, chat_id: ChatId) -> Result<()>
32953295
.query_map(
32963296
"SELECT DISTINCT(m.chat_id) FROM msgs m
32973297
LEFT JOIN chats c ON m.chat_id=c.id
3298-
WHERE m.state=10 AND m.hidden=0 AND m.chat_id>9 AND c.blocked=0 AND c.archived=1",
3299-
(),
3298+
WHERE m.state=10 AND m.chat_id>9 AND c.blocked=0 AND c.archived=1",
3299+
(),
33003300
|row| row.get::<_, ChatId>(0),
3301-
|ids| ids.collect::<Result<Vec<_>, _>>().map_err(Into::into)
3301+
|ids| ids.collect::<Result<Vec<_>, _>>().map_err(Into::into),
33023302
)
33033303
.await?;
33043304
if chat_ids_in_archive.is_empty() {
@@ -3309,7 +3309,7 @@ pub async fn marknoticed_chat(context: &Context, chat_id: ChatId) -> Result<()>
33093309
.sql
33103310
.execute(
33113311
&format!(
3312-
"UPDATE msgs SET state=13 WHERE state=10 AND hidden=0 AND chat_id IN ({});",
3312+
"UPDATE msgs SET state=13 WHERE state=10 AND chat_id IN ({});",
33133313
sql::repeat_vars(chat_ids_in_archive.len())
33143314
),
33153315
rusqlite::params_from_iter(&chat_ids_in_archive),
@@ -3319,20 +3319,38 @@ pub async fn marknoticed_chat(context: &Context, chat_id: ChatId) -> Result<()>
33193319
context.emit_event(EventType::MsgsNoticed(chat_id_in_archive));
33203320
chatlist_events::emit_chatlist_item_changed(context, chat_id_in_archive);
33213321
}
3322-
} else if context
3323-
.sql
3324-
.execute(
3325-
"UPDATE msgs
3326-
SET state=?
3327-
WHERE state=?
3328-
AND hidden=0
3329-
AND chat_id=?;",
3330-
(MessageState::InNoticed, MessageState::InFresh, chat_id),
3331-
)
3332-
.await?
3333-
== 0
3334-
{
3335-
return Ok(());
3322+
} else {
3323+
let conn_fn = |conn: &mut rusqlite::Connection| {
3324+
let nr_msgs_noticed = conn.execute(
3325+
"UPDATE msgs
3326+
SET state=?
3327+
WHERE state=?
3328+
AND hidden=0
3329+
AND chat_id=?",
3330+
(MessageState::InNoticed, MessageState::InFresh, chat_id),
3331+
)?;
3332+
let mut stmt = conn.prepare(
3333+
"SELECT id FROM msgs
3334+
WHERE state>=? AND state<?
3335+
AND hidden=1
3336+
AND chat_id=?",
3337+
)?;
3338+
let hidden_msgs = stmt
3339+
.query_map(
3340+
(MessageState::InFresh, MessageState::InSeen, chat_id),
3341+
|row| {
3342+
let id: MsgId = row.get(0)?;
3343+
Ok(id)
3344+
},
3345+
)?
3346+
.collect::<std::result::Result<Vec<_>, _>>()?;
3347+
Ok((nr_msgs_noticed, hidden_msgs))
3348+
};
3349+
let (nr_msgs_noticed, hidden_msgs) = context.sql.call_write(conn_fn).await?;
3350+
if nr_msgs_noticed == 0 && hidden_msgs.is_empty() {
3351+
return Ok(());
3352+
}
3353+
message::markseen_msgs(context, hidden_msgs).await?;
33363354
}
33373355

33383356
context.emit_event(EventType::MsgsNoticed(chat_id));
@@ -3377,7 +3395,6 @@ pub(crate) async fn mark_old_messages_as_noticed(
33773395
"UPDATE msgs
33783396
SET state=?
33793397
WHERE state=?
3380-
AND hidden=0
33813398
AND chat_id=?
33823399
AND timestamp<=?;",
33833400
(

src/reaction.rs

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -397,7 +397,7 @@ mod tests {
397397
use deltachat_contact_tools::ContactAddress;
398398

399399
use super::*;
400-
use crate::chat::{forward_msgs, get_chat_msgs, send_text_msg};
400+
use crate::chat::{forward_msgs, get_chat_msgs, marknoticed_chat, send_text_msg};
401401
use crate::chatlist::Chatlist;
402402
use crate::config::Config;
403403
use crate::contact::{Contact, Origin};
@@ -641,7 +641,8 @@ Here's my footer -- [email protected]"
641641
assert_eq!(get_chat_msgs(&bob, bob_msg.chat_id).await?.len(), 2);
642642

643643
let bob_reaction_msg = bob.pop_sent_msg().await;
644-
alice.recv_msg_trash(&bob_reaction_msg).await;
644+
let alice_reaction_msg = alice.recv_msg_hidden(&bob_reaction_msg).await;
645+
assert_eq!(alice_reaction_msg.state, MessageState::InFresh);
645646
assert_eq!(get_chat_msgs(&alice, chat_alice.id).await?.len(), 2);
646647

647648
let reactions = get_msg_reactions(&alice, alice_msg.sender_msg_id).await?;
@@ -657,6 +658,20 @@ Here's my footer -- [email protected]"
657658
.await?;
658659
expect_incoming_reactions_event(&alice, alice_msg.sender_msg_id, *bob_id, "👍").await?;
659660

661+
marknoticed_chat(&alice, chat_alice.id).await?;
662+
assert_eq!(
663+
alice_reaction_msg.id.get_state(&alice).await?,
664+
MessageState::InSeen
665+
);
666+
// Reactions don't request MDNs.
667+
assert_eq!(
668+
alice
669+
.sql
670+
.count("SELECT COUNT(*) FROM smtp_mdns", ())
671+
.await?,
672+
0
673+
);
674+
660675
// Alice reacts to own message.
661676
send_reaction(&alice, alice_msg.sender_msg_id, "👍 😀")
662677
.await
@@ -695,7 +710,7 @@ Here's my footer -- [email protected]"
695710
bob_msg1.chat_id.accept(&bob).await?;
696711
send_reaction(&bob, bob_msg1.id, "👍").await?;
697712
let bob_send_reaction = bob.pop_sent_msg().await;
698-
alice.recv_msg_trash(&bob_send_reaction).await;
713+
alice.recv_msg_hidden(&bob_send_reaction).await;
699714
assert!(has_incoming_reactions_event(&alice).await);
700715

701716
let chatlist = Chatlist::try_load(&bob, 0, None, None).await?;
@@ -855,7 +870,7 @@ Here's my footer -- [email protected]"
855870
let bob_reaction_msg = bob.pop_sent_msg().await;
856871

857872
// Alice receives a reaction.
858-
alice.recv_msg_trash(&bob_reaction_msg).await;
873+
alice.recv_msg_hidden(&bob_reaction_msg).await;
859874

860875
let reactions = get_msg_reactions(&alice, alice_msg_id).await?;
861876
assert_eq!(reactions.to_string(), "👍1");
@@ -907,7 +922,7 @@ Here's my footer -- [email protected]"
907922
{
908923
send_reaction(&alice2, alice2_msg.id, "👍").await?;
909924
let msg = alice2.pop_sent_msg().await;
910-
alice1.recv_msg_trash(&msg).await;
925+
alice1.recv_msg_hidden(&msg).await;
911926
}
912927

913928
// Check that the status is still the same.
@@ -929,7 +944,7 @@ Here's my footer -- [email protected]"
929944
let alice1_msg = alice1.recv_msg(&alice0.pop_sent_msg().await).await;
930945

931946
send_reaction(&alice0, alice0_msg_id, "👀").await?;
932-
alice1.recv_msg_trash(&alice0.pop_sent_msg().await).await;
947+
alice1.recv_msg_hidden(&alice0.pop_sent_msg().await).await;
933948

934949
expect_reactions_changed_event(&alice0, chat_id, alice0_msg_id, ContactId::SELF).await?;
935950
expect_reactions_changed_event(&alice1, alice1_msg.chat_id, alice1_msg.id, ContactId::SELF)

src/receive_imf.rs

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -758,7 +758,7 @@ async fn add_parts(
758758
// (of course, the user can add other chats manually later)
759759
let to_id: ContactId;
760760
let state: MessageState;
761-
let mut hidden = false;
761+
let mut hidden = is_reaction;
762762
let mut needs_delete_job = false;
763763
let mut restore_protection = false;
764764

@@ -1016,12 +1016,7 @@ async fn add_parts(
10161016
}
10171017
}
10181018

1019-
state = if seen
1020-
|| fetching_existing_messages
1021-
|| is_mdn
1022-
|| is_reaction
1023-
|| chat_id_blocked == Blocked::Yes
1024-
{
1019+
state = if seen || fetching_existing_messages || is_mdn || chat_id_blocked == Blocked::Yes {
10251020
MessageState::InSeen
10261021
} else {
10271022
MessageState::InFresh
@@ -1230,7 +1225,7 @@ async fn add_parts(
12301225
}
12311226

12321227
let orig_chat_id = chat_id;
1233-
let mut chat_id = if is_mdn || is_reaction {
1228+
let mut chat_id = if is_mdn {
12341229
DC_CHAT_ID_TRASH
12351230
} else {
12361231
chat_id.unwrap_or_else(|| {

src/test_utils.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -607,6 +607,19 @@ impl TestContext {
607607
msg
608608
}
609609

610+
/// Receive a message using the `receive_imf()` pipeline. Panics if it's not hidden.
611+
pub async fn recv_msg_hidden(&self, msg: &SentMessage<'_>) -> Message {
612+
let received = self
613+
.recv_msg_opt(msg)
614+
.await
615+
.expect("receive_imf() seems not to have added a new message to the db");
616+
let msg = Message::load_from_db(self, *received.msg_ids.last().unwrap())
617+
.await
618+
.unwrap();
619+
assert!(msg.hidden);
620+
msg
621+
}
622+
610623
/// Receive a message using the `receive_imf()` pipeline. This is similar
611624
/// to `recv_msg()`, but doesn't assume that the message is shown in the chat.
612625
pub async fn recv_msg_opt(

0 commit comments

Comments
 (0)