matrix_sdk_ffi/
notification.rs

1use std::sync::Arc;
2
3use matrix_sdk_ui::notification_client::{
4    NotificationClient as MatrixNotificationClient, NotificationItem as MatrixNotificationItem,
5};
6use ruma::{EventId, RoomId};
7
8use crate::{client::Client, error::ClientError, event::TimelineEvent};
9
10#[derive(uniffi::Enum)]
11pub enum NotificationEvent {
12    Timeline { event: Arc<TimelineEvent> },
13    Invite { sender: String },
14}
15
16#[derive(uniffi::Record)]
17pub struct NotificationSenderInfo {
18    pub display_name: Option<String>,
19    pub avatar_url: Option<String>,
20    pub is_name_ambiguous: bool,
21}
22
23#[derive(uniffi::Record)]
24pub struct NotificationRoomInfo {
25    pub display_name: String,
26    pub avatar_url: Option<String>,
27    pub canonical_alias: Option<String>,
28    pub joined_members_count: u64,
29    pub is_encrypted: Option<bool>,
30    pub is_direct: bool,
31}
32
33#[derive(uniffi::Record)]
34pub struct NotificationItem {
35    pub event: NotificationEvent,
36
37    pub sender_info: NotificationSenderInfo,
38    pub room_info: NotificationRoomInfo,
39
40    /// Is the notification supposed to be at the "noisy" level?
41    /// Can be `None` if we couldn't determine this, because we lacked
42    /// information to create a push context.
43    pub is_noisy: Option<bool>,
44    pub has_mention: Option<bool>,
45}
46
47impl NotificationItem {
48    fn from_inner(item: MatrixNotificationItem) -> Self {
49        let event = match item.event {
50            matrix_sdk_ui::notification_client::NotificationEvent::Timeline(event) => {
51                NotificationEvent::Timeline { event: Arc::new(TimelineEvent(event)) }
52            }
53            matrix_sdk_ui::notification_client::NotificationEvent::Invite(event) => {
54                NotificationEvent::Invite { sender: event.sender.to_string() }
55            }
56        };
57
58        Self {
59            event,
60            sender_info: NotificationSenderInfo {
61                display_name: item.sender_display_name,
62                avatar_url: item.sender_avatar_url,
63                is_name_ambiguous: item.is_sender_name_ambiguous,
64            },
65            room_info: NotificationRoomInfo {
66                display_name: item.room_computed_display_name,
67                avatar_url: item.room_avatar_url,
68                canonical_alias: item.room_canonical_alias,
69                joined_members_count: item.joined_members_count,
70                is_encrypted: item.is_room_encrypted,
71                is_direct: item.is_direct_message_room,
72            },
73            is_noisy: item.is_noisy,
74            has_mention: item.has_mention,
75        }
76    }
77}
78
79#[derive(uniffi::Object)]
80pub struct NotificationClient {
81    pub(crate) inner: MatrixNotificationClient,
82
83    /// A reference to the FFI client.
84    ///
85    /// Note: we do this to make it so that the FFI `NotificationClient` keeps
86    /// the FFI `Client` and thus the SDK `Client` alive. Otherwise, we
87    /// would need to repeat the hack done in the FFI `Client::drop` method.
88    pub(crate) _client: Arc<Client>,
89}
90
91#[matrix_sdk_ffi_macros::export]
92impl NotificationClient {
93    /// See also documentation of
94    /// `MatrixNotificationClient::get_notification`.
95    pub async fn get_notification(
96        &self,
97        room_id: String,
98        event_id: String,
99    ) -> Result<Option<NotificationItem>, ClientError> {
100        let room_id = RoomId::parse(room_id)?;
101        let event_id = EventId::parse(event_id)?;
102
103        let item =
104            self.inner.get_notification(&room_id, &event_id).await.map_err(ClientError::from)?;
105
106        if let Some(item) = item {
107            Ok(Some(NotificationItem::from_inner(item)))
108        } else {
109            Ok(None)
110        }
111    }
112}