diff --git a/src/Lifecycle.js b/src/Lifecycle.js index 53adea6196..62fbe5f929 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.makeShared().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..d6242719ba 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,40 @@ 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() { + return DMRoomMap._sharedInstance; + } + + start() { + this._populateRoomToUser(); + this.matrixClient.on("accountData", this._onAccountData); + } + + stop() { + this.matrixClient.removeListener("accountData", this._onAccountData); + } + + _onAccountData(ev) { + if (ev.getType() == 'm.direct') { + this.userToRooms = this.matrixClient.getAccountData('m.direct').getContent(); + 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.