mirror of https://github.com/vector-im/riot-web
Make MemberAvatar and MemberTile work without RoomMember objects
parent
c0e5d1d13b
commit
8c9352c484
|
@ -24,10 +24,16 @@ module.exports = React.createClass({
|
||||||
displayName: 'MemberAvatar',
|
displayName: 'MemberAvatar',
|
||||||
|
|
||||||
propTypes: {
|
propTypes: {
|
||||||
member: React.PropTypes.object.isRequired,
|
member: React.PropTypes.object,
|
||||||
width: React.PropTypes.number,
|
width: React.PropTypes.number,
|
||||||
height: React.PropTypes.number,
|
height: React.PropTypes.number,
|
||||||
resizeMethod: React.PropTypes.string,
|
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() {
|
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) {
|
componentWillReceiveProps: function(nextProps) {
|
||||||
this.refreshUrl();
|
this.refreshUrl();
|
||||||
},
|
},
|
||||||
|
|
||||||
defaultAvatarUrl: function(member, width, height, resizeMethod) {
|
|
||||||
return Avatar.defaultAvatarUrlForString(member.userId);
|
|
||||||
},
|
|
||||||
|
|
||||||
onError: function(ev) {
|
onError: function(ev) {
|
||||||
// don't tightloop if the browser can't load a data url
|
// 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;
|
return;
|
||||||
}
|
}
|
||||||
this.setState({
|
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,
|
return Avatar.avatarUrlForMember(this.props.member,
|
||||||
this.props.width,
|
this.props.width,
|
||||||
this.props.height,
|
this.props.height,
|
||||||
this.props.resizeMethod);
|
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() {
|
refreshUrl: function() {
|
||||||
var newUrl = this._computeUrl();
|
var newUrl = this._getMemberImageUrl();
|
||||||
if (newUrl != this.currentUrl) {
|
if (newUrl != this.currentUrl) {
|
||||||
this.currentUrl = newUrl;
|
this.currentUrl = newUrl;
|
||||||
this.setState({imageUrl: newUrl});
|
this.setState({imageUrl: newUrl});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
getInitialState: function() {
|
|
||||||
return {
|
|
||||||
imageUrl: this._computeUrl()
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
///////////////
|
|
||||||
|
|
||||||
render: function() {
|
render: function() {
|
||||||
// XXX: recalculates default avatar url constantly
|
var name = this.props.customDisplayName || this.props.member.name;
|
||||||
if (this.state.imageUrl === this.defaultAvatarUrl(this.props.member)) {
|
|
||||||
var initial;
|
if (this.state.imageUrl === this.state.defaultImageUrl) {
|
||||||
if (this.props.member.name[0])
|
var initialLetter = this._getInitialLetter();
|
||||||
initial = this.props.member.name[0].toUpperCase();
|
|
||||||
if (initial === '@' && this.props.member.name[1])
|
|
||||||
initial = this.props.member.name[1].toUpperCase();
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<span className="mx_MemberAvatar" {...this.props}>
|
<span className="mx_MemberAvatar" {...this.props}>
|
||||||
<span className="mx_MemberAvatar_initial" aria-hidden="true"
|
<span className="mx_MemberAvatar_initial" aria-hidden="true"
|
||||||
style={{ fontSize: (this.props.width * 0.65) + "px",
|
style={{ fontSize: (this.props.width * 0.65) + "px",
|
||||||
width: this.props.width + "px",
|
width: this.props.width + "px",
|
||||||
lineHeight: this.props.height + "px" }}>{ initial }</span>
|
lineHeight: this.props.height + "px" }}>{ initialLetter }</span>
|
||||||
<img className="mx_MemberAvatar_image" src={this.state.imageUrl} title={this.props.member.name}
|
<img className="mx_MemberAvatar_image" src={this.state.imageUrl} title={name}
|
||||||
onError={this.onError} width={this.props.width} height={this.props.height} />
|
onError={this.onError} width={this.props.width} height={this.props.height} />
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
|
@ -104,9 +114,8 @@ module.exports = React.createClass({
|
||||||
<img className="mx_MemberAvatar mx_MemberAvatar_image" src={this.state.imageUrl}
|
<img className="mx_MemberAvatar mx_MemberAvatar_image" src={this.state.imageUrl}
|
||||||
onError={this.onError}
|
onError={this.onError}
|
||||||
width={this.props.width} height={this.props.height}
|
width={this.props.width} height={this.props.height}
|
||||||
title={this.props.member.name}
|
title={name}
|
||||||
{...this.props}
|
{...this.props} />
|
||||||
/>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -15,6 +15,7 @@ limitations under the License.
|
||||||
*/
|
*/
|
||||||
var React = require('react');
|
var React = require('react');
|
||||||
var classNames = require('classnames');
|
var classNames = require('classnames');
|
||||||
|
var Matrix = require("matrix-js-sdk");
|
||||||
var MatrixClientPeg = require("../../../MatrixClientPeg");
|
var MatrixClientPeg = require("../../../MatrixClientPeg");
|
||||||
var Modal = require("../../../Modal");
|
var Modal = require("../../../Modal");
|
||||||
var sdk = require('../../../index');
|
var sdk = require('../../../index');
|
||||||
|
@ -253,14 +254,12 @@ module.exports = React.createClass({
|
||||||
// already added them.
|
// already added them.
|
||||||
var memberEvent = room.currentState.getInviteForThreePidToken(e.getStateKey());
|
var memberEvent = room.currentState.getInviteForThreePidToken(e.getStateKey());
|
||||||
if (memberEvent) {
|
if (memberEvent) {
|
||||||
console.log("Found match => %s", memberEvent.getStateKey());
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
console.log("Display match => ");
|
|
||||||
/*
|
|
||||||
memberList.push(
|
memberList.push(
|
||||||
<MemberTile key={e.getStateKey()} ref={e.getStateKey()} member={}/>
|
<MemberTile key={e.getStateKey()} ref={e.getStateKey()}
|
||||||
) */
|
customDisplayName={e.getContent().display_name} />
|
||||||
|
)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,24 +27,18 @@ module.exports = React.createClass({
|
||||||
displayName: 'MemberTile',
|
displayName: 'MemberTile',
|
||||||
|
|
||||||
propTypes: {
|
propTypes: {
|
||||||
member: React.PropTypes.any.isRequired, // RoomMember
|
member: React.PropTypes.any, // RoomMember
|
||||||
onFinished: React.PropTypes.func
|
onFinished: React.PropTypes.func,
|
||||||
|
customDisplayName: React.PropTypes.string // for 3pid invites
|
||||||
},
|
},
|
||||||
|
|
||||||
getInitialState: function() {
|
getInitialState: function() {
|
||||||
return {};
|
return {};
|
||||||
},
|
},
|
||||||
|
|
||||||
onLeaveClick: function() {
|
|
||||||
dis.dispatch({
|
|
||||||
action: 'leave_room',
|
|
||||||
room_id: this.props.member.roomId,
|
|
||||||
});
|
|
||||||
this.props.onFinished();
|
|
||||||
},
|
|
||||||
|
|
||||||
shouldComponentUpdate: function(nextProps, nextState) {
|
shouldComponentUpdate: function(nextProps, nextState) {
|
||||||
if (this.state.hover !== nextState.hover) return true;
|
if (this.state.hover !== nextState.hover) return true;
|
||||||
|
if (!this.props.member) { return false; } // e.g. 3pid members
|
||||||
if (
|
if (
|
||||||
this.member_last_modified_time === undefined ||
|
this.member_last_modified_time === undefined ||
|
||||||
this.member_last_modified_time < nextProps.member.getLastModifiedTime()
|
this.member_last_modified_time < nextProps.member.getLastModifiedTime()
|
||||||
|
@ -70,13 +64,25 @@ module.exports = React.createClass({
|
||||||
},
|
},
|
||||||
|
|
||||||
onClick: function(e) {
|
onClick: function(e) {
|
||||||
|
if (!this.props.member) { return; } // e.g. 3pid members
|
||||||
|
|
||||||
dis.dispatch({
|
dis.dispatch({
|
||||||
action: 'view_user',
|
action: 'view_user',
|
||||||
member: this.props.member,
|
member: this.props.member,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
_getDisplayName: function() {
|
||||||
|
if (this.props.customDisplayName) {
|
||||||
|
return this.props.customDisplayName;
|
||||||
|
}
|
||||||
|
return this.props.member.name;
|
||||||
|
},
|
||||||
|
|
||||||
getPowerLabel: function() {
|
getPowerLabel: function() {
|
||||||
|
if (!this.props.member) {
|
||||||
|
return this._getDisplayName();
|
||||||
|
}
|
||||||
var label = this.props.member.userId;
|
var label = this.props.member.userId;
|
||||||
if (this.state.isTargetMod) {
|
if (this.state.isTargetMod) {
|
||||||
label += " - Mod (" + this.props.member.powerLevelNorm + "%)";
|
label += " - Mod (" + this.props.member.powerLevelNorm + "%)";
|
||||||
|
@ -85,68 +91,74 @@ module.exports = React.createClass({
|
||||||
},
|
},
|
||||||
|
|
||||||
render: function() {
|
render: function() {
|
||||||
var PresenceLabel = sdk.getComponent("rooms.PresenceLabel");
|
var member = this.props.member;
|
||||||
|
var isMyUser = false;
|
||||||
this.member_last_modified_time = this.props.member.getLastModifiedTime();
|
var name = this._getDisplayName();
|
||||||
if (this.props.member.user) {
|
var active = -1;
|
||||||
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 = <img src={ img } className="mx_MemberTile_power" width="44" height="44" alt=""/>;
|
|
||||||
// }
|
|
||||||
var presenceClass = "mx_MemberTile_offline";
|
var presenceClass = "mx_MemberTile_offline";
|
||||||
var mainClassName = "mx_MemberTile ";
|
|
||||||
if (this.props.member.user) {
|
if (member) {
|
||||||
if (this.props.member.user.presence === "online") {
|
if (member.user) {
|
||||||
presenceClass = "mx_MemberTile_online";
|
this.user_last_modified_time = member.user.getLastModifiedTime();
|
||||||
}
|
|
||||||
else if (this.props.member.user.presence === "unavailable") {
|
// FIXME: make presence data update whenever User.presence changes...
|
||||||
presenceClass = "mx_MemberTile_unavailable";
|
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 = <img src={ img } className="mx_MemberTile_power" width="44" height="44" alt=""/>;
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
var mainClassName = "mx_MemberTile ";
|
||||||
mainClassName += presenceClass;
|
mainClassName += presenceClass;
|
||||||
if (this.state.hover) {
|
if (this.state.hover) {
|
||||||
mainClassName += " mx_MemberTile_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 ? <img className="mx_MemberTile_leave" src="img/delete.png" width="10" height="10" onClick={this.onLeaveClick}/> : null;
|
|
||||||
|
|
||||||
var nameEl;
|
var nameEl;
|
||||||
if (this.state.hover) {
|
if (this.state.hover) {
|
||||||
// FIXME: make presence data update whenever User.presence changes...
|
var presenceState = (member && member.user) ? member.user.presence : null;
|
||||||
var active = this.props.member.user ? ((Date.now() - (this.props.member.user.lastPresenceTs - this.props.member.user.lastActiveAgo)) || -1) : -1;
|
var PresenceLabel = sdk.getComponent("rooms.PresenceLabel");
|
||||||
|
|
||||||
nameEl = (
|
nameEl = (
|
||||||
<div className="mx_MemberTile_details">
|
<div className="mx_MemberTile_details">
|
||||||
<img className="mx_MemberTile_chevron" src="img/member_chevron.png" width="8" height="12"/>
|
<img className="mx_MemberTile_chevron" src="img/member_chevron.png" width="8" height="12"/>
|
||||||
<div className="mx_MemberTile_userId">{ name }</div>
|
<div className="mx_MemberTile_userId">{ name }</div>
|
||||||
<PresenceLabel activeAgo={active}
|
<PresenceLabel activeAgo={active}
|
||||||
presenceState={this.props.member.user ? this.props.member.user.presence : null} />
|
presenceState={presenceState} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
nameEl =
|
nameEl = (
|
||||||
<div className="mx_MemberTile_name">
|
<div className="mx_MemberTile_name">
|
||||||
{ name }
|
{ name }
|
||||||
</div>
|
</div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
var MemberAvatar = sdk.getComponent('avatars.MemberAvatar');
|
var MemberAvatar = sdk.getComponent('avatars.MemberAvatar');
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={mainClassName} title={ this.getPowerLabel() }
|
<div className={mainClassName} title={ this.getPowerLabel() }
|
||||||
onClick={ this.onClick } onMouseEnter={ this.mouseEnter }
|
onClick={ this.onClick } onMouseEnter={ this.mouseEnter }
|
||||||
onMouseLeave={ this.mouseLeave }>
|
onMouseLeave={ this.mouseLeave }>
|
||||||
<div className="mx_MemberTile_avatar">
|
<div className="mx_MemberTile_avatar">
|
||||||
<MemberAvatar member={this.props.member} width={36} height={36} />
|
<MemberAvatar member={this.props.member} width={36} height={36}
|
||||||
{ power }
|
customDisplayName={this.props.customDisplayName} />
|
||||||
</div>
|
</div>
|
||||||
{ nameEl }
|
{ nameEl }
|
||||||
</div>
|
</div>
|
||||||
|
|
Loading…
Reference in New Issue