Skip to content

Commit

Permalink
feat(room): introduce RequestToJoinRoom abstraction.
Browse files Browse the repository at this point in the history
This struct is an abstraction over a room member or state event with knock membership.
  • Loading branch information
jmartinesp committed Nov 27, 2024
1 parent add14cd commit 8d69f8a
Show file tree
Hide file tree
Showing 3 changed files with 121 additions and 1 deletion.
9 changes: 9 additions & 0 deletions crates/matrix-sdk-base/src/deserialized_responses.rs
Original file line number Diff line number Diff line change
Expand Up @@ -476,6 +476,15 @@ impl MemberEvent {
.unwrap_or_else(|| self.user_id().localpart()),
)
}

/// The optional reason why the membership changed.
pub fn reason(&self) -> Option<&str> {
match self {
MemberEvent::Sync(SyncStateEvent::Original(c)) => c.content.reason.as_deref(),
MemberEvent::Stripped(e) => e.content.reason.as_deref(),
_ => None,
}
}
}

impl SyncOrStrippedState<RoomPowerLevelsEventContent> {
Expand Down
18 changes: 17 additions & 1 deletion crates/matrix-sdk/src/room/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,10 @@ use crate::{
event_handler::{EventHandler, EventHandlerDropGuard, EventHandlerHandle, SyncEvent},
media::{MediaFormat, MediaRequestParameters},
notification_settings::{IsEncrypted, IsOneToOne, RoomNotificationMode},
room::power_levels::{RoomPowerLevelChanges, RoomPowerLevelsExt},
room::{
power_levels::{RoomPowerLevelChanges, RoomPowerLevelsExt},
request_to_join::RequestToJoinRoom,
},
sync::RoomUpdate,
utils::{IntoRawMessageLikeEventContent, IntoRawStateEventContent},
BaseRoom, Client, Error, HttpResult, Result, RoomState, TransmissionProgress,
Expand All @@ -146,6 +149,8 @@ pub mod identity_status_changes;
mod member;
mod messages;
pub mod power_levels;
/// Contains code related to requests to join a room.
pub mod request_to_join;

/// A struct containing methods that are common for Joined, Invited and Left
/// Rooms
Expand Down Expand Up @@ -3212,6 +3217,17 @@ impl Room {
};
Ok(current_requests_to_join_ids)
}

/// Subscribes to the set of requests to join that have been marked as
/// 'seen'.
pub async fn subscribe_to_seen_requests_to_join_ids(
&self,
) -> Result<(HashSet<OwnedEventId>, impl Stream<Item = HashSet<OwnedEventId>>)> {
let current = self.get_seen_requests_to_join_ids().await?;
let subscriber =
self.seen_requests_to_join_ids.subscribe().map(|values| values.unwrap_or_default());
Ok((current, subscriber))
}
}

#[cfg(all(feature = "e2e-encryption", not(target_arch = "wasm32")))]
Expand Down
95 changes: 95 additions & 0 deletions crates/matrix-sdk/src/room/request_to_join.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
use std::sync::Arc;

use ruma::{
events::room::member::OriginalSyncRoomMemberEvent, EventId, OwnedEventId, OwnedMxcUri,
OwnedUserId, RoomId,
};

use crate::{room::RoomMember, Error, Room};

/// A request to join a room with `knock` join rule.
#[derive(Debug, Clone)]
pub struct RequestToJoinRoom {
room: Arc<Room>,
/// The event id of the event containing knock membership change.
pub event_id: OwnedEventId,
/// Some general room member info to display.
pub member_info: RequestToJoinMemberInfo,
/// Whether it's been marked as 'seen' by the client.
pub is_seen: bool,
}

impl RequestToJoinRoom {
pub(crate) fn new(
room: Arc<Room>,
event_id: &EventId,
member: RequestToJoinMemberInfo,
is_seen: bool,
) -> Self {
Self { room, event_id: event_id.to_owned(), member_info: member, is_seen }
}

/// The room id for the `Room` form whose access is requested.
pub fn room_id(&self) -> &RoomId {
self.room.room_id()
}

/// Marks the request to join as 'seen' so the client can ignore it in the
/// future.
pub async fn mark_as_seen(&mut self) -> Result<bool, Error> {
self.room.mark_requests_to_join_as_seen(&[self.event_id.to_owned()]).await?;
Ok(true)
}

/// Accepts the request to join by inviting the user to the room.
pub async fn accept(&self) -> Result<(), Error> {
self.room.invite_user_by_id(&self.member_info.user_id).await
}

/// Declines the request to join by kicking the user from the room, with an
/// optional reason.
pub async fn decline(&self, reason: Option<&str>) -> Result<(), Error> {
self.room.kick_user(&self.member_info.user_id, reason).await
}

/// Declines the request to join by banning the user from the room, with an
/// optional reason.
pub async fn decline_and_ban(&self, reason: Option<&str>) -> Result<(), Error> {
self.room.ban_user(&self.member_info.user_id, reason).await
}
}

/// General room member info to display along with the join request.
#[derive(Debug, Clone)]
pub struct RequestToJoinMemberInfo {
/// The user id for the room member requesting access.
pub user_id: OwnedUserId,
/// The optional display name of the room member requesting access.
pub display_name: Option<String>,
/// The optional avatar url of the room member requesting access.
pub avatar_url: Option<OwnedMxcUri>,
/// An optional reason why the user wants access to the room.
pub reason: Option<String>,
}

impl From<RoomMember> for RequestToJoinMemberInfo {
fn from(member: RoomMember) -> Self {
Self {
user_id: member.user_id().to_owned(),
display_name: member.display_name().map(ToOwned::to_owned),
avatar_url: member.avatar_url().map(ToOwned::to_owned),
reason: member.event().reason().map(ToOwned::to_owned),
}
}
}

impl From<OriginalSyncRoomMemberEvent> for RequestToJoinMemberInfo {
fn from(member: OriginalSyncRoomMemberEvent) -> Self {
Self {
user_id: member.state_key,
display_name: member.content.displayname,
avatar_url: member.content.avatar_url,
reason: member.content.reason,
}
}
}

0 comments on commit 8d69f8a

Please sign in to comment.