sdk-base: add pinned events to BaseRoomInfo to keep track of them.

Also add `Room::pinned_events(&self)` to get the current pinned events at any time.
This commit is contained in:
Jorge Martín
2024-07-18 12:20:55 +02:00
committed by Jorge Martin Espinosa
parent 99da0ff18d
commit 79010af9e2
4 changed files with 75 additions and 3 deletions

View File

@@ -30,6 +30,7 @@ use ruma::{
join_rules::RoomJoinRulesEventContent,
member::MembershipState,
name::RoomNameEventContent,
pinned_events::RoomPinnedEventsEventContent,
tombstone::RoomTombstoneEventContent,
topic::RoomTopicEventContent,
},
@@ -117,6 +118,8 @@ pub struct BaseRoomInfo {
/// others, and this field collects them.
#[serde(skip_serializing_if = "RoomNotableTags::is_empty", default)]
pub(crate) notable_tags: RoomNotableTags,
/// The `m.room.pinned_events` of this room.
pub(crate) pinned_events: Option<RoomPinnedEventsEventContent>,
}
impl BaseRoomInfo {
@@ -194,6 +197,9 @@ impl BaseRoomInfo {
ev.as_original().is_some_and(|o| !o.content.active_memberships(None).is_empty())
});
}
AnySyncStateEvent::RoomPinnedEvents(p) => {
self.pinned_events = p.as_original().map(|p| p.content.clone());
}
_ => return false,
}
@@ -253,6 +259,11 @@ impl BaseRoomInfo {
// wont have call information.
return false;
}
AnyStrippedStateEvent::RoomPinnedEvents(p) => {
if let Some(pinned) = p.content.pinned.clone() {
self.pinned_events = Some(RoomPinnedEventsEventContent::new(pinned));
}
}
_ => return false,
}
@@ -349,6 +360,7 @@ impl Default for BaseRoomInfo {
rtc_member: BTreeMap::new(),
is_marked_unread: false,
notable_tags: RoomNotableTags::empty(),
pinned_events: None,
}
}
}

View File

@@ -947,6 +947,11 @@ impl Room {
pub fn recency_stamp(&self) -> Option<u64> {
self.inner.read().recency_stamp
}
/// Get the list of event ids for pinned events in this room.
pub fn pinned_events(&self) -> Vec<OwnedEventId> {
self.inner.get().base_info.pinned_events.map(|content| content.pinned).unwrap_or_default()
}
}
/// The underlying pure data structure for joined and left rooms.
@@ -1615,10 +1620,11 @@ mod tests {
SyncRoomMemberEvent,
},
name::RoomNameEventContent,
pinned_events::RoomPinnedEventsEventContent,
},
AnySyncStateEvent, EmptyStateKey, StateEventType, StateUnsigned, SyncStateEvent,
},
room_alias_id, room_id,
owned_event_id, room_alias_id, room_id,
serde::Raw,
user_id, EventEncryptionAlgorithm, MilliSecondsSinceUnixEpoch, OwnedEventId, OwnedUserId,
UserId,
@@ -1671,7 +1677,9 @@ mod tests {
latest_event: Some(Box::new(LatestEvent::new(
Raw::from_json_string(json!({"sender": "@u:i.uk"}).to_string()).unwrap().into(),
))),
base_info: Box::new(BaseRoomInfo::new()),
base_info: Box::new(
assign!(BaseRoomInfo::new(), { pinned_events: Some(RoomPinnedEventsEventContent::new(vec![owned_event_id!("$a")])) }),
),
read_receipts: Default::default(),
warned_about_unknown_room_version: Arc::new(false.into()),
cached_display_name: None,
@@ -1720,6 +1728,9 @@ mod tests {
"name": null,
"tombstone": null,
"topic": null,
"pinned_events": {
"pinned": ["$a"]
},
},
"read_receipts": {
"num_unread": 0,

View File

@@ -860,11 +860,12 @@ mod tests {
member::{MembershipState, RoomMemberEventContent},
message::SyncRoomMessageEvent,
name::RoomNameEventContent,
pinned_events::RoomPinnedEventsEventContent,
},
AnySyncMessageLikeEvent, AnySyncTimelineEvent, GlobalAccountDataEventContent,
StateEventContent,
},
mxc_uri, owned_mxc_uri, owned_user_id, room_alias_id, room_id,
mxc_uri, owned_event_id, owned_mxc_uri, owned_user_id, room_alias_id, room_id,
serde::Raw,
uint, user_id, JsOption, MxcUri, OwnedRoomId, OwnedUserId, RoomAliasId, RoomId, UserId,
};
@@ -2178,6 +2179,53 @@ mod tests {
);
}
#[async_test]
async fn test_pinned_events_are_updated_on_sync() {
let user_a_id = user_id!("@a:e.uk");
let client = logged_in_base_client(Some(user_a_id)).await;
let room_id = room_id!("!r:e.uk");
let pinned_event_id = owned_event_id!("$an-id:e.uk");
// Create room
let mut room_response = http::response::Room::new();
set_room_joined(&mut room_response, user_a_id);
let response = response_with_room(room_id, room_response);
client.process_sliding_sync(&response, &(), true).await.expect("Failed to process sync");
// The newly created room has no pinned event ids
let room = client.get_room(room_id).unwrap();
let pinned_event_ids = room.pinned_events();
assert!(pinned_event_ids.is_empty());
// Load new pinned event id
let mut room_response = http::response::Room::new();
room_response.required_state.push(make_state_event(
user_a_id,
"",
RoomPinnedEventsEventContent::new(vec![pinned_event_id.clone()]),
None,
));
let response = response_with_room(room_id, room_response);
client.process_sliding_sync(&response, &(), true).await.expect("Failed to process sync");
let pinned_event_ids = room.pinned_events();
assert_eq!(pinned_event_ids.len(), 1);
assert_eq!(pinned_event_ids[0], pinned_event_id);
// Pinned event ids are now empty
let mut room_response = http::response::Room::new();
room_response.required_state.push(make_state_event(
user_a_id,
"",
RoomPinnedEventsEventContent::new(Vec::new()),
None,
));
let response = response_with_room(room_id, room_response);
client.process_sliding_sync(&response, &(), true).await.expect("Failed to process sync");
let pinned_event_ids = room.pinned_events();
assert!(pinned_event_ids.is_empty());
}
async fn choose_event_to_cache(events: &[SyncTimelineEvent]) -> Option<SyncTimelineEvent> {
let room = make_room();
let mut room_info = room.clone_info();

View File

@@ -213,6 +213,7 @@ impl BaseRoomInfoV1 {
rtc_member: BTreeMap::new(),
is_marked_unread: false,
notable_tags: RoomNotableTags::empty(),
pinned_events: None,
})
}
}