mirror of
https://github.com/chatmail/core.git
synced 2026-05-22 16:26:31 +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();
|
.ok();
|
||||||
}
|
}
|
||||||
if delete {
|
if delete {
|
||||||
self.delete(context).await?;
|
self.delete_ex(context, Nosync).await?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -773,6 +773,10 @@ impl ChatId {
|
|||||||
|
|
||||||
/// Deletes a chat.
|
/// Deletes a chat.
|
||||||
pub async fn delete(self, context: &Context) -> Result<()> {
|
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!(
|
ensure!(
|
||||||
!self.is_special(),
|
!self.is_special(),
|
||||||
"bad chat_id, can not be a special chat: {}",
|
"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 chat = Chat::load_from_db(context, self).await?;
|
||||||
|
let sync_id = match sync {
|
||||||
|
Nosync => None,
|
||||||
|
Sync => chat.get_sync_id(context).await?,
|
||||||
|
};
|
||||||
|
|
||||||
context
|
context
|
||||||
.sql
|
.sql
|
||||||
@@ -796,12 +804,13 @@ impl ChatId {
|
|||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
context.emit_msgs_changed_without_ids();
|
context.emit_msgs_changed_without_ids();
|
||||||
chatlist_events::emit_chatlist_changed(context);
|
|
||||||
|
|
||||||
context
|
if let Some(id) = sync_id {
|
||||||
.set_config_internal(Config::LastHousekeeping, None)
|
self::sync(context, id, SyncAction::Delete)
|
||||||
.await?;
|
.await
|
||||||
context.scheduler.interrupt_inbox().await;
|
.log_err(context)
|
||||||
|
.ok();
|
||||||
|
}
|
||||||
|
|
||||||
if chat.is_self_talk() {
|
if chat.is_self_talk() {
|
||||||
let mut msg = Message::new_text(stock_str::self_deleted_msg_body(context).await);
|
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);
|
chatlist_events::emit_chatlist_changed(context);
|
||||||
|
|
||||||
|
context
|
||||||
|
.set_config_internal(Config::LastHousekeeping, None)
|
||||||
|
.await?;
|
||||||
|
context.scheduler.interrupt_inbox().await;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4875,6 +4889,7 @@ pub(crate) enum SyncAction {
|
|||||||
Rename(String),
|
Rename(String),
|
||||||
/// Set chat contacts by their addresses.
|
/// Set chat contacts by their addresses.
|
||||||
SetContacts(Vec<String>),
|
SetContacts(Vec<String>),
|
||||||
|
Delete,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Context {
|
impl Context {
|
||||||
@@ -4934,6 +4949,7 @@ impl Context {
|
|||||||
}
|
}
|
||||||
SyncAction::Rename(to) => rename_ex(self, Nosync, chat_id, to).await,
|
SyncAction::Rename(to) => rename_ex(self, Nosync, chat_id, to).await,
|
||||||
SyncAction::SetContacts(addrs) => set_contacts_by_addrs(self, chat_id, addrs).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(())
|
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)]
|
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||||
async fn test_sync_adhoc_grp() -> Result<()> {
|
async fn test_sync_adhoc_grp() -> Result<()> {
|
||||||
let alice0 = &TestContext::new_alice().await;
|
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)
|
assert!(get_past_chat_contacts(alice1, a1_broadcast_id)
|
||||||
.await?
|
.await?
|
||||||
.is_empty());
|
.is_empty());
|
||||||
|
|
||||||
|
a0_broadcast_id.delete(alice0).await?;
|
||||||
|
sync(alice0, alice1).await;
|
||||||
|
alice1.assert_no_chat(a1_broadcast_id).await;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -743,6 +743,15 @@ impl TestContext {
|
|||||||
Chat::load_from_db(self, chat_id).await.unwrap()
|
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.
|
/// Sends out the text message.
|
||||||
///
|
///
|
||||||
/// This is not hooked up to any SMTP-IMAP pipeline, so the other account must call
|
/// This is not hooked up to any SMTP-IMAP pipeline, so the other account must call
|
||||||
|
|||||||
Reference in New Issue
Block a user