Skip to content

Commit cab7360

Browse files
committed
bindings filter messages by type
1 parent db84199 commit cab7360

File tree

3 files changed

+147
-9
lines changed

3 files changed

+147
-9
lines changed

Cargo.lock

+2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

bindings_ffi/Cargo.toml

+2
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,12 @@ futures.workspace = true
1212
tracing.workspace = true
1313
tracing-subscriber = { workspace = true, features = ["registry", "env-filter", "fmt", "json"] }
1414
parking_lot.workspace = true
15+
prost.workspace = true
1516
thiserror.workspace = true
1617
tokio = { workspace = true, features = ["macros"] }
1718
uniffi = { version = "0.28.0", default-features = false, features = ["tokio"] }
1819
xmtp_api_grpc = { path = "../xmtp_api_grpc" }
20+
xmtp_content_types = { path = "../xmtp_content_types" }
1921
xmtp_cryptography = { path = "../xmtp_cryptography" }
2022
xmtp_id = { path = "../xmtp_id" }
2123
xmtp_mls = { path = "../xmtp_mls" }

bindings_ffi/src/mls.rs

+143-9
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@ use xmtp_mls::groups::device_sync::preference_sync::UserPreferenceUpdate;
1919
use xmtp_mls::groups::scoped_client::LocalScopedGroupClient;
2020
use xmtp_mls::groups::HmacKey;
2121
use xmtp_mls::storage::group::ConversationType;
22-
use xmtp_mls::storage::group_message::MsgQueryArgs;
2322
use xmtp_mls::storage::group_message::SortDirection;
23+
use xmtp_mls::storage::group_message::{ContentType, MsgQueryArgs};
2424
use xmtp_mls::{
2525
api::ApiClientWrapper,
2626
builder::ClientBuilder,
@@ -1259,6 +1259,38 @@ pub struct FfiListMessagesOptions {
12591259
pub limit: Option<i64>,
12601260
pub delivery_status: Option<FfiDeliveryStatus>,
12611261
pub direction: Option<FfiDirection>,
1262+
pub content_types: Option<Vec<FfiContentType>>,
1263+
}
1264+
1265+
#[derive(uniffi::Enum, Clone)]
1266+
pub enum FfiContentType {
1267+
Unknown,
1268+
Text,
1269+
GroupMembershipChange,
1270+
GroupUpdated,
1271+
Reaction,
1272+
ReadReceipt,
1273+
Reply,
1274+
Attachment,
1275+
RemoteAttachment,
1276+
TransactionReference,
1277+
}
1278+
1279+
impl From<FfiContentType> for ContentType {
1280+
fn from(value: FfiContentType) -> Self {
1281+
match value {
1282+
FfiContentType::Unknown => ContentType::Unknown,
1283+
FfiContentType::Text => ContentType::Text,
1284+
FfiContentType::GroupMembershipChange => ContentType::GroupMembershipChange,
1285+
FfiContentType::GroupUpdated => ContentType::GroupUpdated,
1286+
FfiContentType::Reaction => ContentType::Reaction,
1287+
FfiContentType::ReadReceipt => ContentType::ReadReceipt,
1288+
FfiContentType::Reply => ContentType::Reply,
1289+
FfiContentType::Attachment => ContentType::Attachment,
1290+
FfiContentType::RemoteAttachment => ContentType::RemoteAttachment,
1291+
FfiContentType::TransactionReference => ContentType::TransactionReference,
1292+
}
1293+
}
12621294
}
12631295

12641296
#[derive(uniffi::Record, Clone, Default)]
@@ -1331,7 +1363,11 @@ impl FfiConversation {
13311363
.maybe_kind(kind)
13321364
.maybe_delivery_status(delivery_status)
13331365
.maybe_limit(opts.limit)
1334-
.maybe_direction(direction),
1366+
.maybe_direction(direction)
1367+
.maybe_content_types(
1368+
opts.content_types
1369+
.map(|types| types.into_iter().map(|t| t.into()).collect()),
1370+
),
13351371
)?
13361372
.into_iter()
13371373
.map(|msg| msg.into())
@@ -1877,19 +1913,25 @@ mod tests {
18771913
};
18781914
use crate::{
18791915
connect_to_backend, get_inbox_id_for_address, inbox_owner::SigningError, FfiConsent,
1880-
FfiConsentEntityType, FfiConsentState, FfiConversation, FfiConversationCallback,
1881-
FfiConversationMessageKind, FfiCreateGroupOptions, FfiGroupPermissionsOptions,
1882-
FfiInboxOwner, FfiListConversationsOptions, FfiListMessagesOptions, FfiMetadataField,
1883-
FfiPermissionPolicy, FfiPermissionPolicySet, FfiPermissionUpdateType, FfiSubscribeError,
1916+
FfiConsentEntityType, FfiConsentState, FfiContentType, FfiConversation,
1917+
FfiConversationCallback, FfiConversationMessageKind, FfiCreateGroupOptions, FfiDirection,
1918+
FfiGroupPermissionsOptions, FfiInboxOwner, FfiListConversationsOptions,
1919+
FfiListMessagesOptions, FfiMetadataField, FfiPermissionPolicy, FfiPermissionPolicySet,
1920+
FfiPermissionUpdateType, FfiSubscribeError,
18841921
};
18851922
use ethers::utils::hex;
1886-
use std::sync::{
1887-
atomic::{AtomicU32, Ordering},
1888-
Arc, Mutex,
1923+
use prost::Message;
1924+
use std::{
1925+
collections::HashMap,
1926+
sync::{
1927+
atomic::{AtomicU32, Ordering},
1928+
Arc, Mutex,
1929+
},
18891930
};
18901931
use tokio::{sync::Notify, time::error::Elapsed};
18911932
use xmtp_common::tmp_path;
18921933
use xmtp_common::{wait_for_eq, wait_for_ok};
1934+
use xmtp_content_types::{read_receipt, text::TextCodec, ContentCodec};
18931935
use xmtp_cryptography::{signature::RecoverableSignature, utils::rng};
18941936
use xmtp_id::associations::{
18951937
generate_inbox_id,
@@ -1900,6 +1942,7 @@ mod tests {
19001942
storage::EncryptionKey,
19011943
InboxOwner,
19021944
};
1945+
use xmtp_proto::xmtp::mls::message_contents::{ContentTypeId, EncodedContent};
19031946

19041947
const HISTORY_SYNC_URL: &str = "http://localhost:5558";
19051948

@@ -4832,4 +4875,95 @@ mod tests {
48324875
Ok(_) => panic!("Expected an error, but got Ok"),
48334876
}
48344877
}
4878+
4879+
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
4880+
async fn test_can_list_messages_with_content_types() {
4881+
// Create test clients
4882+
let alix = new_test_client().await;
4883+
let bo = new_test_client().await;
4884+
4885+
// Alix creates group with Bo
4886+
let alix_group = alix
4887+
.conversations()
4888+
.create_group(
4889+
vec![bo.account_address.clone()],
4890+
FfiCreateGroupOptions::default(),
4891+
)
4892+
.await
4893+
.unwrap();
4894+
4895+
// Bo syncs to get the group
4896+
bo.conversations().sync().await.unwrap();
4897+
let bo_group = bo.conversation(alix_group.id()).unwrap();
4898+
4899+
// Alix sends first message
4900+
alix_group.send("hey".as_bytes().to_vec()).await.unwrap();
4901+
4902+
// Bo syncs and responds
4903+
bo_group.sync().await.unwrap();
4904+
let bo_message_response = TextCodec::encode("hey alix".to_string()).unwrap();
4905+
let mut buf = Vec::new();
4906+
bo_message_response.encode(&mut buf).unwrap();
4907+
bo_group.send(buf).await.unwrap();
4908+
4909+
// Bo sends read receipt
4910+
let read_receipt_content_id = ContentTypeId {
4911+
authority_id: "xmtp.org".to_string(),
4912+
type_id: read_receipt::ReadReceiptCodec::TYPE_ID.to_string(),
4913+
version_major: 1,
4914+
version_minor: 0,
4915+
};
4916+
let read_receipt_encoded_content = EncodedContent {
4917+
r#type: Some(read_receipt_content_id),
4918+
parameters: HashMap::new(),
4919+
fallback: None,
4920+
compression: None,
4921+
content: vec![],
4922+
};
4923+
4924+
let mut buf = Vec::new();
4925+
read_receipt_encoded_content.encode(&mut buf).unwrap();
4926+
bo_group.send(buf).await.unwrap();
4927+
4928+
// Alix syncs and gets all messages
4929+
alix_group.sync().await.unwrap();
4930+
let latest_message = alix_group
4931+
// ... existing code ...
4932+
.find_messages(FfiListMessagesOptions {
4933+
direction: Some(FfiDirection::Descending),
4934+
limit: Some(1),
4935+
..Default::default()
4936+
})
4937+
.await
4938+
.unwrap();
4939+
4940+
// Verify last message is the read receipt
4941+
assert_eq!(latest_message.len(), 1);
4942+
let latest_message_encoded_content =
4943+
EncodedContent::decode(latest_message.last().unwrap().content.clone().as_slice())
4944+
.unwrap();
4945+
assert_eq!(
4946+
latest_message_encoded_content.r#type.unwrap().type_id,
4947+
"readReceipt"
4948+
);
4949+
4950+
// Get only text messages
4951+
let text_messages = alix_group
4952+
.find_messages(FfiListMessagesOptions {
4953+
content_types: Some(vec![FfiContentType::Text]),
4954+
direction: Some(FfiDirection::Descending),
4955+
limit: Some(1),
4956+
..Default::default()
4957+
})
4958+
.await
4959+
.unwrap();
4960+
4961+
// Verify last message is "hey alix" when filtered
4962+
assert_eq!(text_messages.len(), 1);
4963+
let latest_message_encoded_content =
4964+
EncodedContent::decode(text_messages.last().unwrap().content.clone().as_slice())
4965+
.unwrap();
4966+
let text_message = TextCodec::decode(latest_message_encoded_content).unwrap();
4967+
assert_eq!(text_message, "hey alix");
4968+
}
48354969
}

0 commit comments

Comments
 (0)