diff --git a/crates/matrix-sdk-ui/src/timeline/controller/observable_items.rs b/crates/matrix-sdk-ui/src/timeline/controller/observable_items.rs index b204dd67279..5d1094f4c31 100644 --- a/crates/matrix-sdk-ui/src/timeline/controller/observable_items.rs +++ b/crates/matrix-sdk-ui/src/timeline/controller/observable_items.rs @@ -1254,10 +1254,20 @@ impl AllRemoteEvents { /// Shift to the right all timeline item indexes that are equal to or /// greater than `new_timeline_item_index`. fn increment_all_timeline_item_index_after(&mut self, new_timeline_item_index: usize) { - for event_meta in self.0.iter_mut() { + // Traverse items from back to front because: + // - if `new_timeline_item_index` is 0, we need to shift all items anyways, so + // all items must be traversed, + // - otherwise, it's unlikely we want to traverse all items: the item has been + // either inserted or pushed back, so there is no need to traverse the first + // items; we can also break the iteration as soon as all timeline item index + // after `new_timeline_item_index` has been updated. + for event_meta in self.0.iter_mut().rev() { if let Some(timeline_item_index) = event_meta.timeline_item_index.as_mut() { if *timeline_item_index >= new_timeline_item_index { *timeline_item_index += 1; + } else { + // Items are ordered. + break; } } } @@ -1266,10 +1276,20 @@ impl AllRemoteEvents { /// Shift to the left all timeline item indexes that are greater than /// `removed_wtimeline_item_index`. fn decrement_all_timeline_item_index_after(&mut self, removed_timeline_item_index: usize) { - for event_meta in self.0.iter_mut() { + // Traverse items from back to front because: + // - if `new_timeline_item_index` is 0, we need to shift all items anyways, so + // all items must be traversed, + // - otherwise, it's unlikely we want to traverse all items: the item has been + // either inserted or pushed back, so there is no need to traverse the first + // items; we can also break the iteration as soon as all timeline item index + // after `new_timeline_item_index` has been updated. + for event_meta in self.0.iter_mut().rev() { if let Some(timeline_item_index) = event_meta.timeline_item_index.as_mut() { if *timeline_item_index > removed_timeline_item_index { *timeline_item_index -= 1; + } else { + // Items are ordered. + break; } } }