mirror of https://github.com/vector-im/riot-web
Factor out common code between MemberTile and UserTile into EntityTile. Use EntityTile.
parent
fd99b260f4
commit
71009d81b6
|
@ -60,6 +60,7 @@ module.exports.components['views.messages.MVideoBody'] = require('./components/v
|
||||||
module.exports.components['views.messages.TextualBody'] = require('./components/views/messages/TextualBody');
|
module.exports.components['views.messages.TextualBody'] = require('./components/views/messages/TextualBody');
|
||||||
module.exports.components['views.messages.TextualEvent'] = require('./components/views/messages/TextualEvent');
|
module.exports.components['views.messages.TextualEvent'] = require('./components/views/messages/TextualEvent');
|
||||||
module.exports.components['views.messages.UnknownBody'] = require('./components/views/messages/UnknownBody');
|
module.exports.components['views.messages.UnknownBody'] = require('./components/views/messages/UnknownBody');
|
||||||
|
module.exports.components['views.rooms.EntityTile'] = require('./components/views/rooms/EntityTile');
|
||||||
module.exports.components['views.rooms.EventTile'] = require('./components/views/rooms/EventTile');
|
module.exports.components['views.rooms.EventTile'] = require('./components/views/rooms/EventTile');
|
||||||
module.exports.components['views.rooms.MemberInfo'] = require('./components/views/rooms/MemberInfo');
|
module.exports.components['views.rooms.MemberInfo'] = require('./components/views/rooms/MemberInfo');
|
||||||
module.exports.components['views.rooms.MemberList'] = require('./components/views/rooms/MemberList');
|
module.exports.components['views.rooms.MemberList'] = require('./components/views/rooms/MemberList');
|
||||||
|
|
|
@ -0,0 +1,118 @@
|
||||||
|
/*
|
||||||
|
Copyright 2015, 2016 OpenMarket Ltd
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var React = require('react');
|
||||||
|
|
||||||
|
var MatrixClientPeg = require('../../../MatrixClientPeg');
|
||||||
|
var sdk = require('../../../index');
|
||||||
|
|
||||||
|
|
||||||
|
var PRESENCE_CLASS = {
|
||||||
|
"offline": "mx_MemberTile_offline",
|
||||||
|
"online": "mx_MemberTile_online",
|
||||||
|
"unavailable": "mx_MemberTile_unavailable"
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = React.createClass({
|
||||||
|
displayName: 'EntityTile',
|
||||||
|
|
||||||
|
propTypes: {
|
||||||
|
name: React.PropTypes.string,
|
||||||
|
title: React.PropTypes.string,
|
||||||
|
avatarJsx: React.PropTypes.any, // <BaseAvatar />
|
||||||
|
presenceState: React.PropTypes.string,
|
||||||
|
presenceActiveAgo: React.PropTypes.number,
|
||||||
|
showInviteButton: React.PropTypes.bool,
|
||||||
|
shouldComponentUpdate: React.PropTypes.func,
|
||||||
|
onClick: React.PropTypes.func
|
||||||
|
},
|
||||||
|
|
||||||
|
getDefaultProps: function() {
|
||||||
|
return {
|
||||||
|
shouldComponentUpdate: function(nextProps, nextState) { return false; },
|
||||||
|
onClick: function() {},
|
||||||
|
presenceState: "offline",
|
||||||
|
presenceActiveAgo: -1,
|
||||||
|
showInviteButton: false,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
getInitialState: function() {
|
||||||
|
return {
|
||||||
|
hover: false
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
shouldComponentUpdate: function(nextProps, nextState) {
|
||||||
|
if (this.state.hover !== nextState.hover) return true;
|
||||||
|
return this.props.shouldComponentUpdate(nextProps, nextState);
|
||||||
|
},
|
||||||
|
|
||||||
|
mouseEnter: function(e) {
|
||||||
|
this.setState({ 'hover': true });
|
||||||
|
},
|
||||||
|
|
||||||
|
mouseLeave: function(e) {
|
||||||
|
this.setState({ 'hover': false });
|
||||||
|
},
|
||||||
|
|
||||||
|
render: function() {
|
||||||
|
var presenceClass = PRESENCE_CLASS[this.props.presenceState];
|
||||||
|
var mainClassName = "mx_MemberTile ";
|
||||||
|
mainClassName += presenceClass;
|
||||||
|
if (this.state.hover) {
|
||||||
|
mainClassName += " mx_MemberTile_hover";
|
||||||
|
}
|
||||||
|
|
||||||
|
var nameEl;
|
||||||
|
if (this.state.hover) {
|
||||||
|
var PresenceLabel = sdk.getComponent("rooms.PresenceLabel");
|
||||||
|
nameEl = (
|
||||||
|
<div className="mx_MemberTile_details">
|
||||||
|
<img className="mx_MemberTile_chevron" src="img/member_chevron.png" width="8" height="12"/>
|
||||||
|
<div className="mx_MemberTile_userId">{ this.props.name }</div>
|
||||||
|
<PresenceLabel activeAgo={this.props.presenceActiveAgo}
|
||||||
|
presenceState={this.props.presenceState} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
nameEl = (
|
||||||
|
<div className="mx_MemberTile_name">
|
||||||
|
{ this.props.name }
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
var MemberAvatar = sdk.getComponent('avatars.MemberAvatar');
|
||||||
|
var BaseAvatar = sdk.getComponent('avatars.BaseAvatar');
|
||||||
|
|
||||||
|
var av = this.props.avatarJsx || <BaseAvatar name={name} width={36} height={36} />;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={mainClassName} title={ this.props.title }
|
||||||
|
onClick={ this.props.onClick } onMouseEnter={ this.mouseEnter }
|
||||||
|
onMouseLeave={ this.mouseLeave }>
|
||||||
|
<div className="mx_MemberTile_avatar">
|
||||||
|
{av}
|
||||||
|
</div>
|
||||||
|
{ nameEl }
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
|
@ -28,8 +28,7 @@ module.exports = React.createClass({
|
||||||
|
|
||||||
propTypes: {
|
propTypes: {
|
||||||
member: React.PropTypes.any, // RoomMember
|
member: React.PropTypes.any, // RoomMember
|
||||||
onFinished: React.PropTypes.func,
|
customDisplayName: React.PropTypes.string, // for 3pid invites
|
||||||
customDisplayName: React.PropTypes.string // for 3pid invites
|
|
||||||
},
|
},
|
||||||
|
|
||||||
getInitialState: function() {
|
getInitialState: function() {
|
||||||
|
@ -37,13 +36,12 @@ module.exports = React.createClass({
|
||||||
},
|
},
|
||||||
|
|
||||||
shouldComponentUpdate: function(nextProps, nextState) {
|
shouldComponentUpdate: function(nextProps, nextState) {
|
||||||
if (this.state.hover !== nextState.hover) return true;
|
|
||||||
if (!this.props.member) { return false; } // e.g. 3pid members
|
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()
|
||||||
) {
|
) {
|
||||||
return true
|
return true;
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
nextProps.member.user &&
|
nextProps.member.user &&
|
||||||
|
@ -55,14 +53,6 @@ module.exports = React.createClass({
|
||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
|
|
||||||
mouseEnter: function(e) {
|
|
||||||
this.setState({ 'hover': true });
|
|
||||||
},
|
|
||||||
|
|
||||||
mouseLeave: function(e) {
|
|
||||||
this.setState({ 'hover': false });
|
|
||||||
},
|
|
||||||
|
|
||||||
onClick: function(e) {
|
onClick: function(e) {
|
||||||
if (!this.props.member) { return; } // e.g. 3pid members
|
if (!this.props.member) { return; } // e.g. 3pid members
|
||||||
|
|
||||||
|
@ -91,13 +81,21 @@ module.exports = React.createClass({
|
||||||
},
|
},
|
||||||
|
|
||||||
render: function() {
|
render: function() {
|
||||||
|
var MemberAvatar = sdk.getComponent('avatars.MemberAvatar');
|
||||||
|
var BaseAvatar = sdk.getComponent('avatars.BaseAvatar');
|
||||||
|
var EntityTile = sdk.getComponent('rooms.EntityTile');
|
||||||
|
|
||||||
var member = this.props.member;
|
var member = this.props.member;
|
||||||
var isMyUser = false;
|
|
||||||
var name = this._getDisplayName();
|
var name = this._getDisplayName();
|
||||||
var active = -1;
|
var active = -1;
|
||||||
var presenceClass = "mx_MemberTile_offline";
|
var presenceState = (member && member.user) ? member.user.presence : null;
|
||||||
|
|
||||||
|
var av;
|
||||||
if (member) {
|
if (member) {
|
||||||
|
av = (
|
||||||
|
<MemberAvatar member={member} width={36} height={36} />
|
||||||
|
);
|
||||||
|
|
||||||
if (member.user) {
|
if (member.user) {
|
||||||
this.user_last_modified_time = member.user.getLastModifiedTime();
|
this.user_last_modified_time = member.user.getLastModifiedTime();
|
||||||
|
|
||||||
|
@ -105,75 +103,20 @@ module.exports = React.createClass({
|
||||||
active = (
|
active = (
|
||||||
(Date.now() - (member.user.lastPresenceTs - member.user.lastActiveAgo)) || -1
|
(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();
|
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;
|
|
||||||
if (this.state.hover) {
|
|
||||||
mainClassName += " mx_MemberTile_hover";
|
|
||||||
}
|
|
||||||
|
|
||||||
var nameEl;
|
|
||||||
if (this.state.hover) {
|
|
||||||
var presenceState = (member && member.user) ? member.user.presence : null;
|
|
||||||
var PresenceLabel = sdk.getComponent("rooms.PresenceLabel");
|
|
||||||
nameEl = (
|
|
||||||
<div className="mx_MemberTile_details">
|
|
||||||
<img className="mx_MemberTile_chevron" src="img/member_chevron.png" width="8" height="12"/>
|
|
||||||
<div className="mx_MemberTile_userId">{ name }</div>
|
|
||||||
<PresenceLabel activeAgo={active}
|
|
||||||
presenceState={presenceState} />
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
nameEl = (
|
|
||||||
<div className="mx_MemberTile_name">
|
|
||||||
{ name }
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
var MemberAvatar = sdk.getComponent('avatars.MemberAvatar');
|
|
||||||
var BaseAvatar = sdk.getComponent('avatars.BaseAvatar');
|
|
||||||
|
|
||||||
var av;
|
|
||||||
if (member) {
|
|
||||||
av = (
|
|
||||||
<MemberAvatar member={member} width={36} height={36} />
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
av = (
|
av = (
|
||||||
<BaseAvatar name={name} width={36} height={36} />
|
<BaseAvatar name={name} width={36} height={36} />
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={mainClassName} title={ this.getPowerLabel() }
|
<EntityTile {...this.props} presenceActiveAgo={active} presenceState={presenceState}
|
||||||
onClick={ this.onClick } onMouseEnter={ this.mouseEnter }
|
avatarJsx={av} title={this.getPowerLabel()} onClick={this.onClick}
|
||||||
onMouseLeave={ this.mouseLeave }>
|
shouldComponentUpdate={this.shouldComponentUpdate.bind(this)}
|
||||||
<div className="mx_MemberTile_avatar">
|
name={name} />
|
||||||
{av}
|
|
||||||
</div>
|
|
||||||
{ nameEl }
|
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -28,6 +28,7 @@ var SearchableEntityList = React.createClass({
|
||||||
emptyQueryShowsAll: React.PropTypes.bool,
|
emptyQueryShowsAll: React.PropTypes.bool,
|
||||||
onSubmit: React.PropTypes.func, // fn(inputText)
|
onSubmit: React.PropTypes.func, // fn(inputText)
|
||||||
entities: React.PropTypes.array,
|
entities: React.PropTypes.array,
|
||||||
|
onEntityClick: React.PropTypes.func
|
||||||
},
|
},
|
||||||
|
|
||||||
getDefaultProps: function() {
|
getDefaultProps: function() {
|
||||||
|
@ -35,7 +36,8 @@ var SearchableEntityList = React.createClass({
|
||||||
searchPlaceholderText: "Search",
|
searchPlaceholderText: "Search",
|
||||||
entities: [],
|
entities: [],
|
||||||
emptyQueryShowsAll: false,
|
emptyQueryShowsAll: false,
|
||||||
onSubmit: function() {}
|
onSubmit: function() {},
|
||||||
|
onEntityClick: function() {}
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -77,8 +79,8 @@ var SearchableEntityList = React.createClass({
|
||||||
placeholder={this.props.searchPlaceholderText} />
|
placeholder={this.props.searchPlaceholderText} />
|
||||||
</form>
|
</form>
|
||||||
<div className="mx_SearchableEntityList_list">
|
<div className="mx_SearchableEntityList_list">
|
||||||
{this.state.results.map(function(entity) {
|
{this.state.results.map((entity) => {
|
||||||
return entity.getJsx();
|
return entity.getJsx(this.props.onEntityClick);
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -28,101 +28,29 @@ module.exports = React.createClass({
|
||||||
displayName: 'UserTile',
|
displayName: 'UserTile',
|
||||||
|
|
||||||
propTypes: {
|
propTypes: {
|
||||||
user: React.PropTypes.any.isRequired, // User
|
user: React.PropTypes.any.isRequired // User
|
||||||
onInviteClick: React.PropTypes.func, //onInviteClick(User)
|
|
||||||
showInvite: React.PropTypes.bool,
|
|
||||||
onClick: React.PropTypes.func
|
|
||||||
},
|
|
||||||
|
|
||||||
getInitialState: function() {
|
|
||||||
return {};
|
|
||||||
},
|
|
||||||
|
|
||||||
getDefaultProps: function() {
|
|
||||||
return {
|
|
||||||
onClick: function() {},
|
|
||||||
onInviteClick: function() {},
|
|
||||||
showInvite: false
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
shouldComponentUpdate: function(nextProps, nextState) {
|
|
||||||
if (this.state.hover !== nextState.hover) return true;
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
|
|
||||||
mouseEnter: function(e) {
|
|
||||||
this.setState({ 'hover': true });
|
|
||||||
},
|
|
||||||
|
|
||||||
mouseLeave: function(e) {
|
|
||||||
this.setState({ 'hover': false });
|
|
||||||
},
|
},
|
||||||
|
|
||||||
render: function() {
|
render: function() {
|
||||||
|
var EntityTile = sdk.getComponent("rooms.EntityTile");
|
||||||
var user = this.props.user;
|
var user = this.props.user;
|
||||||
var name = user.displayName || user.userId;
|
var name = user.displayName || user.userId;
|
||||||
var isMyUser = MatrixClientPeg.get().credentials.userId == user.userId;
|
|
||||||
var active = -1;
|
var active = -1;
|
||||||
var presenceClass = "mx_MemberTile_offline";
|
|
||||||
|
|
||||||
this.user_last_modified_time = user.getLastModifiedTime();
|
|
||||||
|
|
||||||
// FIXME: make presence data update whenever User.presence changes...
|
// FIXME: make presence data update whenever User.presence changes...
|
||||||
active = (
|
active = (
|
||||||
(Date.now() - (user.lastPresenceTs - user.lastActiveAgo)) || -1
|
(Date.now() - (user.lastPresenceTs - user.lastActiveAgo)) || -1
|
||||||
);
|
);
|
||||||
|
|
||||||
if (user.presence === "online") {
|
|
||||||
presenceClass = "mx_MemberTile_online";
|
|
||||||
}
|
|
||||||
else if (user.presence === "unavailable") {
|
|
||||||
presenceClass = "mx_MemberTile_unavailable";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
var mainClassName = "mx_MemberTile ";
|
|
||||||
mainClassName += presenceClass;
|
|
||||||
if (this.state.hover) {
|
|
||||||
mainClassName += " mx_MemberTile_hover";
|
|
||||||
}
|
|
||||||
|
|
||||||
var nameEl;
|
|
||||||
if (this.state.hover) {
|
|
||||||
var PresenceLabel = sdk.getComponent("rooms.PresenceLabel");
|
|
||||||
nameEl = (
|
|
||||||
<div className="mx_MemberTile_details">
|
|
||||||
<img className="mx_MemberTile_chevron" src="img/member_chevron.png" width="8" height="12"/>
|
|
||||||
<div className="mx_MemberTile_userId">{ name }</div>
|
|
||||||
<PresenceLabel activeAgo={active}
|
|
||||||
presenceState={user.presence} />
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
nameEl = (
|
|
||||||
<div className="mx_MemberTile_name">
|
|
||||||
{ name }
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
var BaseAvatar = sdk.getComponent('avatars.BaseAvatar');
|
var BaseAvatar = sdk.getComponent('avatars.BaseAvatar');
|
||||||
|
var avatarJsx = (
|
||||||
if (this.props.showInvite) {
|
<BaseAvatar width={36} height={36} name={name} idName={user.userId}
|
||||||
// TODO
|
url={ Avatar.avatarUrlForUser(user, 36, 36, "crop") } />
|
||||||
}
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={mainClassName} title={ user.userId }
|
<EntityTile {...this.props} presenceState={user.presence} presenceActiveAgo={active}
|
||||||
onClick={ this.props.onClick } onMouseEnter={ this.mouseEnter }
|
name={name} title={user.userId} avatarJsx={avatarJsx} />
|
||||||
onMouseLeave={ this.mouseLeave }>
|
|
||||||
<div className="mx_MemberTile_avatar">
|
|
||||||
<BaseAvatar width={36} height={36} name={name} idName={user.userId}
|
|
||||||
url={ Avatar.avatarUrlForUser(user, 36, 36, "crop") } />
|
|
||||||
</div>
|
|
||||||
{ nameEl }
|
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue