Merge branch 'develop' of https://github.com/matrix-org/matrix-react-sdk into soru/spoilers

This commit is contained in:
Sorunome 2019-08-28 20:23:24 +02:00
commit fe9ae46ffb
No known key found for this signature in database
GPG key ID: 63E31F7B5993A9C4
389 changed files with 23061 additions and 5544 deletions

View file

@ -25,17 +25,16 @@ import highlight from 'highlight.js';
import * as HtmlUtils from '../../../HtmlUtils';
import {formatDate} from '../../../DateUtils';
import sdk from '../../../index';
import ScalarAuthClient from '../../../ScalarAuthClient';
import Modal from '../../../Modal';
import SdkConfig from '../../../SdkConfig';
import dis from '../../../dispatcher';
import { _t } from '../../../languageHandler';
import MatrixClientPeg from '../../../MatrixClientPeg';
import * as ContextualMenu from '../../structures/ContextualMenu';
import SettingsStore from "../../../settings/SettingsStore";
import PushProcessor from 'matrix-js-sdk/lib/pushprocessor';
import ReplyThread from "../elements/ReplyThread";
import {host as matrixtoHost} from '../../../matrix-to';
import {pillifyLinks} from '../../../utils/pillify';
import {IntegrationManagers} from "../../../integrations/IntegrationManagers";
module.exports = React.createClass({
displayName: 'TextualBody',
@ -90,7 +89,7 @@ module.exports = React.createClass({
componentDidMount: function() {
this._unmounted = false;
if (!this.props.isEditing) {
if (!this.props.editState) {
this._applyFormatting();
}
},
@ -101,7 +100,7 @@ module.exports = React.createClass({
// 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.
this.pillifyLinks(this.refs.content.children);
pillifyLinks(this.refs.content.children, this.props.mxEvent);
HtmlUtils.linkifyElement(this.refs.content);
this.calculateUrlPreview();
@ -133,8 +132,8 @@ module.exports = React.createClass({
},
componentDidUpdate: function(prevProps) {
if (!this.props.isEditing) {
const stoppedEditing = prevProps.isEditing && !this.props.isEditing;
if (!this.props.editState) {
const stoppedEditing = prevProps.editState && !this.props.editState;
const messageWasEdited = prevProps.replacingEventId !== this.props.replacingEventId;
if (messageWasEdited || stoppedEditing) {
this._applyFormatting();
@ -155,7 +154,7 @@ module.exports = React.createClass({
nextProps.replacingEventId !== this.props.replacingEventId ||
nextProps.highlightLink !== this.props.highlightLink ||
nextProps.showUrlPreview !== this.props.showUrlPreview ||
nextProps.isEditing !== this.props.isEditing ||
nextProps.editState !== this.props.editState ||
nextState.links !== this.state.links ||
nextState.editedMarkerHovered !== this.state.editedMarkerHovered ||
nextState.widgetHidden !== this.state.widgetHidden);
@ -214,98 +213,6 @@ module.exports = React.createClass({
}
},
pillifyLinks: function(nodes) {
const shouldShowPillAvatar = SettingsStore.getValue("Pill.shouldShowPillAvatar");
let node = nodes[0];
while (node) {
let pillified = false;
if (node.tagName === "A" && node.getAttribute("href")) {
const href = node.getAttribute("href");
// If the link is a (localised) matrix.to link, replace it with a pill
const Pill = sdk.getComponent('elements.Pill');
if (Pill.isMessagePillUrl(href)) {
const pillContainer = document.createElement('span');
const room = MatrixClientPeg.get().getRoom(this.props.mxEvent.getRoomId());
const pill = <Pill
url={href}
inMessage={true}
room={room}
shouldShowPillAvatar={shouldShowPillAvatar}
/>;
ReactDOM.render(pill, pillContainer);
node.parentNode.replaceChild(pillContainer, node);
// Pills within pills aren't going to go well, so move on
pillified = true;
// update the current node with one that's now taken its place
node = pillContainer;
}
} else if (node.nodeType === Node.TEXT_NODE) {
const Pill = sdk.getComponent('elements.Pill');
let currentTextNode = node;
const roomNotifTextNodes = [];
// Take a textNode and break it up to make all the instances of @room their
// own textNode, adding those nodes to roomNotifTextNodes
while (currentTextNode !== null) {
const roomNotifPos = Pill.roomNotifPos(currentTextNode.textContent);
let nextTextNode = null;
if (roomNotifPos > -1) {
let roomTextNode = currentTextNode;
if (roomNotifPos > 0) roomTextNode = roomTextNode.splitText(roomNotifPos);
if (roomTextNode.textContent.length > Pill.roomNotifLen()) {
nextTextNode = roomTextNode.splitText(Pill.roomNotifLen());
}
roomNotifTextNodes.push(roomTextNode);
}
currentTextNode = nextTextNode;
}
if (roomNotifTextNodes.length > 0) {
const pushProcessor = new PushProcessor(MatrixClientPeg.get());
const atRoomRule = pushProcessor.getPushRuleById(".m.rule.roomnotif");
if (atRoomRule && pushProcessor.ruleMatchesEvent(atRoomRule, this.props.mxEvent)) {
// Now replace all those nodes with Pills
for (const roomNotifTextNode of roomNotifTextNodes) {
// Set the next node to be processed to the one after the node
// we're adding now, since we've just inserted nodes into the structure
// we're iterating over.
// Note we've checked roomNotifTextNodes.length > 0 so we'll do this at least once
node = roomNotifTextNode.nextSibling;
const pillContainer = document.createElement('span');
const room = MatrixClientPeg.get().getRoom(this.props.mxEvent.getRoomId());
const pill = <Pill
type={Pill.TYPE_AT_ROOM_MENTION}
inMessage={true}
room={room}
shouldShowPillAvatar={true}
/>;
ReactDOM.render(pill, pillContainer);
roomNotifTextNode.parentNode.replaceChild(pillContainer, roomNotifTextNode);
}
// Nothing else to do for a text node (and we don't need to advance
// the loop pointer because we did it above)
continue;
}
}
}
if (node.childNodes && node.childNodes.length && !pillified) {
this.pillifyLinks(node.childNodes);
}
node = node.nextSibling;
}
},
findLinks: function(nodes) {
let links = [];
@ -441,12 +348,19 @@ module.exports = React.createClass({
// which requires the user to click through and THEN we can open the link in a new tab because
// the window.open command occurs in the same stack frame as the onClick callback.
const managers = IntegrationManagers.sharedInstance();
if (!managers.hasManager()) {
managers.openNoManagerDialog();
return;
}
// Go fetch a scalar token
const scalarClient = new ScalarAuthClient();
const integrationManager = managers.getPrimaryManager();
const scalarClient = integrationManager.getScalarClient();
scalarClient.connect().then(() => {
const completeUrl = scalarClient.getStarterLink(starterLink);
const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
const integrationsUrl = SdkConfig.get().integrations_ui_url;
const integrationsUrl = integrationManager.uiUrl;
Modal.createTrackedDialog('Add an integration', '', QuestionDialog, {
title: _t("Add an Integration"),
description:
@ -478,20 +392,26 @@ module.exports = React.createClass({
this.setState({editedMarkerHovered: false});
},
_openHistoryDialog: async function() {
const MessageEditHistoryDialog = sdk.getComponent("views.dialogs.MessageEditHistoryDialog");
Modal.createDialog(MessageEditHistoryDialog, {mxEvent: this.props.mxEvent});
},
_renderEditedMarker: function() {
let editedTooltip;
if (this.state.editedMarkerHovered) {
const Tooltip = sdk.getComponent('elements.Tooltip');
const editEvent = this.props.mxEvent.replacingEvent();
const date = editEvent && formatDate(editEvent.getDate());
const date = this.props.mxEvent.replacingEventDate();
const dateString = date && formatDate(date);
editedTooltip = <Tooltip
tooltipClassName="mx_Tooltip_timeline"
label={_t("Edited at %(date)s", {date})}
label={_t("Edited at %(date)s. Click to view edits.", {date: dateString})}
/>;
}
return (
<div
key="editedMarker" className="mx_EventTile_edited"
onClick={this._openHistoryDialog}
onMouseEnter={this._onMouseEnterEditedMarker}
onMouseLeave={this._onMouseLeaveEditedMarker}
>{editedTooltip}<span>{`(${_t("edited")})`}</span></div>
@ -499,9 +419,9 @@ module.exports = React.createClass({
},
render: function() {
if (this.props.isEditing) {
const MessageEditor = sdk.getComponent('elements.MessageEditor');
return <MessageEditor event={this.props.mxEvent} className="mx_EventTile_content" />;
if (this.props.editState) {
const EditMessageComposer = sdk.getComponent('rooms.EditMessageComposer');
return <EditMessageComposer editState={this.props.editState} className="mx_EventTile_content" />;
}
const mxEvent = this.props.mxEvent;
const content = mxEvent.getContent();