From aac5bcfe80538c5f2aa93a079a4e8428200bc6b5 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Tue, 5 Dec 2017 11:25:30 +0000 Subject: [PATCH 1/7] Attempt to improve TagPanel performance by only recalculating rooms to show (for a given group) when a group updates. --- src/components/views/rooms/RoomList.js | 55 +++++++++++++++----------- 1 file changed, 31 insertions(+), 24 deletions(-) diff --git a/src/components/views/rooms/RoomList.js b/src/components/views/rooms/RoomList.js index 6157f65c9d..fbb563cf14 100644 --- a/src/components/views/rooms/RoomList.js +++ b/src/components/views/rooms/RoomList.js @@ -71,6 +71,8 @@ module.exports = React.createClass({ this.mounted = false; const cli = MatrixClientPeg.get(); + const dmRoomMap = new DMRoomMap(cli); + cli.on("Room", this.onRoom); cli.on("deleteRoom", this.onDeleteRoom); cli.on("Room.timeline", this.onRoomTimeline); @@ -84,8 +86,8 @@ module.exports = React.createClass({ cli.on("Group.myMembership", this._onGroupMyMembership); this._groupStores = {}; + this._selectedTagsRoomIdsForGroup = {}; this._selectedTagsRoomIds = []; - this._selectedTagsUserIds = []; // When the selected tags are changed, initialise a group store if necessary this._filterStoreToken = FilterStore.addListener(() => { FilterStore.getSelectedTags().forEach((tag) => { @@ -94,10 +96,12 @@ module.exports = React.createClass({ } this._groupStores[tag] = GroupStoreCache.getGroupStore(tag); this._groupStores[tag].registerListener(() => { - this.updateSelectedTagsEntities(); + // This group's rooms or members may have updated, update rooms for its tag + this.updateSelectedTagsRooms(dmRoomMap, [tag]); }); }); - this.updateSelectedTagsEntities(); + // Filters themselves have changed, refresh the selected tags + this.updateSelectedTagsRooms(dmRoomMap, FilterStore.getSelectedTags()); }); this.refreshRoomList(); @@ -260,20 +264,31 @@ module.exports = React.createClass({ }, 500), // Update which rooms and users should appear in RoomList as dictated by selected tags - updateSelectedTagsEntities: function() { + updateSelectedTagsRooms: function(dmRoomMap, updatedTags) { if (!this.mounted) return; - this._selectedTagsRoomIds = []; - this._selectedTagsUserIds = []; - FilterStore.getSelectedTags().forEach((tag) => { - this._selectedTagsRoomIds = this._selectedTagsRoomIds.concat( - this._groupStores[tag].getGroupRooms().map((room) => room.roomId), - ); - // TODO: Check if room has been tagged to the group by the user + updatedTags.forEach((tag) => { + // For now, only handle group tags + const store = this._groupStores[tag]; + if (!store) return; - this._selectedTagsUserIds = this._selectedTagsUserIds.concat( - this._groupStores[tag].getGroupMembers().map((member) => member.userId), + this._selectedTagsRoomIdsForGroup[tag] = []; + store.getGroupRooms().forEach((room) => this._selectedTagsRoomIdsForGroup[tag].push(room.roomId)); + store.getGroupMembers().forEach((member) => { + if (member.userId === MatrixClientPeg.get().credentials.userId) return; + dmRoomMap.getDMRoomsForUserId(member.userId).forEach( + (roomId) => this._selectedTagsRoomIdsForGroup[tag].push(roomId), + ); + }); + // TODO: Check if room has been tagged to the group by the user + }); + + this._selectedTagsRoomIds = []; + FilterStore.getSelectedTags().forEach((tag) => { + (this._selectedTagsRoomIdsForGroup[tag] || []).forEach( + (roomId) => this._selectedTagsRoomIds.push(roomId), ); }); + this.setState({ selectedTags: FilterStore.getSelectedTags(), }, () => { @@ -281,17 +296,9 @@ module.exports = React.createClass({ }); }, - isRoomInSelectedTags: function(room, me, dmRoomMap) { + isRoomInSelectedTags: function(room) { // No selected tags = every room is visible in the list - if (this.state.selectedTags.length === 0) { - return true; - } - if (this._selectedTagsRoomIds.includes(room.roomId)) { - return true; - } - const dmUserId = dmRoomMap.getUserIdForRoomId(room.roomId); - return dmUserId && dmUserId !== me.userId && - this._selectedTagsUserIds.includes(dmUserId); + return this.state.selectedTags.length === 0 || this._selectedTagsRoomIds.includes(room.roomId); }, refreshRoomList: function() { @@ -341,7 +348,7 @@ module.exports = React.createClass({ const tagNames = Object.keys(room.tags); // Apply TagPanel filtering, derived from FilterStore - if (!this.isRoomInSelectedTags(room, me, dmRoomMap)) { + if (!this.isRoomInSelectedTags(room)) { return; } From 3732fd29d5318ba28b74f6076a0d687940f51ef0 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Thu, 14 Dec 2017 16:17:06 +0000 Subject: [PATCH 2/7] Comments for instance variables --- src/components/views/rooms/RoomList.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/components/views/rooms/RoomList.js b/src/components/views/rooms/RoomList.js index fbb563cf14..95d910c880 100644 --- a/src/components/views/rooms/RoomList.js +++ b/src/components/views/rooms/RoomList.js @@ -86,7 +86,12 @@ module.exports = React.createClass({ cli.on("Group.myMembership", this._onGroupMyMembership); this._groupStores = {}; - this._selectedTagsRoomIdsForGroup = {}; + // A map between tags which are group IDs and the room IDs of rooms that should be kept + // in the room list when filtering by that tag. + this._selectedTagsRoomIdsForGroup = { + // $groupId: [$roomId1, $roomId2, ...], + }; + // All rooms that should be kept in the room list when filtering this._selectedTagsRoomIds = []; // When the selected tags are changed, initialise a group store if necessary this._filterStoreToken = FilterStore.addListener(() => { From df1134f092699dcb4c973816708be01a9fdc8d83 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Thu, 14 Dec 2017 16:34:49 +0000 Subject: [PATCH 3/7] Use "shared" DMRoomMap --- src/components/views/rooms/RoomList.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/views/rooms/RoomList.js b/src/components/views/rooms/RoomList.js index 95d910c880..d94fef7d31 100644 --- a/src/components/views/rooms/RoomList.js +++ b/src/components/views/rooms/RoomList.js @@ -71,7 +71,6 @@ module.exports = React.createClass({ this.mounted = false; const cli = MatrixClientPeg.get(); - const dmRoomMap = new DMRoomMap(cli); cli.on("Room", this.onRoom); cli.on("deleteRoom", this.onDeleteRoom); @@ -85,6 +84,7 @@ module.exports = React.createClass({ cli.on("accountData", this.onAccountData); cli.on("Group.myMembership", this._onGroupMyMembership); + const dmRoomMap = DMRoomMap.shared(); this._groupStores = {}; // A map between tags which are group IDs and the room IDs of rooms that should be kept // in the room list when filtering by that tag. @@ -333,7 +333,7 @@ module.exports = React.createClass({ lists["m.lowpriority"] = []; lists["im.vector.fake.archived"] = []; - const dmRoomMap = new DMRoomMap(MatrixClientPeg.get()); + const dmRoomMap = DMRoomMap.shared(); MatrixClientPeg.get().getRooms().forEach((room) => { const me = room.getMember(MatrixClientPeg.get().credentials.userId); if (!me) return; From 961d5e1868275712a649f5ffe29a0179112cb694 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Fri, 15 Dec 2017 14:23:35 +0000 Subject: [PATCH 4/7] Split updatedSelectedTagsRooms because we don't need to get the rooms for all groups when the filtered tags change. --- src/components/views/rooms/RoomList.js | 33 +++++++++++++------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/src/components/views/rooms/RoomList.js b/src/components/views/rooms/RoomList.js index d94fef7d31..ec13f6d535 100644 --- a/src/components/views/rooms/RoomList.js +++ b/src/components/views/rooms/RoomList.js @@ -102,11 +102,12 @@ module.exports = React.createClass({ this._groupStores[tag] = GroupStoreCache.getGroupStore(tag); this._groupStores[tag].registerListener(() => { // This group's rooms or members may have updated, update rooms for its tag - this.updateSelectedTagsRooms(dmRoomMap, [tag]); + this.updateSelectedTagsRoomsForGroups(dmRoomMap, tag); + this.updateSelectedTagsRooms(); }); }); // Filters themselves have changed, refresh the selected tags - this.updateSelectedTagsRooms(dmRoomMap, FilterStore.getSelectedTags()); + this.updateSelectedTagsRooms(); }); this.refreshRoomList(); @@ -269,24 +270,24 @@ module.exports = React.createClass({ }, 500), // Update which rooms and users should appear in RoomList as dictated by selected tags - updateSelectedTagsRooms: function(dmRoomMap, updatedTags) { + updateSelectedTagsRoomsForGroups: function(dmRoomMap, tag) { if (!this.mounted) return; - updatedTags.forEach((tag) => { - // For now, only handle group tags - const store = this._groupStores[tag]; - if (!store) return; + // For now, only handle group tags + const store = this._groupStores[tag]; + if (!store) return; - this._selectedTagsRoomIdsForGroup[tag] = []; - store.getGroupRooms().forEach((room) => this._selectedTagsRoomIdsForGroup[tag].push(room.roomId)); - store.getGroupMembers().forEach((member) => { - if (member.userId === MatrixClientPeg.get().credentials.userId) return; - dmRoomMap.getDMRoomsForUserId(member.userId).forEach( - (roomId) => this._selectedTagsRoomIdsForGroup[tag].push(roomId), - ); - }); - // TODO: Check if room has been tagged to the group by the user + this._selectedTagsRoomIdsForGroup[tag] = []; + store.getGroupRooms().forEach((room) => this._selectedTagsRoomIdsForGroup[tag].push(room.roomId)); + store.getGroupMembers().forEach((member) => { + if (member.userId === MatrixClientPeg.get().credentials.userId) return; + dmRoomMap.getDMRoomsForUserId(member.userId).forEach( + (roomId) => this._selectedTagsRoomIdsForGroup[tag].push(roomId), + ); }); + // TODO: Check if room has been tagged to the group by the user + }, + updateSelectedTagsRooms: function() { this._selectedTagsRoomIds = []; FilterStore.getSelectedTags().forEach((tag) => { (this._selectedTagsRoomIdsForGroup[tag] || []).forEach( From 653137f6ec56063a77f543088cea767c08e99c82 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Fri, 15 Dec 2017 17:21:20 +0000 Subject: [PATCH 5/7] Update comment --- src/components/views/rooms/RoomList.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/rooms/RoomList.js b/src/components/views/rooms/RoomList.js index ec13f6d535..85a076aa48 100644 --- a/src/components/views/rooms/RoomList.js +++ b/src/components/views/rooms/RoomList.js @@ -269,7 +269,7 @@ module.exports = React.createClass({ this.refreshRoomList(); }, 500), - // Update which rooms and users should appear in RoomList as dictated by selected tags + // Update which rooms and users should appear in RoomList for a given group tag updateSelectedTagsRoomsForGroups: function(dmRoomMap, tag) { if (!this.mounted) return; // For now, only handle group tags From 56affd3d42b9432a804c95cbcbb8b643b06a7b2a Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Fri, 15 Dec 2017 17:29:06 +0000 Subject: [PATCH 6/7] Rename for clarity --- src/components/views/rooms/RoomList.js | 28 +++++++++++++------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/components/views/rooms/RoomList.js b/src/components/views/rooms/RoomList.js index 85a076aa48..1fba2070ba 100644 --- a/src/components/views/rooms/RoomList.js +++ b/src/components/views/rooms/RoomList.js @@ -88,11 +88,11 @@ module.exports = React.createClass({ this._groupStores = {}; // A map between tags which are group IDs and the room IDs of rooms that should be kept // in the room list when filtering by that tag. - this._selectedTagsRoomIdsForGroup = { + this._visibleRoomsForGroup = { // $groupId: [$roomId1, $roomId2, ...], }; // All rooms that should be kept in the room list when filtering - this._selectedTagsRoomIds = []; + this._visibleRooms = []; // When the selected tags are changed, initialise a group store if necessary this._filterStoreToken = FilterStore.addListener(() => { FilterStore.getSelectedTags().forEach((tag) => { @@ -102,12 +102,12 @@ module.exports = React.createClass({ this._groupStores[tag] = GroupStoreCache.getGroupStore(tag); this._groupStores[tag].registerListener(() => { // This group's rooms or members may have updated, update rooms for its tag - this.updateSelectedTagsRoomsForGroups(dmRoomMap, tag); - this.updateSelectedTagsRooms(); + this.updateVisibleRoomsForTag(dmRoomMap, tag); + this.updateVisibleRooms(); }); }); // Filters themselves have changed, refresh the selected tags - this.updateSelectedTagsRooms(); + this.updateVisibleRooms(); }); this.refreshRoomList(); @@ -270,28 +270,28 @@ module.exports = React.createClass({ }, 500), // Update which rooms and users should appear in RoomList for a given group tag - updateSelectedTagsRoomsForGroups: function(dmRoomMap, tag) { + updateVisibleRoomsForTag: function(dmRoomMap, tag) { if (!this.mounted) return; // For now, only handle group tags const store = this._groupStores[tag]; if (!store) return; - this._selectedTagsRoomIdsForGroup[tag] = []; - store.getGroupRooms().forEach((room) => this._selectedTagsRoomIdsForGroup[tag].push(room.roomId)); + this._visibleRoomsForGroup[tag] = []; + store.getGroupRooms().forEach((room) => this._visibleRoomsForGroup[tag].push(room.roomId)); store.getGroupMembers().forEach((member) => { if (member.userId === MatrixClientPeg.get().credentials.userId) return; dmRoomMap.getDMRoomsForUserId(member.userId).forEach( - (roomId) => this._selectedTagsRoomIdsForGroup[tag].push(roomId), + (roomId) => this._visibleRoomsForGroup[tag].push(roomId), ); }); // TODO: Check if room has been tagged to the group by the user }, - updateSelectedTagsRooms: function() { - this._selectedTagsRoomIds = []; + updateVisibleRooms: function() { + this._visibleRooms = []; FilterStore.getSelectedTags().forEach((tag) => { - (this._selectedTagsRoomIdsForGroup[tag] || []).forEach( - (roomId) => this._selectedTagsRoomIds.push(roomId), + (this._visibleRoomsForGroup[tag] || []).forEach( + (roomId) => this._visibleRooms.push(roomId), ); }); @@ -304,7 +304,7 @@ module.exports = React.createClass({ isRoomInSelectedTags: function(room) { // No selected tags = every room is visible in the list - return this.state.selectedTags.length === 0 || this._selectedTagsRoomIds.includes(room.roomId); + return this.state.selectedTags.length === 0 || this._visibleRooms.includes(room.roomId); }, refreshRoomList: function() { From d292dab9c6350530cff81cd057339074ebf1ca0b Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Fri, 15 Dec 2017 17:30:21 +0000 Subject: [PATCH 7/7] More doc --- src/components/views/rooms/RoomList.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/views/rooms/RoomList.js b/src/components/views/rooms/RoomList.js index 1fba2070ba..b305b04fd0 100644 --- a/src/components/views/rooms/RoomList.js +++ b/src/components/views/rooms/RoomList.js @@ -287,6 +287,7 @@ module.exports = React.createClass({ // TODO: Check if room has been tagged to the group by the user }, + // Update which rooms and users should appear according to which tags are selected updateVisibleRooms: function() { this._visibleRooms = []; FilterStore.getSelectedTags().forEach((tag) => {