Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(ffi): add more info to RoomPreview #4264

Merged
merged 3 commits into from
Nov 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 44 additions & 4 deletions bindings/matrix-sdk-ffi/src/room_preview.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
use anyhow::Context as _;
use matrix_sdk::{room_preview::RoomPreview as SdkRoomPreview, Client};
use ruma::space::SpaceRoomJoinRule;
use ruma::{room::RoomType as RumaRoomType, space::SpaceRoomJoinRule};
use tracing::warn;

use crate::{client::JoinRule, error::ClientError, room::Membership, utils::AsyncRuntimeDropped};
use crate::{
client::JoinRule, error::ClientError, room::Membership, room_member::RoomMember,
utils::AsyncRuntimeDropped,
};

/// A room preview for a room. It's intended to be used to represent rooms that
/// aren't joined yet.
Expand All @@ -25,14 +28,16 @@ impl RoomPreview {
topic: info.topic.clone(),
avatar_url: info.avatar_url.as_ref().map(|url| url.to_string()),
num_joined_members: info.num_joined_members,
room_type: info.room_type.as_ref().map(|room_type| room_type.to_string()),
num_active_members: info.num_active_members,
room_type: info.room_type.as_ref().into(),
is_history_world_readable: info.is_world_readable,
membership: info.state.map(|state| state.into()),
join_rule: info
.join_rule
.clone()
.try_into()
.map_err(|_| anyhow::anyhow!("unhandled SpaceRoomJoinRule kind"))?,
is_direct: info.is_direct,
})
}

Expand All @@ -45,6 +50,13 @@ impl RoomPreview {
self.client.get_room(&self.inner.room_id).context("missing room for a room preview")?;
room.leave().await.map_err(Into::into)
}

/// Get the user who created the invite, if any.
pub async fn inviter(&self) -> Option<RoomMember> {
let room = self.client.get_room(&self.inner.room_id)?;
let invite_details = room.invite_details().await.ok()?;
invite_details.inviter.and_then(|m| m.try_into().ok())
}
}

impl RoomPreview {
Expand All @@ -68,14 +80,18 @@ pub struct RoomPreviewInfo {
pub avatar_url: Option<String>,
/// The number of joined members.
pub num_joined_members: u64,
/// The number of active members, if known (joined + invited).
pub num_active_members: Option<u64>,
/// The room type (space, custom) or nothing, if it's a regular room.
pub room_type: Option<String>,
pub room_type: RoomType,
/// Is the history world-readable for this room?
pub is_history_world_readable: bool,
/// The membership state for the current user, if known.
pub membership: Option<Membership>,
/// The join rule for this room (private, public, knock, etc.).
pub join_rule: JoinRule,
/// Whether the room is direct or not, if known.
pub is_direct: Option<bool>,
}

impl TryFrom<SpaceRoomJoinRule> for JoinRule {
Expand All @@ -97,3 +113,27 @@ impl TryFrom<SpaceRoomJoinRule> for JoinRule {
})
}
}

/// The type of room for a [`RoomPreviewInfo`].
#[derive(Debug, Clone, uniffi::Enum)]
pub enum RoomType {
/// It's a plain chat room.
Room,
/// It's a space that can group several rooms.
Space,
/// It's a custom implementation.
Custom { value: String },
}

impl From<Option<&RumaRoomType>> for RoomType {
fn from(value: Option<&RumaRoomType>) -> Self {
match value {
Some(RumaRoomType::Space) => RoomType::Space,
Some(RumaRoomType::_Custom(_)) => RoomType::Custom {
// SAFETY: this was checked in the match branch above
value: value.unwrap().to_string(),
},
_ => RoomType::Room,
}
}
}
18 changes: 17 additions & 1 deletion crates/matrix-sdk/src/room_preview.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@ pub struct RoomPreview {
/// The number of joined members.
pub num_joined_members: u64,

/// The number of active members, if known (joined + invited).
pub num_active_members: Option<u64>,

/// The room type (space, custom) or nothing, if it's a regular room.
pub room_type: Option<RoomType>,

Expand Down Expand Up @@ -83,6 +86,7 @@ impl RoomPreview {
room_info: RoomInfo,
is_direct: Option<bool>,
num_joined_members: u64,
num_active_members: Option<u64>,
state: Option<RoomState>,
) -> Self {
RoomPreview {
Expand All @@ -107,6 +111,7 @@ impl RoomPreview {
},
is_world_readable: *room_info.history_visibility() == HistoryVisibility::WorldReadable,
num_joined_members,
num_active_members,
state,
is_direct,
}
Expand All @@ -121,6 +126,7 @@ impl RoomPreview {
room.clone_info(),
is_direct,
room.joined_members_count(),
Some(room.active_members_count()),
Some(room.state()),
)
}
Expand Down Expand Up @@ -178,6 +184,8 @@ impl RoomPreview {
response.membership.map(|membership| RoomState::from(&membership))
};

let num_active_members = cached_room.as_ref().map(|r| r.active_members_count());

let is_direct = if let Some(cached_room) = cached_room {
cached_room.is_direct().await.ok()
} else {
Expand All @@ -191,6 +199,7 @@ impl RoomPreview {
topic: response.topic,
avatar_url: response.avatar_url,
num_joined_members: response.num_joined_members.into(),
num_active_members,
room_type: response.room_type,
join_rule: response.join_rule,
is_world_readable: response.world_readable,
Expand Down Expand Up @@ -238,8 +247,15 @@ impl RoomPreview {

let room = client.get_room(room_id);
let state = room.as_ref().map(|room| room.state());
let num_active_members = room.as_ref().map(|r| r.active_members_count());
let is_direct = if let Some(room) = room { room.is_direct().await.ok() } else { None };

Ok(Self::from_room_info(room_info, is_direct, num_joined_members, state))
Ok(Self::from_room_info(
room_info,
is_direct,
num_joined_members,
num_active_members,
state,
))
}
}
Loading