1- use matrix_sdk:: { room_preview:: RoomPreview as SdkRoomPreview , RoomState } ;
1+ use std:: mem:: ManuallyDrop ;
2+
3+ use anyhow:: Context as _;
4+ use async_compat:: TOKIO1 as RUNTIME ;
5+ use matrix_sdk:: { room_preview:: RoomPreview as SdkRoomPreview , Client } ;
26use ruma:: space:: SpaceRoomJoinRule ;
7+ use tracing:: warn;
8+
9+ use crate :: { client:: JoinRule , error:: ClientError , room:: Membership } ;
10+
11+ /// A room preview for a room. It's intended to be used to represent rooms that
12+ /// aren't joined yet.
13+ #[ derive( uniffi:: Object ) ]
14+ pub struct RoomPreview {
15+ inner : SdkRoomPreview ,
16+ client : ManuallyDrop < Client > ,
17+ }
18+
19+ impl Drop for RoomPreview {
20+ fn drop ( & mut self ) {
21+ // Dropping the inner OlmMachine must happen within a tokio context
22+ // because deadpool drops sqlite connections in the DB pool on tokio's
23+ // blocking threadpool to avoid blocking async worker threads.
24+ let _guard = RUNTIME . enter ( ) ;
25+ // SAFETY: self.client is never used again, which is the only requirement
26+ // for ManuallyDrop::drop to be used safely.
27+ unsafe {
28+ ManuallyDrop :: drop ( & mut self . client ) ;
29+ }
30+ }
31+ }
32+
33+ #[ matrix_sdk_ffi_macros:: export]
34+ impl RoomPreview {
35+ /// Returns the room info the preview contains.
36+ pub fn info ( & self ) -> Result < RoomPreviewInfo , ClientError > {
37+ let info = & self . inner ;
38+ Ok ( RoomPreviewInfo {
39+ room_id : info. room_id . to_string ( ) ,
40+ canonical_alias : info. canonical_alias . as_ref ( ) . map ( |alias| alias. to_string ( ) ) ,
41+ name : info. name . clone ( ) ,
42+ topic : info. topic . clone ( ) ,
43+ avatar_url : info. avatar_url . as_ref ( ) . map ( |url| url. to_string ( ) ) ,
44+ num_joined_members : info. num_joined_members ,
45+ room_type : info. room_type . as_ref ( ) . map ( |room_type| room_type. to_string ( ) ) ,
46+ is_history_world_readable : info. is_world_readable ,
47+ membership : info. state . map ( |state| state. into ( ) ) ,
48+ join_rule : info
49+ . join_rule
50+ . clone ( )
51+ . try_into ( )
52+ . map_err ( |_| anyhow:: anyhow!( "unhandled SpaceRoomJoinRule kind" ) ) ?,
53+ } )
54+ }
55+
56+ /// Leave the room if the room preview state is either joined, invited or
57+ /// knocked.
58+ ///
59+ /// Will return an error otherwise.
60+ pub async fn leave ( & self ) -> Result < ( ) , ClientError > {
61+ let room =
62+ self . client . get_room ( & self . inner . room_id ) . context ( "missing room for a room preview" ) ?;
63+ room. leave ( ) . await . map_err ( Into :: into)
64+ }
65+ }
66+
67+ impl RoomPreview {
68+ pub ( crate ) fn new ( client : ManuallyDrop < Client > , inner : SdkRoomPreview ) -> Self {
69+ Self { client, inner }
70+ }
71+ }
372
473/// The preview of a room, be it invited/joined/left, or not.
574#[ derive( uniffi:: Record ) ]
6- pub struct RoomPreview {
75+ pub struct RoomPreviewInfo {
776 /// The room id for this room.
877 pub room_id : String ,
978 /// The canonical alias for the room.
@@ -20,34 +89,28 @@ pub struct RoomPreview {
2089 pub room_type : Option < String > ,
2190 /// Is the history world-readable for this room?
2291 pub is_history_world_readable : bool ,
23- /// Is the room joined by the current user?
24- pub is_joined : bool ,
25- /// Is the current user invited to this room?
26- pub is_invited : bool ,
27- /// is the join rule public for this room?
28- pub is_public : bool ,
29- /// Can we knock (or restricted-knock) to this room?
30- pub can_knock : bool ,
92+ /// The membership state for the current user, if known.
93+ pub membership : Option < Membership > ,
94+ /// The join rule for this room (private, public, knock, etc.).
95+ pub join_rule : JoinRule ,
3196}
3297
33- impl RoomPreview {
34- pub ( crate ) fn from_sdk ( preview : SdkRoomPreview ) -> Self {
35- Self {
36- room_id : preview. room_id . to_string ( ) ,
37- canonical_alias : preview. canonical_alias . map ( |alias| alias. to_string ( ) ) ,
38- name : preview. name ,
39- topic : preview. topic ,
40- avatar_url : preview. avatar_url . map ( |url| url. to_string ( ) ) ,
41- num_joined_members : preview. num_joined_members ,
42- room_type : preview. room_type . map ( |room_type| room_type. to_string ( ) ) ,
43- is_history_world_readable : preview. is_world_readable ,
44- is_joined : preview. state . map_or ( false , |state| state == RoomState :: Joined ) ,
45- is_invited : preview. state . map_or ( false , |state| state == RoomState :: Invited ) ,
46- is_public : preview. join_rule == SpaceRoomJoinRule :: Public ,
47- can_knock : matches ! (
48- preview. join_rule,
49- SpaceRoomJoinRule :: KnockRestricted | SpaceRoomJoinRule :: Knock
50- ) ,
51- }
98+ impl TryFrom < SpaceRoomJoinRule > for JoinRule {
99+ type Error = ( ) ;
100+
101+ fn try_from ( join_rule : SpaceRoomJoinRule ) -> Result < Self , ( ) > {
102+ Ok ( match join_rule {
103+ SpaceRoomJoinRule :: Invite => JoinRule :: Invite ,
104+ SpaceRoomJoinRule :: Knock => JoinRule :: Knock ,
105+ SpaceRoomJoinRule :: Private => JoinRule :: Private ,
106+ SpaceRoomJoinRule :: Restricted => JoinRule :: Restricted { rules : Vec :: new ( ) } ,
107+ SpaceRoomJoinRule :: KnockRestricted => JoinRule :: KnockRestricted { rules : Vec :: new ( ) } ,
108+ SpaceRoomJoinRule :: Public => JoinRule :: Public ,
109+ SpaceRoomJoinRule :: _Custom( _) => JoinRule :: Custom { repr : join_rule. to_string ( ) } ,
110+ _ => {
111+ warn ! ( "unhandled SpaceRoomJoinRule: {join_rule}" ) ;
112+ return Err ( ( ) ) ;
113+ }
114+ } )
52115 }
53116}
0 commit comments