Skip to content

Commit

Permalink
base: Add method to construct RoomMember from parts
Browse files Browse the repository at this point in the history
Signed-off-by: Kévin Commaille <[email protected]>
  • Loading branch information
zecakeh authored and jplatte committed Jun 14, 2023
1 parent e32e9b5 commit 38fc1f7
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 29 deletions.
10 changes: 10 additions & 0 deletions crates/matrix-sdk-base/src/deserialized_responses.rs
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,16 @@ impl MemberEvent {
pub fn user_id(&self) -> &UserId {
self.state_key()
}

/// The name that should be displayed for this member event.
///
/// It there is no `displayname` in the event's content, the localpart or
/// the user ID is returned.
pub fn display_name(&self) -> &str {
self.original_content()
.and_then(|c| c.displayname.as_deref())
.unwrap_or_else(|| self.user_id().localpart())
}
}

impl SyncOrStrippedState<RoomPowerLevelsEventContent> {
Expand Down
50 changes: 48 additions & 2 deletions crates/matrix-sdk-base/src/rooms/members.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@
// See the License for the specific language governing permissions and
// limitations under the License.

use std::sync::Arc;
use std::{
collections::{BTreeMap, BTreeSet},
sync::Arc,
};

use ruma::{
events::{
Expand All @@ -23,7 +26,7 @@ use ruma::{
},
MessageLikeEventType, StateEventType,
},
MxcUri, UserId,
MxcUri, OwnedUserId, UserId,
};

use crate::{
Expand All @@ -49,6 +52,33 @@ pub struct RoomMember {
}

impl RoomMember {
pub(crate) fn from_parts(member_info: MemberInfo, room_info: &MemberRoomInfo<'_>) -> Self {
let MemberInfo { event, profile, presence } = member_info;
let MemberRoomInfo {
power_levels,
max_power_level,
room_creator,
users_display_names,
ignored_users,
} = room_info;

let is_room_creator = room_creator.as_deref() == Some(event.user_id());
let display_name_ambiguous =
users_display_names.get(event.display_name()).is_some_and(|s| s.len() > 1);
let is_ignored = ignored_users.as_ref().is_some_and(|s| s.contains(event.user_id()));

Self {
event: event.into(),
profile: profile.into(),
presence: presence.into(),
power_levels: power_levels.clone(),
max_power_level: *max_power_level,
is_room_creator,
display_name_ambiguous,
is_ignored,
}
}

/// Get the unique user id of this member.
pub fn user_id(&self) -> &UserId {
self.event.user_id()
Expand Down Expand Up @@ -191,3 +221,19 @@ impl RoomMember {
self.is_ignored
}
}

// Information about a room member.
pub(crate) struct MemberInfo {
pub event: MemberEvent,
pub(crate) profile: Option<MinimalRoomMemberEvent>,
pub(crate) presence: Option<PresenceEvent>,
}

// Information about a the room a member is in.
pub(crate) struct MemberRoomInfo<'a> {
pub(crate) power_levels: Arc<Option<SyncOrStrippedState<RoomPowerLevelsEventContent>>>,
pub(crate) max_power_level: i64,
pub(crate) room_creator: Option<OwnedUserId>,
pub(crate) users_display_names: BTreeMap<&'a str, BTreeSet<OwnedUserId>>,
pub(crate) ignored_users: Option<BTreeSet<OwnedUserId>>,
}
58 changes: 31 additions & 27 deletions crates/matrix-sdk-base/src/rooms/normal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,10 @@ use ruma::{
use serde::{Deserialize, Serialize};
use tracing::{debug, info, instrument, warn};

use super::{BaseRoomInfo, DisplayName, RoomMember};
use super::{
members::{MemberInfo, MemberRoomInfo},
BaseRoomInfo, DisplayName, RoomMember,
};
use crate::{
deserialized_responses::MemberEvent,
store::{DynStateStore, Result as StoreResult, StateStoreExt},
Expand Down Expand Up @@ -457,51 +460,52 @@ impl Room {
let Some(raw_event) = self.store.get_member_event(self.room_id(), user_id).await? else {
return Ok(None);
};
let member_event = raw_event.deserialize()?;
let event = raw_event.deserialize()?;

let presence =
self.store.get_presence_event(user_id).await?.and_then(|e| e.deserialize().ok());
let profile = self.store.get_profile(self.room_id(), user_id).await?;

let display_names = [event.display_name().to_owned()];
let room_info = self.member_room_info(&display_names).await?;

let member_info = MemberInfo { event, profile, presence };

Ok(Some(RoomMember::from_parts(member_info, &room_info)))
}

/// The current `MemberRoomInfo` for this room.
async fn member_room_info<'a>(
&self,
display_names: &'a [String],
) -> StoreResult<MemberRoomInfo<'a>> {
let max_power_level = self.max_power_level();
let is_room_creator = self.inner.read().unwrap().creator() == Some(user_id);
let room_creator = self.inner.read().unwrap().creator().map(ToOwned::to_owned);

let power = self
let power_levels = self
.store
.get_state_event_static(self.room_id())
.await?
.and_then(|e| e.deserialize().ok());

let ambiguous = self
.store
.get_users_with_display_name(
self.room_id(),
member_event
.original_content()
.and_then(|c| c.displayname.as_deref())
.unwrap_or_else(|| user_id.localpart()),
)
.await?
.len()
> 1;
let users_display_names =
self.store.get_users_with_display_names(self.room_id(), display_names).await?;

let is_ignored = self
let ignored_users = self
.store
.get_account_data_event_static::<IgnoredUserListEventContent>()
.await?
.map(|c| c.deserialize())
.transpose()?
.is_some_and(|e| e.content.ignored_users.contains_key(member_event.user_id()));
.map(|e| e.content.ignored_users.into_keys().collect());

Ok(Some(RoomMember {
event: Arc::new(member_event),
profile: profile.into(),
presence: presence.into(),
power_levels: power.into(),
Ok(MemberRoomInfo {
power_levels: power_levels.into(),
max_power_level,
is_room_creator,
display_name_ambiguous: ambiguous,
is_ignored,
}))
room_creator,
users_display_names,
ignored_users,
})
}

/// Get the `Tags` for this room.
Expand Down

0 comments on commit 38fc1f7

Please sign in to comment.