Move and merge RoomTile/MemberTile to react SDK. Keep DND stuff in vector as RoomDNDView.

This commit is contained in:
Kegan Dougal 2015-11-27 11:52:29 +00:00
parent b007edca63
commit f969ccb50c
5 changed files with 7 additions and 299 deletions

View file

@ -21,11 +21,10 @@ var DragSource = require('react-dnd').DragSource;
var DropTarget = require('react-dnd').DropTarget; var DropTarget = require('react-dnd').DropTarget;
var classNames = require('classnames'); var classNames = require('classnames');
var RoomTileController = require('matrix-react-sdk/lib/controllers/molecules/RoomTile') var dis = require("matrix-react-sdk/lib/dispatcher");
var MatrixClientPeg = require('matrix-react-sdk/lib/MatrixClientPeg'); var MatrixClientPeg = require('matrix-react-sdk/lib/MatrixClientPeg');
var sdk = require('matrix-react-sdk');
var sdk = require('matrix-react-sdk') var RoomTile = require('matrix-react-sdk/lib/components/views/rooms/RoomTile');
/** /**
* Specifies the drag source contract. * Specifies the drag source contract.
@ -183,117 +182,6 @@ var roomTileTarget = {
}, },
}; };
var RoomTile = React.createClass({
displayName: 'RoomTile',
mixins: [RoomTileController],
propTypes: {
connectDragSource: React.PropTypes.func.isRequired,
connectDropTarget: React.PropTypes.func.isRequired,
isDragging: React.PropTypes.bool.isRequired,
room: React.PropTypes.object.isRequired,
collapsed: React.PropTypes.bool.isRequired,
selected: React.PropTypes.bool.isRequired,
unread: React.PropTypes.bool.isRequired,
highlight: React.PropTypes.bool.isRequired,
isInvite: React.PropTypes.bool.isRequired,
roomSubList: React.PropTypes.object.isRequired,
},
getInitialState: function() {
return( { hover : false });
},
onMouseEnter: function() {
this.setState( { hover : true });
},
onMouseLeave: function() {
this.setState( { hover : false });
},
render: function() {
// if (this.props.clientOffset) {
// //console.log("room " + this.props.room.roomId + " has dropTarget clientOffset " + this.props.clientOffset.x + "," + this.props.clientOffset.y);
// }
/*
if (this.props.room._dragging) {
var RoomDropTarget = sdk.getComponent("molecules.RoomDropTarget");
return <RoomDropTarget placeholder={true}/>;
}
*/
var myUserId = MatrixClientPeg.get().credentials.userId;
var me = this.props.room.currentState.members[myUserId];
var classes = classNames({
'mx_RoomTile': true,
'mx_RoomTile_selected': this.props.selected,
'mx_RoomTile_unread': this.props.unread,
'mx_RoomTile_highlight': this.props.highlight,
'mx_RoomTile_invited': (me && me.membership == 'invite'),
});
var name;
if (this.props.isInvite) {
name = this.props.room.getMember(myUserId).events.member.getSender();
}
else {
// XXX: We should never display raw room IDs, but sometimes the room name js sdk gives is undefined
name = this.props.room.name || this.props.room.roomId;
}
name = name.replace(":", ":\u200b"); // add a zero-width space to allow linewrapping after the colon
var badge;
if (this.props.highlight) {
badge = <div className="mx_RoomTile_badge"/>;
}
/*
if (this.props.highlight) {
badge = <div className="mx_RoomTile_badge">!</div>;
}
else if (this.props.unread) {
badge = <div className="mx_RoomTile_badge">1</div>;
}
var nameCell;
if (badge) {
nameCell = <div className="mx_RoomTile_nameBadge"><div className="mx_RoomTile_name">{name}</div><div className="mx_RoomTile_badgeCell">{badge}</div></div>;
}
else {
nameCell = <div className="mx_RoomTile_name">{name}</div>;
}
*/
var label;
if (!this.props.collapsed) {
var className = 'mx_RoomTile_name' + (this.props.isInvite ? ' mx_RoomTile_invite' : '');
label = <div className={ className }>{name}</div>;
}
else if (this.state.hover) {
var RoomTooltip = sdk.getComponent("molecules.RoomTooltip");
label = <RoomTooltip room={this.props.room}/>;
}
var RoomAvatar = sdk.getComponent('avatars.RoomAvatar');
// These props are injected by React DnD,
// as defined by your `collect` function above:
var isDragging = this.props.isDragging;
var connectDragSource = this.props.connectDragSource;
var connectDropTarget = this.props.connectDropTarget;
return connectDragSource(connectDropTarget(
<div className={classes} onClick={this.onClick} onMouseEnter={this.onMouseEnter} onMouseLeave={this.onMouseLeave}>
<div className="mx_RoomTile_avatar">
<RoomAvatar room={this.props.room} width="24" height="24" />
{ badge }
</div>
{ label }
</div>
));
}
});
// Export the wrapped version, inlining the 'collect' functions // Export the wrapped version, inlining the 'collect' functions
// to more closely resemble the ES7 // to more closely resemble the ES7
module.exports = module.exports =

