Centralise the methods to send chatlist events

this is the first step to debouncing
This commit is contained in:
Simon Laux
2024-01-11 03:12:41 +01:00
parent 7483aa532b
commit 2c3734153a
13 changed files with 127 additions and 128 deletions

View File

@@ -46,6 +46,7 @@ use crate::tools::{
create_smeared_timestamps, get_abs_path, gm2local_offset, improve_single_line_input,
smeared_time, strip_rtlo_characters, time, IsNoneOrEmpty,
};
use crate::ui_events;
use crate::webxdc::WEBXDC_SUFFIX;
/// An chat item, such as a message or a marker.
@@ -309,10 +310,8 @@ impl ChatId {
}
};
context.emit_msgs_changed_without_ids();
context.emit_event(EventType::UIChatListChanged);
context.emit_event(EventType::UIChatListItemChanged {
chat_id: Some(chat_id),
});
ui_events::emit_chatlist_changed(context);
ui_events::emit_chatlist_item_changed(context, chat_id);
Ok(chat_id)
}
@@ -429,7 +428,7 @@ impl ChatId {
}
}
}
context.emit_event(EventType::UIChatListChanged);
ui_events::emit_chatlist_changed(context);
if sync.into() {
// NB: For a 1:1 chat this currently triggers `Contact::block()` on other devices.
@@ -452,6 +451,8 @@ impl ChatId {
pub(crate) async fn unblock_ex(self, context: &Context, sync: sync::Sync) -> Result<()> {
self.set_blocked(context, Blocked::Not).await?;
ui_events::emit_chatlist_changed(context);
if sync.into() {
let chat = Chat::load_from_db(context, self).await?;
// TODO: For a 1:1 chat this currently triggers `Contact::unblock()` on other devices.
@@ -461,9 +462,8 @@ impl ChatId {
.await
.log_err(context)
.ok();
context.emit_event(EventType::UIChatListChanged);
}
Ok(())
}
@@ -507,9 +507,7 @@ impl ChatId {
if self.set_blocked(context, Blocked::Not).await? {
context.emit_event(EventType::ChatModified(self));
context.emit_event(EventType::UIChatListItemChanged {
chat_id: Some(self),
});
ui_events::emit_chatlist_item_changed(context, self);
}
if sync.into() {
@@ -552,9 +550,7 @@ impl ChatId {
.await?;
context.emit_event(EventType::ChatModified(self));
context.emit_event(EventType::UIChatListItemChanged {
chat_id: Some(self),
});
ui_events::emit_chatlist_item_changed(context, self);
// make sure, the receivers will get all keys
self.reset_gossiped_timestamp(context).await?;
@@ -603,9 +599,7 @@ impl ChatId {
if protection_status_modified {
self.add_protection_msg(context, protect, contact_id, timestamp_sort)
.await?;
context.emit_event(EventType::UIChatListItemChanged {
chat_id: Some(self),
});
ui_events::emit_chatlist_item_changed(context, self);
}
Ok(())
}
@@ -692,10 +686,8 @@ impl ChatId {
.await?;
context.emit_msgs_changed_without_ids();
context.emit_event(EventType::UIChatListChanged);
context.emit_event(EventType::UIChatListItemChanged {
chat_id: Some(self),
});
ui_events::emit_chatlist_changed(context);
ui_events::emit_chatlist_item_changed(context, self);
if sync.into() {
let chat = Chat::load_from_db(context, self).await?;
@@ -802,7 +794,7 @@ impl ChatId {
.await?;
context.emit_msgs_changed_without_ids();
context.emit_event(EventType::UIChatListChanged);
ui_events::emit_chatlist_changed(context);
context.set_config(Config::LastHousekeeping, None).await?;
context.scheduler.interrupt_inbox().await;
@@ -812,7 +804,7 @@ impl ChatId {
msg.text = stock_str::self_deleted_msg_body(context).await;
add_device_msg(context, None, Some(&mut msg)).await?;
}
context.emit_event(EventType::UIChatListChanged);
ui_events::emit_chatlist_changed(context);
Ok(())
}
@@ -3102,13 +3094,9 @@ pub async fn marknoticed_chat(context: &Context, chat_id: ChatId) -> Result<()>
.await?;
for chat_id_in_archive in chat_ids_in_archive {
context.emit_event(EventType::MsgsNoticed(chat_id_in_archive));
context.emit_event(EventType::UIChatListItemChanged {
chat_id: Some(chat_id_in_archive),
});
ui_events::emit_chatlist_item_changed(context, chat_id_in_archive);
}
context.emit_event(EventType::UIChatListItemChanged {
chat_id: Some(DC_CHAT_ID_ARCHIVED_LINK),
});
ui_events::emit_chatlist_item_changed(context, DC_CHAT_ID_ARCHIVED_LINK);
} else {
let exists = context
.sql
@@ -3135,9 +3123,7 @@ pub async fn marknoticed_chat(context: &Context, chat_id: ChatId) -> Result<()>
}
context.emit_event(EventType::MsgsNoticed(chat_id));
context.emit_event(EventType::UIChatListItemChanged {
chat_id: Some(chat_id),
});
ui_events::emit_chatlist_item_changed(context, chat_id);
Ok(())
}
@@ -3205,7 +3191,7 @@ pub(crate) async fn mark_old_messages_as_noticed(
for c in changed_chats {
context.emit_event(EventType::MsgsNoticed(c));
context.emit_event(EventType::UIChatListItemChanged { chat_id: Some(c) });
ui_events::emit_chatlist_item_changed(context, c);
}
Ok(())
@@ -3368,10 +3354,8 @@ pub async fn create_group_chat(
}
context.emit_msgs_changed_without_ids();
context.emit_event(EventType::UIChatListChanged);
context.emit_event(EventType::UIChatListItemChanged {
chat_id: Some(chat_id),
});
ui_events::emit_chatlist_changed(context);
ui_events::emit_chatlist_item_changed(context, chat_id);
if protect == ProtectionStatus::Protected {
chat_id
@@ -3459,7 +3443,7 @@ pub(crate) async fn create_broadcast_list_ex(
let chat_id = ChatId::new(u32::try_from(row_id)?);
context.emit_msgs_changed_without_ids();
context.emit_event(EventType::UIChatListChanged);
ui_events::emit_chatlist_changed(context);
if sync.into() {
let id = SyncId::Grpid(grpid);
@@ -3737,9 +3721,7 @@ pub(crate) async fn set_muted_ex(
.await
.context(format!("Failed to set mute duration for {chat_id}"))?;
context.emit_event(EventType::ChatModified(chat_id));
context.emit_event(EventType::UIChatListItemChanged {
chat_id: Some(chat_id),
});
ui_events::emit_chatlist_item_changed(context, chat_id);
if sync.into() {
let chat = Chat::load_from_db(context, chat_id).await?;
chat.sync(context, SyncAction::SetMuted(duration))
@@ -3900,9 +3882,7 @@ async fn rename_ex(
sync = Nosync;
}
context.emit_event(EventType::ChatModified(chat_id));
context.emit_event(EventType::UIChatListItemChanged {
chat_id: Some(chat_id),
});
ui_events::emit_chatlist_item_changed(context, chat_id);
success = true;
}
}
@@ -3963,9 +3943,7 @@ pub async fn set_chat_profile_image(
context.emit_msgs_changed(chat_id, msg.id);
}
context.emit_event(EventType::ChatModified(chat_id));
context.emit_event(EventType::UIChatListItemChanged {
chat_id: Some(chat_id),
});
ui_events::emit_chatlist_item_changed(context, chat_id);
Ok(())
}
@@ -4112,9 +4090,7 @@ pub async fn resend_msgs(context: &Context, msg_ids: &[MsgId]) -> Result<()> {
msg_id: msg.id,
});
// note(treefit): only matters if it is the last message in chat (but probably to expensive to check, debounce also solves it)
context.emit_event(EventType::UIChatListItemChanged {
chat_id: Some(msg.chat_id),
});
ui_events::emit_chatlist_item_changed(context, msg.chat_id);
if !create_send_msg_jobs(context, &mut msg).await?.is_empty() {
context.scheduler.interrupt_smtp().await;
}

View File

@@ -38,7 +38,7 @@ use crate::tools::{
duration_to_str, get_abs_path, improve_single_line_input, strip_rtlo_characters, time,
EmailAddress,
};
use crate::{chat, stock_str};
use crate::{chat, stock_str, ui_events};
/// Time during which a contact is considered as seen recently.
const SEEN_RECENTLY_SECONDS: i64 = 600;
@@ -658,7 +658,6 @@ impl Contact {
);
let mut update_addr = false;
let mut updated_name = false;
let row_id = context.sql.transaction(|transaction| {
let row = transaction.query_row(
@@ -762,7 +761,7 @@ impl Contact {
if count > 0 {
// Chat name updated
context.emit_event(EventType::ChatModified(chat_id));
updated_name = true;
ui_events::emit_chatlist_items_changed_for_contact(context, contact_id);
}
}
}
@@ -801,16 +800,6 @@ impl Contact {
let contact_id = ContactId::new(row_id);
if updated_name {
// update the chats the contact that changed their name is part of
// (treefit): could make sense to only update chats where the last message is from the contact, but the db query for that is more expensive
for chat_id in Contact::get_chats_with_contact(context, &contact_id).await? {
context.emit_event(EventType::UIChatListItemChanged {
chat_id: Some(chat_id),
});
}
}
Ok((contact_id, sth_modified))
}
@@ -1564,7 +1553,7 @@ WHERE type=? AND id IN (
}
}
context.emit_event(EventType::UIChatListChanged);
ui_events::emit_chatlist_changed(context);
Ok(())
}
@@ -1613,7 +1602,7 @@ pub(crate) async fn set_profile_image(
if changed {
contact.update_param(context).await?;
context.emit_event(EventType::ContactsChanged(Some(contact_id)));
// TODO update DM chat
ui_events::emit_chatlist_item_changed_for_contacts_dm_chat(context, contact_id);
}
Ok(())
}
@@ -1820,7 +1809,10 @@ impl RecentlySeenLoop {
// Timeout, notify about contact.
if let Some(contact_id) = contact_id {
context.emit_event(EventType::ContactsChanged(Some(*contact_id)));
// TODO update DM chat
ui_events::emit_chatlist_item_changed_for_contacts_dm_chat(
&context,
*contact_id,
);
unseen_queue.pop();
}
}
@@ -1850,7 +1842,10 @@ impl RecentlySeenLoop {
// Event is already in the past.
if let Some(contact_id) = contact_id {
context.emit_event(EventType::ContactsChanged(Some(*contact_id)));
// TODO update DM chat
ui_events::emit_chatlist_item_changed_for_contacts_dm_chat(
&context,
*contact_id,
);
}
unseen_queue.pop();
}

View File

@@ -28,6 +28,7 @@ use crate::sql::Sql;
use crate::stock_str::StockStrings;
use crate::timesmearing::SmearedTimestamp;
use crate::tools::{duration_to_str, time};
use crate::ui_events;
/// Builder for the [`Context`].
///
@@ -485,19 +486,15 @@ impl Context {
/// Emits a MsgsChanged event with specified chat and message ids
pub fn emit_msgs_changed(&self, chat_id: ChatId, msg_id: MsgId) {
self.emit_event(EventType::MsgsChanged { chat_id, msg_id });
self.emit_event(EventType::UIChatListChanged);
self.emit_event(EventType::UIChatListItemChanged {
chat_id: Some(chat_id),
});
ui_events::emit_chatlist_changed(self);
ui_events::emit_chatlist_item_changed(self, chat_id);
}
/// Emits an IncomingMsg event with specified chat and message ids
pub fn emit_incoming_msg(&self, chat_id: ChatId, msg_id: MsgId) {
self.emit_event(EventType::IncomingMsg { chat_id, msg_id });
self.emit_event(EventType::UIChatListChanged);
self.emit_event(EventType::UIChatListItemChanged {
chat_id: Some(chat_id),
});
ui_events::emit_chatlist_changed(self);
ui_events::emit_chatlist_item_changed(self, chat_id);
}
/// Returns a receiver for emitted events.

View File

@@ -13,7 +13,7 @@ use crate::imap::{Imap, ImapActionResult};
use crate::message::{Message, MsgId, Viewtype};
use crate::mimeparser::{MimeMessage, Part};
use crate::tools::time;
use crate::{stock_str, EventType};
use crate::{stock_str, ui_events, EventType};
/// Download limits should not be used below `MIN_DOWNLOAD_LIMIT`.
///
@@ -115,9 +115,7 @@ impl MsgId {
chat_id: msg.chat_id,
msg_id: self,
});
context.emit_event(EventType::UIChatListItemChanged {
chat_id: Some(msg.chat_id),
});
ui_events::emit_chatlist_item_changed(context, msg.chat_id);
Ok(())
}
}

View File

@@ -4,6 +4,7 @@ use async_channel::{self as channel, Receiver, Sender, TrySendError};
use pin_project::pin_project;
mod payload;
pub(crate) mod ui_events;
pub use self::payload::EventType;

58
src/events/ui_events.rs Normal file
View File

@@ -0,0 +1,58 @@
use crate::{
chat::{ChatId, ChatIdBlocked},
contact::{Contact, ContactId},
context::Context,
EventType,
};
use async_channel::{self as channel, Receiver, Sender};
use futures::executor::block_on;
use tokio::time::Duration;
use tokio::{
task,
time::{sleep_until, Instant},
};
/// order or content of chatlist changes (chat ids, not the actual chatlist item)
pub(crate) fn emit_chatlist_changed(context: &Context) {
context.emit_event(EventType::UIChatListChanged);
}
/// Chatlist item of a specific chat changed
pub(crate) fn emit_chatlist_item_changed(context: &Context, chat_id: ChatId) {
context.emit_event(EventType::UIChatListItemChanged {
chat_id: Some(chat_id),
});
}
#[allow(unused)]
/// Used when you don't know which chatlist items changed, this reloads all cached chatlist items in the UI
/// note(treefit): This is not used right now, but I know there will be a point where someone wants it
pub(crate) fn emit_unknown_chatlist_items_changed(context: &Context) {
context.emit_event(EventType::UIChatListItemChanged { chat_id: None });
}
/// update event for dm chat of contact
/// used when recently seen changes and when profile image changes
pub(crate) fn emit_chatlist_item_changed_for_contacts_dm_chat(
context: &Context,
contact_id: ContactId,
) {
block_on(async {
if let Ok(Some(chat_id)) = ChatId::lookup_by_contact(context, contact_id).await {
self::emit_chatlist_item_changed(context, chat_id);
}
});
}
/// update dm for chats that have the contact
/// used when contact changes their name or did AEAP for example
pub(crate) fn emit_chatlist_items_changed_for_contact(context: &Context, contact_id: ContactId) {
// note:(treefit): could make sense to only update chats where the last message is from the contact, but the db query for that is more expensive
block_on(async {
if let Ok(chat_ids) = Contact::get_chats_with_contact(context, &contact_id).await {
for chat_id in chat_ids {
self::emit_chatlist_item_changed(context, chat_id);
}
}
});
}

View File

@@ -42,6 +42,7 @@ use crate::socks::Socks5Config;
use crate::sql;
use crate::stock_str;
use crate::tools::{create_id, duration_to_str};
use crate::ui_events;
pub(crate) mod capabilities;
mod client;
@@ -1319,9 +1320,7 @@ impl Imap {
.with_context(|| format!("failed to set MODSEQ for folder {folder}"))?;
for updated_chat_id in updated_chat_ids {
context.emit_event(EventType::MsgsNoticed(updated_chat_id));
context.emit_event(EventType::UIChatListItemChanged {
chat_id: Some(updated_chat_id),
});
ui_events::emit_chatlist_item_changed(context, updated_chat_id);
}
Ok(())

View File

@@ -14,8 +14,8 @@ use crate::context::Context;
use crate::events::EventType;
use crate::message::{Message, MsgId, Viewtype};
use crate::mimeparser::SystemMessage;
use crate::stock_str;
use crate::tools::{duration_to_str, time};
use crate::{stock_str, ui_events};
/// Location record.
#[derive(Debug, Clone, Default)]
@@ -290,9 +290,7 @@ pub async fn send_locations_to_chat(
chat::add_info_msg(context, chat_id, &stock_str, now).await?;
}
context.emit_event(EventType::ChatModified(chat_id));
context.emit_event(EventType::UIChatListItemChanged {
chat_id: Some(chat_id),
});
ui_events::emit_chatlist_item_changed(context, chat_id);
if 0 != seconds {
context.scheduler.interrupt_location().await;
}
@@ -790,9 +788,7 @@ async fn maybe_send_locations(context: &Context) -> Result<Option<u64>> {
let stock_str = stock_str::msg_location_disabled(context).await;
chat::add_info_msg(context, chat_id, &stock_str, now).await?;
context.emit_event(EventType::ChatModified(chat_id));
context.emit_event(EventType::UIChatListItemChanged {
chat_id: Some(chat_id),
});
ui_events::emit_chatlist_item_changed(context, chat_id);
}
}

View File

@@ -30,6 +30,7 @@ use crate::tools::{
buf_compress, buf_decompress, get_filebytes, get_filemeta, gm2local_offset, read_file, time,
timestamp_to_str, truncate,
};
use crate::ui_events;
/// Message ID, including reserved IDs.
///
@@ -138,9 +139,7 @@ WHERE id=?;
chat_id,
msg_id: self,
});
context.emit_event(EventType::UIChatListItemChanged {
chat_id: Some(chat_id),
});
ui_events::emit_chatlist_item_changed(context, chat_id);
Ok(())
}
@@ -1521,14 +1520,12 @@ pub async fn delete_msgs(context: &Context, msg_ids: &[MsgId]) -> Result<()> {
for modified_chat_id in modified_chat_ids {
context.emit_msgs_changed(modified_chat_id, MsgId::new(0));
context.emit_event(EventType::UIChatListItemChanged {
chat_id: Some(modified_chat_id),
});
ui_events::emit_chatlist_item_changed(context, modified_chat_id);
}
if !msg_ids.is_empty() {
context.emit_msgs_changed_without_ids();
context.emit_event(EventType::UIChatListChanged);
ui_events::emit_chatlist_changed(context);
// Run housekeeping to delete unused blobs.
context.set_config(Config::LastHousekeeping, None).await?;
}
@@ -1661,9 +1658,7 @@ pub async fn markseen_msgs(context: &Context, msg_ids: Vec<MsgId>) -> Result<()>
for updated_chat_id in updated_chat_ids {
context.emit_event(EventType::MsgsNoticed(updated_chat_id));
context.emit_event(EventType::UIChatListItemChanged {
chat_id: Some(updated_chat_id),
});
ui_events::emit_chatlist_item_changed(context, updated_chat_id);
}
Ok(())
@@ -1724,9 +1719,7 @@ pub(crate) async fn set_msg_failed(
chat_id: msg.chat_id,
msg_id: msg.id,
});
context.emit_event(EventType::UIChatListItemChanged {
chat_id: Some(msg.chat_id),
});
ui_events::emit_chatlist_item_changed(context, msg.chat_id);
Ok(())
}

View File

@@ -35,13 +35,12 @@ use crate::message::{
use crate::param::{Param, Params};
use crate::peerstate::Peerstate;
use crate::simplify::{simplify, SimplifiedText};
use crate::stock_str;
use crate::sync::SyncItems;
use crate::tools::{
create_smeared_timestamp, get_filemeta, parse_receive_headers, smeared_time,
strip_rtlo_characters, truncate_by_lines,
};
use crate::{location, tools};
use crate::{location, stock_str, tools, ui_events};
/// A parsed MIME message.
///
@@ -2120,9 +2119,7 @@ async fn handle_mdn(
update_msg_state(context, msg_id, MessageState::OutMdnRcvd).await?;
context.emit_event(EventType::MsgRead { chat_id, msg_id });
// note(treefit): only matters if it is the last message in chat (but probably to expensive to check, debounce also solves it)
context.emit_event(EventType::UIChatListItemChanged {
chat_id: Some(chat_id),
});
ui_events::emit_chatlist_item_changed(context, chat_id);
}
Ok(())
}

View File

@@ -15,7 +15,7 @@ use crate::key::{DcKey, Fingerprint, SignedPublicKey};
use crate::message::Message;
use crate::mimeparser::SystemMessage;
use crate::sql::Sql;
use crate::stock_str;
use crate::{stock_str, ui_events};
/// Type of the public key stored inside the peerstate.
#[derive(Debug)]
@@ -695,13 +695,9 @@ impl Peerstate {
.await?;
}
context.emit_event(EventType::UIChatListChanged);
ui_events::emit_chatlist_changed(context);
// update the chats the contact is part of
for chat_id in Contact::get_chats_with_contact(context, &contact_id).await? {
context.emit_event(EventType::UIChatListItemChanged {
chat_id: Some(chat_id),
});
}
ui_events::emit_chatlist_items_changed_for_contact(context, contact_id);
Ok(())
}

View File

@@ -23,7 +23,6 @@ use crate::ephemeral::{stock_ephemeral_timer_changed, Timer as EphemeralTimer};
use crate::events::EventType;
use crate::headerdef::{HeaderDef, HeaderDefMap};
use crate::imap::{markseen_on_imap_table, GENERATED_PREFIX};
use crate::location;
use crate::log::LogExt;
use crate::message::{
self, rfc724_mid_exists, rfc724_mid_exists_and, Message, MessageState, MessengerMessage, MsgId,
@@ -40,6 +39,7 @@ use crate::stock_str;
use crate::sync::Sync::*;
use crate::tools::{buf_compress, extract_grpid_from_rfc724_mid, strip_rtlo_characters};
use crate::{contact, imap};
use crate::{location, ui_events};
/// This is the struct that is returned after receiving one email (aka MIME message).
///
@@ -1778,10 +1778,8 @@ async fn create_or_lookup_group(
chat::add_to_chat_contacts_table(context, new_chat_id, &members).await?;
context.emit_event(EventType::ChatModified(new_chat_id));
context.emit_event(EventType::UIChatListChanged);
context.emit_event(EventType::UIChatListItemChanged {
chat_id: Some(new_chat_id),
});
ui_events::emit_chatlist_changed(context);
ui_events::emit_chatlist_item_changed(context, new_chat_id);
}
if let Some(chat_id) = chat_id {
@@ -2073,9 +2071,7 @@ async fn apply_group_changes(
if send_event_chat_modified {
context.emit_event(EventType::ChatModified(chat_id));
context.emit_event(EventType::UIChatListItemChanged {
chat_id: Some(chat_id),
});
ui_events::emit_chatlist_item_changed(context, chat_id);
}
Ok((group_changes_msgs, better_msg))
}
@@ -2375,10 +2371,8 @@ async fn create_adhoc_group(
chat::add_to_chat_contacts_table(context, new_chat_id, member_ids).await?;
context.emit_event(EventType::ChatModified(new_chat_id));
context.emit_event(EventType::UIChatListChanged);
context.emit_event(EventType::UIChatListItemChanged {
chat_id: Some(new_chat_id),
});
ui_events::emit_chatlist_changed(context);
ui_events::emit_chatlist_item_changed(context, new_chat_id);
Ok(Some(new_chat_id))
}

View File

@@ -25,6 +25,7 @@ use crate::stock_str;
use crate::sync::Sync::*;
use crate::token;
use crate::tools::time;
use crate::ui_events;
mod bob;
mod bobstate;
@@ -683,9 +684,7 @@ async fn secure_connection_established(
)
.await?;
context.emit_event(EventType::ChatModified(chat_id));
context.emit_event(EventType::UIChatListItemChanged {
chat_id: Some(chat_id),
});
ui_events::emit_chatlist_item_changed(context, chat_id);
Ok(())
}