diff --git a/crates/ruma-common/src/events/room/member.rs b/crates/ruma-common/src/events/room/member.rs index c241e39d..88996a1d 100644 --- a/crates/ruma-common/src/events/room/member.rs +++ b/crates/ruma-common/src/events/room/member.rs @@ -323,7 +323,7 @@ impl OriginalRoomMemberEvent { /// Check [the specification][spec] for details. /// /// [spec]: https://spec.matrix.org/v1.2/client-server-api/#mroommember - pub fn membership_change(&self) -> MembershipChange { + pub fn membership_change(&self) -> MembershipChange<'_> { membership_change(self.details(), self.prev_details(), &self.sender, &self.state_key) } } @@ -346,10 +346,10 @@ impl RedactedRoomMemberEvent { /// Check [the specification][spec] for details. /// /// [spec]: https://spec.matrix.org/v1.2/client-server-api/#mroommember - pub fn membership_change( - &self, - prev_details: Option>, - ) -> MembershipChange { + pub fn membership_change<'a>( + &'a self, + prev_details: Option>, + ) -> MembershipChange<'a> { membership_change(self.details(), prev_details, &self.sender, &self.state_key) } } @@ -379,7 +379,7 @@ impl OriginalSyncRoomMemberEvent { /// Check [the specification][spec] for details. /// /// [spec]: https://spec.matrix.org/v1.2/client-server-api/#mroommember - pub fn membership_change(&self) -> MembershipChange { + pub fn membership_change(&self) -> MembershipChange<'_> { membership_change(self.details(), self.prev_details(), &self.sender, &self.state_key) } } @@ -402,10 +402,10 @@ impl RedactedSyncRoomMemberEvent { /// Check [the specification][spec] for details. /// /// [spec]: https://spec.matrix.org/v1.2/client-server-api/#mroommember - pub fn membership_change( - &self, - prev_details: Option>, - ) -> MembershipChange { + pub fn membership_change<'a>( + &'a self, + prev_details: Option>, + ) -> MembershipChange<'a> { membership_change(self.details(), prev_details, &self.sender, &self.state_key) } } @@ -428,10 +428,10 @@ impl StrippedRoomMemberEvent { /// Check [the specification][spec] for details. /// /// [spec]: https://spec.matrix.org/v1.2/client-server-api/#mroommember - pub fn membership_change( - &self, - prev_details: Option>, - ) -> MembershipChange { + pub fn membership_change<'a>( + &'a self, + prev_details: Option>, + ) -> MembershipChange<'a> { membership_change(self.details(), prev_details, &self.sender, &self.state_key) } } diff --git a/crates/ruma-common/src/events/room/member/change.rs b/crates/ruma-common/src/events/room/member/change.rs index 7990bbe3..4e4d3606 100644 --- a/crates/ruma-common/src/events/room/member/change.rs +++ b/crates/ruma-common/src/events/room/member/change.rs @@ -12,7 +12,7 @@ pub struct MembershipDetails<'a> { /// Translation of the membership change in `m.room.member` event. #[derive(Clone, Debug)] #[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)] -pub enum MembershipChange { +pub enum MembershipChange<'a> { /// No change. None, @@ -48,25 +48,45 @@ pub enum MembershipChange { /// `displayname` or `avatar_url` changed. ProfileChanged { - /// Whether the `displayname` changed. - displayname_changed: bool, + /// The details of the displayname change, if applicable. + displayname_change: Option>>, - /// Whether the `avatar_url` changed. - avatar_url_changed: bool, + /// The details of the avatar url change, if applicable. + avatar_url_change: Option>>, }, /// Not implemented. NotImplemented, } +/// A simple representation of a change, containing old and new data. +#[derive(Clone, Debug)] +pub struct Change { + /// The old data. + pub old: T, + + /// The new data. + pub new: T, +} + +impl Change { + fn new(old: T, new: T) -> Option { + if old == new { + None + } else { + Some(Self { old, new }) + } + } +} + /// Internal function so all `RoomMemberEventContent` state event kinds can share the same /// implementation. -pub(super) fn membership_change( - details: MembershipDetails<'_>, - prev_details: Option>, +pub(super) fn membership_change<'a>( + details: MembershipDetails<'a>, + prev_details: Option>, sender: &UserId, state_key: &UserId, -) -> MembershipChange { +) -> MembershipChange<'a> { use MembershipChange as Ch; use MembershipState as St; @@ -83,8 +103,8 @@ pub(super) fn membership_change( (St::Invite, St::Ban) | (St::Leave, St::Ban) => Ch::Banned, (St::Join, St::Invite) | (St::Ban, St::Invite) | (St::Ban, St::Join) => Ch::Error, (St::Join, St::Join) => Ch::ProfileChanged { - displayname_changed: prev_details.displayname != details.displayname, - avatar_url_changed: prev_details.avatar_url != details.avatar_url, + displayname_change: Change::new(prev_details.displayname, details.displayname), + avatar_url_change: Change::new(prev_details.avatar_url, details.avatar_url), }, (St::Join, St::Leave) if sender == state_key => Ch::Left, (St::Join, St::Leave) => Ch::Kicked,