refactor(sdk): Split power_levels in latest_event.

This patch splits `power_levels: &Option<(&UserId, RoomPowerLevels)>`
into 2 variables: `own_user_id: Option<&UserId>` and `power_levels:
Option<&RoomPowerLevels>`. The idea is to be able to get the
`own_user_id` even if the power levels are `None`.
This commit is contained in:
Ivan Enderlin
2025-10-02 11:24:35 +02:00
parent 203a3783ae
commit f4a6d12979
2 changed files with 119 additions and 70 deletions
@@ -87,7 +87,8 @@ impl LatestEvent {
pub async fn update_with_event_cache(
&mut self,
room_event_cache: &RoomEventCache,
power_levels: &Option<(&UserId, RoomPowerLevels)>,
own_user_id: Option<&UserId>,
power_levels: Option<&RoomPowerLevels>,
) {
if self.buffer_of_values_for_local_events.is_empty().not() {
// At least one `LatestEventValue` exists for local events (i.e. coming from the
@@ -96,9 +97,12 @@ impl LatestEvent {
return;
}
let new_value =
LatestEventValueBuilder::new_remote_with_power_levels(room_event_cache, power_levels)
.await;
let new_value = LatestEventValueBuilder::new_remote_with_power_levels(
room_event_cache,
own_user_id,
power_levels,
)
.await;
self.update(new_value).await;
}
@@ -109,12 +113,14 @@ impl LatestEvent {
&mut self,
send_queue_update: &RoomSendQueueUpdate,
room_event_cache: &RoomEventCache,
power_levels: &Option<(&UserId, RoomPowerLevels)>,
own_user_id: Option<&UserId>,
power_levels: Option<&RoomPowerLevels>,
) {
let new_value = LatestEventValueBuilder::new_local(
send_queue_update,
&mut self.buffer_of_values_for_local_events,
room_event_cache,
own_user_id,
power_levels,
)
.await;
@@ -310,7 +316,7 @@ mod tests_latest_event {
// First, let's create a `LatestEventValue` from the event cache. It must work.
{
latest_event.update_with_event_cache(&room_event_cache, &None).await;
latest_event.update_with_event_cache(&room_event_cache, None, None).await;
assert_matches!(latest_event.current_value.get().await, LatestEventValue::Remote(_));
}
@@ -327,7 +333,7 @@ mod tests_latest_event {
content,
});
latest_event.update_with_send_queue(&update, &room_event_cache, &None).await;
latest_event.update_with_send_queue(&update, &room_event_cache, None, None).await;
assert_matches!(
latest_event.current_value.get().await,
@@ -339,7 +345,7 @@ mod tests_latest_event {
// Nothing must happen, it cannot overwrite the current
// `LatestEventValue` because the local event isn't sent yet.
{
latest_event.update_with_event_cache(&room_event_cache, &None).await;
latest_event.update_with_event_cache(&room_event_cache, None, None).await;
assert_matches!(
latest_event.current_value.get().await,
@@ -355,7 +361,7 @@ mod tests_latest_event {
event_id: event_id!("$ev1").to_owned(),
};
latest_event.update_with_send_queue(&update, &room_event_cache, &None).await;
latest_event.update_with_send_queue(&update, &room_event_cache, None, None).await;
assert_matches!(
latest_event.current_value.get().await,
@@ -366,7 +372,7 @@ mod tests_latest_event {
// Finally, let's create a `LatestEventValue` from the event cache. _Now_ it's
// possible, because there is no more local events.
{
latest_event.update_with_event_cache(&room_event_cache, &None).await;
latest_event.update_with_event_cache(&room_event_cache, None, None).await;
assert_matches!(latest_event.current_value.get().await, LatestEventValue::Remote(_));
}
@@ -433,7 +439,7 @@ mod tests_latest_event {
// Generate a new `LatestEventValue`.
{
let mut latest_event = LatestEvent::new(&weak_room, None, &room_event_cache).await;
latest_event.update_with_event_cache(&room_event_cache, &None).await;
latest_event.update_with_event_cache(&room_event_cache, None, None).await;
assert_matches!(
latest_event.current_value.get().await,
@@ -485,28 +491,30 @@ impl LatestEventValueBuilder {
// Get the power levels of the user for the current room if the `WeakRoom` is
// still valid.
let room = weak_room.get();
let power_levels = match &room {
let (own_user_id, power_levels) = match &room {
Some(room) => {
let power_levels = room.power_levels().await.ok();
Some(room.own_user_id()).zip(power_levels)
(Some(room.own_user_id()), power_levels)
}
None => None,
None => (None, None),
};
Self::new_remote_with_power_levels(room_event_cache, &power_levels).await
Self::new_remote_with_power_levels(room_event_cache, own_user_id, power_levels.as_ref())
.await
}
/// Create a new [`LatestEventValue::Remote`] based on existing power
/// levels.
async fn new_remote_with_power_levels(
room_event_cache: &RoomEventCache,
power_levels: &Option<(&UserId, RoomPowerLevels)>,
own_user_id: Option<&UserId>,
power_levels: Option<&RoomPowerLevels>,
) -> LatestEventValue {
room_event_cache
.rfind_map_event_in_memory_by(|event| {
filter_timeline_event(event, power_levels).then(|| event.clone())
filter_timeline_event(event, own_user_id, power_levels).then(|| event.clone())
})
.await
.map(LatestEventValue::Remote)
@@ -519,7 +527,8 @@ impl LatestEventValueBuilder {
send_queue_update: &RoomSendQueueUpdate,
buffer_of_values_for_local_events: &mut LatestEventValuesForLocalEvents,
room_event_cache: &RoomEventCache,
power_levels: &Option<(&UserId, RoomPowerLevels)>,
own_user_id: Option<&UserId>,
power_levels: Option<&RoomPowerLevels>,
) -> LatestEventValue {
use crate::send_queue::{LocalEcho, LocalEchoContent};
@@ -576,6 +585,7 @@ impl LatestEventValueBuilder {
Self::new_local_or_remote(
buffer_of_values_for_local_events,
room_event_cache,
own_user_id,
power_levels,
)
.await
@@ -608,6 +618,7 @@ impl LatestEventValueBuilder {
let value = Self::new_local_or_remote(
buffer_of_values_for_local_events,
room_event_cache,
own_user_id,
power_levels,
)
.await;
@@ -654,6 +665,7 @@ impl LatestEventValueBuilder {
Self::new_local_or_remote(
buffer_of_values_for_local_events,
room_event_cache,
own_user_id,
power_levels,
)
.await
@@ -669,6 +681,7 @@ impl LatestEventValueBuilder {
Self::new_local_or_remote(
buffer_of_values_for_local_events,
room_event_cache,
own_user_id,
power_levels,
)
.await
@@ -684,6 +697,7 @@ impl LatestEventValueBuilder {
Self::new_local_or_remote(
buffer_of_values_for_local_events,
room_event_cache,
own_user_id,
power_levels,
)
.await
@@ -705,12 +719,13 @@ impl LatestEventValueBuilder {
async fn new_local_or_remote(
buffer_of_values_for_local_events: &mut LatestEventValuesForLocalEvents,
room_event_cache: &RoomEventCache,
power_levels: &Option<(&UserId, RoomPowerLevels)>,
own_user_id: Option<&UserId>,
power_levels: Option<&RoomPowerLevels>,
) -> LatestEventValue {
if let Some(value) = buffer_of_values_for_local_events.last() {
value.clone()
} else {
Self::new_remote_with_power_levels(room_event_cache, power_levels).await
Self::new_remote_with_power_levels(room_event_cache, own_user_id, power_levels).await
}
}
}
@@ -899,7 +914,8 @@ impl LatestEventValuesForLocalEvents {
fn filter_timeline_event(
event: &TimelineEvent,
power_levels: &Option<(&UserId, RoomPowerLevels)>,
own_user_id: Option<&UserId>,
power_levels: Option<&RoomPowerLevels>,
) -> bool {
// Cast the event into an `AnySyncTimelineEvent`. If deserializing fails, we
// ignore the event.
@@ -927,7 +943,9 @@ fn filter_timeline_event(
}
}
AnySyncTimelineEvent::State(state) => filter_any_sync_state_event(state, power_levels),
AnySyncTimelineEvent::State(state) => {
filter_any_sync_state_event(state, own_user_id, power_levels)
}
}
}
@@ -970,14 +988,15 @@ fn filter_any_message_like_event_content(event: AnyMessageLikeEventContent) -> b
fn filter_any_sync_state_event(
event: AnySyncStateEvent,
power_levels: &Option<(&UserId, RoomPowerLevels)>,
own_user_id: Option<&UserId>,
power_levels: Option<&RoomPowerLevels>,
) -> bool {
match event {
AnySyncStateEvent::RoomMember(member) => {
match member.membership() {
MembershipState::Knock => {
let can_accept_or_decline_knocks = match power_levels {
Some((own_user_id, room_power_levels)) => {
let can_accept_or_decline_knocks = match (own_user_id, power_levels) {
(Some(own_user_id), Some(room_power_levels)) => {
room_power_levels.user_can_invite(own_user_id)
|| room_power_levels.user_can_kick(own_user_id)
}
@@ -1040,7 +1059,7 @@ mod tests_latest_event_content {
$event_builder
};
assert_eq!(filter_timeline_event(&event, &None), $expect );
assert_eq!(filter_timeline_event(&event, Some(user_id!("@mnt_io:matrix.org")), None), $expect );
};
}
@@ -1220,33 +1239,30 @@ mod tests_latest_event_content {
// Cannot accept. Cannot decline.
{
let mut room_power_levels = room_power_levels.clone();
room_power_levels.invite = 10.into();
room_power_levels.kick = 10.into();
assert!(
filter_timeline_event(&event, &Some((user_id, room_power_levels))).not(),
filter_timeline_event(&event, Some(user_id), Some(&room_power_levels)).not(),
"cannot accept, cannot decline",
);
}
// Can accept. Cannot decline.
{
let mut room_power_levels = room_power_levels.clone();
room_power_levels.invite = 0.into();
room_power_levels.kick = 10.into();
assert!(
filter_timeline_event(&event, &Some((user_id, room_power_levels))),
filter_timeline_event(&event, Some(user_id), Some(&room_power_levels)),
"can accept, cannot decline",
);
}
// Cannot accept. Can decline.
{
let mut room_power_levels = room_power_levels.clone();
room_power_levels.invite = 10.into();
room_power_levels.kick = 0.into();
assert!(
filter_timeline_event(&event, &Some((user_id, room_power_levels))),
filter_timeline_event(&event, Some(user_id), Some(&room_power_levels)),
"cannot accept, can decline",
);
}
@@ -1256,7 +1272,7 @@ mod tests_latest_event_content {
room_power_levels.invite = 0.into();
room_power_levels.kick = 0.into();
assert!(
filter_timeline_event(&event, &Some((user_id, room_power_levels))),
filter_timeline_event(&event, Some(user_id), Some(&room_power_levels)),
"can accept, can decline",
);
}
@@ -1290,7 +1306,7 @@ mod tests_latest_event_content {
assert_latest_event_content!(
event | event_factory | {
event_factory
.member(user_id!("@mnt.io:matrix.org"))
.member(user_id!("@mnt_io:matrix.org"))
.membership(MembershipState::Invite)
.into_event()
}
@@ -1727,7 +1743,7 @@ mod tests_latest_event_value_builder {
// The `LatestEventValue` matches the new local event.
assert_local_value_matches_room_message_with_body!(
LatestEventValueBuilder::new_local(&update, &mut buffer, &room_event_cache, &None).await,
LatestEventValueBuilder::new_local(&update, &mut buffer, &room_event_cache, None, None).await,
LatestEventValue::LocalIsSending => with body = "A"
);
}
@@ -1741,7 +1757,7 @@ mod tests_latest_event_value_builder {
// The `LatestEventValue` matches the new local event.
assert_local_value_matches_room_message_with_body!(
LatestEventValueBuilder::new_local(&update, &mut buffer, &room_event_cache, &None).await,
LatestEventValueBuilder::new_local(&update, &mut buffer, &room_event_cache, None, None).await,
LatestEventValue::LocalIsSending => with body = "B"
);
}
@@ -1772,7 +1788,7 @@ mod tests_latest_event_value_builder {
// The `LatestEventValue` matches the new local event.
assert_local_value_matches_room_message_with_body!(
LatestEventValueBuilder::new_local(&update, &mut buffer, &room_event_cache, &None).await,
LatestEventValueBuilder::new_local(&update, &mut buffer, &room_event_cache, None, None).await,
LatestEventValue::LocalIsSending => with body = body
);
}
@@ -1790,7 +1806,7 @@ mod tests_latest_event_value_builder {
// The `LatestEventValue` hasn't changed, it still matches the latest local
// event.
assert_local_value_matches_room_message_with_body!(
LatestEventValueBuilder::new_local(&update, &mut buffer, &room_event_cache, &None).await,
LatestEventValueBuilder::new_local(&update, &mut buffer, &room_event_cache, None, None).await,
LatestEventValue::LocalIsSending => with body = "C"
);
@@ -1807,7 +1823,7 @@ mod tests_latest_event_value_builder {
// The `LatestEventValue` has changed, it matches the previous (so the first)
// local event.
assert_local_value_matches_room_message_with_body!(
LatestEventValueBuilder::new_local(&update, &mut buffer, &room_event_cache, &None).await,
LatestEventValueBuilder::new_local(&update, &mut buffer, &room_event_cache, None, None).await,
LatestEventValue::LocalIsSending => with body = "A"
);
@@ -1824,8 +1840,14 @@ mod tests_latest_event_value_builder {
// The `LatestEventValue` has changed, it's empty!
assert_matches!(
LatestEventValueBuilder::new_local(&update, &mut buffer, &room_event_cache, &None)
.await,
LatestEventValueBuilder::new_local(
&update,
&mut buffer,
&room_event_cache,
None,
None
)
.await,
LatestEventValue::None
);
@@ -1853,7 +1875,7 @@ mod tests_latest_event_value_builder {
// The `LatestEventValue` matches the new local event.
assert_local_value_matches_room_message_with_body!(
LatestEventValueBuilder::new_local(&update, &mut buffer, &room_event_cache, &None).await,
LatestEventValueBuilder::new_local(&update, &mut buffer, &room_event_cache, None, None).await,
LatestEventValue::LocalIsSending => with body = body
);
}
@@ -1872,7 +1894,7 @@ mod tests_latest_event_value_builder {
// The `LatestEventValue` hasn't changed, it still matches the latest local
// event.
assert_local_value_matches_room_message_with_body!(
LatestEventValueBuilder::new_local(&update, &mut buffer, &room_event_cache, &None).await,
LatestEventValueBuilder::new_local(&update, &mut buffer, &room_event_cache, None, None).await,
LatestEventValue::LocalIsSending => with body = "B"
);
@@ -1889,7 +1911,7 @@ mod tests_latest_event_value_builder {
// The `LatestEventValue` hasn't changed.
assert_local_value_matches_room_message_with_body!(
LatestEventValueBuilder::new_local(&update, &mut buffer, &room_event_cache, &None).await,
LatestEventValueBuilder::new_local(&update, &mut buffer, &room_event_cache, None, None).await,
LatestEventValue::LocalIsSending => with body = "B"
);
@@ -1917,7 +1939,7 @@ mod tests_latest_event_value_builder {
// The `LatestEventValue` matches the new local event.
assert_local_value_matches_room_message_with_body!(
LatestEventValueBuilder::new_local(&update, &mut buffer, &room_event_cache, &None).await,
LatestEventValueBuilder::new_local(&update, &mut buffer, &room_event_cache, None, None).await,
LatestEventValue::LocalIsSending => with body = body
);
}
@@ -1943,7 +1965,7 @@ mod tests_latest_event_value_builder {
// The `LatestEventValue` hasn't changed, it still matches the latest local
// event.
assert_local_value_matches_room_message_with_body!(
LatestEventValueBuilder::new_local(&update, &mut buffer, &room_event_cache, &None).await,
LatestEventValueBuilder::new_local(&update, &mut buffer, &room_event_cache, None, None).await,
LatestEventValue::LocalIsSending => with body = "B"
);
@@ -1968,7 +1990,7 @@ mod tests_latest_event_value_builder {
// The `LatestEventValue` has changed, it still matches the latest local
// event but with its new content.
assert_local_value_matches_room_message_with_body!(
LatestEventValueBuilder::new_local(&update, &mut buffer, &room_event_cache, &None).await,
LatestEventValueBuilder::new_local(&update, &mut buffer, &room_event_cache, None, None).await,
LatestEventValue::LocalIsSending => with body = "B."
);
@@ -1994,7 +2016,7 @@ mod tests_latest_event_value_builder {
// The `LatestEventValue` matches the new local event.
assert_local_value_matches_room_message_with_body!(
LatestEventValueBuilder::new_local(&update, &mut buffer, &room_event_cache, &None).await,
LatestEventValueBuilder::new_local(&update, &mut buffer, &room_event_cache, None, None).await,
LatestEventValue::LocalIsSending => with body = "A"
);
@@ -2021,8 +2043,14 @@ mod tests_latest_event_value_builder {
// The `LatestEventValue` has changed!
assert_matches!(
LatestEventValueBuilder::new_local(&update, &mut buffer, &room_event_cache, &None)
.await,
LatestEventValueBuilder::new_local(
&update,
&mut buffer,
&room_event_cache,
None,
None
)
.await,
LatestEventValue::None
);
@@ -2050,7 +2078,7 @@ mod tests_latest_event_value_builder {
// The `LatestEventValue` matches the new local event.
assert_local_value_matches_room_message_with_body!(
LatestEventValueBuilder::new_local(&update, &mut buffer, &room_event_cache, &None).await,
LatestEventValueBuilder::new_local(&update, &mut buffer, &room_event_cache, None, None).await,
LatestEventValue::LocalIsSending => with body = body
);
}
@@ -2070,7 +2098,7 @@ mod tests_latest_event_value_builder {
// The `LatestEventValue` has changed, it still matches the latest local
// event but it's marked as “cannot be sent”.
assert_local_value_matches_room_message_with_body!(
LatestEventValueBuilder::new_local(&update, &mut buffer, &room_event_cache, &None).await,
LatestEventValueBuilder::new_local(&update, &mut buffer, &room_event_cache, None, None).await,
LatestEventValue::LocalCannotBeSent => with body = "B"
);
@@ -2091,7 +2119,7 @@ mod tests_latest_event_value_builder {
// The `LatestEventValue` has changed, it still matches the latest local
// event but it's “is sending”.
assert_local_value_matches_room_message_with_body!(
LatestEventValueBuilder::new_local(&update, &mut buffer, &room_event_cache, &None).await,
LatestEventValueBuilder::new_local(&update, &mut buffer, &room_event_cache, None, None).await,
LatestEventValue::LocalIsSending => with body = "B"
);
@@ -2120,7 +2148,7 @@ mod tests_latest_event_value_builder {
// The `LatestEventValue` matches the new local event.
assert_local_value_matches_room_message_with_body!(
LatestEventValueBuilder::new_local(&update, &mut buffer, &room_event_cache, &None).await,
LatestEventValueBuilder::new_local(&update, &mut buffer, &room_event_cache, None, None).await,
LatestEventValue::LocalIsSending => with body = body
);
}
@@ -2140,7 +2168,7 @@ mod tests_latest_event_value_builder {
// The `LatestEventValue` has changed, it still matches the latest local
// event but it's marked as “cannot be sent”.
assert_local_value_matches_room_message_with_body!(
LatestEventValueBuilder::new_local(&update, &mut buffer, &room_event_cache, &None).await,
LatestEventValueBuilder::new_local(&update, &mut buffer, &room_event_cache, None, None).await,
LatestEventValue::LocalCannotBeSent => with body = "B"
);
@@ -2158,7 +2186,7 @@ mod tests_latest_event_value_builder {
// The `LatestEventValue` has changed, it still matches the latest local
// event but it's “is sending”.
assert_local_value_matches_room_message_with_body!(
LatestEventValueBuilder::new_local(&update, &mut buffer, &room_event_cache, &None).await,
LatestEventValueBuilder::new_local(&update, &mut buffer, &room_event_cache, None, None).await,
LatestEventValue::LocalIsSending => with body = "B"
);
@@ -2186,7 +2214,7 @@ mod tests_latest_event_value_builder {
// The `LatestEventValue` matches the new local event.
assert_local_value_matches_room_message_with_body!(
LatestEventValueBuilder::new_local(&update, &mut buffer, &room_event_cache, &None).await,
LatestEventValueBuilder::new_local(&update, &mut buffer, &room_event_cache, None, None).await,
LatestEventValue::LocalIsSending => with body = "A"
);
@@ -2206,8 +2234,14 @@ mod tests_latest_event_value_builder {
// The `LatestEventValue` has changed somehow, it tells no new
// `LatestEventValue` is computed.
assert_matches!(
LatestEventValueBuilder::new_local(&update, &mut buffer, &room_event_cache, &None)
.await,
LatestEventValueBuilder::new_local(
&update,
&mut buffer,
&room_event_cache,
None,
None
)
.await,
LatestEventValue::None
);
@@ -2274,7 +2308,8 @@ mod tests_latest_event_value_builder {
},
&mut buffer,
&room_event_cache,
&None,
None,
None,
)
.await
=> with body = "hello"
@@ -165,14 +165,14 @@ impl RoomLatestEventsWriteGuard {
// Get it once for all the updates of all the latest events for this room (be
// the room and its threads).
let room = self.inner.weak_room.get();
let power_levels = match &room {
let (own_user_id, power_levels) = match &room {
Some(room) => {
let power_levels = room.power_levels().await.ok();
Some(room.own_user_id()).zip(power_levels)
(Some(room.own_user_id()), power_levels)
}
None => None,
None => (None, None),
};
let inner = &mut *self.inner;
@@ -180,10 +180,14 @@ impl RoomLatestEventsWriteGuard {
let per_thread = &mut inner.per_thread;
let room_event_cache = &inner.room_event_cache;
for_the_room.update_with_event_cache(room_event_cache, &power_levels).await;
for_the_room
.update_with_event_cache(room_event_cache, own_user_id, power_levels.as_ref())
.await;
for latest_event in per_thread.values_mut() {
latest_event.update_with_event_cache(room_event_cache, &power_levels).await;
latest_event
.update_with_event_cache(room_event_cache, own_user_id, power_levels.as_ref())
.await;
}
}
@@ -196,14 +200,14 @@ impl RoomLatestEventsWriteGuard {
// Get it once for all the updates of all the latest events for this room (be
// the room and its threads).
let room = self.inner.weak_room.get();
let power_levels = match &room {
let (own_user_id, power_levels) = match &room {
Some(room) => {
let power_levels = room.power_levels().await.ok();
Some(room.own_user_id()).zip(power_levels)
(Some(room.own_user_id()), power_levels)
}
None => None,
None => (None, None),
};
let inner = &mut *self.inner;
@@ -212,12 +216,22 @@ impl RoomLatestEventsWriteGuard {
let room_event_cache = &inner.room_event_cache;
for_the_room
.update_with_send_queue(send_queue_update, room_event_cache, &power_levels)
.update_with_send_queue(
send_queue_update,
room_event_cache,
own_user_id,
power_levels.as_ref(),
)
.await;
for latest_event in per_thread.values_mut() {
latest_event
.update_with_send_queue(send_queue_update, room_event_cache, &power_levels)
.update_with_send_queue(
send_queue_update,
room_event_cache,
own_user_id,
power_levels.as_ref(),
)
.await;
}
}