Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(room_list): allow knock state event as latest_event #4170

Merged
merged 3 commits into from
Oct 29, 2024

Conversation

jmartinesp
Copy link
Contributor

This allows clients to display pending knocking requests in the room list items (needed by EXI and EXA).

  • Public API changes documented in changelogs (optional)

Signed-off-by:

@jmartinesp jmartinesp requested a review from a team as a code owner October 25, 2024 14:02
@jmartinesp jmartinesp requested review from stefanceriu and removed request for a team October 25, 2024 14:02
Copy link

codecov bot commented Oct 25, 2024

Codecov Report

Attention: Patch coverage is 90.56604% with 5 lines in your changes missing coverage. Please review.

Project coverage is 84.85%. Comparing base (6752cf7) to head (61f48ba).
Report is 3 commits behind head on main.

Files with missing lines Patch % Lines
crates/matrix-sdk-base/src/client.rs 66.66% 1 Missing ⚠️
crates/matrix-sdk-base/src/latest_event.rs 91.66% 1 Missing ⚠️
crates/matrix-sdk-base/src/rooms/normal.rs 83.33% 1 Missing ⚠️
crates/matrix-sdk-base/src/sliding_sync/mod.rs 90.90% 1 Missing ⚠️
...trix-sdk-ui/src/timeline/event_item/content/mod.rs 91.66% 1 Missing ⚠️
Additional details and impacted files
@@           Coverage Diff           @@
##             main    #4170   +/-   ##
=======================================
  Coverage   84.84%   84.85%           
=======================================
  Files         270      270           
  Lines       28991    29031   +40     
=======================================
+ Hits        24597    24633   +36     
- Misses       4394     4398    +4     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Copy link
Member

@stefanceriu stefanceriu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very nice, lgtm 👌

@jmartinesp
Copy link
Contributor Author

@stefanceriu I added some logic changes in c79eaf0 in case you want to re-review. @bnjbvr let me know if you want to take a look too.

Comment on lines 512 to 522
/// Gets this Room's power levels.
pub async fn power_levels(&self) -> Option<RoomPowerLevels> {
self.store
.get_state_event_static::<RoomPowerLevelsEventContent>(&self.room_id)
.await
.ok()
.flatten()
.and_then(|raw| raw.deserialize().ok())
.map(|ev| ev.power_levels())
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We already have matrix_sdk::Room::room_power_levels, but we needed something at the matrix_sdk_base crate too. Since sdk::Room already has access to the fns in sdk_base::Room, should I just remove the one in sdk and use this one instead?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed, they do the same thing. Can we have this function here return a Result instead, to not silently swallow errors, please? (and we can keep the shorter power_levels name, I like it better 👍)

// can either accept or decline them
if let AnySyncStateEvent::RoomMember(member) = state {
if matches!(member.membership(), MembershipState::Knock) {
let can_accept_or_decline_knocks = match power_levels_info {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it make sense to move this logic to within the RoomPowerLevels, similar to the other can_foos?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure it's worth it, since it'll only be used here (I hope).

@@ -698,14 +698,34 @@ async fn cache_latest_events(
let mut encrypted_events =
Vec::with_capacity(room.latest_encrypted_events.read().unwrap().capacity());

// Try to get room power levels from the current changes
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This feels like a lot of work to do just in case you get a knocked state event, which I presume doesn't happen very often.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, but I didn't find any alternatives other than not implementing this part of the functionality 🫤 . We'd have to change the sync process so we can process these latest events after the client has processed the sync request and saved all the data to the store and I think that would be quite complex.

@@ -158,9 +158,21 @@ impl EventTimelineItem {
let event_id = event.event_id().to_owned();
let is_own = client.user_id().map(|uid| uid == sender).unwrap_or(false);

// Get the room's power levels for calculating the latest event
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here I guess but I'm not sure how heavy it actually is. Does fetching a room and power levels have any potential of introducing slowdowns?

Passing the client into PossibleLatestEvent would be weird and it wouldn't improve the sliding sync part 🤔

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think getting both the room and the state event should be quite lightweight, but I'm not sure how much it could affect performance. The alternative could be to only load them if we reach a knock state event, maybe, although I'd have to change some data structures.

@bnjbvr bnjbvr self-requested a review October 29, 2024 09:00
@bnjbvr
Copy link
Member

bnjbvr commented Oct 29, 2024

I'll do a lightweight review (I promise 😇)

Copy link
Member

@bnjbvr bnjbvr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks!

@@ -37,6 +47,9 @@ pub enum PossibleLatestEvent<'a> {
/// This message is suitable - it's a call notification
YesCallNotify(&'a SyncCallNotifyEvent),

/// This state event is suitable - it's a knock membership change
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/// This state event is suitable - it's a knock membership change
/// This state event is suitable - it's a knock membership change
/// that can be handled by the current user.

Comment on lines 512 to 522
/// Gets this Room's power levels.
pub async fn power_levels(&self) -> Option<RoomPowerLevels> {
self.store
.get_state_event_static::<RoomPowerLevelsEventContent>(&self.room_id)
.await
.ok()
.flatten()
.and_then(|raw| raw.deserialize().ok())
.map(|ev| ev.power_levels())
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed, they do the same thing. Can we have this function here return a Result instead, to not silently swallow errors, please? (and we can keep the shorter power_levels name, I like it better 👍)

Comment on lines 702 to 716
let power_levels_from_changes = || {
let state_changes = changes?.state.get(room_info.room_id())?;
let room_power_levels_state =
state_changes.get(&StateEventType::RoomPowerLevels)?.values().next()?;
match room_power_levels_state.deserialize().ok()? {
AnySyncStateEvent::RoomPowerLevels(ev) => Some(ev.power_levels()),
_ => None,
}
};

// If we didn't get any info, try getting it from local data
let power_levels = match power_levels_from_changes() {
Some(power_levels) => Some(power_levels),
None => room.power_levels().await,
};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Beautiful 🤩

Comment on lines 167 to 170
let room_power_levels_info = match (client.user_id(), power_levels.as_ref()) {
(Some(user_id), Some(power_levels)) => Some((user_id, power_levels)),
_ => None,
};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GOOD NEWS EVERYONE! There's Option::zip() that does exactly the same thing :)

Suggested change
let room_power_levels_info = match (client.user_id(), power_levels.as_ref()) {
(Some(user_id), Some(power_levels)) => Some((user_id, power_levels)),
_ => None,
};
let room_power_levels_info = client.user_id().zip(power_levels.as_ref()));

@jmartinesp jmartinesp force-pushed the misc/add-knock-to-latest-events branch from c79eaf0 to c97b36a Compare October 29, 2024 11:38
This allows clients to display pending knocking requests in the room list items.
…nt user can act on them

That is, if their power level allows them to either invite or kick users.
This has been replaced by `sdk_base::Room::power_levels`, which can also be used from `sdk::Room`
@jmartinesp jmartinesp force-pushed the misc/add-knock-to-latest-events branch from c97b36a to 61f48ba Compare October 29, 2024 11:40
@jmartinesp jmartinesp enabled auto-merge (rebase) October 29, 2024 11:47
@jmartinesp jmartinesp merged commit 0353583 into main Oct 29, 2024
39 checks passed
@jmartinesp jmartinesp deleted the misc/add-knock-to-latest-events branch October 29, 2024 11:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants