From 690309adfc16183e7cd008f9e45ce5b70d36bd53 Mon Sep 17 00:00:00 2001 From: David Baker Date: Mon, 26 Sep 2016 18:02:14 +0100 Subject: [PATCH 1/2] Bring back the little green men without slowness Introduces a singleton DMRoomMap that subscribes to account data to keep itself up to date so we don't have to keep doing the map inversion for each room tile. --- src/Lifecycle.js | 3 +++ src/components/views/rooms/RoomTile.js | 11 +++----- src/utils/DMRoomMap.js | 37 ++++++++++++++++++++++++++ 3 files changed, 44 insertions(+), 7 deletions(-) diff --git a/src/Lifecycle.js b/src/Lifecycle.js index 53adea6196..cf1feea8c6 100644 --- a/src/Lifecycle.js +++ b/src/Lifecycle.js @@ -22,6 +22,7 @@ import Notifier from './Notifier' import UserActivity from './UserActivity'; import Presence from './Presence'; import dis from './dispatcher'; +import DMRoomMap from './utils/DMRoomMap'; /** * Called at startup, to attempt to build a logged-in Matrix session. It tries @@ -317,6 +318,7 @@ export function startMatrixClient() { Notifier.start(); UserActivity.start(); Presence.start(); + DMRoomMap.shared().start(); MatrixClientPeg.start(); } @@ -354,6 +356,7 @@ export function stopMatrixClient() { Notifier.stop(); UserActivity.stop(); Presence.stop(); + DMRoomMap.shared().stop(); var cli = MatrixClientPeg.get(); if (cli) { cli.stopClient(); diff --git a/src/components/views/rooms/RoomTile.js b/src/components/views/rooms/RoomTile.js index 9efb7164bb..1f0338a4de 100644 --- a/src/components/views/rooms/RoomTile.js +++ b/src/components/views/rooms/RoomTile.js @@ -70,8 +70,7 @@ module.exports = React.createClass({ }, _isDirectMessageRoom: function(roomId) { - const dmRoomMap = new DMRoomMap(MatrixClientPeg.get()); - var dmRooms = dmRoomMap.getUserIdForRoomId(roomId); + var dmRooms = DMRoomMap.shared().getUserIdForRoomId(roomId); if (dmRooms) { return true; } else { @@ -277,11 +276,9 @@ module.exports = React.createClass({ var RoomAvatar = sdk.getComponent('avatars.RoomAvatar'); var directMessageIndicator; - // Temporarily turning off the LGM badges as isDirectMessageRoom is horribly unperformant - // - see https://github.com/vector-im/vector-web/issues/2343 - // if (this._isDirectMessageRoom(this.props.room.roomId)) { - // directMessageIndicator = dm; - // } + if (this._isDirectMessageRoom(this.props.room.roomId)) { + directMessageIndicator = dm; + } // These props are injected by React DnD, // as defined by your `collect` function above: diff --git a/src/utils/DMRoomMap.js b/src/utils/DMRoomMap.js index 78ace8fb11..8209023b3c 100644 --- a/src/utils/DMRoomMap.js +++ b/src/utils/DMRoomMap.js @@ -14,16 +14,25 @@ See the License for the specific language governing permissions and limitations under the License. */ +import MatrixClientPeg from '../MatrixClientPeg'; + /** * Class that takes a Matrix Client and flips the m.direct map * so the operation of mapping a room ID to which user it's a DM * with can be performed efficiently. + * + * With 'start', this can also keep itself up to date over time. */ export default class DMRoomMap { constructor(matrixClient) { this.matrixClient = matrixClient; this.roomToUser = null; + // XXX: Force-bind the event handler method because it + // doesn't call it with our object as the 'this' + // (use a static property arrow function for this when we can) + this._onAccountData = this._onAccountData.bind(this); + const mDirectEvent = matrixClient.getAccountData('m.direct'); if (!mDirectEvent) { this.userToRooms = {}; @@ -32,6 +41,34 @@ export default class DMRoomMap { } } + /** + * Returns a shared instance of the class + * that uses the singleton matrix client + * The shared instance must be started before use. + */ + static shared() { + if (!DMRoomMap._sharedInstance) { + DMRoomMap._sharedInstance = new DMRoomMap(MatrixClientPeg.get()); + } + return DMRoomMap._sharedInstance; + } + + start() { + this._populateRoomToUser(); + this.matrixClient.on("accountData", this._onAccountData); + } + + stop() { + this.matrixClient.removeListener("accountData", this._onAccountData); + } + + _onAccountData(ev) { + this.userToRooms = this.matrixClient.getAccountData('m.direct').getContent(); + if (ev.getType() == 'm.direct') { + this._populateRoomToUser(); + } + } + getDMRoomsForUserId(userId) { // Here, we return the empty list if there are no rooms, // since the number of conversations you have with this user is zero. From 2be1cc9f854c4ffcbfdbc69e2a94facf35edf960 Mon Sep 17 00:00:00 2001 From: David Baker Date: Tue, 27 Sep 2016 09:56:31 +0100 Subject: [PATCH 2/2] Give DMRoomMap an explicit makeShared Otherwise it will hang on to the old state client on logout. --- src/Lifecycle.js | 2 +- src/utils/DMRoomMap.js | 14 ++++++++++---- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/Lifecycle.js b/src/Lifecycle.js index cf1feea8c6..62fbe5f929 100644 --- a/src/Lifecycle.js +++ b/src/Lifecycle.js @@ -318,7 +318,7 @@ export function startMatrixClient() { Notifier.start(); UserActivity.start(); Presence.start(); - DMRoomMap.shared().start(); + DMRoomMap.makeShared().start(); MatrixClientPeg.start(); } diff --git a/src/utils/DMRoomMap.js b/src/utils/DMRoomMap.js index 8209023b3c..d6242719ba 100644 --- a/src/utils/DMRoomMap.js +++ b/src/utils/DMRoomMap.js @@ -41,15 +41,21 @@ export default class DMRoomMap { } } + /** + * Makes and returns a new shared instance that can then be accessed + * with shared(). This returned instance is not automatically started. + */ + static makeShared() { + DMRoomMap._sharedInstance = new DMRoomMap(MatrixClientPeg.get()); + return DMRoomMap._sharedInstance; + } + /** * Returns a shared instance of the class * that uses the singleton matrix client * The shared instance must be started before use. */ static shared() { - if (!DMRoomMap._sharedInstance) { - DMRoomMap._sharedInstance = new DMRoomMap(MatrixClientPeg.get()); - } return DMRoomMap._sharedInstance; } @@ -63,8 +69,8 @@ export default class DMRoomMap { } _onAccountData(ev) { - this.userToRooms = this.matrixClient.getAccountData('m.direct').getContent(); if (ev.getType() == 'm.direct') { + this.userToRooms = this.matrixClient.getAccountData('m.direct').getContent(); this._populateRoomToUser(); } }