diff --git a/matrix_sdk_base/src/client.rs b/matrix_sdk_base/src/client.rs index 4b2e6173..33b37a70 100644 --- a/matrix_sdk_base/src/client.rs +++ b/matrix_sdk_base/src/client.rs @@ -54,7 +54,7 @@ use zeroize::Zeroizing; use crate::{ error::Result, - responses::{JoinedRoom, Rooms, State, SyncResponse, Timeline}, + responses::{JoinedRoom, LeftRoom, Presence, Rooms, State, SyncResponse, Timeline}, session::Session, store::{InnerSummary, Room, RoomType, StateChanges, Store}, }; @@ -539,7 +539,7 @@ impl BaseClient { // that case we already received this response and there's nothing to // do. if self.sync_token.read().await.as_ref() == Some(&response.next_batch) { - return Ok(SyncResponse::new_empty(response.next_batch.clone())); + return Ok(SyncResponse::new(response.next_batch)); } #[cfg(feature = "encryption")] @@ -558,10 +558,11 @@ impl BaseClient { let mut changes = StateChanges::default(); let mut rooms = Rooms::default(); - for (room_id, room_info) in &response.rooms.join { - let room = self.get_or_create_room(room_id, RoomType::Joined).await; - + for (room_id, room_info) in response.rooms.join { + let room = self.get_or_create_room(&room_id, RoomType::Joined).await; let mut summary = room.clone_summary(); + + summary.mark_as_joined(); summary.update(&room_info.summary); summary.set_prev_batch(room_info.timeline.prev_batch.as_deref()); @@ -583,27 +584,46 @@ impl BaseClient { // TODO if the room isn't encrypted but the new summary is, // add all the room users. if let Some(o) = self.olm_machine().await { - if let Some(users) = changes.joined_user_ids.get(room_id) { + if let Some(users) = changes.joined_user_ids.get(&room_id) { o.update_tracked_users(users).await } - if let Some(users) = changes.invited_user_ids.get(room_id) { + if let Some(users) = changes.invited_user_ids.get(&room_id) { o.update_tracked_users(users).await } } } - rooms - .join - .insert(room_id.to_owned(), JoinedRoom::new(timeline, state)); - if room_info.timeline.limited { summary.mark_members_missing(); } + rooms.join.insert(room_id, JoinedRoom::new(timeline, state)); + changes.add_room(summary); } + for (room_id, room_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 state = self + .handle_state( + &room_id, + &room_info.state.events, + &mut summary, + &mut changes, + ) + .await; + + let timeline = self + .handle_timeline(&room_id, &room_info.timeline, &mut summary, &mut changes) + .await; + + rooms.leave.insert(room_id, LeftRoom::new(timeline, state)); + } + for event in &response.presence.events { if let Ok(e) = event.deserialize() { changes.add_presence_event(e); @@ -614,7 +634,21 @@ impl BaseClient { *self.sync_token.write().await = Some(response.next_batch.clone()); self.apply_changes(&changes).await; - Ok(SyncResponse::new(response, rooms, changes)) + Ok(SyncResponse { + next_batch: response.next_batch, + rooms, + presence: Presence { + events: changes.presence.into_iter().map(|(_, v)| v).collect(), + }, + device_lists: response.device_lists, + device_one_time_keys_count: response + .device_one_time_keys_count + .into_iter() + .map(|(k, v)| (k, v.into())) + .collect(), + + ..Default::default() + }) } async fn apply_changes(&self, changes: &StateChanges) { diff --git a/matrix_sdk_base/src/responses.rs b/matrix_sdk_base/src/responses.rs index 96777c46..dfb0b87b 100644 --- a/matrix_sdk_base/src/responses.rs +++ b/matrix_sdk_base/src/responses.rs @@ -2,13 +2,11 @@ use serde::{Deserialize, Serialize}; use std::collections::BTreeMap; use matrix_sdk_common::{ - api::r0::sync::sync_events::{self, DeviceLists}, + api::r0::sync::sync_events::DeviceLists, events::{presence::PresenceEvent, AnySyncRoomEvent, AnySyncStateEvent, AnyToDeviceEvent}, identifiers::{DeviceKeyAlgorithm, 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. @@ -31,24 +29,7 @@ pub struct SyncResponse { } impl SyncResponse { - pub fn new(response: sync_events::Response, rooms: Rooms, changes: StateChanges) -> Self { - Self { - next_batch: response.next_batch, - rooms, - presence: Presence { - events: changes.presence.into_iter().map(|(_, v)| v).collect(), - }, - device_lists: response.device_lists, - device_one_time_keys_count: response - .device_one_time_keys_count - .into_iter() - .map(|(k, v)| (k, v.into())) - .collect(), - ..Default::default() - } - } - - pub fn new_empty(next_batch: String) -> Self { + pub fn new(next_batch: String) -> Self { Self { next_batch, ..Default::default() @@ -72,8 +53,8 @@ pub struct ToDevice { #[derive(Clone, Debug, Default, Deserialize, Serialize)] pub struct Rooms { - // /// The rooms that the user has left or been banned from. - // pub leave: BTreeMap, + /// The rooms that the user has left or been banned from. + pub leave: BTreeMap, /// The rooms that the user has joined. pub join: BTreeMap, // /// The rooms that the user has been invited to. @@ -104,6 +85,23 @@ impl JoinedRoom { } } +#[derive(Clone, Debug, Deserialize, Serialize)] +pub struct LeftRoom { + /// The timeline of messages and state changes in the room up to the point + /// when the user left. + pub timeline: Timeline, + /// Updates to the state, between the time indicated by the `since` parameter, and the start + /// of the `timeline` (or all state up to the start of the `timeline`, if `since` is not + /// given, or `full_state` is true). + pub state: State, +} + +impl LeftRoom { + pub fn new(timeline: Timeline, state: State) -> Self { + Self { timeline, state } + } +} + /// Events in the room. #[derive(Clone, Debug, Default, Deserialize, Serialize)] pub struct Timeline { diff --git a/matrix_sdk_base/src/store.rs b/matrix_sdk_base/src/store.rs index 3369453c..c6b7341e 100644 --- a/matrix_sdk_base/src/store.rs +++ b/matrix_sdk_base/src/store.rs @@ -379,6 +379,14 @@ impl InnerSummary { } } + pub fn mark_as_joined(&mut self) { + self.room_type = RoomType::Joined; + } + + pub fn mark_as_left(&mut self) { + self.room_type = RoomType::Left; + } + pub fn mark_members_synced(&mut self) { self.members_synced = true; }