View file

@ -27,6 +27,7 @@ var skin = {};
skin['elements.Spinner'] = require('../../components/views/elements/Spinner'); skin['elements.Spinner'] = require('../../components/views/elements/Spinner');
skin['elements.ImageView'] = require('../../components/views/elements/ImageView'); skin['elements.ImageView'] = require('../../components/views/elements/ImageView');
skin['messages.MessageTimestamp'] = require('../../components/views/messages/MessageTimestamp'); skin['messages.MessageTimestamp'] = require('../../components/views/messages/MessageTimestamp');
skin['rooms.RoomTile'] = require('../../components/views/rooms/RoomDNDView');
// TODO: Fix this so matrix-react-sdk stuff is in react SDK skindex? // TODO: Fix this so matrix-react-sdk stuff is in react SDK skindex?
skin['avatars.RoomAvatar'] = require('matrix-react-sdk/lib/components/views/avatars/RoomAvatar'); skin['avatars.RoomAvatar'] = require('matrix-react-sdk/lib/components/views/avatars/RoomAvatar');
@ -42,6 +43,7 @@ skin['messages.MessageComposer'] = require('matrix-react-sdk/lib/components/view
skin['rooms.MemberInfo'] = require('matrix-react-sdk/lib/components/views/rooms/MemberInfo'); skin['rooms.MemberInfo'] = require('matrix-react-sdk/lib/components/views/rooms/MemberInfo');
skin['rooms.RoomHeader'] = require('matrix-react-sdk/lib/components/views/rooms/RoomHeader'); skin['rooms.RoomHeader'] = require('matrix-react-sdk/lib/components/views/rooms/RoomHeader');
skin['rooms.RoomSettings'] = require('matrix-react-sdk/lib/components/views/rooms/RoomSettings'); skin['rooms.RoomSettings'] = require('matrix-react-sdk/lib/components/views/rooms/RoomSettings');
skin['rooms.MemberTile'] = require('matrix-react-sdk/lib/components/views/rooms/MemberTile');
skin['create_room.CreateRoomButton'] = require('matrix-react-sdk/lib/components/views/create_room/CreateRoomButton'); skin['create_room.CreateRoomButton'] = require('matrix-react-sdk/lib/components/views/create_room/CreateRoomButton');
skin['create_room.Presets'] = require('matrix-react-sdk/lib/components/views/create_room/Presets'); skin['create_room.Presets'] = require('matrix-react-sdk/lib/components/views/create_room/Presets');
skin['create_room.RoomAlias'] = require('matrix-react-sdk/lib/components/views/create_room/RoomAlias'); skin['create_room.RoomAlias'] = require('matrix-react-sdk/lib/components/views/create_room/RoomAlias');
@ -64,12 +66,10 @@ skin['molecules.MRoomMemberTile'] = require('./views/molecules/MRoomMemberTile')
skin['molecules.MTextTile'] = require('./views/molecules/MTextTile'); skin['molecules.MTextTile'] = require('./views/molecules/MTextTile');
skin['molecules.MVideoTile'] = require('./views/molecules/MVideoTile'); skin['molecules.MVideoTile'] = require('./views/molecules/MVideoTile');
skin['molecules.MatrixToolbar'] = require('./views/molecules/MatrixToolbar'); skin['molecules.MatrixToolbar'] = require('./views/molecules/MatrixToolbar');
skin['molecules.MemberTile'] = require('./views/molecules/MemberTile');
skin['molecules.MessageContextMenu'] = require('./views/molecules/MessageContextMenu'); skin['molecules.MessageContextMenu'] = require('./views/molecules/MessageContextMenu');
skin['molecules.MessageTile'] = require('./views/molecules/MessageTile'); skin['molecules.MessageTile'] = require('./views/molecules/MessageTile');
skin['molecules.RoomCreate'] = require('./views/molecules/RoomCreate'); skin['molecules.RoomCreate'] = require('./views/molecules/RoomCreate');
skin['molecules.RoomDropTarget'] = require('./views/molecules/RoomDropTarget'); skin['molecules.RoomDropTarget'] = require('./views/molecules/RoomDropTarget');
skin['molecules.RoomTile'] = require('./views/molecules/RoomTile');
skin['molecules.RoomTooltip'] = require('./views/molecules/RoomTooltip'); skin['molecules.RoomTooltip'] = require('./views/molecules/RoomTooltip');
skin['molecules.SearchBar'] = require('./views/molecules/SearchBar'); skin['molecules.SearchBar'] = require('./views/molecules/SearchBar');
skin['molecules.SenderProfile'] = require('./views/molecules/SenderProfile'); skin['molecules.SenderProfile'] = require('./views/molecules/SenderProfile');

View file

@ -1,180 +0,0 @@
/*
Copyright 2015 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('matrix-react-sdk/lib/MatrixClientPeg');
var sdk = require('matrix-react-sdk')
var dis = require('matrix-react-sdk/lib/dispatcher');
var MemberTileController = require('matrix-react-sdk/lib/controllers/molecules/MemberTile')
// The Lato WOFF doesn't include sensible combining diacritics, so Chrome chokes on rendering them.
// Revert to Arial when this happens, which on OSX works at least.
var zalgo = /[\u0300-\u036f\u1ab0-\u1aff\u1dc0-\u1dff\u20d0-\u20ff\ufe20-\ufe2f]/;
module.exports = React.createClass({
displayName: 'MemberTile',
mixins: [MemberTileController],
shouldComponentUpdate: function(nextProps, nextState) {
if (this.state.hover !== nextState.hover) return true;
if (
this.member_last_modified_time === undefined ||
this.member_last_modified_time < nextProps.member.getLastModifiedTime()
) {
return true
}
if (
nextProps.member.user &&
(this.user_last_modified_time === undefined ||
this.user_last_modified_time < nextProps.member.user.getLastModifiedTime())
) {
return true
}
return false;
},
mouseEnter: function(e) {
this.setState({ 'hover': true });
},
mouseLeave: function(e) {
this.setState({ 'hover': false });
},
onClick: function(e) {
dis.dispatch({
action: 'view_user',
member: this.props.member,
});
},
getDuration: function(time) {
if (!time) return;
var t = parseInt(time / 1000);
var s = t % 60;
var m = parseInt(t / 60) % 60;
var h = parseInt(t / (60 * 60)) % 24;
var d = parseInt(t / (60 * 60 * 24));
if (t < 60) {
if (t < 0) {
return "0s";
}
return s + "s";
}
if (t < 60 * 60) {
return m + "m";
}
if (t < 24 * 60 * 60) {
return h + "h";
}
return d + "d ";
},
getPrettyPresence: function(user) {
if (!user) return "Unknown";
var presence = user.presence;
if (presence === "online") return "Online";
if (presence === "unavailable") return "Idle"; // XXX: is this actually right?
if (presence === "offline") return "Offline";
return "Unknown";
},
getPowerLabel: function() {
var label = this.props.member.userId;
if (this.state.isTargetMod) {
label += " - Mod (" + this.props.member.powerLevelNorm + "%)";
}
return label;
},
render: function() {
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 = <img src={ img } className="mx_MemberTile_power" width="44" height="44" alt=""/>;
// }
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";
}
}
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 ? <img className="mx_MemberTile_leave" src="img/delete.png" width="10" height="10" onClick={this.onLeaveClick}/> : null;
var nameClass = "mx_MemberTile_name";
if (zalgo.test(name)) {
nameClass += " mx_MemberTile_zalgo";
}
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 = <div className="mx_MemberTile_presence">{ this.getPrettyPresence(this.props.member.user) } { this.getDuration(active) } ago</div>;
}
else {
presence = <div className="mx_MemberTile_presence">{ this.getPrettyPresence(this.props.member.user) }</div>;
}
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>
{ presence }
</div>
}
else {
nameEl =
<div className={nameClass}>
{ name }
</div>
}
var MemberAvatar = sdk.getComponent('avatars.MemberAvatar');
return (
<div className={mainClassName} title={ this.getPowerLabel() } onClick={ this.onClick } onMouseEnter={ this.mouseEnter } onMouseLeave={ this.mouseLeave }>
<div className="mx_MemberTile_avatar">
<MemberAvatar member={this.props.member} width={36} height={36} />
{ power }
</div>
{ nameEl }
</div>
);
}
});

View file

@ -56,7 +56,7 @@ module.exports = React.createClass({
}, },
makeMemberTiles: function(membership) { makeMemberTiles: function(membership) {
var MemberTile = sdk.getComponent("molecules.MemberTile"); var MemberTile = sdk.getComponent("rooms.MemberTile");
var self = this; var self = this;
return self.state.members.filter(function(userId) { return self.state.members.filter(function(userId) {

View file

@ -215,7 +215,7 @@ var RoomSubList = React.createClass({
makeRoomTiles: function() { makeRoomTiles: function() {
var self = this; var self = this;
var RoomTile = sdk.getComponent("molecules.RoomTile"); var RoomTile = sdk.getComponent("rooms.RoomTile");
return this.state.sortedList.map(function(room) { return this.state.sortedList.map(function(room) {
var selected = room.roomId == self.props.selectedRoom; var selected = room.roomId == self.props.selectedRoom;
// XXX: is it evil to pass in self as a prop to RoomTile? // XXX: is it evil to pass in self as a prop to RoomTile?