mirror of
https://github.com/chatmail/core.git
synced 2026-05-12 11:26:29 +03:00
fix: Emit MsgsChanged if the number of unnoticed archived chats could decrease (#5768)
Follow-up to 3cf78749df "Emit DC_EVENT_MSGS_CHANGED for
DC_CHAT_ID_ARCHIVED_LINK when the number of archived chats with unread messages increases (#3940)".
In general we don't want to make an extra db query to know if a noticied chat is
archived. Emitting events should be cheap, better to allow false-positive `MsgsChanged` events.
This commit is contained in:
69
src/chat.rs
69
src/chat.rs
@@ -3268,35 +3268,25 @@ pub async fn marknoticed_chat(context: &Context, chat_id: ChatId) -> Result<()>
|
|||||||
context.emit_event(EventType::MsgsNoticed(chat_id_in_archive));
|
context.emit_event(EventType::MsgsNoticed(chat_id_in_archive));
|
||||||
chatlist_events::emit_chatlist_item_changed(context, chat_id_in_archive);
|
chatlist_events::emit_chatlist_item_changed(context, chat_id_in_archive);
|
||||||
}
|
}
|
||||||
chatlist_events::emit_chatlist_item_changed(context, DC_CHAT_ID_ARCHIVED_LINK);
|
} else if context
|
||||||
} else {
|
.sql
|
||||||
let exists = context
|
.execute(
|
||||||
.sql
|
"UPDATE msgs
|
||||||
.exists(
|
SET state=?
|
||||||
"SELECT COUNT(*) FROM msgs WHERE state=? AND hidden=0 AND chat_id=?;",
|
WHERE state=?
|
||||||
(MessageState::InFresh, chat_id),
|
AND hidden=0
|
||||||
)
|
AND chat_id=?;",
|
||||||
.await?;
|
(MessageState::InNoticed, MessageState::InFresh, chat_id),
|
||||||
if !exists {
|
)
|
||||||
return Ok(());
|
.await?
|
||||||
}
|
== 0
|
||||||
|
{
|
||||||
context
|
return Ok(());
|
||||||
.sql
|
|
||||||
.execute(
|
|
||||||
"UPDATE msgs
|
|
||||||
SET state=?
|
|
||||||
WHERE state=?
|
|
||||||
AND hidden=0
|
|
||||||
AND chat_id=?;",
|
|
||||||
(MessageState::InNoticed, MessageState::InFresh, chat_id),
|
|
||||||
)
|
|
||||||
.await?;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
context.emit_event(EventType::MsgsNoticed(chat_id));
|
context.emit_event(EventType::MsgsNoticed(chat_id));
|
||||||
chatlist_events::emit_chatlist_item_changed(context, chat_id);
|
chatlist_events::emit_chatlist_item_changed(context, chat_id);
|
||||||
|
context.on_archived_chats_maybe_noticed();
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3359,6 +3349,7 @@ pub(crate) async fn mark_old_messages_as_noticed(
|
|||||||
context,
|
context,
|
||||||
"Marking chats as noticed because there are newer outgoing messages: {changed_chats:?}."
|
"Marking chats as noticed because there are newer outgoing messages: {changed_chats:?}."
|
||||||
);
|
);
|
||||||
|
context.on_archived_chats_maybe_noticed();
|
||||||
}
|
}
|
||||||
|
|
||||||
for c in changed_chats {
|
for c in changed_chats {
|
||||||
@@ -4697,6 +4688,14 @@ impl Context {
|
|||||||
SyncAction::SetContacts(addrs) => set_contacts_by_addrs(self, chat_id, addrs).await,
|
SyncAction::SetContacts(addrs) => set_contacts_by_addrs(self, chat_id, addrs).await,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Emits the appropriate `MsgsChanged` event. Should be called if the number of unnoticed
|
||||||
|
/// archived chats could decrease. In general we don't want to make an extra db query to know if
|
||||||
|
/// a noticied chat is archived. Emitting events should be cheap, a false-positive `MsgsChanged`
|
||||||
|
/// is ok.
|
||||||
|
pub(crate) fn on_archived_chats_maybe_noticed(&self) {
|
||||||
|
self.emit_msgs_changed(DC_CHAT_ID_ARCHIVED_LINK, MsgId::new(0));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
@@ -5868,7 +5867,27 @@ mod tests {
|
|||||||
assert_eq!(DC_CHAT_ID_ARCHIVED_LINK.get_fresh_msg_cnt(&t).await?, 2);
|
assert_eq!(DC_CHAT_ID_ARCHIVED_LINK.get_fresh_msg_cnt(&t).await?, 2);
|
||||||
|
|
||||||
// mark one of the archived+muted chats as noticed: check that the archive-link counter is changed as well
|
// mark one of the archived+muted chats as noticed: check that the archive-link counter is changed as well
|
||||||
|
t.evtracker.clear_events();
|
||||||
marknoticed_chat(&t, claire_chat_id).await?;
|
marknoticed_chat(&t, claire_chat_id).await?;
|
||||||
|
let ev = t
|
||||||
|
.evtracker
|
||||||
|
.get_matching(|ev| {
|
||||||
|
matches!(
|
||||||
|
ev,
|
||||||
|
EventType::MsgsChanged {
|
||||||
|
chat_id: DC_CHAT_ID_ARCHIVED_LINK,
|
||||||
|
..
|
||||||
|
}
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.await;
|
||||||
|
assert_eq!(
|
||||||
|
ev,
|
||||||
|
EventType::MsgsChanged {
|
||||||
|
chat_id: DC_CHAT_ID_ARCHIVED_LINK,
|
||||||
|
msg_id: MsgId::new(0),
|
||||||
|
}
|
||||||
|
);
|
||||||
assert_eq!(bob_chat_id.get_fresh_msg_cnt(&t).await?, 2);
|
assert_eq!(bob_chat_id.get_fresh_msg_cnt(&t).await?, 2);
|
||||||
assert_eq!(claire_chat_id.get_fresh_msg_cnt(&t).await?, 0);
|
assert_eq!(claire_chat_id.get_fresh_msg_cnt(&t).await?, 0);
|
||||||
assert_eq!(DC_CHAT_ID_ARCHIVED_LINK.get_fresh_msg_cnt(&t).await?, 1);
|
assert_eq!(DC_CHAT_ID_ARCHIVED_LINK.get_fresh_msg_cnt(&t).await?, 1);
|
||||||
|
|||||||
@@ -1201,6 +1201,9 @@ impl Session {
|
|||||||
set_modseq(context, folder, highest_modseq)
|
set_modseq(context, folder, highest_modseq)
|
||||||
.await
|
.await
|
||||||
.with_context(|| format!("failed to set MODSEQ for folder {folder}"))?;
|
.with_context(|| format!("failed to set MODSEQ for folder {folder}"))?;
|
||||||
|
if !updated_chat_ids.is_empty() {
|
||||||
|
context.on_archived_chats_maybe_noticed();
|
||||||
|
}
|
||||||
for updated_chat_id in updated_chat_ids {
|
for updated_chat_id in updated_chat_ids {
|
||||||
context.emit_event(EventType::MsgsNoticed(updated_chat_id));
|
context.emit_event(EventType::MsgsNoticed(updated_chat_id));
|
||||||
chatlist_events::emit_chatlist_item_changed(context, updated_chat_id);
|
chatlist_events::emit_chatlist_item_changed(context, updated_chat_id);
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ use serde::{Deserialize, Serialize};
|
|||||||
use tokio::{fs, io};
|
use tokio::{fs, io};
|
||||||
|
|
||||||
use crate::blob::BlobObject;
|
use crate::blob::BlobObject;
|
||||||
use crate::chat::{Chat, ChatId, ChatIdBlocked};
|
use crate::chat::{Chat, ChatId, ChatIdBlocked, ChatVisibility};
|
||||||
use crate::chatlist_events;
|
use crate::chatlist_events;
|
||||||
use crate::config::Config;
|
use crate::config::Config;
|
||||||
use crate::constants::{
|
use crate::constants::{
|
||||||
@@ -1664,6 +1664,7 @@ pub async fn markseen_msgs(context: &Context, msg_ids: Vec<MsgId>) -> Result<()>
|
|||||||
m.param AS param,
|
m.param AS param,
|
||||||
m.from_id AS from_id,
|
m.from_id AS from_id,
|
||||||
m.rfc724_mid AS rfc724_mid,
|
m.rfc724_mid AS rfc724_mid,
|
||||||
|
c.archived AS archived,
|
||||||
c.blocked AS blocked
|
c.blocked AS blocked
|
||||||
FROM msgs m LEFT JOIN chats c ON c.id=m.chat_id
|
FROM msgs m LEFT JOIN chats c ON c.id=m.chat_id
|
||||||
WHERE m.id IN ({}) AND m.chat_id>9",
|
WHERE m.id IN ({}) AND m.chat_id>9",
|
||||||
@@ -1677,16 +1678,20 @@ pub async fn markseen_msgs(context: &Context, msg_ids: Vec<MsgId>) -> Result<()>
|
|||||||
let param: Params = row.get::<_, String>("param")?.parse().unwrap_or_default();
|
let param: Params = row.get::<_, String>("param")?.parse().unwrap_or_default();
|
||||||
let from_id: ContactId = row.get("from_id")?;
|
let from_id: ContactId = row.get("from_id")?;
|
||||||
let rfc724_mid: String = row.get("rfc724_mid")?;
|
let rfc724_mid: String = row.get("rfc724_mid")?;
|
||||||
|
let visibility: ChatVisibility = row.get("archived")?;
|
||||||
let blocked: Option<Blocked> = row.get("blocked")?;
|
let blocked: Option<Blocked> = row.get("blocked")?;
|
||||||
let ephemeral_timer: EphemeralTimer = row.get("ephemeral_timer")?;
|
let ephemeral_timer: EphemeralTimer = row.get("ephemeral_timer")?;
|
||||||
Ok((
|
Ok((
|
||||||
id,
|
(
|
||||||
chat_id,
|
id,
|
||||||
state,
|
chat_id,
|
||||||
param,
|
state,
|
||||||
from_id,
|
param,
|
||||||
rfc724_mid,
|
from_id,
|
||||||
blocked.unwrap_or_default(),
|
rfc724_mid,
|
||||||
|
visibility,
|
||||||
|
blocked.unwrap_or_default(),
|
||||||
|
),
|
||||||
ephemeral_timer,
|
ephemeral_timer,
|
||||||
))
|
))
|
||||||
},
|
},
|
||||||
@@ -1694,25 +1699,28 @@ pub async fn markseen_msgs(context: &Context, msg_ids: Vec<MsgId>) -> Result<()>
|
|||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
if msgs.iter().any(
|
if msgs
|
||||||
|(_id, _chat_id, _state, _param, _from_id, _rfc724_mid, _blocked, ephemeral_timer)| {
|
.iter()
|
||||||
*ephemeral_timer != EphemeralTimer::Disabled
|
.any(|(_, ephemeral_timer)| *ephemeral_timer != EphemeralTimer::Disabled)
|
||||||
},
|
{
|
||||||
) {
|
|
||||||
start_ephemeral_timers_msgids(context, &msg_ids)
|
start_ephemeral_timers_msgids(context, &msg_ids)
|
||||||
.await
|
.await
|
||||||
.context("failed to start ephemeral timers")?;
|
.context("failed to start ephemeral timers")?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut updated_chat_ids = BTreeSet::new();
|
let mut updated_chat_ids = BTreeSet::new();
|
||||||
|
let mut archived_chats_maybe_noticed = false;
|
||||||
for (
|
for (
|
||||||
id,
|
(
|
||||||
curr_chat_id,
|
id,
|
||||||
curr_state,
|
curr_chat_id,
|
||||||
curr_param,
|
curr_state,
|
||||||
curr_from_id,
|
curr_param,
|
||||||
curr_rfc724_mid,
|
curr_from_id,
|
||||||
curr_blocked,
|
curr_rfc724_mid,
|
||||||
|
curr_visibility,
|
||||||
|
curr_blocked,
|
||||||
|
),
|
||||||
_curr_ephemeral_timer,
|
_curr_ephemeral_timer,
|
||||||
) in msgs
|
) in msgs
|
||||||
{
|
{
|
||||||
@@ -1750,12 +1758,17 @@ pub async fn markseen_msgs(context: &Context, msg_ids: Vec<MsgId>) -> Result<()>
|
|||||||
}
|
}
|
||||||
updated_chat_ids.insert(curr_chat_id);
|
updated_chat_ids.insert(curr_chat_id);
|
||||||
}
|
}
|
||||||
|
archived_chats_maybe_noticed |=
|
||||||
|
curr_state == MessageState::InFresh && curr_visibility == ChatVisibility::Archived;
|
||||||
}
|
}
|
||||||
|
|
||||||
for updated_chat_id in updated_chat_ids {
|
for updated_chat_id in updated_chat_ids {
|
||||||
context.emit_event(EventType::MsgsNoticed(updated_chat_id));
|
context.emit_event(EventType::MsgsNoticed(updated_chat_id));
|
||||||
chatlist_events::emit_chatlist_item_changed(context, updated_chat_id);
|
chatlist_events::emit_chatlist_item_changed(context, updated_chat_id);
|
||||||
}
|
}
|
||||||
|
if archived_chats_maybe_noticed {
|
||||||
|
context.on_archived_chats_maybe_noticed();
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user