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:
iequidoo
2023-11-15 02:29:58 -03:00
committed by l
parent ba0a7f1f0b
commit 586aae690c
3 changed files with 68 additions and 6 deletions

View File

@@ -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,
}
}

View File

@@ -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(())
}

View File

@@ -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