@@ -260,26 +260,6 @@ pub(super) struct TimelineEventHandler<'a, 'o> {
260
260
result : HandleEventResult ,
261
261
}
262
262
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
-
283
263
impl < ' a , ' o > TimelineEventHandler < ' a , ' o > {
284
264
pub ( super ) fn new (
285
265
state : & ' a mut TimelineInnerStateTransaction < ' o > ,
@@ -429,10 +409,10 @@ impl<'a, 'o> TimelineEventHandler<'a, 'o> {
429
409
& mut self ,
430
410
replacement : Replacement < RoomMessageEventContentWithoutRelation > ,
431
411
) {
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 ( ) {
434
414
info ! (
435
- original_sender = ?event_item. sender( ) , edit_sender = ?self . ctx. sender,
415
+ original_sender = ?event_item. sender( ) , edit_sender = ?this . ctx. sender,
436
416
"Edit event applies to another user's timeline item, discarding"
437
417
) ;
438
418
return None ;
@@ -457,14 +437,18 @@ impl<'a, 'o> TimelineEventHandler<'a, 'o> {
457
437
edited : true ,
458
438
} ) ;
459
439
460
- let edit_json = match & self . ctx. flow {
440
+ let edit_json = match & this . ctx . flow {
461
441
Flow :: Local { .. } => None ,
462
442
Flow :: Remote { raw_event, .. } => Some ( raw_event. clone ( ) ) ,
463
443
} ;
464
444
465
445
trace ! ( "Applying edit" ) ;
466
446
Some ( event_item. with_content ( new_content, edit_json) )
467
447
} ) ;
448
+
449
+ if !found {
450
+ debug ! ( "Timeline item not found, discarding edit" ) ;
451
+ }
468
452
}
469
453
470
454
// Redacted reaction events are no-ops so don't need to be handled
@@ -554,10 +538,10 @@ impl<'a, 'o> TimelineEventHandler<'a, 'o> {
554
538
& mut self ,
555
539
replacement : Replacement < NewUnstablePollStartEventContentWithoutRelation > ,
556
540
) {
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 ( ) {
559
543
info ! (
560
- original_sender = ?event_item. sender( ) , edit_sender = ?self . ctx. sender,
544
+ original_sender = ?event_item. sender( ) , edit_sender = ?this . ctx. sender,
561
545
"Edit event applies to another user's timeline item, discarding"
562
546
) ;
563
547
return None ;
@@ -579,14 +563,18 @@ impl<'a, 'o> TimelineEventHandler<'a, 'o> {
579
563
}
580
564
} ;
581
565
582
- let edit_json = match & self . ctx. flow {
566
+ let edit_json = match & this . ctx . flow {
583
567
Flow :: Local { .. } => None ,
584
568
Flow :: Remote { raw_event, .. } => Some ( raw_event. clone ( ) ) ,
585
569
} ;
586
570
587
571
trace ! ( "Applying edit" ) ;
588
572
Some ( event_item. with_content ( new_content, edit_json) )
589
573
} ) ;
574
+
575
+ if !found {
576
+ debug ! ( "Timeline item not found, discarding poll edit" ) ;
577
+ }
590
578
}
591
579
592
580
fn handle_poll_start ( & mut self , c : NewUnstablePollStartEventContent , should_add : bool ) {
@@ -600,52 +588,45 @@ impl<'a, 'o> TimelineEventHandler<'a, 'o> {
600
588
}
601
589
602
590
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 ,
622
597
& 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
+ }
626
611
}
627
612
628
613
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
643
623
}
644
- } ,
645
- not_found: || {
646
- self . meta. poll_pending_events. add_end( & c. relates_to. event_id, self . ctx. timestamp) ;
647
624
}
648
- ) ;
625
+ } ) ;
626
+
627
+ if !found {
628
+ self . meta . poll_pending_events . add_end ( & c. relates_to . event_id , self . ctx . timestamp ) ;
629
+ }
649
630
}
650
631
651
632
// Redacted redactions are no-ops (unfortunately)
@@ -655,8 +636,10 @@ impl<'a, 'o> TimelineEventHandler<'a, 'o> {
655
636
// https://github.com/matrix-org/matrix-rust-sdk/pull/2381#issuecomment-1689647825
656
637
657
638
let id = EventItemIdentifier :: EventId ( redacts. clone ( ) ) ;
639
+
640
+ // Redact the reaction, if any.
658
641
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| {
660
643
let Some ( remote_event_item) = event_item. as_remote ( ) else {
661
644
error ! ( "inconsistent state: redaction received on a non-remote event item" ) ;
662
645
return None ;
@@ -689,6 +672,10 @@ impl<'a, 'o> TimelineEventHandler<'a, 'o> {
689
672
Some ( event_item. with_kind ( remote_event_item. with_reactions ( reactions) ) )
690
673
} ) ;
691
674
675
+ if !found_reacted_to {
676
+ debug ! ( "Timeline item not found, discarding reaction redaction" ) ;
677
+ }
678
+
692
679
if self . result . items_updated == 0 {
693
680
if let Some ( reactions) = self . meta . reactions . pending . get_mut ( & rel. event_id ) {
694
681
if !reactions. swap_remove ( & redacts. clone ( ) ) {
@@ -708,7 +695,7 @@ impl<'a, 'o> TimelineEventHandler<'a, 'o> {
708
695
// implemented) => no early return here.
709
696
}
710
697
711
- update_timeline_item ! ( self , & redacts, "redaction" , | event_item| {
698
+ let found_redacted_event = self . update_timeline_item ( & redacts, |this , event_item| {
712
699
if event_item. as_remote ( ) . is_none ( ) {
713
700
error ! ( "inconsistent state: redaction received on a non-remote event item" ) ;
714
701
return None ;
@@ -719,9 +706,13 @@ impl<'a, 'o> TimelineEventHandler<'a, 'o> {
719
706
return None ;
720
707
}
721
708
722
- Some ( event_item. redact( & self . meta. room_version) )
709
+ Some ( event_item. redact ( & this . meta . room_version ) )
723
710
} ) ;
724
711
712
+ if !found_redacted_event {
713
+ debug ! ( "Timeline item not found, discarding redaction" ) ;
714
+ }
715
+
725
716
if self . result . items_updated == 0 {
726
717
// We will want to know this when debugging redaction issues.
727
718
debug ! ( "redaction affected no event" ) ;
@@ -754,8 +745,10 @@ impl<'a, 'o> TimelineEventHandler<'a, 'o> {
754
745
_content : RoomRedactionEventContent ,
755
746
) {
756
747
let id = EventItemIdentifier :: TransactionId ( redacts) ;
748
+
749
+ // Redact the reaction, if any.
757
750
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| {
759
752
let Some ( remote_event_item) = event_item. as_remote ( ) else {
760
753
error ! ( "inconsistent state: redaction received on a non-remote event item" ) ;
761
754
return None ;
@@ -782,6 +775,10 @@ impl<'a, 'o> TimelineEventHandler<'a, 'o> {
782
775
trace ! ( "Removing reaction" ) ;
783
776
Some ( event_item. with_kind ( remote_event_item. with_reactions ( reactions) ) )
784
777
} ) ;
778
+
779
+ if !found {
780
+ debug ! ( "Timeline item not found, discarding local redaction" ) ;
781
+ }
785
782
}
786
783
787
784
if self . result . items_updated == 0 {
@@ -1120,6 +1117,28 @@ impl<'a, 'o> TimelineEventHandler<'a, 'o> {
1120
1117
}
1121
1118
}
1122
1119
}
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
+ }
1123
1142
}
1124
1143
1125
1144
/// Transfer `TimelineDetails` that weren't available on the original item and
@@ -1139,22 +1158,3 @@ fn transfer_details(item: &mut EventTimelineItem, old_item: &EventTimelineItem)
1139
1158
in_reply_to. event = old_in_reply_to. event . clone ( ) ;
1140
1159
}
1141
1160
}
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