base: Upcast the bare rooms based on the membership state

master
Damir Jelić 2020-12-19 16:37:35 +01:00
parent 7abf0c8805
commit f9af880176
7 changed files with 252 additions and 136 deletions

View File

@ -41,7 +41,7 @@ use tracing::{debug, warn};
use tracing::{error, info, instrument};
use matrix_sdk_base::{
responses::SyncResponse, BaseClient, BaseClientConfig, Room, Session, Store,
responses::SyncResponse, BaseClient, BaseClientConfig, JoinedRoom, Room, Session, Store,
};
#[cfg(feature = "encryption")]
@ -575,8 +575,8 @@ impl Client {
/// # Arguments
///
/// `room_id` - The unique id of the room that should be fetched.
pub fn get_joined_room(&self, room_id: &RoomId) -> Option<Room> {
self.base_client.get_room(room_id)
pub fn get_joined_room(&self, room_id: &RoomId) -> Option<JoinedRoom> {
self.base_client.get_joined_room(room_id)
}
///// Get an invited room with the given room id.
@ -1150,7 +1150,7 @@ impl Client {
let _guard = mutex.lock().await;
{
let room = self.base_client.get_room(room_id).unwrap();
let room = self.get_joined_room(room_id).unwrap();
let members = room.joined_user_ids().await;
// TODO don't collect here.
let members_iter: Vec<UserId> = members.collect().await;
@ -1252,17 +1252,17 @@ impl Client {
/// Returns true if a room with the given id was found and the room is
/// encrypted, false if the room wasn't found or isn't encrypted.
async fn is_room_encrypted(&self, room_id: &RoomId) -> bool {
match self.base_client.get_room(room_id) {
Some(r) => r.is_encrypted(),
None => false,
}
self.base_client
.get_room(room_id)
.map(|r| r.is_encrypted())
.unwrap_or(false)
}
async fn are_members_synced(&self, room_id: &RoomId) -> bool {
match self.base_client.get_room(room_id) {
Some(r) => r.are_members_synced(),
None => true,
}
self.base_client
.get_room(room_id)
.map(|r| r.are_members_synced())
.unwrap_or(true)
}
/// Send an attachment to a room.

View File

@ -66,7 +66,10 @@ compile_error!("only one of 'native-tls' or 'rustls-tls' features can be enabled
#[cfg(feature = "encryption")]
#[cfg_attr(feature = "docs", doc(cfg(encryption)))]
pub use matrix_sdk_base::crypto::LocalTrust;
pub use matrix_sdk_base::{Error as BaseError, Room, RoomInfo, RoomMember, Session};
pub use matrix_sdk_base::{
Error as BaseError, EventEmitter, InvitedRoom, JoinedRoom, LeftRoom, RoomInfo, RoomMember,
Session,
};
pub use matrix_sdk_common::*;
pub use reqwest;

View File

@ -59,12 +59,14 @@ use zeroize::Zeroizing;
use crate::{
error::Result,
responses::{
AccountData, Ephemeral, InviteState, InvitedRoom, JoinedRoom, LeftRoom, MemberEvent,
Presence, Rooms, State, StrippedMemberEvent, SyncResponse, Timeline,
AccountData, Ephemeral, InviteState, InvitedRoom as InvitedRoomResponse,
JoinedRoom as JoinedRoomResponse, LeftRoom as LeftRoomResponse, MemberEvent, Presence,
Rooms, State, StrippedMemberEvent, SyncResponse, Timeline,
},
rooms::{Room, RoomInfo, RoomType, StrippedRoom, StrippedRoomInfo},
session::Session,
store::{StateChanges, Store},
EventEmitter, InvitedRoom, JoinedRoom, LeftRoom, RoomState,
};
pub type Token = String;
@ -163,21 +165,6 @@ pub enum RoomStateType {
Invited,
}
/// An enum that represents the state of the given `Room`.
///
/// If the event came from the `join`, `invite` or `leave` rooms map from the server
/// the variant that holds the corresponding room is used. `RoomState` is generic
/// so it can be used to represent a `Room` or an `Arc<RwLock<Room>>`
#[derive(Debug)]
pub enum RoomState<R> {
/// A room from the `join` section of a sync response.
Joined(R),
/// A room from the `leave` section of a sync response.
Left(R),
/// A room from the `invite` section of a sync response.
Invited(R),
}
/// A no IO Client implementation.
///
/// This Client is a state machine that receives responses and events and
@ -199,6 +186,9 @@ pub struct BaseClient {
cryptostore: Arc<Mutex<Option<Box<dyn CryptoStore>>>>,
store_path: Arc<Option<PathBuf>>,
store_passphrase: Arc<Zeroizing<String>>,
/// Any implementor of EventEmitter will act as the callbacks for various
/// events.
event_emitter: Arc<RwLock<Option<Box<dyn EventEmitter>>>>,
}
#[cfg(not(tarpaulin_include))]
@ -303,21 +293,21 @@ impl BaseClient {
};
Ok(BaseClient {
session: Arc::new(RwLock::new(None)),
sync_token: Arc::new(RwLock::new(None)),
session: RwLock::new(None).into(),
sync_token: RwLock::new(None).into(),
store,
rooms: Arc::new(DashMap::new()),
stripped_rooms: Arc::new(DashMap::new()),
rooms: DashMap::new().into(),
stripped_rooms: DashMap::new().into(),
#[cfg(feature = "encryption")]
olm: Arc::new(Mutex::new(None)),
olm: Mutex::new(None).into(),
#[cfg(feature = "encryption")]
cryptostore: Arc::new(Mutex::new(config.crypto_store)),
store_path: Arc::new(config.store_path),
store_passphrase: Arc::new(
config
cryptostore: Mutex::new(config.crypto_store).into(),
store_path: config.store_path.into(),
store_passphrase: config
.passphrase
.unwrap_or_else(|| Zeroizing::new("DEFAULT_PASSPHRASE".to_owned())),
),
.unwrap_or_else(|| Zeroizing::new("DEFAULT_PASSPHRASE".to_owned()))
.into(),
event_emitter: RwLock::new(None).into(),
})
}
@ -425,6 +415,13 @@ impl BaseClient {
self.sync_token.read().await.clone()
}
/// Add `EventEmitter` to `Client`.
///
/// The methods of `EventEmitter` are called when the respective `RoomEvents` occur.
pub async fn add_event_emitter(&self, emitter: Box<dyn EventEmitter>) {
*self.event_emitter.write().await = Some(emitter);
}
async fn get_or_create_stripped_room(&self, room_id: &RoomId) -> StrippedRoom {
let session = self.session.read().await;
let user_id = &session
@ -738,7 +735,13 @@ impl BaseClient {
rooms.join.insert(
room_id,
JoinedRoom::new(timeline, state, account_data, ephemeral, notification_count),
JoinedRoomResponse::new(
timeline,
state,
account_data,
ephemeral,
notification_count,
),
);
changes.add_room(room_info);
@ -769,9 +772,10 @@ impl BaseClient {
.handle_room_account_data(&room_id, &new_info.account_data.events, &mut changes)
.await;
rooms
.leave
.insert(room_id, LeftRoom::new(timeline, state, account_data));
rooms.leave.insert(
room_id,
LeftRoomResponse::new(timeline, state, account_data),
);
}
for (room_id, new_info) in response.rooms.invite {
@ -791,7 +795,7 @@ impl BaseClient {
changes.stripped_members.insert(room_id.clone(), members);
changes.stripped_state.insert(room_id.clone(), state_events);
let room = InvitedRoom {
let room = InvitedRoomResponse {
invite_state: state,
};
@ -851,7 +855,7 @@ impl BaseClient {
async fn apply_changes(&self, changes: &StateChanges) {
// TODO emit room changes here
for (room_id, room_info) in &changes.room_infos {
if let Some(room) = self.get_room(&room_id) {
if let Some(room) = self.get_bare_room(&room_id) {
room.update_summary(room_info.clone())
}
}
@ -862,7 +866,7 @@ impl BaseClient {
room_id: &RoomId,
response: &api::membership::get_member_events::Response,
) -> Result<()> {
if let Some(room) = self.get_room(room_id) {
if let Some(room) = self.get_bare_room(room_id) {
let mut room_info = room.clone_info();
room_info.mark_members_synced();
@ -1027,12 +1031,28 @@ impl BaseClient {
}
}
pub fn get_room(&self, room_id: &RoomId) -> Option<Room> {
fn get_bare_room(&self, room_id: &RoomId) -> Option<Room> {
#[allow(clippy::map_clone)]
self.rooms.get(room_id).map(|r| r.clone())
}
pub fn get_stripped_room(&self, room_id: &RoomId) -> Option<StrippedRoom> {
pub fn get_joined_room(&self, room_id: &RoomId) -> Option<JoinedRoom> {
self.get_room(room_id).map(|r| r.joined()).flatten()
}
pub fn get_room(&self, room_id: &RoomId) -> Option<RoomState> {
self.get_bare_room(room_id)
.map(|r| match r.room_type() {
RoomType::Joined => Some(RoomState::Joined(JoinedRoom { inner: r })),
RoomType::Left => Some(RoomState::Left(LeftRoom { inner: r })),
RoomType::Invited => self
.get_stripped_room(room_id)
.map(|r| RoomState::Invited(InvitedRoom { inner: r })),
})
.flatten()
}
fn get_stripped_room(&self, room_id: &RoomId) -> Option<StrippedRoom> {
#[allow(clippy::map_clone)]
self.stripped_rooms.get(room_id).map(|r| r.clone())
}

View File

@ -40,13 +40,11 @@ use crate::{
typing::TypingEventContent,
BasicEvent, StrippedStateEvent, SyncEphemeralRoomEvent, SyncMessageEvent, SyncStateEvent,
},
Room, RoomState,
rooms::RoomState,
Room,
};
use matrix_sdk_common_macros::async_trait;
/// Type alias for `RoomState` enum when passed to `EventEmitter` methods.
pub type SyncRoom = RoomState<Arc<RwLock<Room>>>;
/// This represents the various "unrecognized" events.
#[derive(Clone, Copy, Debug)]
pub enum CustomEvent<'c> {
@ -76,7 +74,7 @@ pub enum CustomEvent<'c> {
/// # room::message::{MessageEventContent, TextMessageEventContent},
/// # SyncMessageEvent
/// # },
/// # EventEmitter, SyncRoom
/// # EventEmitter, RoomState
/// # };
/// # use matrix_sdk_common::locks::RwLock;
/// # use matrix_sdk_common_macros::async_trait;
@ -85,8 +83,8 @@ pub enum CustomEvent<'c> {
///
/// #[async_trait]
/// impl EventEmitter for EventCallback {
/// async fn on_room_message(&self, room: SyncRoom, event: &SyncMessageEvent<MessageEventContent>) {
/// if let SyncRoom::Joined(room) = room {
/// async fn on_room_message(&self, room: RoomState, event: &SyncMessageEvent<MessageEventContent>) {
/// if let RoomState::Joined(room) = room {
/// if let SyncMessageEvent {
/// content: MessageEventContent::Text(TextMessageEventContent { body: msg_body, .. }),
/// sender,
@ -112,135 +110,140 @@ pub enum CustomEvent<'c> {
pub trait EventEmitter: Send + Sync {
// ROOM EVENTS from `IncomingTimeline`
/// Fires when `Client` receives a `RoomEvent::RoomMember` event.
async fn on_room_member(&self, _: SyncRoom, _: &SyncStateEvent<MemberEventContent>) {}
async fn on_room_member(&self, _: RoomState, _: &SyncStateEvent<MemberEventContent>) {}
/// Fires when `Client` receives a `RoomEvent::RoomName` event.
async fn on_room_name(&self, _: SyncRoom, _: &SyncStateEvent<NameEventContent>) {}
async fn on_room_name(&self, _: RoomState, _: &SyncStateEvent<NameEventContent>) {}
/// Fires when `Client` receives a `RoomEvent::RoomCanonicalAlias` event.
async fn on_room_canonical_alias(
&self,
_: SyncRoom,
_: RoomState,
_: &SyncStateEvent<CanonicalAliasEventContent>,
) {
}
/// Fires when `Client` receives a `RoomEvent::RoomAliases` event.
async fn on_room_aliases(&self, _: SyncRoom, _: &SyncStateEvent<AliasesEventContent>) {}
async fn on_room_aliases(&self, _: RoomState, _: &SyncStateEvent<AliasesEventContent>) {}
/// Fires when `Client` receives a `RoomEvent::RoomAvatar` event.
async fn on_room_avatar(&self, _: SyncRoom, _: &SyncStateEvent<AvatarEventContent>) {}
async fn on_room_avatar(&self, _: RoomState, _: &SyncStateEvent<AvatarEventContent>) {}
/// Fires when `Client` receives a `RoomEvent::RoomMessage` event.
async fn on_room_message(&self, _: SyncRoom, _: &SyncMessageEvent<MsgEventContent>) {}
async fn on_room_message(&self, _: RoomState, _: &SyncMessageEvent<MsgEventContent>) {}
/// Fires when `Client` receives a `RoomEvent::RoomMessageFeedback` event.
async fn on_room_message_feedback(
&self,
_: SyncRoom,
_: RoomState,
_: &SyncMessageEvent<FeedbackEventContent>,
) {
}
/// Fires when `Client` receives a `RoomEvent::RoomRedaction` event.
async fn on_room_redaction(&self, _: SyncRoom, _: &SyncRedactionEvent) {}
async fn on_room_redaction(&self, _: RoomState, _: &SyncRedactionEvent) {}
/// Fires when `Client` receives a `RoomEvent::RoomPowerLevels` event.
async fn on_room_power_levels(&self, _: SyncRoom, _: &SyncStateEvent<PowerLevelsEventContent>) {
async fn on_room_power_levels(
&self,
_: RoomState,
_: &SyncStateEvent<PowerLevelsEventContent>,
) {
}
/// Fires when `Client` receives a `RoomEvent::Tombstone` event.
async fn on_room_join_rules(&self, _: SyncRoom, _: &SyncStateEvent<JoinRulesEventContent>) {}
async fn on_room_join_rules(&self, _: RoomState, _: &SyncStateEvent<JoinRulesEventContent>) {}
/// Fires when `Client` receives a `RoomEvent::Tombstone` event.
async fn on_room_tombstone(&self, _: SyncRoom, _: &SyncStateEvent<TombstoneEventContent>) {}
async fn on_room_tombstone(&self, _: RoomState, _: &SyncStateEvent<TombstoneEventContent>) {}
// `RoomEvent`s from `IncomingState`
/// Fires when `Client` receives a `StateEvent::RoomMember` event.
async fn on_state_member(&self, _: SyncRoom, _: &SyncStateEvent<MemberEventContent>) {}
async fn on_state_member(&self, _: RoomState, _: &SyncStateEvent<MemberEventContent>) {}
/// Fires when `Client` receives a `StateEvent::RoomName` event.
async fn on_state_name(&self, _: SyncRoom, _: &SyncStateEvent<NameEventContent>) {}
async fn on_state_name(&self, _: RoomState, _: &SyncStateEvent<NameEventContent>) {}
/// Fires when `Client` receives a `StateEvent::RoomCanonicalAlias` event.
async fn on_state_canonical_alias(
&self,
_: SyncRoom,
_: RoomState,
_: &SyncStateEvent<CanonicalAliasEventContent>,
) {
}
/// Fires when `Client` receives a `StateEvent::RoomAliases` event.
async fn on_state_aliases(&self, _: SyncRoom, _: &SyncStateEvent<AliasesEventContent>) {}
async fn on_state_aliases(&self, _: RoomState, _: &SyncStateEvent<AliasesEventContent>) {}
/// Fires when `Client` receives a `StateEvent::RoomAvatar` event.
async fn on_state_avatar(&self, _: SyncRoom, _: &SyncStateEvent<AvatarEventContent>) {}
async fn on_state_avatar(&self, _: RoomState, _: &SyncStateEvent<AvatarEventContent>) {}
/// Fires when `Client` receives a `StateEvent::RoomPowerLevels` event.
async fn on_state_power_levels(
&self,
_: SyncRoom,
_: RoomState,
_: &SyncStateEvent<PowerLevelsEventContent>,
) {
}
/// Fires when `Client` receives a `StateEvent::RoomJoinRules` event.
async fn on_state_join_rules(&self, _: SyncRoom, _: &SyncStateEvent<JoinRulesEventContent>) {}
async fn on_state_join_rules(&self, _: RoomState, _: &SyncStateEvent<JoinRulesEventContent>) {}
// `AnyStrippedStateEvent`s
/// Fires when `Client` receives a `AnyStrippedStateEvent::StrippedRoomMember` event.
async fn on_stripped_state_member(
&self,
_: SyncRoom,
_: RoomState,
_: &StrippedStateEvent<MemberEventContent>,
_: Option<MemberEventContent>,
) {
}
/// Fires when `Client` receives a `AnyStrippedStateEvent::StrippedRoomName` event.
async fn on_stripped_state_name(&self, _: SyncRoom, _: &StrippedStateEvent<NameEventContent>) {}
async fn on_stripped_state_name(&self, _: RoomState, _: &StrippedStateEvent<NameEventContent>) {
}
/// Fires when `Client` receives a `AnyStrippedStateEvent::StrippedRoomCanonicalAlias` event.
async fn on_stripped_state_canonical_alias(
&self,
_: SyncRoom,
_: RoomState,
_: &StrippedStateEvent<CanonicalAliasEventContent>,
) {
}
/// Fires when `Client` receives a `AnyStrippedStateEvent::StrippedRoomAliases` event.
async fn on_stripped_state_aliases(
&self,
_: SyncRoom,
_: RoomState,
_: &StrippedStateEvent<AliasesEventContent>,
) {
}
/// Fires when `Client` receives a `AnyStrippedStateEvent::StrippedRoomAvatar` event.
async fn on_stripped_state_avatar(
&self,
_: SyncRoom,
_: RoomState,
_: &StrippedStateEvent<AvatarEventContent>,
) {
}
/// Fires when `Client` receives a `AnyStrippedStateEvent::StrippedRoomPowerLevels` event.
async fn on_stripped_state_power_levels(
&self,
_: SyncRoom,
_: RoomState,
_: &StrippedStateEvent<PowerLevelsEventContent>,
) {
}
/// Fires when `Client` receives a `AnyStrippedStateEvent::StrippedRoomJoinRules` event.
async fn on_stripped_state_join_rules(
&self,
_: SyncRoom,
_: RoomState,
_: &StrippedStateEvent<JoinRulesEventContent>,
) {
}
// `NonRoomEvent` (this is a type alias from ruma_events)
/// Fires when `Client` receives a `NonRoomEvent::RoomPresence` event.
async fn on_non_room_presence(&self, _: SyncRoom, _: &PresenceEvent) {}
async fn on_non_room_presence(&self, _: RoomState, _: &PresenceEvent) {}
/// Fires when `Client` receives a `NonRoomEvent::RoomName` event.
async fn on_non_room_ignored_users(
&self,
_: SyncRoom,
_: RoomState,
_: &BasicEvent<IgnoredUserListEventContent>,
) {
}
/// Fires when `Client` receives a `NonRoomEvent::RoomCanonicalAlias` event.
async fn on_non_room_push_rules(&self, _: SyncRoom, _: &BasicEvent<PushRulesEventContent>) {}
async fn on_non_room_push_rules(&self, _: RoomState, _: &BasicEvent<PushRulesEventContent>) {}
/// Fires when `Client` receives a `NonRoomEvent::RoomAliases` event.
async fn on_non_room_fully_read(
&self,
_: SyncRoom,
_: RoomState,
_: &SyncEphemeralRoomEvent<FullyReadEventContent>,
) {
}
/// Fires when `Client` receives a `NonRoomEvent::Typing` event.
async fn on_non_room_typing(
&self,
_: SyncRoom,
_: RoomState,
_: &SyncEphemeralRoomEvent<TypingEventContent>,
) {
}
@ -249,27 +252,27 @@ pub trait EventEmitter: Send + Sync {
/// This is always a read receipt.
async fn on_non_room_receipt(
&self,
_: SyncRoom,
_: RoomState,
_: &SyncEphemeralRoomEvent<ReceiptEventContent>,
) {
}
// `PresenceEvent` is a struct so there is only the one method
/// Fires when `Client` receives a `NonRoomEvent::RoomAliases` event.
async fn on_presence_event(&self, _: SyncRoom, _: &PresenceEvent) {}
async fn on_presence_event(&self, _: RoomState, _: &PresenceEvent) {}
/// Fires when `Client` receives a `Event::Custom` event or if deserialization fails
/// because the event was unknown to ruma.
///
/// The only guarantee this method can give about the event is that it is valid JSON.
async fn on_unrecognized_event(&self, _: SyncRoom, _: &RawJsonValue) {}
async fn on_unrecognized_event(&self, _: RoomState, _: &RawJsonValue) {}
/// Fires when `Client` receives a `Event::Custom` event or if deserialization fails
/// because the event was unknown to ruma.
///
/// The only guarantee this method can give about the event is that it is in the
/// shape of a valid matrix event.
async fn on_custom_event(&self, _: SyncRoom, _: &CustomEvent<'_>) {}
async fn on_custom_event(&self, _: RoomState, _: &CustomEvent<'_>) {}
}
#[cfg(test)]
@ -288,78 +291,78 @@ mod test {
#[async_trait]
impl EventEmitter for EvEmitterTest {
async fn on_room_member(&self, _: SyncRoom, _: &SyncStateEvent<MemberEventContent>) {
async fn on_room_member(&self, _: RoomState, _: &SyncStateEvent<MemberEventContent>) {
self.0.lock().await.push("member".to_string())
}
async fn on_room_name(&self, _: SyncRoom, _: &SyncStateEvent<NameEventContent>) {
async fn on_room_name(&self, _: RoomState, _: &SyncStateEvent<NameEventContent>) {
self.0.lock().await.push("name".to_string())
}
async fn on_room_canonical_alias(
&self,
_: SyncRoom,
_: RoomState,
_: &SyncStateEvent<CanonicalAliasEventContent>,
) {
self.0.lock().await.push("canonical".to_string())
}
async fn on_room_aliases(&self, _: SyncRoom, _: &SyncStateEvent<AliasesEventContent>) {
async fn on_room_aliases(&self, _: RoomState, _: &SyncStateEvent<AliasesEventContent>) {
self.0.lock().await.push("aliases".to_string())
}
async fn on_room_avatar(&self, _: SyncRoom, _: &SyncStateEvent<AvatarEventContent>) {
async fn on_room_avatar(&self, _: RoomState, _: &SyncStateEvent<AvatarEventContent>) {
self.0.lock().await.push("avatar".to_string())
}
async fn on_room_message(&self, _: SyncRoom, _: &SyncMessageEvent<MsgEventContent>) {
async fn on_room_message(&self, _: RoomState, _: &SyncMessageEvent<MsgEventContent>) {
self.0.lock().await.push("message".to_string())
}
async fn on_room_message_feedback(
&self,
_: SyncRoom,
_: RoomState,
_: &SyncMessageEvent<FeedbackEventContent>,
) {
self.0.lock().await.push("feedback".to_string())
}
async fn on_room_redaction(&self, _: SyncRoom, _: &SyncRedactionEvent) {
async fn on_room_redaction(&self, _: RoomState, _: &SyncRedactionEvent) {
self.0.lock().await.push("redaction".to_string())
}
async fn on_room_power_levels(
&self,
_: SyncRoom,
_: RoomState,
_: &SyncStateEvent<PowerLevelsEventContent>,
) {
self.0.lock().await.push("power".to_string())
}
async fn on_room_tombstone(&self, _: SyncRoom, _: &SyncStateEvent<TombstoneEventContent>) {
async fn on_room_tombstone(&self, _: RoomState, _: &SyncStateEvent<TombstoneEventContent>) {
self.0.lock().await.push("tombstone".to_string())
}
async fn on_state_member(&self, _: SyncRoom, _: &SyncStateEvent<MemberEventContent>) {
async fn on_state_member(&self, _: RoomState, _: &SyncStateEvent<MemberEventContent>) {
self.0.lock().await.push("state member".to_string())
}
async fn on_state_name(&self, _: SyncRoom, _: &SyncStateEvent<NameEventContent>) {
async fn on_state_name(&self, _: RoomState, _: &SyncStateEvent<NameEventContent>) {
self.0.lock().await.push("state name".to_string())
}
async fn on_state_canonical_alias(
&self,
_: SyncRoom,
_: RoomState,
_: &SyncStateEvent<CanonicalAliasEventContent>,
) {
self.0.lock().await.push("state canonical".to_string())
}
async fn on_state_aliases(&self, _: SyncRoom, _: &SyncStateEvent<AliasesEventContent>) {
async fn on_state_aliases(&self, _: RoomState, _: &SyncStateEvent<AliasesEventContent>) {
self.0.lock().await.push("state aliases".to_string())
}
async fn on_state_avatar(&self, _: SyncRoom, _: &SyncStateEvent<AvatarEventContent>) {
async fn on_state_avatar(&self, _: RoomState, _: &SyncStateEvent<AvatarEventContent>) {
self.0.lock().await.push("state avatar".to_string())
}
async fn on_state_power_levels(
&self,
_: SyncRoom,
_: RoomState,
_: &SyncStateEvent<PowerLevelsEventContent>,
) {
self.0.lock().await.push("state power".to_string())
}
async fn on_state_join_rules(
&self,
_: SyncRoom,
_: RoomState,
_: &SyncStateEvent<JoinRulesEventContent>,
) {
self.0.lock().await.push("state rules".to_string())
@ -369,7 +372,7 @@ mod test {
/// Fires when `Client` receives a `AnyStrippedStateEvent::StrippedRoomMember` event.
async fn on_stripped_state_member(
&self,
_: SyncRoom,
_: RoomState,
_: &StrippedStateEvent<MemberEventContent>,
_: Option<MemberEventContent>,
) {
@ -381,7 +384,7 @@ mod test {
/// Fires when `Client` receives a `AnyStrippedStateEvent::StrippedRoomName` event.
async fn on_stripped_state_name(
&self,
_: SyncRoom,
_: RoomState,
_: &StrippedStateEvent<NameEventContent>,
) {
self.0.lock().await.push("stripped state name".to_string())
@ -389,7 +392,7 @@ mod test {
/// Fires when `Client` receives a `AnyStrippedStateEvent::StrippedRoomCanonicalAlias` event.
async fn on_stripped_state_canonical_alias(
&self,
_: SyncRoom,
_: RoomState,
_: &StrippedStateEvent<CanonicalAliasEventContent>,
) {
self.0
@ -400,7 +403,7 @@ mod test {
/// Fires when `Client` receives a `AnyStrippedStateEvent::StrippedRoomAliases` event.
async fn on_stripped_state_aliases(
&self,
_: SyncRoom,
_: RoomState,
_: &StrippedStateEvent<AliasesEventContent>,
) {
self.0
@ -411,7 +414,7 @@ mod test {
/// Fires when `Client` receives a `AnyStrippedStateEvent::StrippedRoomAvatar` event.
async fn on_stripped_state_avatar(
&self,
_: SyncRoom,
_: RoomState,
_: &StrippedStateEvent<AvatarEventContent>,
) {
self.0
@ -422,7 +425,7 @@ mod test {
/// Fires when `Client` receives a `AnyStrippedStateEvent::StrippedRoomPowerLevels` event.
async fn on_stripped_state_power_levels(
&self,
_: SyncRoom,
_: RoomState,
_: &StrippedStateEvent<PowerLevelsEventContent>,
) {
self.0.lock().await.push("stripped state power".to_string())
@ -430,53 +433,57 @@ mod test {
/// Fires when `Client` receives a `AnyStrippedStateEvent::StrippedRoomJoinRules` event.
async fn on_stripped_state_join_rules(
&self,
_: SyncRoom,
_: RoomState,
_: &StrippedStateEvent<JoinRulesEventContent>,
) {
self.0.lock().await.push("stripped state rules".to_string())
}
async fn on_non_room_presence(&self, _: SyncRoom, _: &PresenceEvent) {
async fn on_non_room_presence(&self, _: RoomState, _: &PresenceEvent) {
self.0.lock().await.push("presence".to_string())
}
async fn on_non_room_ignored_users(
&self,
_: SyncRoom,
_: RoomState,
_: &BasicEvent<IgnoredUserListEventContent>,
) {
self.0.lock().await.push("account ignore".to_string())
}
async fn on_non_room_push_rules(&self, _: SyncRoom, _: &BasicEvent<PushRulesEventContent>) {
async fn on_non_room_push_rules(
&self,
_: RoomState,
_: &BasicEvent<PushRulesEventContent>,
) {
self.0.lock().await.push("account push rules".to_string())
}
async fn on_non_room_fully_read(
&self,
_: SyncRoom,
_: RoomState,
_: &SyncEphemeralRoomEvent<FullyReadEventContent>,
) {
self.0.lock().await.push("account read".to_string())
}
async fn on_non_room_typing(
&self,
_: SyncRoom,
_: RoomState,
_: &SyncEphemeralRoomEvent<TypingEventContent>,
) {
self.0.lock().await.push("typing event".to_string())
}
async fn on_non_room_receipt(
&self,
_: SyncRoom,
_: RoomState,
_: &SyncEphemeralRoomEvent<ReceiptEventContent>,
) {
self.0.lock().await.push("receipt event".to_string())
}
async fn on_presence_event(&self, _: SyncRoom, _: &PresenceEvent) {
async fn on_presence_event(&self, _: RoomState, _: &PresenceEvent) {
self.0.lock().await.push("presence event".to_string())
}
async fn on_unrecognized_event(&self, _: SyncRoom, _: &RawJsonValue) {
async fn on_unrecognized_event(&self, _: RoomState, _: &RawJsonValue) {
self.0.lock().await.push("unrecognized event".to_string())
}
async fn on_custom_event(&self, _: SyncRoom, _: &CustomEvent<'_>) {
async fn on_custom_event(&self, _: RoomState, _: &CustomEvent<'_>) {
self.0.lock().await.push("custom event".to_string())
}
}
@ -503,8 +510,8 @@ mod test {
let client = get_client().await;
client.add_event_emitter(emitter).await;
let mut response = sync_response(SyncResponseFile::Default);
client.receive_sync_response(&mut response).await.unwrap();
let response = sync_response(SyncResponseFile::Default);
client.receive_sync_response(response).await.unwrap();
let v = test_vec.lock().await;
assert_eq!(
@ -535,8 +542,8 @@ mod test {
let client = get_client().await;
client.add_event_emitter(emitter).await;
let mut response = sync_response(SyncResponseFile::Invite);
client.receive_sync_response(&mut response).await.unwrap();
let response = sync_response(SyncResponseFile::Invite);
client.receive_sync_response(response).await.unwrap();
let v = test_vec.lock().await;
assert_eq!(
@ -554,8 +561,8 @@ mod test {
let client = get_client().await;
client.add_event_emitter(emitter).await;
let mut response = sync_response(SyncResponseFile::Leave);
client.receive_sync_response(&mut response).await.unwrap();
let response = sync_response(SyncResponseFile::Leave);
client.receive_sync_response(response).await.unwrap();
let v = test_vec.lock().await;
assert_eq!(
@ -582,8 +589,8 @@ mod test {
let client = get_client().await;
client.add_event_emitter(emitter).await;
let mut response = sync_response(SyncResponseFile::All);
client.receive_sync_response(&mut response).await.unwrap();
let response = sync_response(SyncResponseFile::All);
client.receive_sync_response(response).await.unwrap();
let v = test_vec.lock().await;
assert_eq!(

View File

@ -44,15 +44,17 @@ pub use matrix_sdk_common::*;
mod client;
mod error;
mod event_emitter;
pub mod responses;
mod rooms;
mod session;
mod store;
pub use rooms::{Room, RoomInfo, RoomMember};
pub use event_emitter::EventEmitter;
pub use rooms::{InvitedRoom, JoinedRoom, LeftRoom, Room, RoomInfo, RoomMember, RoomState};
pub use store::Store;
pub use client::{BaseClient, BaseClientConfig, RoomState, RoomStateType};
pub use client::{BaseClient, BaseClientConfig, RoomStateType};
#[cfg(feature = "encryption")]
#[cfg_attr(feature = "docs", doc(cfg(encryption)))]

View File

@ -8,7 +8,7 @@ pub use stripped::{StrippedRoom, StrippedRoomInfo};
pub use members::RoomMember;
use serde::{Deserialize, Serialize};
use std::cmp::max;
use std::{cmp::max, ops::Deref};
use matrix_sdk_common::{
events::{
@ -18,6 +18,86 @@ use matrix_sdk_common::{
identifiers::RoomAliasId,
};
/// An enum that represents the state of the given `Room`.
///
/// If the event came from the `join`, `invite` or `leave` rooms map from the server
/// the variant that holds the corresponding room is used. `RoomState` is generic
/// so it can be used to represent a `Room` or an `Arc<RwLock<Room>>`
#[derive(Debug, Clone)]
pub enum RoomState {
/// A room from the `join` section of a sync response.
Joined(JoinedRoom),
/// A room from the `leave` section of a sync response.
Left(LeftRoom),
/// A room from the `invite` section of a sync response.
Invited(InvitedRoom),
}
impl RoomState {
pub fn joined(self) -> Option<JoinedRoom> {
if let RoomState::Joined(r) = self {
Some(r)
} else {
None
}
}
pub fn is_encrypted(&self) -> bool {
match self {
RoomState::Joined(r) => r.inner.is_encrypted(),
RoomState::Left(r) => r.inner.is_encrypted(),
RoomState::Invited(r) => r.inner.is_encrypted(),
}
}
pub fn are_members_synced(&self) -> bool {
if let RoomState::Joined(r) = self {
r.inner.are_members_synced()
} else {
true
}
}
}
#[derive(Debug, Clone)]
pub struct JoinedRoom {
pub(crate) inner: Room,
}
impl Deref for JoinedRoom {
type Target = Room;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
#[derive(Debug, Clone)]
pub struct LeftRoom {
pub(crate) inner: Room,
}
impl Deref for LeftRoom {
type Target = Room;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
#[derive(Debug, Clone)]
pub struct InvitedRoom {
pub(crate) inner: StrippedRoom,
}
impl Deref for InvitedRoom {
type Target = StrippedRoom;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct BaseRoomInfo {
pub name: Option<String>,

View File

@ -83,6 +83,10 @@ impl Room {
self.inner.lock().unwrap().members_synced
}
pub fn room_type(&self) -> RoomType {
self.inner.lock().unwrap().room_type
}
pub async fn get_active_members(&self) -> impl Stream<Item = RoomMember> + '_ {
let joined = self.store.get_joined_user_ids(self.room_id()).await;
let invited = self.store.get_invited_user_ids(self.room_id()).await;