diff --git a/src/components/views/avatars/MemberAvatar.js b/src/components/views/avatars/MemberAvatar.js index 21c717aac5..f209006b1c 100644 --- a/src/components/views/avatars/MemberAvatar.js +++ b/src/components/views/avatars/MemberAvatar.js @@ -24,10 +24,16 @@ module.exports = React.createClass({ displayName: 'MemberAvatar', propTypes: { - member: React.PropTypes.object.isRequired, + member: React.PropTypes.object, width: React.PropTypes.number, height: React.PropTypes.number, resizeMethod: React.PropTypes.string, + /** + * The custom display name to use for this member. This can serve as a + * drop in replacement for RoomMember objects, or as a clobber name on + * an existing RoomMember. Used for 3pid invites. + */ + customDisplayName: React.PropTypes.string }, getDefaultProps: function() { @@ -38,64 +44,68 @@ module.exports = React.createClass({ } }, + getInitialState: function() { + var defaultImageUrl = Avatar.defaultAvatarUrlForString( + this.props.customDisplayName || this.props.member.userId + ) + return { + imageUrl: this._getMemberImageUrl() || defaultImageUrl, + defaultImageUrl: defaultImageUrl + }; + }, + componentWillReceiveProps: function(nextProps) { this.refreshUrl(); }, - defaultAvatarUrl: function(member, width, height, resizeMethod) { - return Avatar.defaultAvatarUrlForString(member.userId); - }, - onError: function(ev) { // don't tightloop if the browser can't load a data url - if (ev.target.src == this.defaultAvatarUrl(this.props.member)) { + if (ev.target.src == this.state.defaultImageUrl) { return; } this.setState({ - imageUrl: this.defaultAvatarUrl(this.props.member) + imageUrl: this.state.defaultImageUrl }); }, - _computeUrl: function() { + _getMemberImageUrl: function() { + if (!this.props.member) { return null; } + return Avatar.avatarUrlForMember(this.props.member, this.props.width, this.props.height, this.props.resizeMethod); }, + _getInitialLetter: function() { + var name = this.props.customDisplayName || this.props.member.name; + var initial = name[0]; + if (initial === '@' && name[1]) { + initial = name[1]; + } + return initial.toUpperCase(); + }, + refreshUrl: function() { - var newUrl = this._computeUrl(); + var newUrl = this._getMemberImageUrl(); if (newUrl != this.currentUrl) { this.currentUrl = newUrl; this.setState({imageUrl: newUrl}); } }, - getInitialState: function() { - return { - imageUrl: this._computeUrl() - }; - }, - - - /////////////// - render: function() { - // XXX: recalculates default avatar url constantly - if (this.state.imageUrl === this.defaultAvatarUrl(this.props.member)) { - var initial; - if (this.props.member.name[0]) - initial = this.props.member.name[0].toUpperCase(); - if (initial === '@' && this.props.member.name[1]) - initial = this.props.member.name[1].toUpperCase(); - + var name = this.props.customDisplayName || this.props.member.name; + + if (this.state.imageUrl === this.state.defaultImageUrl) { + var initialLetter = this._getInitialLetter(); return ( - { initialLetter } + ); @@ -104,9 +114,8 @@ module.exports = React.createClass({ + title={name} + {...this.props} /> ); } }); diff --git a/src/components/views/rooms/MemberList.js b/src/components/views/rooms/MemberList.js index f4d017733d..eac5466e88 100644 --- a/src/components/views/rooms/MemberList.js +++ b/src/components/views/rooms/MemberList.js @@ -15,6 +15,7 @@ limitations under the License. */ var React = require('react'); var classNames = require('classnames'); +var Matrix = require("matrix-js-sdk"); var MatrixClientPeg = require("../../../MatrixClientPeg"); var Modal = require("../../../Modal"); var sdk = require('../../../index'); @@ -253,14 +254,12 @@ module.exports = React.createClass({ // already added them. var memberEvent = room.currentState.getInviteForThreePidToken(e.getStateKey()); if (memberEvent) { - console.log("Found match => %s", memberEvent.getStateKey()); return; } - console.log("Display match => "); - /* memberList.push( - - ) */ + + ) }) } } diff --git a/src/components/views/rooms/MemberTile.js b/src/components/views/rooms/MemberTile.js index 0a32441a00..4752c4d539 100644 --- a/src/components/views/rooms/MemberTile.js +++ b/src/components/views/rooms/MemberTile.js @@ -27,24 +27,18 @@ module.exports = React.createClass({ displayName: 'MemberTile', propTypes: { - member: React.PropTypes.any.isRequired, // RoomMember - onFinished: React.PropTypes.func + member: React.PropTypes.any, // RoomMember + onFinished: React.PropTypes.func, + customDisplayName: React.PropTypes.string // for 3pid invites }, getInitialState: function() { return {}; }, - onLeaveClick: function() { - dis.dispatch({ - action: 'leave_room', - room_id: this.props.member.roomId, - }); - this.props.onFinished(); - }, - shouldComponentUpdate: function(nextProps, nextState) { if (this.state.hover !== nextState.hover) return true; + if (!this.props.member) { return false; } // e.g. 3pid members if ( this.member_last_modified_time === undefined || this.member_last_modified_time < nextProps.member.getLastModifiedTime() @@ -70,13 +64,25 @@ module.exports = React.createClass({ }, onClick: function(e) { + if (!this.props.member) { return; } // e.g. 3pid members + dis.dispatch({ action: 'view_user', member: this.props.member, }); }, + _getDisplayName: function() { + if (this.props.customDisplayName) { + return this.props.customDisplayName; + } + return this.props.member.name; + }, + getPowerLabel: function() { + if (!this.props.member) { + return this._getDisplayName(); + } var label = this.props.member.userId; if (this.state.isTargetMod) { label += " - Mod (" + this.props.member.powerLevelNorm + "%)"; @@ -85,68 +91,74 @@ module.exports = React.createClass({ }, render: function() { - var PresenceLabel = sdk.getComponent("rooms.PresenceLabel"); - - this.member_last_modified_time = this.props.member.getLastModifiedTime(); - if (this.props.member.user) { - this.user_last_modified_time = this.props.member.user.getLastModifiedTime(); - } - - var isMyUser = MatrixClientPeg.get().credentials.userId == this.props.member.userId; - - var power; - // if (this.props.member && this.props.member.powerLevelNorm > 0) { - // var img = "img/p/p" + Math.floor(20 * this.props.member.powerLevelNorm / 100) + ".png"; - // power = ; - // } + var member = this.props.member; + var isMyUser = false; + var name = this._getDisplayName(); + var active = -1; var presenceClass = "mx_MemberTile_offline"; - var mainClassName = "mx_MemberTile "; - if (this.props.member.user) { - if (this.props.member.user.presence === "online") { - presenceClass = "mx_MemberTile_online"; - } - else if (this.props.member.user.presence === "unavailable") { - presenceClass = "mx_MemberTile_unavailable"; + + if (member) { + if (member.user) { + this.user_last_modified_time = member.user.getLastModifiedTime(); + + // FIXME: make presence data update whenever User.presence changes... + active = ( + (Date.now() - (member.user.lastPresenceTs - member.user.lastActiveAgo)) || -1 + ); + + if (member.user.presence === "online") { + presenceClass = "mx_MemberTile_online"; + } + else if (member.user.presence === "unavailable") { + presenceClass = "mx_MemberTile_unavailable"; + } } + this.member_last_modified_time = member.getLastModifiedTime(); + isMyUser = MatrixClientPeg.get().credentials.userId == member.userId; + + // if (this.props.member && this.props.member.powerLevelNorm > 0) { + // var img = "img/p/p" + Math.floor(20 * this.props.member.powerLevelNorm / 100) + ".png"; + // power = ; + // } } + + + var mainClassName = "mx_MemberTile "; mainClassName += presenceClass; if (this.state.hover) { mainClassName += " mx_MemberTile_hover"; } - var name = this.props.member.name; - // if (isMyUser) name += " (me)"; // this does nothing other than introduce line wrapping and pain - //var leave = isMyUser ? : null; - var nameEl; if (this.state.hover) { - // FIXME: make presence data update whenever User.presence changes... - var active = this.props.member.user ? ((Date.now() - (this.props.member.user.lastPresenceTs - this.props.member.user.lastActiveAgo)) || -1) : -1; - + var presenceState = (member && member.user) ? member.user.presence : null; + var PresenceLabel = sdk.getComponent("rooms.PresenceLabel"); nameEl = (
{ name }
+ presenceState={presenceState} />
); } else { - nameEl = + nameEl = (
{ name }
+ ); } var MemberAvatar = sdk.getComponent('avatars.MemberAvatar'); + return (
- - { power } +
{ nameEl }