Skip to content

Commit 1292755

Browse files
committed
feat(push): add experimental support for applying MSC4359 ("Do not Disturb" notification settings)
Signed-off-by: Johannes Marbach <[email protected]>
1 parent 943b048 commit 1292755

File tree

15 files changed

+466
-75
lines changed

15 files changed

+466
-75
lines changed

Cargo.lock

Lines changed: 108 additions & 71 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ rand = "0.8.5"
6565
regex = "1.11.2"
6666
reqwest = { version = "0.12.23", default-features = false }
6767
rmp-serde = "1.3.0"
68-
ruma = { git = "https://github.com/ruma/ruma", rev = "2f64faeabb85950de27e9829faeb389d2779ac57", features = [
68+
ruma = { git = "https://github.com/ruma/ruma", rev = "de227ef5c5b2d2ecff89ab021ebe53c5d565577d", features = [
6969
"client-api-c",
7070
"compat-upload-signatures",
7171
"compat-arbitrary-length-ids",
@@ -85,11 +85,12 @@ ruma = { git = "https://github.com/ruma/ruma", rev = "2f64faeabb85950de27e9829fa
8585
"unstable-msc4286",
8686
"unstable-msc4306",
8787
"unstable-msc4308",
88-
"unstable-msc4310"
88+
"unstable-msc4310",
89+
"unstable-msc4359"
8990
] }
9091
sentry = { version = "0.42.0", default-features = false }
9192
sentry-tracing = "0.42.0"
92-
serde = { version = "1.0.219", features = ["rc"] }
93+
serde = { version = "1.0.221", features = ["rc"] }
9394
serde_html_form = "0.2.7"
9495
serde_json = "1.0.143"
9596
sha2 = "0.10.9"

bindings/matrix-sdk-ffi/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ All notable changes to this project will be documented in this file.
1919

2020
- 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)).
2121
- 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)).
22+
- 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))
2223

2324
## [0.14.0] - 2025-09-04
2425

