diff --git a/src/chat.rs b/src/chat.rs index 1c2d6ad554..7915520c84 100644 --- a/src/chat.rs +++ b/src/chat.rs @@ -39,6 +39,7 @@ use crate::mimeparser::SystemMessage; use crate::param::{Param, Params}; use crate::peerstate::Peerstate; use crate::receive_imf::ReceivedMsg; +use crate::rusqlite::OptionalExtension; use crate::securejoin::BobState; use crate::smtp::send_msg_to_smtp; use crate::sql; @@ -3316,37 +3317,57 @@ pub async fn marknoticed_chat(context: &Context, chat_id: ChatId) -> Result<()> } } else { let conn_fn = |conn: &mut rusqlite::Connection| { + // This is to trigger emitting `MsgsNoticed` on other devices when reactions are noticed + // locally. We filter out `InNoticed` messages because they are normally a result of + // `mark_old_messages_as_noticed()` which happens on all devices anyway. Also we limit + // this to one message because the effect is the same anyway. + // + // Even if `message::markseen_msgs()` fails then, in the worst case other devices won't + // emit `MsgsNoticed` and app notifications won't be removed. The bigger problem is that + // another device may have more reactions received and not yet seen notifications are + // removed from it, but the same problem already exists for "usual" messages, so let's + // not solve it for now. + let mut stmt = conn.prepare( + "SELECT id, state FROM msgs + WHERE (state=? OR state=? OR state=?) + AND hidden=1 + AND chat_id=? + ORDER BY id DESC LIMIT 1", + )?; + let id_to_markseen = stmt + .query_row( + ( + MessageState::InFresh, + MessageState::InNoticed, + MessageState::InSeen, + chat_id, + ), + |row| { + let id: MsgId = row.get(0)?; + let state: MessageState = row.get(1)?; + Ok((id, state)) + }, + ) + .optional()? + .filter(|&(_, state)| state == MessageState::InFresh) + .map(|(id, _)| id); + let nr_msgs_noticed = conn.execute( "UPDATE msgs SET state=? WHERE state=? - AND hidden=0 AND chat_id=?", (MessageState::InNoticed, MessageState::InFresh, chat_id), )?; - let mut stmt = conn.prepare( - "SELECT id FROM msgs - WHERE state>=? AND state, _>>()?; - Ok((nr_msgs_noticed, hidden_msgs)) + Ok((nr_msgs_noticed, id_to_markseen)) }; - let (nr_msgs_noticed, hidden_msgs) = context.sql.call_write(conn_fn).await?; - if nr_msgs_noticed == 0 && hidden_msgs.is_empty() { + let (nr_msgs_noticed, id_to_markseen) = context.sql.call_write(conn_fn).await?; + if nr_msgs_noticed == 0 { return Ok(()); } - message::markseen_msgs(context, hidden_msgs).await?; + if let Some(id) = id_to_markseen { + message::markseen_msgs(context, vec![id]).await?; + } } context.emit_event(EventType::MsgsNoticed(chat_id));