Skip to content
Draft
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
179 changes: 108 additions & 71 deletions Cargo.lock

Large diffs are not rendered by default.

7 changes: 4 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ rand = "0.8.5"
regex = "1.11.2"
reqwest = { version = "0.12.23", default-features = false }
rmp-serde = "1.3.0"
ruma = { git = "https://github.com/ruma/ruma", rev = "2f64faeabb85950de27e9829faeb389d2779ac57", features = [
ruma = { git = "https://github.com/ruma/ruma", rev = "de227ef5c5b2d2ecff89ab021ebe53c5d565577d", features = [
"client-api-c",
"compat-upload-signatures",
"compat-arbitrary-length-ids",
Expand All @@ -85,11 +85,12 @@ ruma = { git = "https://github.com/ruma/ruma", rev = "2f64faeabb85950de27e9829fa
"unstable-msc4286",
"unstable-msc4306",
"unstable-msc4308",
"unstable-msc4310"
"unstable-msc4310",
"unstable-msc4359"
] }
sentry = { version = "0.42.0", default-features = false }
sentry-tracing = "0.42.0"
serde = { version = "1.0.219", features = ["rc"] }
serde = { version = "1.0.221", features = ["rc"] }
serde_html_form = "0.2.7"
serde_json = "1.0.143"
sha2 = "0.10.9"
Expand Down
1 change: 1 addition & 0 deletions bindings/matrix-sdk-ffi/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ All notable changes to this project will be documented in this file.

- Add `Room::load_or_fetch_event` so we can get a `TimelineEvent` given its event id ([#5678](https://github.com/matrix-org/matrix-rust-sdk/pull/5678)).
- Add `TimelineEvent::thread_root_event_id` to expose the thread root event id for this type too ([#5678](https://github.com/matrix-org/matrix-rust-sdk/pull/5678)).
- Add support for "Do not Disturb" room list in account data as per MSC4359 ([#5687](https://github.com/matrix-org/matrix-rust-sdk/pull/5687))

## [0.14.0] - 2025-09-04

Expand Down
1 change: 1 addition & 0 deletions bindings/matrix-sdk-ffi/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ crate-type = [
default = ["bundled-sqlite", "unstable-msc4274", "experimental-element-recent-emojis"]
bundled-sqlite = ["matrix-sdk/bundled-sqlite"]
unstable-msc4274 = ["matrix-sdk-ui/unstable-msc4274"]
unstable-msc4359 = ["matrix-sdk-ui/unstable-msc4359"]
# Required when targeting a Javascript environment, like Wasm in a browser.
js = ["matrix-sdk-ui/js"]
# Use the TLS implementation provided by the host system, necessary on iOS and Wasm platforms.
Expand Down
4 changes: 4 additions & 0 deletions bindings/matrix-sdk-ffi/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ use ruma::{
},
events::{
direct::DirectEventContent,
do_not_disturb::DoNotDisturbEventContent,
fully_read::FullyReadEventContent,
identity_server::IdentityServerEventContent,
ignored_user_list::IgnoredUserListEventContent,
Expand Down Expand Up @@ -699,6 +700,9 @@ impl Client {
AccountDataEventType::Direct => {
observe!(DirectEventContent)
}
AccountDataEventType::DoNotDisturbRoomList => {
observe!(DoNotDisturbEventContent)
}
AccountDataEventType::IdentityServer => {
observe!(IdentityServerEventContent)
}
Expand Down
64 changes: 64 additions & 0 deletions bindings/matrix-sdk-ffi/src/ruma.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ use ruma::{
assign,
events::{
direct::DirectEventContent,
do_not_disturb::{
DoNotDisturbEventContent, DoNotDisturbRoom as RumaDoNotDisturbRoom,
DoNotDisturbRoomKey as RumaDoNotDisturbRoomKey,
},
fully_read::FullyReadEventContent,
identity_server::IdentityServerEventContent,
ignored_user_list::{IgnoredUser as RumaIgnoredUser, IgnoredUserListEventContent},
Expand Down Expand Up @@ -1090,6 +1094,8 @@ pub fn content_without_relation_from_message(
pub enum AccountDataEventType {
/// m.direct
Direct,
/// dm.filament.do_not_disturb
DoNotDisturbRoomList,
/// m.identity_server
IdentityServer,
/// m.ignored_user_list
Expand All @@ -1108,6 +1114,7 @@ impl TryFrom<RumaGlobalAccountDataEventType> for AccountDataEventType {
fn try_from(value: RumaGlobalAccountDataEventType) -> Result<Self, Self::Error> {
match value {
RumaGlobalAccountDataEventType::Direct => Ok(Self::Direct),
RumaGlobalAccountDataEventType::DoNotDisturb => Ok(Self::DoNotDisturbRoomList),
RumaGlobalAccountDataEventType::IdentityServer => Ok(Self::IdentityServer),
RumaGlobalAccountDataEventType::IgnoredUserList => Ok(Self::IgnoredUserList),
RumaGlobalAccountDataEventType::PushRules => Ok(Self::PushRules),
Expand All @@ -1131,6 +1138,12 @@ pub enum AccountDataEvent {
/// for that user ID.
map: HashMap<String, Vec<String>>,
},
/// dm.filament.do_not_disturb
DoNotDisturbRoomList {
/// The map of rooms in "Do not Disturb" mode. This is a mapping from
/// [`DoNotDisturbRoomKey`] to empty object.
rooms: HashMap<DoNotDisturbRoomKey, DoNotDisturbRoom>,
},
/// m.identity_server
IdentityServer {
/// The base URL for the identity server for client-server connections.
Expand Down Expand Up @@ -1232,6 +1245,42 @@ impl From<InviteAvatars> for RumaInviteAvatars {
}
}

/// The key for a "Do not Disturb" setting.
///
/// This either matches a single room or all rooms.
#[derive(Clone, Eq, Hash, PartialEq, uniffi::Enum)]
pub enum DoNotDisturbRoomKey {
/// Match any room.
AllRooms,

/// Match a single room based on its room ID.
SingleRoom(String),
}

impl From<RumaDoNotDisturbRoomKey> for DoNotDisturbRoomKey {
fn from(value: RumaDoNotDisturbRoomKey) -> Self {
match value {
RumaDoNotDisturbRoomKey::AllRooms => DoNotDisturbRoomKey::AllRooms,
RumaDoNotDisturbRoomKey::SingleRoom(room_id) => {
DoNotDisturbRoomKey::SingleRoom(room_id.into())
}
_ => panic!("Unexpected DoNotDisturbRoomKey: {value:?}"),
}
}
}

/// Details about a room in "Do not Disturb" mode.
///
/// This is currently empty.
#[derive(Clone, uniffi::Record)]
pub struct DoNotDisturbRoom {}

impl From<RumaDoNotDisturbRoom> for DoNotDisturbRoom {
fn from(_value: RumaDoNotDisturbRoom) -> Self {
DoNotDisturbRoom {}
}
}

/// Details about an ignored user.
///
/// This is currently empty.
Expand Down Expand Up @@ -1567,6 +1616,21 @@ impl From<RumaGlobalAccountDataEvent<DirectEventContent>> for AccountDataEvent {
}
}

impl From<RumaGlobalAccountDataEvent<DoNotDisturbEventContent>> for AccountDataEvent {
fn from(value: RumaGlobalAccountDataEvent<DoNotDisturbEventContent>) -> Self {
Self::DoNotDisturbRoomList {
rooms: value
.content
.rooms
.into_iter()
.map(|(key, do_not_disturb_room)| {
(key.into(), DoNotDisturbRoom::from(do_not_disturb_room))
})
.collect(),
}
}
}

impl From<RumaGlobalAccountDataEvent<IdentityServerEventContent>> for AccountDataEvent {
fn from(value: RumaGlobalAccountDataEvent<IdentityServerEventContent>) -> Self {
Self::IdentityServer { base_url: value.content.base_url.into_option() }
Expand Down
3 changes: 3 additions & 0 deletions crates/matrix-sdk-base/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,9 @@ testing = [
# Add support for inline media galleries via msgtypes
unstable-msc4274 = []

# "Do not Disturb" notification settings
unstable-msc4359 = ["ruma/unstable-msc4359"]

experimental-element-recent-emojis = []

[dependencies]
Expand Down
51 changes: 51 additions & 0 deletions crates/matrix-sdk-base/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ use matrix_sdk_crypto::{
};
#[cfg(doc)]
use ruma::DeviceId;
#[cfg(feature = "unstable-msc4359")]
use ruma::events::do_not_disturb::{DoNotDisturbEventContent, DoNotDisturbRoomKey};
#[cfg(feature = "e2e-encryption")]
use ruma::events::room::{history_visibility::HistoryVisibility, member::MembershipState};
use ruma::{
Expand Down Expand Up @@ -1135,6 +1137,37 @@ impl BaseClient {
}
}
}

/// Checks whether the provided `room_id` belongs to a room in "Do not
/// Disturb" mode.
#[cfg(feature = "unstable-msc4359")]
pub async fn is_room_in_do_not_disturb_mode(&self, room_id: &RoomId) -> bool {
match self.state_store.get_account_data_event_static::<DoNotDisturbEventContent>().await {
Ok(Some(raw_do_not_disturb_room_list)) => {
match raw_do_not_disturb_room_list.deserialize() {
Ok(current_do_not_disturb_room_list) => {
current_do_not_disturb_room_list
.content
.rooms
.contains_key(&DoNotDisturbRoomKey::AllRooms)
|| current_do_not_disturb_room_list
.content
.rooms
.contains_key(&DoNotDisturbRoomKey::SingleRoom(room_id.to_owned()))
}
Err(error) => {
warn!(?error, "Failed to deserialize the 'Do not Disturb' room list event");
false
}
}
}
Ok(None) => false,
Err(error) => {
warn!(?error, "Could not get the 'Do not Disturb' room list from the state store");
false
}
}
}
}

/// Represent the `required_state` values sent by a sync request.
Expand Down Expand Up @@ -1772,6 +1805,24 @@ mod tests {
assert!(client.is_user_ignored(ignored_user_id).await);
}

#[cfg(feature = "unstable-msc4359")]
#[async_test]
async fn test_is_room_in_do_not_disturb() {
let dnd_room_id = room_id!("!sonofagun");
let client = logged_in_base_client(None).await;

assert!(!client.is_room_in_do_not_disturb_mode(dnd_room_id).await);

let mut sync_builder = SyncResponseBuilder::new();
let f = EventFactory::new();
let response = sync_builder
.add_global_account_data(f.do_not_disturb_room_list([dnd_room_id.to_owned()]))
.build_sync_response();
client.receive_sync_response(response).await.unwrap();

assert!(client.is_room_in_do_not_disturb_mode(dnd_room_id).await);
}

#[async_test]
async fn test_invite_details_are_set() {
let user_id = user_id!("@alice:localhost");
Expand Down
6 changes: 6 additions & 0 deletions crates/matrix-sdk-ui/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,12 @@ All notable changes to this project will be documented in this file.
`RoomListItem`.
([#5684](https://github.com/matrix-org/matrix-rust-sdk/pull/5684))

### Features

- Apply "Do not Disturb" room list when filtering notifications as
per MSC4359
([#5687](https://github.com/matrix-org/matrix-rust-sdk/pull/5687))

## [0.14.0] - 2025-09-04

### Features
Expand Down
4 changes: 4 additions & 0 deletions crates/matrix-sdk-ui/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ unstable-msc3956 = ["ruma/unstable-msc3956"]
# Add support for inline media galleries via msgtypes
unstable-msc4274 = ["matrix-sdk/unstable-msc4274"]

# "Do not Disturb" notification settings
unstable-msc4359 = ["matrix-sdk/unstable-msc4359"]

# Enable experimental support for encrypting state events; see
# https://github.com/matrix-org/matrix-rust-sdk/issues/5397.
experimental-encrypted-state-events = [
Expand All @@ -38,6 +41,7 @@ async-rx.workspace = true
async-stream.workspace = true
async_cell = "0.2.3"
bitflags.workspace = true
cfg-if.workspace = true
chrono.workspace = true
eyeball.workspace = true
eyeball-im.workspace = true
Expand Down
15 changes: 14 additions & 1 deletion crates/matrix-sdk-ui/src/notification_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ use std::{
time::Duration,
};

use cfg_if::cfg_if;
use futures_util::{StreamExt as _, pin_mut};
use matrix_sdk::{
Client, ClientBuildError, SlidingSyncList, SlidingSyncMode, room::Room, sleep::sleep,
Expand Down Expand Up @@ -637,7 +638,19 @@ impl NotificationClient {
let notification_item =
NotificationItem::new(room, raw_event, push_actions, state_events).await?;

if self.client.is_user_ignored(notification_item.event.sender()).await {
let is_room_in_do_not_disturb = {
cfg_if! {
if #[cfg(feature = "unstable-msc4359")] {
self.client.is_room_in_do_not_disturb_mode(room.room_id()).await
} else {
false
}
}
};

if self.client.is_user_ignored(notification_item.event.sender()).await
|| is_room_in_do_not_disturb
{
Ok(NotificationStatus::EventFilteredOut)
} else {
Ok(NotificationStatus::Event(Box::new(notification_item)))
Expand Down
Loading
Loading