Skip to content
This repository has been archived by the owner on Sep 11, 2024. It is now read-only.

Commit

Permalink
Merge pull request #3711 from matrix-org/t3chguy/clean_up_TextualBody
Browse files Browse the repository at this point in the history
Change ref handling in TextualBody to prevent it parsing generated nodes
  • Loading branch information
t3chguy authored Jan 9, 2020
2 parents 1d9d706 + f3f9292 commit 71b3005
Show file tree
Hide file tree
Showing 11 changed files with 659 additions and 27 deletions.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,8 @@
"babel-preset-react": "^6.24.1",
"chokidar": "^2.1.2",
"concurrently": "^4.0.1",
"enzyme": "^3.10.0",
"enzyme-adapter-react-16": "^1.15.1",
"eslint": "^5.12.0",
"eslint-config-google": "^0.7.1",
"eslint-plugin-babel": "^5.2.1",
Expand Down
5 changes: 3 additions & 2 deletions src/HtmlUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -377,6 +377,7 @@ class TextHighlighter extends BaseHighlighter {
* opts.stripReplyFallback: optional argument specifying the event is a reply and so fallback needs removing
* opts.returnString: return an HTML string rather than JSX elements
* opts.forComposerQuote: optional param to lessen the url rewriting done by sanitization, for quoting into composer
* opts.ref: React ref to attach to any React components returned (not compatible with opts.returnString)
*/
export function bodyToHtml(content, highlights, opts={}) {
const isHtmlMessage = content.format === "org.matrix.custom.html" && content.formatted_body;
Expand Down Expand Up @@ -459,8 +460,8 @@ export function bodyToHtml(content, highlights, opts={}) {
});

return isDisplayedWithHtml ?
<span key="body" className={className} dangerouslySetInnerHTML={{ __html: safeBody }} dir="auto" /> :
<span key="body" className={className} dir="auto">{ strippedBody }</span>;
<span key="body" ref={opts.ref} className={className} dangerouslySetInnerHTML={{ __html: safeBody }} dir="auto" /> :
<span key="body" ref={opts.ref} className={className} dir="auto">{ strippedBody }</span>;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import MatrixClientPeg from '../../../../MatrixClientPeg';
import { scorePassword } from '../../../../utils/PasswordScorer';
import { _t } from '../../../../languageHandler';
import { accessSecretStorage } from '../../../../CrossSigningManager';
import SettingsStore from '../../../../../lib/settings/SettingsStore';
import SettingsStore from '../../../../settings/SettingsStore';

const PHASE_PASSPHRASE = 0;
const PHASE_PASSPHRASE_CONFIRM = 1;
Expand Down
2 changes: 1 addition & 1 deletion src/components/views/context_menus/MessageContextMenu.js
Original file line number Diff line number Diff line change
Expand Up @@ -422,7 +422,7 @@ module.exports = createReactClass({
</MenuItem>
);

if (this.props.eventTileOps && this.props.eventTileOps.getInnerText) {
if (this.props.eventTileOps) { // this event is rendered using TextualBody
quoteButton = (
<MenuItem className="mx_MessageContextMenu_field" onClick={this.onQuoteClick}>
{ _t('Quote') }
Expand Down
2 changes: 1 addition & 1 deletion src/components/views/elements/Pill.js
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@ const Pill = createReactClass({
}

const classes = classNames("mx_Pill", pillClass, {
"mx_UserPill_me": userId === MatrixClientPeg.get().credentials.userId,
"mx_UserPill_me": userId === MatrixClientPeg.get().getUserId(),
"mx_UserPill_selected": this.props.isSelected,
});

Expand Down
21 changes: 9 additions & 12 deletions src/components/views/messages/TextualBody.js
Original file line number Diff line number Diff line change
Expand Up @@ -98,12 +98,12 @@ module.exports = createReactClass({
},

_applyFormatting() {
this.activateSpoilers(this._content.current.children);
this.activateSpoilers([this._content.current]);

// pillifyLinks BEFORE linkifyElement because plain room/user URLs in the composer
// are still sent as plaintext URLs. If these are ever pillified in the composer,
// we should be pillify them here by doing the linkifying BEFORE the pillifying.
pillifyLinks(this._content.current.children, this.props.mxEvent);
pillifyLinks([this._content.current], this.props.mxEvent);
HtmlUtils.linkifyElement(this._content.current);
this.calculateUrlPreview();

Expand Down Expand Up @@ -167,7 +167,8 @@ module.exports = createReactClass({
//console.info("calculateUrlPreview: ShowUrlPreview for %s is %s", this.props.mxEvent.getId(), this.props.showUrlPreview);

if (this.props.showUrlPreview) {
let links = this.findLinks(this._content.current.children);
// pass only the first child which is the event tile otherwise this recurses on edited events
let links = this.findLinks([this._content.current]);
if (links.length) {
// de-dup the links (but preserve ordering)
const seen = new Set();
Expand Down Expand Up @@ -329,10 +330,6 @@ module.exports = createReactClass({
global.localStorage.removeItem("hide_preview_" + this.props.mxEvent.getId());
}
},

getInnerText: () => {
return this._content.current.innerText;
},
};
},

Expand Down Expand Up @@ -433,6 +430,7 @@ module.exports = createReactClass({
disableBigEmoji: content.msgtype === "m.emote" || !SettingsStore.getValue('TextualBody.enableBigEmoji'),
// Part of Replies fallback support
stripReplyFallback: stripReply,
ref: this._content,
});
if (this.props.replacingEventId) {
body = [body, this._renderEditedMarker()];
Expand All @@ -459,15 +457,14 @@ module.exports = createReactClass({

switch (content.msgtype) {
case "m.emote":
const name = mxEvent.sender ? mxEvent.sender.name : mxEvent.getSender();
return (
<span ref={this._content} className="mx_MEmoteBody mx_EventTile_content">
<span className="mx_MEmoteBody mx_EventTile_content">
*&nbsp;
<span
className="mx_MEmoteBody_sender"
onClick={this.onEmoteSenderClick}
>
{ name }
{ mxEvent.sender ? mxEvent.sender.name : mxEvent.getSender() }
</span>
&nbsp;
{ body }
Expand All @@ -476,14 +473,14 @@ module.exports = createReactClass({
);
case "m.notice":
return (
<span ref={this._content} className="mx_MNoticeBody mx_EventTile_content">
<span className="mx_MNoticeBody mx_EventTile_content">
{ body }
{ widgets }
</span>
);
default: // including "m.text"
return (
<span ref={this._content} className="mx_MTextBody mx_EventTile_content">
<span className="mx_MTextBody mx_EventTile_content">
{ body }
{ widgets }
</span>
Expand Down
2 changes: 1 addition & 1 deletion src/components/views/settings/KeyBackupPanel.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import sdk from '../../../index';
import MatrixClientPeg from '../../../MatrixClientPeg';
import { _t } from '../../../languageHandler';
import Modal from '../../../Modal';
import SettingsStore from '../../../../lib/settings/SettingsStore';
import SettingsStore from '../../../settings/SettingsStore';

export default class KeyBackupPanel extends React.PureComponent {
constructor(props) {
Expand Down
1 change: 1 addition & 0 deletions src/utils/pillify.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/

import React from "react";
import ReactDOM from 'react-dom';
import MatrixClientPeg from '../MatrixClientPeg';
import SettingsStore from "../settings/SettingsStore";
Expand Down
Loading

0 comments on commit 71b3005

Please sign in to comment.