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

This commit is contained in:
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::{
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<UserId>,
) -> 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;

View file

@ -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<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::{
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<RoomId>,
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 summary: RoomSummary,
pub members_synced: bool,
pub encryption: Option<EncryptionEventContent>,
pub last_prev_batch: Option<String>,
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() {

View file

@ -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<RoomId>,
@ -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<RoomId>,
pub name: Option<String>,
pub canonical_alias: Option<RoomAliasId>,
pub avatar_url: Option<String>,
pub topic: Option<String>,
pub encryption: Option<EncryptionEventContent>,
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())
}
}