Merge remote-tracking branch 'origin/develop' into develop
This commit is contained in:
commit
c300514bc7
1 changed files with 92 additions and 19 deletions
|
@ -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) {
|
||||||
|
|
Loading…
Reference in a new issue