@@ -42,16 +42,17 @@ use tracing::{debug, error, field::debug, info, instrument, trace, warn};
4242
4343use super :: {
4444 event_item:: {
45- AnyOtherFullStateEventContent , BundledReactions , EventSendState , EventTimelineItemKind ,
46- LocalEventTimelineItem , Profile , RemoteEventOrigin , RemoteEventTimelineItem ,
45+ AnyOtherFullStateEventContent , BundledReactions , EventItemIdentifier , EventSendState ,
46+ EventTimelineItemKind , LocalEventTimelineItem , Profile , RemoteEventOrigin ,
47+ RemoteEventTimelineItem ,
4748 } ,
4849 find_read_marker,
4950 read_receipts:: maybe_add_implicit_read_receipt,
5051 rfind_event_by_id, rfind_event_item, EventTimelineItem , Message , OtherState , ReactionGroup ,
5152 Sticker , TimelineDetails , TimelineInnerState , TimelineItem , TimelineItemContent ,
5253 VirtualTimelineItem , DEFAULT_SANITIZER_MODE ,
5354} ;
54- use crate :: events:: SyncTimelineEventWithoutContent ;
55+ use crate :: { events:: SyncTimelineEventWithoutContent , timeline :: event_item :: ReactionSenderData } ;
5556
5657#[ derive( Clone ) ]
5758pub ( super ) enum Flow {
@@ -208,11 +209,7 @@ pub(super) struct TimelineEventHandler<'a> {
208209 meta : TimelineEventMetadata ,
209210 flow : Flow ,
210211 items : & ' a mut ObservableVector < Arc < TimelineItem > > ,
211- #[ allow( clippy:: type_complexity) ]
212- reaction_map : & ' a mut HashMap <
213- ( Option < OwnedTransactionId > , Option < OwnedEventId > ) ,
214- ( OwnedUserId , Annotation ) ,
215- > ,
212+ reaction_map : & ' a mut HashMap < EventItemIdentifier , ( ReactionSenderData , Annotation ) > ,
216213 pending_reactions : & ' a mut HashMap < OwnedEventId , IndexSet < OwnedEventId > > ,
217214 fully_read_event : & ' a mut Option < OwnedEventId > ,
218215 event_should_update_fully_read_marker : & ' a mut bool ,
@@ -433,9 +430,11 @@ impl<'a> TimelineEventHandler<'a> {
433430 fn handle_reaction ( & mut self , c : ReactionEventContent ) {
434431 let event_id: & EventId = & c. relates_to . event_id ;
435432 let ( reaction_id, old_txn_id) = match & self . flow {
436- Flow :: Local { txn_id, .. } => ( ( Some ( txn_id. clone ( ) ) , None ) , None ) ,
433+ Flow :: Local { txn_id, .. } => {
434+ ( EventItemIdentifier :: TransactionId ( txn_id. clone ( ) ) , None )
435+ }
437436 Flow :: Remote { event_id, txn_id, .. } => {
438- ( ( None , Some ( event_id. clone ( ) ) ) , txn_id. as_ref ( ) )
437+ ( EventItemIdentifier :: EventId ( event_id. clone ( ) ) , txn_id. as_ref ( ) )
439438 }
440439 } ;
441440
@@ -455,15 +454,22 @@ impl<'a> TimelineEventHandler<'a> {
455454 let reaction_group = reactions. entry ( c. relates_to . key . clone ( ) ) . or_default ( ) ;
456455
457456 if let Some ( txn_id) = old_txn_id {
457+ let id = EventItemIdentifier :: TransactionId ( txn_id. clone ( ) ) ;
458458 // Remove the local echo from the related event.
459- if reaction_group. 0 . remove ( & ( Some ( txn_id . clone ( ) ) , None ) ) . is_none ( ) {
459+ if reaction_group. 0 . remove ( & id ) . is_none ( ) {
460460 warn ! (
461461 "Received reaction with transaction ID, but didn't \
462462 find matching reaction in the related event's reactions"
463463 ) ;
464464 }
465465 }
466- reaction_group. 0 . insert ( reaction_id. clone ( ) , self . meta . sender . clone ( ) ) ;
466+ reaction_group. 0 . insert (
467+ reaction_id. clone ( ) ,
468+ ReactionSenderData {
469+ sender_id : self . meta . sender . clone ( ) ,
470+ timestamp : self . meta . timestamp ,
471+ } ,
472+ ) ;
467473
468474 trace ! ( "Adding reaction" ) ;
469475 self . items . set (
@@ -476,26 +482,31 @@ impl<'a> TimelineEventHandler<'a> {
476482 }
477483 } else {
478484 trace ! ( "Timeline item not found, adding reaction to the pending list" ) ;
479- let ( None , Some ( reaction_event_id) ) = & reaction_id else {
485+ let EventItemIdentifier :: EventId ( reaction_event_id) = reaction_id. clone ( ) else {
480486 error ! ( "Adding local reaction echo to event absent from the timeline" ) ;
481487 return ;
482488 } ;
483489
484490 let pending = self . pending_reactions . entry ( event_id. to_owned ( ) ) . or_default ( ) ;
485491
486- pending. insert ( reaction_event_id. clone ( ) ) ;
492+ pending. insert ( reaction_event_id) ;
487493 }
488494
489495 if let Flow :: Remote { txn_id : Some ( txn_id) , .. } = & self . flow {
496+ let id = EventItemIdentifier :: TransactionId ( txn_id. clone ( ) ) ;
490497 // Remove the local echo from the reaction map.
491- if self . reaction_map . remove ( & ( Some ( txn_id . clone ( ) ) , None ) ) . is_none ( ) {
498+ if self . reaction_map . remove ( & id ) . is_none ( ) {
492499 warn ! (
493500 "Received reaction with transaction ID, but didn't \
494501 find matching reaction in reaction_map"
495502 ) ;
496503 }
497504 }
498- self . reaction_map . insert ( reaction_id, ( self . meta . sender . clone ( ) , c. relates_to ) ) ;
505+ let reaction_sender_data = ReactionSenderData {
506+ sender_id : self . meta . sender . clone ( ) ,
507+ timestamp : self . meta . timestamp ,
508+ } ;
509+ self . reaction_map . insert ( reaction_id, ( reaction_sender_data, c. relates_to ) ) ;
499510 }
500511
501512 #[ instrument( skip_all) ]
@@ -507,7 +518,8 @@ impl<'a> TimelineEventHandler<'a> {
507518 // Redacted redactions are no-ops (unfortunately)
508519 #[ instrument( skip_all, fields( redacts_event_id = ?redacts) ) ]
509520 fn handle_redaction ( & mut self , redacts : OwnedEventId , _content : RoomRedactionEventContent ) {
510- if let Some ( ( _, rel) ) = self . reaction_map . remove ( & ( None , Some ( redacts. clone ( ) ) ) ) {
521+ let id = EventItemIdentifier :: EventId ( redacts. clone ( ) ) ;
522+ if let Some ( ( _, rel) ) = self . reaction_map . remove ( & id) {
511523 update_timeline_item ! ( self , & rel. event_id, "redaction" , |event_item| {
512524 let Some ( remote_event_item) = event_item. as_remote( ) else {
513525 error!( "inconsistent state: redaction received on a non-remote event item" ) ;
@@ -522,7 +534,7 @@ impl<'a> TimelineEventHandler<'a> {
522534 } ;
523535 let group = group_entry. get_mut( ) ;
524536
525- if group. 0 . remove( & ( None , Some ( redacts . clone ( ) ) ) ) . is_none( ) {
537+ if group. 0 . remove( & id ) . is_none( ) {
526538 error!(
527539 "inconsistent state: reaction from reaction_map not in reaction list \
528540 of timeline item"
@@ -543,7 +555,7 @@ impl<'a> TimelineEventHandler<'a> {
543555
544556 if self . result . items_updated == 0 {
545557 if let Some ( reactions) = self . pending_reactions . get_mut ( & rel. event_id ) {
546- if !reactions. remove ( & redacts) {
558+ if !reactions. remove ( & redacts. clone ( ) ) {
547559 error ! (
548560 "inconsistent state: reaction from reaction_map not in reaction list \
549561 of pending_reactions"
@@ -589,7 +601,8 @@ impl<'a> TimelineEventHandler<'a> {
589601 redacts : OwnedTransactionId ,
590602 _content : RoomRedactionEventContent ,
591603 ) {
592- if let Some ( ( _, rel) ) = self . reaction_map . remove ( & ( Some ( redacts. clone ( ) ) , None ) ) {
604+ let id = EventItemIdentifier :: TransactionId ( redacts) ;
605+ if let Some ( ( _, rel) ) = self . reaction_map . remove ( & id) {
593606 update_timeline_item ! ( self , & rel. event_id, "redaction" , |event_item| {
594607 let Some ( remote_event_item) = event_item. as_remote( ) else {
595608 error!( "inconsistent state: redaction received on a non-remote event item" ) ;
@@ -602,7 +615,7 @@ impl<'a> TimelineEventHandler<'a> {
602615 } ;
603616 let group = group_entry. get_mut( ) ;
604617
605- if group. 0 . remove( & ( Some ( redacts . clone ( ) ) , None ) ) . is_none( ) {
618+ if group. 0 . remove( & id ) . is_none( ) {
606619 error!(
607620 "inconsistent state: reaction from reaction_map not in reaction list \
608621 of timeline item"
@@ -941,8 +954,10 @@ impl<'a> TimelineEventHandler<'a> {
941954 let mut bundled = IndexMap :: new ( ) ;
942955
943956 for reaction_event_id in reactions {
944- let reaction_id = ( None , Some ( reaction_event_id) ) ;
945- let Some ( ( sender, annotation) ) = self . reaction_map . get ( & reaction_id) else {
957+ let reaction_id = EventItemIdentifier :: EventId ( reaction_event_id) ;
958+ let Some ( ( reaction_sender_data, annotation) ) =
959+ self . reaction_map . get ( & reaction_id)
960+ else {
946961 error ! (
947962 "inconsistent state: reaction from pending_reactions not in reaction_map"
948963 ) ;
@@ -951,7 +966,7 @@ impl<'a> TimelineEventHandler<'a> {
951966
952967 let group: & mut ReactionGroup =
953968 bundled. entry ( annotation. key . clone ( ) ) . or_default ( ) ;
954- group. 0 . insert ( reaction_id, sender . clone ( ) ) ;
969+ group. 0 . insert ( reaction_id, reaction_sender_data . clone ( ) ) ;
955970 }
956971
957972 Some ( bundled)
0 commit comments