@@ -26,7 +26,7 @@ use matrix_sdk_test::{
2626 ALICE , BOB , CAROL , JoinedRoomBuilder , RoomAccountDataTestEvent , async_test,
2727 event_factory:: EventFactory ,
2828} ;
29- use matrix_sdk_ui:: timeline:: { RoomExt , TimelineFocus } ;
29+ use matrix_sdk_ui:: timeline:: { RoomExt , TimelineFocus , TimelineReadReceiptTracking } ;
3030use ruma:: {
3131 MilliSecondsSinceUnixEpoch ,
3232 api:: client:: receipt:: create_receipt:: v3:: ReceiptType as CreateReceiptType ,
@@ -407,6 +407,188 @@ async fn test_read_receipts_updates_on_filtered_events() {
407407 assert_pending ! ( timeline_stream) ;
408408}
409409
410+ #[ async_test]
411+ async fn test_read_receipts_updates_on_message_like_events ( ) {
412+ let server = MatrixMockServer :: new ( ) . await ;
413+ let client = server. client_builder ( ) . build ( ) . await ;
414+
415+ server. mock_room_state_encryption ( ) . plain ( ) . mount ( ) . await ;
416+
417+ let room_id = room_id ! ( "!a98sd12bjh:example.org" ) ;
418+ let room = server. sync_joined_room ( & client, room_id) . await ;
419+
420+ let own_user_id = client. user_id ( ) . unwrap ( ) ;
421+
422+ let event_a_id = event_id ! ( "$152037280074GZeOm:localhost" ) ;
423+ let event_b_id = event_id ! ( "$e32037280er453l:localhost" ) ;
424+ let event_c_id = event_id ! ( "$Sg2037280074GZr34:localhost" ) ;
425+
426+ let timeline = room
427+ . timeline_builder ( )
428+ . track_read_marker_and_receipts ( TimelineReadReceiptTracking :: MessageLikeEvents )
429+ . build ( )
430+ . await
431+ . unwrap ( ) ;
432+ let ( items, mut timeline_stream) = timeline. subscribe ( ) . await ;
433+
434+ assert ! ( items. is_empty( ) ) ;
435+
436+ let own_receipt = timeline. latest_user_read_receipt ( own_user_id) . await ;
437+ assert_matches ! ( own_receipt, None ) ;
438+ let own_receipt_timeline_event =
439+ timeline. latest_user_read_receipt_timeline_event_id ( own_user_id) . await ;
440+ assert_matches ! ( own_receipt_timeline_event, None ) ;
441+ let alice_receipt = timeline. latest_user_read_receipt ( * ALICE ) . await ;
442+ assert_matches ! ( alice_receipt, None ) ;
443+ let alice_receipt_timeline_event =
444+ timeline. latest_user_read_receipt_timeline_event_id ( * ALICE ) . await ;
445+ assert_matches ! ( alice_receipt_timeline_event, None ) ;
446+ let bob_receipt = timeline. latest_user_read_receipt ( * BOB ) . await ;
447+ assert_matches ! ( bob_receipt, None ) ;
448+ let bob_receipt_timeline_event =
449+ timeline. latest_user_read_receipt_timeline_event_id ( * BOB ) . await ;
450+ assert_matches ! ( bob_receipt_timeline_event, None ) ;
451+
452+ let f = EventFactory :: new ( ) ;
453+ server
454+ . sync_room (
455+ & client,
456+ JoinedRoomBuilder :: new ( room_id)
457+ // Event A
458+ . add_timeline_event (
459+ f. text_msg ( "is dancing" ) . sender ( own_user_id) . event_id ( event_a_id) ,
460+ )
461+ // Event B
462+ . add_timeline_event ( f. room_name ( "Party Room" ) . sender ( * BOB ) . event_id ( event_b_id) )
463+ // Event C
464+ . add_timeline_event (
465+ f. text_msg ( "Viva la macarena!" ) . sender ( * ALICE ) . event_id ( event_c_id) ,
466+ ) ,
467+ )
468+ . await ;
469+
470+ assert_let ! ( Some ( timeline_updates) = timeline_stream. next( ) . await ) ;
471+ assert_eq ! ( timeline_updates. len( ) , 5 ) ;
472+
473+ // We don't list the read receipt of our own user on events.
474+ assert_let ! ( VectorDiff :: PushBack { value: item_a } = & timeline_updates[ 0 ] ) ;
475+ let event_a = item_a. as_event ( ) . unwrap ( ) ;
476+ assert ! ( event_a. read_receipts( ) . is_empty( ) ) ;
477+
478+ let ( own_receipt_event_id, _) = timeline. latest_user_read_receipt ( own_user_id) . await . unwrap ( ) ;
479+ assert_eq ! ( own_receipt_event_id, event_a_id) ;
480+ let own_receipt_timeline_event =
481+ timeline. latest_user_read_receipt_timeline_event_id ( own_user_id) . await . unwrap ( ) ;
482+ assert_eq ! ( own_receipt_timeline_event, event_a_id) ;
483+
484+ // Implicit read receipt of @bob:localhost.
485+ assert_let ! ( VectorDiff :: Set { index: 0 , value: item_a } = & timeline_updates[ 1 ] ) ;
486+ let event_a = item_a. as_event ( ) . unwrap ( ) ;
487+ assert_eq ! ( event_a. read_receipts( ) . len( ) , 1 ) ;
488+
489+ assert_let ! ( VectorDiff :: PushBack { value: item_b } = & timeline_updates[ 2 ] ) ;
490+ let event_b = item_b. as_event ( ) . unwrap ( ) ;
491+ assert_eq ! ( event_b. read_receipts( ) . len( ) , 0 ) ;
492+
493+ // Real receipt is on event B.
494+ let ( bob_receipt_event_id, _) = timeline. latest_user_read_receipt ( * BOB ) . await . unwrap ( ) ;
495+ assert_eq ! ( bob_receipt_event_id, event_b_id) ;
496+ // Visible receipt is on event A.
497+ let bob_receipt_timeline_event =
498+ timeline. latest_user_read_receipt_timeline_event_id ( * BOB ) . await . unwrap ( ) ;
499+ assert_eq ! ( bob_receipt_timeline_event, event_a. event_id( ) . unwrap( ) ) ;
500+
501+ // Implicit read receipt of @alice:localhost.
502+ assert_let ! ( VectorDiff :: PushBack { value: item_c } = & timeline_updates[ 3 ] ) ;
503+ let event_c = item_c. as_event ( ) . unwrap ( ) ;
504+ assert_eq ! ( event_c. read_receipts( ) . len( ) , 1 ) ;
505+
506+ let ( alice_receipt_event_id, _) = timeline. latest_user_read_receipt ( * ALICE ) . await . unwrap ( ) ;
507+ assert_eq ! ( alice_receipt_event_id, event_c_id) ;
508+ let alice_receipt_timeline_event =
509+ timeline. latest_user_read_receipt_timeline_event_id ( * ALICE ) . await . unwrap ( ) ;
510+ assert_eq ! ( alice_receipt_timeline_event, event_c_id) ;
511+
512+ assert_let ! ( VectorDiff :: PushFront { value: date_divider } = & timeline_updates[ 4 ] ) ;
513+ assert ! ( date_divider. is_date_divider( ) ) ;
514+
515+ // Read receipt on filtered event.
516+ server
517+ . sync_room (
518+ & client,
519+ JoinedRoomBuilder :: new ( room_id) . add_receipt (
520+ f. read_receipts ( )
521+ . add ( event_b_id, own_user_id, EventReceiptType :: Read , ReceiptThread :: Unthreaded )
522+ . into_event ( ) ,
523+ ) ,
524+ )
525+ . await ;
526+
527+ // Real receipt changed to event B.
528+ let ( own_receipt_event_id, _) = timeline. latest_user_read_receipt ( own_user_id) . await . unwrap ( ) ;
529+ assert_eq ! ( own_receipt_event_id, event_b_id) ;
530+ // Visible receipt is still on event A.
531+ let own_receipt_timeline_event =
532+ timeline. latest_user_read_receipt_timeline_event_id ( own_user_id) . await . unwrap ( ) ;
533+ assert_eq ! ( own_receipt_timeline_event, event_a. event_id( ) . unwrap( ) ) ;
534+
535+ // Update with explicit read receipt.
536+ server
537+ . sync_room (
538+ & client,
539+ JoinedRoomBuilder :: new ( room_id) . add_receipt (
540+ f. read_receipts ( )
541+ . add ( event_c_id, * BOB , EventReceiptType :: Read , ReceiptThread :: Unthreaded )
542+ . into_event ( ) ,
543+ ) ,
544+ )
545+ . await ;
546+
547+ assert_let ! ( Some ( timeline_updates) = timeline_stream. next( ) . await ) ;
548+ assert_eq ! ( timeline_updates. len( ) , 2 ) ;
549+
550+ assert_let ! ( VectorDiff :: Set { index: 1 , value: item_a } = & timeline_updates[ 0 ] ) ;
551+ let event_a = item_a. as_event ( ) . unwrap ( ) ;
552+ assert ! ( event_a. read_receipts( ) . is_empty( ) ) ;
553+
554+ assert_let ! ( VectorDiff :: Set { index: 3 , value: item_c } = & timeline_updates[ 1 ] ) ;
555+ let event_c = item_c. as_event ( ) . unwrap ( ) ;
556+ assert_eq ! ( event_c. read_receipts( ) . len( ) , 2 ) ;
557+
558+ // Both real and visible receipts are now on event C.
559+ let ( bob_receipt_event_id, _) = timeline. latest_user_read_receipt ( * BOB ) . await . unwrap ( ) ;
560+ assert_eq ! ( bob_receipt_event_id, event_c_id) ;
561+ let bob_receipt_timeline_event =
562+ timeline. latest_user_read_receipt_timeline_event_id ( * BOB ) . await . unwrap ( ) ;
563+ assert_eq ! ( bob_receipt_timeline_event, event_c_id) ;
564+
565+ // Private read receipt is updated.
566+ server
567+ . sync_room (
568+ & client,
569+ JoinedRoomBuilder :: new ( room_id) . add_receipt (
570+ f. read_receipts ( )
571+ . add (
572+ event_c_id,
573+ own_user_id,
574+ EventReceiptType :: ReadPrivate ,
575+ ReceiptThread :: Unthreaded ,
576+ )
577+ . into_event ( ) ,
578+ ) ,
579+ )
580+ . await ;
581+
582+ // Both real and visible receipts are now on event C.
583+ let ( own_user_receipt_event_id, _) =
584+ timeline. latest_user_read_receipt ( own_user_id) . await . unwrap ( ) ;
585+ assert_eq ! ( own_user_receipt_event_id, event_c_id) ;
586+ let own_receipt_timeline_event =
587+ timeline. latest_user_read_receipt_timeline_event_id ( own_user_id) . await . unwrap ( ) ;
588+ assert_eq ! ( own_receipt_timeline_event, event_c_id) ;
589+ assert_pending ! ( timeline_stream) ;
590+ }
591+
410592#[ async_test]
411593async fn test_send_single_receipt ( ) {
412594 let server = MatrixMockServer :: new ( ) . await ;
0 commit comments