diff --git a/src/imap.rs b/src/imap.rs index 9248db7d4f..24117db339 100644 --- a/src/imap.rs +++ b/src/imap.rs @@ -1284,6 +1284,9 @@ impl Session { context.on_archived_chats_maybe_noticed(); } for updated_chat_id in updated_chat_ids { + // NB: There are no other events that remove notifications at least for messages seen on + // other devices, so while we may also remove useful notifications for newer messages, + // we have no other choice. context.emit_event(EventType::MsgsNoticed(updated_chat_id)); chatlist_events::emit_chatlist_item_changed(context, updated_chat_id); } diff --git a/src/reaction.rs b/src/reaction.rs index f0f18b2598..a705fafa83 100644 --- a/src/reaction.rs +++ b/src/reaction.rs @@ -547,6 +547,32 @@ Here's my footer -- bob@example.net" let reactions = get_msg_reactions(&alice, msg.id).await?; assert_eq!(reactions.to_string(), "😀1"); + // Alice receives a seen reaction to her message from Bob. Reactions are assigned to the + // trash chat and shouldn't cause emitting `MsgsNoticed`. + alice.evtracker.clear_events(); + let seen = true; + receive_imf( + &alice, + "To: alice@example.org\n\ +From: bob@example.net\n\ +Date: Today, 29 February 2021 00:00:10 -800\n\ +Message-ID: 56791@example.net\n\ +In-Reply-To: 12345@example.org\n\ +Subject: Meeting\n\ +Mime-Version: 1.0 (1.0)\n\ +Content-Type: text/plain; charset=utf-8\n\ +Content-Disposition: reaction\n\ +\n\ +\u{1F44D}" + .as_bytes(), + seen, + ) + .await?; + let ev = alice + .evtracker + .get_matching_opt(&alice, |e| matches!(e, EventType::MsgsNoticed { .. })) + .await; + assert!(ev.is_none()); Ok(()) } diff --git a/src/receive_imf.rs b/src/receive_imf.rs index 006151306f..6a4e04d51e 100644 --- a/src/receive_imf.rs +++ b/src/receive_imf.rs @@ -614,6 +614,9 @@ pub(crate) async fn receive_imf_inner( chat_id.emit_msg_event(context, *msg_id, mime_parser.incoming && fresh); } } + if !chat_id.is_trash() && received_msg.state == MessageState::InSeen { + context.emit_event(EventType::MsgsNoticed(chat_id)); + } context.new_msgs_notify.notify_one(); mime_parser diff --git a/src/receive_imf/tests.rs b/src/receive_imf/tests.rs index 398471719e..515a09dea8 100644 --- a/src/receive_imf/tests.rs +++ b/src/receive_imf/tests.rs @@ -269,6 +269,31 @@ async fn test_adhoc_groups_merge() -> Result<()> { Ok(()) } +#[tokio::test(flavor = "multi_thread", worker_threads = 2)] +async fn test_msgs_noticed_on_seen_msg() -> Result<()> { + let mut tcm = TestContextManager::new(); + let alice = &tcm.alice().await; + let seen = true; + let rcvd_msg = receive_imf( + alice, + b"From: bob@example.net\n\ + To: alice@example.org\n\ + Message-ID: <3333@example.net>\n\ + Date: Sun, 22 Mar 2020 22:37:57 +0000\n\ + \n\ + This is a seen message.\n", + seen, + ) + .await? + .unwrap(); + let ev = alice + .evtracker + .get_matching(|e| matches!(e, EventType::MsgsNoticed { .. })) + .await; + assert_eq!(ev, EventType::MsgsNoticed(rcvd_msg.chat_id)); + Ok(()) +} + #[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn test_read_receipt_and_unarchive() -> Result<()> { // create alice's account @@ -3009,6 +3034,35 @@ async fn test_read_receipts_dont_unmark_bots() -> Result<()> { Ok(()) } +#[tokio::test(flavor = "multi_thread", worker_threads = 2)] +async fn test_no_msgs_noticed_on_seen_mdn() -> Result<()> { + let mut tcm = TestContextManager::new(); + let alice = &tcm.alice().await; + let bob = &tcm.bob().await; + + let received_msg = tcm.send_recv_accept(alice, bob, "hi").await; + + let mdn_mimefactory = crate::mimefactory::MimeFactory::from_mdn( + bob, + received_msg.from_id, + received_msg.rfc724_mid, + vec![], + ) + .await?; + let rendered_mdn = mdn_mimefactory.render(bob).await?; + let mdn_body = rendered_mdn.message; + + let seen = true; + alice.evtracker.clear_events(); + receive_imf(alice, mdn_body.as_bytes(), seen).await?; + let ev = alice + .evtracker + .get_matching_opt(alice, |e| matches!(e, EventType::MsgsNoticed { .. })) + .await; + assert!(ev.is_none()); + Ok(()) +} + #[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn test_gmx_forwarded_msg() -> Result<()> { let t = TestContext::new_alice().await;