Move all Event/Message Tiles to React SDK.
This commit is contained in:
parent
f969ccb50c
commit
40b974f22d
11 changed files with 20 additions and 796 deletions
|
@ -470,7 +470,7 @@ module.exports = {
|
||||||
var ret = [];
|
var ret = [];
|
||||||
var count = 0;
|
var count = 0;
|
||||||
|
|
||||||
var EventTile = sdk.getComponent('molecules.EventTile');
|
var EventTile = sdk.getComponent('messages.EventTile');
|
||||||
|
|
||||||
if (this.state.searchResults) {
|
if (this.state.searchResults) {
|
||||||
// XXX: this dance is foul, due to the results API not returning sorted results
|
// XXX: this dance is foul, due to the results API not returning sorted results
|
||||||
|
|
|
@ -32,48 +32,56 @@ 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');
|
||||||
skin['avatars.MemberAvatar'] = require('matrix-react-sdk/lib/components/views/avatars/MemberAvatar');
|
skin['avatars.MemberAvatar'] = require('matrix-react-sdk/lib/components/views/avatars/MemberAvatar');
|
||||||
|
|
||||||
skin['settings.EnableNotificationsButton'] = require('matrix-react-sdk/lib/components/views/settings/EnableNotificationsButton');
|
skin['settings.EnableNotificationsButton'] = require('matrix-react-sdk/lib/components/views/settings/EnableNotificationsButton');
|
||||||
skin['settings.ChangeAvatar'] = require('matrix-react-sdk/lib/components/views/settings/ChangeAvatar');
|
skin['settings.ChangeAvatar'] = require('matrix-react-sdk/lib/components/views/settings/ChangeAvatar');
|
||||||
skin['settings.ChangeDisplayName'] = require('matrix-react-sdk/lib/components/views/settings/ChangeDisplayName');
|
skin['settings.ChangeDisplayName'] = require('matrix-react-sdk/lib/components/views/settings/ChangeDisplayName');
|
||||||
skin['settings.ChangePassword'] = require('matrix-react-sdk/lib/components/views/settings/ChangePassword');
|
skin['settings.ChangePassword'] = require('matrix-react-sdk/lib/components/views/settings/ChangePassword');
|
||||||
|
|
||||||
skin['elements.EditableText'] = require('matrix-react-sdk/lib/components/views/elements/EditableText');
|
skin['elements.EditableText'] = require('matrix-react-sdk/lib/components/views/elements/EditableText');
|
||||||
skin['elements.ProgressBar'] = require('matrix-react-sdk/lib/components/views/elements/ProgressBar');
|
skin['elements.ProgressBar'] = require('matrix-react-sdk/lib/components/views/elements/ProgressBar');
|
||||||
skin['elements.UserSelector'] = require('matrix-react-sdk/lib/components/views/elements/UserSelector');
|
skin['elements.UserSelector'] = require('matrix-react-sdk/lib/components/views/elements/UserSelector');
|
||||||
|
|
||||||
skin['messages.MessageComposer'] = require('matrix-react-sdk/lib/components/views/messages/MessageComposer');
|
skin['messages.MessageComposer'] = require('matrix-react-sdk/lib/components/views/messages/MessageComposer');
|
||||||
|
skin['messages.TextualEvent'] = require('matrix-react-sdk/lib/components/views/messages/TextualEvent');
|
||||||
|
skin['messages.MRoomMemberEvent'] = require('matrix-react-sdk/lib/components/views/messages/MRoomMemberEvent');
|
||||||
|
skin['messages.Event'] = require('matrix-react-sdk/lib/components/views/messages/Event');
|
||||||
|
skin['messages.Message'] = require('matrix-react-sdk/lib/components/views/messages/Message');
|
||||||
|
skin['messages.MEmoteMessage'] = require('matrix-react-sdk/lib/components/views/messages/MEmoteMessage');
|
||||||
|
skin['messages.MFileMessage'] = require('matrix-react-sdk/lib/components/views/messages/MFileMessage');
|
||||||
|
skin['messages.MImageMessage'] = require('matrix-react-sdk/lib/components/views/messages/MImageMessage');
|
||||||
|
skin['messages.MNoticeMessage'] = require('matrix-react-sdk/lib/components/views/messages/MNoticeMessage');
|
||||||
|
skin['messages.MTextMessage'] = require('matrix-react-sdk/lib/components/views/messages/MTextMessage');
|
||||||
|
skin['messages.MVideoMessage'] = require('matrix-react-sdk/lib/components/views/messages/MVideoMessage');
|
||||||
|
skin['messages.UnknownMessage'] = require('matrix-react-sdk/lib/components/views/messages/UnknownMessage');
|
||||||
|
|
||||||
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['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');
|
||||||
|
|
||||||
skin['voip.CallView'] = require('matrix-react-sdk/lib/components/views/voip/CallView');
|
skin['voip.CallView'] = require('matrix-react-sdk/lib/components/views/voip/CallView');
|
||||||
skin['voip.IncomingCallBox'] = require('matrix-react-sdk/lib/components/views/voip/IncomingCallBox');
|
skin['voip.IncomingCallBox'] = require('matrix-react-sdk/lib/components/views/voip/IncomingCallBox');
|
||||||
skin['voip.VideoView'] = require('matrix-react-sdk/lib/components/views/voip/VideoView');
|
skin['voip.VideoView'] = require('matrix-react-sdk/lib/components/views/voip/VideoView');
|
||||||
skin['voip.VideoFeed'] = require('matrix-react-sdk/lib/components/views/voip/VideoFeed');
|
skin['voip.VideoFeed'] = require('matrix-react-sdk/lib/components/views/voip/VideoFeed');
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Old style stuff
|
// Old style stuff
|
||||||
skin['molecules.BottomLeftMenu'] = require('./views/molecules/BottomLeftMenu');
|
skin['molecules.BottomLeftMenu'] = require('./views/molecules/BottomLeftMenu');
|
||||||
skin['molecules.BottomLeftMenuTile'] = require('./views/molecules/BottomLeftMenuTile');
|
skin['molecules.BottomLeftMenuTile'] = require('./views/molecules/BottomLeftMenuTile');
|
||||||
skin['molecules.DateSeparator'] = require('./views/molecules/DateSeparator');
|
skin['molecules.DateSeparator'] = require('./views/molecules/DateSeparator');
|
||||||
skin['molecules.EventAsTextTile'] = require('./views/molecules/EventAsTextTile');
|
|
||||||
skin['molecules.EventTile'] = require('./views/molecules/EventTile');
|
|
||||||
skin['molecules.MEmoteTile'] = require('./views/molecules/MEmoteTile');
|
|
||||||
skin['molecules.MFileTile'] = require('./views/molecules/MFileTile');
|
|
||||||
skin['molecules.MImageTile'] = require('./views/molecules/MImageTile');
|
|
||||||
skin['molecules.MNoticeTile'] = require('./views/molecules/MNoticeTile');
|
|
||||||
skin['molecules.MRoomMemberTile'] = require('./views/molecules/MRoomMemberTile');
|
|
||||||
skin['molecules.MTextTile'] = require('./views/molecules/MTextTile');
|
|
||||||
skin['molecules.MVideoTile'] = require('./views/molecules/MVideoTile');
|
|
||||||
skin['molecules.MatrixToolbar'] = require('./views/molecules/MatrixToolbar');
|
skin['molecules.MatrixToolbar'] = require('./views/molecules/MatrixToolbar');
|
||||||
skin['molecules.MessageContextMenu'] = require('./views/molecules/MessageContextMenu');
|
skin['molecules.MessageContextMenu'] = require('./views/molecules/MessageContextMenu');
|
||||||
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.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');
|
||||||
skin['molecules.UnknownMessageTile'] = require('./views/molecules/UnknownMessageTile');
|
|
||||||
skin['organisms.CreateRoom'] = require('./views/organisms/CreateRoom');
|
skin['organisms.CreateRoom'] = require('./views/organisms/CreateRoom');
|
||||||
skin['organisms.ErrorDialog'] = require('./views/organisms/ErrorDialog');
|
skin['organisms.ErrorDialog'] = require('./views/organisms/ErrorDialog');
|
||||||
skin['organisms.LeftPanel'] = require('./views/organisms/LeftPanel');
|
skin['organisms.LeftPanel'] = require('./views/organisms/LeftPanel');
|
||||||
|
|
|
@ -1,274 +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 ReactDom = require('react-dom');
|
|
||||||
var classNames = require("classnames");
|
|
||||||
|
|
||||||
var sdk = require('matrix-react-sdk')
|
|
||||||
var MatrixClientPeg = require('matrix-react-sdk/lib/MatrixClientPeg')
|
|
||||||
|
|
||||||
var EventTileController = require('matrix-react-sdk/lib/controllers/molecules/EventTile')
|
|
||||||
var ContextualMenu = require('../../../../ContextualMenu');
|
|
||||||
|
|
||||||
var TextForEvent = require('matrix-react-sdk/lib/TextForEvent');
|
|
||||||
|
|
||||||
var Velociraptor = require('../../../../Velociraptor');
|
|
||||||
require('../../../../VelocityBounce');
|
|
||||||
|
|
||||||
var bounce = false;
|
|
||||||
try {
|
|
||||||
if (global.localStorage) {
|
|
||||||
bounce = global.localStorage.getItem('avatar_bounce') == 'true';
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
}
|
|
||||||
|
|
||||||
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.name' : 'molecules.EventAsTextTile',
|
|
||||||
'm.room.topic' : 'molecules.EventAsTextTile',
|
|
||||||
};
|
|
||||||
|
|
||||||
var MAX_READ_AVATARS = 5;
|
|
||||||
|
|
||||||
module.exports = React.createClass({
|
|
||||||
displayName: 'EventTile',
|
|
||||||
mixins: [EventTileController],
|
|
||||||
|
|
||||||
statics: {
|
|
||||||
haveTileForEvent: function(e) {
|
|
||||||
if (eventTileTypes[e.getType()] == undefined) return false;
|
|
||||||
if (eventTileTypes[e.getType()] == 'molecules.EventAsTextTile') {
|
|
||||||
return TextForEvent.textForEvent(e) !== '';
|
|
||||||
} else {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
getInitialState: function() {
|
|
||||||
return {menu: false, allReadAvatars: false};
|
|
||||||
},
|
|
||||||
|
|
||||||
onEditClicked: function(e) {
|
|
||||||
var MessageContextMenu = sdk.getComponent('molecules.MessageContextMenu');
|
|
||||||
var buttonRect = e.target.getBoundingClientRect()
|
|
||||||
var x = buttonRect.right;
|
|
||||||
var y = buttonRect.top + (e.target.height / 2);
|
|
||||||
var self = this;
|
|
||||||
ContextualMenu.createMenu(MessageContextMenu, {
|
|
||||||
mxEvent: this.props.mxEvent,
|
|
||||||
left: x,
|
|
||||||
top: y,
|
|
||||||
onFinished: function() {
|
|
||||||
self.setState({menu: false});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
this.setState({menu: true});
|
|
||||||
},
|
|
||||||
|
|
||||||
toggleAllReadAvatars: function() {
|
|
||||||
this.setState({
|
|
||||||
allReadAvatars: !this.state.allReadAvatars
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
getReadAvatars: function() {
|
|
||||||
var avatars = [];
|
|
||||||
|
|
||||||
var room = MatrixClientPeg.get().getRoom(this.props.mxEvent.getRoomId());
|
|
||||||
|
|
||||||
if (!room) return [];
|
|
||||||
|
|
||||||
var myUserId = MatrixClientPeg.get().credentials.userId;
|
|
||||||
|
|
||||||
// get list of read receipts, sorted most recent first
|
|
||||||
var receipts = room.getReceiptsForEvent(this.props.mxEvent).filter(function(r) {
|
|
||||||
return r.type === "m.read" && r.userId != myUserId;
|
|
||||||
}).sort(function(r1, r2) {
|
|
||||||
return r2.data.ts - r1.data.ts;
|
|
||||||
});
|
|
||||||
|
|
||||||
var MemberAvatar = sdk.getComponent('avatars.MemberAvatar');
|
|
||||||
|
|
||||||
var left = 0;
|
|
||||||
|
|
||||||
var reorderTransitionOpts = {
|
|
||||||
duration: 100,
|
|
||||||
easing: 'easeOut'
|
|
||||||
};
|
|
||||||
|
|
||||||
for (var i = 0; i < receipts.length; ++i) {
|
|
||||||
var member = room.getMember(receipts[i].userId);
|
|
||||||
|
|
||||||
// Using react refs here would mean both getting Velociraptor to expose
|
|
||||||
// them and making them scoped to the whole RoomView. Not impossible, but
|
|
||||||
// getElementById seems simpler at least for a first cut.
|
|
||||||
var oldAvatarDomNode = document.getElementById('mx_readAvatar'+member.userId);
|
|
||||||
var startStyles = [];
|
|
||||||
var enterTransitionOpts = [];
|
|
||||||
var oldNodeTop = -15; // For avatars that weren't on screen, act as if they were just off the top
|
|
||||||
if (oldAvatarDomNode) {
|
|
||||||
oldNodeTop = oldAvatarDomNode.getBoundingClientRect().top;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.readAvatarNode) {
|
|
||||||
var topOffset = oldNodeTop - this.readAvatarNode.getBoundingClientRect().top;
|
|
||||||
|
|
||||||
if (oldAvatarDomNode && oldAvatarDomNode.style.left !== '0px') {
|
|
||||||
var leftOffset = oldAvatarDomNode.style.left;
|
|
||||||
// start at the old height and in the old h pos
|
|
||||||
startStyles.push({ top: topOffset, left: leftOffset });
|
|
||||||
enterTransitionOpts.push(reorderTransitionOpts);
|
|
||||||
}
|
|
||||||
|
|
||||||
// then shift to the rightmost column,
|
|
||||||
// and then it will drop down to its resting position
|
|
||||||
startStyles.push({ top: topOffset, left: '0px' });
|
|
||||||
enterTransitionOpts.push({
|
|
||||||
duration: bounce ? Math.min(Math.log(Math.abs(topOffset)) * 200, 3000) : 300,
|
|
||||||
easing: bounce ? 'easeOutBounce' : 'easeOutCubic',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
var style = {
|
|
||||||
left: left+'px',
|
|
||||||
top: '0px',
|
|
||||||
visibility: ((i < MAX_READ_AVATARS) || this.state.allReadAvatars) ? 'visible' : 'hidden'
|
|
||||||
};
|
|
||||||
|
|
||||||
//console.log("i = " + i + ", MAX_READ_AVATARS = " + MAX_READ_AVATARS + ", allReadAvatars = " + this.state.allReadAvatars + " visibility = " + style.visibility);
|
|
||||||
|
|
||||||
// add to the start so the most recent is on the end (ie. ends up rightmost)
|
|
||||||
avatars.unshift(
|
|
||||||
<MemberAvatar key={member.userId} member={member}
|
|
||||||
width={14} height={14} resizeMethod="crop"
|
|
||||||
style={style}
|
|
||||||
startStyle={startStyles}
|
|
||||||
enterTransitionOpts={enterTransitionOpts}
|
|
||||||
id={'mx_readAvatar'+member.userId}
|
|
||||||
onClick={this.toggleAllReadAvatars}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
// TODO: we keep the extra read avatars in the dom to make animation simpler
|
|
||||||
// we could optimise this to reduce the dom size.
|
|
||||||
if (i < MAX_READ_AVATARS - 1 || this.state.allReadAvatars) { // XXX: where does this -1 come from? is it to make the max'th avatar animate properly?
|
|
||||||
left -= 15;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var editButton;
|
|
||||||
if (!this.state.allReadAvatars) {
|
|
||||||
var remainder = receipts.length - MAX_READ_AVATARS;
|
|
||||||
var remText;
|
|
||||||
if (i >= MAX_READ_AVATARS - 1) left -= 15;
|
|
||||||
if (remainder > 0) {
|
|
||||||
remText = <span className="mx_EventTile_readAvatarRemainder"
|
|
||||||
onClick={this.toggleAllReadAvatars}
|
|
||||||
style={{ left: left }}>{ remainder }+
|
|
||||||
</span>;
|
|
||||||
left -= 15;
|
|
||||||
}
|
|
||||||
editButton = (
|
|
||||||
<input style={{ left: left }}
|
|
||||||
type="image" src="img/edit.png" alt="Options" title="Options" width="14" height="14"
|
|
||||||
className="mx_EventTile_editButton" onClick={this.onEditClicked} />
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return <span className="mx_EventTile_readAvatars" ref={this.collectReadAvatarNode}>
|
|
||||||
{ editButton }
|
|
||||||
{ remText }
|
|
||||||
<Velociraptor transition={ reorderTransitionOpts }>
|
|
||||||
{ avatars }
|
|
||||||
</Velociraptor>
|
|
||||||
</span>;
|
|
||||||
},
|
|
||||||
|
|
||||||
collectReadAvatarNode: function(node) {
|
|
||||||
this.readAvatarNode = ReactDom.findDOMNode(node);
|
|
||||||
},
|
|
||||||
|
|
||||||
render: function() {
|
|
||||||
var MessageTimestamp = sdk.getComponent('messages.MessageTimestamp');
|
|
||||||
var SenderProfile = sdk.getComponent('molecules.SenderProfile');
|
|
||||||
var MemberAvatar = sdk.getComponent('avatars.MemberAvatar');
|
|
||||||
|
|
||||||
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) {
|
|
||||||
throw new Error("Event type not supported");
|
|
||||||
}
|
|
||||||
|
|
||||||
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,
|
|
||||||
mx_EventTile_contextual: this.props.contextual,
|
|
||||||
menu: this.state.menu,
|
|
||||||
});
|
|
||||||
var timestamp = <MessageTimestamp ts={this.props.mxEvent.getTs()} />
|
|
||||||
|
|
||||||
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 readAvatars = this.getReadAvatars();
|
|
||||||
|
|
||||||
var avatar, sender;
|
|
||||||
if (!this.props.continuation) {
|
|
||||||
if (this.props.mxEvent.sender) {
|
|
||||||
avatar = (
|
|
||||||
<div className="mx_EventTile_avatar">
|
|
||||||
<MemberAvatar member={this.props.mxEvent.sender} width={24} height={24} />
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (EventTileType.needsSenderProfile()) {
|
|
||||||
sender = <SenderProfile mxEvent={this.props.mxEvent} aux={aux} />;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<div className={classes}>
|
|
||||||
<div className="mx_EventTile_msgOption">
|
|
||||||
{ timestamp }
|
|
||||||
{ readAvatars }
|
|
||||||
</div>
|
|
||||||
{ avatar }
|
|
||||||
{ sender }
|
|
||||||
<div className="mx_EventTile_line">
|
|
||||||
<EventTileType mxEvent={this.props.mxEvent} searchTerm={this.props.searchTerm} />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
});
|
|
|
@ -1,38 +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 MEmoteTileController = require('matrix-react-sdk/lib/controllers/molecules/MEmoteTile')
|
|
||||||
|
|
||||||
module.exports = React.createClass({
|
|
||||||
displayName: 'MEmoteTile',
|
|
||||||
mixins: [MEmoteTileController],
|
|
||||||
|
|
||||||
render: function() {
|
|
||||||
var mxEvent = this.props.mxEvent;
|
|
||||||
var content = mxEvent.getContent();
|
|
||||||
var name = mxEvent.sender ? mxEvent.sender.name : mxEvent.getSender();
|
|
||||||
return (
|
|
||||||
<span ref="content" className="mx_MEmoteTile mx_MessageTile_content">
|
|
||||||
* {name} {content.body}
|
|
||||||
</span>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
|
@ -1,54 +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 MFileTileController = require('matrix-react-sdk/lib/controllers/molecules/MFileTile')
|
|
||||||
|
|
||||||
var MatrixClientPeg = require('matrix-react-sdk/lib/MatrixClientPeg');
|
|
||||||
|
|
||||||
module.exports = React.createClass({
|
|
||||||
displayName: 'MFileTile',
|
|
||||||
mixins: [MFileTileController],
|
|
||||||
|
|
||||||
render: function() {
|
|
||||||
var content = this.props.mxEvent.getContent();
|
|
||||||
var cli = MatrixClientPeg.get();
|
|
||||||
|
|
||||||
var httpUrl = cli.mxcUrlToHttp(content.url);
|
|
||||||
var text = this.presentableTextForFile(content);
|
|
||||||
|
|
||||||
if (httpUrl) {
|
|
||||||
return (
|
|
||||||
<span className="mx_MFileTile">
|
|
||||||
<div className="mx_MImageTile_download">
|
|
||||||
<a href={cli.mxcUrlToHttp(content.url)} target="_blank">
|
|
||||||
<img src="img/download.png" width="10" height="12"/>
|
|
||||||
Download {text}
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</span>
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
var extra = text ? ': '+text : '';
|
|
||||||
return <span className="mx_MFileTile">
|
|
||||||
Invalid file{extra}
|
|
||||||
</span>
|
|
||||||
}
|
|
||||||
},
|
|
||||||
});
|
|
|
@ -1,136 +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 filesize = require('filesize');
|
|
||||||
|
|
||||||
var MatrixClientPeg = require('matrix-react-sdk/lib/MatrixClientPeg');
|
|
||||||
var Modal = require('matrix-react-sdk/lib/Modal');
|
|
||||||
var sdk = require('matrix-react-sdk')
|
|
||||||
|
|
||||||
module.exports = React.createClass({
|
|
||||||
displayName: 'MImageTile',
|
|
||||||
|
|
||||||
thumbHeight: function(fullWidth, fullHeight, thumbWidth, thumbHeight) {
|
|
||||||
if (!fullWidth || !fullHeight) {
|
|
||||||
// Cannot calculate thumbnail height for image: missing w/h in metadata. We can't even
|
|
||||||
// log this because it's spammy
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
if (fullWidth < thumbWidth && fullHeight < thumbHeight) {
|
|
||||||
// no scaling needs to be applied
|
|
||||||
return fullHeight;
|
|
||||||
}
|
|
||||||
var widthMulti = thumbWidth / fullWidth;
|
|
||||||
var heightMulti = thumbHeight / fullHeight;
|
|
||||||
if (widthMulti < heightMulti) {
|
|
||||||
// width is the dominant dimension so scaling will be fixed on that
|
|
||||||
return Math.floor(widthMulti * fullHeight);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// height is the dominant dimension so scaling will be fixed on that
|
|
||||||
return Math.floor(heightMulti * fullHeight);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
onClick: function(ev) {
|
|
||||||
if (ev.button == 0 && !ev.metaKey) {
|
|
||||||
ev.preventDefault();
|
|
||||||
var content = this.props.mxEvent.getContent();
|
|
||||||
var httpUrl = MatrixClientPeg.get().mxcUrlToHttp(content.url);
|
|
||||||
var ImageView = sdk.getComponent("elements.ImageView");
|
|
||||||
Modal.createDialog(ImageView, {
|
|
||||||
src: httpUrl,
|
|
||||||
width: content.info.w,
|
|
||||||
height: content.info.h,
|
|
||||||
mxEvent: this.props.mxEvent,
|
|
||||||
}, "mx_Dialog_lightbox");
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
_isGif: function() {
|
|
||||||
var content = this.props.mxEvent.getContent();
|
|
||||||
return (content && content.info && content.info.mimetype === "image/gif");
|
|
||||||
},
|
|
||||||
|
|
||||||
onImageEnter: function(e) {
|
|
||||||
if (!this._isGif()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var imgElement = e.target;
|
|
||||||
imgElement.src = MatrixClientPeg.get().mxcUrlToHttp(
|
|
||||||
this.props.mxEvent.getContent().url
|
|
||||||
);
|
|
||||||
},
|
|
||||||
|
|
||||||
onImageLeave: function(e) {
|
|
||||||
if (!this._isGif()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var imgElement = e.target;
|
|
||||||
imgElement.src = this._getThumbUrl();
|
|
||||||
},
|
|
||||||
|
|
||||||
_getThumbUrl: function() {
|
|
||||||
var content = this.props.mxEvent.getContent();
|
|
||||||
return MatrixClientPeg.get().mxcUrlToHttp(content.url, 480, 360);
|
|
||||||
},
|
|
||||||
|
|
||||||
render: function() {
|
|
||||||
var content = this.props.mxEvent.getContent();
|
|
||||||
var cli = MatrixClientPeg.get();
|
|
||||||
|
|
||||||
var thumbHeight = null;
|
|
||||||
if (content.info) thumbHeight = this.thumbHeight(content.info.w, content.info.h, 480, 360);
|
|
||||||
|
|
||||||
var imgStyle = {};
|
|
||||||
if (thumbHeight) imgStyle['height'] = thumbHeight;
|
|
||||||
|
|
||||||
var thumbUrl = this._getThumbUrl();
|
|
||||||
if (thumbUrl) {
|
|
||||||
return (
|
|
||||||
<span className="mx_MImageTile">
|
|
||||||
<a href={cli.mxcUrlToHttp(content.url)} onClick={ this.onClick }>
|
|
||||||
<img className="mx_MImageTile_thumbnail" src={thumbUrl}
|
|
||||||
alt={content.body} style={imgStyle}
|
|
||||||
onMouseEnter={this.onImageEnter}
|
|
||||||
onMouseLeave={this.onImageLeave} />
|
|
||||||
</a>
|
|
||||||
<div className="mx_MImageTile_download">
|
|
||||||
<a href={cli.mxcUrlToHttp(content.url)} target="_blank">
|
|
||||||
<img src="img/download.png" width="10" height="12"/>
|
|
||||||
Download {content.body} ({ content.info && content.info.size ? filesize(content.info.size) : "Unknown size" })
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</span>
|
|
||||||
);
|
|
||||||
} else if (content.body) {
|
|
||||||
return (
|
|
||||||
<span className="mx_MImageTile">
|
|
||||||
Image '{content.body}' cannot be displayed.
|
|
||||||
</span>
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return (
|
|
||||||
<span className="mx_MImageTile">
|
|
||||||
This image cannot be displayed.
|
|
||||||
</span>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
});
|
|
|
@ -1,56 +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 HtmlUtils = require('../../../../HtmlUtils');
|
|
||||||
|
|
||||||
var MNoticeTileController = require('matrix-react-sdk/lib/controllers/molecules/MNoticeTile')
|
|
||||||
|
|
||||||
module.exports = React.createClass({
|
|
||||||
displayName: 'MNoticeTile',
|
|
||||||
mixins: [MNoticeTileController],
|
|
||||||
|
|
||||||
componentDidMount: function() {
|
|
||||||
if (this.props.mxEvent.getContent().format === "org.matrix.custom.html")
|
|
||||||
HtmlUtils.highlightDom(this.getDOMNode());
|
|
||||||
},
|
|
||||||
|
|
||||||
componentDidUpdate: function() {
|
|
||||||
if (this.props.mxEvent.getContent().format === "org.matrix.custom.html")
|
|
||||||
HtmlUtils.highlightDom(this.getDOMNode());
|
|
||||||
},
|
|
||||||
|
|
||||||
shouldComponentUpdate: function(nextProps) {
|
|
||||||
// exploit that events are immutable :)
|
|
||||||
return (nextProps.mxEvent.getId() !== this.props.mxEvent.getId() ||
|
|
||||||
nextProps.searchTerm !== this.props.searchTerm);
|
|
||||||
},
|
|
||||||
|
|
||||||
// XXX: fix horrible duplication with MTextTile
|
|
||||||
render: function() {
|
|
||||||
var content = this.props.mxEvent.getContent();
|
|
||||||
var body = HtmlUtils.bodyToHtml(content, this.props.searchTerm);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<span ref="content" className="mx_MNoticeTile mx_MessageTile_content">
|
|
||||||
{ body }
|
|
||||||
</span>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
|
@ -1,55 +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 HtmlUtils = require('../../../../HtmlUtils');
|
|
||||||
|
|
||||||
var MTextTileController = require('matrix-react-sdk/lib/controllers/molecules/MTextTile')
|
|
||||||
|
|
||||||
module.exports = React.createClass({
|
|
||||||
displayName: 'MTextTile',
|
|
||||||
mixins: [MTextTileController],
|
|
||||||
|
|
||||||
componentDidMount: function() {
|
|
||||||
if (this.props.mxEvent.getContent().format === "org.matrix.custom.html")
|
|
||||||
HtmlUtils.highlightDom(this.getDOMNode());
|
|
||||||
},
|
|
||||||
|
|
||||||
componentDidUpdate: function() {
|
|
||||||
if (this.props.mxEvent.getContent().format === "org.matrix.custom.html")
|
|
||||||
HtmlUtils.highlightDom(this.getDOMNode());
|
|
||||||
},
|
|
||||||
|
|
||||||
shouldComponentUpdate: function(nextProps) {
|
|
||||||
// exploit that events are immutable :)
|
|
||||||
return (nextProps.mxEvent.getId() !== this.props.mxEvent.getId() ||
|
|
||||||
nextProps.searchTerm !== this.props.searchTerm);
|
|
||||||
},
|
|
||||||
|
|
||||||
render: function() {
|
|
||||||
var content = this.props.mxEvent.getContent();
|
|
||||||
var body = HtmlUtils.bodyToHtml(content, this.props.searchTerm);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<span ref="content" className="mx_MTextTile mx_MessageTile_content">
|
|
||||||
{ body }
|
|
||||||
</span>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
|
@ -1,83 +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 filesize = require('filesize');
|
|
||||||
|
|
||||||
var MatrixClientPeg = require('matrix-react-sdk/lib/MatrixClientPeg');
|
|
||||||
var Modal = require('matrix-react-sdk/lib/Modal');
|
|
||||||
var sdk = require('matrix-react-sdk')
|
|
||||||
|
|
||||||
module.exports = React.createClass({
|
|
||||||
displayName: 'MVideoTile',
|
|
||||||
|
|
||||||
thumbScale: function(fullWidth, fullHeight, thumbWidth, thumbHeight) {
|
|
||||||
if (!fullWidth || !fullHeight) {
|
|
||||||
// Cannot calculate thumbnail height for image: missing w/h in metadata. We can't even
|
|
||||||
// log this because it's spammy
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
if (fullWidth < thumbWidth && fullHeight < thumbHeight) {
|
|
||||||
// no scaling needs to be applied
|
|
||||||
return fullHeight;
|
|
||||||
}
|
|
||||||
var widthMulti = thumbWidth / fullWidth;
|
|
||||||
var heightMulti = thumbHeight / fullHeight;
|
|
||||||
if (widthMulti < heightMulti) {
|
|
||||||
// width is the dominant dimension so scaling will be fixed on that
|
|
||||||
return widthMulti;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// height is the dominant dimension so scaling will be fixed on that
|
|
||||||
return heightMulti;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
render: function() {
|
|
||||||
var content = this.props.mxEvent.getContent();
|
|
||||||
var cli = MatrixClientPeg.get();
|
|
||||||
|
|
||||||
var height = null;
|
|
||||||
var width = null;
|
|
||||||
var poster = null;
|
|
||||||
var preload = "metadata";
|
|
||||||
if (content.info) {
|
|
||||||
var scale = this.thumbScale(content.info.w, content.info.h, 480, 360);
|
|
||||||
if (scale) {
|
|
||||||
width = Math.floor(content.info.w * scale);
|
|
||||||
height = Math.floor(content.info.h * scale);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (content.info.thumbnail_url) {
|
|
||||||
poster = cli.mxcUrlToHttp(content.info.thumbnail_url);
|
|
||||||
preload = "none";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return (
|
|
||||||
<span className="mx_MVideoTile">
|
|
||||||
<video className="mx_MVideoTile" src={cli.mxcUrlToHttp(content.url)} alt={content.body}
|
|
||||||
controls preload={preload} autoplay="false" loop
|
|
||||||
height={height} width={width} poster={poster}>
|
|
||||||
</video>
|
|
||||||
</span>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
});
|
|
|
@ -1,56 +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 sdk = require('matrix-react-sdk')
|
|
||||||
|
|
||||||
var MessageTileController = require('matrix-react-sdk/lib/controllers/molecules/MessageTile')
|
|
||||||
|
|
||||||
module.exports = React.createClass({
|
|
||||||
displayName: 'MessageTile',
|
|
||||||
mixins: [MessageTileController],
|
|
||||||
|
|
||||||
statics: {
|
|
||||||
needsSenderProfile: function() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
render: function() {
|
|
||||||
var UnknownMessageTile = sdk.getComponent('molecules.UnknownMessageTile');
|
|
||||||
|
|
||||||
var tileTypes = {
|
|
||||||
'm.text': sdk.getComponent('molecules.MTextTile'),
|
|
||||||
'm.notice': sdk.getComponent('molecules.MNoticeTile'),
|
|
||||||
'm.emote': sdk.getComponent('molecules.MEmoteTile'),
|
|
||||||
'm.image': sdk.getComponent('molecules.MImageTile'),
|
|
||||||
'm.file': sdk.getComponent('molecules.MFileTile'),
|
|
||||||
'm.video': sdk.getComponent('molecules.MVideoTile')
|
|
||||||
};
|
|
||||||
|
|
||||||
var content = this.props.mxEvent.getContent();
|
|
||||||
var msgtype = content.msgtype;
|
|
||||||
var TileType = UnknownMessageTile;
|
|
||||||
if (msgtype && tileTypes[msgtype]) {
|
|
||||||
TileType = tileTypes[msgtype];
|
|
||||||
}
|
|
||||||
|
|
||||||
return <TileType mxEvent={this.props.mxEvent} searchTerm={this.props.searchTerm} />;
|
|
||||||
},
|
|
||||||
});
|
|
|
@ -1,32 +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');
|
|
||||||
|
|
||||||
module.exports = React.createClass({
|
|
||||||
displayName: 'UnknownMessageTile',
|
|
||||||
|
|
||||||
render: function() {
|
|
||||||
var content = this.props.mxEvent.getContent();
|
|
||||||
return (
|
|
||||||
<span className="mx_UnknownMessageTile">
|
|
||||||
{content.body}
|
|
||||||
</span>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
});
|
|
Loading…
Reference in a new issue