"use strict"; /** * @module models/room-member */ var EventEmitter = require("events").EventEmitter; var utils = require("../utils"); /** * Construct a new room member. * @constructor * @param {string} roomId The room ID of the member. * @param {string} userId The user ID of the member. * @prop {string} roomId The room ID for this member. * @prop {string} userId The user ID of this member. * @prop {boolean} typing True if the room member is currently typing. * @prop {string} name The human-readable name for this room member. * @prop {Number} powerLevel The power level for this room member. * @prop {Number} powerLevelNorm The normalised power level (0-100) for this * room member. * @prop {User} user The User object for this room member, if one exists. * @prop {string} membership The membership state for this room member e.g. 'join'. * @prop {Object} events The events describing this RoomMember. * @prop {MatrixEvent} events.member The m.room.member event for this RoomMember. */ function RoomMember(roomId, userId) { this.roomId = roomId; this.userId = userId; this.typing = false; this.name = userId; this.powerLevel = 0; this.powerLevelNorm = 0; this.user = null; this.membership = null; this.events = { member: null }; } utils.inherits(RoomMember, EventEmitter); /** * Update this room member's membership event. May fire "RoomMember.name" if * this event updates this member's name. * @param {MatrixEvent} event The m.room.member event * @param {RoomState} roomState Optional. The room state to take into account * when calculating (e.g. for disambiguating users with the same name). * @fires module:client~MatrixClient#event:"RoomMember.name" * @fires module:client~MatrixClient#event:"RoomMember.membership" */ RoomMember.prototype.setMembershipEvent = function(event, roomState) { if (event.getType() !== "m.room.member") { return; } this.events.member = event; var oldMembership = this.membership; this.membership = event.getDirectionalContent().membership; var oldName = this.name; this.name = calculateDisplayName(this, event, roomState); if (oldMembership !== this.membership) { this.emit("RoomMember.membership", event, this); } if (oldName !== this.name) { this.emit("RoomMember.name", event, this); } }; /** * Update this room member's power level event. May fire * "RoomMember.powerLevel" if this event updates this member's power levels. * @param {MatrixEvent} powerLevelEvent The m.room.power_levels * event * @fires module:client~MatrixClient#event:"RoomMember.powerLevel" */ RoomMember.prototype.setPowerLevelEvent = function(powerLevelEvent) { if (powerLevelEvent.getType() !== "m.room.power_levels") { return; } var maxLevel = powerLevelEvent.getContent().users_default || 0; utils.forEach(utils.values(powerLevelEvent.getContent().users), function(lvl) { maxLevel = Math.max(maxLevel, lvl); }); var oldPowerLevel = this.powerLevel; var oldPowerLevelNorm = this.powerLevelNorm; this.powerLevel = ( powerLevelEvent.getContent().users[this.userId] || powerLevelEvent.getContent().users_default || 0 ); this.powerLevelNorm = 0; if (maxLevel > 0) { this.powerLevelNorm = (this.powerLevel * 100) / maxLevel; } // emit for changes in powerLevelNorm as well (since the app will need to // redraw everyone's level if the max has changed) if (oldPowerLevel !== this.powerLevel || oldPowerLevelNorm !== this.powerLevelNorm) { this.emit("RoomMember.powerLevel", powerLevelEvent, this); } }; /** * Update this room member's typing event. May fire "RoomMember.typing" if * this event changes this member's typing state. * @param {MatrixEvent} event The typing event * @fires module:client~MatrixClient#event:"RoomMember.typing" */ RoomMember.prototype.setTypingEvent = function(event) { if (event.getType() !== "m.typing") { return; } var oldTyping = this.typing; this.typing = false; var typingList = event.getContent().user_ids; if (!utils.isArray(typingList)) { // malformed event :/ bail early. TODO: whine? return; } if (typingList.indexOf(this.userId) !== -1) { this.typing = true; } if (oldTyping !== this.typing) { this.emit("RoomMember.typing", event, this); } }; function calculateDisplayName(member, event, roomState) { var displayName = event.getDirectionalContent().displayname; var selfUserId = member.userId; if (!displayName) { return selfUserId; } if (!roomState) { return displayName; } var stateEvents = utils.filter( roomState.getStateEvents("m.room.member"), function(e) { return e.getContent().displayname === displayName && e.getSender() !== selfUserId; } ); if (stateEvents.length > 0) { // need to disambiguate return displayName + " (" + selfUserId + ")"; } return displayName; } /** * The RoomMember class. */ module.exports = RoomMember; /** * Fires whenever any room member's name changes. * @event module:client~MatrixClient#"RoomMember.name" * @param {MatrixEvent} event The matrix event which caused this event to fire. * @param {RoomMember} member The member whose RoomMember.name changed. * @example * matrixClient.on("RoomMember.name", function(event, member){ * var newName = member.name; * }); */ /** * Fires whenever any room member's membership state changes. * @event module:client~MatrixClient#"RoomMember.membership" * @param {MatrixEvent} event The matrix event which caused this event to fire. * @param {RoomMember} member The member whose RoomMember.membership changed. * @example * matrixClient.on("RoomMember.membership", function(event, member){ * var newState = member.membership; * }); */ /** * Fires whenever any room member's typing state changes. * @event module:client~MatrixClient#"RoomMember.typing" * @param {MatrixEvent} event The matrix event which caused this event to fire. * @param {RoomMember} member The member whose RoomMember.typing changed. * @example * matrixClient.on("RoomMember.typing", function(event, member){ * var isTyping = member.typing; * }); */ /** * Fires whenever any room member's power level changes. * @event module:client~MatrixClient#"RoomMember.powerLevel" * @param {MatrixEvent} event The matrix event which caused this event to fire. * @param {RoomMember} member The member whose RoomMember.powerLevel changed. * @example * matrixClient.on("RoomMember.powerLevel", function(event, member){ * var newPowerLevel = member.powerLevel; * var newNormPowerLevel = member.powerLevelNorm; * }); */