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

Show diff for formatted messages in the edit history #3244

Merged
merged 1 commit into from
Jul 24, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
"classnames": "^2.1.2",
"commonmark": "^0.28.1",
"counterpart": "^0.18.0",
"diff-dom": "^4.1.3",
"diff-match-patch": "^1.0.4",
"emojibase-data": "^4.0.0",
"emojibase-regex": "^3.0.0",
Expand Down
4 changes: 2 additions & 2 deletions res/css/views/dialogs/_MessageEditHistoryDialog.scss
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,12 @@ limitations under the License.
padding: 0px 2px;
}

span.mx_EditHistoryMessage_deletion {
.mx_EditHistoryMessage_deletion {
color: rgb(255, 76, 85);
background-color: rgba(255, 76, 85, 0.1);
}

span.mx_EditHistoryMessage_insertion {
.mx_EditHistoryMessage_insertion {
color: rgb(26, 169, 123);
background-color: rgba(26, 169, 123, 0.1);
}
Expand Down
37 changes: 36 additions & 1 deletion src/HtmlUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -468,7 +468,7 @@ export function bodyToHtml(content, highlights, opts={}) {
// their username
(
content.formatted_body == undefined ||
!content.formatted_body.includes("https://matrix.to/")
!content.formatted_body.includes("https://matrix.to/")
);
}

Expand Down Expand Up @@ -513,3 +513,38 @@ export function linkifyElement(element, options = linkifyMatrix.options) {
export function linkifyAndSanitizeHtml(dirtyHtml) {
return sanitizeHtml(linkifyString(dirtyHtml), sanitizeHtmlParams);
}

/**
* Returns if a node is a block element or not.
* Only takes html nodes into account that are allowed in matrix messages.
*
* @param {Node} node
* @returns {bool}
*/
export function checkBlockNode(node) {
switch (node.nodeName) {
case "H1":
case "H2":
case "H3":
case "H4":
case "H5":
case "H6":
case "PRE":
case "BLOCKQUOTE":
case "DIV":
case "P":
case "UL":
case "OL":
case "LI":
case "HR":
case "TABLE":
case "THEAD":
case "TBODY":
case "TR":
case "TH":
case "TD":
return true;
default:
return false;
}
}
27 changes: 3 additions & 24 deletions src/components/views/messages/EditHistoryMessage.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ limitations under the License.
import React from 'react';
import PropTypes from 'prop-types';
import * as HtmlUtils from '../../../HtmlUtils';
import { editBodyDiffToHtml } from '../../../utils/MessageDiffUtils';
import {formatTime} from '../../../DateUtils';
import {MatrixEvent} from 'matrix-js-sdk';
import {pillifyLinks} from '../../../utils/pillify';
Expand All @@ -25,18 +26,12 @@ import sdk from '../../../index';
import MatrixClientPeg from '../../../MatrixClientPeg';
import Modal from '../../../Modal';
import classNames from 'classnames';
import DiffMatchPatch from 'diff-match-patch';

function getReplacedContent(event) {
const originalContent = event.getOriginalContent();
return originalContent["m.new_content"] || originalContent;
}

function isPlainMessage(event) {
const content = getReplacedContent(event);
return content.msgtype === "m.text" && !content.format;
}

export default class EditHistoryMessage extends React.PureComponent {
static propTypes = {
// the message event being edited
Expand Down Expand Up @@ -128,22 +123,6 @@ export default class EditHistoryMessage extends React.PureComponent {
);
}

_renderBodyDiff(oldBody, newBody) {
const dpm = new DiffMatchPatch();
const diff = dpm.diff_main(oldBody, newBody);
dpm.diff_cleanupSemantic(diff);
return diff.map(([modifier, text], i) => {
// not using del and ins tags here as del is used for strikethrough
if (modifier < 0) {
return (<span className="mx_EditHistoryMessage_deletion" key={i}>{text}</span>);
} else if (modifier > 0) {
return (<span className="mx_EditHistoryMessage_insertion" key={i}>{text}</span>);
} else {
return text;
}
});
}

render() {
const {mxEvent} = this.props;
const content = getReplacedContent(mxEvent);
Expand All @@ -153,8 +132,8 @@ export default class EditHistoryMessage extends React.PureComponent {
contentContainer = <UnknownBody mxEvent={this.props.mxEvent} />;
} else {
let contentElements;
if (isPlainMessage(mxEvent) && this.props.previousEdit && isPlainMessage(this.props.previousEdit)) {
contentElements = this._renderBodyDiff(getReplacedContent(this.props.previousEdit).body, content.body);
if (this.props.previousEdit) {
contentElements = editBodyDiffToHtml(getReplacedContent(this.props.previousEdit), content);
} else {
contentElements = HtmlUtils.bodyToHtml(content, null, {stripReplyFallback: true});
}
Expand Down
16 changes: 1 addition & 15 deletions src/editor/deserialize.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ limitations under the License.

import { MATRIXTO_URL_PATTERN } from '../linkify-matrix';
import { walkDOMDepthFirst } from "./dom";
import { checkBlockNode } from "../HtmlUtils";

const REGEX_MATRIXTO = new RegExp(MATRIXTO_URL_PATTERN);

Expand Down Expand Up @@ -118,21 +119,6 @@ function checkDecendInto(node) {
}
}

function checkBlockNode(node) {
switch (node.nodeName) {
case "PRE":
case "BLOCKQUOTE":
case "DIV":
case "P":
case "UL":
case "OL":
case "LI":
return true;
default:
return false;
}
}

function checkIgnored(n) {
if (n.nodeType === Node.TEXT_NODE) {
// riot adds \n text nodes in a lot of places,
Expand Down
Loading