Skip to content

Add direct_target to Room struct #104

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Oct 8, 2020
Merged
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
3 changes: 2 additions & 1 deletion matrix_sdk/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,8 @@ pub use matrix_sdk_base::crypto::LocalTrust;
#[cfg(not(target_arch = "wasm32"))]
pub use matrix_sdk_base::JsonStore;
pub use matrix_sdk_base::{
CustomEvent, Error as BaseError, EventEmitter, Room, RoomState, Session, StateStore, SyncRoom,
CustomEvent, Error as BaseError, EventEmitter, Room, RoomMember, RoomState, Session,
StateStore, SyncRoom,
};

#[cfg(feature = "messages")]
Expand Down
71 changes: 67 additions & 4 deletions matrix_sdk_base/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
},
Expand Down Expand Up @@ -695,6 +695,25 @@ 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) -> Vec<Arc<RwLock<Room>>> {
let mut updated_rooms = vec![];

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_locked = room.write().await;
if room_locked.handle_direct(user_id) {
updated_rooms.push(room.to_owned());
}
}
}
}
updated_rooms
}

/// Receive a timeline event for a joined room and update the client state.
///
/// Returns a bool, true when the `Room` state has been updated.
Expand Down Expand Up @@ -875,7 +894,8 @@ impl BaseClient {
}
}

/// Receive an account data event from a sync response and updates the client state.
/// Receive an account data event associated to a room from a sync
/// response and updates the client state.
///
/// Returns true if the state of the `Room` has changed, false otherwise.
///
Expand All @@ -884,14 +904,32 @@ impl BaseClient {
/// * `room_id` - The unique id of the room the event belongs to.
///
/// * `event` - The presence event for a specified room member.
pub async fn receive_account_data_event(&self, _: &RoomId, event: &AnyBasicEvent) -> bool {
pub async fn receive_room_account_data_event(&self, _: &RoomId, event: &AnyBasicEvent) -> bool {
match event {
AnyBasicEvent::IgnoredUserList(event) => self.handle_ignored_users(event).await,
AnyBasicEvent::PushRules(event) => self.handle_push_rules(event).await,
_ => false,
}
}

/// Receive an account data event from a sync response and updates
/// the client state.
///
/// Returns true if the state of any room has changed, false otherwise.
///
/// # Arguments
///
/// * `event` - The presence event for a specified room member.
pub async fn receive_account_data_event(
&self,
event: &AnyBasicEvent,
) -> Vec<Arc<RwLock<Room>>> {
match event {
AnyBasicEvent::Direct(event) => self.handle_direct(event).await,
_ => vec![],
}
}

/// Receive an ephemeral event from a sync response and updates the client state.
///
/// Returns true if the state of the `Room` has changed, false otherwise.
Expand Down Expand Up @@ -952,6 +990,7 @@ impl BaseClient {
self.iter_joined_rooms(response).await?;
self.iter_invited_rooms(response).await?;
self.iter_left_rooms(response).await?;
self.iter_account_data(response).await?;

let store = self.state_store.read().await;

Expand Down Expand Up @@ -1052,7 +1091,7 @@ impl BaseClient {
// FIXME: receive_* and emit_* methods shouldn't be called in parallel. We
// should only pass events to receive_* methods and then let *them* emit.
if let Ok(e) = account_data.deserialize() {
if self.receive_account_data_event(&room_id, &e).await {
if self.receive_room_account_data_event(&room_id, &e).await {
updated = true;
}
self.emit_account_data_event(room_id, &e, RoomStateType::Joined)
Expand Down Expand Up @@ -1168,6 +1207,30 @@ impl BaseClient {
Ok(updated)
}

async fn iter_account_data(
&self,
response: &mut api::sync::sync_events::Response,
) -> Result<bool> {
let mut updated = false;
for account_data in &response.account_data.events {
{
// FIXME: emit_account_data_event assumes a room is given
if let Ok(e) = account_data.deserialize() {
for room in self.receive_account_data_event(&e).await {
if let Some(store) = self.state_store.read().await.as_ref() {
// FIXME: currently only operate on Joined rooms
store
.store_room_state(RoomState::Joined(room.read().await.deref()))
.await?;
}
updated = true;
}
}
}
}
Ok(updated)
}

async fn iter_invited_rooms(
&self,
response: &api::sync::sync_events::Response,
Expand Down
2 changes: 1 addition & 1 deletion matrix_sdk_base/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ mod state;

pub use client::{BaseClient, BaseClientConfig, RoomState, RoomStateType};
pub use event_emitter::{CustomEvent, EventEmitter, SyncRoom};
pub use models::Room;
pub use models::{Room, RoomMember};
pub use state::{AllRooms, ClientState};

#[cfg(feature = "encryption")]
Expand Down
2 changes: 2 additions & 0 deletions matrix_sdk_base/src/models/message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@ mod test {
},
"own_user_id": "@example:example.com",
"creator": null,
"direct_target": null,
"joined_members": {},
"invited_members": {},
"messages": [ msg ],
Expand Down Expand Up @@ -253,6 +254,7 @@ mod test {
},
"own_user_id": "@example:example.com",
"creator": null,
"direct_target": null,
"joined_members": {},
"invited_members": {},
"messages": [ msg ],
Expand Down
17 changes: 17 additions & 0 deletions matrix_sdk_base/src/models/room.rs
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,8 @@ pub struct Room {
pub own_user_id: UserId,
/// The mxid of the room creator.
pub creator: Option<UserId>,
/// The mxid of the "direct" target if any
pub direct_target: Option<UserId>,
// TODO: Track banned members, e.g. for /unban support?
/// The map of invited room members.
pub invited_members: HashMap<UserId, RoomMember>,
Expand Down Expand Up @@ -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")]
Expand Down Expand Up @@ -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<EncryptionEventContent>) -> bool {
self.encrypted = Some(event.into());
true
Expand Down
8 changes: 8 additions & 0 deletions matrix_sdk_base/src/models/room_member.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,14 @@ impl PartialEq for RoomMember {
}

impl RoomMember {
/// Create a new room member.
///
/// # Arguments
///
/// * `event` - event associated with a member joining, leaving or getting
/// invited to a room.
///
/// * `room_id` - The unique id of the room this member is part of.
pub fn new(event: &SyncStateEvent<MemberEventContent>, room_id: &RoomId) -> Self {
Self {
name: event.state_key.clone(),
Expand Down
2 changes: 2 additions & 0 deletions matrix_sdk_base/src/state/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ mod test {
},
"own_user_id": "@example:example.com",
"creator": null,
"direct_target": null,
"joined_members": {},
"invited_members": {},
"typing_users": [],
Expand Down Expand Up @@ -188,6 +189,7 @@ mod test {
},
"own_user_id": "@example:example.com",
"creator": null,
"direct_target": null,
"joined_members": {},
"invited_members": {},
"messages": [],
Expand Down