ui: Group timeline reaction metadata into a new struct

This commit is contained in:
Jonas Platte
2023-07-19 12:19:17 +02:00
committed by Jonas Platte
parent 340e0b7a03
commit 689d022b7a
3 changed files with 44 additions and 25 deletions

View File

@@ -16,13 +16,13 @@ use std::{collections::HashMap, sync::Arc};
use chrono::{Datelike, Local, TimeZone};
use eyeball_im::ObservableVector;
use indexmap::{map::Entry, IndexMap, IndexSet};
use indexmap::{map::Entry, IndexMap};
use matrix_sdk::deserialized_responses::EncryptionInfo;
use ruma::{
events::{
reaction::ReactionEventContent,
receipt::{Receipt, ReceiptType},
relation::{Annotation, Replacement},
relation::Replacement,
room::{
encrypted::RoomEncryptedEventContent,
member::RoomMemberEventContent,
@@ -51,6 +51,7 @@ use super::{
},
find_read_marker,
item::{new_timeline_item, timeline_item},
reactions::Reactions,
read_receipts::maybe_add_implicit_read_receipt,
rfind_event_by_id, rfind_event_item, EventTimelineItem, Message, OtherState, ReactionGroup,
ReactionSenderData, Sticker, TimelineDetails, TimelineInnerState, TimelineItem,
@@ -214,8 +215,7 @@ pub(super) struct TimelineEventHandler<'a> {
flow: Flow,
items: &'a mut ObservableVector<Arc<TimelineItem>>,
next_internal_id: &'a mut u64,
reaction_map: &'a mut HashMap<EventItemIdentifier, (ReactionSenderData, Annotation)>,
pending_reactions: &'a mut HashMap<OwnedEventId, IndexSet<OwnedEventId>>,
reactions: &'a mut Reactions,
fully_read_event: &'a mut Option<OwnedEventId>,
event_should_update_fully_read_marker: &'a mut bool,
track_read_receipts: bool,
@@ -251,8 +251,7 @@ impl<'a> TimelineEventHandler<'a> {
flow,
items: &mut state.items,
next_internal_id: &mut state.next_internal_id,
reaction_map: &mut state.reaction_map,
pending_reactions: &mut state.pending_reactions,
reactions: &mut state.reactions,
fully_read_event: &mut state.fully_read_event,
event_should_update_fully_read_marker: &mut state.event_should_update_fully_read_marker,
track_read_receipts,
@@ -494,7 +493,7 @@ impl<'a> TimelineEventHandler<'a> {
return;
};
let pending = self.pending_reactions.entry(event_id.to_owned()).or_default();
let pending = self.reactions.pending.entry(event_id.to_owned()).or_default();
pending.insert(reaction_event_id);
}
@@ -502,7 +501,7 @@ impl<'a> TimelineEventHandler<'a> {
if let Flow::Remote { txn_id: Some(txn_id), .. } = &self.flow {
let id = EventItemIdentifier::TransactionId(txn_id.clone());
// Remove the local echo from the reaction map.
if self.reaction_map.remove(&id).is_none() {
if self.reactions.map.remove(&id).is_none() {
warn!(
"Received reaction with transaction ID, but didn't \
find matching reaction in reaction_map"
@@ -513,7 +512,7 @@ impl<'a> TimelineEventHandler<'a> {
sender_id: self.meta.sender.clone(),
timestamp: self.meta.timestamp,
};
self.reaction_map.insert(reaction_id, (reaction_sender_data, c.relates_to));
self.reactions.map.insert(reaction_id, (reaction_sender_data, c.relates_to));
}
#[instrument(skip_all)]
@@ -526,7 +525,7 @@ impl<'a> TimelineEventHandler<'a> {
#[instrument(skip_all, fields(redacts_event_id = ?redacts))]
fn handle_redaction(&mut self, redacts: OwnedEventId, _content: RoomRedactionEventContent) {
let id = EventItemIdentifier::EventId(redacts.clone());
if let Some((_, rel)) = self.reaction_map.remove(&id) {
if let Some((_, rel)) = self.reactions.map.remove(&id) {
update_timeline_item!(self, &rel.event_id, "redaction", |event_item| {
let Some(remote_event_item) = event_item.as_remote() else {
error!("inconsistent state: redaction received on a non-remote event item");
@@ -561,7 +560,7 @@ impl<'a> TimelineEventHandler<'a> {
});
if self.result.items_updated == 0 {
if let Some(reactions) = self.pending_reactions.get_mut(&rel.event_id) {
if let Some(reactions) = self.reactions.pending.get_mut(&rel.event_id) {
if !reactions.remove(&redacts.clone()) {
error!(
"inconsistent state: reaction from reaction_map not in reaction list \
@@ -609,7 +608,7 @@ impl<'a> TimelineEventHandler<'a> {
_content: RoomRedactionEventContent,
) {
let id = EventItemIdentifier::TransactionId(redacts);
if let Some((_, rel)) = self.reaction_map.remove(&id) {
if let Some((_, rel)) = self.reactions.map.remove(&id) {
update_timeline_item!(self, &rel.event_id, "redaction", |event_item| {
let Some(remote_event_item) = event_item.as_remote() else {
error!("inconsistent state: redaction received on a non-remote event item");
@@ -1000,13 +999,13 @@ impl<'a> TimelineEventHandler<'a> {
match &self.flow {
Flow::Local { .. } => None,
Flow::Remote { event_id, .. } => {
let reactions = self.pending_reactions.remove(event_id)?;
let reactions = self.reactions.pending.remove(event_id)?;
let mut bundled = IndexMap::new();
for reaction_event_id in reactions {
let reaction_id = EventItemIdentifier::EventId(reaction_event_id);
let Some((reaction_sender_data, annotation)) =
self.reaction_map.get(&reaction_id)
self.reactions.map.get(&reaction_id)
else {
error!(
"inconsistent state: reaction from pending_reactions not in reaction_map"

View File

@@ -20,7 +20,7 @@ use eyeball_im::{ObservableVector, ObservableVectorEntry, VectorSubscriber};
#[cfg(any(test, feature = "testing"))]
use eyeball_im_util::{FilterMapVectorSubscriber, VectorExt};
use imbl::Vector;
use indexmap::{IndexMap, IndexSet};
use indexmap::IndexMap;
use itertools::Itertools;
#[cfg(all(test, feature = "e2e-encryption"))]
use matrix_sdk::crypto::OlmMachine;
@@ -63,7 +63,7 @@ use super::{
},
event_item::EventItemIdentifier,
item::{new_timeline_item, timeline_item},
reactions::ReactionToggleResult,
reactions::{ReactionToggleResult, Reactions},
rfind_event_by_id, rfind_event_item,
traits::RoomDataProvider,
AnnotationKey, EventSendState, EventTimelineItem, InReplyToDetails, Message, Profile,
@@ -83,11 +83,7 @@ pub(super) struct TimelineInner<P: RoomDataProvider = Room> {
pub(super) struct TimelineInnerState {
pub(super) items: ObservableVector<Arc<TimelineItem>>,
pub(super) next_internal_id: u64,
/// Reaction event / txn ID => sender and reaction data.
pub(super) reaction_map: HashMap<EventItemIdentifier, (ReactionSenderData, Annotation)>,
/// ID of event that is not in the timeline yet => List of reaction event
/// IDs.
pub(super) pending_reactions: HashMap<OwnedEventId, IndexSet<OwnedEventId>>,
pub(super) reactions: Reactions,
pub(super) fully_read_event: Option<OwnedEventId>,
/// Whether the fully-read marker item should try to be updated when an
/// event is added.
@@ -1225,7 +1221,7 @@ impl TimelineInnerState {
pub(super) fn clear(&mut self) {
self.items.clear();
self.reaction_map.clear();
self.reactions.clear();
self.fully_read_event = None;
self.event_should_update_fully_read_marker = false;
}
@@ -1368,7 +1364,7 @@ fn update_timeline_reaction(
// (should the local echo already be up-to-date after event handling?)
if let Some(txn_id) = local_echo_to_remove {
let id = EventItemIdentifier::TransactionId(txn_id.clone());
if state.reaction_map.remove(&id).is_none() {
if state.reactions.map.remove(&id).is_none() {
warn!(
"Tried to remove reaction by transaction ID, but didn't \
find matching reaction in the reaction map"
@@ -1377,7 +1373,7 @@ fn update_timeline_reaction(
}
// Add the remote echo to the reaction_map
if let Some(event_id) = remote_echo_to_add {
state.reaction_map.insert(
state.reactions.map.insert(
EventItemIdentifier::EventId(event_id.clone()),
(reaction_sender_data, annotation.clone()),
);

View File

@@ -12,7 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
use ruma::{MilliSecondsSinceUnixEpoch, OwnedEventId, OwnedTransactionId, OwnedUserId};
use std::collections::HashMap;
use indexmap::IndexSet;
use ruma::{
events::relation::Annotation, MilliSecondsSinceUnixEpoch, OwnedEventId, OwnedTransactionId,
OwnedUserId,
};
use super::event_item::EventItemIdentifier;
/// Data associated with a reaction sender. It can be used to display
/// a details UI component for a reaction with both sender
@@ -25,6 +33,22 @@ pub struct ReactionSenderData {
pub timestamp: MilliSecondsSinceUnixEpoch,
}
#[derive(Debug, Default)]
pub(super) struct Reactions {
/// Reaction event / txn ID => sender and reaction data.
pub(super) map: HashMap<EventItemIdentifier, (ReactionSenderData, Annotation)>,
/// ID of event that is not in the timeline yet => List of reaction event
/// IDs.
pub(super) pending: HashMap<OwnedEventId, IndexSet<OwnedEventId>>,
}
impl Reactions {
pub(super) fn clear(&mut self) {
self.map.clear();
self.pending.clear();
}
}
/// The result of toggling a reaction
///
/// Holds the data required to update the state of the reaction in the timeline