1use std::{
16 cmp::Ordering,
17 collections::{vec_deque::Iter, VecDeque},
18 ops::{Deref, RangeBounds},
19 sync::Arc,
20};
21
22use eyeball_im::{
23 ObservableVector, ObservableVectorEntries, ObservableVectorEntry, ObservableVectorTransaction,
24 ObservableVectorTransactionEntry, VectorSubscriber,
25};
26use imbl::Vector;
27use ruma::EventId;
28
29use super::{metadata::EventMeta, TimelineItem};
30
31#[derive(Debug)]
35pub struct ObservableItems {
36 items: ObservableVector<Arc<TimelineItem>>,
44
45 all_remote_events: AllRemoteEvents,
53}
54
55impl ObservableItems {
56 pub fn new() -> Self {
58 Self {
59 items: ObservableVector::with_capacity(32),
63 all_remote_events: AllRemoteEvents::default(),
64 }
65 }
66
67 pub fn all_remote_events(&self) -> &AllRemoteEvents {
69 &self.all_remote_events
70 }
71
72 pub fn is_empty(&self) -> bool {
74 self.items.is_empty()
75 }
76
77 pub fn subscribe(&self) -> VectorSubscriber<Arc<TimelineItem>> {
79 self.items.subscribe()
80 }
81
82 pub fn clone_items(&self) -> Vector<Arc<TimelineItem>> {
86 self.items.clone()
87 }
88
89 pub fn transaction(&mut self) -> ObservableItemsTransaction<'_> {
91 ObservableItemsTransaction {
92 items: self.items.transaction(),
93 all_remote_events: &mut self.all_remote_events,
94 }
95 }
96
97 pub fn replace(
104 &mut self,
105 timeline_item_index: usize,
106 timeline_item: Arc<TimelineItem>,
107 ) -> Arc<TimelineItem> {
108 self.items.set(timeline_item_index, timeline_item)
109 }
110
111 pub fn entries(&mut self) -> ObservableItemsEntries<'_> {
113 ObservableItemsEntries(self.items.entries())
114 }
115
116 pub fn for_each<F>(&mut self, mut f: F)
119 where
120 F: FnMut(ObservableItemsEntry<'_>),
121 {
122 self.items.for_each(|entry| f(ObservableItemsEntry(entry)))
123 }
124}
125
126impl Deref for ObservableItems {
132 type Target = Vector<Arc<TimelineItem>>;
133
134 fn deref(&self) -> &Self::Target {
135 &self.items
136 }
137}
138
139pub struct ObservableItemsEntries<'a>(ObservableVectorEntries<'a, Arc<TimelineItem>>);
146
147impl ObservableItemsEntries<'_> {
148 pub fn next(&mut self) -> Option<ObservableItemsEntry<'_>> {
151 self.0.next().map(ObservableItemsEntry)
152 }
153}
154
155#[derive(Debug)]
157pub struct ObservableItemsEntry<'a>(ObservableVectorEntry<'a, Arc<TimelineItem>>);
158
159impl ObservableItemsEntry<'_> {
160 pub fn replace(this: &mut Self, timeline_item: Arc<TimelineItem>) -> Arc<TimelineItem> {
162 ObservableVectorEntry::set(&mut this.0, timeline_item)
163 }
164}
165
166impl Deref for ObservableItemsEntry<'_> {
172 type Target = Arc<TimelineItem>;
173
174 fn deref(&self) -> &Self::Target {
175 &self.0
176 }
177}
178
179#[derive(Debug)]
186pub struct ObservableItemsTransaction<'observable_items> {
187 items: ObservableVectorTransaction<'observable_items, Arc<TimelineItem>>,
188 all_remote_events: &'observable_items mut AllRemoteEvents,
189}
190
191impl<'observable_items> ObservableItemsTransaction<'observable_items> {
192 pub fn get(&self, timeline_item_index: usize) -> Option<&Arc<TimelineItem>> {
194 self.items.get(timeline_item_index)
195 }
196
197 pub fn all_remote_events(&self) -> &AllRemoteEvents {
199 self.all_remote_events
200 }
201
202 pub fn remove_remote_event(&mut self, event_index: usize) -> Option<EventMeta> {
206 self.all_remote_events.remove(event_index)
207 }
208
209 pub fn push_front_remote_event(&mut self, event_meta: EventMeta) {
213 self.all_remote_events.push_front(event_meta);
214 }
215
216 pub fn push_back_remote_event(&mut self, event_meta: EventMeta) {
220 self.all_remote_events.push_back(event_meta);
221 }
222
223 pub fn insert_remote_event(&mut self, event_index: usize, event_meta: EventMeta) {
227 self.all_remote_events.insert(event_index, event_meta);
228 }
229
230 pub fn get_remote_event_by_event_id_mut(
232 &mut self,
233 event_id: &EventId,
234 ) -> Option<&mut EventMeta> {
235 self.all_remote_events.get_by_event_id_mut(event_id)
236 }
237
238 pub fn get_remote_event_by_event_id(&self, event_id: &EventId) -> Option<&EventMeta> {
240 self.all_remote_events.get_by_event_id(event_id)
241 }
242
243 pub fn replace(
246 &mut self,
247 timeline_item_index: usize,
248 timeline_item: Arc<TimelineItem>,
249 ) -> Arc<TimelineItem> {
250 self.items.set(timeline_item_index, timeline_item)
251 }
252
253 pub fn remove(&mut self, timeline_item_index: usize) -> Arc<TimelineItem> {
255 let removed_timeline_item = self.items.remove(timeline_item_index);
256 self.all_remote_events.timeline_item_has_been_removed_at(timeline_item_index);
257
258 removed_timeline_item
259 }
260
261 pub fn insert(
270 &mut self,
271 timeline_item_index: usize,
272 timeline_item: Arc<TimelineItem>,
273 event_index: Option<usize>,
274 ) {
275 self.items.insert(timeline_item_index, timeline_item);
276 self.all_remote_events.timeline_item_has_been_inserted_at(timeline_item_index, event_index);
277 }
278
279 pub fn push_front(&mut self, timeline_item: Arc<TimelineItem>, event_index: Option<usize>) {
288 self.items.push_front(timeline_item);
289 self.all_remote_events.timeline_item_has_been_inserted_at(0, event_index);
290 }
291
292 pub fn push_back(&mut self, timeline_item: Arc<TimelineItem>, event_index: Option<usize>) {
301 self.items.push_back(timeline_item);
302 self.all_remote_events
303 .timeline_item_has_been_inserted_at(self.items.len().saturating_sub(1), event_index);
304 }
305
306 pub fn clear(&mut self) {
308 self.items.clear();
309 self.all_remote_events.clear();
310 }
311
312 pub fn for_each<F>(&mut self, mut f: F)
315 where
316 F: FnMut(ObservableItemsTransactionEntry<'_, 'observable_items>),
317 {
318 self.items.for_each(|entry| {
319 f(ObservableItemsTransactionEntry { entry, all_remote_events: self.all_remote_events })
320 })
321 }
322
323 pub fn commit(self) {
326 self.items.commit()
327 }
328}
329
330impl Deref for ObservableItemsTransaction<'_> {
336 type Target = Vector<Arc<TimelineItem>>;
337
338 fn deref(&self) -> &Self::Target {
339 &self.items
340 }
341}
342
343pub struct ObservableItemsTransactionEntry<'observable_transaction_items, 'observable_items> {
345 entry: ObservableVectorTransactionEntry<
346 'observable_transaction_items,
347 'observable_items,
348 Arc<TimelineItem>,
349 >,
350 all_remote_events: &'observable_transaction_items mut AllRemoteEvents,
351}
352
353impl ObservableItemsTransactionEntry<'_, '_> {
354 pub fn remove(this: Self) {
356 let entry_index = ObservableVectorTransactionEntry::index(&this.entry);
357
358 ObservableVectorTransactionEntry::remove(this.entry);
359 this.all_remote_events.timeline_item_has_been_removed_at(entry_index);
360 }
361}
362
363impl Deref for ObservableItemsTransactionEntry<'_, '_> {
369 type Target = Arc<TimelineItem>;
370
371 fn deref(&self) -> &Self::Target {
372 &self.entry
373 }
374}
375
376#[cfg(test)]
377mod observable_items_tests {
378 use std::ops::Not;
379
380 use assert_matches::assert_matches;
381 use eyeball_im::VectorDiff;
382 use ruma::{
383 events::room::message::{MessageType, TextMessageEventContent},
384 owned_user_id, MilliSecondsSinceUnixEpoch,
385 };
386 use stream_assert::assert_next_matches;
387
388 use super::*;
389 use crate::timeline::{
390 controller::{EventTimelineItemKind, RemoteEventOrigin},
391 event_item::RemoteEventTimelineItem,
392 EventTimelineItem, Message, MsgLikeContent, MsgLikeKind, TimelineDetails,
393 TimelineItemContent, TimelineUniqueId,
394 };
395
396 fn item(event_id: &str) -> Arc<TimelineItem> {
397 TimelineItem::new(
398 EventTimelineItem::new(
399 owned_user_id!("@ivan:mnt.io"),
400 TimelineDetails::Unavailable,
401 MilliSecondsSinceUnixEpoch(0u32.into()),
402 TimelineItemContent::MsgLike(MsgLikeContent {
403 kind: MsgLikeKind::Message(Message {
404 msgtype: MessageType::Text(TextMessageEventContent::plain("hello")),
405 edited: false,
406 mentions: None,
407 }),
408 reactions: Default::default(),
409 thread_root: None,
410 in_reply_to: None,
411 }),
412 EventTimelineItemKind::Remote(RemoteEventTimelineItem {
413 event_id: event_id.parse().unwrap(),
414 transaction_id: None,
415 read_receipts: Default::default(),
416 is_own: false,
417 is_highlighted: false,
418 encryption_info: None,
419 original_json: None,
420 latest_edit_json: None,
421 origin: RemoteEventOrigin::Sync,
422 }),
423 false,
424 ),
425 TimelineUniqueId(format!("__id_{event_id}")),
426 )
427 }
428
429 fn read_marker() -> Arc<TimelineItem> {
430 TimelineItem::read_marker()
431 }
432
433 fn event_meta(event_id: &str) -> EventMeta {
434 EventMeta { event_id: event_id.parse().unwrap(), timeline_item_index: None, visible: false }
435 }
436
437 macro_rules! assert_event_id {
438 ( $timeline_item:expr, $event_id:literal $( , $message:expr )? $(,)? ) => {
439 assert_eq!($timeline_item.as_event().unwrap().event_id().unwrap().as_str(), $event_id $( , $message)? );
440 };
441 }
442
443 macro_rules! assert_mapping {
444 ( on $transaction:ident:
445 | event_id | event_index | timeline_item_index |
446 | $( - )+ | $( - )+ | $( - )+ |
447 $(
448 | $event_id:literal | $event_index:literal | $( $timeline_item_index:literal )? |
449 )+
450 ) => {
451 let all_remote_events = $transaction .all_remote_events();
452
453 $(
454 assert_matches!(all_remote_events.0.get( $event_index ), Some(EventMeta { event_id, timeline_item_index, .. }) => {
456 assert_eq!(
458 event_id.as_str(),
459 $event_id ,
460 concat!("event #", $event_index, " should have ID ", $event_id)
461 );
462
463
464 #[allow(unused_variables)]
466 let timeline_item_index_is_expected = false;
467 $(
468 let timeline_item_index_is_expected = true;
469 let _ = $timeline_item_index;
470 )?
471
472 if timeline_item_index_is_expected.not() {
473 assert!(
475 timeline_item_index.is_none(),
476 concat!("event #", $event_index, " with ID ", $event_id, " should NOT map to a timeline item index" )
477 );
478 }
479
480 $(
481 assert_eq!(
483 *timeline_item_index,
484 Some( $timeline_item_index ),
485 concat!("event #", $event_index, " with ID ", $event_id, " should map to timeline item #", $timeline_item_index )
486 );
487
488 assert_matches!( $transaction .get( $timeline_item_index ), Some(timeline_item) => {
490 assert_event_id!(
492 timeline_item,
493 $event_id ,
494 concat!("timeline item #", $timeline_item_index, " should map to event ID ", $event_id )
495 );
496 });
497 )?
498 });
499 )*
500 }
501 }
502
503 #[test]
504 fn test_is_empty() {
505 let mut items = ObservableItems::new();
506
507 assert!(items.is_empty());
508
509 let mut transaction = items.transaction();
511 transaction.push_back(item("$ev0"), Some(0));
512 transaction.commit();
513
514 assert!(items.is_empty().not());
515 }
516
517 #[test]
518 fn test_subscribe() {
519 let mut items = ObservableItems::new();
520 let mut subscriber = items.subscribe().into_stream();
521
522 let mut transaction = items.transaction();
524 transaction.push_back(item("$ev0"), Some(0));
525 transaction.commit();
526
527 assert_next_matches!(subscriber, VectorDiff::PushBack { value: event } => {
529 assert_event_id!(event, "$ev0");
530 });
531 }
532
533 #[test]
534 fn test_clone_items() {
535 let mut items = ObservableItems::new();
536
537 let mut transaction = items.transaction();
538 transaction.push_back(item("$ev0"), Some(0));
539 transaction.push_back(item("$ev1"), Some(1));
540 transaction.commit();
541
542 let items = items.clone_items();
543 assert_eq!(items.len(), 2);
544 assert_event_id!(items[0], "$ev0");
545 assert_event_id!(items[1], "$ev1");
546 }
547
548 #[test]
549 fn test_replace() {
550 let mut items = ObservableItems::new();
551
552 let mut transaction = items.transaction();
554 transaction.push_back(item("$ev0"), Some(0));
555 transaction.commit();
556
557 items.replace(0, item("$ev1"));
559
560 let items = items.clone_items();
561 assert_eq!(items.len(), 1);
562 assert_event_id!(items[0], "$ev1");
563 }
564
565 #[test]
566 fn test_entries() {
567 let mut items = ObservableItems::new();
568
569 let mut transaction = items.transaction();
571 transaction.push_back(item("$ev0"), Some(0));
572 transaction.push_back(item("$ev1"), Some(1));
573 transaction.push_back(item("$ev2"), Some(2));
574 transaction.commit();
575
576 let mut entries = items.entries();
577
578 assert_matches!(entries.next(), Some(entry) => {
579 assert_event_id!(entry, "$ev0");
580 });
581 assert_matches!(entries.next(), Some(entry) => {
582 assert_event_id!(entry, "$ev1");
583 });
584 assert_matches!(entries.next(), Some(entry) => {
585 assert_event_id!(entry, "$ev2");
586 });
587 assert_matches!(entries.next(), None);
588 }
589
590 #[test]
591 fn test_entry_replace() {
592 let mut items = ObservableItems::new();
593
594 let mut transaction = items.transaction();
596 transaction.push_back(item("$ev0"), Some(0));
597 transaction.commit();
598
599 let mut entries = items.entries();
600
601 assert_matches!(entries.next(), Some(mut entry) => {
603 assert_event_id!(entry, "$ev0");
604 ObservableItemsEntry::replace(&mut entry, item("$ev1"));
605 });
606 assert_matches!(entries.next(), None);
607
608 let mut entries = items.entries();
610
611 assert_matches!(entries.next(), Some(entry) => {
612 assert_event_id!(entry, "$ev1");
613 });
614 assert_matches!(entries.next(), None);
615 }
616
617 #[test]
618 fn test_for_each() {
619 let mut items = ObservableItems::new();
620
621 let mut transaction = items.transaction();
623 transaction.push_back(item("$ev0"), Some(0));
624 transaction.push_back(item("$ev1"), Some(1));
625 transaction.push_back(item("$ev2"), Some(2));
626 transaction.commit();
627
628 let mut nth = 0;
629
630 items.for_each(|entry| {
632 match nth {
633 0 => {
634 assert_event_id!(entry, "$ev0");
635 }
636 1 => {
637 assert_event_id!(entry, "$ev1");
638 }
639 2 => {
640 assert_event_id!(entry, "$ev2");
641 }
642 _ => unreachable!(),
643 }
644
645 nth += 1;
646 });
647 }
648
649 #[test]
650 fn test_transaction_commit() {
651 let mut items = ObservableItems::new();
652
653 let mut transaction = items.transaction();
655 transaction.push_back(item("$ev0"), Some(0));
656 drop(transaction);
657
658 assert!(items.is_empty());
659
660 let mut transaction = items.transaction();
662 transaction.push_back(item("$ev0"), Some(0));
663 transaction.commit();
664
665 assert!(items.is_empty().not());
666 }
667
668 #[test]
669 fn test_transaction_get() {
670 let mut items = ObservableItems::new();
671
672 let mut transaction = items.transaction();
673 transaction.push_back(item("$ev0"), Some(0));
674
675 assert_matches!(transaction.get(0), Some(event) => {
676 assert_event_id!(event, "$ev0");
677 });
678 }
679
680 #[test]
681 fn test_transaction_replace() {
682 let mut items = ObservableItems::new();
683
684 let mut transaction = items.transaction();
685 transaction.push_back(item("$ev0"), Some(0));
686 transaction.replace(0, item("$ev1"));
687
688 assert_matches!(transaction.get(0), Some(event) => {
689 assert_event_id!(event, "$ev1");
690 });
691 }
692
693 #[test]
694 fn test_transaction_insert() {
695 let mut items = ObservableItems::new();
696
697 let mut transaction = items.transaction();
698
699 transaction.push_back_remote_event(event_meta("$ev0"));
701 transaction.insert(0, item("$ev0"), Some(0));
702
703 assert_mapping! {
704 on transaction:
705
706 | event_id | event_index | timeline_item_index |
707 |----------|-------------|---------------------|
708 | "$ev0" | 0 | 0 | }
710
711 transaction.insert(0, read_marker(), None);
713
714 assert_mapping! {
715 on transaction:
716
717 | event_id | event_index | timeline_item_index |
718 |----------|-------------|---------------------|
719 | "$ev0" | 0 | 1 | }
721
722 transaction.push_back_remote_event(event_meta("$ev1"));
724 transaction.insert(2, item("$ev1"), Some(1));
725
726 assert_mapping! {
727 on transaction:
728
729 | event_id | event_index | timeline_item_index |
730 |----------|-------------|---------------------|
731 | "$ev0" | 0 | 1 |
732 | "$ev1" | 1 | 2 | }
734
735 transaction.push_back_remote_event(event_meta("$ev2"));
737
738 assert_mapping! {
739 on transaction:
740
741 | event_id | event_index | timeline_item_index |
742 |----------|-------------|---------------------|
743 | "$ev0" | 0 | 1 |
744 | "$ev1" | 1 | 2 |
745 | "$ev2" | 2 | | }
747
748 transaction.push_back_remote_event(event_meta("$ev3"));
750 transaction.insert(3, item("$ev3"), Some(3));
751
752 assert_mapping! {
753 on transaction:
754
755 | event_id | event_index | timeline_item_index |
756 |----------|-------------|---------------------|
757 | "$ev0" | 0 | 1 |
758 | "$ev1" | 1 | 2 |
759 | "$ev2" | 2 | |
760 | "$ev3" | 3 | 3 | }
762
763 transaction.insert(3, item("$ev2"), Some(2));
766
767 assert_mapping! {
768 on transaction:
769
770 | event_id | event_index | timeline_item_index |
771 |----------|-------------|---------------------|
772 | "$ev0" | 0 | 1 |
773 | "$ev1" | 1 | 2 |
774 | "$ev2" | 2 | 3 | | "$ev3" | 3 | 4 | }
777
778 transaction.remove(0);
780 transaction.insert(2, read_marker(), None);
781
782 assert_mapping! {
783 on transaction:
784
785 | event_id | event_index | timeline_item_index |
786 |----------|-------------|---------------------|
787 | "$ev0" | 0 | 0 | | "$ev1" | 1 | 1 | | "$ev2" | 2 | 3 |
790 | "$ev3" | 3 | 4 |
791 }
792
793 assert_eq!(transaction.len(), 5);
794 }
795
796 #[test]
797 fn test_transaction_push_front() {
798 let mut items = ObservableItems::new();
799
800 let mut transaction = items.transaction();
801
802 transaction.push_front_remote_event(event_meta("$ev0"));
804 transaction.push_front(item("$ev0"), Some(0));
805
806 assert_mapping! {
807 on transaction:
808
809 | event_id | event_index | timeline_item_index |
810 |----------|-------------|---------------------|
811 | "$ev0" | 0 | 0 | }
813
814 transaction.push_front(read_marker(), None);
816
817 assert_mapping! {
818 on transaction:
819
820 | event_id | event_index | timeline_item_index |
821 |----------|-------------|---------------------|
822 | "$ev0" | 0 | 1 | }
824
825 transaction.push_front_remote_event(event_meta("$ev1"));
827 transaction.push_front(item("$ev1"), Some(0));
828
829 assert_mapping! {
830 on transaction:
831
832 | event_id | event_index | timeline_item_index |
833 |----------|-------------|---------------------|
834 | "$ev1" | 0 | 0 | | "$ev0" | 1 | 2 | }
837
838 transaction.push_front_remote_event(event_meta("$ev2"));
840
841 assert_mapping! {
842 on transaction:
843
844 | event_id | event_index | timeline_item_index |
845 |----------|-------------|---------------------|
846 | "$ev2" | 0 | |
847 | "$ev1" | 1 | 0 | | "$ev0" | 2 | 2 | }
850
851 transaction.push_front_remote_event(event_meta("$ev3"));
853 transaction.push_front(item("$ev3"), Some(0));
854
855 assert_mapping! {
856 on transaction:
857
858 | event_id | event_index | timeline_item_index |
859 |----------|-------------|---------------------|
860 | "$ev3" | 0 | 0 | | "$ev2" | 1 | |
862 | "$ev1" | 2 | 1 | | "$ev0" | 3 | 3 | }
865
866 assert_eq!(transaction.len(), 4);
867 }
868
869 #[test]
870 fn test_transaction_push_back() {
871 let mut items = ObservableItems::new();
872
873 let mut transaction = items.transaction();
874
875 transaction.push_back_remote_event(event_meta("$ev0"));
877 transaction.push_back(item("$ev0"), Some(0));
878
879 assert_mapping! {
880 on transaction:
881
882 | event_id | event_index | timeline_item_index |
883 |----------|-------------|---------------------|
884 | "$ev0" | 0 | 0 | }
886
887 transaction.push_back(read_marker(), None);
889
890 assert_mapping! {
891 on transaction:
892
893 | event_id | event_index | timeline_item_index |
894 |----------|-------------|---------------------|
895 | "$ev0" | 0 | 0 |
896 }
897
898 transaction.push_back_remote_event(event_meta("$ev1"));
900 transaction.push_back(item("$ev1"), Some(1));
901
902 assert_mapping! {
903 on transaction:
904
905 | event_id | event_index | timeline_item_index |
906 |----------|-------------|---------------------|
907 | "$ev0" | 0 | 0 |
908 | "$ev1" | 1 | 2 | }
910
911 transaction.push_back_remote_event(event_meta("$ev2"));
913
914 assert_mapping! {
915 on transaction:
916
917 | event_id | event_index | timeline_item_index |
918 |----------|-------------|---------------------|
919 | "$ev0" | 0 | 0 |
920 | "$ev1" | 1 | 2 |
921 | "$ev2" | 2 | | }
923
924 transaction.push_back_remote_event(event_meta("$ev3"));
926 transaction.push_back(item("$ev3"), Some(3));
927
928 assert_mapping! {
929 on transaction:
930
931 | event_id | event_index | timeline_item_index |
932 |----------|-------------|---------------------|
933 | "$ev0" | 0 | 0 |
934 | "$ev1" | 1 | 2 |
935 | "$ev2" | 2 | |
936 | "$ev3" | 3 | 3 | }
938
939 assert_eq!(transaction.len(), 4);
940 }
941
942 #[test]
943 fn test_transaction_remove() {
944 let mut items = ObservableItems::new();
945
946 let mut transaction = items.transaction();
947
948 transaction.push_back_remote_event(event_meta("$ev0"));
950 transaction.push_back(item("$ev0"), Some(0));
951
952 transaction.push_back(read_marker(), None);
954
955 transaction.push_back_remote_event(event_meta("$ev1"));
957 transaction.push_back(item("$ev1"), Some(1));
958
959 transaction.push_back_remote_event(event_meta("$ev2"));
961
962 transaction.push_back_remote_event(event_meta("$ev3"));
964 transaction.push_back(item("$ev3"), Some(3));
965
966 assert_mapping! {
967 on transaction:
968
969 | event_id | event_index | timeline_item_index |
970 |----------|-------------|---------------------|
971 | "$ev0" | 0 | 0 |
972 | "$ev1" | 1 | 2 |
973 | "$ev2" | 2 | |
974 | "$ev3" | 3 | 3 |
975 }
976
977 transaction.remove(1);
979
980 assert_mapping! {
981 on transaction:
982
983 | event_id | event_index | timeline_item_index |
984 |----------|-------------|---------------------|
985 | "$ev0" | 0 | 0 |
986 | "$ev1" | 1 | 1 | | "$ev2" | 2 | |
988 | "$ev3" | 3 | 2 | }
990
991 transaction.remove(1);
993
994 assert_mapping! {
995 on transaction:
996
997 | event_id | event_index | timeline_item_index |
998 |----------|-------------|---------------------|
999 | "$ev0" | 0 | 0 |
1000 | "$ev1" | 1 | | | "$ev2" | 2 | |
1002 | "$ev3" | 3 | 1 | }
1004
1005 transaction.remove(1);
1007
1008 assert_mapping! {
1009 on transaction:
1010
1011 | event_id | event_index | timeline_item_index |
1012 |----------|-------------|---------------------|
1013 | "$ev0" | 0 | 0 |
1014 | "$ev1" | 1 | |
1015 | "$ev2" | 2 | |
1016 | "$ev3" | 3 | | }
1018
1019 transaction.remove(0);
1021
1022 assert_mapping! {
1023 on transaction:
1024
1025 | event_id | event_index | timeline_item_index |
1026 |----------|-------------|---------------------|
1027 | "$ev0" | 0 | | | "$ev1" | 1 | |
1029 | "$ev2" | 2 | |
1030 | "$ev3" | 3 | |
1031 }
1032
1033 assert!(transaction.is_empty());
1034 }
1035
1036 #[test]
1037 fn test_transaction_clear() {
1038 let mut items = ObservableItems::new();
1039
1040 let mut transaction = items.transaction();
1041
1042 transaction.push_back_remote_event(event_meta("$ev0"));
1044 transaction.push_back(item("$ev0"), Some(0));
1045
1046 transaction.push_back(read_marker(), None);
1048
1049 transaction.push_back_remote_event(event_meta("$ev1"));
1051 transaction.push_back(item("$ev1"), Some(1));
1052
1053 transaction.push_back_remote_event(event_meta("$ev2"));
1055
1056 transaction.push_back_remote_event(event_meta("$ev3"));
1058 transaction.push_back(item("$ev3"), Some(3));
1059
1060 assert_mapping! {
1061 on transaction:
1062
1063 | event_id | event_index | timeline_item_index |
1064 |----------|-------------|---------------------|
1065 | "$ev0" | 0 | 0 |
1066 | "$ev1" | 1 | 2 |
1067 | "$ev2" | 2 | |
1068 | "$ev3" | 3 | 3 |
1069 }
1070
1071 assert_eq!(transaction.all_remote_events().0.len(), 4);
1072 assert_eq!(transaction.len(), 4);
1073
1074 transaction.clear();
1076
1077 assert!(transaction.all_remote_events().0.is_empty());
1078 assert!(transaction.is_empty());
1079 }
1080
1081 #[test]
1082 fn test_transaction_for_each() {
1083 let mut items = ObservableItems::new();
1084
1085 let mut transaction = items.transaction();
1087 transaction.push_back(item("$ev0"), Some(0));
1088 transaction.push_back(item("$ev1"), Some(1));
1089 transaction.push_back(item("$ev2"), Some(2));
1090
1091 let mut nth = 0;
1092
1093 transaction.for_each(|entry| {
1095 match nth {
1096 0 => {
1097 assert_event_id!(entry, "$ev0");
1098 }
1099 1 => {
1100 assert_event_id!(entry, "$ev1");
1101 }
1102 2 => {
1103 assert_event_id!(entry, "$ev2");
1104 }
1105 _ => unreachable!(),
1106 }
1107
1108 nth += 1;
1109 });
1110 }
1111
1112 #[test]
1113 fn test_transaction_for_each_remove() {
1114 let mut items = ObservableItems::new();
1115
1116 let mut transaction = items.transaction();
1118
1119 transaction.push_back_remote_event(event_meta("$ev0"));
1120 transaction.push_back(item("$ev0"), Some(0));
1121
1122 transaction.push_back_remote_event(event_meta("$ev1"));
1123 transaction.push_back(item("$ev1"), Some(1));
1124
1125 transaction.push_back_remote_event(event_meta("$ev2"));
1126 transaction.push_back(item("$ev2"), Some(2));
1127
1128 assert_mapping! {
1129 on transaction:
1130
1131 | event_id | event_index | timeline_item_index |
1132 |----------|-------------|---------------------|
1133 | "$ev0" | 0 | 0 |
1134 | "$ev1" | 1 | 1 |
1135 | "$ev2" | 2 | 2 |
1136 }
1137
1138 transaction.for_each(|entry| {
1140 if entry.as_event().unwrap().event_id().unwrap().as_str() == "$ev1" {
1141 ObservableItemsTransactionEntry::remove(entry);
1142 }
1143 });
1144
1145 assert_mapping! {
1146 on transaction:
1147
1148 | event_id | event_index | timeline_item_index |
1149 |----------|-------------|---------------------|
1150 | "$ev0" | 0 | 0 |
1151 | "$ev2" | 2 | 1 | }
1153
1154 assert_eq!(transaction.all_remote_events().0.len(), 3);
1155 assert_eq!(transaction.len(), 2);
1156 }
1157}
1158
1159#[derive(Clone, Debug, Default)]
1165pub struct AllRemoteEvents(VecDeque<EventMeta>);
1166
1167impl AllRemoteEvents {
1168 pub fn get(&self, event_index: usize) -> Option<&EventMeta> {
1170 self.0.get(event_index)
1171 }
1172
1173 pub fn iter(&self) -> Iter<'_, EventMeta> {
1175 self.0.iter()
1176 }
1177
1178 pub fn range<R>(&self, range: R) -> Iter<'_, EventMeta>
1181 where
1182 R: RangeBounds<usize>,
1183 {
1184 self.0.range(range)
1185 }
1186
1187 fn clear(&mut self) {
1189 self.0.clear();
1190 }
1191
1192 fn push_front(&mut self, event_meta: EventMeta) {
1194 if let Some(new_timeline_item_index) = event_meta.timeline_item_index {
1197 self.increment_all_timeline_item_index_after(new_timeline_item_index);
1198 }
1199
1200 self.0.push_front(event_meta)
1202 }
1203
1204 fn push_back(&mut self, event_meta: EventMeta) {
1206 if let Some(new_timeline_item_index) = event_meta.timeline_item_index {
1209 self.increment_all_timeline_item_index_after(new_timeline_item_index);
1210 }
1211
1212 self.0.push_back(event_meta)
1214 }
1215
1216 fn insert(&mut self, event_index: usize, event_meta: EventMeta) {
1218 if let Some(new_timeline_item_index) = event_meta.timeline_item_index {
1221 self.increment_all_timeline_item_index_after(new_timeline_item_index);
1222 }
1223
1224 self.0.insert(event_index, event_meta)
1226 }
1227
1228 fn remove(&mut self, event_index: usize) -> Option<EventMeta> {
1230 let event_meta = self.0.remove(event_index)?;
1232
1233 if let Some(removed_timeline_item_index) = event_meta.timeline_item_index {
1236 self.decrement_all_timeline_item_index_after(removed_timeline_item_index);
1237 };
1238
1239 Some(event_meta)
1240 }
1241
1242 pub fn last(&self) -> Option<&EventMeta> {
1244 self.0.back()
1245 }
1246
1247 pub fn last_index(&self) -> Option<usize> {
1249 self.0.len().checked_sub(1)
1250 }
1251
1252 pub fn get_by_event_id_mut(&mut self, event_id: &EventId) -> Option<&mut EventMeta> {
1254 self.0.iter_mut().rev().find(|event_meta| event_meta.event_id == event_id)
1255 }
1256
1257 pub fn get_by_event_id(&self, event_id: &EventId) -> Option<&EventMeta> {
1259 self.0.iter().rev().find(|event_meta| event_meta.event_id == event_id)
1260 }
1261
1262 fn increment_all_timeline_item_index_after(&mut self, new_timeline_item_index: usize) {
1265 for event_meta in self.0.iter_mut().rev() {
1273 if let Some(timeline_item_index) = event_meta.timeline_item_index.as_mut() {
1274 if *timeline_item_index >= new_timeline_item_index {
1275 *timeline_item_index += 1;
1276 } else {
1277 break;
1279 }
1280 }
1281 }
1282 }
1283
1284 fn decrement_all_timeline_item_index_after(&mut self, removed_timeline_item_index: usize) {
1287 for event_meta in self.0.iter_mut().rev() {
1295 if let Some(timeline_item_index) = event_meta.timeline_item_index.as_mut() {
1296 if *timeline_item_index > removed_timeline_item_index {
1297 *timeline_item_index -= 1;
1298 } else {
1299 break;
1301 }
1302 }
1303 }
1304 }
1305
1306 fn timeline_item_has_been_inserted_at(
1311 &mut self,
1312 new_timeline_item_index: usize,
1313 event_index: Option<usize>,
1314 ) {
1315 self.increment_all_timeline_item_index_after(new_timeline_item_index);
1316
1317 if let Some(event_index) = event_index {
1318 if let Some(event_meta) = self.0.get_mut(event_index) {
1319 event_meta.timeline_item_index = Some(new_timeline_item_index);
1320 }
1321 }
1322 }
1323
1324 fn timeline_item_has_been_removed_at(&mut self, timeline_item_index_to_remove: usize) {
1327 for event_meta in self.0.iter_mut() {
1328 let mut remove_timeline_item_index = false;
1329
1330 if let Some(timeline_item_index) = event_meta.timeline_item_index.as_mut() {
1333 match (*timeline_item_index).cmp(&timeline_item_index_to_remove) {
1334 Ordering::Equal => {
1335 remove_timeline_item_index = true;
1336 }
1337
1338 Ordering::Greater => {
1339 *timeline_item_index -= 1;
1340 }
1341
1342 Ordering::Less => {}
1343 }
1344 }
1345
1346 if remove_timeline_item_index {
1349 event_meta.timeline_item_index = None;
1350 }
1351 }
1352 }
1353}
1354
1355#[cfg(test)]
1356mod all_remote_events_tests {
1357 use assert_matches::assert_matches;
1358 use ruma::event_id;
1359
1360 use super::{AllRemoteEvents, EventMeta};
1361
1362 fn event_meta(event_id: &str, timeline_item_index: Option<usize>) -> EventMeta {
1363 EventMeta { event_id: event_id.parse().unwrap(), timeline_item_index, visible: false }
1364 }
1365
1366 macro_rules! assert_events {
1367 ( $events:ident, [ $( ( $event_id:literal, $timeline_item_index:expr ) ),* $(,)? ] ) => {
1368 let mut iter = $events .iter();
1369
1370 $(
1371 assert_matches!(iter.next(), Some(EventMeta { event_id, timeline_item_index, .. }) => {
1372 assert_eq!(event_id.as_str(), $event_id );
1373 assert_eq!(*timeline_item_index, $timeline_item_index );
1374 });
1375 )*
1376
1377 assert!(iter.next().is_none(), "Not all events have been asserted");
1378 }
1379 }
1380
1381 #[test]
1382 fn test_range() {
1383 let mut events = AllRemoteEvents::default();
1384
1385 events.push_back(event_meta("$ev0", None));
1387 events.push_back(event_meta("$ev1", None));
1388 events.push_back(event_meta("$ev2", None));
1389
1390 assert_eq!(events.iter().count(), 3);
1391
1392 assert_eq!(events.range(..).count(), 3);
1394 assert_eq!(events.range(1..).count(), 2);
1395 assert_eq!(events.range(0..=1).count(), 2);
1396
1397 let mut some_events = events.range(1..);
1399
1400 assert_matches!(some_events.next(), Some(EventMeta { event_id, .. }) => {
1401 assert_eq!(event_id.as_str(), "$ev1");
1402 });
1403 assert_matches!(some_events.next(), Some(EventMeta { event_id, .. }) => {
1404 assert_eq!(event_id.as_str(), "$ev2");
1405 });
1406 assert!(some_events.next().is_none());
1407 }
1408
1409 #[test]
1410 fn test_clear() {
1411 let mut events = AllRemoteEvents::default();
1412
1413 events.push_back(event_meta("$ev0", None));
1415 events.push_back(event_meta("$ev1", None));
1416 events.push_back(event_meta("$ev2", None));
1417
1418 assert_eq!(events.iter().count(), 3);
1419
1420 events.clear();
1422
1423 assert_eq!(events.iter().count(), 0);
1424 }
1425
1426 #[test]
1427 fn test_push_front() {
1428 let mut events = AllRemoteEvents::default();
1429
1430 events.push_front(event_meta("$ev0", Some(1)));
1432
1433 events.push_front(event_meta("$ev1", None));
1435
1436 events.push_front(event_meta("$ev2", Some(0)));
1438
1439 events.push_front(event_meta("$ev3", Some(0)));
1441
1442 assert_events!(
1443 events,
1444 [
1445 ("$ev3", Some(0)),
1447 ("$ev2", Some(1)),
1449 ("$ev1", None),
1451 ("$ev0", Some(3)),
1453 ]
1454 );
1455 }
1456
1457 #[test]
1458 fn test_push_back() {
1459 let mut events = AllRemoteEvents::default();
1460
1461 events.push_back(event_meta("$ev0", Some(0)));
1463
1464 events.push_back(event_meta("$ev1", None));
1466
1467 events.push_back(event_meta("$ev2", Some(1)));
1469
1470 events.push_back(event_meta("$ev3", Some(1)));
1474
1475 assert_events!(
1476 events,
1477 [
1478 ("$ev0", Some(0)),
1480 ("$ev1", None),
1482 ("$ev2", Some(2)),
1484 ("$ev3", Some(1)),
1486 ]
1487 );
1488 }
1489
1490 #[test]
1491 fn test_insert() {
1492 let mut events = AllRemoteEvents::default();
1493
1494 events.insert(0, event_meta("$ev0", Some(0)));
1496
1497 events.insert(1, event_meta("$ev1", None));
1499
1500 events.insert(2, event_meta("$ev2", Some(1)));
1502
1503 events.insert(0, event_meta("$ev3", Some(0)));
1505
1506 assert_events!(
1507 events,
1508 [
1509 ("$ev3", Some(0)),
1511 ("$ev0", Some(1)),
1513 ("$ev1", None),
1515 ("$ev2", Some(2)),
1517 ]
1518 );
1519 }
1520
1521 #[test]
1522 fn test_remove() {
1523 let mut events = AllRemoteEvents::default();
1524
1525 events.push_back(event_meta("$ev0", Some(0)));
1527 events.push_back(event_meta("$ev1", Some(1)));
1528 events.push_back(event_meta("$ev2", None));
1529 events.push_back(event_meta("$ev3", Some(2)));
1530
1531 assert_events!(
1533 events,
1534 [("$ev0", Some(0)), ("$ev1", Some(1)), ("$ev2", None), ("$ev3", Some(2))]
1535 );
1536
1537 events.remove(2); events.remove(1); assert_events!(
1542 events,
1543 [
1544 ("$ev0", Some(0)),
1545 ("$ev3", Some(1)),
1547 ]
1548 );
1549 }
1550
1551 #[test]
1552 fn test_last() {
1553 let mut events = AllRemoteEvents::default();
1554
1555 assert!(events.last().is_none());
1556 assert!(events.last_index().is_none());
1557
1558 events.push_back(event_meta("$ev0", Some(0)));
1560 events.push_back(event_meta("$ev1", Some(1)));
1561
1562 assert_matches!(events.last(), Some(EventMeta { event_id, .. }) => {
1563 assert_eq!(event_id.as_str(), "$ev1");
1564 });
1565 assert_eq!(events.last_index(), Some(1));
1566 }
1567
1568 #[test]
1569 fn test_get_by_event_by_mut() {
1570 let mut events = AllRemoteEvents::default();
1571
1572 events.push_back(event_meta("$ev0", Some(0)));
1574 events.push_back(event_meta("$ev1", Some(1)));
1575
1576 assert!(events.get_by_event_id_mut(event_id!("$ev0")).is_some());
1577 assert!(events.get_by_event_id_mut(event_id!("$ev42")).is_none());
1578 }
1579
1580 #[test]
1581 fn test_timeline_item_has_been_inserted_at() {
1582 let mut events = AllRemoteEvents::default();
1583
1584 events.push_back(event_meta("$ev0", Some(0)));
1586 events.push_back(event_meta("$ev1", Some(1)));
1587 events.push_back(event_meta("$ev2", None));
1588 events.push_back(event_meta("$ev3", None));
1589 events.push_back(event_meta("$ev4", Some(2)));
1590 events.push_back(event_meta("$ev5", Some(3)));
1591 events.push_back(event_meta("$ev6", None));
1592
1593 events.timeline_item_has_been_inserted_at(2, None);
1595
1596 assert_events!(
1597 events,
1598 [
1599 ("$ev0", Some(0)),
1600 ("$ev1", Some(1)),
1601 ("$ev2", None),
1602 ("$ev3", None),
1603 ("$ev4", Some(3)),
1605 ("$ev5", Some(4)),
1607 ("$ev6", None),
1608 ]
1609 );
1610
1611 events.timeline_item_has_been_inserted_at(5, Some(6));
1613
1614 assert_events!(
1615 events,
1616 [
1617 ("$ev0", Some(0)),
1618 ("$ev1", Some(1)),
1619 ("$ev2", None),
1620 ("$ev3", None),
1621 ("$ev4", Some(3)),
1622 ("$ev5", Some(4)),
1623 ("$ev6", Some(5)),
1625 ]
1626 );
1627 }
1628
1629 #[test]
1630 fn test_timeline_item_has_been_removed_at() {
1631 let mut events = AllRemoteEvents::default();
1632
1633 events.push_back(event_meta("$ev0", Some(0)));
1635 events.push_back(event_meta("$ev1", Some(1)));
1636 events.push_back(event_meta("$ev2", None));
1637 events.push_back(event_meta("$ev3", None));
1638 events.push_back(event_meta("$ev4", Some(3)));
1639 events.push_back(event_meta("$ev5", Some(4)));
1640 events.push_back(event_meta("$ev6", None));
1641
1642 events.timeline_item_has_been_removed_at(2);
1644
1645 assert_events!(
1646 events,
1647 [
1648 ("$ev0", Some(0)),
1649 ("$ev1", Some(1)),
1650 ("$ev2", None),
1651 ("$ev3", None),
1652 ("$ev4", Some(2)),
1654 ("$ev5", Some(3)),
1656 ("$ev6", None),
1657 ]
1658 );
1659
1660 events.timeline_item_has_been_removed_at(2);
1662
1663 assert_events!(
1664 events,
1665 [
1666 ("$ev0", Some(0)),
1667 ("$ev1", Some(1)),
1668 ("$ev2", None),
1669 ("$ev3", None),
1670 ("$ev4", None),
1672 ("$ev5", Some(2)),
1674 ("$ev6", None),
1675 ]
1676 );
1677
1678 events.timeline_item_has_been_removed_at(0);
1680
1681 assert_events!(
1682 events,
1683 [
1684 ("$ev0", None),
1686 ("$ev1", Some(0)),
1688 ("$ev2", None),
1689 ("$ev3", None),
1690 ("$ev4", None),
1691 ("$ev5", Some(1)),
1693 ("$ev6", None),
1694 ]
1695 );
1696 }
1697}