mirror of
https://github.com/vector-im/element-web.git
synced 2024-11-17 05:55:00 +08:00
Merge branch 'develop' into kegan/controller-merging4
This commit is contained in:
commit
78cfaeb5c3
@ -23,6 +23,7 @@ var highlight = require('highlight.js');
|
|||||||
var sanitizeHtmlParams = {
|
var sanitizeHtmlParams = {
|
||||||
allowedTags: [
|
allowedTags: [
|
||||||
'font', // custom to matrix. deliberately no h1/h2 to stop people shouting.
|
'font', // custom to matrix. deliberately no h1/h2 to stop people shouting.
|
||||||
|
'del', // for markdown
|
||||||
'h3', 'h4', 'h5', 'h6', 'blockquote', 'p', 'a', 'ul', 'ol',
|
'h3', 'h4', 'h5', 'h6', 'blockquote', 'p', 'a', 'ul', 'ol',
|
||||||
'nl', 'li', 'b', 'i', 'strong', 'em', 'strike', 'code', 'hr', 'br', 'div',
|
'nl', 'li', 'b', 'i', 'strong', 'em', 'strike', 'code', 'hr', 'br', 'div',
|
||||||
'table', 'thead', 'caption', 'tbody', 'tr', 'th', 'td', 'pre'
|
'table', 'thead', 'caption', 'tbody', 'tr', 'th', 'td', 'pre'
|
||||||
@ -48,39 +49,79 @@ var sanitizeHtmlParams = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
bodyToHtml: function(content, searchTerm) {
|
_applyHighlights: function(safeSnippet, highlights, html, k) {
|
||||||
var originalBody = content.body;
|
|
||||||
var body;
|
|
||||||
|
|
||||||
if (searchTerm) {
|
|
||||||
var lastOffset = 0;
|
var lastOffset = 0;
|
||||||
var bodyList = [];
|
|
||||||
var k = 0;
|
|
||||||
var offset;
|
var offset;
|
||||||
|
var nodes = [];
|
||||||
|
|
||||||
// XXX: rather than searching for the search term in the body,
|
// XXX: when highlighting HTML, synapse performs the search on the plaintext body,
|
||||||
// we should be looking at the match delimiters returned by the FTS engine
|
// but we're attempting to apply the highlights here to the HTML body. This is
|
||||||
if (content.format === "org.matrix.custom.html") {
|
// never going to end well - we really should be hooking into the sanitzer HTML
|
||||||
|
// parser to only attempt to highlight text nodes to avoid corrupting tags.
|
||||||
|
// If and when this happens, we'll probably have to split his method in two between
|
||||||
|
// HTML and plain-text highlighting.
|
||||||
|
|
||||||
var safeBody = sanitizeHtml(content.formatted_body, sanitizeHtmlParams);
|
var safeHighlight = html ? sanitizeHtml(highlights[0], sanitizeHtmlParams) : highlights[0];
|
||||||
var safeSearchTerm = sanitizeHtml(searchTerm, sanitizeHtmlParams);
|
while ((offset = safeSnippet.indexOf(safeHighlight, lastOffset)) >= 0) {
|
||||||
while ((offset = safeBody.indexOf(safeSearchTerm, lastOffset)) >= 0) {
|
// handle preamble
|
||||||
// FIXME: we need to apply the search highlighting to only the text elements of HTML, which means
|
if (offset > lastOffset) {
|
||||||
// hooking into the sanitizer parser rather than treating it as a string. Otherwise
|
nodes = nodes.concat(this._applySubHighlightsInRange(safeSnippet, lastOffset, offset, highlights, html, k));
|
||||||
// the act of highlighting a <b/> or whatever will break the HTML badly.
|
k += nodes.length;
|
||||||
bodyList.push(<span key={ k++ } dangerouslySetInnerHTML={{ __html: safeBody.substring(lastOffset, offset) }} />);
|
|
||||||
bodyList.push(<span key={ k++ } dangerouslySetInnerHTML={{ __html: safeSearchTerm }} className="mx_MessageTile_searchHighlight" />);
|
|
||||||
lastOffset = offset + safeSearchTerm.length;
|
|
||||||
}
|
}
|
||||||
bodyList.push(<span className="markdown-body" key={ k++ } dangerouslySetInnerHTML={{ __html: safeBody.substring(lastOffset) }} />);
|
|
||||||
|
// do highlight
|
||||||
|
if (html) {
|
||||||
|
nodes.push(<span key={ k++ } dangerouslySetInnerHTML={{ __html: safeHighlight }} className="mx_MessageTile_searchHighlight" />);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
while ((offset = originalBody.indexOf(searchTerm, lastOffset)) >= 0) {
|
nodes.push(<span key={ k++ } className="mx_MessageTile_searchHighlight">{ safeHighlight }</span>);
|
||||||
bodyList.push(<span key={ k++ } >{ originalBody.substring(lastOffset, offset) }</span>);
|
|
||||||
bodyList.push(<span key={ k++ } className="mx_MessageTile_searchHighlight">{ searchTerm }</span>);
|
|
||||||
lastOffset = offset + searchTerm.length;
|
|
||||||
}
|
}
|
||||||
bodyList.push(<span key={ k++ }>{ originalBody.substring(lastOffset) }</span>);
|
|
||||||
|
lastOffset = offset + safeHighlight.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
// handle postamble
|
||||||
|
if (lastOffset != safeSnippet.length) {
|
||||||
|
nodes = nodes.concat(this._applySubHighlightsInRange(safeSnippet, lastOffset, undefined, highlights, html, k));
|
||||||
|
k += nodes.length;
|
||||||
|
}
|
||||||
|
return nodes;
|
||||||
|
},
|
||||||
|
|
||||||
|
_applySubHighlightsInRange: function(safeSnippet, lastOffset, offset, highlights, html, k) {
|
||||||
|
var nodes = [];
|
||||||
|
if (highlights[1]) {
|
||||||
|
// recurse into this range to check for the next set of highlight matches
|
||||||
|
var subnodes = this._applyHighlights( safeSnippet.substring(lastOffset, offset), highlights.slice(1), html, k );
|
||||||
|
nodes = nodes.concat(subnodes);
|
||||||
|
k += subnodes.length;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// no more highlights to be found, just return the unhighlighted string
|
||||||
|
if (html) {
|
||||||
|
nodes.push(<span key={ k++ } dangerouslySetInnerHTML={{ __html: safeSnippet.substring(lastOffset, offset) }} />);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
nodes.push(<span key={ k++ }>{ safeSnippet.substring(lastOffset, offset) }</span>);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nodes;
|
||||||
|
},
|
||||||
|
|
||||||
|
bodyToHtml: function(content, highlights) {
|
||||||
|
var originalBody = content.body;
|
||||||
|
var body;
|
||||||
|
var k = 0;
|
||||||
|
|
||||||
|
if (highlights && highlights.length > 0) {
|
||||||
|
var bodyList = [];
|
||||||
|
|
||||||
|
if (content.format === "org.matrix.custom.html") {
|
||||||
|
var safeBody = sanitizeHtml(content.formatted_body, sanitizeHtmlParams);
|
||||||
|
bodyList = this._applyHighlights(safeBody, highlights, true, k);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
bodyList = this._applyHighlights(originalBody, highlights, true, k);
|
||||||
}
|
}
|
||||||
body = bodyList;
|
body = bodyList;
|
||||||
}
|
}
|
||||||
|
@ -43,7 +43,18 @@ class UserActivity {
|
|||||||
document.onkeypress = undefined;
|
document.onkeypress = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
_onUserActivity() {
|
_onUserActivity(event) {
|
||||||
|
if (event.screenX) {
|
||||||
|
if (event.screenX === this.lastScreenX &&
|
||||||
|
event.screenY === this.lastScreenY)
|
||||||
|
{
|
||||||
|
// mouse hasn't actually moved
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.lastScreenX = event.screenX;
|
||||||
|
this.lastScreenY = event.screenY;
|
||||||
|
}
|
||||||
|
|
||||||
this.lastActivityAtTs = (new Date).getTime();
|
this.lastActivityAtTs = (new Date).getTime();
|
||||||
if (this.lastDispatchAtTs < this.lastActivityAtTs - MIN_DISPATCH_INTERVAL) {
|
if (this.lastDispatchAtTs < this.lastActivityAtTs - MIN_DISPATCH_INTERVAL) {
|
||||||
this.lastDispatchAtTs = this.lastActivityAtTs;
|
this.lastDispatchAtTs = this.lastActivityAtTs;
|
||||||
|
@ -268,7 +268,7 @@ module.exports = React.createClass({
|
|||||||
{ avatar }
|
{ avatar }
|
||||||
{ sender }
|
{ sender }
|
||||||
<div className="mx_EventTile_line">
|
<div className="mx_EventTile_line">
|
||||||
<EventTileType mxEvent={this.props.mxEvent} searchTerm={this.props.searchTerm} />
|
<EventTileType mxEvent={this.props.mxEvent} highlights={this.props.highlights} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -1,44 +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 linkify = require('linkifyjs');
|
|
||||||
var linkifyElement = require('linkifyjs/element');
|
|
||||||
var linkifyMatrix = require('../../../linkify-matrix');
|
|
||||||
|
|
||||||
linkifyMatrix(linkify);
|
|
||||||
|
|
||||||
module.exports = React.createClass({
|
|
||||||
displayName: 'MEmoteMessage',
|
|
||||||
|
|
||||||
componentDidMount: function() {
|
|
||||||
linkifyElement(this.refs.content, linkifyMatrix.options);
|
|
||||||
},
|
|
||||||
|
|
||||||
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,59 +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 linkify = require('linkifyjs');
|
|
||||||
var linkifyElement = require('linkifyjs/element');
|
|
||||||
var linkifyMatrix = require('../../../linkify-matrix.js');
|
|
||||||
linkifyMatrix(linkify);
|
|
||||||
var HtmlUtils = require('../../../HtmlUtils');
|
|
||||||
|
|
||||||
module.exports = React.createClass({
|
|
||||||
displayName: 'MNoticeMessage',
|
|
||||||
|
|
||||||
componentDidMount: function() {
|
|
||||||
linkifyElement(this.refs.content, linkifyMatrix.options);
|
|
||||||
|
|
||||||
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>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
@ -69,12 +69,10 @@ module.exports = React.createClass({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<span className="mx_MVideoTile">
|
<span className="mx_MVideoTile">
|
||||||
<video className="mx_MVideoTile" src={cli.mxcUrlToHttp(content.url)} alt={content.body}
|
<video className="mx_MVideoTile" src={cli.mxcUrlToHttp(content.url)} alt={content.body}
|
||||||
controls preload={preload} autoplay="false" loop
|
controls preload={preload} autoPlay="0"
|
||||||
height={height} width={width} poster={poster}>
|
height={height} width={width} poster={poster}>
|
||||||
</video>
|
</video>
|
||||||
</span>
|
</span>
|
||||||
|
@ -32,9 +32,9 @@ module.exports = React.createClass({
|
|||||||
var UnknownMessageTile = sdk.getComponent('messages.UnknownMessage');
|
var UnknownMessageTile = sdk.getComponent('messages.UnknownMessage');
|
||||||
|
|
||||||
var tileTypes = {
|
var tileTypes = {
|
||||||
'm.text': sdk.getComponent('messages.MTextMessage'),
|
'm.text': sdk.getComponent('messages.TextualMessage'),
|
||||||
'm.notice': sdk.getComponent('messages.MNoticeMessage'),
|
'm.notice': sdk.getComponent('messages.TextualMessage'),
|
||||||
'm.emote': sdk.getComponent('messages.MEmoteMessage'),
|
'm.emote': sdk.getComponent('messages.TextualMessage'),
|
||||||
'm.image': sdk.getComponent('messages.MImageMessage'),
|
'm.image': sdk.getComponent('messages.MImageMessage'),
|
||||||
'm.file': sdk.getComponent('messages.MFileMessage'),
|
'm.file': sdk.getComponent('messages.MFileMessage'),
|
||||||
'm.video': sdk.getComponent('messages.MVideoMessage')
|
'm.video': sdk.getComponent('messages.MVideoMessage')
|
||||||
@ -47,6 +47,6 @@ module.exports = React.createClass({
|
|||||||
TileType = tileTypes[msgtype];
|
TileType = tileTypes[msgtype];
|
||||||
}
|
}
|
||||||
|
|
||||||
return <TileType mxEvent={this.props.mxEvent} searchTerm={this.props.searchTerm} />;
|
return <TileType mxEvent={this.props.mxEvent} highlights={this.props.highlights} />;
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -69,6 +69,7 @@ module.exports = React.createClass({
|
|||||||
original: null,
|
original: null,
|
||||||
index: 0
|
index: 0
|
||||||
};
|
};
|
||||||
|
var self = this;
|
||||||
this.sentHistory = {
|
this.sentHistory = {
|
||||||
// The list of typed messages. Index 0 is more recent
|
// The list of typed messages. Index 0 is more recent
|
||||||
data: [],
|
data: [],
|
||||||
@ -138,6 +139,8 @@ module.exports = React.createClass({
|
|||||||
// restore the original text the user was typing.
|
// restore the original text the user was typing.
|
||||||
this.element.value = this.originalText;
|
this.element.value = this.originalText;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.resizeInput();
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -153,6 +156,7 @@ module.exports = React.createClass({
|
|||||||
var text = window.sessionStorage.getItem("input_" + this.roomId);
|
var text = window.sessionStorage.getItem("input_" + this.roomId);
|
||||||
if (text) {
|
if (text) {
|
||||||
this.element.value = text;
|
this.element.value = text;
|
||||||
|
self.resizeInput();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -164,6 +168,7 @@ module.exports = React.createClass({
|
|||||||
this.refs.textarea,
|
this.refs.textarea,
|
||||||
this.props.room.roomId
|
this.props.room.roomId
|
||||||
);
|
);
|
||||||
|
this.resizeInput();
|
||||||
},
|
},
|
||||||
|
|
||||||
componentWillUnmount: function() {
|
componentWillUnmount: function() {
|
||||||
@ -235,7 +240,7 @@ module.exports = React.createClass({
|
|||||||
// temporarily crimp clientHeight to 0 to get an accurate scrollHeight value
|
// temporarily crimp clientHeight to 0 to get an accurate scrollHeight value
|
||||||
this.refs.textarea.style.height = "0px";
|
this.refs.textarea.style.height = "0px";
|
||||||
var newHeight = this.refs.textarea.scrollHeight < 100 ? this.refs.textarea.scrollHeight : 100;
|
var newHeight = this.refs.textarea.scrollHeight < 100 ? this.refs.textarea.scrollHeight : 100;
|
||||||
this.refs.textarea.style.height = newHeight + "px";
|
this.refs.textarea.style.height = Math.ceil(newHeight) + "px";
|
||||||
if (this.props.roomView) {
|
if (this.props.roomView) {
|
||||||
// kick gemini-scrollbar to re-layout
|
// kick gemini-scrollbar to re-layout
|
||||||
this.props.roomView.forceUpdate();
|
this.props.roomView.forceUpdate();
|
||||||
@ -307,23 +312,21 @@ module.exports = React.createClass({
|
|||||||
|
|
||||||
var isEmote = /^\/me /i.test(contentText);
|
var isEmote = /^\/me /i.test(contentText);
|
||||||
var sendMessagePromise;
|
var sendMessagePromise;
|
||||||
|
|
||||||
if (isEmote) {
|
if (isEmote) {
|
||||||
sendMessagePromise = MatrixClientPeg.get().sendEmoteMessage(
|
contentText = contentText.substring(4);
|
||||||
this.props.room.roomId, contentText.substring(4)
|
}
|
||||||
);
|
|
||||||
|
var htmlText;
|
||||||
|
if (this.markdownEnabled && (htmlText = mdownToHtml(contentText)) !== contentText) {
|
||||||
|
sendMessagePromise = isEmote ?
|
||||||
|
MatrixClientPeg.get().sendHtmlEmote(this.props.room.roomId, contentText, htmlText) :
|
||||||
|
MatrixClientPeg.get().sendHtmlMessage(this.props.room.roomId, contentText, htmlText);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
var htmlText = mdownToHtml(contentText);
|
sendMessagePromise = isEmote ?
|
||||||
if (this.markdownEnabled && htmlText !== contentText) {
|
MatrixClientPeg.get().sendEmoteMessage(this.props.room.roomId, contentText) :
|
||||||
sendMessagePromise = MatrixClientPeg.get().sendHtmlMessage(
|
MatrixClientPeg.get().sendTextMessage(this.props.room.roomId, contentText);
|
||||||
this.props.room.roomId, contentText, htmlText
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
sendMessagePromise = MatrixClientPeg.get().sendTextMessage(
|
|
||||||
this.props.room.roomId, contentText
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sendMessagePromise.then(function() {
|
sendMessagePromise.then(function() {
|
||||||
|
@ -17,6 +17,7 @@ limitations under the License.
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var React = require('react');
|
var React = require('react');
|
||||||
|
var ReactDOM = require('react-dom');
|
||||||
var HtmlUtils = require('../../../HtmlUtils');
|
var HtmlUtils = require('../../../HtmlUtils');
|
||||||
var linkify = require('linkifyjs');
|
var linkify = require('linkifyjs');
|
||||||
var linkifyElement = require('linkifyjs/element');
|
var linkifyElement = require('linkifyjs/element');
|
||||||
@ -25,35 +26,52 @@ var linkifyMatrix = require('../../../linkify-matrix');
|
|||||||
linkifyMatrix(linkify);
|
linkifyMatrix(linkify);
|
||||||
|
|
||||||
module.exports = React.createClass({
|
module.exports = React.createClass({
|
||||||
displayName: 'MTextMessage',
|
displayName: 'TextualMessage',
|
||||||
|
|
||||||
componentDidMount: function() {
|
componentDidMount: function() {
|
||||||
linkifyElement(this.refs.content, linkifyMatrix.options);
|
linkifyElement(this.refs.content, linkifyMatrix.options);
|
||||||
|
|
||||||
if (this.props.mxEvent.getContent().format === "org.matrix.custom.html")
|
if (this.props.mxEvent.getContent().format === "org.matrix.custom.html")
|
||||||
HtmlUtils.highlightDom(this.getDOMNode());
|
HtmlUtils.highlightDom(ReactDOM.findDOMNode(this));
|
||||||
},
|
},
|
||||||
|
|
||||||
componentDidUpdate: function() {
|
componentDidUpdate: function() {
|
||||||
if (this.props.mxEvent.getContent().format === "org.matrix.custom.html")
|
if (this.props.mxEvent.getContent().format === "org.matrix.custom.html")
|
||||||
HtmlUtils.highlightDom(this.getDOMNode());
|
HtmlUtils.highlightDom(ReactDOM.findDOMNode(this));
|
||||||
},
|
},
|
||||||
|
|
||||||
shouldComponentUpdate: function(nextProps) {
|
shouldComponentUpdate: function(nextProps) {
|
||||||
// exploit that events are immutable :)
|
// exploit that events are immutable :)
|
||||||
return (nextProps.mxEvent.getId() !== this.props.mxEvent.getId() ||
|
return (nextProps.mxEvent.getId() !== this.props.mxEvent.getId() ||
|
||||||
nextProps.searchTerm !== this.props.searchTerm);
|
nextProps.highlights !== this.props.highlights);
|
||||||
},
|
},
|
||||||
|
|
||||||
render: function() {
|
render: function() {
|
||||||
var content = this.props.mxEvent.getContent();
|
var mxEvent = this.props.mxEvent;
|
||||||
var body = HtmlUtils.bodyToHtml(content, this.props.searchTerm);
|
var content = mxEvent.getContent();
|
||||||
|
var body = HtmlUtils.bodyToHtml(content, this.props.highlights);
|
||||||
|
|
||||||
|
switch (content.msgtype) {
|
||||||
|
case "m.emote":
|
||||||
|
var name = mxEvent.sender ? mxEvent.sender.name : mxEvent.getSender();
|
||||||
|
return (
|
||||||
|
<span ref="content" className="mx_MEmoteTile mx_MessageTile_content">
|
||||||
|
* { name } { body }
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
case "m.notice":
|
||||||
|
return (
|
||||||
|
<span ref="content" className="mx_MNoticeTile mx_MessageTile_content">
|
||||||
|
{ body }
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
default: // including "m.text"
|
||||||
return (
|
return (
|
||||||
<span ref="content" className="mx_MTextTile mx_MessageTile_content">
|
<span ref="content" className="mx_MTextTile mx_MessageTile_content">
|
||||||
{ body }
|
{ body }
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
@ -23,10 +23,6 @@ var sdk = require('../../../index');
|
|||||||
var dis = require('../../../dispatcher');
|
var dis = require('../../../dispatcher');
|
||||||
var Modal = require("../../../Modal");
|
var Modal = require("../../../Modal");
|
||||||
|
|
||||||
// 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({
|
module.exports = React.createClass({
|
||||||
displayName: 'MemberTile',
|
displayName: 'MemberTile',
|
||||||
|
|
||||||
@ -168,11 +164,6 @@ module.exports = React.createClass({
|
|||||||
// if (isMyUser) name += " (me)"; // this does nothing other than introduce line wrapping and pain
|
// 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 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;
|
var nameEl;
|
||||||
if (this.state.hover) {
|
if (this.state.hover) {
|
||||||
var presence;
|
var presence;
|
||||||
@ -194,7 +185,7 @@ module.exports = React.createClass({
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
nameEl =
|
nameEl =
|
||||||
<div className={nameClass}>
|
<div className="mx_MemberTile_name">
|
||||||
{ name }
|
{ name }
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user