Factor out stuff commnon to all timeline events into EventTile: makes timestamp & edit button etc appear on everything, not just messages.
This commit is contained in:
parent
3d3680e42f
commit
1f3a6e408c
6 changed files with 163 additions and 111 deletions
|
@ -356,23 +356,20 @@ module.exports = {
|
|||
},
|
||||
|
||||
getEventTiles: function() {
|
||||
var tileTypes = {
|
||||
'm.room.message': sdk.getComponent('molecules.MessageTile'),
|
||||
'm.room.member' : sdk.getComponent('molecules.EventAsTextTile'),
|
||||
'm.call.invite' : sdk.getComponent('molecules.EventAsTextTile'),
|
||||
'm.call.answer' : sdk.getComponent('molecules.EventAsTextTile'),
|
||||
'm.call.hangup' : sdk.getComponent('molecules.EventAsTextTile'),
|
||||
'm.room.topic' : sdk.getComponent('molecules.EventAsTextTile'),
|
||||
};
|
||||
|
||||
var DateSeparator = sdk.getComponent('molecules.DateSeparator');
|
||||
|
||||
var ret = [];
|
||||
var count = 0;
|
||||
|
||||
var EventTile = sdk.getComponent('molecules.EventTile');
|
||||
|
||||
for (var i = this.state.room.timeline.length-1; i >= 0 && count < this.state.messageCap; --i) {
|
||||
var mxEv = this.state.room.timeline[i];
|
||||
var TileType = tileTypes[mxEv.getType()];
|
||||
|
||||
if (!EventTile.supportsEventType(mxEv.getType())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var continuation = false;
|
||||
var last = false;
|
||||
var dateSeparator = null;
|
||||
|
@ -401,13 +398,12 @@ module.exports = {
|
|||
|
||||
if (i === 1) { // n.b. 1, not 0, as the 0th event is an m.room.create and so doesn't show on the timeline
|
||||
var ts1 = this.state.room.timeline[i].getTs();
|
||||
dateSeparator = <DateSeparator key={ts1} ts={ts1}/>;
|
||||
dateSeparator = <li key={ts1}><DateSeparator ts={ts1}/></li>;
|
||||
continuation = false;
|
||||
}
|
||||
|
||||
if (!TileType) continue;
|
||||
ret.unshift(
|
||||
<li key={mxEv.getId()}><TileType mxEvent={mxEv} continuation={continuation} last={last}/></li>
|
||||
<li key={mxEv.getId()}><EventTile mxEvent={mxEv} continuation={continuation} last={last}/></li>
|
||||
);
|
||||
if (dateSeparator) {
|
||||
ret.unshift(dateSeparator);
|
||||
|
|
|
@ -14,14 +14,14 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
.mx_MessageTile {
|
||||
.mx_EventTile {
|
||||
max-width: 100%;
|
||||
clear: both;
|
||||
margin-top: 32px;
|
||||
margin-left: 56px;
|
||||
}
|
||||
|
||||
.mx_MessageTile_avatar {
|
||||
.mx_EventTile_avatar {
|
||||
padding-left: 12px;
|
||||
padding-right: 12px;
|
||||
margin-left: -64px;
|
||||
|
@ -29,17 +29,17 @@ limitations under the License.
|
|||
float: left;
|
||||
}
|
||||
|
||||
.mx_MessageTile_avatar img {
|
||||
.mx_EventTile_avatar img {
|
||||
background-color: #dbdbdb;
|
||||
border-radius: 20px;
|
||||
border: 0px;
|
||||
}
|
||||
|
||||
.mx_MessageTile_continuation {
|
||||
.mx_EventTile_continuation {
|
||||
margin-top: 8px ! important;
|
||||
}
|
||||
|
||||
.mx_MessageTile .mx_SenderProfile {
|
||||
.mx_EventTile .mx_SenderProfile {
|
||||
color: #454545;
|
||||
opacity: 0.5;
|
||||
font-size: 14px;
|
||||
|
@ -47,35 +47,35 @@ limitations under the License.
|
|||
display: block;
|
||||
}
|
||||
|
||||
.mx_MessageTile .mx_MessageTimestamp {
|
||||
.mx_EventTile .mx_MessageTimestamp {
|
||||
color: #454545;
|
||||
opacity: 0.5;
|
||||
font-size: 14px;
|
||||
float: right;
|
||||
}
|
||||
|
||||
.mx_MessageTile_content {
|
||||
.mx_EventTile_content {
|
||||
padding-right: 100px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.mx_MessageTile_notice .mx_MessageTile_content {
|
||||
.mx_EventTile_notice .mx_MessageTile_content {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.mx_MessageTile_sending {
|
||||
.mx_EventTile_sending {
|
||||
color: #ddd;
|
||||
}
|
||||
|
||||
.mx_MessageTile_notSent {
|
||||
.mx_EventTile_notSent {
|
||||
color: #f11;
|
||||
}
|
||||
|
||||
.mx_MessageTile_highlight {
|
||||
.mx_EventTile_highlight {
|
||||
color: #FF0064;
|
||||
}
|
||||
|
||||
.mx_MessageTile_msgOption {
|
||||
.mx_EventTile_msgOption {
|
||||
float: right;
|
||||
}
|
||||
|
||||
|
@ -83,29 +83,30 @@ limitations under the License.
|
|||
display: none;
|
||||
}
|
||||
|
||||
.mx_MessageTile_last .mx_MessageTimestamp {
|
||||
.mx_EventTile_last .mx_MessageTimestamp {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.mx_MessageTile:hover .mx_MessageTimestamp {
|
||||
.mx_EventTile:hover .mx_MessageTimestamp {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.mx_MessageTile_editButton {
|
||||
.mx_EventTile_editButton {
|
||||
float: right;
|
||||
display: none;
|
||||
border: 0px;
|
||||
outline: none;
|
||||
margin-right: 3px;
|
||||
}
|
||||
|
||||
.mx_MessageTile:hover .mx_MessageTile_editButton {
|
||||
.mx_EventTile:hover .mx_EventTile_editButton {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.mx_MessageTile.menu .mx_MessageTile_editButton {
|
||||
.mx_EventTile.menu .mx_EventTile_editButton {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.mx_MessageTile.menu .mx_MessageTimestamp {
|
||||
.mx_EventTile.menu .mx_MessageTimestamp {
|
||||
display: inline-block;
|
||||
}
|
|
@ -41,6 +41,7 @@ skin['molecules.ChangeDisplayName'] = require('./views/molecules/ChangeDisplayNa
|
|||
skin['molecules.ChangePassword'] = require('./views/molecules/ChangePassword');
|
||||
skin['molecules.DateSeparator'] = require('./views/molecules/DateSeparator');
|
||||
skin['molecules.EventAsTextTile'] = require('./views/molecules/EventAsTextTile');
|
||||
skin['molecules.EventTile'] = require('./views/molecules/EventTile');
|
||||
skin['molecules.MatrixToolbar'] = require('./views/molecules/MatrixToolbar');
|
||||
skin['molecules.MemberInfo'] = require('./views/molecules/MemberInfo');
|
||||
skin['molecules.MemberTile'] = require('./views/molecules/MemberTile');
|
||||
|
|
|
@ -36,15 +36,8 @@ module.exports = React.createClass({
|
|||
var timestamp = this.props.last ? <MessageTimestamp ts={this.props.mxEvent.getTs()} /> : null;
|
||||
var avatar = this.props.mxEvent.sender ? <MemberAvatar member={this.props.mxEvent.sender} /> : null;
|
||||
return (
|
||||
<div className="mx_MessageTile mx_MessageTile_notice">
|
||||
<div className="mx_MessageTile_avatar">
|
||||
{ avatar }
|
||||
</div>
|
||||
{ timestamp }
|
||||
<span className="mx_SenderProfile"></span>
|
||||
<span className="mx_MessageTile_content">
|
||||
<div className="mx_EventAsTextTile">
|
||||
{TextForEvent.textForEvent(this.props.mxEvent)}
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
|
|
131
src/skins/vector/views/molecules/EventTile.js
Normal file
131
src/skins/vector/views/molecules/EventTile.js
Normal file
|
@ -0,0 +1,131 @@
|
|||
/*
|
||||
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 classNames = require("classnames");
|
||||
|
||||
var sdk = require('matrix-react-sdk')
|
||||
|
||||
var EventTileController = require('matrix-react-sdk/lib/controllers/molecules/EventTile')
|
||||
var ContextualMenu = require('../../../../ContextualMenu');
|
||||
|
||||
var eventTileTypes = {
|
||||
'm.room.message': 'molecules.MessageTile',
|
||||
'm.room.member' : 'molecules.EventAsTextTile',
|
||||
'm.call.invite' : 'molecules.EventAsTextTile',
|
||||
'm.call.answer' : 'molecules.EventAsTextTile',
|
||||
'm.call.hangup' : 'molecules.EventAsTextTile',
|
||||
'm.room.topic' : 'molecules.EventAsTextTile',
|
||||
};
|
||||
|
||||
module.exports = React.createClass({
|
||||
displayName: 'EventTile',
|
||||
mixins: [EventTileController],
|
||||
|
||||
statics: {
|
||||
supportsEventType: function(et) {
|
||||
return eventTileTypes[et] !== undefined;
|
||||
}
|
||||
},
|
||||
|
||||
getInitialState: function() {
|
||||
return {menu: false};
|
||||
},
|
||||
|
||||
onEditClicked: function(e) {
|
||||
var MessageContextMenu = sdk.getComponent('molecules.MessageContextMenu');
|
||||
var buttonRect = e.target.getBoundingClientRect()
|
||||
var x = window.innerWidth - buttonRect.left;
|
||||
var y = buttonRect.top + (e.target.height / 2);
|
||||
var self = this;
|
||||
ContextualMenu.createMenu(MessageContextMenu, {
|
||||
mxEvent: this.props.mxEvent,
|
||||
right: x,
|
||||
top: y,
|
||||
onFinished: function() {
|
||||
self.setState({menu: false});
|
||||
}
|
||||
});
|
||||
this.setState({menu: true});
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var MessageTimestamp = sdk.getComponent('atoms.MessageTimestamp');
|
||||
var SenderProfile = sdk.getComponent('molecules.SenderProfile');
|
||||
var MemberAvatar = sdk.getComponent('atoms.MemberAvatar');
|
||||
|
||||
var UnknownMessageTile = sdk.getComponent('molecules.UnknownMessageTile');
|
||||
|
||||
var content = this.props.mxEvent.getContent();
|
||||
var msgtype = content.msgtype;
|
||||
|
||||
var EventTileType = sdk.getComponent(eventTileTypes[this.props.mxEvent.getType()]);
|
||||
// This shouldn't happen: the caller should check we support this type
|
||||
// before trying to instantiate us
|
||||
if (!EventTileType) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var classes = classNames({
|
||||
mx_EventTile: true,
|
||||
mx_EventTile_sending: ['sending', 'queued'].indexOf(
|
||||
this.props.mxEvent.status
|
||||
) !== -1,
|
||||
mx_EventTile_notSent: this.props.mxEvent.status == 'not_sent',
|
||||
mx_EventTile_highlight: this.shouldHighlight(),
|
||||
mx_EventTile_continuation: this.props.continuation,
|
||||
mx_EventTile_last: this.props.last,
|
||||
menu: this.state.menu
|
||||
});
|
||||
var timestamp = <MessageTimestamp ts={this.props.mxEvent.getTs()} />
|
||||
var editButton = (
|
||||
<input
|
||||
type="image" src="img/edit.png" alt="Edit"
|
||||
className="mx_EventTile_editButton" onClick={this.onEditClicked}
|
||||
/>
|
||||
);
|
||||
|
||||
var aux = null;
|
||||
if (msgtype === 'm.image') aux = "sent an image";
|
||||
else if (msgtype === 'm.video') aux = "sent a video";
|
||||
else if (msgtype === 'm.file') aux = "uploaded a file";
|
||||
|
||||
var avatar, sender;
|
||||
if (!this.props.continuation) {
|
||||
if (this.props.mxEvent.sender) {
|
||||
avatar = (
|
||||
<div className="mx_EventTile_avatar">
|
||||
<MemberAvatar member={this.props.mxEvent.sender} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
sender = <SenderProfile mxEvent={this.props.mxEvent} aux={aux} />;
|
||||
}
|
||||
return (
|
||||
<div className={classes}>
|
||||
{ avatar }
|
||||
{ sender }
|
||||
<div>
|
||||
{ timestamp }
|
||||
{ editButton }
|
||||
<EventTileType mxEvent={this.props.mxEvent} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
});
|
|
@ -28,28 +28,7 @@ module.exports = React.createClass({
|
|||
displayName: 'MessageTile',
|
||||
mixins: [MessageTileController],
|
||||
|
||||
onEditClicked: function(e) {
|
||||
var MessageContextMenu = sdk.getComponent('molecules.MessageContextMenu');
|
||||
var buttonRect = e.target.getBoundingClientRect()
|
||||
var x = window.innerWidth - buttonRect.left;
|
||||
var y = buttonRect.top + (e.target.height / 2);
|
||||
var self = this;
|
||||
ContextualMenu.createMenu(MessageContextMenu, {
|
||||
mxEvent: this.props.mxEvent,
|
||||
right: x,
|
||||
top: y,
|
||||
onFinished: function() {
|
||||
self.setState({menu: false});
|
||||
}
|
||||
});
|
||||
this.setState({menu: true});
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var MessageTimestamp = sdk.getComponent('atoms.MessageTimestamp');
|
||||
var SenderProfile = sdk.getComponent('molecules.SenderProfile');
|
||||
var MemberAvatar = sdk.getComponent('atoms.MemberAvatar');
|
||||
|
||||
var UnknownMessageTile = sdk.getComponent('molecules.UnknownMessageTile');
|
||||
|
||||
var tileTypes = {
|
||||
|
@ -66,56 +45,7 @@ module.exports = React.createClass({
|
|||
if (msgtype && tileTypes[msgtype]) {
|
||||
TileType = tileTypes[msgtype];
|
||||
}
|
||||
var classes = classNames({
|
||||
mx_MessageTile: true,
|
||||
mx_MessageTile_sending: ['sending', 'queued'].indexOf(
|
||||
this.props.mxEvent.status
|
||||
) !== -1,
|
||||
mx_MessageTile_notSent: this.props.mxEvent.status == 'not_sent',
|
||||
mx_MessageTile_highlight: this.shouldHighlight(),
|
||||
mx_MessageTile_continuation: this.props.continuation,
|
||||
mx_MessageTile_last: this.props.last,
|
||||
menu: this.state.menu
|
||||
});
|
||||
var timestamp = <MessageTimestamp ts={this.props.mxEvent.getTs()} />
|
||||
var editButton = (
|
||||
<input
|
||||
type="image" src="img/edit.png" alt="Edit"
|
||||
className="mx_MessageTile_editButton" onClick={this.onEditClicked}
|
||||
/>
|
||||
);
|
||||
|
||||
var aux = null;
|
||||
if (msgtype === 'm.image') aux = "sent an image";
|
||||
else if (msgtype === 'm.video') aux = "sent a video";
|
||||
else if (msgtype === 'm.file') aux = "uploaded a file";
|
||||
|
||||
var avatar, sender, resend;
|
||||
if (!this.props.continuation) {
|
||||
if (this.props.mxEvent.sender) {
|
||||
avatar = (
|
||||
<div className="mx_MessageTile_avatar">
|
||||
<MemberAvatar member={this.props.mxEvent.sender} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
sender = <SenderProfile mxEvent={this.props.mxEvent} aux={aux} />;
|
||||
}
|
||||
if (this.props.mxEvent.status === "not_sent" && !this.state.resending) {
|
||||
resend = <button className="mx_MessageTile_msgOption" onClick={this.onResend}>
|
||||
Resend
|
||||
</button>;
|
||||
}
|
||||
return (
|
||||
<div className={classes}>
|
||||
{ avatar }
|
||||
{ sender }
|
||||
<div>
|
||||
{ timestamp }
|
||||
{ editButton }
|
||||
<TileType mxEvent={this.props.mxEvent} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
return <TileType mxEvent={this.props.mxEvent} />;
|
||||
},
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue