From 38048a20436054eeab93d9d68cb6dd0af1a55a08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Damir=20Jeli=C4=87?= Date: Mon, 30 Nov 2020 14:42:08 +0100 Subject: [PATCH] base: Add presence storing. --- matrix_sdk_base/src/client.rs | 22 ++++-- matrix_sdk_base/src/responses.rs | 28 ++++++-- matrix_sdk_base/src/store.rs | 112 ++++++++++++++++++------------- 3 files changed, 101 insertions(+), 61 deletions(-) diff --git a/matrix_sdk_base/src/client.rs b/matrix_sdk_base/src/client.rs index 1f0b1406..fc7807a0 100644 --- a/matrix_sdk_base/src/client.rs +++ b/matrix_sdk_base/src/client.rs @@ -579,18 +579,28 @@ impl BaseClient { changes.add_room(summary); } + for event in &response.presence.events { + if let Ok(e) = event.deserialize() { + changes.add_presence_event(e); + } + } + self.store.save_changes(&changes).await; *self.sync_token.write().await = Some(response.next_batch.clone()); - self.apply_changes(changes).await; + self.apply_changes(&changes).await; - Ok(SyncResponse::new(response.next_batch.clone(), rooms)) + Ok(SyncResponse::new( + response.next_batch.clone(), + rooms, + changes, + )) } - async fn apply_changes(&self, changes: StateChanges) { + async fn apply_changes(&self, changes: &StateChanges) { // TODO emit room changes here - for (room_id, summary) in changes.room_summaries { + for (room_id, summary) in &changes.room_summaries { if let Some(room) = self.get_joined_room(&room_id) { - room.update_summary(summary) + room.update_summary(summary.clone()) } } } @@ -638,7 +648,7 @@ impl BaseClient { changes.add_room(summary); self.store.save_changes(&changes).await; - self.apply_changes(changes).await; + self.apply_changes(&changes).await; } Ok(()) diff --git a/matrix_sdk_base/src/responses.rs b/matrix_sdk_base/src/responses.rs index 73558e64..58fd6607 100644 --- a/matrix_sdk_base/src/responses.rs +++ b/matrix_sdk_base/src/responses.rs @@ -2,20 +2,20 @@ use serde::{Deserialize, Serialize}; use std::collections::BTreeMap; use matrix_sdk_common::{ - events::{AnySyncRoomEvent, AnySyncStateEvent}, + events::{presence::PresenceEvent, AnySyncRoomEvent, AnySyncStateEvent}, identifiers::RoomId, }; +use crate::store::StateChanges; + #[derive(Clone, Debug, Default, Deserialize, Serialize)] pub struct SyncResponse { /// The batch token to supply in the `since` param of the next `/sync` request. pub next_batch: String, /// Updates to rooms. pub rooms: Rooms, - ///// Updates to the presence status of other users. - //#[serde(default, skip_serializing_if = "Presence::is_empty")] - //pub presence: Presence, - + /// Updates to the presence status of other users. + pub presence: Presence, ///// The global private data created by this user. //#[serde(default, skip_serializing_if = "AccountData::is_empty")] //pub account_data: AccountData, @@ -37,8 +37,15 @@ pub struct SyncResponse { } impl SyncResponse { - pub fn new(next_batch: String, rooms: Rooms) -> Self { - Self { next_batch, rooms } + pub fn new(next_batch: String, rooms: Rooms, changes: StateChanges) -> Self { + Self { + next_batch, + rooms, + presence: Presence { + events: changes.presence.into_iter().map(|(_, v)| v).collect(), + }, + ..Default::default() + } } pub fn new_empty(next_batch: String) -> Self { @@ -49,6 +56,13 @@ impl SyncResponse { } } +/// Updates to the presence status of other users. +#[derive(Clone, Debug, Default, Deserialize, Serialize)] +pub struct Presence { + /// A list of events. + pub events: Vec, +} + #[derive(Clone, Debug, Default, Deserialize, Serialize)] pub struct Rooms { // /// The rooms that the user has left or been banned from. diff --git a/matrix_sdk_base/src/store.rs b/matrix_sdk_base/src/store.rs index b575f000..aeca57df 100644 --- a/matrix_sdk_base/src/store.rs +++ b/matrix_sdk_base/src/store.rs @@ -12,6 +12,7 @@ use futures::{ use matrix_sdk_common::{ api::r0::sync::sync_events::RoomSummary as RumaSummary, events::{ + presence::PresenceEvent, room::{encryption::EncryptionEventContent, member::MemberEventContent}, AnySyncStateEvent, EventContent, SyncStateEvent, }, @@ -32,20 +33,22 @@ pub struct Store { invited_user_ids: Tree, room_state: Tree, room_summaries: Tree, + presence: Tree, } use crate::{client::hoist_and_deserialize_state_event, Session}; #[derive(Debug, Default)] pub struct StateChanges { - session: Option, - members: BTreeMap>>, - state: BTreeMap>, + pub session: Option, + pub members: BTreeMap>>, + pub state: BTreeMap>, pub room_summaries: BTreeMap, // display_names: BTreeMap>>, pub joined_user_ids: BTreeMap>, pub invited_user_ids: BTreeMap>, - removed_user_ids: BTreeMap, + pub removed_user_ids: BTreeMap, + pub presence: BTreeMap, } impl StateChanges { @@ -65,6 +68,10 @@ impl StateChanges { .insert(user_id, event); } + pub fn add_presence_event(&mut self, event: PresenceEvent) { + self.presence.insert(event.sender.clone(), event); + } + pub fn add_invited_member( &mut self, room_id: &RoomId, @@ -455,6 +462,7 @@ impl Store { let room_state = db.open_tree("room_state").unwrap(); let room_summaries = db.open_tree("room_summaries").unwrap(); + let presence = db.open_tree("presence").unwrap(); Self { inner: db, @@ -462,6 +470,7 @@ impl Store { members, joined_user_ids, invited_user_ids, + presence, room_state, room_summaries, } @@ -501,60 +510,67 @@ impl Store { &self.invited_user_ids, &self.room_state, &self.room_summaries, + &self.presence, ) - .transaction(|(session, members, joined, invited, state, summaries)| { - if let Some(s) = &changes.session { - session.insert("session", serde_json::to_vec(s).unwrap())?; - } - - for (room, events) in &changes.members { - for (user_id, event) in events { - members.insert( - format!("{}{}", room.as_str(), user_id.as_str()).as_str(), - serde_json::to_vec(&event).unwrap(), - )?; + .transaction( + |(session, members, joined, invited, state, summaries, presence)| { + if let Some(s) = &changes.session { + session.insert("session", serde_json::to_vec(s).unwrap())?; } - } - for (room, users) in &changes.joined_user_ids { - for user in users { - let key = format!("{}{}", room.as_str(), user.as_str()); - info!("SAVING joined {}", &key); - joined.insert(key.as_bytes(), user.as_bytes())?; - invited.remove(key.as_bytes())?; + for (room, events) in &changes.members { + for (user_id, event) in events { + members.insert( + format!("{}{}", room.as_str(), user_id.as_str()).as_str(), + serde_json::to_vec(&event).unwrap(), + )?; + } } - } - for (room, users) in &changes.invited_user_ids { - for user in users { - let key = format!("{}{}", room.as_str(), user.as_str()); - info!("SAVING invited {}", &key); - invited.insert(key.as_bytes(), user.as_bytes())?; - joined.remove(key.as_bytes())?; + for (room, users) in &changes.joined_user_ids { + for user in users { + let key = format!("{}{}", room.as_str(), user.as_str()); + info!("SAVING joined {}", &key); + joined.insert(key.as_bytes(), user.as_bytes())?; + invited.remove(key.as_bytes())?; + } } - } - for (room, events) in &changes.state { - for (state_key, event) in events { - state.insert( - format!( - "{}{}{}", - room.as_str(), - event.content().event_type(), - state_key - ) - .as_bytes(), - serde_json::to_vec(&event).unwrap(), - )?; + for (room, users) in &changes.invited_user_ids { + for user in users { + let key = format!("{}{}", room.as_str(), user.as_str()); + info!("SAVING invited {}", &key); + invited.insert(key.as_bytes(), user.as_bytes())?; + joined.remove(key.as_bytes())?; + } } - } - for (room_id, summary) in &changes.room_summaries { - summaries.insert(room_id.as_str().as_bytes(), summary.serialize())?; - } + for (room, events) in &changes.state { + for (state_key, event) in events { + state.insert( + format!( + "{}{}{}", + room.as_str(), + event.content().event_type(), + state_key + ) + .as_bytes(), + serde_json::to_vec(&event).unwrap(), + )?; + } + } - Ok(()) - }); + for (room_id, summary) in &changes.room_summaries { + summaries.insert(room_id.as_bytes(), summary.serialize())?; + } + + for (sender, event) in &changes.presence { + presence.insert(sender.as_bytes(), serde_json::to_vec(&event).unwrap())?; + } + + Ok(()) + }, + ); ret.unwrap();