mirror of
https://github.com/matrix-org/matrix-rust-sdk.git
synced 2026-05-18 21:52:30 -04:00
sdk: Get push actions of events received via back pagination
Signed-off-by: Kévin Commaille <zecakeh@tedomum.fr>
This commit is contained in:
committed by
Jonas Platte
parent
aebd5fe4eb
commit
cc585974e0
@@ -28,10 +28,12 @@ use ruma::{
|
||||
assign,
|
||||
events::{
|
||||
direct::DirectEventContent,
|
||||
push_rules::PushRulesEventContent,
|
||||
receipt::{Receipt, ReceiptThread, ReceiptType},
|
||||
room::{
|
||||
encryption::RoomEncryptionEventContent, history_visibility::HistoryVisibility,
|
||||
server_acl::RoomServerAclEventContent, MediaSource,
|
||||
power_levels::RoomPowerLevelsEventContent, server_acl::RoomServerAclEventContent,
|
||||
MediaSource,
|
||||
},
|
||||
tag::{TagInfo, TagName},
|
||||
AnyRoomAccountDataEvent, AnyStateEvent, AnySyncStateEvent, EmptyStateKey, RedactContent,
|
||||
@@ -39,6 +41,7 @@ use ruma::{
|
||||
RoomAccountDataEventType, StateEventType, StaticEventContent, StaticStateEventContent,
|
||||
SyncStateEvent,
|
||||
},
|
||||
push::{PushConditionRoomCtx, Ruleset},
|
||||
serde::Raw,
|
||||
uint, EventId, MatrixToUri, MatrixUri, OwnedEventId, OwnedServerName, OwnedUserId, RoomId,
|
||||
UInt, UserId,
|
||||
@@ -236,6 +239,20 @@ impl Common {
|
||||
response.chunk.extend(http_response.chunk.into_iter().map(TimelineEvent::new));
|
||||
}
|
||||
|
||||
if let Some(push_context) = self.push_context().await? {
|
||||
let push_rules = self
|
||||
.client()
|
||||
.account()
|
||||
.account_data::<PushRulesEventContent>()
|
||||
.await?
|
||||
.and_then(|r| r.deserialize().ok().map(|r| r.global))
|
||||
.unwrap_or_else(|| Ruleset::server_default(self.own_user_id()));
|
||||
|
||||
for event in &mut response.chunk {
|
||||
event.push_actions = push_rules.get_actions(&event.event, &push_context).to_owned();
|
||||
}
|
||||
}
|
||||
|
||||
Ok(response)
|
||||
}
|
||||
|
||||
@@ -1008,6 +1025,43 @@ impl Common {
|
||||
) -> Result<Vec<(OwnedUserId, Receipt)>> {
|
||||
self.inner.event_receipts(receipt_type, thread, event_id).await.map_err(Into::into)
|
||||
}
|
||||
|
||||
/// Get the push context for this room.
|
||||
///
|
||||
/// Returns `None` if some data couldn't be found. This should only happen
|
||||
/// in brand new rooms, while we process its state.
|
||||
async fn push_context(&self) -> Result<Option<PushConditionRoomCtx>> {
|
||||
let room_id = self.room_id();
|
||||
let user_id = self.own_user_id();
|
||||
let room_info = self.clone_info();
|
||||
let member_count = room_info.active_members_count();
|
||||
|
||||
let user_display_name = if let Some(member) = self.get_member_no_sync(user_id).await? {
|
||||
member.name().to_owned()
|
||||
} else {
|
||||
return Ok(None);
|
||||
};
|
||||
|
||||
let room_power_levels = if let Some(event) = self
|
||||
.get_state_event_static::<RoomPowerLevelsEventContent>()
|
||||
.await?
|
||||
.and_then(|e| e.deserialize().ok())
|
||||
{
|
||||
event.power_levels()
|
||||
} else {
|
||||
return Ok(None);
|
||||
};
|
||||
|
||||
Ok(Some(PushConditionRoomCtx {
|
||||
user_id: user_id.to_owned(),
|
||||
room_id: room_id.to_owned(),
|
||||
member_count: UInt::new(member_count).unwrap_or(UInt::MAX),
|
||||
user_display_name,
|
||||
users_power_levels: room_power_levels.users,
|
||||
default_power_level: room_power_levels.users_default,
|
||||
notification_power_levels: room_power_levels.notifications,
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
/// Options for [`messages`][Common::messages].
|
||||
|
||||
@@ -812,3 +812,99 @@ async fn sync_highlighted() {
|
||||
// `m.room.tombstone` should be highlighted by default.
|
||||
assert!(remote_event.is_highlighted());
|
||||
}
|
||||
|
||||
#[async_test]
|
||||
async fn back_pagination_highlighted() {
|
||||
let room_id = room_id!("!a98sd12bjh:example.org");
|
||||
let (client, server) = logged_in_client().await;
|
||||
let sync_settings = SyncSettings::new().timeout(Duration::from_millis(3000));
|
||||
|
||||
let mut ev_builder = EventBuilder::new();
|
||||
ev_builder
|
||||
// We need the member event and power levels locally so the push rules processor works.
|
||||
.add_joined_room(
|
||||
JoinedRoomBuilder::new(room_id)
|
||||
.add_state_event(StateTestEvent::Member)
|
||||
.add_state_event(StateTestEvent::PowerLevels),
|
||||
);
|
||||
|
||||
mock_sync(&server, ev_builder.build_json_sync_response(), None).await;
|
||||
let _response = client.sync_once(sync_settings.clone()).await.unwrap();
|
||||
server.reset().await;
|
||||
|
||||
let room = client.get_room(room_id).unwrap();
|
||||
let timeline = Arc::new(room.timeline().await);
|
||||
let (_, mut timeline_stream) = timeline.subscribe().await;
|
||||
|
||||
let response_json = json!({
|
||||
"chunk": [
|
||||
{
|
||||
"content": {
|
||||
"body": "hello",
|
||||
"msgtype": "m.text",
|
||||
},
|
||||
"event_id": "$msda7m0df9E9op3",
|
||||
"origin_server_ts": 152037280,
|
||||
"sender": "@example:localhost",
|
||||
"type": "m.room.message",
|
||||
"room_id": room_id,
|
||||
},
|
||||
{
|
||||
"content": {
|
||||
"body": "This room has been replaced",
|
||||
"replacement_room": "!newroom:localhost",
|
||||
},
|
||||
"event_id": "$foun39djjod0f",
|
||||
"origin_server_ts": 152039280,
|
||||
"sender": "@bob:localhost",
|
||||
"state_key": "",
|
||||
"type": "m.room.tombstone",
|
||||
"room_id": room_id,
|
||||
},
|
||||
],
|
||||
"end": "t47409-4357353_219380_26003_2269",
|
||||
"start": "t392-516_47314_0_7_1_1_1_11444_1"
|
||||
});
|
||||
Mock::given(method("GET"))
|
||||
.and(path_regex(r"^/_matrix/client/r0/rooms/.*/messages$"))
|
||||
.and(header("authorization", "Bearer 1234"))
|
||||
.respond_with(ResponseTemplate::new(200).set_body_json(response_json))
|
||||
.expect(1)
|
||||
.named("messages_batch_1")
|
||||
.mount(&server)
|
||||
.await;
|
||||
|
||||
timeline.paginate_backwards(PaginationOptions::single_request(10)).await.unwrap();
|
||||
server.reset().await;
|
||||
|
||||
let loading = assert_matches!(
|
||||
timeline_stream.next().await,
|
||||
Some(VectorDiff::PushFront { value }) => value
|
||||
);
|
||||
assert_matches!(loading.as_virtual().unwrap(), VirtualTimelineItem::LoadingIndicator);
|
||||
|
||||
let day_divider = assert_matches!(
|
||||
timeline_stream.next().await,
|
||||
Some(VectorDiff::Insert { index: 1, value }) => value
|
||||
);
|
||||
assert_matches!(day_divider.as_virtual().unwrap(), VirtualTimelineItem::DayDivider(_));
|
||||
|
||||
let first = assert_matches!(
|
||||
timeline_stream.next().await,
|
||||
Some(VectorDiff::Insert { index: 2, value }) => value
|
||||
);
|
||||
let remote_event = first.as_event().unwrap().as_remote().unwrap();
|
||||
// Own events don't trigger push rules.
|
||||
assert!(!remote_event.is_highlighted());
|
||||
|
||||
let second = assert_matches!(
|
||||
timeline_stream.next().await,
|
||||
Some(VectorDiff::Insert { index: 2, value }) => value
|
||||
);
|
||||
let remote_event = second.as_event().unwrap().as_remote().unwrap();
|
||||
// `m.room.tombstone` should be highlighted by default.
|
||||
assert!(remote_event.is_highlighted());
|
||||
|
||||
// Removal of the loading indicator
|
||||
assert_matches!(timeline_stream.next().await, Some(VectorDiff::PopFront));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user