diff --git a/crates/matrix-sdk-base/src/room/members.rs b/crates/matrix-sdk-base/src/room/members.rs index 6884c678050..e63e3835042 100644 --- a/crates/matrix-sdk-base/src/room/members.rs +++ b/crates/matrix-sdk-base/src/room/members.rs @@ -179,10 +179,13 @@ impl Room { .transpose()? .map(|e| e.content.ignored_users.into_keys().collect()); + let active_users = self.store.get_user_ids(self.room_id(), RoomMemberships::ACTIVE).await?; + Ok(MemberRoomInfo { power_levels: power_levels.into(), max_power_level, users_display_names, + active_users, ignored_users, }) } @@ -211,13 +214,24 @@ impl RoomMember { presence: Option, room_info: &MemberRoomInfo<'_>, ) -> Self { - let MemberRoomInfo { power_levels, max_power_level, users_display_names, ignored_users } = - room_info; + let MemberRoomInfo { + power_levels, + max_power_level, + users_display_names, + ignored_users, + active_users, + } = room_info; let display_name = event.display_name(); - let display_name_ambiguous = users_display_names - .get(&display_name) - .is_some_and(|s| is_display_name_ambiguous(&display_name, s)); + + let display_name_ambiguous = users_display_names.get(&display_name).is_some_and(|s| { + // s.filter(|n| ) + if !is_display_name_ambiguous(&display_name, s) { + return false; + } + //We check of many active_users with the same surname exist + active_users.iter().filter(|u| s.contains(*u)).count() > 1 + }); let is_ignored = ignored_users.as_ref().is_some_and(|s| s.contains(event.user_id())); Self { @@ -390,6 +404,7 @@ pub(crate) struct MemberRoomInfo<'a> { pub(crate) max_power_level: i64, pub(crate) users_display_names: HashMap<&'a DisplayName, BTreeSet>, pub(crate) ignored_users: Option>, + pub(crate) active_users: Vec, } /// The kind of room member updates that just happened. @@ -478,9 +493,23 @@ pub fn normalize_power_level(power_level: Int, max_power_level: i64) -> Int { #[cfg(test)] mod tests { + use std::sync::Arc; + + use matrix_sdk_test::{async_test, event_factory::EventFactory}; use proptest::prelude::*; + use ruma::{room_id, user_id}; use super::*; + use crate::{RoomState, StateChanges, StateStore, store::MemoryStore}; + + fn make_room_test_helper(room_type: RoomState) -> (Arc, Room) { + let store = Arc::new(MemoryStore::new()); + let user_id = user_id!("@me:example.org"); + let room_id = room_id!("!test:localhost"); + let (sender, _receiver) = tokio::sync::broadcast::channel(1); + + (store.clone(), Room::new(user_id, store, room_id, room_type, sender)) + } prop_compose! { fn arb_int()(id in any::()) -> Int { @@ -526,4 +555,89 @@ mod tests { assert!(normalized >= 0); assert!(normalized <= 100); } + + #[async_test] + async fn test_room_member_from_parts() { + let (store, room) = make_room_test_helper(RoomState::Joined); + + let carol = user_id!("@carol:example.org"); + let denis = user_id!("@denis:example.org"); + let erica = user_id!("@erica:example.org"); + let fred = user_id!("@fred:example.org"); + let fredo = user_id!("@fredo:example.org"); + let bob = user_id!("@bob:example.org"); + let julie = user_id!("@julie:example.org"); + let me = user_id!("@me:example.org"); + let mewto = user_id!("@mewto:example.org"); + + let mut changes = StateChanges::new("".to_owned()); + + let f = EventFactory::new().room(room_id!("!test:localhost")); + + { + let members = changes + .state + .entry(room.room_id().to_owned()) + .or_default() + .entry(StateEventType::RoomMember) + .or_default(); + + let ambiguity_maps = + changes.ambiguity_maps.entry(room.room_id().to_owned()).or_default(); + + let display_name = DisplayName::new("Carol"); + members.insert(carol.into(), f.member(carol).display_name("Carol").into()); + ambiguity_maps.entry(display_name).or_default().insert(carol.to_owned()); + + let display_name = DisplayName::new("Fred"); + members.insert(fred.into(), f.member(fred).display_name("Fred").into()); + ambiguity_maps.entry(display_name.clone()).or_default().insert(fred.to_owned()); + members.insert( + fredo.into(), + f.member(fredo).display_name("Fred").membership(MembershipState::Knock).into(), + ); + ambiguity_maps.entry(display_name.clone()).or_default().insert(fredo.to_owned()); + members.insert( + denis.into(), + f.member(denis).display_name("Fred").membership(MembershipState::Leave).into(), + ); + ambiguity_maps.entry(display_name.clone()).or_default().insert(erica.to_owned()); + members.insert( + erica.into(), + f.member(erica).display_name("Fred").membership(MembershipState::Ban).into(), + ); + + let display_name = DisplayName::new("Bob"); + members.insert( + bob.into(), + f.member(bob).display_name("Bob").membership(MembershipState::Invite).into(), + ); + ambiguity_maps.entry(display_name.clone()).or_default().insert(bob.to_owned()); + members.insert(julie.into(), f.member(me).display_name("Bob").into()); + ambiguity_maps.entry(display_name.clone()).or_default().insert(julie.to_owned()); + + let display_name = DisplayName::new("Me"); + members.insert(me.into(), f.member(me).display_name("Me").into()); + ambiguity_maps.entry(display_name.clone()).or_default().insert(me.to_owned()); + members.insert(mewto.into(), f.member(mewto).display_name("Me").into()); + ambiguity_maps.entry(display_name.clone()).or_default().insert(mewto.to_owned()); + + store.save_changes(&changes).await.unwrap(); + } + + assert!(!room.get_member(carol).await.unwrap().expect("Carol user").name_ambiguous()); + + assert!(!room.get_member(fred).await.unwrap().expect("Fred user").name_ambiguous()); + assert!(!room.get_member(fredo).await.unwrap().expect("Fredo user").name_ambiguous()); + assert!(!room.get_member(denis).await.unwrap().expect("Denis user").name_ambiguous()); + assert!(!room.get_member(erica).await.unwrap().expect("Erica user").name_ambiguous()); + + assert!(!room.get_member(bob).await.unwrap().expect("Bob user").name_ambiguous()); + + assert!(!room.get_member(julie).await.unwrap().expect("Julie user").name_ambiguous()); + assert!(!room.get_member(bob).await.unwrap().expect("Bob user").name_ambiguous()); + + assert!(room.get_member(me).await.unwrap().expect("Me user").name_ambiguous()); + assert!(room.get_member(mewto).await.unwrap().expect("Mewto user").name_ambiguous()); + } }