From f4a6d129795ca63eb59c9461ee15fe90a8302637 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Thu, 2 Oct 2025 11:24:35 +0200 Subject: [PATCH] refactor(sdk): Split `power_levels` in `latest_event`. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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`. --- .../src/latest_events/latest_event.rs | 155 +++++++++++------- .../src/latest_events/room_latest_events.rs | 34 ++-- 2 files changed, 119 insertions(+), 70 deletions(-) diff --git a/crates/matrix-sdk/src/latest_events/latest_event.rs b/crates/matrix-sdk/src/latest_events/latest_event.rs index e26503f9c..bda5608ec 100644 --- a/crates/matrix-sdk/src/latest_events/latest_event.rs +++ b/crates/matrix-sdk/src/latest_events/latest_event.rs @@ -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" diff --git a/crates/matrix-sdk/src/latest_events/room_latest_events.rs b/crates/matrix-sdk/src/latest_events/room_latest_events.rs index 44854bf58..242edb84d 100644 --- a/crates/matrix-sdk/src/latest_events/room_latest_events.rs +++ b/crates/matrix-sdk/src/latest_events/room_latest_events.rs @@ -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; } }