5454logger = logging .getLogger (__name__ )
5555
5656
57+ # The event types that clients should consider as new activity.
58+ DEFAULT_BUMP_EVENT_TYPES = {
59+ EventTypes .Message ,
60+ EventTypes .Encrypted ,
61+ EventTypes .Sticker ,
62+ EventTypes .CallInvite ,
63+ EventTypes .PollStart ,
64+ EventTypes .LiveLocationShareStart ,
65+ }
66+
67+
5768def filter_membership_for_sync (
5869 * , membership : str , user_id : str , sender : Optional [str ]
5970) -> bool :
@@ -285,6 +296,7 @@ class _RoomMembershipForUser:
285296 range
286297 """
287298
299+ room_id : str
288300 event_id : Optional [str ]
289301 event_pos : PersistedEventPosition
290302 membership : str
@@ -469,7 +481,9 @@ async def current_sync_for_user(
469481 #
470482 # Both sides of range are inclusive so we `+ 1`
471483 max_num_rooms = range [1 ] - range [0 ] + 1
472- for room_id , _ in sorted_room_info [range [0 ] :]:
484+ for room_membership in sorted_room_info [range [0 ] :]:
485+ room_id = room_membership .room_id
486+
473487 if len (room_ids_in_list ) >= max_num_rooms :
474488 break
475489
@@ -519,7 +533,7 @@ async def current_sync_for_user(
519533 user = sync_config .user ,
520534 room_id = room_id ,
521535 room_sync_config = room_sync_config ,
522- rooms_membership_for_user_at_to_token = sync_room_map [room_id ],
536+ room_membership_for_user_at_to_token = sync_room_map [room_id ],
523537 from_token = from_token ,
524538 to_token = to_token ,
525539 )
@@ -591,6 +605,7 @@ async def get_sync_room_ids_for_user(
591605 # (below) because they are potentially from the current snapshot time
592606 # instead from the time of the `to_token`.
593607 room_for_user .room_id : _RoomMembershipForUser (
608+ room_id = room_for_user .room_id ,
594609 event_id = room_for_user .event_id ,
595610 event_pos = room_for_user .event_pos ,
596611 membership = room_for_user .membership ,
@@ -691,6 +706,7 @@ async def get_sync_room_ids_for_user(
691706 is not None
692707 ):
693708 sync_room_id_set [room_id ] = _RoomMembershipForUser (
709+ room_id = room_id ,
694710 event_id = first_membership_change_after_to_token .prev_event_id ,
695711 event_pos = first_membership_change_after_to_token .prev_event_pos ,
696712 membership = first_membership_change_after_to_token .prev_membership ,
@@ -785,6 +801,7 @@ async def get_sync_room_ids_for_user(
785801 # is their own leave event
786802 if last_membership_change_in_from_to_range .membership == Membership .LEAVE :
787803 filtered_sync_room_id_set [room_id ] = _RoomMembershipForUser (
804+ room_id = room_id ,
788805 event_id = last_membership_change_in_from_to_range .event_id ,
789806 event_pos = last_membership_change_in_from_to_range .event_pos ,
790807 membership = last_membership_change_in_from_to_range .membership ,
@@ -969,7 +986,7 @@ async def sort_rooms(
969986 self ,
970987 sync_room_map : Dict [str , _RoomMembershipForUser ],
971988 to_token : StreamToken ,
972- ) -> List [Tuple [ str , _RoomMembershipForUser ] ]:
989+ ) -> List [_RoomMembershipForUser ]:
973990 """
974991 Sort by `stream_ordering` of the last event that the user should see in the
975992 room. `stream_ordering` is unique so we get a stable sort.
@@ -1007,12 +1024,17 @@ async def sort_rooms(
10071024 else :
10081025 # Otherwise, if the user has left/been invited/knocked/been banned from
10091026 # a room, they shouldn't see anything past that point.
1027+ #
1028+ # FIXME: It's possible that people should see beyond this point in
1029+ # invited/knocked cases if for example the room has
1030+ # `invite`/`world_readable` history visibility, see
1031+ # https://github.com/matrix-org/matrix-spec-proposals/pull/3575#discussion_r1653045932
10101032 last_activity_in_room_map [room_id ] = room_for_user .event_pos .stream
10111033
10121034 return sorted (
1013- sync_room_map .items (),
1035+ sync_room_map .values (),
10141036 # Sort by the last activity (stream_ordering) in the room
1015- key = lambda room_info : last_activity_in_room_map [room_info [ 0 ] ],
1037+ key = lambda room_info : last_activity_in_room_map [room_info . room_id ],
10161038 # We want descending order
10171039 reverse = True ,
10181040 )
@@ -1022,7 +1044,7 @@ async def get_room_sync_data(
10221044 user : UserID ,
10231045 room_id : str ,
10241046 room_sync_config : RoomSyncConfig ,
1025- rooms_membership_for_user_at_to_token : _RoomMembershipForUser ,
1047+ room_membership_for_user_at_to_token : _RoomMembershipForUser ,
10261048 from_token : Optional [StreamToken ],
10271049 to_token : StreamToken ,
10281050 ) -> SlidingSyncResult .RoomResult :
@@ -1036,7 +1058,7 @@ async def get_room_sync_data(
10361058 room_id: The room ID to fetch data for
10371059 room_sync_config: Config for what data we should fetch for a room in the
10381060 sync response.
1039- rooms_membership_for_user_at_to_token : Membership information for the user
1061+ room_membership_for_user_at_to_token : Membership information for the user
10401062 in the room at the time of `to_token`.
10411063 from_token: The point in the stream to sync from.
10421064 to_token: The point in the stream to sync up to.
@@ -1056,7 +1078,7 @@ async def get_room_sync_data(
10561078 if (
10571079 room_sync_config .timeline_limit > 0
10581080 # No timeline for invite/knock rooms (just `stripped_state`)
1059- and rooms_membership_for_user_at_to_token .membership
1081+ and room_membership_for_user_at_to_token .membership
10601082 not in (Membership .INVITE , Membership .KNOCK )
10611083 ):
10621084 limited = False
@@ -1069,12 +1091,12 @@ async def get_room_sync_data(
10691091 # We're going to paginate backwards from the `to_token`
10701092 from_bound = to_token .room_key
10711093 # People shouldn't see past their leave/ban event
1072- if rooms_membership_for_user_at_to_token .membership in (
1094+ if room_membership_for_user_at_to_token .membership in (
10731095 Membership .LEAVE ,
10741096 Membership .BAN ,
10751097 ):
10761098 from_bound = (
1077- rooms_membership_for_user_at_to_token .event_pos .to_room_stream_token ()
1099+ room_membership_for_user_at_to_token .event_pos .to_room_stream_token ()
10781100 )
10791101
10801102 # Determine whether we should limit the timeline to the token range.
@@ -1089,7 +1111,7 @@ async def get_room_sync_data(
10891111 to_bound = (
10901112 from_token .room_key
10911113 if from_token is not None
1092- and not rooms_membership_for_user_at_to_token .newly_joined
1114+ and not room_membership_for_user_at_to_token .newly_joined
10931115 else None
10941116 )
10951117
@@ -1126,7 +1148,7 @@ async def get_room_sync_data(
11261148 self .storage_controllers ,
11271149 user .to_string (),
11281150 timeline_events ,
1129- is_peeking = rooms_membership_for_user_at_to_token .membership
1151+ is_peeking = room_membership_for_user_at_to_token .membership
11301152 != Membership .JOIN ,
11311153 filter_send_to_client = True ,
11321154 )
@@ -1181,16 +1203,16 @@ async def get_room_sync_data(
11811203 # Figure out any stripped state events for invite/knocks. This allows the
11821204 # potential joiner to identify the room.
11831205 stripped_state : List [JsonDict ] = []
1184- if rooms_membership_for_user_at_to_token .membership in (
1206+ if room_membership_for_user_at_to_token .membership in (
11851207 Membership .INVITE ,
11861208 Membership .KNOCK ,
11871209 ):
11881210 # This should never happen. If someone is invited/knocked on room, then
11891211 # there should be an event for it.
1190- assert rooms_membership_for_user_at_to_token .event_id is not None
1212+ assert room_membership_for_user_at_to_token .event_id is not None
11911213
11921214 invite_or_knock_event = await self .store .get_event (
1193- rooms_membership_for_user_at_to_token .event_id
1215+ room_membership_for_user_at_to_token .event_id
11941216 )
11951217
11961218 stripped_state = []
@@ -1206,7 +1228,7 @@ async def get_room_sync_data(
12061228 stripped_state .append (strip_event (invite_or_knock_event ))
12071229
12081230 # TODO: Handle state resets. For example, if we see
1209- # `rooms_membership_for_user_at_to_token .membership = Membership.LEAVE` but
1231+ # `room_membership_for_user_at_to_token .membership = Membership.LEAVE` but
12101232 # `required_state` doesn't include it, we should indicate to the client that a
12111233 # state reset happened. Perhaps we should indicate this by setting `initial:
12121234 # True` and empty `required_state`.
@@ -1226,7 +1248,7 @@ async def get_room_sync_data(
12261248 # `invite`/`knock` rooms only have `stripped_state`. See
12271249 # https://github.com/matrix-org/matrix-spec-proposals/pull/3575#discussion_r1653045932
12281250 room_state : Optional [StateMap [EventBase ]] = None
1229- if rooms_membership_for_user_at_to_token .membership not in (
1251+ if room_membership_for_user_at_to_token .membership not in (
12301252 Membership .INVITE ,
12311253 Membership .KNOCK ,
12321254 ):
@@ -1303,15 +1325,15 @@ async def get_room_sync_data(
13031325 # initial sync
13041326 if initial :
13051327 # People shouldn't see past their leave/ban event
1306- if rooms_membership_for_user_at_to_token .membership in (
1328+ if room_membership_for_user_at_to_token .membership in (
13071329 Membership .LEAVE ,
13081330 Membership .BAN ,
13091331 ):
13101332 room_state = await self .storage_controllers .state .get_state_at (
13111333 room_id ,
13121334 stream_position = to_token .copy_and_replace (
13131335 StreamKeyType .ROOM ,
1314- rooms_membership_for_user_at_to_token .event_pos .to_room_stream_token (),
1336+ room_membership_for_user_at_to_token .event_pos .to_room_stream_token (),
13151337 ),
13161338 state_filter = state_filter ,
13171339 # Partially-stated rooms should have all state events except for
@@ -1341,6 +1363,20 @@ async def get_room_sync_data(
13411363 # we can return updates instead of the full required state.
13421364 raise NotImplementedError ()
13431365
1366+ # Figure out the last bump event in the room
1367+ last_bump_event_result = (
1368+ await self .store .get_last_event_pos_in_room_before_stream_ordering (
1369+ room_id , to_token .room_key , event_types = DEFAULT_BUMP_EVENT_TYPES
1370+ )
1371+ )
1372+
1373+ # By default, just choose the membership event position
1374+ bump_stamp = room_membership_for_user_at_to_token .event_pos .stream
1375+ # But if we found a bump event, use that instead
1376+ if last_bump_event_result is not None :
1377+ _ , bump_event_pos = last_bump_event_result
1378+ bump_stamp = bump_event_pos .stream
1379+
13441380 return SlidingSyncResult .RoomResult (
13451381 # TODO: Dummy value
13461382 name = None ,
@@ -1358,6 +1394,7 @@ async def get_room_sync_data(
13581394 prev_batch = prev_batch_token ,
13591395 limited = limited ,
13601396 num_live = num_live ,
1397+ bump_stamp = bump_stamp ,
13611398 # TODO: Dummy values
13621399 joined_count = 0 ,
13631400 invited_count = 0 ,
0 commit comments