@@ -39,6 +39,7 @@ use crate::mimeparser::SystemMessage;
39
39
use crate :: param:: { Param , Params } ;
40
40
use crate :: peerstate:: Peerstate ;
41
41
use crate :: receive_imf:: ReceivedMsg ;
42
+ use crate :: rusqlite:: OptionalExtension ;
42
43
use crate :: securejoin:: BobState ;
43
44
use crate :: smtp:: send_msg_to_smtp;
44
45
use crate :: sql;
@@ -3316,37 +3317,57 @@ pub async fn marknoticed_chat(context: &Context, chat_id: ChatId) -> Result<()>
3316
3317
}
3317
3318
} else {
3318
3319
let conn_fn = |conn : & mut rusqlite:: Connection | {
3320
+ // This is to trigger emitting `MsgsNoticed` on other devices when reactions are noticed
3321
+ // locally. We filter out `InNoticed` messages because they are normally a result of
3322
+ // `mark_old_messages_as_noticed()` which happens on all devices anyway. Also we limit
3323
+ // this to one message because the effect is the same anyway.
3324
+ //
3325
+ // Even if `message::markseen_msgs()` fails then, in the worst case other devices won't
3326
+ // emit `MsgsNoticed` and app notifications won't be removed. The bigger problem is that
3327
+ // another device may have more reactions received and not yet seen notifications are
3328
+ // removed from it, but the same problem already exists for "usual" messages, so let's
3329
+ // not solve it for now.
3330
+ let mut stmt = conn. prepare (
3331
+ "SELECT id, state FROM msgs
3332
+ WHERE (state=? OR state=? OR state=?)
3333
+ AND hidden=1
3334
+ AND chat_id=?
3335
+ ORDER BY id DESC LIMIT 1" ,
3336
+ ) ?;
3337
+ let id_to_markseen = stmt
3338
+ . query_row (
3339
+ (
3340
+ MessageState :: InFresh ,
3341
+ MessageState :: InNoticed ,
3342
+ MessageState :: InSeen ,
3343
+ chat_id,
3344
+ ) ,
3345
+ |row| {
3346
+ let id: MsgId = row. get ( 0 ) ?;
3347
+ let state: MessageState = row. get ( 1 ) ?;
3348
+ Ok ( ( id, state) )
3349
+ } ,
3350
+ )
3351
+ . optional ( ) ?
3352
+ . filter ( |& ( _, state) | state == MessageState :: InFresh )
3353
+ . map ( |( id, _) | id) ;
3354
+
3319
3355
let nr_msgs_noticed = conn. execute (
3320
3356
"UPDATE msgs
3321
3357
SET state=?
3322
3358
WHERE state=?
3323
- AND hidden=0
3324
3359
AND chat_id=?" ,
3325
3360
( MessageState :: InNoticed , MessageState :: InFresh , chat_id) ,
3326
3361
) ?;
3327
- let mut stmt = conn. prepare (
3328
- "SELECT id FROM msgs
3329
- WHERE state>=? AND state<?
3330
- AND hidden=1
3331
- AND chat_id=?
3332
- ORDER BY id DESC LIMIT 100" ,
3333
- ) ?;
3334
- let hidden_msgs = stmt
3335
- . query_map (
3336
- ( MessageState :: InFresh , MessageState :: InSeen , chat_id) ,
3337
- |row| {
3338
- let id: MsgId = row. get ( 0 ) ?;
3339
- Ok ( id)
3340
- } ,
3341
- ) ?
3342
- . collect :: < std:: result:: Result < Vec < _ > , _ > > ( ) ?;
3343
- Ok ( ( nr_msgs_noticed, hidden_msgs) )
3362
+ Ok ( ( nr_msgs_noticed, id_to_markseen) )
3344
3363
} ;
3345
- let ( nr_msgs_noticed, hidden_msgs ) = context. sql . call_write ( conn_fn) . await ?;
3346
- if nr_msgs_noticed == 0 && hidden_msgs . is_empty ( ) {
3364
+ let ( nr_msgs_noticed, id_to_markseen ) = context. sql . call_write ( conn_fn) . await ?;
3365
+ if nr_msgs_noticed == 0 {
3347
3366
return Ok ( ( ) ) ;
3348
3367
}
3349
- message:: markseen_msgs ( context, hidden_msgs) . await ?;
3368
+ if let Some ( id) = id_to_markseen {
3369
+ message:: markseen_msgs ( context, vec ! [ id] ) . await ?;
3370
+ }
3350
3371
}
3351
3372
3352
3373
context. emit_event ( EventType :: MsgsNoticed ( chat_id) ) ;
0 commit comments