Merge remote-tracking branch 'origin/develop' into develop

This commit is contained in:
Weblate 2018-11-02 00:24:09 +00:00
commit c300514bc7

View file

@ -54,6 +54,24 @@ class RoomListStore extends Store {
"im.vector.fake.archived": [], "im.vector.fake.archived": [],
}, },
ready: false, ready: false,
// The room cache stores a mapping of roomId to cache record.
// Each cache record is a key/value pair for various bits of
// data used to sort the room list. Currently this stores the
// following bits of informations:
// "timestamp": number, The timestamp of the last relevant
// event in the room.
// "notifications": boolean, Whether or not the user has been
// highlighted on any unread events.
// "unread": boolean, Whether or not the user has any
// unread events.
//
// All of the cached values are lazily loaded on read in the
// recents comparator. When an event is received for a particular
// room, all the cached values are invalidated - forcing the
// next read to set new values. The entries do not expire on
// their own.
roomCache: {},
}; };
} }
@ -85,6 +103,8 @@ class RoomListStore extends Store {
!payload.isLiveUnfilteredRoomTimelineEvent || !payload.isLiveUnfilteredRoomTimelineEvent ||
!this._eventTriggersRecentReorder(payload.event) !this._eventTriggersRecentReorder(payload.event)
) break; ) break;
this._clearCachedRoomState(payload.event.getRoomId());
this._generateRoomLists(); this._generateRoomLists();
} }
break; break;
@ -112,6 +132,8 @@ class RoomListStore extends Store {
if (liveTimeline !== eventTimeline || if (liveTimeline !== eventTimeline ||
!this._eventTriggersRecentReorder(payload.event) !this._eventTriggersRecentReorder(payload.event)
) break; ) break;
this._clearCachedRoomState(payload.event.getRoomId());
this._generateRoomLists(); this._generateRoomLists();
} }
break; break;
@ -217,11 +239,18 @@ class RoomListStore extends Store {
} }
}); });
// Note: we check the settings up here instead of in the forEach or
// in the _recentsComparator to avoid hitting the SettingsStore a few
// thousand times.
const pinUnread = SettingsStore.getValue("pinUnreadRooms");
const pinMentioned = SettingsStore.getValue("pinMentionedRooms");
Object.keys(lists).forEach((listKey) => { Object.keys(lists).forEach((listKey) => {
let comparator; let comparator;
switch (RoomListStore._listOrders[listKey]) { switch (RoomListStore._listOrders[listKey]) {
case "recent": case "recent":
comparator = this._recentsComparator; comparator = (roomA, roomB) => {
return this._recentsComparator(roomA, roomB, pinUnread, pinMentioned);
};
break; break;
case "manual": case "manual":
default: default:
@ -237,6 +266,44 @@ class RoomListStore extends Store {
}); });
} }
_updateCachedRoomState(roomId, type, value) {
const roomCache = this._state.roomCache;
if (!roomCache[roomId]) roomCache[roomId] = {};
if (value) roomCache[roomId][type] = value;
else delete roomCache[roomId][type];
this._setState({roomCache});
}
_clearCachedRoomState(roomId) {
const roomCache = this._state.roomCache;
delete roomCache[roomId];
this._setState({roomCache});
}
_getRoomState(room, type) {
const roomId = room.roomId;
const roomCache = this._state.roomCache;
if (roomCache[roomId] && typeof roomCache[roomId][type] !== 'undefined') {
return roomCache[roomId][type];
}
if (type === "timestamp") {
const ts = this._tsOfNewestEvent(room);
this._updateCachedRoomState(roomId, "timestamp", ts);
return ts;
} else if (type === "unread") {
const unread = room.getUnreadNotificationCount() > 0;
this._updateCachedRoomState(roomId, "unread", unread);
return unread;
} else if (type === "notifications") {
const notifs = room.getUnreadNotificationCount("highlight") > 0;
this._updateCachedRoomState(roomId, "notifications", notifs);
return notifs;
} else throw new Error("Unrecognized room cache type: " + type);
}
_eventTriggersRecentReorder(ev) { _eventTriggersRecentReorder(ev) {
return ev.getTs() && ( return ev.getTs() && (
Unread.eventTriggersUnreadCount(ev) || Unread.eventTriggersUnreadCount(ev) ||
@ -262,34 +329,40 @@ class RoomListStore extends Store {
} }
} }
_recentsComparator(roomA, roomB) { _recentsComparator(roomA, roomB, pinUnread, pinMentioned) {
const pinUnread = SettingsStore.getValue("pinUnreadRooms");
const pinMentioned = SettingsStore.getValue("pinMentionedRooms");
// We try and set the ordering to be Mentioned > Unread > Recent // We try and set the ordering to be Mentioned > Unread > Recent
// assuming the user has the right settings, of course // assuming the user has the right settings, of course.
const timestampA = this._getRoomState(roomA, "timestamp");
const timestampB = this._getRoomState(roomB, "timestamp");
const timestampDiff = timestampB - timestampA;
if (pinMentioned) { if (pinMentioned) {
const mentionsA = roomA.getUnreadNotificationCount("highlight") > 0; const mentionsA = this._getRoomState(roomA, "notifications");
const mentionsB = roomB.getUnreadNotificationCount("highlight") > 0; const mentionsB = this._getRoomState(roomB, "notifications");
if (mentionsA && !mentionsB) return -1; if (mentionsA && !mentionsB) return -1;
if (!mentionsA && mentionsB) return 1; if (!mentionsA && mentionsB) return 1;
if (mentionsA && mentionsB) return 0;
// If neither have mentions, fall through to remaining checks // If they both have notifications, sort by timestamp.
// If neither have notifications (the fourth check not shown
// here), then try and sort by unread messages and finally by
// timestamp.
if (mentionsA && mentionsB) return timestampDiff;
} }
if (pinUnread) { if (pinUnread) {
const unreadA = Unread.doesRoomHaveUnreadMessages(roomA); const unreadA = this._getRoomState(roomA, "unread");
const unreadB = Unread.doesRoomHaveUnreadMessages(roomB); const unreadB = this._getRoomState(roomB, "unread");
if (unreadA && !unreadB) return -1; if (unreadA && !unreadB) return -1;
if (!unreadA && unreadB) return 1; if (!unreadA && unreadB) return 1;
if (unreadA && unreadB) return 0;
// If neither have unread messages, fall through to remaining checks // If they both have unread messages, sort by timestamp
// If nether have unread message (the fourth check not shown
// here), then just sort by timestamp anyways.
if (unreadA && unreadB) return timestampDiff;
} }
// XXX: We could use a cache here and update it when we see new return timestampDiff;
// events that trigger a reorder
return this._tsOfNewestEvent(roomB) - this._tsOfNewestEvent(roomA);
} }
_lexicographicalComparator(roomA, roomB) { _lexicographicalComparator(roomA, roomB) {