base: Add initial left rooms handling.

master
Damir Jelić 2020-12-01 10:23:28 +01:00
parent 0e563a9a81
commit 27b5bf3ddd
3 changed files with 75 additions and 35 deletions

View File

@ -54,7 +54,7 @@ use zeroize::Zeroizing;
use crate::{ use crate::{
error::Result, error::Result,
responses::{JoinedRoom, Rooms, State, SyncResponse, Timeline}, responses::{JoinedRoom, LeftRoom, Presence, Rooms, State, SyncResponse, Timeline},
session::Session, session::Session,
store::{InnerSummary, Room, RoomType, StateChanges, Store}, store::{InnerSummary, Room, RoomType, StateChanges, Store},
}; };
@ -539,7 +539,7 @@ impl BaseClient {
// that case we already received this response and there's nothing to // that case we already received this response and there's nothing to
// do. // do.
if self.sync_token.read().await.as_ref() == Some(&response.next_batch) { 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")] #[cfg(feature = "encryption")]
@ -558,10 +558,11 @@ 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, room_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 summary = room.clone_summary();
summary.mark_as_joined();
summary.update(&room_info.summary); summary.update(&room_info.summary);
summary.set_prev_batch(room_info.timeline.prev_batch.as_deref()); 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, // TODO if the room isn't encrypted but the new summary is,
// add all the room users. // add all the room users.
if let Some(o) = self.olm_machine().await { 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 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 o.update_tracked_users(users).await
} }
} }
} }
rooms
.join
.insert(room_id.to_owned(), JoinedRoom::new(timeline, state));
if room_info.timeline.limited { if room_info.timeline.limited {
summary.mark_members_missing(); summary.mark_members_missing();
} }
rooms.join.insert(room_id, JoinedRoom::new(timeline, state));
changes.add_room(summary); 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 { for event in &response.presence.events {
if let Ok(e) = event.deserialize() { if let Ok(e) = event.deserialize() {
changes.add_presence_event(e); changes.add_presence_event(e);
@ -614,7 +634,21 @@ impl BaseClient {
*self.sync_token.write().await = Some(response.next_batch.clone()); *self.sync_token.write().await = Some(response.next_batch.clone());
self.apply_changes(&changes).await; 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) { async fn apply_changes(&self, changes: &StateChanges) {

View File

@ -2,13 +2,11 @@ use serde::{Deserialize, Serialize};
use std::collections::BTreeMap; use std::collections::BTreeMap;
use matrix_sdk_common::{ use matrix_sdk_common::{
api::r0::sync::sync_events::{self, DeviceLists}, api::r0::sync::sync_events::DeviceLists,
events::{presence::PresenceEvent, AnySyncRoomEvent, AnySyncStateEvent, AnyToDeviceEvent}, events::{presence::PresenceEvent, AnySyncRoomEvent, AnySyncStateEvent, AnyToDeviceEvent},
identifiers::{DeviceKeyAlgorithm, RoomId}, identifiers::{DeviceKeyAlgorithm, RoomId},
}; };
use crate::store::StateChanges;
#[derive(Clone, Debug, Default, Deserialize, Serialize)] #[derive(Clone, Debug, Default, Deserialize, Serialize)]
pub struct SyncResponse { pub struct SyncResponse {
/// The batch token to supply in the `since` param of the next `/sync` request. /// The batch token to supply in the `since` param of the next `/sync` request.
@ -31,24 +29,7 @@ pub struct SyncResponse {
} }
impl SyncResponse { impl SyncResponse {
pub fn new(response: sync_events::Response, rooms: Rooms, changes: StateChanges) -> Self { pub fn new(next_batch: String) -> 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 {
Self { Self {
next_batch, next_batch,
..Default::default() ..Default::default()
@ -72,8 +53,8 @@ pub struct ToDevice {
#[derive(Clone, Debug, Default, Deserialize, Serialize)] #[derive(Clone, Debug, Default, Deserialize, Serialize)]
pub struct Rooms { pub struct Rooms {
// /// The rooms that the user has left or been banned from. /// The rooms that the user has left or been banned from.
// pub leave: BTreeMap<RoomId, LeftRoom>, pub leave: BTreeMap<RoomId, LeftRoom>,
/// The rooms that the user has joined. /// The rooms that the user has joined.
pub join: BTreeMap<RoomId, JoinedRoom>, pub join: BTreeMap<RoomId, JoinedRoom>,
// /// The rooms that the user has been invited to. // /// 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. /// Events in the room.
#[derive(Clone, Debug, Default, Deserialize, Serialize)] #[derive(Clone, Debug, Default, Deserialize, Serialize)]
pub struct Timeline { pub struct Timeline {

View File

@ -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) { pub fn mark_members_synced(&mut self) {
self.members_synced = true; self.members_synced = true;
} }