mirror of
https://github.com/matrix-org/sliding-sync.git
synced 2025-03-10 13:37:11 +00:00
108 lines
4.4 KiB
Go
108 lines
4.4 KiB
Go
package sync3
|
|
|
|
import (
|
|
"encoding/json"
|
|
|
|
"github.com/matrix-org/sliding-sync/internal"
|
|
|
|
"github.com/matrix-org/sliding-sync/sync3/caches"
|
|
)
|
|
|
|
type Room struct {
|
|
Name string `json:"name,omitempty"`
|
|
AvatarChange AvatarChange `json:"avatar,omitempty"`
|
|
Heroes []internal.Hero `json:"heroes,omitempty"`
|
|
RequiredState []json.RawMessage `json:"required_state,omitempty"`
|
|
Timeline []json.RawMessage `json:"timeline,omitempty"`
|
|
InviteState []json.RawMessage `json:"invite_state,omitempty"`
|
|
NotificationCount int64 `json:"notification_count"`
|
|
HighlightCount int64 `json:"highlight_count"`
|
|
Initial bool `json:"initial,omitempty"`
|
|
IsDM bool `json:"is_dm,omitempty"`
|
|
JoinedCount int `json:"joined_count,omitempty"`
|
|
InvitedCount *int `json:"invited_count,omitempty"`
|
|
PrevBatch string `json:"prev_batch,omitempty"`
|
|
NumLive int `json:"num_live,omitempty"`
|
|
Timestamp uint64 `json:"timestamp,omitempty"`
|
|
}
|
|
|
|
// RoomConnMetadata represents a room as seen by one specific connection (hence one
|
|
// specific device).
|
|
type RoomConnMetadata struct {
|
|
// We enclose copies of the data kept in the global and user caches. These snapshots
|
|
// represent the state we reported to the connection the last time they requested
|
|
// a sync. Note that we are free to tweak fields within these copies if we want, to
|
|
// report more appropriate data to clients that kept in the caches.
|
|
internal.RoomMetadata
|
|
caches.UserRoomData
|
|
// plus any per-conn data.
|
|
|
|
// LastInterestedEventTimestamps is a map from list name to the origin_server_ts of
|
|
// the most recent event seen in the room since the user's join that the list is
|
|
// interested in.
|
|
//
|
|
// Connections can specify that a list is only interested in certain event types by
|
|
// providing "bump_event_types" in their sliding sync request. This happens on a
|
|
// list-by-list basis. Because the same room can appear in different lists with
|
|
// different bump criteria, we need to track a LastInterestedEventTimestamp for each
|
|
// list.
|
|
//
|
|
// While this conceptually tracks the internal.RoomMetadata.LastMessageTimestamp
|
|
// field, said field can decrease rapidly at any moment---so
|
|
// LastInterestedEventTimestamp can also decrease at any moment. When sorting by
|
|
// recency, this means rooms can suddenly fall down and jump back up the room
|
|
// list. See also the description of this in the React SDK docs:
|
|
// https://github.com/matrix-org/matrix-react-sdk/blob/526645c79160ab1ad4b4c3845de27d51263a405e/docs/room-list-store.md#tag-sorting-algorithm-recent
|
|
LastInterestedEventTimestamps map[string]uint64
|
|
}
|
|
|
|
// SameRoomAvatar checks if the fields relevant for room avatars have changed between the two metadatas.
|
|
// Returns true if there are no changes.
|
|
func (r *RoomConnMetadata) SameRoomAvatar(next *RoomConnMetadata) bool {
|
|
sameRoomAvatar := r.AvatarEvent == next.AvatarEvent
|
|
if next.IsDM {
|
|
// the avatar is the same IF:
|
|
// - the m.room.avatar event is the same AND
|
|
// - the heroes haven't changed AND
|
|
// - the number of heroes is 1
|
|
return sameRoomAvatar && sameHeroAvatars(r.Heroes, next.Heroes) && len(next.Heroes) == 1
|
|
}
|
|
// the avatar is the same IF:
|
|
// - the m.room.avatar event is the same
|
|
return sameRoomAvatar
|
|
}
|
|
|
|
func sameHeroAvatars(a, b []internal.Hero) bool {
|
|
if len(a) != len(b) {
|
|
return false
|
|
}
|
|
for i := range a {
|
|
if a[i].ID != b[i].ID {
|
|
return false
|
|
}
|
|
if a[i].Avatar != b[i].Avatar {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
|
|
func (r *RoomConnMetadata) GetLastInterestedEventTimestamp(listKey string) uint64 {
|
|
ts, ok := r.LastInterestedEventTimestamps[listKey]
|
|
if ok {
|
|
return ts
|
|
}
|
|
// SetRoom is responsible for maintaining LastInterestedEventTimestamps.
|
|
// However, if a brand-new list appears we don't call SetRoom until we have
|
|
// some RoomEventUpdates to process. We need to ensure we hand back a sensible
|
|
// timestamp. So: use the (current) LastMessageTimestamp as a fallback.
|
|
// TODO: if we had access to the request's bump event types, we could lookup the
|
|
// a timestamp by event type from the global metadata (c.f. ConnState.load).
|
|
ts = r.LastMessageTimestamp
|
|
// Write this value into the map. If we don't and only uninteresting events
|
|
// arrive after, the fallback value will have jumped ahead despite nothing of
|
|
// interest happening.
|
|
r.LastInterestedEventTimestamps[listKey] = ts
|
|
return ts
|
|
}
|