Skip to content

Commit e660de4

Browse files
committed
refactor(timeline): get rid of two uses of meta.reactions.map
1 parent dd2c92d commit e660de4

File tree

2 files changed

+56
-35
lines changed

2 files changed

+56
-35
lines changed

crates/matrix-sdk-ui/src/timeline/controller/aggregations.rs

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ use std::collections::HashMap;
1616

1717
use matrix_sdk::send_queue::SendHandle;
1818
use ruma::{MilliSecondsSinceUnixEpoch, OwnedEventId, OwnedUserId};
19+
use tracing::warn;
1920

2021
use crate::timeline::{
2122
PollState, ReactionInfo, ReactionStatus, TimelineEventItemId, TimelineItemContent,
@@ -45,7 +46,7 @@ pub(crate) enum AggregationKind {
4546

4647
#[derive(Clone, Debug)]
4748
pub(crate) struct Aggregation {
48-
kind: AggregationKind,
49+
pub kind: AggregationKind,
4950
pub own_id: TimelineEventItemId,
5051
}
5152

@@ -131,22 +132,52 @@ impl Aggregation {
131132
pub(crate) struct Aggregations {
132133
/// Mapping of a target event to its list of aggregations.
133134
related_events: HashMap<TimelineEventItemId, Vec<Aggregation>>,
135+
136+
/// Mapping of a related event identifier to its target.
137+
inverted_map: HashMap<TimelineEventItemId, TimelineEventItemId>,
134138
}
135139

136140
impl Aggregations {
137141
pub fn clear(&mut self) {
138142
self.related_events.clear();
143+
self.inverted_map.clear();
139144
}
140145

141146
pub fn add(&mut self, related_to: OwnedEventId, aggregation: Aggregation) {
147+
self.inverted_map
148+
.insert(aggregation.own_id.clone(), TimelineEventItemId::EventId(related_to.clone()));
142149
self.related_events
143150
.entry(TimelineEventItemId::EventId(related_to))
144151
.or_default()
145152
.push(aggregation);
146153
}
147154

148-
pub fn get_mut(&mut self, related_to: &TimelineEventItemId) -> Option<&mut Vec<Aggregation>> {
149-
self.related_events.get_mut(related_to)
155+
/// Is the given id one for a known aggregation to another event?
156+
///
157+
/// If so, returns the target event identifier as well as the aggregation.
158+
pub fn try_remove_aggregation(
159+
&mut self,
160+
aggregation_id: &TimelineEventItemId,
161+
) -> Option<(&TimelineEventItemId, Aggregation)> {
162+
if let Some(found) = self.inverted_map.get(aggregation_id) {
163+
// Find and remove the aggregation in the other mapping.
164+
let aggregation = self.related_events.get_mut(found).and_then(|aggregations| {
165+
if let Some(idx) = aggregations.iter().position(|agg| agg.own_id == *aggregation_id)
166+
{
167+
Some(aggregations.remove(idx))
168+
} else {
169+
None
170+
}
171+
});
172+
173+
if aggregation.is_none() {
174+
warn!("unexpected missing aggregation {aggregation_id:?}: was present in the inverted map, not in the actual map");
175+
}
176+
177+
Some((found, aggregation?))
178+
} else {
179+
None
180+
}
150181
}
151182

152183
pub fn apply(

crates/matrix-sdk-ui/src/timeline/event_handler.rs

Lines changed: 22 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ use ruma::{
5151
use tracing::{debug, error, field::debug, info, instrument, trace, warn};
5252

5353
use super::{
54-
algorithms::rfind_event_by_id,
54+
algorithms::{rfind_event_by_id, rfind_event_by_item_id},
5555
controller::{
5656
Aggregation, AggregationKind, ObservableItemsTransaction, ObservableItemsTransactionEntry,
5757
PendingEdit, PendingEditKind, TimelineMetadata, TimelineStateTransaction,
@@ -1007,41 +1007,31 @@ impl<'a, 'o> TimelineEventHandler<'a, 'o> {
10071007
fn handle_reaction_redaction(&mut self, reaction_id: OwnedEventId) -> bool {
10081008
let reaction_id = TimelineEventItemId::EventId(reaction_id);
10091009

1010-
if let Some(FullReactionKey {
1011-
item: TimelineEventItemId::EventId(reacted_to_event_id),
1012-
key,
1013-
sender,
1014-
}) = self.meta.reactions.map.remove(&reaction_id)
1010+
if let Some((target, aggregation)) =
1011+
self.meta.aggregations.try_remove_aggregation(&reaction_id)
10151012
{
1016-
let Some((item_pos, item)) = rfind_event_by_id(self.items, &reacted_to_event_id) else {
1017-
// The remote event wasn't in the timeline.
1018-
1019-
// Remove any possibly pending reactions to that event, as this redaction would
1020-
// affect them.
1021-
if let Some(aggregations) = self
1022-
.meta
1023-
.aggregations
1024-
.get_mut(&TimelineEventItemId::EventId(reacted_to_event_id))
1025-
{
1026-
if let Some(found) = aggregations
1027-
.iter()
1028-
.enumerate()
1029-
.find_map(|(idx, agg)| (agg.own_id == reaction_id).then_some(idx))
1030-
{
1031-
aggregations.remove(found);
1013+
match &aggregation.kind {
1014+
AggregationKind::Reaction { sender, key, .. } => {
1015+
let Some((item_pos, item)) = rfind_event_by_item_id(&self.items, &target)
1016+
else {
1017+
warn!("missing reacted-to item {target:?}");
1018+
return false;
1019+
};
1020+
let mut reactions = item.content().reactions().clone();
1021+
if reactions.remove_reaction(&sender, &key).is_some() {
1022+
trace!("Removing reaction");
1023+
self.items.replace(item_pos, item.with_reactions(reactions));
1024+
self.result.items_updated += 1;
1025+
return true;
10321026
}
10331027
}
10341028

1035-
// We haven't redacted the reaction.
1036-
return false;
1037-
};
1038-
1039-
let mut reactions = item.content().reactions().clone();
1040-
if reactions.remove_reaction(&sender, &key).is_some() {
1041-
trace!("Removing reaction");
1042-
self.items.replace(item_pos, item.with_reactions(reactions));
1043-
self.result.items_updated += 1;
1044-
return true;
1029+
_ => {
1030+
warn!(
1031+
"unexpected aggregation kind in `handle_reaction_redaction`: {:?}",
1032+
aggregation.kind
1033+
);
1034+
}
10451035
}
10461036
}
10471037

0 commit comments

Comments
 (0)