@@ -260,26 +260,6 @@ pub(super) struct TimelineEventHandler<'a, 'o> {
260260 result : HandleEventResult ,
261261}
262262
263- // This is a macro instead of a method plus free fn so the borrow checker can
264- // "see through" it, allowing borrows of TimelineEventHandler fields other than
265- // `timeline_items` and `items_updated` in the update closure.
266- macro_rules! update_timeline_item {
267- ( $this: ident, $event_id: expr, found: $found: expr, not_found: $not_found: expr) => {
268- _update_timeline_item(
269- & mut $this. items,
270- & mut $this. result. items_updated,
271- $event_id,
272- $found,
273- $not_found,
274- )
275- } ;
276- ( $this: ident, $event_id: expr, $action: expr, $found: expr) => {
277- update_timeline_item!( $this, $event_id, found: $found, not_found: || {
278- debug!( "Timeline item not found, discarding {}" , $action) ;
279- } ) ;
280- } ;
281- }
282-
283263impl < ' a , ' o > TimelineEventHandler < ' a , ' o > {
284264 pub ( super ) fn new (
285265 state : & ' a mut TimelineInnerStateTransaction < ' o > ,
@@ -429,10 +409,10 @@ impl<'a, 'o> TimelineEventHandler<'a, 'o> {
429409 & mut self ,
430410 replacement : Replacement < RoomMessageEventContentWithoutRelation > ,
431411 ) {
432- update_timeline_item ! ( self , & replacement. event_id, "edit" , | event_item| {
433- if self . ctx. sender != event_item. sender( ) {
412+ let found = self . update_timeline_item ( & replacement. event_id , |this , event_item| {
413+ if this . ctx . sender != event_item. sender ( ) {
434414 info ! (
435- original_sender = ?event_item. sender( ) , edit_sender = ?self . ctx. sender,
415+ original_sender = ?event_item. sender( ) , edit_sender = ?this . ctx. sender,
436416 "Edit event applies to another user's timeline item, discarding"
437417 ) ;
438418 return None ;
@@ -457,14 +437,18 @@ impl<'a, 'o> TimelineEventHandler<'a, 'o> {
457437 edited : true ,
458438 } ) ;
459439
460- let edit_json = match & self . ctx. flow {
440+ let edit_json = match & this . ctx . flow {
461441 Flow :: Local { .. } => None ,
462442 Flow :: Remote { raw_event, .. } => Some ( raw_event. clone ( ) ) ,
463443 } ;
464444
465445 trace ! ( "Applying edit" ) ;
466446 Some ( event_item. with_content ( new_content, edit_json) )
467447 } ) ;
448+
449+ if !found {
450+ debug ! ( "Timeline item not found, discarding edit" ) ;
451+ }
468452 }
469453
470454 // Redacted reaction events are no-ops so don't need to be handled
@@ -554,10 +538,10 @@ impl<'a, 'o> TimelineEventHandler<'a, 'o> {
554538 & mut self ,
555539 replacement : Replacement < NewUnstablePollStartEventContentWithoutRelation > ,
556540 ) {
557- update_timeline_item ! ( self , & replacement. event_id, "poll edit" , | event_item| {
558- if self . ctx. sender != event_item. sender( ) {
541+ let found = self . update_timeline_item ( & replacement. event_id , |this , event_item| {
542+ if this . ctx . sender != event_item. sender ( ) {
559543 info ! (
560- original_sender = ?event_item. sender( ) , edit_sender = ?self . ctx. sender,
544+ original_sender = ?event_item. sender( ) , edit_sender = ?this . ctx. sender,
561545 "Edit event applies to another user's timeline item, discarding"
562546 ) ;
563547 return None ;
@@ -579,14 +563,18 @@ impl<'a, 'o> TimelineEventHandler<'a, 'o> {
579563 }
580564 } ;
581565
582- let edit_json = match & self . ctx. flow {
566+ let edit_json = match & this . ctx . flow {
583567 Flow :: Local { .. } => None ,
584568 Flow :: Remote { raw_event, .. } => Some ( raw_event. clone ( ) ) ,
585569 } ;
586570
587571 trace ! ( "Applying edit" ) ;
588572 Some ( event_item. with_content ( new_content, edit_json) )
589573 } ) ;
574+
575+ if !found {
576+ debug ! ( "Timeline item not found, discarding poll edit" ) ;
577+ }
590578 }
591579
592580 fn handle_poll_start ( & mut self , c : NewUnstablePollStartEventContent , should_add : bool ) {
@@ -600,52 +588,45 @@ impl<'a, 'o> TimelineEventHandler<'a, 'o> {
600588 }
601589
602590 fn handle_poll_response ( & mut self , c : UnstablePollResponseEventContent ) {
603- update_timeline_item ! (
604- self ,
605- & c. relates_to. event_id,
606- found: |event_item| {
607- let poll_state = as_variant!( event_item. content( ) , TimelineItemContent :: Poll ) ?;
608- Some ( event_item. with_content(
609- TimelineItemContent :: Poll ( poll_state. add_response(
610- & self . ctx. sender,
611- self . ctx. timestamp,
612- & c,
613- ) ) ,
614- None ,
615- ) )
616- } ,
617- not_found: || {
618- self . meta. poll_pending_events. add_response(
619- & c. relates_to. event_id,
620- & self . ctx. sender,
621- self . ctx. timestamp,
591+ let found = self . update_timeline_item ( & c. relates_to . event_id , |this, event_item| {
592+ let poll_state = as_variant ! ( event_item. content( ) , TimelineItemContent :: Poll ) ?;
593+ Some ( event_item. with_content (
594+ TimelineItemContent :: Poll ( poll_state. add_response (
595+ & this. ctx . sender ,
596+ this. ctx . timestamp ,
622597 & c,
623- ) ;
624- }
625- ) ;
598+ ) ) ,
599+ None ,
600+ ) )
601+ } ) ;
602+
603+ if !found {
604+ self . meta . poll_pending_events . add_response (
605+ & c. relates_to . event_id ,
606+ & self . ctx . sender ,
607+ self . ctx . timestamp ,
608+ & c,
609+ ) ;
610+ }
626611 }
627612
628613 fn handle_poll_end ( & mut self , c : UnstablePollEndEventContent ) {
629- update_timeline_item ! (
630- self ,
631- & c. relates_to. event_id,
632- found: |event_item| {
633- let poll_state = as_variant!( event_item. content( ) , TimelineItemContent :: Poll ) ?;
634- match poll_state. end( self . ctx. timestamp) {
635- Ok ( poll_state) => Some ( event_item. with_content(
636- TimelineItemContent :: Poll ( poll_state) ,
637- None
638- ) ) ,
639- Err ( _) => {
640- info!( "Got multiple poll end events, discarding" ) ;
641- None
642- } ,
614+ let found = self . update_timeline_item ( & c. relates_to . event_id , |this, event_item| {
615+ let poll_state = as_variant ! ( event_item. content( ) , TimelineItemContent :: Poll ) ?;
616+ match poll_state. end ( this. ctx . timestamp ) {
617+ Ok ( poll_state) => {
618+ Some ( event_item. with_content ( TimelineItemContent :: Poll ( poll_state) , None ) )
619+ }
620+ Err ( _) => {
621+ info ! ( "Got multiple poll end events, discarding" ) ;
622+ None
643623 }
644- } ,
645- not_found: || {
646- self . meta. poll_pending_events. add_end( & c. relates_to. event_id, self . ctx. timestamp) ;
647624 }
648- ) ;
625+ } ) ;
626+
627+ if !found {
628+ self . meta . poll_pending_events . add_end ( & c. relates_to . event_id , self . ctx . timestamp ) ;
629+ }
649630 }
650631
651632 // Redacted redactions are no-ops (unfortunately)
@@ -655,8 +636,10 @@ impl<'a, 'o> TimelineEventHandler<'a, 'o> {
655636 // https://github.com/matrix-org/matrix-rust-sdk/pull/2381#issuecomment-1689647825
656637
657638 let id = EventItemIdentifier :: EventId ( redacts. clone ( ) ) ;
639+
640+ // Redact the reaction, if any.
658641 if let Some ( ( _, rel) ) = self . meta . reactions . map . remove ( & id) {
659- update_timeline_item ! ( self , & rel. event_id, "redaction" , | event_item| {
642+ let found_reacted_to = self . update_timeline_item ( & rel. event_id , |_this , event_item| {
660643 let Some ( remote_event_item) = event_item. as_remote ( ) else {
661644 error ! ( "inconsistent state: redaction received on a non-remote event item" ) ;
662645 return None ;
@@ -689,6 +672,10 @@ impl<'a, 'o> TimelineEventHandler<'a, 'o> {
689672 Some ( event_item. with_kind ( remote_event_item. with_reactions ( reactions) ) )
690673 } ) ;
691674
675+ if !found_reacted_to {
676+ debug ! ( "Timeline item not found, discarding reaction redaction" ) ;
677+ }
678+
692679 if self . result . items_updated == 0 {
693680 if let Some ( reactions) = self . meta . reactions . pending . get_mut ( & rel. event_id ) {
694681 if !reactions. swap_remove ( & redacts. clone ( ) ) {
@@ -708,7 +695,7 @@ impl<'a, 'o> TimelineEventHandler<'a, 'o> {
708695 // implemented) => no early return here.
709696 }
710697
711- update_timeline_item ! ( self , & redacts, "redaction" , | event_item| {
698+ let found_redacted_event = self . update_timeline_item ( & redacts, |this , event_item| {
712699 if event_item. as_remote ( ) . is_none ( ) {
713700 error ! ( "inconsistent state: redaction received on a non-remote event item" ) ;
714701 return None ;
@@ -719,9 +706,13 @@ impl<'a, 'o> TimelineEventHandler<'a, 'o> {
719706 return None ;
720707 }
721708
722- Some ( event_item. redact( & self . meta. room_version) )
709+ Some ( event_item. redact ( & this . meta . room_version ) )
723710 } ) ;
724711
712+ if !found_redacted_event {
713+ debug ! ( "Timeline item not found, discarding redaction" ) ;
714+ }
715+
725716 if self . result . items_updated == 0 {
726717 // We will want to know this when debugging redaction issues.
727718 debug ! ( "redaction affected no event" ) ;
@@ -754,8 +745,10 @@ impl<'a, 'o> TimelineEventHandler<'a, 'o> {
754745 _content : RoomRedactionEventContent ,
755746 ) {
756747 let id = EventItemIdentifier :: TransactionId ( redacts) ;
748+
749+ // Redact the reaction, if any.
757750 if let Some ( ( _, rel) ) = self . meta . reactions . map . remove ( & id) {
758- update_timeline_item ! ( self , & rel. event_id, "redaction" , | event_item| {
751+ let found = self . update_timeline_item ( & rel. event_id , |_this , event_item| {
759752 let Some ( remote_event_item) = event_item. as_remote ( ) else {
760753 error ! ( "inconsistent state: redaction received on a non-remote event item" ) ;
761754 return None ;
@@ -782,6 +775,10 @@ impl<'a, 'o> TimelineEventHandler<'a, 'o> {
782775 trace ! ( "Removing reaction" ) ;
783776 Some ( event_item. with_kind ( remote_event_item. with_reactions ( reactions) ) )
784777 } ) ;
778+
779+ if !found {
780+ debug ! ( "Timeline item not found, discarding local redaction" ) ;
781+ }
785782 }
786783
787784 if self . result . items_updated == 0 {
@@ -1120,6 +1117,28 @@ impl<'a, 'o> TimelineEventHandler<'a, 'o> {
11201117 }
11211118 }
11221119 }
1120+
1121+ /// Updates the given timeline item.
1122+ ///
1123+ /// Returns true iff the item has been found (not necessarily updated),
1124+ /// false if it's not been found.
1125+ fn update_timeline_item (
1126+ & mut self ,
1127+ event_id : & EventId ,
1128+ update : impl FnOnce ( & Self , & EventTimelineItem ) -> Option < EventTimelineItem > ,
1129+ ) -> bool {
1130+ if let Some ( ( idx, item) ) = rfind_event_by_id ( self . items , event_id) {
1131+ trace ! ( "Found timeline item to update" ) ;
1132+ if let Some ( new_item) = update ( self , item. inner ) {
1133+ trace ! ( "Updating item" ) ;
1134+ self . items . set ( idx, TimelineItem :: new ( new_item, item. internal_id ) ) ;
1135+ self . result . items_updated += 1 ;
1136+ }
1137+ true
1138+ } else {
1139+ false
1140+ }
1141+ }
11231142}
11241143
11251144/// Transfer `TimelineDetails` that weren't available on the original item and
@@ -1139,22 +1158,3 @@ fn transfer_details(item: &mut EventTimelineItem, old_item: &EventTimelineItem)
11391158 in_reply_to. event = old_in_reply_to. event . clone ( ) ;
11401159 }
11411160}
1142-
1143- fn _update_timeline_item (
1144- items : & mut ObservableVectorTransaction < ' _ , Arc < TimelineItem > > ,
1145- items_updated : & mut u16 ,
1146- event_id : & EventId ,
1147- update : impl FnOnce ( & EventTimelineItem ) -> Option < EventTimelineItem > ,
1148- not_found : impl FnOnce ( ) ,
1149- ) {
1150- if let Some ( ( idx, item) ) = rfind_event_by_id ( items, event_id) {
1151- trace ! ( "Found timeline item to update" ) ;
1152- if let Some ( new_item) = update ( item. inner ) {
1153- trace ! ( "Updating item" ) ;
1154- items. set ( idx, TimelineItem :: new ( new_item, item. internal_id ) ) ;
1155- * items_updated += 1 ;
1156- }
1157- } else {
1158- not_found ( )
1159- }
1160- }
0 commit comments