Merge branch 'master' into crypto-improvements

master
Damir Jelić 2020-10-08 18:28:04 +02:00
commit 661f182382
7 changed files with 99 additions and 6 deletions

View File

@ -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")]

View File

@ -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,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.
@ -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.
///
@ -884,7 +904,7 @@ 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,
@ -892,6 +912,24 @@ impl BaseClient {
}
}
/// 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.
@ -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;
@ -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)
@ -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,

View File

@ -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")]

View File

@ -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 ],

View File

@ -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>,
@ -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<EncryptionEventContent>) -> bool {
self.encrypted = Some(event.into());
true

View File

@ -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(),

View File

@ -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": [],