From 45db95742a1b5478690e3548d4ca316bcc566cc2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Damir=20Jeli=C4=87?= Date: Mon, 14 Dec 2020 14:36:39 +0100 Subject: [PATCH] base: Add a common room info struct for normal and stripped rooms. --- matrix_sdk_base/src/client.rs | 82 +++++++++++++-------------- matrix_sdk_base/src/rooms/mod.rs | 76 +++++++++++++++++++++++++ matrix_sdk_base/src/rooms/normal.rs | 63 ++++++-------------- matrix_sdk_base/src/rooms/stripped.rs | 48 ++++------------ 4 files changed, 145 insertions(+), 124 deletions(-) diff --git a/matrix_sdk_base/src/client.rs b/matrix_sdk_base/src/client.rs index 2a6c5563..593c97a4 100644 --- a/matrix_sdk_base/src/client.rs +++ b/matrix_sdk_base/src/client.rs @@ -30,8 +30,10 @@ use futures::StreamExt; use matrix_sdk_common::{ api::r0 as api, events::{ - presence::PresenceEvent, room::member::{MemberEventContent, MembershipState}, AnyBasicEvent, - AnyStrippedStateEvent, AnySyncRoomEvent, AnySyncStateEvent, EventContent, StateEvent, + presence::PresenceEvent, + room::member::{MemberEventContent, MembershipState}, + AnyBasicEvent, AnyStrippedStateEvent, AnySyncRoomEvent, AnySyncStateEvent, EventContent, + StateEvent, }, identifiers::{RoomId, UserId}, locks::RwLock, @@ -40,10 +42,7 @@ use matrix_sdk_common::{ #[cfg(feature = "encryption")] use matrix_sdk_common::{ api::r0::keys::claim_keys::Request as KeysClaimRequest, - events::{ - room::encrypted::EncryptedEventContent, - AnyMessageEventContent, AnySyncMessageEvent, - }, + events::{room::encrypted::EncryptedEventContent, AnyMessageEventContent, AnySyncMessageEvent}, identifiers::DeviceId, locks::Mutex, uuid::Uuid, @@ -456,7 +455,7 @@ impl BaseClient { &self, room_id: &RoomId, ruma_timeline: api::sync::sync_events::Timeline, - summary: &mut RoomInfo, + room_info: &mut RoomInfo, changes: &mut StateChanges, user_ids: &mut BTreeSet, ) -> Timeline { @@ -485,7 +484,7 @@ impl BaseClient { } } _ => { - summary.handle_state_event(&s); + room_info.handle_state_event(&s); changes.add_state_event(room_id, s.clone()); } }, @@ -668,40 +667,39 @@ impl BaseClient { let mut changes = StateChanges::default(); let mut rooms = Rooms::default(); - for (room_id, room_info) in response.rooms.join { + for (room_id, new_info) in response.rooms.join { let room = self.get_or_create_room(&room_id, RoomType::Joined).await; - let mut summary = room.clone_summary(); + let mut room_info = room.clone_info(); - summary.mark_as_joined(); - summary.update(&room_info.summary); - summary.set_prev_batch(room_info.timeline.prev_batch.as_deref()); + room_info.update_summary(&new_info.summary); + room_info.set_prev_batch(new_info.timeline.prev_batch.as_deref()); let (state, members, state_events, mut user_ids) = - self.handle_state(room_info.state.events, &mut summary); + self.handle_state(new_info.state.events, &mut room_info); changes.members.insert(room_id.clone(), members); changes.state.insert(room_id.clone(), state_events); - if room_info.timeline.limited { - summary.mark_members_missing(); + if new_info.timeline.limited { + room_info.mark_members_missing(); } let timeline = self .handle_timeline( &room_id, - room_info.timeline, - &mut summary, + new_info.timeline, + &mut room_info, &mut changes, &mut user_ids, ) .await; let account_data = self - .handle_room_account_data(&room_id, &room_info.account_data.events, &mut changes) + .handle_room_account_data(&room_id, &new_info.account_data.events, &mut changes) .await; #[cfg(feature = "encryption")] - if summary.is_encrypted() { + if room_info.is_encrypted() { if let Some(o) = self.olm_machine().await { if !room.is_encrypted() { // The room turned on encryption in this sync, we need @@ -719,12 +717,12 @@ impl BaseClient { } } - let notification_count = room_info.unread_notifications.into(); - summary.update_notification_count(notification_count); + let notification_count = new_info.unread_notifications.into(); + room_info.update_notification_count(notification_count); // TODO should we store this? let ephemeral = Ephemeral { - events: room_info + events: new_info .ephemeral .events .into_iter() @@ -737,16 +735,16 @@ impl BaseClient { JoinedRoom::new(timeline, state, account_data, ephemeral, notification_count), ); - changes.add_room(summary); + changes.add_room(room_info); } - for (room_id, room_info) in response.rooms.leave { + for (room_id, new_info) in response.rooms.leave { let room = self.get_or_create_room(&room_id, RoomType::Left).await; - let mut summary = room.clone_summary(); - summary.mark_as_left(); + let mut room_info = room.clone_info(); + room_info.mark_as_left(); let (state, members, state_events, mut user_ids) = - self.handle_state(room_info.state.events, &mut summary); + self.handle_state(new_info.state.events, &mut room_info); changes.members.insert(room_id.clone(), members); changes.state.insert(room_id.clone(), state_events); @@ -754,15 +752,15 @@ impl BaseClient { let timeline = self .handle_timeline( &room_id, - room_info.timeline, - &mut summary, + new_info.timeline, + &mut room_info, &mut changes, &mut user_ids, ) .await; let account_data = self - .handle_room_account_data(&room_id, &room_info.account_data.events, &mut changes) + .handle_room_account_data(&room_id, &new_info.account_data.events, &mut changes) .await; rooms @@ -770,19 +768,19 @@ impl BaseClient { .insert(room_id, LeftRoom::new(timeline, state, account_data)); } - for (room_id, invited) in response.rooms.invite { + for (room_id, new_info) in response.rooms.invite { { let room = self.get_or_create_room(&room_id, RoomType::Invited).await; - let mut room_info = room.clone_summary(); + let mut room_info = room.clone_info(); room_info.mark_as_invited(); changes.add_room(room_info); } let room = self.get_or_create_stripped_room(&room_id).await; - let mut room_info = room.clone_summary(); + let mut room_info = room.clone_info(); let (state, members, state_events) = - self.handle_invited_state(invited.invite_state.events, &mut room_info); + self.handle_invited_state(new_info.invite_state.events, &mut room_info); changes.stripped_members.insert(room_id.clone(), members); changes.stripped_state.insert(room_id.clone(), state_events); @@ -846,9 +844,9 @@ impl BaseClient { async fn apply_changes(&self, changes: &StateChanges) { // TODO emit room changes here - for (room_id, summary) in &changes.room_infos { + for (room_id, room_info) in &changes.room_infos { if let Some(room) = self.get_room(&room_id) { - room.update_summary(summary.clone()) + room.update_summary(room_info.clone()) } } } @@ -859,8 +857,8 @@ impl BaseClient { response: &api::membership::get_member_events::Response, ) -> Result<()> { if let Some(room) = self.get_room(room_id) { - let mut summary = room.clone_summary(); - summary.mark_members_synced(); + let mut room_info = room.clone_info(); + room_info.mark_members_synced(); let mut members = BTreeMap::new(); @@ -877,7 +875,7 @@ impl BaseClient { .store .get_member_event(&room_id, &member.state_key) .await - .is_some() + .is_none() { #[cfg(feature = "encryption")] match member.content.membership { @@ -895,13 +893,13 @@ impl BaseClient { changes.members.insert(room_id.clone(), members); #[cfg(feature = "encryption")] - if summary.is_encrypted() { + if room_info.is_encrypted() { if let Some(o) = self.olm_machine().await { o.update_tracked_users(&user_ids).await } } - changes.add_room(summary); + changes.add_room(room_info); self.store.save_changes(&changes).await; self.apply_changes(&changes).await; diff --git a/matrix_sdk_base/src/rooms/mod.rs b/matrix_sdk_base/src/rooms/mod.rs index 905ade2a..337346d6 100644 --- a/matrix_sdk_base/src/rooms/mod.rs +++ b/matrix_sdk_base/src/rooms/mod.rs @@ -6,3 +6,79 @@ pub use normal::{Room, RoomInfo, RoomType}; pub use stripped::{StrippedRoom, StrippedRoomInfo}; pub use members::RoomMember; + +use serde::{Deserialize, Serialize}; +use std::cmp::max; + +use matrix_sdk_common::{ + events::{ + room::{encryption::EncryptionEventContent, tombstone::TombstoneEventContent}, + AnyStateEventContent, + }, + identifiers::RoomAliasId, +}; + +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct BaseRoomInfo { + pub name: Option, + pub canonical_alias: Option, + pub avatar_url: Option, + pub topic: Option, + pub encryption: Option, + pub tombstone: Option, + pub max_power_level: i64, +} + +impl BaseRoomInfo { + pub fn new() -> Self { + Self::default() + } + + pub fn handle_state_event(&mut self, content: &AnyStateEventContent) -> bool { + match content { + AnyStateEventContent::RoomEncryption(encryption) => { + self.encryption = Some(encryption.clone()); + true + } + AnyStateEventContent::RoomName(n) => { + self.name = n.name().map(|n| n.to_string()); + true + } + AnyStateEventContent::RoomCanonicalAlias(a) => { + self.canonical_alias = a.alias.clone(); + true + } + AnyStateEventContent::RoomTopic(t) => { + self.topic = Some(t.topic.clone()); + true + } + AnyStateEventContent::RoomTombstone(t) => { + self.tombstone = Some(t.clone()); + true + } + AnyStateEventContent::RoomPowerLevels(p) => { + let max_power_level = p + .users + .values() + .fold(self.max_power_level, |acc, p| max(acc, (*p).into())); + self.max_power_level = max_power_level; + true + } + _ => false, + } + } +} + +impl Default for BaseRoomInfo { + fn default() -> Self { + Self { + name: None, + canonical_alias: None, + avatar_url: None, + topic: None, + encryption: None, + tombstone: None, + max_power_level: 100, + } + } +} diff --git a/matrix_sdk_base/src/rooms/normal.rs b/matrix_sdk_base/src/rooms/normal.rs index 307c7138..99804cb6 100644 --- a/matrix_sdk_base/src/rooms/normal.rs +++ b/matrix_sdk_base/src/rooms/normal.rs @@ -23,14 +23,14 @@ use futures::{ }; use matrix_sdk_common::{ api::r0::sync::sync_events::RoomSummary as RumaSummary, - events::{room::encryption::EncryptionEventContent, AnySyncStateEvent, EventType}, - identifiers::{RoomAliasId, RoomId, UserId}, + events::{AnySyncStateEvent, EventType}, + identifiers::{RoomId, UserId}, }; use serde::{Deserialize, Serialize}; use crate::{responses::UnreadNotificationsCount, store::Store}; -use super::RoomMember; +use super::{BaseRoomInfo, RoomMember}; #[derive(Debug, Clone)] pub struct Room { @@ -69,15 +69,11 @@ impl Room { inner: Arc::new(SyncMutex::new(RoomInfo { room_id, room_type, - encryption: None, - summary: Default::default(), - last_prev_batch: None, - members_synced: false, - name: None, - canonical_alias: None, - avatar_url: None, - topic: None, notification_counts: Default::default(), + summary: Default::default(), + members_synced: false, + last_prev_batch: None, + base_info: BaseRoomInfo::new(), })), } } @@ -128,10 +124,10 @@ impl Room { pub async fn calculate_name(&self) -> String { let inner = self.inner.lock().unwrap(); - if let Some(name) = &inner.name { + if let Some(name) = &inner.base_info.name { let name = name.trim(); name.to_string() - } else if let Some(alias) = &inner.canonical_alias { + } else if let Some(alias) = &inner.base_info.canonical_alias { let alias = alias.alias().trim(); alias.to_string() } else { @@ -210,7 +206,7 @@ impl Room { &self.own_user_id } - pub(crate) fn clone_summary(&self) -> RoomInfo { + pub(crate) fn clone_info(&self) -> RoomInfo { (*self.inner.lock().unwrap()).clone() } @@ -219,7 +215,7 @@ impl Room { } pub fn is_encrypted(&self) -> bool { - self.inner.lock().unwrap().encryption.is_some() + self.inner.lock().unwrap().is_encrypted() } pub fn update_summary(&self, summary: RoomInfo) { @@ -270,17 +266,12 @@ pub struct RoomInfo { pub room_id: Arc, pub room_type: RoomType, - pub name: Option, - pub canonical_alias: Option, - pub avatar_url: Option, - pub topic: Option, - pub notification_counts: UnreadNotificationsCount, pub summary: RoomSummary, pub members_synced: bool, - - pub encryption: Option, pub last_prev_batch: Option, + + pub base_info: BaseRoomInfo, } impl RoomInfo { @@ -313,37 +304,19 @@ impl RoomInfo { } } - pub fn handle_state_event(&mut self, event: &AnySyncStateEvent) -> bool { - match event { - AnySyncStateEvent::RoomEncryption(encryption) => { - self.encryption = Some(encryption.content.clone()); - true - } - AnySyncStateEvent::RoomName(n) => { - self.name = n.content.name().map(|n| n.to_string()); - true - } - AnySyncStateEvent::RoomCanonicalAlias(a) => { - self.canonical_alias = a.content.alias.clone(); - true - } - AnySyncStateEvent::RoomTopic(t) => { - self.topic = Some(t.content.topic.clone()); - true - } - _ => false, - } + pub fn is_encrypted(&self) -> bool { + self.base_info.encryption.is_some() } - pub fn is_encrypted(&self) -> bool { - self.encryption.is_some() + pub fn handle_state_event(&mut self, event: &AnySyncStateEvent) -> bool { + self.base_info.handle_state_event(&event.content()) } pub fn update_notification_count(&mut self, notification_counts: UnreadNotificationsCount) { self.notification_counts = notification_counts; } - pub(crate) fn update(&mut self, summary: &RumaSummary) -> bool { + pub(crate) fn update_summary(&mut self, summary: &RumaSummary) -> bool { let mut changed = false; if !summary.is_empty() { diff --git a/matrix_sdk_base/src/rooms/stripped.rs b/matrix_sdk_base/src/rooms/stripped.rs index f651031f..df905caf 100644 --- a/matrix_sdk_base/src/rooms/stripped.rs +++ b/matrix_sdk_base/src/rooms/stripped.rs @@ -15,13 +15,15 @@ use std::sync::{Arc, Mutex as SyncMutex}; use matrix_sdk_common::{ - events::{room::encryption::EncryptionEventContent, AnyStrippedStateEvent}, - identifiers::{RoomAliasId, RoomId, UserId}, + events::AnyStrippedStateEvent, + identifiers::{RoomId, UserId}, }; use serde::{Deserialize, Serialize}; use crate::store::Store; +use super::BaseRoomInfo; + #[derive(Debug, Clone)] pub struct StrippedRoom { room_id: Arc, @@ -40,11 +42,7 @@ impl StrippedRoom { store, inner: Arc::new(SyncMutex::new(StrippedRoomInfo { room_id, - encryption: None, - name: None, - canonical_alias: None, - avatar_url: None, - topic: None, + base_info: BaseRoomInfo::new(), })), } } @@ -59,10 +57,10 @@ impl StrippedRoom { pub async fn calculate_name(&self) -> String { let inner = self.inner.lock().unwrap(); - if let Some(name) = &inner.name { + if let Some(name) = &inner.base_info.name { let name = name.trim(); name.to_string() - } else if let Some(alias) = &inner.canonical_alias { + } else if let Some(alias) = &inner.base_info.canonical_alias { let alias = alias.alias().trim(); alias.to_string() } else { @@ -142,12 +140,12 @@ impl StrippedRoom { &self.own_user_id } - pub(crate) fn clone_summary(&self) -> StrippedRoomInfo { + pub(crate) fn clone_info(&self) -> StrippedRoomInfo { (*self.inner.lock().unwrap()).clone() } pub fn is_encrypted(&self) -> bool { - self.inner.lock().unwrap().encryption.is_some() + self.inner.lock().unwrap().base_info.encryption.is_some() } pub fn room_id(&self) -> &RoomId { @@ -162,35 +160,11 @@ impl StrippedRoom { #[derive(Clone, Debug, Serialize, Deserialize)] pub struct StrippedRoomInfo { pub room_id: Arc, - - pub name: Option, - pub canonical_alias: Option, - pub avatar_url: Option, - pub topic: Option, - - pub encryption: Option, + pub base_info: BaseRoomInfo, } impl StrippedRoomInfo { pub(crate) fn handle_state_event(&mut self, event: &AnyStrippedStateEvent) -> bool { - match event { - AnyStrippedStateEvent::RoomEncryption(encryption) => { - self.encryption = Some(encryption.content.clone()); - true - } - AnyStrippedStateEvent::RoomName(n) => { - self.name = n.content.name().map(|n| n.to_string()); - true - } - AnyStrippedStateEvent::RoomCanonicalAlias(a) => { - self.canonical_alias = a.content.alias.clone(); - true - } - AnyStrippedStateEvent::RoomTopic(t) => { - self.topic = Some(t.content.topic.clone()); - true - } - _ => false, - } + self.base_info.handle_state_event(&event.content()) } }