diff --git a/src/component-index.js b/src/component-index.js
index 9fe15adfc6..7ae15ba12c 100644
--- a/src/component-index.js
+++ b/src/component-index.js
@@ -64,6 +64,7 @@ module.exports.components['views.rooms.MemberInfo'] = require('./components/view
module.exports.components['views.rooms.MemberList'] = require('./components/views/rooms/MemberList');
module.exports.components['views.rooms.MemberTile'] = require('./components/views/rooms/MemberTile');
module.exports.components['views.rooms.MessageComposer'] = require('./components/views/rooms/MessageComposer');
+module.exports.components['views.rooms.PresenceLabel'] = require('./components/views/rooms/PresenceLabel');
module.exports.components['views.rooms.RoomHeader'] = require('./components/views/rooms/RoomHeader');
module.exports.components['views.rooms.RoomList'] = require('./components/views/rooms/RoomList');
module.exports.components['views.rooms.RoomPreviewBar'] = require('./components/views/rooms/RoomPreviewBar');
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 b0e2baa3d3..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');
@@ -229,7 +230,8 @@ module.exports = React.createClass({
var MemberTile = sdk.getComponent("rooms.MemberTile");
var self = this;
- return self.state.members.filter(function(userId) {
+
+ var memberList = self.state.members.filter(function(userId) {
var m = self.memberDict[userId];
return m.membership == membership;
}).map(function(userId) {
@@ -238,6 +240,31 @@ module.exports = React.createClass({
;
- // }
+ 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) {
- var presence;
- // 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;
- if (active >= 0) {
- presence =