mirror of
https://github.com/chatmail/core.git
synced 2026-05-04 22:06:29 +03:00
feat: Sync chats deletion across devices
Currently broadcast lists creation is synced across devices. Groups creation, in some means, too -- on a group promotion by a first message. Otoh, messages deletion is synced now as well. So, for feature-completeness, sync chats deletion too.
This commit is contained in:
28
src/chat.rs
28
src/chat.rs
@@ -434,7 +434,7 @@ impl ChatId {
|
||||
.ok();
|
||||
}
|
||||
if delete {
|
||||
self.delete(context).await?;
|
||||
self.delete_ex(context, Nosync).await?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@@ -773,6 +773,10 @@ impl ChatId {
|
||||
|
||||
/// Deletes a chat.
|
||||
pub async fn delete(self, context: &Context) -> Result<()> {
|
||||
self.delete_ex(context, Sync).await
|
||||
}
|
||||
|
||||
pub(crate) async fn delete_ex(self, context: &Context, sync: sync::Sync) -> Result<()> {
|
||||
ensure!(
|
||||
!self.is_special(),
|
||||
"bad chat_id, can not be a special chat: {}",
|
||||
@@ -780,6 +784,10 @@ impl ChatId {
|
||||
);
|
||||
|
||||
let chat = Chat::load_from_db(context, self).await?;
|
||||
let sync_id = match sync {
|
||||
Nosync => None,
|
||||
Sync => chat.get_sync_id(context).await?,
|
||||
};
|
||||
|
||||
context
|
||||
.sql
|
||||
@@ -796,12 +804,13 @@ impl ChatId {
|
||||
.await?;
|
||||
|
||||
context.emit_msgs_changed_without_ids();
|
||||
chatlist_events::emit_chatlist_changed(context);
|
||||
|
||||
context
|
||||
.set_config_internal(Config::LastHousekeeping, None)
|
||||
.await?;
|
||||
context.scheduler.interrupt_inbox().await;
|
||||
if let Some(id) = sync_id {
|
||||
self::sync(context, id, SyncAction::Delete)
|
||||
.await
|
||||
.log_err(context)
|
||||
.ok();
|
||||
}
|
||||
|
||||
if chat.is_self_talk() {
|
||||
let mut msg = Message::new_text(stock_str::self_deleted_msg_body(context).await);
|
||||
@@ -809,6 +818,11 @@ impl ChatId {
|
||||
}
|
||||
chatlist_events::emit_chatlist_changed(context);
|
||||
|
||||
context
|
||||
.set_config_internal(Config::LastHousekeeping, None)
|
||||
.await?;
|
||||
context.scheduler.interrupt_inbox().await;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -4875,6 +4889,7 @@ pub(crate) enum SyncAction {
|
||||
Rename(String),
|
||||
/// Set chat contacts by their addresses.
|
||||
SetContacts(Vec<String>),
|
||||
Delete,
|
||||
}
|
||||
|
||||
impl Context {
|
||||
@@ -4934,6 +4949,7 @@ impl Context {
|
||||
}
|
||||
SyncAction::Rename(to) => rename_ex(self, Nosync, chat_id, to).await,
|
||||
SyncAction::SetContacts(addrs) => set_contacts_by_addrs(self, chat_id, addrs).await,
|
||||
SyncAction::Delete => chat_id.delete_ex(self, Nosync).await,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3030,6 +3030,39 @@ async fn test_sync_block_before_first_msg() -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||
async fn test_sync_delete_chat() -> Result<()> {
|
||||
let alice0 = &TestContext::new_alice().await;
|
||||
let alice1 = &TestContext::new_alice().await;
|
||||
for a in [alice0, alice1] {
|
||||
a.set_config_bool(Config::SyncMsgs, true).await?;
|
||||
}
|
||||
let bob = TestContext::new_bob().await;
|
||||
|
||||
let ba_chat = bob.create_chat(alice0).await;
|
||||
let sent_msg = bob.send_text(ba_chat.id, "hi").await;
|
||||
let a0b_chat_id = alice0.recv_msg(&sent_msg).await.chat_id;
|
||||
let a1b_chat_id = alice1.recv_msg(&sent_msg).await.chat_id;
|
||||
a0b_chat_id.accept(alice0).await?;
|
||||
sync(alice0, alice1).await;
|
||||
a0b_chat_id.delete(alice0).await?;
|
||||
sync(alice0, alice1).await;
|
||||
alice1.assert_no_chat(a1b_chat_id).await;
|
||||
|
||||
let bob_grp_chat_id = bob
|
||||
.create_group_with_members(ProtectionStatus::Unprotected, "grp", &[alice0])
|
||||
.await;
|
||||
let sent_msg = bob.send_text(bob_grp_chat_id, "hi").await;
|
||||
let a0_grp_chat_id = alice0.recv_msg(&sent_msg).await.chat_id;
|
||||
let a1_grp_chat_id = alice1.recv_msg(&sent_msg).await.chat_id;
|
||||
a0_grp_chat_id.accept(alice0).await?;
|
||||
sync(alice0, alice1).await;
|
||||
a0_grp_chat_id.delete(alice0).await?;
|
||||
sync(alice0, alice1).await;
|
||||
alice1.assert_no_chat(a1_grp_chat_id).await;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||
async fn test_sync_adhoc_grp() -> Result<()> {
|
||||
let alice0 = &TestContext::new_alice().await;
|
||||
@@ -3212,6 +3245,10 @@ async fn test_sync_broadcast() -> Result<()> {
|
||||
assert!(get_past_chat_contacts(alice1, a1_broadcast_id)
|
||||
.await?
|
||||
.is_empty());
|
||||
|
||||
a0_broadcast_id.delete(alice0).await?;
|
||||
sync(alice0, alice1).await;
|
||||
alice1.assert_no_chat(a1_broadcast_id).await;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
@@ -743,6 +743,15 @@ impl TestContext {
|
||||
Chat::load_from_db(self, chat_id).await.unwrap()
|
||||
}
|
||||
|
||||
pub async fn assert_no_chat(&self, id: ChatId) {
|
||||
assert!(Chat::load_from_db(self, id).await.is_err());
|
||||
assert!(!self
|
||||
.sql
|
||||
.exists("SELECT COUNT(*) FROM chats WHERE id=?", (id,))
|
||||
.await
|
||||
.unwrap());
|
||||
}
|
||||
|
||||
/// Sends out the text message.
|
||||
///
|
||||
/// This is not hooked up to any SMTP-IMAP pipeline, so the other account must call
|
||||
|
||||
Reference in New Issue
Block a user