diff --git a/matrix_sdk_base/src/client.rs b/matrix_sdk_base/src/client.rs index ff91cfcd..f28b8ec2 100644 --- a/matrix_sdk_base/src/client.rs +++ b/matrix_sdk_base/src/client.rs @@ -27,7 +27,7 @@ use matrix_sdk_common::locks::Mutex; use matrix_sdk_common::{ api::r0 as api, events::{ - ignored_user_list::IgnoredUserListEvent, push_rules::PushRulesEvent, + direct::DirectEvent, ignored_user_list::IgnoredUserListEvent, push_rules::PushRulesEvent, room::member::MemberEventContent, AnyBasicEvent, AnyStrippedStateEvent, AnySyncEphemeralRoomEvent, AnySyncMessageEvent, AnySyncRoomEvent, AnySyncStateEvent, }, @@ -695,6 +695,24 @@ impl BaseClient { // } } + /// Handle a m.direct event, updating rooms states if necessary. + /// + /// Returns true if any room changed, false otherwise. + pub(crate) async fn handle_direct(&self, event: &DirectEvent) -> bool { + let mut update = false; + for (user_id, rooms) in event.content.iter() { + for room_id in rooms.iter() { + if let Some(room) = self.get_joined_room(room_id).await { + let mut room = room.write().await; + if room.handle_direct(user_id) { + update = true; + } + } + } + } + update + } + /// Receive a timeline event for a joined room and update the client state. /// /// Returns a bool, true when the `Room` state has been updated. @@ -888,6 +906,7 @@ impl BaseClient { match event { AnyBasicEvent::IgnoredUserList(event) => self.handle_ignored_users(event).await, AnyBasicEvent::PushRules(event) => self.handle_push_rules(event).await, + AnyBasicEvent::Direct(event) => self.handle_direct(event).await, _ => false, } } diff --git a/matrix_sdk_base/src/models/message.rs b/matrix_sdk_base/src/models/message.rs index 9cac09c9..9403c6c0 100644 --- a/matrix_sdk_base/src/models/message.rs +++ b/matrix_sdk_base/src/models/message.rs @@ -206,6 +206,7 @@ mod test { }, "own_user_id": "@example:example.com", "creator": null, + "direct_target": null, "joined_members": {}, "invited_members": {}, "messages": [ msg ], @@ -253,6 +254,7 @@ mod test { }, "own_user_id": "@example:example.com", "creator": null, + "direct_target": null, "joined_members": {}, "invited_members": {}, "messages": [ msg ], diff --git a/matrix_sdk_base/src/models/room.rs b/matrix_sdk_base/src/models/room.rs index 33150622..aa333c57 100644 --- a/matrix_sdk_base/src/models/room.rs +++ b/matrix_sdk_base/src/models/room.rs @@ -190,6 +190,8 @@ pub struct Room { pub own_user_id: UserId, /// The mxid of the room creator. pub creator: Option, + /// The mxid of the "direct" target if any + pub direct_target: Option, // TODO: Track banned members, e.g. for /unban support? /// The map of invited room members. pub invited_members: HashMap, @@ -312,6 +314,7 @@ impl Room { room_name: RoomName::default(), own_user_id: own_user_id.clone(), creator: None, + direct_target: None, invited_members: HashMap::new(), joined_members: HashMap::new(), #[cfg(feature = "messages")] @@ -799,6 +802,20 @@ impl Room { true } + /// Handle setting direct attribute as part of a m.direct event, + /// updating the room if necessary + /// + /// Returns true if the direct_target changed, false otherwise. + pub fn handle_direct(&mut self, user_id: &UserId) -> bool { + if let Some(old_target) = &self.direct_target { + if old_target == user_id { + return false; + } + } + self.direct_target = Some(user_id.clone()); + true + } + fn handle_encryption_event(&mut self, event: &SyncStateEvent) -> bool { self.encrypted = Some(event.into()); true diff --git a/matrix_sdk_base/src/state/mod.rs b/matrix_sdk_base/src/state/mod.rs index 4d18a47c..ffd53d58 100644 --- a/matrix_sdk_base/src/state/mod.rs +++ b/matrix_sdk_base/src/state/mod.rs @@ -160,6 +160,7 @@ mod test { }, "own_user_id": "@example:example.com", "creator": null, + "direct_target": null, "joined_members": {}, "invited_members": {}, "typing_users": [], @@ -188,6 +189,7 @@ mod test { }, "own_user_id": "@example:example.com", "creator": null, + "direct_target": null, "joined_members": {}, "invited_members": {}, "messages": [],