use std::{
collections::{BTreeMap, HashSet},
sync::Arc,
};
#[cfg(feature = "experimental-sliding-sync")]
use matrix_sdk_common::deserialized_responses::SyncTimelineEvent;
use ruma::{
events::{
direct::OwnedDirectUserIdentifier,
room::{
avatar::RoomAvatarEventContent,
canonical_alias::RoomCanonicalAliasEventContent,
create::RoomCreateEventContent,
encryption::RoomEncryptionEventContent,
guest_access::RoomGuestAccessEventContent,
history_visibility::RoomHistoryVisibilityEventContent,
join_rules::RoomJoinRulesEventContent,
name::{RedactedRoomNameEventContent, RoomNameEventContent},
tombstone::RoomTombstoneEventContent,
topic::RoomTopicEventContent,
},
EmptyStateKey, EventContent, RedactContent, StateEventContent, StateEventType,
},
OwnedRoomId, OwnedUserId, RoomId,
};
use serde::{Deserialize, Serialize};
#[cfg(feature = "experimental-sliding-sync")]
use crate::latest_event::LatestEvent;
use crate::{
deserialized_responses::SyncOrStrippedState,
rooms::{
normal::{RoomSummary, SyncInfo},
BaseRoomInfo, RoomNotableTags,
},
sync::UnreadNotificationsCount,
MinimalStateEvent, OriginalMinimalStateEvent, RoomInfo, RoomState,
};
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct RoomInfoV1 {
room_id: OwnedRoomId,
room_type: RoomState,
notification_counts: UnreadNotificationsCount,
summary: RoomSummary,
members_synced: bool,
last_prev_batch: Option<String>,
#[serde(default = "sync_info_complete")] sync_info: SyncInfo,
#[serde(default = "encryption_state_default")] encryption_state_synced: bool,
#[cfg(feature = "experimental-sliding-sync")]
latest_event: Option<SyncTimelineEvent>,
base_info: BaseRoomInfoV1,
}
impl RoomInfoV1 {
pub fn room_id(&self) -> &RoomId {
&self.room_id
}
pub fn state(&self) -> RoomState {
self.room_type
}
pub fn migrate(self, create: Option<&SyncOrStrippedState<RoomCreateEventContent>>) -> RoomInfo {
let RoomInfoV1 {
room_id,
room_type,
notification_counts,
summary,
members_synced,
last_prev_batch,
sync_info,
encryption_state_synced,
#[cfg(feature = "experimental-sliding-sync")]
latest_event,
base_info,
} = self;
RoomInfo {
version: 0,
room_id,
room_state: room_type,
prev_room_state: None,
notification_counts,
summary,
members_synced,
last_prev_batch,
sync_info,
encryption_state_synced,
#[cfg(feature = "experimental-sliding-sync")]
latest_event: latest_event.map(|ev| Box::new(LatestEvent::new(ev))),
read_receipts: Default::default(),
base_info: base_info.migrate(create),
warned_about_unknown_room_version: Arc::new(false.into()),
cached_display_name: None,
cached_user_defined_notification_mode: None,
#[cfg(feature = "experimental-sliding-sync")]
recency_stamp: None,
}
}
}
fn sync_info_complete() -> SyncInfo {
SyncInfo::FullySynced
}
fn encryption_state_default() -> bool {
true
}
#[derive(Clone, Debug, Serialize, Deserialize)]
struct BaseRoomInfoV1 {
avatar: Option<MinimalStateEvent<RoomAvatarEventContent>>,
canonical_alias: Option<MinimalStateEvent<RoomCanonicalAliasEventContent>>,
dm_targets: HashSet<OwnedUserId>,
encryption: Option<RoomEncryptionEventContent>,
guest_access: Option<MinimalStateEvent<RoomGuestAccessEventContent>>,
history_visibility: Option<MinimalStateEvent<RoomHistoryVisibilityEventContent>>,
join_rules: Option<MinimalStateEvent<RoomJoinRulesEventContent>>,
max_power_level: i64,
name: Option<MinimalStateEvent<RoomNameEventContentV1>>,
tombstone: Option<MinimalStateEvent<RoomTombstoneEventContent>>,
topic: Option<MinimalStateEvent<RoomTopicEventContent>>,
}
impl BaseRoomInfoV1 {
fn migrate(
self,
create: Option<&SyncOrStrippedState<RoomCreateEventContent>>,
) -> Box<BaseRoomInfo> {
let BaseRoomInfoV1 {
avatar,
canonical_alias,
dm_targets,
encryption,
guest_access,
history_visibility,
join_rules,
max_power_level,
name,
tombstone,
topic,
} = self;
let create = create.map(|ev| match ev {
SyncOrStrippedState::Sync(e) => e.into(),
SyncOrStrippedState::Stripped(e) => e.into(),
});
let name = name.map(|name| match name {
MinimalStateEvent::Original(ev) => {
MinimalStateEvent::Original(OriginalMinimalStateEvent {
content: ev.content.into(),
event_id: ev.event_id,
})
}
MinimalStateEvent::Redacted(ev) => MinimalStateEvent::Redacted(ev),
});
let mut converted_dm_targets = HashSet::new();
for dm_target in dm_targets {
converted_dm_targets.insert(OwnedDirectUserIdentifier::from(dm_target));
}
Box::new(BaseRoomInfo {
avatar,
beacons: BTreeMap::new(),
canonical_alias,
create,
dm_targets: converted_dm_targets,
encryption,
guest_access,
history_visibility,
join_rules,
max_power_level,
name,
tombstone,
topic,
rtc_member_events: BTreeMap::new(),
is_marked_unread: false,
notable_tags: RoomNotableTags::empty(),
pinned_events: None,
})
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
struct RoomNameEventContentV1 {
name: Option<String>,
}
impl EventContent for RoomNameEventContentV1 {
type EventType = StateEventType;
fn event_type(&self) -> Self::EventType {
StateEventType::RoomName
}
}
impl StateEventContent for RoomNameEventContentV1 {
type StateKey = EmptyStateKey;
}
impl RedactContent for RoomNameEventContentV1 {
type Redacted = RedactedRoomNameEventContent;
fn redact(self, _version: &ruma::RoomVersionId) -> Self::Redacted {
RedactedRoomNameEventContent::new()
}
}
impl From<RoomNameEventContentV1> for RoomNameEventContent {
fn from(value: RoomNameEventContentV1) -> Self {
RoomNameEventContent::new(value.name.unwrap_or_default())
}
}