base: WIP lazy loading support.
parent
3da1d3cf8f
commit
9edf8657d0
|
@ -69,7 +69,7 @@ use matrix_sdk_common::{
|
||||||
directory::{get_public_rooms, get_public_rooms_filtered},
|
directory::{get_public_rooms, get_public_rooms_filtered},
|
||||||
media::create_content,
|
media::create_content,
|
||||||
membership::{
|
membership::{
|
||||||
ban_user, forget_room,
|
ban_user, forget_room, get_member_events,
|
||||||
invite_user::{self, InvitationRecipient},
|
invite_user::{self, InvitationRecipient},
|
||||||
join_room_by_id, join_room_by_id_or_alias, kick_user, leave_room, Invite3pid,
|
join_room_by_id, join_room_by_id_or_alias, kick_user, leave_room, Invite3pid,
|
||||||
},
|
},
|
||||||
|
@ -1088,6 +1088,11 @@ impl Client {
|
||||||
|
|
||||||
#[cfg(feature = "encryption")]
|
#[cfg(feature = "encryption")]
|
||||||
let content = if self.is_room_encrypted(room_id).await {
|
let content = if self.is_room_encrypted(room_id).await {
|
||||||
|
if !self.are_members_synced(room_id).await {
|
||||||
|
self.room_members(room_id).await?;
|
||||||
|
// TODO query keys here?
|
||||||
|
}
|
||||||
|
|
||||||
self.preshare_group_session(room_id).await?;
|
self.preshare_group_session(room_id).await?;
|
||||||
AnyMessageEventContent::RoomEncrypted(self.base_client.encrypt(room_id, content).await?)
|
AnyMessageEventContent::RoomEncrypted(self.base_client.encrypt(room_id, content).await?)
|
||||||
} else {
|
} else {
|
||||||
|
@ -1112,6 +1117,13 @@ impl Client {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn are_members_synced(&self, room_id: &RoomId) -> bool {
|
||||||
|
match self.base_client.get_joined_room(room_id) {
|
||||||
|
Some(r) => r.is_encrypted(),
|
||||||
|
None => true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Send an attachment to a room.
|
/// Send an attachment to a room.
|
||||||
///
|
///
|
||||||
/// This will upload the given data that the reader produces using the
|
/// This will upload the given data that the reader produces using the
|
||||||
|
@ -1434,6 +1446,16 @@ impl Client {
|
||||||
self.send(request).await
|
self.send(request).await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
async fn room_members(&self, room_id: &RoomId) -> Result<()> {
|
||||||
|
let request = get_member_events::Request::new(room_id);
|
||||||
|
let response = self.send(request).await?;
|
||||||
|
|
||||||
|
self.base_client.receive_members(room_id, &response).await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
/// Synchronize the client's state with the latest state on the server.
|
/// Synchronize the client's state with the latest state on the server.
|
||||||
///
|
///
|
||||||
/// **Note**: You should not use this method to repeatedly sync if encryption
|
/// **Note**: You should not use this method to repeatedly sync if encryption
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
|
convert::TryFrom,
|
||||||
fmt,
|
fmt,
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
result::Result as StdResult,
|
result::Result as StdResult,
|
||||||
|
@ -29,7 +30,7 @@ use matrix_sdk_common::{
|
||||||
api::r0 as api,
|
api::r0 as api,
|
||||||
events::{
|
events::{
|
||||||
room::member::MemberEventContent, AnyStrippedStateEvent, AnySyncRoomEvent,
|
room::member::MemberEventContent, AnyStrippedStateEvent, AnySyncRoomEvent,
|
||||||
AnySyncStateEvent, SyncStateEvent,
|
AnySyncStateEvent, StateEvent, SyncStateEvent,
|
||||||
},
|
},
|
||||||
identifiers::{RoomId, UserId},
|
identifiers::{RoomId, UserId},
|
||||||
locks::RwLock,
|
locks::RwLock,
|
||||||
|
@ -103,6 +104,22 @@ pub fn hoist_and_deserialize_state_event(
|
||||||
Ok(ev)
|
Ok(ev)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn hoist_member_event(
|
||||||
|
event: &Raw<StateEvent<MemberEventContent>>,
|
||||||
|
) -> StdResult<StateEvent<MemberEventContent>, serde_json::Error> {
|
||||||
|
let prev_content = serde_json::from_str::<AdditionalEventData>(event.json().get())?
|
||||||
|
.unsigned
|
||||||
|
.prev_content;
|
||||||
|
|
||||||
|
let mut e = event.deserialize()?;
|
||||||
|
|
||||||
|
if e.prev_content.is_none() {
|
||||||
|
e.prev_content = prev_content.map(|e| e.deserialize().ok()).flatten();
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(e)
|
||||||
|
}
|
||||||
|
|
||||||
fn hoist_room_event_prev_content(
|
fn hoist_room_event_prev_content(
|
||||||
event: &Raw<AnySyncRoomEvent>,
|
event: &Raw<AnySyncRoomEvent>,
|
||||||
) -> StdResult<AnySyncRoomEvent, serde_json::Error> {
|
) -> StdResult<AnySyncRoomEvent, serde_json::Error> {
|
||||||
|
@ -132,6 +149,27 @@ fn stripped_deserialize_prev_content(
|
||||||
.ok()
|
.ok()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn handle_membership(
|
||||||
|
changes: &mut StateChanges,
|
||||||
|
room_id: &RoomId,
|
||||||
|
event: SyncStateEvent<MemberEventContent>,
|
||||||
|
) {
|
||||||
|
use matrix_sdk_common::events::room::member::MembershipState::*;
|
||||||
|
match &event.content.membership {
|
||||||
|
Join => {
|
||||||
|
info!("ADDING MEMBER {} to {}", event.state_key, room_id);
|
||||||
|
changes.add_joined_member(room_id, event)
|
||||||
|
// TODO check if the display name is
|
||||||
|
// ambigous
|
||||||
|
}
|
||||||
|
Invite => {
|
||||||
|
info!("ADDING INVITED MEMBER {} to {}", event.state_key, room_id);
|
||||||
|
changes.add_invited_member(room_id, event)
|
||||||
|
}
|
||||||
|
_ => info!("UNHANDLED MEMBERSHIP"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Signals to the `BaseClient` which `RoomState` to send to `EventEmitter`.
|
/// Signals to the `BaseClient` which `RoomState` to send to `EventEmitter`.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum RoomStateType {
|
pub enum RoomStateType {
|
||||||
|
@ -449,29 +487,6 @@ impl BaseClient {
|
||||||
// apply and emit the new events and rooms.
|
// apply and emit the new events and rooms.
|
||||||
let mut changes = StateChanges::default();
|
let mut changes = StateChanges::default();
|
||||||
|
|
||||||
let handle_membership =
|
|
||||||
|changes: &mut StateChanges, room_id, event: SyncStateEvent<MemberEventContent>| {
|
|
||||||
// let member_id = UserId::try_from(member.state_key.clone()).unwrap();
|
|
||||||
// self.store.get_member_event(room_id, &member_id).await;
|
|
||||||
|
|
||||||
// TODO this isn't right, check the diff against
|
|
||||||
// your previous state.
|
|
||||||
use matrix_sdk_common::events::room::member::MembershipState::*;
|
|
||||||
match &event.content.membership {
|
|
||||||
Join => {
|
|
||||||
info!("ADDING MEMBER {} to {}", event.state_key, room_id);
|
|
||||||
changes.add_joined_member(room_id, event)
|
|
||||||
// TODO check if the display name is
|
|
||||||
// ambigous
|
|
||||||
}
|
|
||||||
Invite => {
|
|
||||||
info!("ADDING INVITED MEMBER {} to {}", event.state_key, room_id);
|
|
||||||
changes.add_invited_member(room_id, event)
|
|
||||||
}
|
|
||||||
_ => info!("UNHANDLED MEMBERSHIP"),
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
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;
|
||||||
|
|
||||||
|
@ -543,6 +558,36 @@ impl BaseClient {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn receive_members(
|
||||||
|
&self,
|
||||||
|
room_id: &RoomId,
|
||||||
|
response: &api::membership::get_member_events::Response,
|
||||||
|
) -> Result<()> {
|
||||||
|
if self.get_joined_room(room_id).is_some() {
|
||||||
|
let mut changes = StateChanges::default();
|
||||||
|
|
||||||
|
// TODO make sure we don't overwrite memership events from a sync.
|
||||||
|
for e in &response.chunk {
|
||||||
|
if let Ok(event) = hoist_member_event(e) {
|
||||||
|
if let Ok(user_id) = UserId::try_from(event.state_key.as_str()) {
|
||||||
|
if self
|
||||||
|
.store
|
||||||
|
.get_member_event(room_id, &user_id)
|
||||||
|
.await
|
||||||
|
.is_none()
|
||||||
|
{
|
||||||
|
handle_membership(&mut changes, room_id, event.into());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.store.save_changes(&changes).await;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
/// Should the client share a group session for the given room.
|
/// Should the client share a group session for the given room.
|
||||||
///
|
///
|
||||||
/// Returns true if a session needs to be shared before room messages can be
|
/// Returns true if a session needs to be shared before room messages can be
|
||||||
|
|
|
@ -158,6 +158,10 @@ impl Room {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn are_members_synced(&self) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn get_j_members(&self) -> impl Stream<Item = RoomMember> + '_ {
|
pub async fn get_j_members(&self) -> impl Stream<Item = RoomMember> + '_ {
|
||||||
let joined = self.store.get_joined_user_ids(self.room_id()).await;
|
let joined = self.store.get_joined_user_ids(self.room_id()).await;
|
||||||
let invited = self.store.get_invited_user_ids(self.room_id()).await;
|
let invited = self.store.get_invited_user_ids(self.room_id()).await;
|
||||||
|
|
Loading…
Reference in New Issue