@@ -501,7 +501,9 @@ impl TimelineInnerStateTransaction<'_> {
501
501
timestamp : Some ( event. origin_server_ts ( ) ) ,
502
502
visible : false ,
503
503
} ;
504
- self . add_event ( event_meta, position, room_data_provider, settings) . await ;
504
+ let _event_added_or_updated = self
505
+ . add_or_update_event ( event_meta, position, room_data_provider, settings)
506
+ . await ;
505
507
506
508
return HandleEventResult :: default ( ) ;
507
509
}
@@ -526,7 +528,9 @@ impl TimelineInnerStateTransaction<'_> {
526
528
timestamp,
527
529
visible : false ,
528
530
} ;
529
- self . add_event ( event_meta, position, room_data_provider, settings) . await ;
531
+ let _event_added_or_updated = self
532
+ . add_or_update_event ( event_meta, position, room_data_provider, settings)
533
+ . await ;
530
534
}
531
535
532
536
return HandleEventResult :: default ( ) ;
@@ -543,7 +547,15 @@ impl TimelineInnerStateTransaction<'_> {
543
547
timestamp : Some ( timestamp) ,
544
548
visible : should_add,
545
549
} ;
546
- self . add_event ( event_meta, position, room_data_provider, settings) . await ;
550
+
551
+ let event_added_or_updated =
552
+ self . add_or_update_event ( event_meta, position, room_data_provider, settings) . await ;
553
+
554
+ // If the event has not been added or updated, it's because it's a duplicated
555
+ // event. Let's return early.
556
+ if !event_added_or_updated {
557
+ return HandleEventResult :: default ( ) ;
558
+ }
547
559
548
560
let sender_profile = room_data_provider. profile_from_user_id ( & sender) . await ;
549
561
let ctx = TimelineEventContext {
@@ -637,23 +649,37 @@ impl TimelineInnerStateTransaction<'_> {
637
649
items. commit ( ) ;
638
650
}
639
651
640
- async fn add_event < P : RoomDataProvider > (
652
+ /// Add or update an event in the [`TimelineInnerMeta::all_events`]
653
+ /// collection.
654
+ ///
655
+ /// This method also adjusts read receipt if needed.
656
+ ///
657
+ /// It returns `true` if the event has been added or updated, `false`
658
+ /// otherwise. The latter happens if the event already exists, i.e. if
659
+ /// an existing event is requested to be added.
660
+ async fn add_or_update_event < P : RoomDataProvider > (
641
661
& mut self ,
642
662
event_meta : FullEventMeta < ' _ > ,
643
663
position : TimelineItemPosition ,
644
664
room_data_provider : & P ,
645
665
settings : & TimelineInnerSettings ,
646
- ) {
666
+ ) -> bool {
667
+ // Detect if an event already exists in [`TimelineInnerMeta::all_events`]
668
+ fn event_already_exists ( new_event_id : & EventId , all_events : & VecDeque < EventMeta > ) -> bool {
669
+ all_events. iter ( ) . any ( |EventMeta { event_id, .. } | event_id == new_event_id)
670
+ }
671
+
647
672
match position {
648
673
TimelineItemPosition :: Start { .. } => {
674
+ if event_already_exists ( event_meta. event_id , & self . meta . all_events ) {
675
+ return false ;
676
+ }
677
+
649
678
self . meta . all_events . push_front ( event_meta. base_meta ( ) )
650
679
}
651
680
TimelineItemPosition :: End { .. } => {
652
- // Handle duplicated event.
653
- if let Some ( pos) =
654
- self . meta . all_events . iter ( ) . position ( |ev| ev. event_id == event_meta. event_id )
655
- {
656
- self . meta . all_events . remove ( pos) ;
681
+ if event_already_exists ( event_meta. event_id , & self . meta . all_events ) {
682
+ return false ;
657
683
}
658
684
659
685
self . meta . all_events . push_back ( event_meta. base_meta ( ) ) ;
@@ -686,6 +712,8 @@ impl TimelineInnerStateTransaction<'_> {
686
712
687
713
self . maybe_add_implicit_read_receipt ( event_meta) ;
688
714
}
715
+
716
+ true
689
717
}
690
718
691
719
fn adjust_day_dividers ( & mut self , mut adjuster : DayDividerAdjuster ) {
0 commit comments