@@ -29,7 +29,12 @@ use ruma::{
2929 EventId , MilliSecondsSinceUnixEpoch , OwnedEventId , OwnedTransactionId , TransactionId , UserId ,
3030 events:: {
3131 AnyMessageLikeEventContent , AnySyncStateEvent , AnySyncTimelineEvent , SyncStateEvent ,
32- room:: { member:: MembershipState , message:: MessageType , power_levels:: RoomPowerLevels } ,
32+ relation:: Replacement ,
33+ room:: {
34+ member:: MembershipState ,
35+ message:: { MessageType , Relation } ,
36+ power_levels:: RoomPowerLevels ,
37+ } ,
3338 } ,
3439} ;
3540use tracing:: { error, instrument, warn} ;
@@ -519,8 +524,9 @@ impl LatestEventValueBuilder {
519524 power_levels : Option < & RoomPowerLevels > ,
520525 ) -> LatestEventValue {
521526 if let Ok ( Some ( event) ) = room_event_cache
522- . rfind_map_event_in_memory_by ( |event| {
523- filter_timeline_event ( event, own_user_id, power_levels) . then ( || event. clone ( ) )
527+ . rfind_map_event_in_memory_by ( |event, previous_event_id| {
528+ filter_timeline_event ( event, previous_event_id, own_user_id, power_levels)
529+ . then ( || event. clone ( ) )
524530 } )
525531 . await
526532 {
@@ -552,7 +558,7 @@ impl LatestEventValueBuilder {
552558 LocalEchoContent :: Event { serialized_event : serialized_event_content, .. } => {
553559 match serialized_event_content. deserialize ( ) {
554560 Ok ( content) => {
555- if filter_any_message_like_event_content ( content) {
561+ if filter_any_message_like_event_content ( content, None ) {
556562 let local_value = LocalLatestEventValue {
557563 timestamp : MilliSecondsSinceUnixEpoch :: now ( ) ,
558564 content : serialized_event_content. clone ( ) ,
@@ -660,7 +666,7 @@ impl LatestEventValueBuilder {
660666 if let Some ( position) = buffer_of_values_for_local_events. position ( transaction_id) {
661667 match new_serialized_event_content. deserialize ( ) {
662668 Ok ( content) => {
663- if filter_any_message_like_event_content ( content) {
669+ if filter_any_message_like_event_content ( content, None ) {
664670 buffer_of_values_for_local_events. replace_content (
665671 position,
666672 new_serialized_event_content. clone ( ) ,
@@ -933,6 +939,7 @@ impl LatestEventValuesForLocalEvents {
933939
934940fn filter_timeline_event (
935941 event : & TimelineEvent ,
942+ previous_event_id : Option < OwnedEventId > ,
936943 own_user_id : Option < & UserId > ,
937944 power_levels : Option < & RoomPowerLevels > ,
938945) -> bool {
@@ -953,9 +960,10 @@ fn filter_timeline_event(
953960 match event {
954961 AnySyncTimelineEvent :: MessageLike ( message_like_event) => {
955962 match message_like_event. original_content ( ) {
956- Some ( any_message_like_event_content) => {
957- filter_any_message_like_event_content ( any_message_like_event_content)
958- }
963+ Some ( any_message_like_event_content) => filter_any_message_like_event_content (
964+ any_message_like_event_content,
965+ previous_event_id,
966+ ) ,
959967
960968 // The event has been redacted.
961969 None => true ,
@@ -968,15 +976,27 @@ fn filter_timeline_event(
968976 }
969977}
970978
971- fn filter_any_message_like_event_content ( event : AnyMessageLikeEventContent ) -> bool {
979+ fn filter_any_message_like_event_content (
980+ event : AnyMessageLikeEventContent ,
981+ previous_event_id : Option < OwnedEventId > ,
982+ ) -> bool {
972983 match event {
973984 AnyMessageLikeEventContent :: RoomMessage ( message) => {
974985 // Don't show incoming verification requests.
975986 if let MessageType :: VerificationRequest ( _) = message. msgtype {
976987 return false ;
977988 }
978989
979- true
990+ // Not all relations are accepted. Let's filter them.
991+ match & message. relates_to {
992+ Some ( Relation :: Replacement ( Replacement { event_id, .. } ) ) => {
993+ // If the edit relates to the immediate previous event, this is an acceptable
994+ // latest event, otherwise let's ignore it.
995+ Some ( event_id) == previous_event_id. as_ref ( )
996+ }
997+
998+ _ => true ,
999+ }
9801000 }
9811001
9821002 AnyMessageLikeEventContent :: UnstablePollStart ( _)
@@ -1074,7 +1094,7 @@ mod tests_latest_event_content {
10741094 $event_builder
10751095 } ;
10761096
1077- assert_eq!( filter_timeline_event( & event, Some ( user_id!( "@mnt_io:matrix.org" ) ) , None ) , $expect ) ;
1097+ assert_eq!( filter_timeline_event( & event, None , Some ( user_id!( "@mnt_io:matrix.org" ) ) , None ) , $expect ) ;
10781098 } ;
10791099 }
10801100
@@ -1103,15 +1123,59 @@ mod tests_latest_event_content {
11031123
11041124 #[ test]
11051125 fn test_room_message_replacement ( ) {
1106- assert_latest_event_content ! (
1107- event | event_factory | {
1108- event_factory
1109- . text_msg( "bonjour" )
1110- . edit( event_id!( "$ev0" ) , RoomMessageEventContent :: text_plain( "hello" ) . into( ) )
1111- . into_event( )
1112- }
1113- is a candidate
1114- ) ;
1126+ let user_id = user_id ! ( "@mnt_io:matrix.org" ) ;
1127+ let event_factory = EventFactory :: new ( ) . sender ( user_id) ;
1128+ let event = event_factory
1129+ . text_msg ( "bonjour" )
1130+ . edit ( event_id ! ( "$ev0" ) , RoomMessageEventContent :: text_plain ( "hello" ) . into ( ) )
1131+ . into_event ( ) ;
1132+
1133+ // Without a previous event.
1134+ //
1135+ // This is an edge case where either the event cache has been emptied and only
1136+ // the edit is received via the sync for example, or either the previous event
1137+ // is part of another chunk that is not loaded in memory yet. In this case,
1138+ // let's not consider the event as a `LatestEventValue` candidate.
1139+ {
1140+ let previous_event_id = None ;
1141+
1142+ assert ! (
1143+ filter_timeline_event(
1144+ & event,
1145+ previous_event_id,
1146+ Some ( user_id!( "@mnt_io:matrix.org" ) ) ,
1147+ None
1148+ )
1149+ . not( )
1150+ ) ;
1151+ }
1152+
1153+ // With a previous event, but the one being replaced.
1154+ {
1155+ let previous_event_id = Some ( event_id ! ( "$ev1" ) . to_owned ( ) ) ;
1156+
1157+ assert ! (
1158+ filter_timeline_event(
1159+ & event,
1160+ previous_event_id,
1161+ Some ( user_id!( "@mnt_io:matrix.org" ) ) ,
1162+ None
1163+ )
1164+ . not( )
1165+ ) ;
1166+ }
1167+
1168+ // With a previous event, and that's the one being replaced!
1169+ {
1170+ let previous_event_id = Some ( event_id ! ( "$ev0" ) . to_owned ( ) ) ;
1171+
1172+ assert ! ( filter_timeline_event(
1173+ & event,
1174+ previous_event_id,
1175+ Some ( user_id!( "@mnt_io:matrix.org" ) ) ,
1176+ None
1177+ ) ) ;
1178+ }
11151179 }
11161180
11171181 #[ test]
@@ -1258,7 +1322,7 @@ mod tests_latest_event_content {
12581322 room_power_levels. invite = 10 . into ( ) ;
12591323 room_power_levels. kick = 10 . into ( ) ;
12601324 assert ! (
1261- filter_timeline_event( & event, Some ( user_id) , Some ( & room_power_levels) ) . not( ) ,
1325+ filter_timeline_event( & event, None , Some ( user_id) , Some ( & room_power_levels) ) . not( ) ,
12621326 "cannot accept, cannot decline" ,
12631327 ) ;
12641328 }
@@ -1268,7 +1332,7 @@ mod tests_latest_event_content {
12681332 room_power_levels. invite = 0 . into ( ) ;
12691333 room_power_levels. kick = 10 . into ( ) ;
12701334 assert ! (
1271- filter_timeline_event( & event, Some ( user_id) , Some ( & room_power_levels) ) ,
1335+ filter_timeline_event( & event, None , Some ( user_id) , Some ( & room_power_levels) ) ,
12721336 "can accept, cannot decline" ,
12731337 ) ;
12741338 }
@@ -1278,7 +1342,7 @@ mod tests_latest_event_content {
12781342 room_power_levels. invite = 10 . into ( ) ;
12791343 room_power_levels. kick = 0 . into ( ) ;
12801344 assert ! (
1281- filter_timeline_event( & event, Some ( user_id) , Some ( & room_power_levels) ) ,
1345+ filter_timeline_event( & event, None , Some ( user_id) , Some ( & room_power_levels) ) ,
12821346 "cannot accept, can decline" ,
12831347 ) ;
12841348 }
@@ -1288,7 +1352,7 @@ mod tests_latest_event_content {
12881352 room_power_levels. invite = 0 . into ( ) ;
12891353 room_power_levels. kick = 0 . into ( ) ;
12901354 assert ! (
1291- filter_timeline_event( & event, Some ( user_id) , Some ( & room_power_levels) ) ,
1355+ filter_timeline_event( & event, None , Some ( user_id) , Some ( & room_power_levels) ) ,
12921356 "can accept, can decline" ,
12931357 ) ;
12941358 }
@@ -1304,7 +1368,7 @@ mod tests_latest_event_content {
13041368 room_power_levels. kick = 0 . into ( ) ;
13051369
13061370 assert ! (
1307- filter_timeline_event( & event, Some ( user_id) , Some ( & room_power_levels) ) . not( ) ,
1371+ filter_timeline_event( & event, None , Some ( user_id) , Some ( & room_power_levels) ) . not( ) ,
13081372 "cannot accept, can decline, at least same user levels" ,
13091373 ) ;
13101374 }
0 commit comments