-
Notifications
You must be signed in to change notification settings - Fork 258
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
sdk-base: add Room::pinned_events(&self)
#3747
Conversation
b08d07f
to
1750b00
Compare
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #3747 +/- ##
==========================================
- Coverage 84.02% 84.02% -0.01%
==========================================
Files 260 260
Lines 26729 26737 +8
==========================================
+ Hits 22459 22465 +6
- Misses 4270 4272 +2 ☔ View full report in Codecov by Sentry. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds like you're on the right track! Thanks for writing a test.
@@ -340,6 +340,9 @@ pub struct StateChanges { | |||
/// A map from room id to a map of a display name and a set of user ids that | |||
/// share that display name in the given room. | |||
pub ambiguity_maps: BTreeMap<OwnedRoomId, BTreeMap<String, BTreeSet<OwnedUserId>>>, | |||
|
|||
/// A map of `RoomId` to pinned `OwnedEventId`s for each room. | |||
pub pinned_events: BTreeMap<OwnedRoomId, Vec<OwnedEventId>>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this should be here: this is not stored, and this struct is meant to include things that are to be stored. Instead, you probably want a local variable in the one function that makes use of this pinned_events
field.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed this in eafed32
|
||
/// The list of pinned event ids in this room in an observable format so | ||
/// they can be subscribed to. | ||
pub pinned_event_ids: SharedObservable<Vec<OwnedEventId>>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: not pub
, since there's a getter for a subscriber
Also, would it make sense to use ObservableVector
here? If we did that, and rejigger the API so that we only push new pinned event / remove pinned event, we could have a finer-grained API, but maybe it's not worth it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can try 🤞 .
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ObservableVector
doesn't implement Clone
so it can't be used in Room
, which does.
crates/matrix-sdk-base/src/client.rs
Outdated
if let Some(room) = self.store.room(&room_id) { | ||
room.pinned_event_ids.update(|ids| { | ||
ids.clear(); | ||
ids.append(&mut pinned_event_ids.clone()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🦀 🧑🏫
- Vec::extend can take an iterator of the element type (that's
ids
) - and a
Vec
also has anIntoIter
implementation, so it can be used as the parameter forextend
(here I'm talking aboutpinned_event_ids
).
Combining the two, that gives you a way to avoid the cloning:
ids.append(&mut pinned_event_ids.clone()); | |
ids.extend(pinned_event_ids); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had to use Vector::extend_from_slice
in some places instead, but it's done in 8c43c75
crates/matrix-sdk-base/src/client.rs
Outdated
@@ -1173,6 +1180,15 @@ impl BaseClient { | |||
} | |||
} | |||
|
|||
for (room_id, pinned_event_ids) in changes.pinned_events.clone() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: you shouldn't need the clone()
here, and as said before changes.pinned_events
should be a local variable
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed in 8c43c75
8c43c75
to
0d76899
Compare
I had to add an extra check so the pinned event ids are only emitted if they are different from the previous list. |
Sweet, did you add a test for that too? 🥺 |
The test for this is the previously added one not failing anymore 😅 . |
I actually ended up adding an extra test check and improving how the new values are set. |
/// The list of pinned event ids in this room in an observable format so | ||
/// they can be subscribed to. | ||
pub(crate) pinned_event_ids: SharedObservable<Vec<OwnedEventId>>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So the reason why we usually don't put things in this struct is that they're not persisted after a reload; if you reload a room, you'd have to wait for the next sync to arrive to give you the list of events, and if you happen to be offline, that means that now you don't have access to pinned events.
From here, we have a few possibilities:
- include the
Vec<OwnedEventId>
inRoomInfo
, - include the pinned event in the
BaseRoomInfo
, and have a getter to read the pinned event ids from there - have a new (de)serializable field in
Room
that is filled at startup, and updated as the events come. You've done half of the work here by having it be updated as the events come, and we'd need some way to serialize/deserialize it too later.
My preference would likely go to the first or second option (second option might be faster to ser/de), to benefit from persistence. Can you also add a test that would've failed without this change, please?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, I tried fixing this in 4aa51ca using the 2nd strategy 🤞 .
AnyStrippedStateEvent::RoomPinnedEvents(p) => { | ||
if let Some(pinned) = p.content.pinned.clone() { | ||
self.pinned_events = Some(RoomPinnedEventsEventContent::new(pinned)); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not entirely sure about this part.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Stripped events = for a room in which we're invited. I think your code is fine, we could also decide to store None
there, but this shouldn't matter much 👍 I don't expect one to be able to look at pinned events in an invited room, at least for a first pass.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks!
AnyStrippedStateEvent::RoomPinnedEvents(p) => { | ||
if let Some(pinned) = p.content.pinned.clone() { | ||
self.pinned_events = Some(RoomPinnedEventsEventContent::new(pinned)); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Stripped events = for a room in which we're invited. I think your code is fine, we could also decide to store None
there, but this shouldn't matter much 👍 I don't expect one to be able to look at pinned events in an invited room, at least for a first pass.
@@ -117,6 +118,8 @@ pub struct BaseRoomInfo { | |||
/// others, and this field collects them. | |||
#[serde(skip_serializing_if = "RoomNotableTags::is_empty", default)] | |||
pub(crate) notable_tags: RoomNotableTags, | |||
/// The `m.room.pinned_events` of this room. | |||
pub(crate) pinned_events: Option<RoomPinnedEventsEventContent>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note to self: i think we could have used MinimalStateEvent
here, but it's unclear what's the value of it, so no need to change anything here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can try changing it so it matches the other fields if it's easy to do (I'm not sure how I missed it 🫤 ).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, it does make everything way more complex just to store a possible event id which isn't used anywhere, so it's probably not worth to add it.
Also add `Room::pinned_events(&self)` to get the current pinned events at any time.
4aa51ca
to
3e78ee7
Compare
This can be used to subscribe to pinned event ids in a room.
Implements the first part of #3726.
Signed-off-by: