mirror of
https://github.com/matrix-org/matrix-rust-sdk.git
synced 2026-05-08 07:56:55 -04:00
feat(base): Store the timestamp from SS in RoomInfo::recency_timestamp.
This patch adds a new field in `RoomInfo`: `recency_timestamp: Option<MilliSecondsSinceUnixEpoch>>`. Its value comes from a Sliding Sync Room response, that's why all this API is behind `cfg(feature = "experimental-sliding-sync")`.
This commit is contained in:
@@ -24,8 +24,6 @@ use bitflags::bitflags;
|
||||
use eyeball::{SharedObservable, Subscriber};
|
||||
#[cfg(all(feature = "e2e-encryption", feature = "experimental-sliding-sync"))]
|
||||
use matrix_sdk_common::ring_buffer::RingBuffer;
|
||||
#[cfg(feature = "experimental-sliding-sync")]
|
||||
use ruma::events::AnySyncTimelineEvent;
|
||||
use ruma::{
|
||||
api::client::sync::sync_events::v3::RoomSummary as RumaSummary,
|
||||
events::{
|
||||
@@ -51,6 +49,8 @@ use ruma::{
|
||||
EventId, MxcUri, OwnedEventId, OwnedMxcUri, OwnedRoomAliasId, OwnedRoomId, OwnedUserId,
|
||||
RoomAliasId, RoomId, RoomVersionId, UserId,
|
||||
};
|
||||
#[cfg(feature = "experimental-sliding-sync")]
|
||||
use ruma::{events::AnySyncTimelineEvent, MilliSecondsSinceUnixEpoch};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use tokio::sync::broadcast;
|
||||
use tracing::{debug, field::debug, info, instrument, warn};
|
||||
@@ -888,6 +888,14 @@ impl Room {
|
||||
pub fn is_marked_unread(&self) -> bool {
|
||||
self.inner.read().base_info.is_marked_unread
|
||||
}
|
||||
|
||||
/// Returns the recency timestamp of the room.
|
||||
///
|
||||
/// Please read `RoomInfo::recency_timestamp` to learn more.
|
||||
#[cfg(feature = "experimental-sliding-sync")]
|
||||
pub fn recency_timestamp(&self) -> Option<MilliSecondsSinceUnixEpoch> {
|
||||
self.inner.read().recency_timestamp
|
||||
}
|
||||
}
|
||||
|
||||
/// The underlying pure data structure for joined and left rooms.
|
||||
@@ -946,6 +954,16 @@ pub struct RoomInfo {
|
||||
/// filled at start when creating a room, or on every successful sync.
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub(crate) cached_display_name: Option<DisplayName>,
|
||||
|
||||
/// The recency timestamp of this room.
|
||||
///
|
||||
/// It's not to be confused with `origin_server_ts` of the latest event.
|
||||
/// Sliding Sync might "ignore” some events when computing the recency
|
||||
/// timestamp of the room. Thus, using this `recency_timestamp` value is
|
||||
/// more accurate than relying on the latest event.
|
||||
#[cfg(feature = "experimental-sliding-sync")]
|
||||
#[serde(default)]
|
||||
pub(crate) recency_timestamp: Option<MilliSecondsSinceUnixEpoch>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
|
||||
@@ -983,6 +1001,8 @@ impl RoomInfo {
|
||||
base_info: Box::new(BaseRoomInfo::new()),
|
||||
warned_about_unknown_room_version: Arc::new(false.into()),
|
||||
cached_display_name: None,
|
||||
#[cfg(feature = "experimental-sliding-sync")]
|
||||
recency_timestamp: None,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1387,6 +1407,14 @@ impl RoomInfo {
|
||||
pub fn latest_event(&self) -> Option<&LatestEvent> {
|
||||
self.latest_event.as_deref()
|
||||
}
|
||||
|
||||
/// Updates the recency timestamp of this room.
|
||||
///
|
||||
/// Please read [`Self::recency_timestamp`] to learn more.
|
||||
#[cfg(feature = "experimental-sliding-sync")]
|
||||
pub(crate) fn update_recency_timestamp(&mut self, timestamp: MilliSecondsSinceUnixEpoch) {
|
||||
self.recency_timestamp = Some(timestamp);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "experimental-sliding-sync")]
|
||||
@@ -1601,6 +1629,7 @@ mod tests {
|
||||
read_receipts: Default::default(),
|
||||
warned_about_unknown_room_version: Arc::new(false.into()),
|
||||
cached_display_name: None,
|
||||
recency_timestamp: Some(MilliSecondsSinceUnixEpoch(42u32.into())),
|
||||
};
|
||||
|
||||
let info_json = json!({
|
||||
@@ -1653,6 +1682,7 @@ mod tests {
|
||||
"latest_active": null,
|
||||
"pending": []
|
||||
},
|
||||
"recency_timestamp": 42,
|
||||
});
|
||||
|
||||
assert_eq!(serde_json::to_value(info).unwrap(), info_json);
|
||||
|
||||
@@ -733,6 +733,10 @@ fn process_room_properties(room_data: &v4::SlidingSyncRoom, room_info: &mut Room
|
||||
if room_data.limited {
|
||||
room_info.mark_members_missing();
|
||||
}
|
||||
|
||||
if let Some(recency_timestamp) = &room_data.timestamp {
|
||||
room_info.update_recency_timestamp(*recency_timestamp);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@@ -762,7 +766,8 @@ mod tests {
|
||||
},
|
||||
mxc_uri, owned_mxc_uri, owned_user_id, room_alias_id, room_id,
|
||||
serde::Raw,
|
||||
uint, user_id, JsOption, MxcUri, OwnedRoomId, OwnedUserId, RoomAliasId, RoomId, UserId,
|
||||
uint, user_id, JsOption, MilliSecondsSinceUnixEpoch, MxcUri, OwnedRoomId, OwnedUserId,
|
||||
RoomAliasId, RoomId, UserId,
|
||||
};
|
||||
use serde_json::json;
|
||||
|
||||
@@ -1736,6 +1741,80 @@ mod tests {
|
||||
assert_eq!(rawev_id(room.latest_event().unwrap().event().clone()), "$a");
|
||||
}
|
||||
|
||||
#[async_test]
|
||||
async fn test_recency_timestamp_is_found_when_processing_sliding_sync_response() {
|
||||
// Given a logged-in client
|
||||
let client = logged_in_base_client(None).await;
|
||||
let room_id = room_id!("!r:e.uk");
|
||||
|
||||
// When I send sliding sync response containing a room with a recency timestamp
|
||||
let room = assign!(v4::SlidingSyncRoom::new(), {
|
||||
timestamp: Some(MilliSecondsSinceUnixEpoch(42u32.into())),
|
||||
});
|
||||
let response = response_with_room(room_id, room);
|
||||
client.process_sliding_sync(&response, &()).await.expect("Failed to process sync");
|
||||
|
||||
// Then the room in the client has the recency timestamp
|
||||
let client_room = client.get_room(room_id).expect("No room found");
|
||||
assert_eq!(client_room.recency_timestamp().expect("No recency timestamp").0, 42u32.into());
|
||||
}
|
||||
|
||||
#[async_test]
|
||||
async fn test_recency_timestamp_can_be_overwritten_when_present_in_a_sliding_sync_response() {
|
||||
// Given a logged-in client
|
||||
let client = logged_in_base_client(None).await;
|
||||
let room_id = room_id!("!r:e.uk");
|
||||
|
||||
{
|
||||
// When I send sliding sync response containing a room with a recency timestamp
|
||||
let room = assign!(v4::SlidingSyncRoom::new(), {
|
||||
timestamp: Some(MilliSecondsSinceUnixEpoch(42u32.into())),
|
||||
});
|
||||
let response = response_with_room(room_id, room);
|
||||
client.process_sliding_sync(&response, &()).await.expect("Failed to process sync");
|
||||
|
||||
// Then the room in the client has the recency timestamp
|
||||
let client_room = client.get_room(room_id).expect("No room found");
|
||||
assert_eq!(
|
||||
client_room.recency_timestamp().expect("No recency timestamp").0,
|
||||
42u32.into()
|
||||
);
|
||||
}
|
||||
|
||||
{
|
||||
// When I send sliding sync response containing a room with NO recency timestamp
|
||||
let room = assign!(v4::SlidingSyncRoom::new(), {
|
||||
timestamp: None,
|
||||
});
|
||||
let response = response_with_room(room_id, room);
|
||||
client.process_sliding_sync(&response, &()).await.expect("Failed to process sync");
|
||||
|
||||
// Then the room in the client has the previous recency timestamp
|
||||
let client_room = client.get_room(room_id).expect("No room found");
|
||||
assert_eq!(
|
||||
client_room.recency_timestamp().expect("No recency timestamp").0,
|
||||
42u32.into()
|
||||
);
|
||||
}
|
||||
|
||||
{
|
||||
// When I send sliding sync response containing a room with a NEW recency
|
||||
// timestamp
|
||||
let room = assign!(v4::SlidingSyncRoom::new(), {
|
||||
timestamp: Some(MilliSecondsSinceUnixEpoch(153u32.into())),
|
||||
});
|
||||
let response = response_with_room(room_id, room);
|
||||
client.process_sliding_sync(&response, &()).await.expect("Failed to process sync");
|
||||
|
||||
// Then the room in the client has the recency timestamp
|
||||
let client_room = client.get_room(room_id).expect("No room found");
|
||||
assert_eq!(
|
||||
client_room.recency_timestamp().expect("No recency timestamp").0,
|
||||
153u32.into()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
async fn choose_event_to_cache(events: &[SyncTimelineEvent]) -> Option<SyncTimelineEvent> {
|
||||
let room = make_room();
|
||||
let mut room_info = room.clone_info();
|
||||
|
||||
@@ -125,6 +125,8 @@ impl RoomInfoV1 {
|
||||
base_info: base_info.migrate(create),
|
||||
warned_about_unknown_room_version: Arc::new(false.into()),
|
||||
cached_display_name: None,
|
||||
#[cfg(feature = "experimental-sliding-sync")]
|
||||
recency_timestamp: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user