From 2d00998b61b0a2a971cd657e34e5c0c4cd04d06b Mon Sep 17 00:00:00 2001 From: Kegan Dougal Date: Mon, 8 Jun 2015 16:10:23 +0100 Subject: [PATCH] Move getFriendlyRoomName to Room. Add recalculate() function to cache info. --- lib/client.js | 66 ++-------------------------------------- lib/models/room-state.js | 8 +++++ lib/models/room.js | 58 +++++++++++++++++++++++++++++++++++ lib/store/memory.js | 13 ++++++-- lib/utils.js | 11 ++++++- 5 files changed, 89 insertions(+), 67 deletions(-) diff --git a/lib/client.js b/lib/client.js index ca630dd25..f99ec8ccc 100644 --- a/lib/client.js +++ b/lib/client.js @@ -496,70 +496,6 @@ module.exports.MatrixClient.prototype = { // due to ambiguity (or should this be on a chat-specific layer)? // reconnect after connectivity outages - /* - * Helper method for retrieving the name of a room suitable for display - * in the UI - * TODO: in future, this should be being generated serverside. - * @param {String} roomId ID of room whose name is to be resolved - * @return {String} human-readable label for room. - */ - getFriendlyRoomName: function(roomId) { - // we need a store to track the inputs for calculating room names - if (!this.store) { - return roomId; - } - - // check for an alias, if any. for now, assume first alias is the - // official one. - var alias; - var mRoomAliases = this.store.getStateEvents(roomId, 'm.room.aliases')[0]; - if (mRoomAliases) { - alias = mRoomAliases.event.content.aliases[0]; - } - - var mRoomName = this.store.getStateEvent(roomId, 'm.room.name', ''); - if (mRoomName) { - return mRoomName.event.content.name + (alias ? " (" + alias + ")" : ""); - } - else if (alias) { - return alias; - } - else { - var userId = this.credentials.userId; - var members = this.store.getStateEvents(roomId, 'm.room.member') - .filter(function(event) { - return event.event.user_id !== userId; - }); - - if (members.length === 0) { - return "Unknown"; - } - else if (members.length == 1) { - return ( - members[0].event.content.displayname || - members[0].event.user_id - ); - } - else if (members.length == 2) { - return ( - (members[0].event.content.displayname || - members[0].event.user_id) + - " and " + - (members[1].event.content.displayname || - members[1].event.user_id) - ); - } - else { - return ( - (members[0].event.content.displayname || - members[0].event.user_id) + - " and " + - (members.length - 1) + " others" - ); - } - } - }, - /** * High level helper method to call initialSync, emit the resulting events, * and then start polling the eventStream for new events. @@ -607,6 +543,8 @@ module.exports.MatrixClient.prototype = { utils.map(data.rooms[i].messages.chunk, eventMapper) ); + room.recalculate(); + self.store.storeRoom(room); } } diff --git a/lib/models/room-state.js b/lib/models/room-state.js index b52c6c1c3..feead6339 100644 --- a/lib/models/room-state.js +++ b/lib/models/room-state.js @@ -25,6 +25,14 @@ function RoomState(roomId) { this.paginationToken = null; } RoomState.prototype = { + /** + * Get all RoomMembers in this room. + * @return {Array} A list of RoomMembers. + */ + getMembers: function() { + return utils.values(this.members); + }, + /** * Get state events from the state of the room. * @param {string} eventType The event type of the state event. diff --git a/lib/models/room.js b/lib/models/room.js index 91575f0e4..c5f2ea865 100644 --- a/lib/models/room.js +++ b/lib/models/room.js @@ -3,6 +3,8 @@ * @module models/room */ var RoomState = require("./room-state"); +var RoomSummary = require("./room-summary"); +var utils = require("../utils"); /** * Construct a new Room. @@ -43,6 +45,62 @@ Room.prototype = { this.timeline.push(events[i]); } } + }, + + /** + * Recalculate various aspects of the room, including the room name and + * room summary. Call this any time the room's current state is modified. + * @param {string} userId The client's user ID. + */ + recalculate: function(userId) { + this.name = this.calculateRoomName(userId); + this.summary = new RoomSummary(this.roomId, { + title: this.name + }); + }, + + /** + * Calculates the name of the room from the current room state. + * @param {string} userId The client's user ID. Used to filter room members + * correctly. + * @return {string} The calculated room name. + */ + calculateRoomName: function(userId) { + // check for an alias, if any. for now, assume first alias is the + // official one. + var alias; + var mRoomAliases = this.currentState.getStateEvents("m.room.aliases")[0]; + if (mRoomAliases && utils.isArray(mRoomAliases.getContent().aliases)) { + alias = mRoomAliases.getContent().aliases[0]; + } + + var mRoomName = this.currentState.getStateEvents('m.room.name', ''); + if (mRoomName) { + return mRoomName.getContent().name + (alias ? " (" + alias + ")" : ""); + } + else if (alias) { + return alias; + } + else { + var members = this.currentState.getMembers(); + + if (members.length === 0) { + return "Unknown"; + } + else if (members.length == 1) { + return members[0].name; + } + else if (members.length == 2) { + return ( + members[0].name + " and " + members[1].name + ); + } + else { + return ( + members[0].name + " and " + (members.length - 1) + " others" + ); + } + } } }; diff --git a/lib/store/memory.js b/lib/store/memory.js index 51e1159d4..e14fee685 100644 --- a/lib/store/memory.js +++ b/lib/store/memory.js @@ -3,12 +3,16 @@ * This is an internal module. See {@link MatrixInMemoryStore} for the public class. * @module store/memory */ + var utils = require("../utils"); /** * Construct a new in-memory data store for the Matrix Client. * @constructor */ module.exports.MatrixInMemoryStore = function MatrixInMemoryStore() { + this.rooms = { + // roomId: Room + }; this.presence = { // presence objects keyed by userId }; @@ -21,7 +25,7 @@ module.exports.MatrixInMemoryStore.prototype = { * @param {Room} room The room to be stored. All properties must be stored. */ storeRoom: function(room) { - + this.rooms[room.roomId] = room; }, /** @@ -30,6 +34,9 @@ module.exports.MatrixInMemoryStore.prototype = { * @return {Room} The room or null. */ getRoom: function(roomId) { + if (this.rooms[roomId]) { + return this.rooms[roomId]; + } return null; }, @@ -38,7 +45,9 @@ module.exports.MatrixInMemoryStore.prototype = { * @return {RoomSummary[]} A summary of each room. */ getRoomSummaries: function() { - return []; + return utils.map(utils.values(this.rooms), function(room) { + return room.summary; + }); }, setPresenceEvents: function(presenceEvents) { diff --git a/lib/utils.js b/lib/utils.js index eeceeb7e5..645f35e78 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -42,7 +42,7 @@ module.exports.encodeUri = function(pathTemplate, variables) { * Applies a map function to the given array. * @param {Array} array The array to apply the function to. * @param {Function} fn The function that will be invoked for each element in - * the array. + * the array with the signature fn(element){...} * @return {Array} A new array with the results of the function. */ module.exports.map = function(array, fn) { @@ -108,6 +108,15 @@ module.exports.isFunction = function(value) { return Object.prototype.toString.call(value) == "[object Function]"; }; +/** + * Checks if the given thing is an array. + * @param {*} value The thing to check. + * @return {boolean} True if it is an array. + */ +module.exports.isArray = function(value) { + return Boolean(value && value.constructor === Array); +}; + /** * Checks that the given object has the specified keys. * @param {Object} obj The object to check.