matrix_sdk_ffi/
room_preview.rs1use anyhow::Context as _;
2use matrix_sdk::{room_preview::RoomPreview as SdkRoomPreview, Client};
3use ruma::{room::RoomType as RumaRoomType, space::SpaceRoomJoinRule};
4use tracing::warn;
5
6use crate::{
7 client::JoinRule,
8 error::ClientError,
9 room::{Membership, RoomHero},
10 room_member::RoomMember,
11 utils::AsyncRuntimeDropped,
12};
13
14#[derive(uniffi::Object)]
17pub struct RoomPreview {
18 inner: SdkRoomPreview,
19 client: AsyncRuntimeDropped<Client>,
20}
21
22#[matrix_sdk_ffi_macros::export]
23impl RoomPreview {
24 pub fn info(&self) -> Result<RoomPreviewInfo, ClientError> {
26 let info = &self.inner;
27 Ok(RoomPreviewInfo {
28 room_id: info.room_id.to_string(),
29 canonical_alias: info.canonical_alias.as_ref().map(|alias| alias.to_string()),
30 name: info.name.clone(),
31 topic: info.topic.clone(),
32 avatar_url: info.avatar_url.as_ref().map(|url| url.to_string()),
33 num_joined_members: info.num_joined_members,
34 num_active_members: info.num_active_members,
35 room_type: info.room_type.as_ref().into(),
36 is_history_world_readable: info.is_world_readable,
37 membership: info.state.map(|state| state.into()),
38 join_rule: info
39 .join_rule
40 .clone()
41 .try_into()
42 .map_err(|_| anyhow::anyhow!("unhandled SpaceRoomJoinRule kind"))?,
43 is_direct: info.is_direct,
44 heroes: info
45 .heroes
46 .as_ref()
47 .map(|heroes| heroes.iter().map(|h| h.to_owned().into()).collect()),
48 })
49 }
50
51 pub async fn leave(&self) -> Result<(), ClientError> {
56 let room =
57 self.client.get_room(&self.inner.room_id).context("missing room for a room preview")?;
58 room.leave().await.map_err(Into::into)
59 }
60
61 pub async fn inviter(&self) -> Option<RoomMember> {
63 let room = self.client.get_room(&self.inner.room_id)?;
64 let invite_details = room.invite_details().await.ok()?;
65 invite_details.inviter.and_then(|m| m.try_into().ok())
66 }
67
68 pub async fn forget(&self) -> Result<(), ClientError> {
70 let room =
71 self.client.get_room(&self.inner.room_id).context("missing room for a room preview")?;
72 room.forget().await?;
73 Ok(())
74 }
75
76 pub async fn own_membership_details(&self) -> Option<RoomMembershipDetails> {
78 let room = self.client.get_room(&self.inner.room_id)?;
79
80 let (own_member, sender_member) = match room.own_membership_details().await {
81 Ok(memberships) => memberships,
82 Err(error) => {
83 warn!("Couldn't get membership info: {error}");
84 return None;
85 }
86 };
87
88 Some(RoomMembershipDetails {
89 own_room_member: own_member.try_into().ok()?,
90 sender_room_member: sender_member.and_then(|member| member.try_into().ok()),
91 })
92 }
93}
94
95#[derive(uniffi::Record)]
98pub struct RoomMembershipDetails {
99 pub own_room_member: RoomMember,
100 pub sender_room_member: Option<RoomMember>,
101}
102
103impl RoomPreview {
104 pub(crate) fn new(client: AsyncRuntimeDropped<Client>, inner: SdkRoomPreview) -> Self {
105 Self { client, inner }
106 }
107}
108
109#[derive(uniffi::Record)]
111pub struct RoomPreviewInfo {
112 pub room_id: String,
114 pub canonical_alias: Option<String>,
116 pub name: Option<String>,
118 pub topic: Option<String>,
120 pub avatar_url: Option<String>,
122 pub num_joined_members: u64,
124 pub num_active_members: Option<u64>,
126 pub room_type: RoomType,
128 pub is_history_world_readable: Option<bool>,
130 pub membership: Option<Membership>,
132 pub join_rule: JoinRule,
134 pub is_direct: Option<bool>,
136 pub heroes: Option<Vec<RoomHero>>,
138}
139
140impl TryFrom<SpaceRoomJoinRule> for JoinRule {
141 type Error = ();
142
143 fn try_from(join_rule: SpaceRoomJoinRule) -> Result<Self, ()> {
144 Ok(match join_rule {
145 SpaceRoomJoinRule::Invite => JoinRule::Invite,
146 SpaceRoomJoinRule::Knock => JoinRule::Knock,
147 SpaceRoomJoinRule::Private => JoinRule::Private,
148 SpaceRoomJoinRule::Restricted => JoinRule::Restricted { rules: Vec::new() },
149 SpaceRoomJoinRule::KnockRestricted => JoinRule::KnockRestricted { rules: Vec::new() },
150 SpaceRoomJoinRule::Public => JoinRule::Public,
151 SpaceRoomJoinRule::_Custom(_) => JoinRule::Custom { repr: join_rule.to_string() },
152 _ => {
153 warn!("unhandled SpaceRoomJoinRule: {join_rule}");
154 return Err(());
155 }
156 })
157 }
158}
159
160#[derive(Debug, Clone, uniffi::Enum)]
162pub enum RoomType {
163 Room,
165 Space,
167 Custom { value: String },
169}
170
171impl From<Option<&RumaRoomType>> for RoomType {
172 fn from(value: Option<&RumaRoomType>) -> Self {
173 match value {
174 Some(RumaRoomType::Space) => RoomType::Space,
175 Some(RumaRoomType::_Custom(_)) => RoomType::Custom {
176 value: value.unwrap().to_string(),
178 },
179 _ => RoomType::Room,
180 }
181 }
182}