bindings/matrix-sdk-ffi/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ crate-type = [
2727
default = ["bundled-sqlite", "unstable-msc4274", "experimental-element-recent-emojis"]
2828
bundled-sqlite = ["matrix-sdk/bundled-sqlite"]
2929
unstable-msc4274 = ["matrix-sdk-ui/unstable-msc4274"]
30+
unstable-msc4359 = ["matrix-sdk-ui/unstable-msc4359"]
3031
# Required when targeting a Javascript environment, like Wasm in a browser.
3132
js = ["matrix-sdk-ui/js"]
3233
# Use the TLS implementation provided by the host system, necessary on iOS and Wasm platforms.

bindings/matrix-sdk-ffi/src/client.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ use ruma::{
6161
},
6262
events::{
6363
direct::DirectEventContent,
64+
do_not_disturb::DoNotDisturbEventContent,
6465
fully_read::FullyReadEventContent,
6566
identity_server::IdentityServerEventContent,
6667
ignored_user_list::IgnoredUserListEventContent,
@@ -699,6 +700,9 @@ impl Client {
699700
AccountDataEventType::Direct => {
700701
observe!(DirectEventContent)
701702
}
703+
AccountDataEventType::DoNotDisturbRoomList => {
704+
observe!(DoNotDisturbEventContent)
705+
}
702706
AccountDataEventType::IdentityServer => {
703707
observe!(IdentityServerEventContent)
704708
}

bindings/matrix-sdk-ffi/src/ruma.rs

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@ use ruma::{
2424
assign,
2525
events::{
2626
direct::DirectEventContent,
27+
do_not_disturb::{
28+
DoNotDisturbEventContent, DoNotDisturbRoom as RumaDoNotDisturbRoom,
29+
DoNotDisturbRoomKey as RumaDoNotDisturbRoomKey,
30+
},
2731
fully_read::FullyReadEventContent,
2832
identity_server::IdentityServerEventContent,
2933
ignored_user_list::{IgnoredUser as RumaIgnoredUser, IgnoredUserListEventContent},
@@ -1090,6 +1094,8 @@ pub fn content_without_relation_from_message(
10901094
pub enum AccountDataEventType {
10911095
/// m.direct
10921096
Direct,
1097+
/// dm.filament.do_not_disturb
1098+
DoNotDisturbRoomList,
10931099
/// m.identity_server
10941100
IdentityServer,
10951101
/// m.ignored_user_list
@@ -1108,6 +1114,7 @@ impl TryFrom<RumaGlobalAccountDataEventType> for AccountDataEventType {
11081114
fn try_from(value: RumaGlobalAccountDataEventType) -> Result<Self, Self::Error> {
11091115
match value {
11101116
RumaGlobalAccountDataEventType::Direct => Ok(Self::Direct),
1117+
RumaGlobalAccountDataEventType::DoNotDisturb => Ok(Self::DoNotDisturbRoomList),
11111118
RumaGlobalAccountDataEventType::IdentityServer => Ok(Self::IdentityServer),
11121119
RumaGlobalAccountDataEventType::IgnoredUserList => Ok(Self::IgnoredUserList),
11131120
RumaGlobalAccountDataEventType::PushRules => Ok(Self::PushRules),
@@ -1131,6 +1138,12 @@ pub enum AccountDataEvent {
11311138
/// for that user ID.
11321139
map: HashMap<String, Vec<String>>,
11331140
},
1141+
/// dm.filament.do_not_disturb
1142+
DoNotDisturbRoomList {
1143+
/// The map of rooms in "Do not Disturb" mode. This is a mapping from
1144+
/// [`DoNotDisturbRoomKey`] to empty object.
1145+
rooms: HashMap<DoNotDisturbRoomKey, DoNotDisturbRoom>,
1146+
},
11341147
/// m.identity_server
11351148
IdentityServer {
11361149
/// The base URL for the identity server for client-server connections.
@@ -1232,6 +1245,42 @@ impl From<InviteAvatars> for RumaInviteAvatars {
12321245
}
12331246
}
12341247

1248+
/// The key for a "Do not Disturb" setting.
1249+
///
1250+
/// This either matches a single room or all rooms.
1251+
#[derive(Clone, Eq, Hash, PartialEq, uniffi::Enum)]
1252+
pub enum DoNotDisturbRoomKey {
1253+
/// Match any room.
1254+
AllRooms,
1255+
1256+
/// Match a single room based on its room ID.
1257+
SingleRoom(String),
1258+
}
1259+
1260+
impl From<RumaDoNotDisturbRoomKey> for DoNotDisturbRoomKey {
1261+
fn from(value: RumaDoNotDisturbRoomKey) -> Self {
1262+
match value {
1263+
RumaDoNotDisturbRoomKey::AllRooms => DoNotDisturbRoomKey::AllRooms,
1264+
RumaDoNotDisturbRoomKey::SingleRoom(room_id) => {
1265+
DoNotDisturbRoomKey::SingleRoom(room_id.into())
1266+
}
1267+
_ => panic!("Unexpected DoNotDisturbRoomKey: {value:?}"),
1268+
}
1269+
}
1270+
}
1271+
1272+
/// Details about a room in "Do not Disturb" mode.
1273+
///
1274+
/// This is currently empty.
1275+
#[derive(Clone, uniffi::Record)]
1276+
pub struct DoNotDisturbRoom {}
1277+
1278+
impl From<RumaDoNotDisturbRoom> for DoNotDisturbRoom {
1279+
fn from(_value: RumaDoNotDisturbRoom) -> Self {
1280+
DoNotDisturbRoom {}
1281+
}
1282+
}
1283+
12351284
/// Details about an ignored user.
12361285
///
12371286
/// This is currently empty.
@@ -1567,6 +1616,21 @@ impl From<RumaGlobalAccountDataEvent<DirectEventContent>> for AccountDataEvent {
15671616
}
15681617
}
15691618

1619+
impl From<RumaGlobalAccountDataEvent<DoNotDisturbEventContent>> for AccountDataEvent {
1620+
fn from(value: RumaGlobalAccountDataEvent<DoNotDisturbEventContent>) -> Self {
1621+
Self::DoNotDisturbRoomList {
1622+
rooms: value
1623+
.content
1624+
.rooms
1625+
.into_iter()
1626+
.map(|(key, do_not_disturb_room)| {
1627+
(key.into(), DoNotDisturbRoom::from(do_not_disturb_room))
1628+
})
1629+
.collect(),
1630+
}
1631+
}
1632+
}
1633+
15701634
impl From<RumaGlobalAccountDataEvent<IdentityServerEventContent>> for AccountDataEvent {
15711635
fn from(value: RumaGlobalAccountDataEvent<IdentityServerEventContent>) -> Self {
15721636
Self::IdentityServer { base_url: value.content.base_url.into_option() }

crates/matrix-sdk-base/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,9 @@ testing = [
6565
# Add support for inline media galleries via msgtypes
6666
unstable-msc4274 = []
6767

68+
# "Do not Disturb" notification settings
69+
unstable-msc4359 = ["ruma/unstable-msc4359"]
70+
6871
experimental-element-recent-emojis = []
6972

7073
[dependencies]

crates/matrix-sdk-base/src/client.rs

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ use matrix_sdk_crypto::{
3232
};
3333
#[cfg(doc)]
3434
use ruma::DeviceId;
35+
#[cfg(feature = "unstable-msc4359")]
36+
use ruma::events::do_not_disturb::{DoNotDisturbEventContent, DoNotDisturbRoomKey};
3537
#[cfg(feature = "e2e-encryption")]
3638
use ruma::events::room::{history_visibility::HistoryVisibility, member::MembershipState};
3739
use ruma::{
@@ -1135,6 +1137,37 @@ impl BaseClient {
11351137
}
11361138
}
11371139
}
1140+
1141+
/// Checks whether the provided `room_id` belongs to a room in "Do not
1142+
/// Disturb" mode.
1143+
#[cfg(feature = "unstable-msc4359")]
1144+
pub async fn is_room_in_do_not_disturb_mode(&self, room_id: &RoomId) -> bool {
1145+
match self.state_store.get_account_data_event_static::<DoNotDisturbEventContent>().await {
1146+
Ok(Some(raw_do_not_disturb_room_list)) => {
1147+
match raw_do_not_disturb_room_list.deserialize() {
1148+
Ok(current_do_not_disturb_room_list) => {
1149+
current_do_not_disturb_room_list
1150+
.content
1151+
.rooms
1152+
.contains_key(&DoNotDisturbRoomKey::AllRooms)
1153+
|| current_do_not_disturb_room_list
1154+
.content
1155+
.rooms
1156+
.contains_key(&DoNotDisturbRoomKey::SingleRoom(room_id.to_owned()))
1157+
}
1158+
Err(error) => {
1159+
warn!(?error, "Failed to deserialize the 'Do not Disturb' room list event");
1160+
false
1161+
}
1162+
}
1163+
}
1164+
Ok(None) => false,
1165+
Err(error) => {
1166+
warn!(?error, "Could not get the 'Do not Disturb' room list from the state store");
1167+
false
1168+
}
1169+
}
1170+
}
11381171
}
11391172

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

1808+
#[cfg(feature = "unstable-msc4359")]
1809+
#[async_test]
1810+
async fn test_is_room_in_do_not_disturb() {
1811+
let dnd_room_id = room_id!("!sonofagun");
1812+
let client = logged_in_base_client(None).await;
1813+
1814+
assert!(!client.is_room_in_do_not_disturb_mode(dnd_room_id).await);
1815+
1816+
let mut sync_builder = SyncResponseBuilder::new();
1817+
let f = EventFactory::new();
1818+
let response = sync_builder
1819+
.add_global_account_data(f.do_not_disturb_room_list([dnd_room_id.to_owned()]))
1820+
.build_sync_response();
1821+
client.receive_sync_response(response).await.unwrap();
1822+
1823+
assert!(client.is_room_in_do_not_disturb_mode(dnd_room_id).await);
1824+
}
1825+
17751826
#[async_test]
17761827
async fn test_invite_details_are_set() {
17771828
let user_id = user_id!("@alice:localhost");

crates/matrix-sdk-ui/CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,12 @@ All notable changes to this project will be documented in this file.
2525
`RoomListItem`.
2626
([#5684](https://github.com/matrix-org/matrix-rust-sdk/pull/5684))
2727

28+
### Features
29+
30+
- Apply "Do not Disturb" room list when filtering notifications as
31+
per MSC4359
32+
([#5687](https://github.com/matrix-org/matrix-rust-sdk/pull/5687))
33+
2834
## [0.14.0] - 2025-09-04
2935

3036
### Features

crates/matrix-sdk-ui/Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ unstable-msc3956 = ["ruma/unstable-msc3956"]
2525
# Add support for inline media galleries via msgtypes
2626
unstable-msc4274 = ["matrix-sdk/unstable-msc4274"]
2727

28+
# "Do not Disturb" notification settings
29+
unstable-msc4359 = ["matrix-sdk/unstable-msc4359"]
30+
2831
# Enable experimental support for encrypting state events; see
2932
# https://github.com/matrix-org/matrix-rust-sdk/issues/5397.
3033
experimental-encrypted-state-events = [
@@ -38,6 +41,7 @@ async-rx.workspace = true
3841
async-stream.workspace = true
3942
async_cell = "0.2.3"
4043
bitflags.workspace = true
44+
cfg-if.workspace = true
4145
chrono.workspace = true
4246
eyeball.workspace = true
4347
eyeball-im.workspace = true

0 commit comments

Comments
 (0)