diff --git a/src/chat.rs b/src/chat.rs index 464fb2024..685bc8070 100644 --- a/src/chat.rs +++ b/src/chat.rs @@ -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(()); diff --git a/src/contact.rs b/src/contact.rs index 2874e94cd..8068cb654 100644 --- a/src/contact.rs +++ b/src/contact.rs @@ -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(()) diff --git a/src/sync.rs b/src/sync.rs index 87fc6d4ab..beef9b7cd 100644 --- a/src/sync.rs +++ b/src/sync.rs @@ -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