1use std::{
18 collections::{BTreeMap, HashSet},
19 sync::Arc,
20};
21
22use matrix_sdk_common::deserialized_responses::TimelineEvent;
23use ruma::{
24 events::{
25 direct::OwnedDirectUserIdentifier,
26 room::{
27 avatar::RoomAvatarEventContent,
28 canonical_alias::RoomCanonicalAliasEventContent,
29 create::RoomCreateEventContent,
30 encryption::RoomEncryptionEventContent,
31 guest_access::RoomGuestAccessEventContent,
32 history_visibility::RoomHistoryVisibilityEventContent,
33 join_rules::RoomJoinRulesEventContent,
34 name::{RedactedRoomNameEventContent, RoomNameEventContent},
35 tombstone::RoomTombstoneEventContent,
36 topic::RoomTopicEventContent,
37 },
38 EmptyStateKey, EventContent, RedactContent, StateEventContent, StateEventType,
39 },
40 OwnedRoomId, OwnedUserId, RoomId,
41};
42use serde::{Deserialize, Serialize};
43
44use crate::{
45 deserialized_responses::SyncOrStrippedState,
46 latest_event::LatestEvent,
47 room::{BaseRoomInfo, RoomSummary, SyncInfo},
48 sync::UnreadNotificationsCount,
49 MinimalStateEvent, OriginalMinimalStateEvent, RoomInfo, RoomState,
50};
51
52#[derive(Clone, Debug, Serialize, Deserialize)]
65pub struct RoomInfoV1 {
66 room_id: OwnedRoomId,
67 room_type: RoomState,
68 notification_counts: UnreadNotificationsCount,
69 summary: RoomSummary,
70 members_synced: bool,
71 last_prev_batch: Option<String>,
72 #[serde(default = "sync_info_complete")] sync_info: SyncInfo,
74 #[serde(default = "encryption_state_default")] encryption_state_synced: bool,
76 latest_event: Option<TimelineEvent>,
77 base_info: BaseRoomInfoV1,
78}
79
80impl RoomInfoV1 {
81 pub fn room_id(&self) -> &RoomId {
83 &self.room_id
84 }
85
86 pub fn state(&self) -> RoomState {
88 self.room_type
89 }
90
91 pub fn migrate(self, create: Option<&SyncOrStrippedState<RoomCreateEventContent>>) -> RoomInfo {
94 let RoomInfoV1 {
95 room_id,
96 room_type,
97 notification_counts,
98 summary,
99 members_synced,
100 last_prev_batch,
101 sync_info,
102 encryption_state_synced,
103 latest_event,
104 base_info,
105 } = self;
106
107 RoomInfo {
108 data_format_version: 0,
109 room_id,
110 room_state: room_type,
111 notification_counts,
112 summary,
113 members_synced,
114 last_prev_batch,
115 sync_info,
116 encryption_state_synced,
117 latest_event: latest_event.map(|ev| Box::new(LatestEvent::new(ev))),
118 read_receipts: Default::default(),
119 base_info: base_info.migrate(create),
120 warned_about_unknown_room_version: Arc::new(false.into()),
121 cached_display_name: None,
122 cached_user_defined_notification_mode: None,
123 recency_stamp: None,
124 invite_accepted_at: None,
125 }
126 }
127}
128
129fn sync_info_complete() -> SyncInfo {
134 SyncInfo::FullySynced
135}
136
137fn encryption_state_default() -> bool {
142 true
143}
144
145#[derive(Clone, Debug, Serialize, Deserialize)]
147struct BaseRoomInfoV1 {
148 avatar: Option<MinimalStateEvent<RoomAvatarEventContent>>,
149 canonical_alias: Option<MinimalStateEvent<RoomCanonicalAliasEventContent>>,
150 dm_targets: HashSet<OwnedUserId>,
151 encryption: Option<RoomEncryptionEventContent>,
152 guest_access: Option<MinimalStateEvent<RoomGuestAccessEventContent>>,
153 history_visibility: Option<MinimalStateEvent<RoomHistoryVisibilityEventContent>>,
154 join_rules: Option<MinimalStateEvent<RoomJoinRulesEventContent>>,
155 max_power_level: i64,
156 name: Option<MinimalStateEvent<RoomNameEventContentV1>>,
157 tombstone: Option<MinimalStateEvent<RoomTombstoneEventContent>>,
158 topic: Option<MinimalStateEvent<RoomTopicEventContent>>,
159}
160
161impl BaseRoomInfoV1 {
162 fn migrate(
164 self,
165 create: Option<&SyncOrStrippedState<RoomCreateEventContent>>,
166 ) -> Box<BaseRoomInfo> {
167 let BaseRoomInfoV1 {
168 avatar,
169 canonical_alias,
170 dm_targets,
171 encryption,
172 guest_access,
173 history_visibility,
174 join_rules,
175 max_power_level,
176 name,
177 tombstone,
178 topic,
179 } = self;
180
181 let create = create.map(|ev| match ev {
182 SyncOrStrippedState::Sync(e) => e.into(),
183 SyncOrStrippedState::Stripped(e) => e.into(),
184 });
185 let name = name.map(|name| match name {
186 MinimalStateEvent::Original(ev) => {
187 MinimalStateEvent::Original(OriginalMinimalStateEvent {
188 content: ev.content.into(),
189 event_id: ev.event_id,
190 })
191 }
192 MinimalStateEvent::Redacted(ev) => MinimalStateEvent::Redacted(ev),
193 });
194
195 let mut converted_dm_targets = HashSet::new();
196 for dm_target in dm_targets {
197 converted_dm_targets.insert(OwnedDirectUserIdentifier::from(dm_target));
198 }
199
200 Box::new(BaseRoomInfo {
201 avatar,
202 beacons: BTreeMap::new(),
203 canonical_alias,
204 create,
205 dm_targets: converted_dm_targets,
206 encryption,
207 guest_access,
208 history_visibility,
209 join_rules,
210 max_power_level,
211 name,
212 tombstone,
213 topic,
214 ..Default::default()
215 })
216 }
217}
218
219#[derive(Clone, Debug, Serialize, Deserialize)]
221struct RoomNameEventContentV1 {
222 name: Option<String>,
223}
224
225impl EventContent for RoomNameEventContentV1 {
226 type EventType = StateEventType;
227
228 fn event_type(&self) -> Self::EventType {
229 StateEventType::RoomName
230 }
231}
232
233impl StateEventContent for RoomNameEventContentV1 {
234 type StateKey = EmptyStateKey;
235}
236
237impl RedactContent for RoomNameEventContentV1 {
238 type Redacted = RedactedRoomNameEventContent;
239
240 fn redact(self, _version: &ruma::RoomVersionId) -> Self::Redacted {
241 RedactedRoomNameEventContent::new()
242 }
243}
244
245impl From<RoomNameEventContentV1> for RoomNameEventContent {
246 fn from(value: RoomNameEventContentV1) -> Self {
247 RoomNameEventContent::new(value.name.unwrap_or_default())
248 }
249}