matrix_sdk_ffi/
room_info.rs

1use std::collections::HashMap;
2
3use matrix_sdk::{EncryptionState, RoomState};
4use tracing::warn;
5
6use crate::{
7    client::JoinRule,
8    error::ClientError,
9    notification_settings::RoomNotificationMode,
10    room::{Membership, RoomHero, RoomHistoryVisibility},
11    room_member::RoomMember,
12};
13
14#[derive(uniffi::Record)]
15pub struct RoomInfo {
16    id: String,
17    encryption_state: EncryptionState,
18    creator: Option<String>,
19    /// The room's name from the room state event if received from sync, or one
20    /// that's been computed otherwise.
21    display_name: Option<String>,
22    /// Room name as defined by the room state event only.
23    raw_name: Option<String>,
24    topic: Option<String>,
25    avatar_url: Option<String>,
26    is_direct: bool,
27    is_public: bool,
28    is_space: bool,
29    is_tombstoned: bool,
30    is_favourite: bool,
31    canonical_alias: Option<String>,
32    alternative_aliases: Vec<String>,
33    membership: Membership,
34    /// Member who invited the current user to a room that's in the invited
35    /// state.
36    ///
37    /// Can be missing if the room membership invite event is missing from the
38    /// store.
39    inviter: Option<RoomMember>,
40    heroes: Vec<RoomHero>,
41    active_members_count: u64,
42    invited_members_count: u64,
43    joined_members_count: u64,
44    user_power_levels: HashMap<String, i64>,
45    highlight_count: u64,
46    notification_count: u64,
47    cached_user_defined_notification_mode: Option<RoomNotificationMode>,
48    has_room_call: bool,
49    active_room_call_participants: Vec<String>,
50    /// Whether this room has been explicitly marked as unread
51    is_marked_unread: bool,
52    /// "Interesting" messages received in that room, independently of the
53    /// notification settings.
54    num_unread_messages: u64,
55    /// Events that will notify the user, according to their
56    /// notification settings.
57    num_unread_notifications: u64,
58    /// Events causing mentions/highlights for the user, according to their
59    /// notification settings.
60    num_unread_mentions: u64,
61    /// The currently pinned event ids.
62    pinned_event_ids: Vec<String>,
63    /// The join rule for this room, if known.
64    join_rule: Option<JoinRule>,
65    /// The history visibility for this room, if known.
66    history_visibility: RoomHistoryVisibility,
67}
68
69impl RoomInfo {
70    pub(crate) async fn new(room: &matrix_sdk::Room) -> Result<Self, ClientError> {
71        let unread_notification_counts = room.unread_notification_counts();
72
73        let power_levels_map = room.users_with_power_levels().await;
74        let mut user_power_levels = HashMap::<String, i64>::new();
75        for (id, level) in power_levels_map.iter() {
76            user_power_levels.insert(id.to_string(), *level);
77        }
78        let pinned_event_ids =
79            room.pinned_event_ids().unwrap_or_default().iter().map(|id| id.to_string()).collect();
80
81        let join_rule = room.join_rule().try_into();
82        if let Err(e) = &join_rule {
83            warn!("Failed to parse join rule: {:?}", e);
84        }
85
86        Ok(Self {
87            id: room.room_id().to_string(),
88            encryption_state: room.encryption_state(),
89            creator: room.creator().as_ref().map(ToString::to_string),
90            display_name: room.cached_display_name().map(|name| name.to_string()),
91            raw_name: room.name(),
92            topic: room.topic(),
93            avatar_url: room.avatar_url().map(Into::into),
94            is_direct: room.is_direct().await?,
95            is_public: room.is_public(),
96            is_space: room.is_space(),
97            is_tombstoned: room.is_tombstoned(),
98            is_favourite: room.is_favourite(),
99            canonical_alias: room.canonical_alias().map(Into::into),
100            alternative_aliases: room.alt_aliases().into_iter().map(Into::into).collect(),
101            membership: room.state().into(),
102            inviter: match room.state() {
103                RoomState::Invited => room
104                    .invite_details()
105                    .await
106                    .ok()
107                    .and_then(|details| details.inviter)
108                    .map(TryInto::try_into)
109                    .transpose()
110                    .ok()
111                    .flatten(),
112                _ => None,
113            },
114            heroes: room.heroes().into_iter().map(Into::into).collect(),
115            active_members_count: room.active_members_count(),
116            invited_members_count: room.invited_members_count(),
117            joined_members_count: room.joined_members_count(),
118            user_power_levels,
119            highlight_count: unread_notification_counts.highlight_count,
120            notification_count: unread_notification_counts.notification_count,
121            cached_user_defined_notification_mode: room
122                .cached_user_defined_notification_mode()
123                .map(Into::into),
124            has_room_call: room.has_active_room_call(),
125            active_room_call_participants: room
126                .active_room_call_participants()
127                .iter()
128                .map(|u| u.to_string())
129                .collect(),
130            is_marked_unread: room.is_marked_unread(),
131            num_unread_messages: room.num_unread_messages(),
132            num_unread_notifications: room.num_unread_notifications(),
133            num_unread_mentions: room.num_unread_mentions(),
134            pinned_event_ids,
135            join_rule: join_rule.ok(),
136            history_visibility: room.history_visibility_or_default().try_into()?,
137        })
138    }
139}