base: Add a common room info struct for normal and stripped rooms.

master
Damir Jelić 2020-12-14 14:36:39 +01:00
parent 3a76cf7692
commit 45db95742a
4 changed files with 145 additions and 124 deletions

View File

@ -30,8 +30,10 @@ use futures::StreamExt;
use matrix_sdk_common::{ use matrix_sdk_common::{
api::r0 as api, api::r0 as api,
events::{ events::{
presence::PresenceEvent, room::member::{MemberEventContent, MembershipState}, AnyBasicEvent, presence::PresenceEvent,
AnyStrippedStateEvent, AnySyncRoomEvent, AnySyncStateEvent, EventContent, StateEvent, room::member::{MemberEventContent, MembershipState},
AnyBasicEvent, AnyStrippedStateEvent, AnySyncRoomEvent, AnySyncStateEvent, EventContent,
StateEvent,
}, },
identifiers::{RoomId, UserId}, identifiers::{RoomId, UserId},
locks::RwLock, locks::RwLock,
@ -40,10 +42,7 @@ use matrix_sdk_common::{
#[cfg(feature = "encryption")] #[cfg(feature = "encryption")]
use matrix_sdk_common::{ use matrix_sdk_common::{
api::r0::keys::claim_keys::Request as KeysClaimRequest, api::r0::keys::claim_keys::Request as KeysClaimRequest,
events::{ events::{room::encrypted::EncryptedEventContent, AnyMessageEventContent, AnySyncMessageEvent},
room::encrypted::EncryptedEventContent,
AnyMessageEventContent, AnySyncMessageEvent,
},
identifiers::DeviceId, identifiers::DeviceId,
locks::Mutex, locks::Mutex,
uuid::Uuid, uuid::Uuid,
@ -456,7 +455,7 @@ impl BaseClient {
&self, &self,
room_id: &RoomId, room_id: &RoomId,
ruma_timeline: api::sync::sync_events::Timeline, ruma_timeline: api::sync::sync_events::Timeline,
summary: &mut RoomInfo, room_info: &mut RoomInfo,
changes: &mut StateChanges, changes: &mut StateChanges,
user_ids: &mut BTreeSet<UserId>, user_ids: &mut BTreeSet<UserId>,
) -> Timeline { ) -> 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()); changes.add_state_event(room_id, s.clone());
} }
}, },
@ -668,40 +667,39 @@ impl BaseClient {
let mut changes = StateChanges::default(); let mut changes = StateChanges::default();
let mut rooms = Rooms::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 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(); room_info.update_summary(&new_info.summary);
summary.update(&room_info.summary); room_info.set_prev_batch(new_info.timeline.prev_batch.as_deref());
summary.set_prev_batch(room_info.timeline.prev_batch.as_deref());
let (state, members, state_events, mut user_ids) = 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.members.insert(room_id.clone(), members);
changes.state.insert(room_id.clone(), state_events); changes.state.insert(room_id.clone(), state_events);
if room_info.timeline.limited { if new_info.timeline.limited {
summary.mark_members_missing(); room_info.mark_members_missing();
} }
let timeline = self let timeline = self
.handle_timeline( .handle_timeline(
&room_id, &room_id,
room_info.timeline, new_info.timeline,
&mut summary, &mut room_info,
&mut changes, &mut changes,
&mut user_ids, &mut user_ids,
) )
.await; .await;
let account_data = self 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; .await;
#[cfg(feature = "encryption")] #[cfg(feature = "encryption")]
if summary.is_encrypted() { if room_info.is_encrypted() {
if let Some(o) = self.olm_machine().await { if let Some(o) = self.olm_machine().await {
if !room.is_encrypted() { if !room.is_encrypted() {
// The room turned on encryption in this sync, we need // The room turned on encryption in this sync, we need
@ -719,12 +717,12 @@ impl BaseClient {
} }
} }
let notification_count = room_info.unread_notifications.into(); let notification_count = new_info.unread_notifications.into();
summary.update_notification_count(notification_count); room_info.update_notification_count(notification_count);
// TODO should we store this? // TODO should we store this?
let ephemeral = Ephemeral { let ephemeral = Ephemeral {
events: room_info events: new_info
.ephemeral .ephemeral
.events .events
.into_iter() .into_iter()
@ -737,16 +735,16 @@ impl BaseClient {
JoinedRoom::new(timeline, state, account_data, ephemeral, notification_count), 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 room = self.get_or_create_room(&room_id, RoomType::Left).await;
let mut summary = room.clone_summary(); let mut room_info = room.clone_info();
summary.mark_as_left(); room_info.mark_as_left();
let (state, members, state_events, mut user_ids) = 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.members.insert(room_id.clone(), members);
changes.state.insert(room_id.clone(), state_events); changes.state.insert(room_id.clone(), state_events);
@ -754,15 +752,15 @@ impl BaseClient {
let timeline = self let timeline = self
.handle_timeline( .handle_timeline(
&room_id, &room_id,
room_info.timeline, new_info.timeline,
&mut summary, &mut room_info,
&mut changes, &mut changes,
&mut user_ids, &mut user_ids,
) )
.await; .await;
let account_data = self 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; .await;
rooms rooms
@ -770,19 +768,19 @@ impl BaseClient {
.insert(room_id, LeftRoom::new(timeline, state, account_data)); .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 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(); room_info.mark_as_invited();
changes.add_room(room_info); changes.add_room(room_info);
} }
let room = self.get_or_create_stripped_room(&room_id).await; 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) = 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_members.insert(room_id.clone(), members);
changes.stripped_state.insert(room_id.clone(), state_events); changes.stripped_state.insert(room_id.clone(), state_events);
@ -846,9 +844,9 @@ impl BaseClient {
async fn apply_changes(&self, changes: &StateChanges) { async fn apply_changes(&self, changes: &StateChanges) {
// TODO emit room changes here // 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) { 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, response: &api::membership::get_member_events::Response,
) -> Result<()> { ) -> Result<()> {
if let Some(room) = self.get_room(room_id) { if let Some(room) = self.get_room(room_id) {
let mut summary = room.clone_summary(); let mut room_info = room.clone_info();
summary.mark_members_synced(); room_info.mark_members_synced();
let mut members = BTreeMap::new(); let mut members = BTreeMap::new();
@ -877,7 +875,7 @@ impl BaseClient {
.store .store
.get_member_event(&room_id, &member.state_key) .get_member_event(&room_id, &member.state_key)
.await .await
.is_some() .is_none()
{ {
#[cfg(feature = "encryption")] #[cfg(feature = "encryption")]
match member.content.membership { match member.content.membership {
@ -895,13 +893,13 @@ impl BaseClient {
changes.members.insert(room_id.clone(), members); changes.members.insert(room_id.clone(), members);
#[cfg(feature = "encryption")] #[cfg(feature = "encryption")]
if summary.is_encrypted() { if room_info.is_encrypted() {
if let Some(o) = self.olm_machine().await { if let Some(o) = self.olm_machine().await {
o.update_tracked_users(&user_ids).await o.update_tracked_users(&user_ids).await
} }
} }
changes.add_room(summary); changes.add_room(room_info);
self.store.save_changes(&changes).await; self.store.save_changes(&changes).await;
self.apply_changes(&changes).await; self.apply_changes(&changes).await;

View File

@ -6,3 +6,79 @@ pub use normal::{Room, RoomInfo, RoomType};
pub use stripped::{StrippedRoom, StrippedRoomInfo}; pub use stripped::{StrippedRoom, StrippedRoomInfo};
pub use members::RoomMember; 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<String>,
pub canonical_alias: Option<RoomAliasId>,
pub avatar_url: Option<String>,
pub topic: Option<String>,
pub encryption: Option<EncryptionEventContent>,
pub tombstone: Option<TombstoneEventContent>,
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,
}
}
}

View File

@ -23,14 +23,14 @@ use futures::{
}; };
use matrix_sdk_common::{ use matrix_sdk_common::{
api::r0::sync::sync_events::RoomSummary as RumaSummary, api::r0::sync::sync_events::RoomSummary as RumaSummary,
events::{room::encryption::EncryptionEventContent, AnySyncStateEvent, EventType}, events::{AnySyncStateEvent, EventType},
identifiers::{RoomAliasId, RoomId, UserId}, identifiers::{RoomId, UserId},
}; };
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::{responses::UnreadNotificationsCount, store::Store}; use crate::{responses::UnreadNotificationsCount, store::Store};
use super::RoomMember; use super::{BaseRoomInfo, RoomMember};
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Room { pub struct Room {
@ -69,15 +69,11 @@ impl Room {
inner: Arc::new(SyncMutex::new(RoomInfo { inner: Arc::new(SyncMutex::new(RoomInfo {
room_id, room_id,
room_type, 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(), 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 { pub async fn calculate_name(&self) -> String {
let inner = self.inner.lock().unwrap(); let inner = self.inner.lock().unwrap();
if let Some(name) = &inner.name { if let Some(name) = &inner.base_info.name {
let name = name.trim(); let name = name.trim();
name.to_string() 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(); let alias = alias.alias().trim();
alias.to_string() alias.to_string()
} else { } else {
@ -210,7 +206,7 @@ impl Room {
&self.own_user_id &self.own_user_id
} }
pub(crate) fn clone_summary(&self) -> RoomInfo { pub(crate) fn clone_info(&self) -> RoomInfo {
(*self.inner.lock().unwrap()).clone() (*self.inner.lock().unwrap()).clone()
} }
@ -219,7 +215,7 @@ impl Room {
} }
pub fn is_encrypted(&self) -> bool { 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) { pub fn update_summary(&self, summary: RoomInfo) {
@ -270,17 +266,12 @@ pub struct RoomInfo {
pub room_id: Arc<RoomId>, pub room_id: Arc<RoomId>,
pub room_type: RoomType, pub room_type: RoomType,
pub name: Option<String>,
pub canonical_alias: Option<RoomAliasId>,
pub avatar_url: Option<String>,
pub topic: Option<String>,
pub notification_counts: UnreadNotificationsCount, pub notification_counts: UnreadNotificationsCount,
pub summary: RoomSummary, pub summary: RoomSummary,
pub members_synced: bool, pub members_synced: bool,
pub encryption: Option<EncryptionEventContent>,
pub last_prev_batch: Option<String>, pub last_prev_batch: Option<String>,
pub base_info: BaseRoomInfo,
} }
impl RoomInfo { impl RoomInfo {
@ -313,37 +304,19 @@ impl RoomInfo {
} }
} }
pub fn handle_state_event(&mut self, event: &AnySyncStateEvent) -> bool { pub fn is_encrypted(&self) -> bool {
match event { self.base_info.encryption.is_some()
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 { pub fn handle_state_event(&mut self, event: &AnySyncStateEvent) -> bool {
self.encryption.is_some() self.base_info.handle_state_event(&event.content())
} }
pub fn update_notification_count(&mut self, notification_counts: UnreadNotificationsCount) { pub fn update_notification_count(&mut self, notification_counts: UnreadNotificationsCount) {
self.notification_counts = notification_counts; 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; let mut changed = false;
if !summary.is_empty() { if !summary.is_empty() {

View File

@ -15,13 +15,15 @@
use std::sync::{Arc, Mutex as SyncMutex}; use std::sync::{Arc, Mutex as SyncMutex};
use matrix_sdk_common::{ use matrix_sdk_common::{
events::{room::encryption::EncryptionEventContent, AnyStrippedStateEvent}, events::AnyStrippedStateEvent,
identifiers::{RoomAliasId, RoomId, UserId}, identifiers::{RoomId, UserId},
}; };
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::store::Store; use crate::store::Store;
use super::BaseRoomInfo;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct StrippedRoom { pub struct StrippedRoom {
room_id: Arc<RoomId>, room_id: Arc<RoomId>,
@ -40,11 +42,7 @@ impl StrippedRoom {
store, store,
inner: Arc::new(SyncMutex::new(StrippedRoomInfo { inner: Arc::new(SyncMutex::new(StrippedRoomInfo {
room_id, room_id,
encryption: None, base_info: BaseRoomInfo::new(),
name: None,
canonical_alias: None,
avatar_url: None,
topic: None,
})), })),
} }
} }
@ -59,10 +57,10 @@ impl StrippedRoom {
pub async fn calculate_name(&self) -> String { pub async fn calculate_name(&self) -> String {
let inner = self.inner.lock().unwrap(); let inner = self.inner.lock().unwrap();
if let Some(name) = &inner.name { if let Some(name) = &inner.base_info.name {
let name = name.trim(); let name = name.trim();
name.to_string() 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(); let alias = alias.alias().trim();
alias.to_string() alias.to_string()
} else { } else {
@ -142,12 +140,12 @@ impl StrippedRoom {
&self.own_user_id &self.own_user_id
} }
pub(crate) fn clone_summary(&self) -> StrippedRoomInfo { pub(crate) fn clone_info(&self) -> StrippedRoomInfo {
(*self.inner.lock().unwrap()).clone() (*self.inner.lock().unwrap()).clone()
} }
pub fn is_encrypted(&self) -> bool { 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 { pub fn room_id(&self) -> &RoomId {
@ -162,35 +160,11 @@ impl StrippedRoom {
#[derive(Clone, Debug, Serialize, Deserialize)] #[derive(Clone, Debug, Serialize, Deserialize)]
pub struct StrippedRoomInfo { pub struct StrippedRoomInfo {
pub room_id: Arc<RoomId>, pub room_id: Arc<RoomId>,
pub base_info: BaseRoomInfo,
pub name: Option<String>,
pub canonical_alias: Option<RoomAliasId>,
pub avatar_url: Option<String>,
pub topic: Option<String>,
pub encryption: Option<EncryptionEventContent>,
} }
impl StrippedRoomInfo { impl StrippedRoomInfo {
pub(crate) fn handle_state_event(&mut self, event: &AnyStrippedStateEvent) -> bool { pub(crate) fn handle_state_event(&mut self, event: &AnyStrippedStateEvent) -> bool {
match event { self.base_info.handle_state_event(&event.content())
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,
}
} }
} }