diff --git a/src/calls.rs b/src/calls.rs index 4a779a7bc8..7f76428af0 100644 --- a/src/calls.rs +++ b/src/calls.rs @@ -11,7 +11,7 @@ use crate::context::{Context, WeakContext}; use crate::events::EventType; use crate::headerdef::HeaderDef; use crate::log::warn; -use crate::message::{Message, MsgId, Viewtype, markseen_msgs}; +use crate::message::{Message, MsgId, Viewtype}; use crate::mimeparser::{MimeMessage, SystemMessage}; use crate::net::dns::lookup_host_with_cache; use crate::param::Param; @@ -247,7 +247,10 @@ impl Context { if chat.is_contact_request() { chat.id.accept(self).await?; } - markseen_msgs(self, vec![call_id]).await?; + call_id + .mark_as_noticed(self) + .await + .context("Failed to mark incoming call as noticed")?; // send an acceptance message around: to the caller as well as to the other devices of the callee let mut msg = Message { @@ -283,7 +286,10 @@ impl Context { if !call.is_accepted() { if call.is_incoming() { call.mark_as_ended(self).await?; - markseen_msgs(self, vec![call_id]).await?; + call_id + .mark_as_noticed(self) + .await + .context("Failed to mark incoming call as noticed")?; let declined_call_str = stock_str::declined_call(self); call.update_text(self, &declined_call_str).await?; } else { @@ -463,6 +469,11 @@ impl Context { if call.is_incoming() { if from_id == ContactId::SELF { call.mark_as_ended(self).await?; + call.msg + .id + .mark_as_noticed(self) + .await + .context("Failed to mark incoming call as noticed")?; let declined_call_str = stock_str::declined_call(self); call.update_text(self, &declined_call_str).await?; } else { diff --git a/src/calls/calls_tests.rs b/src/calls/calls_tests.rs index 491561a265..2bcc56ab91 100644 --- a/src/calls/calls_tests.rs +++ b/src/calls/calls_tests.rs @@ -2,7 +2,7 @@ use super::*; use crate::chat::forward_msgs; use crate::config::Config; use crate::contact::Contact; -use crate::message::MessageState; +use crate::message::{MessageState, markseen_msgs}; use crate::receive_imf::receive_imf; use crate::test_utils; use crate::test_utils::{ @@ -117,20 +117,18 @@ async fn accept_call() -> Result { bob2_call, } = setup_call().await?; - // Bob accepts the incoming call + // Bob accepts the incoming call. + // Accepting the call marks the message as noticed, but does not send MDN. + // Otherwise second device of Bob will assume Bob has opened the chat + // and mark all messages above the call as noticed. bob.accept_incoming_call(bob_call.id, ACCEPT_INFO.to_string()) .await?; - assert_eq!(bob_call.id.get_state(&bob).await?, MessageState::InSeen); - // Bob sends an MDN to Alice. + assert_eq!(bob_call.id.get_state(&bob).await?, MessageState::InNoticed); assert_eq!( - bob.sql - .count( - "SELECT COUNT(*) FROM smtp_mdns WHERE msg_id=? AND from_id=?", - (bob_call.id, bob_call.from_id) - ) - .await?, - 1 + bob.sql.count("SELECT COUNT(*) FROM smtp_mdns", ()).await?, + 0 ); + assert_text(&bob, bob_call.id, "Incoming video call").await?; bob.evtracker .get_matching(|evt| { @@ -232,19 +230,14 @@ async fn test_accept_call_callee_ends() -> Result<()> { bob2_call, .. } = accept_call().await?; - assert_eq!(bob_call.id.get_state(&bob).await?, MessageState::InSeen); + assert_eq!(bob_call.id.get_state(&bob).await?, MessageState::InNoticed); // Bob has accepted the call and also ends it bob.end_call(bob_call.id).await?; - // Bob sends an MDN to Alice. + assert_eq!(bob_call.id.get_state(&bob).await?, MessageState::InNoticed); assert_eq!( - bob.sql - .count( - "SELECT COUNT(*) FROM smtp_mdns WHERE msg_id=? AND from_id=?", - (bob_call.id, bob_call.from_id) - ) - .await?, - 1 + bob.sql.count("SELECT COUNT(*) FROM smtp_mdns", ()).await?, + 0 ); assert_text(&bob, bob_call.id, "Incoming video call\n<1 minute").await?; bob.evtracker @@ -372,16 +365,14 @@ async fn test_callee_rejects_call() -> Result<()> { // Bob has accepted Alice before, but does not want to talk with Alice bob.end_call(bob_call.id).await?; - assert_eq!(bob_call.id.get_state(&bob).await?, MessageState::InSeen); - // Bob sends an MDN to Alice. + + // The call may be declined from a notification. + // Declining the call does not mean that Bob has seen the + // call message in the chat or opened the chat. + assert_eq!(bob_call.id.get_state(&bob).await?, MessageState::InNoticed); assert_eq!( - bob.sql - .count( - "SELECT COUNT(*) FROM smtp_mdns WHERE msg_id=? AND from_id=?", - (bob_call.id, bob_call.from_id) - ) - .await?, - 1 + bob.sql.count("SELECT COUNT(*) FROM smtp_mdns", ()).await?, + 0 ); assert_text(&bob, bob_call.id, "Declined call").await?; bob.evtracker @@ -389,6 +380,8 @@ async fn test_callee_rejects_call() -> Result<()> { .await; let sent3 = bob.pop_sent_msg().await; assert_eq!(call_state(&bob, bob_call.id).await?, CallState::Declined); + let bob_call = Message::load_from_db(&bob, bob_call.id).await?; + assert_eq!(bob_call.state, MessageState::InNoticed); bob2.recv_msg_trash(&sent3).await; assert_text(&bob2, bob2_call.id, "Declined call").await?; @@ -396,6 +389,8 @@ async fn test_callee_rejects_call() -> Result<()> { .get_matching(|evt| matches!(evt, EventType::CallEnded { .. })) .await; assert_eq!(call_state(&bob2, bob2_call.id).await?, CallState::Declined); + let bob2_call = Message::load_from_db(&bob2, bob2_call.id).await?; + assert_eq!(bob2_call.state, MessageState::InNoticed); // Alice receives decline message alice.recv_msg_trash(&sent3).await; diff --git a/src/message.rs b/src/message.rs index f6def15ada..891c89567c 100644 --- a/src/message.rs +++ b/src/message.rs @@ -172,6 +172,18 @@ SELECT ?1, rfc724_mid, pre_rfc724_mid, timestamp, ?, ? FROM msgs WHERE id=?1 Ok(true) } + /// Marks incoming message as noticed if it is fresh. + pub(crate) async fn mark_as_noticed(self, context: &Context) -> Result<()> { + context + .sql + .execute( + "UPDATE msgs SET state=? WHERE id=? AND state=?", + (MessageState::InNoticed, self, MessageState::InFresh), + ) + .await?; + Ok(()) + } + /// Bad evil escape hatch. /// /// Avoid using this, eventually types should be cleaned up enough