Merge branches 'develop' and 't3chguy/clean_up_TextualBody' of github.com:matrix-org/matrix-react-sdk into t3chguy/clean_up_TextualBody
Conflicts: src/components/views/messages/TextualBody.js
This commit is contained in:
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import React, {createRef} from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import * as HtmlUtils from '../../../HtmlUtils';
|
||||
import { editBodyDiffToHtml } from '../../../utils/MessageDiffUtils';
|
||||
@@ -51,6 +51,8 @@ export default class EditHistoryMessage extends React.PureComponent {
|
||||
}
|
||||
const canRedact = room.currentState.maySendRedactionForEvent(event, userId);
|
||||
this.state = {canRedact, sendStatus: event.getAssociatedStatus()};
|
||||
|
||||
this._content = createRef();
|
||||
}
|
||||
|
||||
_onAssociatedStatusChanged = () => {
|
||||
@@ -78,8 +80,8 @@ export default class EditHistoryMessage extends React.PureComponent {
|
||||
|
||||
pillifyLinks() {
|
||||
// not present for redacted events
|
||||
if (this.refs.content) {
|
||||
pillifyLinks(this.refs.content.children, this.props.mxEvent);
|
||||
if (this._content.current) {
|
||||
pillifyLinks(this._content.current.children, this.props.mxEvent);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -140,13 +142,13 @@ export default class EditHistoryMessage extends React.PureComponent {
|
||||
if (mxEvent.getContent().msgtype === "m.emote") {
|
||||
const name = mxEvent.sender ? mxEvent.sender.name : mxEvent.getSender();
|
||||
contentContainer = (
|
||||
<div className="mx_EventTile_content" ref="content">*
|
||||
<div className="mx_EventTile_content" ref={this._content}>*
|
||||
<span className="mx_MEmoteBody_sender">{ name }</span>
|
||||
{contentElements}
|
||||
</div>
|
||||
);
|
||||
} else {
|
||||
contentContainer = <div className="mx_EventTile_content" ref="content">{contentElements}</div>;
|
||||
contentContainer = <div className="mx_EventTile_content" ref={this._content}>{contentElements}</div>;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -80,7 +80,7 @@ export default class MAudioBody extends React.Component {
|
||||
|
||||
if (this.state.error !== null) {
|
||||
return (
|
||||
<span className="mx_MAudioBody" ref="body">
|
||||
<span className="mx_MAudioBody">
|
||||
<img src={require("../../../../res/img/warning.svg")} width="16" height="16" />
|
||||
{ _t("Error decrypting audio") }
|
||||
</span>
|
||||
|
||||
@@ -15,7 +15,7 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import React, {createRef} from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import createReactClass from 'create-react-class';
|
||||
import filesize from 'filesize';
|
||||
@@ -26,6 +26,7 @@ import {decryptFile} from '../../../utils/DecryptFile';
|
||||
import Tinter from '../../../Tinter';
|
||||
import request from 'browser-request';
|
||||
import Modal from '../../../Modal';
|
||||
import SdkConfig from "../../../SdkConfig";
|
||||
|
||||
|
||||
// A cached tinted copy of require("../../../../res/img/download.svg")
|
||||
@@ -214,10 +215,6 @@ module.exports = createReactClass({
|
||||
tileShape: PropTypes.string,
|
||||
},
|
||||
|
||||
contextTypes: {
|
||||
appConfig: PropTypes.object,
|
||||
},
|
||||
|
||||
/**
|
||||
* Extracts a human readable label for the file attachment to use as
|
||||
* link text.
|
||||
@@ -251,6 +248,12 @@ module.exports = createReactClass({
|
||||
return MatrixClientPeg.get().mxcUrlToHttp(content.url);
|
||||
},
|
||||
|
||||
UNSAFE_componentWillMount: function() {
|
||||
this._iframe = createRef();
|
||||
this._dummyLink = createRef();
|
||||
this._downloadImage = createRef();
|
||||
},
|
||||
|
||||
componentDidMount: function() {
|
||||
// Add this to the list of mounted components to receive notifications
|
||||
// when the tint changes.
|
||||
@@ -272,17 +275,17 @@ module.exports = createReactClass({
|
||||
|
||||
tint: function() {
|
||||
// Update our tinted copy of require("../../../../res/img/download.svg")
|
||||
if (this.refs.downloadImage) {
|
||||
this.refs.downloadImage.src = tintedDownloadImageURL;
|
||||
if (this._downloadImage.current) {
|
||||
this._downloadImage.current.src = tintedDownloadImageURL;
|
||||
}
|
||||
if (this.refs.iframe) {
|
||||
if (this._iframe.current) {
|
||||
// If the attachment is encrypted then the download image
|
||||
// will be inside the iframe so we wont be able to update
|
||||
// it directly.
|
||||
this.refs.iframe.contentWindow.postMessage({
|
||||
this._iframe.current.contentWindow.postMessage({
|
||||
code: remoteSetTint.toString(),
|
||||
imgSrc: tintedDownloadImageURL,
|
||||
style: computedStyle(this.refs.dummyLink),
|
||||
style: computedStyle(this._dummyLink.current),
|
||||
}, "*");
|
||||
}
|
||||
},
|
||||
@@ -325,7 +328,7 @@ module.exports = createReactClass({
|
||||
};
|
||||
|
||||
return (
|
||||
<span className="mx_MFileBody" ref="body">
|
||||
<span className="mx_MFileBody">
|
||||
<div className="mx_MFileBody_download">
|
||||
<a href="javascript:void(0)" onClick={decrypt}>
|
||||
{ _t("Decrypt %(text)s", { text: text }) }
|
||||
@@ -340,7 +343,7 @@ module.exports = createReactClass({
|
||||
ev.target.contentWindow.postMessage({
|
||||
code: remoteRender.toString(),
|
||||
imgSrc: tintedDownloadImageURL,
|
||||
style: computedStyle(this.refs.dummyLink),
|
||||
style: computedStyle(this._dummyLink.current),
|
||||
blob: this.state.decryptedBlob,
|
||||
// Set a download attribute for encrypted files so that the file
|
||||
// will have the correct name when the user tries to download it.
|
||||
@@ -354,8 +357,9 @@ module.exports = createReactClass({
|
||||
|
||||
// If the attachment is encryped then put the link inside an iframe.
|
||||
let renderer_url = DEFAULT_CROSS_ORIGIN_RENDERER;
|
||||
if (this.context.appConfig && this.context.appConfig.cross_origin_renderer_url) {
|
||||
renderer_url = this.context.appConfig.cross_origin_renderer_url;
|
||||
const appConfig = SdkConfig.get();
|
||||
if (appConfig && appConfig.cross_origin_renderer_url) {
|
||||
renderer_url = appConfig.cross_origin_renderer_url;
|
||||
}
|
||||
renderer_url += "?origin=" + encodeURIComponent(window.location.origin);
|
||||
return (
|
||||
@@ -367,9 +371,9 @@ module.exports = createReactClass({
|
||||
* We'll use it to learn how the download link
|
||||
* would have been styled if it was rendered inline.
|
||||
*/ }
|
||||
<a ref="dummyLink" />
|
||||
<a ref={this._dummyLink} />
|
||||
</div>
|
||||
<iframe src={renderer_url} onLoad={onIframeLoad} ref="iframe" />
|
||||
<iframe src={renderer_url} onLoad={onIframeLoad} ref={this._iframe} />
|
||||
</div>
|
||||
</span>
|
||||
);
|
||||
@@ -439,7 +443,7 @@ module.exports = createReactClass({
|
||||
<span className="mx_MFileBody">
|
||||
<div className="mx_MFileBody_download">
|
||||
<a {...downloadProps}>
|
||||
<img src={tintedDownloadImageURL} width="12" height="14" ref="downloadImage" />
|
||||
<img src={tintedDownloadImageURL} width="12" height="14" ref={this._downloadImage} />
|
||||
{ _t("Download %(text)s", { text: text }) }
|
||||
</a>
|
||||
</div>
|
||||
|
||||
@@ -16,9 +16,8 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import React, {createRef} from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { MatrixClient } from 'matrix-js-sdk';
|
||||
|
||||
import MFileBody from './MFileBody';
|
||||
import Modal from '../../../Modal';
|
||||
@@ -26,6 +25,7 @@ import sdk from '../../../index';
|
||||
import { decryptFile } from '../../../utils/DecryptFile';
|
||||
import { _t } from '../../../languageHandler';
|
||||
import SettingsStore from "../../../settings/SettingsStore";
|
||||
import MatrixClientContext from "../../../contexts/MatrixClientContext";
|
||||
|
||||
export default class MImageBody extends React.Component {
|
||||
static propTypes = {
|
||||
@@ -39,9 +39,7 @@ export default class MImageBody extends React.Component {
|
||||
maxImageHeight: PropTypes.number,
|
||||
};
|
||||
|
||||
static contextTypes = {
|
||||
matrixClient: PropTypes.instanceOf(MatrixClient),
|
||||
};
|
||||
static contextType = MatrixClientContext;
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
@@ -65,11 +63,13 @@ export default class MImageBody extends React.Component {
|
||||
hover: false,
|
||||
showImage: SettingsStore.getValue("showImages"),
|
||||
};
|
||||
|
||||
this._image = createRef();
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
this.unmounted = false;
|
||||
this.context.matrixClient.on('sync', this.onClientSync);
|
||||
this.context.on('sync', this.onClientSync);
|
||||
}
|
||||
|
||||
// FIXME: factor this out and aplpy it to MVideoBody and MAudioBody too!
|
||||
@@ -158,8 +158,8 @@ export default class MImageBody extends React.Component {
|
||||
|
||||
let loadedImageDimensions;
|
||||
|
||||
if (this.refs.image) {
|
||||
const { naturalWidth, naturalHeight } = this.refs.image;
|
||||
if (this._image.current) {
|
||||
const { naturalWidth, naturalHeight } = this._image.current;
|
||||
// this is only used as a fallback in case content.info.w/h is missing
|
||||
loadedImageDimensions = { naturalWidth, naturalHeight };
|
||||
}
|
||||
@@ -172,7 +172,7 @@ export default class MImageBody extends React.Component {
|
||||
if (content.file !== undefined) {
|
||||
return this.state.decryptedUrl;
|
||||
} else {
|
||||
return this.context.matrixClient.mxcUrlToHttp(content.url);
|
||||
return this.context.mxcUrlToHttp(content.url);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -196,7 +196,7 @@ export default class MImageBody extends React.Component {
|
||||
// special case to return clientside sender-generated thumbnails for SVGs, if any,
|
||||
// given we deliberately don't thumbnail them serverside to prevent
|
||||
// billion lol attacks and similar
|
||||
return this.context.matrixClient.mxcUrlToHttp(
|
||||
return this.context.mxcUrlToHttp(
|
||||
content.info.thumbnail_url,
|
||||
thumbWidth,
|
||||
thumbHeight,
|
||||
@@ -219,7 +219,7 @@ export default class MImageBody extends React.Component {
|
||||
pixelRatio === 1.0 ||
|
||||
(!info || !info.w || !info.h || !info.size)
|
||||
) {
|
||||
return this.context.matrixClient.mxcUrlToHttp(content.url, thumbWidth, thumbHeight);
|
||||
return this.context.mxcUrlToHttp(content.url, thumbWidth, thumbHeight);
|
||||
} else {
|
||||
// we should only request thumbnails if the image is bigger than 800x600
|
||||
// (or 1600x1200 on retina) otherwise the image in the timeline will just
|
||||
@@ -240,7 +240,7 @@ export default class MImageBody extends React.Component {
|
||||
// image is too large physically and bytewise to clutter our timeline so
|
||||
// we ask for a thumbnail, despite knowing that it will be max 800x600
|
||||
// despite us being retina (as synapse doesn't do 1600x1200 thumbs yet).
|
||||
return this.context.matrixClient.mxcUrlToHttp(
|
||||
return this.context.mxcUrlToHttp(
|
||||
content.url,
|
||||
thumbWidth,
|
||||
thumbHeight,
|
||||
@@ -249,7 +249,7 @@ export default class MImageBody extends React.Component {
|
||||
// download the original image otherwise, so we can scale it client side
|
||||
// to take pixelRatio into account.
|
||||
// ( no width/height means we want the original image)
|
||||
return this.context.matrixClient.mxcUrlToHttp(
|
||||
return this.context.mxcUrlToHttp(
|
||||
content.url,
|
||||
);
|
||||
}
|
||||
@@ -306,7 +306,7 @@ export default class MImageBody extends React.Component {
|
||||
|
||||
componentWillUnmount() {
|
||||
this.unmounted = true;
|
||||
this.context.matrixClient.removeListener('sync', this.onClientSync);
|
||||
this.context.removeListener('sync', this.onClientSync);
|
||||
this._afterComponentWillUnmount();
|
||||
|
||||
if (this.state.decryptedUrl) {
|
||||
@@ -342,7 +342,7 @@ export default class MImageBody extends React.Component {
|
||||
imageElement = <HiddenImagePlaceholder />;
|
||||
} else {
|
||||
imageElement = (
|
||||
<img style={{display: 'none'}} src={thumbUrl} ref="image"
|
||||
<img style={{display: 'none'}} src={thumbUrl} ref={this._image}
|
||||
alt={content.body}
|
||||
onError={this.onImageError}
|
||||
onLoad={this.onImageLoad}
|
||||
@@ -385,7 +385,7 @@ export default class MImageBody extends React.Component {
|
||||
// which has the same width as the timeline
|
||||
// mx_MImageBody_thumbnail resizes img to exactly container size
|
||||
img = (
|
||||
<img className="mx_MImageBody_thumbnail" src={thumbUrl} ref="image"
|
||||
<img className="mx_MImageBody_thumbnail" src={thumbUrl} ref={this._image}
|
||||
style={{ maxWidth: maxWidth + "px" }}
|
||||
alt={content.body}
|
||||
onError={this.onImageError}
|
||||
@@ -459,7 +459,7 @@ export default class MImageBody extends React.Component {
|
||||
|
||||
if (this.state.error !== null) {
|
||||
return (
|
||||
<span className="mx_MImageBody" ref="body">
|
||||
<span className="mx_MImageBody">
|
||||
<img src={require("../../../../res/img/warning.svg")} width="16" height="16" />
|
||||
{ _t("Error decrypting image") }
|
||||
</span>
|
||||
@@ -477,7 +477,7 @@ export default class MImageBody extends React.Component {
|
||||
const thumbnail = this._messageContent(contentUrl, thumbUrl, content);
|
||||
const fileBody = this.getFileBody();
|
||||
|
||||
return <span className="mx_MImageBody" ref="body">
|
||||
return <span className="mx_MImageBody">
|
||||
{ thumbnail }
|
||||
{ fileBody }
|
||||
</span>;
|
||||
|
||||
@@ -52,7 +52,7 @@ export default class MKeyVerificationRequest extends React.Component {
|
||||
const verifier = MatrixClientPeg.get().acceptVerificationDM(this.props.mxEvent, verificationMethods.SAS);
|
||||
Modal.createTrackedDialog('Incoming Verification', '', IncomingSasDialog, {
|
||||
verifier,
|
||||
});
|
||||
}, null, /* priority = */ false, /* static = */ true);
|
||||
};
|
||||
|
||||
_onRejectClicked = () => {
|
||||
|
||||
@@ -132,7 +132,7 @@ module.exports = createReactClass({
|
||||
|
||||
if (this.state.error !== null) {
|
||||
return (
|
||||
<span className="mx_MVideoBody" ref="body">
|
||||
<span className="mx_MVideoBody">
|
||||
<img src={require("../../../../res/img/warning.svg")} width="16" height="16" />
|
||||
{ _t("Error decrypting video") }
|
||||
</span>
|
||||
@@ -144,8 +144,8 @@ module.exports = createReactClass({
|
||||
// The attachment is decrypted in componentDidMount.
|
||||
// For now add an img tag with a spinner.
|
||||
return (
|
||||
<span className="mx_MVideoBody" ref="body">
|
||||
<div className="mx_MImageBody_thumbnail mx_MImageBody_thumbnail_spinner" ref="image">
|
||||
<span className="mx_MVideoBody">
|
||||
<div className="mx_MImageBody_thumbnail mx_MImageBody_thumbnail_spinner">
|
||||
<img src={require("../../../../res/img/spinner.gif")} alt={content.body} width="16" height="16" />
|
||||
</div>
|
||||
</span>
|
||||
|
||||
@@ -25,7 +25,7 @@ import dis from '../../../dispatcher';
|
||||
import Modal from '../../../Modal';
|
||||
import {aboveLeftOf, ContextMenu, ContextMenuButton, useContextMenu} from '../../structures/ContextMenu';
|
||||
import { isContentActionable, canEditContent } from '../../../utils/EventUtils';
|
||||
import {RoomContext} from "../../structures/RoomView";
|
||||
import RoomContext from "../../../contexts/RoomContext";
|
||||
|
||||
const OptionsButton = ({mxEvent, getTile, getReplyThread, permalinkCreator, onFocusChange}) => {
|
||||
const [menuDisplayed, button, openMenu, closeMenu] = useContextMenu();
|
||||
@@ -78,14 +78,17 @@ const OptionsButton = ({mxEvent, getTile, getReplyThread, permalinkCreator, onFo
|
||||
</React.Fragment>;
|
||||
};
|
||||
|
||||
const ReactButton = ({mxEvent, reactions}) => {
|
||||
const ReactButton = ({mxEvent, reactions, onFocusChange}) => {
|
||||
const [menuDisplayed, button, openMenu, closeMenu] = useContextMenu();
|
||||
useEffect(() => {
|
||||
onFocusChange(menuDisplayed);
|
||||
}, [onFocusChange, menuDisplayed]);
|
||||
|
||||
let contextMenu;
|
||||
if (menuDisplayed) {
|
||||
const buttonRect = button.current.getBoundingClientRect();
|
||||
const ReactionPicker = sdk.getComponent('emojipicker.ReactionPicker');
|
||||
contextMenu = <ContextMenu {...aboveLeftOf(buttonRect)} onFinished={closeMenu}>
|
||||
contextMenu = <ContextMenu {...aboveLeftOf(buttonRect)} onFinished={closeMenu} managed={false}>
|
||||
<ReactionPicker mxEvent={mxEvent} reactions={reactions} onFinished={closeMenu} />
|
||||
</ContextMenu>;
|
||||
}
|
||||
@@ -114,9 +117,7 @@ export default class MessageActionBar extends React.PureComponent {
|
||||
onFocusChange: PropTypes.func,
|
||||
};
|
||||
|
||||
static contextTypes = {
|
||||
room: RoomContext,
|
||||
};
|
||||
static contextType = RoomContext;
|
||||
|
||||
componentDidMount() {
|
||||
this.props.mxEvent.on("Event.decrypted", this.onDecrypted);
|
||||
@@ -161,10 +162,12 @@ export default class MessageActionBar extends React.PureComponent {
|
||||
let editButton;
|
||||
|
||||
if (isContentActionable(this.props.mxEvent)) {
|
||||
if (this.context.room.canReact) {
|
||||
reactButton = <ReactButton mxEvent={this.props.mxEvent} reactions={this.props.reactions} />;
|
||||
if (this.context.canReact) {
|
||||
reactButton = (
|
||||
<ReactButton mxEvent={this.props.mxEvent} reactions={this.props.reactions} onFocusChange={this.onFocusChange} />
|
||||
);
|
||||
}
|
||||
if (this.context.room.canReply) {
|
||||
if (this.context.canReply) {
|
||||
replyButton = <AccessibleButton
|
||||
className="mx_MessageActionBar_maskButton mx_MessageActionBar_replyButton"
|
||||
title={_t("Reply")}
|
||||
|
||||
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import React, {createRef} from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import createReactClass from 'create-react-class';
|
||||
import sdk from '../../../index';
|
||||
@@ -47,8 +47,12 @@ module.exports = createReactClass({
|
||||
maxImageHeight: PropTypes.number,
|
||||
},
|
||||
|
||||
UNSAFE_componentWillMount: function() {
|
||||
this._body = createRef();
|
||||
},
|
||||
|
||||
getEventTileOps: function() {
|
||||
return this.refs.body && this.refs.body.getEventTileOps ? this.refs.body.getEventTileOps() : null;
|
||||
return this._body.current && this._body.current.getEventTileOps ? this._body.current.getEventTileOps() : null;
|
||||
},
|
||||
|
||||
onTileUpdate: function() {
|
||||
@@ -103,7 +107,8 @@ module.exports = createReactClass({
|
||||
}
|
||||
|
||||
return <BodyType
|
||||
ref="body" mxEvent={this.props.mxEvent}
|
||||
ref={this._body}
|
||||
mxEvent={this.props.mxEvent}
|
||||
highlights={this.props.highlights}
|
||||
highlightLink={this.props.highlightLink}
|
||||
showUrlPreview={this.props.showUrlPreview}
|
||||
|
||||
@@ -126,10 +126,9 @@ export default class ReactionsRowButton extends React.PureComponent {
|
||||
);
|
||||
}
|
||||
|
||||
return <span className={classes}
|
||||
role="button"
|
||||
const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
|
||||
return <AccessibleButton className={classes}
|
||||
aria-label={label}
|
||||
tabindex="0"
|
||||
onClick={this.onClick}
|
||||
onMouseOver={this.onMouseOver}
|
||||
onMouseOut={this.onMouseOut}
|
||||
@@ -141,6 +140,6 @@ export default class ReactionsRowButton extends React.PureComponent {
|
||||
{count}
|
||||
</span>
|
||||
{tooltip}
|
||||
</span>;
|
||||
</AccessibleButton>;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,11 +17,11 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import createReactClass from 'create-react-class';
|
||||
import {MatrixClient} from 'matrix-js-sdk';
|
||||
import Flair from '../elements/Flair.js';
|
||||
import FlairStore from '../../../stores/FlairStore';
|
||||
import { _t } from '../../../languageHandler';
|
||||
import {getUserNameColorClass} from '../../../utils/FormattingUtils';
|
||||
import MatrixClientContext from "../../../contexts/MatrixClientContext";
|
||||
|
||||
export default createReactClass({
|
||||
displayName: 'SenderProfile',
|
||||
@@ -31,8 +31,8 @@ export default createReactClass({
|
||||
onClick: PropTypes.func,
|
||||
},
|
||||
|
||||
contextTypes: {
|
||||
matrixClient: PropTypes.instanceOf(MatrixClient),
|
||||
statics: {
|
||||
contextType: MatrixClientContext,
|
||||
},
|
||||
|
||||
getInitialState() {
|
||||
@@ -47,18 +47,18 @@ export default createReactClass({
|
||||
this._updateRelatedGroups();
|
||||
|
||||
FlairStore.getPublicisedGroupsCached(
|
||||
this.context.matrixClient, this.props.mxEvent.getSender(),
|
||||
this.context, this.props.mxEvent.getSender(),
|
||||
).then((userGroups) => {
|
||||
if (this.unmounted) return;
|
||||
this.setState({userGroups});
|
||||
});
|
||||
|
||||
this.context.matrixClient.on('RoomState.events', this.onRoomStateEvents);
|
||||
this.context.on('RoomState.events', this.onRoomStateEvents);
|
||||
},
|
||||
|
||||
componentWillUnmount() {
|
||||
this.unmounted = true;
|
||||
this.context.matrixClient.removeListener('RoomState.events', this.onRoomStateEvents);
|
||||
this.context.removeListener('RoomState.events', this.onRoomStateEvents);
|
||||
},
|
||||
|
||||
onRoomStateEvents(event) {
|
||||
@@ -71,7 +71,7 @@ export default createReactClass({
|
||||
|
||||
_updateRelatedGroups() {
|
||||
if (this.unmounted) return;
|
||||
const room = this.context.matrixClient.getRoom(this.props.mxEvent.getRoomId());
|
||||
const room = this.context.getRoom(this.props.mxEvent.getRoomId());
|
||||
if (!room) return;
|
||||
|
||||
const relatedGroupsEvent = room.currentState.getStateEvents('m.room.related_groups', '');
|
||||
|
||||
@@ -86,7 +86,7 @@ module.exports = createReactClass({
|
||||
return successful;
|
||||
},
|
||||
|
||||
componentWillMount: function() {
|
||||
UNSAFE_componentWillMount: function() {
|
||||
this._content = createRef();
|
||||
},
|
||||
|
||||
@@ -281,7 +281,7 @@ module.exports = createReactClass({
|
||||
const buttonRect = e.target.getBoundingClientRect();
|
||||
const GenericTextContextMenu = sdk.getComponent('context_menus.GenericTextContextMenu');
|
||||
const {close} = ContextMenu.createMenu(GenericTextContextMenu, {
|
||||
...toRightOf(buttonRect, 11),
|
||||
...toRightOf(buttonRect, 2),
|
||||
message: successful ? _t('Copied!') : _t('Failed to copy'),
|
||||
});
|
||||
e.target.onmouseleave = close;
|
||||
@@ -402,13 +402,18 @@ module.exports = createReactClass({
|
||||
label={_t("Edited at %(date)s. Click to view edits.", {date: dateString})}
|
||||
/>;
|
||||
}
|
||||
|
||||
const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
|
||||
return (
|
||||
<div
|
||||
key="editedMarker" className="mx_EventTile_edited"
|
||||
<AccessibleButton
|
||||
key="editedMarker"
|
||||
className="mx_EventTile_edited"
|
||||
onClick={this._openHistoryDialog}
|
||||
onMouseEnter={this._onMouseEnterEditedMarker}
|
||||
onMouseLeave={this._onMouseLeaveEditedMarker}
|
||||
>{editedTooltip}<span>{`(${_t("edited")})`}</span></div>
|
||||
>
|
||||
{ editedTooltip }<span>{`(${_t("edited")})`}</span>
|
||||
</AccessibleButton>
|
||||
);
|
||||
},
|
||||
|
||||
|
||||
Reference in New Issue
Block a user