feat: Sync Contact::blocked across devices (#4817)

This commit is contained in:
iequidoo
2023-10-22 01:10:44 -03:00
committed by iequidoo
parent 03f2635296
commit 168021523f
3 changed files with 38 additions and 10 deletions

View File

@@ -372,7 +372,7 @@ impl ChatId {
context,
"Blocking the contact {contact_id} to block 1:1 chat."
);
Contact::block(context, contact_id).await?;
Contact::block(&context.nosync(), contact_id).await?;
}
}
}
@@ -388,6 +388,7 @@ impl ChatId {
}
if !nosync {
// NB: For a 1:1 chat this currently triggers `Contact::block()` on other devices.
chat.add_sync_item(context, ChatAction::Block).await?;
}
Ok(())
@@ -401,6 +402,9 @@ impl ChatId {
if !nosync {
let chat = Chat::load_from_db(context, self).await?;
// TODO: For a 1:1 chat this currently triggers `Contact::unblock()` on other devices.
// Maybe we should unblock the contact locally too, this would also resolve discrepancy
// with `block()` which also blocks the contact.
chat.add_sync_item(context, ChatAction::Unblock).await?;
}
Ok(())
@@ -4035,6 +4039,11 @@ impl Context {
warn!(self, "sync_alter_chat: No contact for addr '{addr}'.");
return Ok(());
};
match &data.action {
ChatAction::Block => return Contact::block(self, contact_id).await,
ChatAction::Unblock => return Contact::unblock(self, contact_id).await,
_ => (),
}
let Some(chat_id) = ChatId::lookup_by_contact(self, contact_id).await? else {
warn!(self, "sync_alter_chat: No chat for addr '{addr}'.");
return Ok(());

View File

@@ -32,6 +32,7 @@ use crate::mimeparser::AvatarAction;
use crate::param::{Param, Params};
use crate::peerstate::{Peerstate, PeerstateVerifiedStatus};
use crate::sql::{self, params_iter};
use crate::sync::{self, SyncData};
use crate::tools::{
duration_to_str, get_abs_path, improve_single_line_input, strip_rtlo_characters, time,
EmailAddress,
@@ -494,7 +495,7 @@ impl Contact {
}
}
if blocked {
Contact::unblock(context, contact_id).await?;
Contact::unblock(&context.nosync(), contact_id).await?;
}
Ok(contact_id)
@@ -1393,6 +1394,7 @@ async fn set_block_contact(
"Can't block special contact {}",
contact_id
);
let (context, nosync) = &context.unwrap_nosync();
let contact = Contact::get_by_id(context, contact_id).await?;
@@ -1438,6 +1440,19 @@ WHERE type=? AND id IN (
chat_id.unblock(&context.nosync()).await?;
}
}
if !nosync {
let action = match new_blocking {
true => sync::ChatAction::Block,
false => sync::ChatAction::Unblock,
};
context
.add_sync_item(SyncData::AlterChat(sync::AlterChatData {
id: sync::ChatId::ContactAddr(contact.addr.clone()),
action,
}))
.await?;
}
}
Ok(())

View File

@@ -36,15 +36,7 @@ pub(crate) enum ChatId {
#[derive(Debug, Serialize, Deserialize, PartialEq)]
pub(crate) enum ChatAction {
Block,
// TODO: Actually unblocking a chat is not a public API. `Contact::unblock()` is what a user
// does actually, but it doesn't call `chat::ChatId::unblock()`. So, unblocking chats sync
// doesn't work now, but let it be implemented on chats nevertheless. The straightforward fix is
// to call `chat::ChatId::unblock()` in a context of user action.
//
// But it still works if a message is sent to a blocked contact because
// `chat::ChatId::unblock()` is called then.
Unblock,
Accept,
SetVisibility(ChatVisibility),
SetMuted(chat::MuteDuration),
@@ -604,6 +596,18 @@ mod tests {
sync(&alices).await?;
assert_eq!(alices[1].get_chat(&bob).await.blocked, Blocked::Not);
// Unblocking a 1:1 chat doesn't unblock the contact currently.
let a0b_contact_id = alices[0].add_or_lookup_contact(&bob).await.id;
Contact::unblock(&alices[0], a0b_contact_id).await?;
assert!(!alices[1].add_or_lookup_contact(&bob).await.is_blocked());
Contact::block(&alices[0], a0b_contact_id).await?;
sync(&alices).await?;
assert!(alices[1].add_or_lookup_contact(&bob).await.is_blocked());
Contact::unblock(&alices[0], a0b_contact_id).await?;
sync(&alices).await?;
assert!(!alices[1].add_or_lookup_contact(&bob).await.is_blocked());
assert_eq!(
alices[1].get_chat(&bob).await.get_visibility(),
ChatVisibility::Normal