Skip to content

Commit

Permalink
fix(disappearing-messages): store settings from welcome message (#1619)
Browse files Browse the repository at this point in the history
* store disappearing settings from welcome msg
expose disappearing setting for creating dms
returning disappearing settings from the db
  • Loading branch information
mchenani authored Feb 10, 2025
1 parent 0c42018 commit f5b1089
Show file tree
Hide file tree
Showing 14 changed files with 413 additions and 81 deletions.
212 changes: 177 additions & 35 deletions bindings_ffi/src/mls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ use xmtp_mls::groups::device_sync::preference_sync::UserPreferenceUpdate;
use xmtp_mls::groups::device_sync::ENC_KEY_SIZE;
use xmtp_mls::groups::group_mutable_metadata::MessageDisappearingSettings;
use xmtp_mls::groups::scoped_client::LocalScopedGroupClient;
use xmtp_mls::groups::HmacKey;
use xmtp_mls::groups::{DMMetadataOptions, HmacKey};
use xmtp_mls::storage::group::ConversationType;
use xmtp_mls::storage::group_message::{ContentType, MsgQueryArgs};
use xmtp_mls::storage::group_message::{SortDirection, StoredGroupMessageWithReactions};
Expand Down Expand Up @@ -1102,10 +1102,11 @@ impl FfiConversations {
pub async fn find_or_create_dm(
&self,
account_address: String,
opts: FfiCreateDMOptions,
) -> Result<Arc<FfiConversation>, GenericError> {
log::info!("creating dm with target address: {}", account_address);
self.inner_client
.find_or_create_dm(account_address)
.find_or_create_dm(account_address, opts.into_dm_metadata_options())
.await
.map(|g| Arc::new(g.into()))
.map_err(Into::into)
Expand All @@ -1114,10 +1115,11 @@ impl FfiConversations {
pub async fn find_or_create_dm_by_inbox_id(
&self,
inbox_id: String,
opts: FfiCreateDMOptions,
) -> Result<Arc<FfiConversation>, GenericError> {
log::info!("creating dm with target inbox_id: {}", inbox_id);
self.inner_client
.find_or_create_dm_by_inbox_id(inbox_id)
.find_or_create_dm_by_inbox_id(inbox_id, opts.into_dm_metadata_options())
.await
.map(|g| Arc::new(g.into()))
.map_err(Into::into)
Expand Down Expand Up @@ -1622,6 +1624,26 @@ impl FfiCreateGroupOptions {
}
}

#[derive(uniffi::Record, Clone, Default)]
pub struct FfiCreateDMOptions {
pub message_disappearing_settings: Option<FfiMessageDisappearingSettings>,
}

impl FfiCreateDMOptions {
pub fn new(disappearing_settings: FfiMessageDisappearingSettings) -> Self {
FfiCreateDMOptions {
message_disappearing_settings: Some(disappearing_settings),
}
}
pub fn into_dm_metadata_options(self) -> DMMetadataOptions {
DMMetadataOptions {
message_disappearing_settings: self
.message_disappearing_settings
.map(|settings| settings.into()),
}
}
}

#[uniffi::export(async_runtime = "tokio")]
impl FfiConversation {
pub async fn send(&self, content_bytes: Vec<u8>) -> Result<Vec<u8>, GenericError> {
Expand Down Expand Up @@ -1854,22 +1876,22 @@ impl FfiConversation {

pub fn conversation_message_disappearing_settings(
&self,
) -> Result<FfiMessageDisappearingSettings, GenericError> {
let provider = self.inner.mls_provider()?;
let group_message_expiration_settings = self
.inner
.conversation_message_disappearing_settings(&provider)?;
) -> Result<Option<FfiMessageDisappearingSettings>, GenericError> {
let settings = self.inner.client.group_disappearing_settings(self.id())?;

Ok(FfiMessageDisappearingSettings::new(
group_message_expiration_settings.from_ns,
group_message_expiration_settings.in_ns,
))
match settings {
Some(s) => Ok(Some(FfiMessageDisappearingSettings::from(s))),
None => Ok(None),
}
}

pub fn is_conversation_message_disappearing_enabled(&self) -> Result<bool, GenericError> {
let settings = self.conversation_message_disappearing_settings()?;

Ok(settings.from_ns > 0 && settings.in_ns > 0)
self.conversation_message_disappearing_settings()
.map(|settings| {
settings
.as_ref()
.is_some_and(|s| s.from_ns > 0 && s.in_ns > 0)
})
}

pub fn admin_list(&self) -> Result<Vec<String>, GenericError> {
Expand Down Expand Up @@ -2411,11 +2433,11 @@ mod tests {
connect_to_backend, decode_reaction, encode_reaction, get_inbox_id_for_address,
inbox_owner::SigningError, FfiConsent, FfiConsentEntityType, FfiConsentState,
FfiContentType, FfiConversation, FfiConversationCallback, FfiConversationMessageKind,
FfiCreateGroupOptions, FfiDirection, FfiGroupPermissionsOptions, FfiInboxOwner,
FfiListConversationsOptions, FfiListMessagesOptions, FfiMessageDisappearingSettings,
FfiMessageWithReactions, FfiMetadataField, FfiPermissionPolicy, FfiPermissionPolicySet,
FfiPermissionUpdateType, FfiReaction, FfiReactionAction, FfiReactionSchema,
FfiSubscribeError,
FfiCreateDMOptions, FfiCreateGroupOptions, FfiDirection, FfiGroupPermissionsOptions,
FfiInboxOwner, FfiListConversationsOptions, FfiListMessagesOptions,
FfiMessageDisappearingSettings, FfiMessageWithReactions, FfiMetadataField,
FfiPermissionPolicy, FfiPermissionPolicySet, FfiPermissionUpdateType, FfiReaction,
FfiReactionAction, FfiReactionSchema, FfiSubscribeError,
};
use ethers::utils::hex;
use prost::Message;
Expand All @@ -2427,6 +2449,7 @@ mod tests {
},
};
use tokio::{sync::Notify, time::error::Elapsed};
use xmtp_common::time::now_ns;
use xmtp_common::tmp_path;
use xmtp_common::{wait_for_eq, wait_for_ok};
use xmtp_content_types::{
Expand Down Expand Up @@ -3143,13 +3166,15 @@ mod tests {
group
.conversation_message_disappearing_settings()
.unwrap()
.unwrap()
.from_ns,
conversation_message_disappearing_settings.clone().from_ns
);
assert_eq!(
group
.conversation_message_disappearing_settings()
.unwrap()
.unwrap()
.in_ns,
conversation_message_disappearing_settings.in_ns
);
Expand Down Expand Up @@ -3386,7 +3411,7 @@ mod tests {

let dm = bo
.conversations()
.find_or_create_dm(alix.account_address.clone())
.find_or_create_dm(alix.account_address.clone(), FfiCreateDMOptions::default())
.await
.unwrap();
dm.send(b"Hello again".to_vec()).await.unwrap();
Expand Down Expand Up @@ -4045,7 +4070,10 @@ mod tests {
// Create DM from client1 to client2
let dm_group = client1
.conversations()
.find_or_create_dm(client2.account_address.clone())
.find_or_create_dm(
client2.account_address.clone(),
FfiCreateDMOptions::default(),
)
.await
.unwrap();

Expand Down Expand Up @@ -4863,7 +4891,7 @@ mod tests {

let alix_group_admin_only = alix
.conversations()
.find_or_create_dm(bo.account_address.clone())
.find_or_create_dm(bo.account_address.clone(), FfiCreateDMOptions::default())
.await
.unwrap();

Expand Down Expand Up @@ -5154,6 +5182,117 @@ mod tests {
// 3 messages got deleted, then two messages got added for metadataUpdate and one normal messaged added later
}

#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
async fn test_set_disappearing_messages_when_creating_group() {
let alix = new_test_client().await;
let alix_provider = alix.inner_client.mls_provider().unwrap();
let bola = new_test_client().await;
let disappearing_settings = FfiMessageDisappearingSettings::new(now_ns(), 2_000_000_000);
// Step 1: Create a group
let alix_group = alix
.conversations()
.create_group(
vec![bola.account_address.clone()],
FfiCreateGroupOptions {
permissions: Some(FfiGroupPermissionsOptions::AdminOnly),
group_name: Some("Group Name".to_string()),
group_image_url_square: Some("url".to_string()),
group_description: Some("group description".to_string()),
custom_permission_policy_set: None,
message_disappearing_settings: Some(disappearing_settings.clone()),
},
)
.await
.unwrap();

// Step 2: Send a message and sync
alix_group
.send("Msg 1 from group".as_bytes().to_vec())
.await
.unwrap();
alix_group.sync().await.unwrap();

// Step 3: Verify initial messages
let alix_messages = alix_group
.find_messages(FfiListMessagesOptions::default())
.await
.unwrap();
assert_eq!(alix_messages.len(), 2);
let group_from_db = alix_provider
.conn_ref()
.find_group(&alix_group.id())
.unwrap();
assert_eq!(
group_from_db
.clone()
.unwrap()
.message_disappear_from_ns
.unwrap(),
disappearing_settings.from_ns
);
assert!(alix_group
.is_conversation_message_disappearing_enabled()
.unwrap());
tokio::time::sleep(std::time::Duration::from_secs(3)).await;
let alix_messages = alix_group
.find_messages(FfiListMessagesOptions::default())
.await
.unwrap();
assert_eq!(alix_messages.len(), 1);
}
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
async fn test_set_disappearing_messages_when_creating_dm() {
let alix = new_test_client().await;
let alix_provider = alix.inner_client.mls_provider().unwrap();
let bola = new_test_client().await;
let disappearing_settings = FfiMessageDisappearingSettings::new(now_ns(), 2_000_000_000);
// Step 1: Create a group
let alix_group = alix
.conversations()
.find_or_create_dm(
bola.account_address.clone(),
FfiCreateDMOptions::new(disappearing_settings.clone()),
)
.await
.unwrap();

// Step 2: Send a message and sync
alix_group
.send("Msg 1 from group".as_bytes().to_vec())
.await
.unwrap();
alix_group.sync().await.unwrap();

// Step 3: Verify initial messages
let alix_messages = alix_group
.find_messages(FfiListMessagesOptions::default())
.await
.unwrap();

assert_eq!(alix_messages.len(), 1);
let group_from_db = alix_provider
.conn_ref()
.find_group(&alix_group.id())
.unwrap();
assert_eq!(
group_from_db
.clone()
.unwrap()
.message_disappear_from_ns
.unwrap(),
disappearing_settings.from_ns
);
assert!(alix_group
.is_conversation_message_disappearing_enabled()
.unwrap());
tokio::time::sleep(std::time::Duration::from_secs(3)).await;
let alix_messages = alix_group
.find_messages(FfiListMessagesOptions::default())
.await
.unwrap();
assert_eq!(alix_messages.len(), 0);
}

#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
async fn test_group_creation_custom_permissions() {
let alix = new_test_client().await;
Expand Down Expand Up @@ -5483,7 +5622,7 @@ mod tests {
let bola_conversations = bola.conversations();

let _alix_dm = alix_conversations
.find_or_create_dm(bola.account_address.clone())
.find_or_create_dm(bola.account_address.clone(), FfiCreateDMOptions::default())
.await
.unwrap();
let alix_num_sync = alix_conversations
Expand Down Expand Up @@ -5551,7 +5690,7 @@ mod tests {

assert_eq!(stream_callback.message_count(), 1);
alix.conversations()
.find_or_create_dm(bo.account_address.clone())
.find_or_create_dm(bo.account_address.clone(), FfiCreateDMOptions::default())
.await
.unwrap();
stream_callback.wait_for_delivery(None).await.unwrap();
Expand Down Expand Up @@ -5580,7 +5719,7 @@ mod tests {

assert_eq!(stream_callback.message_count(), 1);
alix.conversations()
.find_or_create_dm(bo.account_address.clone())
.find_or_create_dm(bo.account_address.clone(), FfiCreateDMOptions::default())
.await
.unwrap();
let result = stream_callback.wait_for_delivery(Some(2)).await;
Expand All @@ -5595,7 +5734,7 @@ mod tests {
let stream = bo.conversations().stream_dms(stream_callback.clone()).await;

caro.conversations()
.find_or_create_dm(bo.account_address.clone())
.find_or_create_dm(bo.account_address.clone(), FfiCreateDMOptions::default())
.await
.unwrap();
stream_callback.wait_for_delivery(None).await.unwrap();
Expand Down Expand Up @@ -5623,7 +5762,7 @@ mod tests {
let bo = new_test_client().await;
let alix_dm = alix
.conversations()
.find_or_create_dm(bo.account_address.clone())
.find_or_create_dm(bo.account_address.clone(), FfiCreateDMOptions::default())
.await
.unwrap();

Expand Down Expand Up @@ -5865,7 +6004,7 @@ mod tests {

let alix_dm = alix
.conversations()
.find_or_create_dm(bo.account_address.clone())
.find_or_create_dm(bo.account_address.clone(), FfiCreateDMOptions::default())
.await
.unwrap();

Expand Down Expand Up @@ -5901,7 +6040,7 @@ mod tests {

let alix_dm = alix
.conversations()
.find_or_create_dm(bo.account_address.clone())
.find_or_create_dm(bo.account_address.clone(), FfiCreateDMOptions::default())
.await
.unwrap();

Expand Down Expand Up @@ -5963,7 +6102,7 @@ mod tests {
// Alix creates DM with Bo
let alix_dm = alix
.conversations()
.find_or_create_dm(bo.account_address.clone())
.find_or_create_dm(bo.account_address.clone(), FfiCreateDMOptions::default())
.await
.unwrap();

Expand Down Expand Up @@ -6108,7 +6247,10 @@ mod tests {
// Alix creates DM with Bo
let bo_dm = bo
.conversations()
.find_or_create_dm(wallet_a.get_address().clone())
.find_or_create_dm(
wallet_a.get_address().clone(),
FfiCreateDMOptions::default(),
)
.await
.unwrap();

Expand Down Expand Up @@ -6549,7 +6691,7 @@ mod tests {
let inbox_id2 = client2.inbox_id();
let dm_by_inbox = client1
.conversations()
.find_or_create_dm_by_inbox_id(inbox_id2)
.find_or_create_dm_by_inbox_id(inbox_id2, FfiCreateDMOptions::default())
.await
.expect("Should create DM with inbox ID");

Expand All @@ -6572,7 +6714,7 @@ mod tests {
// First client tries to create another DM with the same inbox id
let dm_by_inbox2 = client1
.conversations()
.find_or_create_dm_by_inbox_id(client2.inbox_id())
.find_or_create_dm_by_inbox_id(client2.inbox_id(), FfiCreateDMOptions::default())
.await
.unwrap();

Expand All @@ -6595,7 +6737,7 @@ mod tests {
// Second client tries to create a DM with the client 1 inbox id
let dm_by_inbox3 = client2
.conversations()
.find_or_create_dm_by_inbox_id(client1.inbox_id())
.find_or_create_dm_by_inbox_id(client1.inbox_id(), FfiCreateDMOptions::default())
.await
.unwrap();

Expand Down
Loading

0 comments on commit f5b1089

Please sign in to comment.