Merge remote-tracking branch 'upstream/develop' into SuppressSpeechWhenSending

This commit is contained in:
Marco Zehe 2020-07-15 17:27:35 +02:00
commit d8373576f8
1188 changed files with 53232 additions and 22354 deletions

View file

@ -25,7 +25,7 @@ import classNames from "classnames";
import { _t, _td } from '../../../languageHandler';
import * as TextForEvent from "../../../TextForEvent";
import * as sdk from "../../../index";
import dis from '../../../dispatcher';
import dis from '../../../dispatcher/dispatcher';
import SettingsStore from "../../../settings/SettingsStore";
import {EventStatus} from 'matrix-js-sdk';
import {formatTime} from "../../../DateUtils";
@ -34,6 +34,7 @@ import {ALL_RULE_TYPES} from "../../../mjolnir/BanList";
import * as ObjectUtils from "../../../ObjectUtils";
import MatrixClientContext from "../../../contexts/MatrixClientContext";
import {E2E_STATE} from "./E2EIcon";
import {toRem} from "../../../utils/units";
const eventTileTypes = {
'm.room.message': 'messages.MessageEvent',
@ -48,8 +49,6 @@ const eventTileTypes = {
const stateEventTileTypes = {
'm.room.encryption': 'messages.EncryptionEvent',
'm.room.aliases': 'messages.TextualEvent',
// 'm.room.aliases': 'messages.RoomAliasesEvent', // too complex
'm.room.canonical_alias': 'messages.TextualEvent',
'm.room.create': 'messages.RoomCreate',
'm.room.member': 'messages.TextualEvent',
@ -61,6 +60,7 @@ const stateEventTileTypes = {
'm.room.power_levels': 'messages.TextualEvent',
'm.room.pinned_events': 'messages.TextualEvent',
'm.room.server_acl': 'messages.TextualEvent',
// TODO: Enable support for m.widget event type (https://github.com/vector-im/riot-web/issues/13111)
'im.vector.modular.widgets': 'messages.TextualEvent',
'm.room.tombstone': 'messages.TextualEvent',
'm.room.join_rules': 'messages.TextualEvent',
@ -104,7 +104,7 @@ export function getHandlerTile(ev) {
// fall back to showing hidden events, if we're viewing hidden events
// XXX: This is extremely a hack. Possibly these components should have an interface for
// declining to render?
if (type === "m.key.verification.cancel" && SettingsStore.getValue("showHiddenEventsInTimeline")) {
if (type === "m.key.verification.cancel" || type === "m.key.verification.done") {
const MKeyVerificationConclusion = sdk.getComponent("messages.MKeyVerificationConclusion");
if (!MKeyVerificationConclusion.prototype._shouldRender.call(null, ev, ev.request)) {
return;
@ -206,6 +206,9 @@ export default createReactClass({
// whether to show reactions for this event
showReactions: PropTypes.bool,
// whether to use the irc layout
useIRCLayout: PropTypes.bool,
},
getDefaultProps: function() {
@ -235,7 +238,8 @@ export default createReactClass({
contextType: MatrixClientContext,
},
componentWillMount: function() {
// TODO: [REACT-WARNING] Replace component with real class, use constructor for refs
UNSAFE_componentWillMount: function() {
// don't do RR animations until we are mounted
this._suppressReadReceiptAnimation = true;
this._verifyEvent(this.props.mxEvent);
@ -255,7 +259,8 @@ export default createReactClass({
}
},
componentWillReceiveProps: function(nextProps) {
// TODO: [REACT-WARNING] Replace with appropriate lifecycle event
UNSAFE_componentWillReceiveProps: function(nextProps) {
// re-check the sender verification as outgoing events progress through
// the send process.
if (nextProps.eventSendStatus !== this.props.eventSendStatus) {
@ -308,44 +313,52 @@ export default createReactClass({
return;
}
// If we directly trust the device, short-circuit here
const verified = await this.context.isEventSenderVerified(mxEvent);
if (verified) {
this.setState({
verified: E2E_STATE.VERIFIED,
}, () => {
// Decryption may have caused a change in size
this.props.onHeightChanged();
});
return;
}
const encryptionInfo = this.context.getEventEncryptionInfo(mxEvent);
const senderId = mxEvent.getSender();
const userTrust = this.context.checkUserTrust(senderId);
// If cross-signing is off, the old behaviour is to scream at the user
// as if they've done something wrong, which they haven't
if (!SettingsStore.isFeatureEnabled("feature_cross_signing")) {
if (encryptionInfo.mismatchedSender) {
// something definitely wrong is going on here
this.setState({
verified: E2E_STATE.WARNING,
}, this.props.onHeightChanged);
}, this.props.onHeightChanged); // Decryption may have caused a change in size
return;
}
if (!this.context.checkUserTrust(mxEvent.getSender()).isCrossSigningVerified()) {
if (!userTrust.isCrossSigningVerified()) {
// user is not verified, so default to everything is normal
this.setState({
verified: E2E_STATE.NORMAL,
}, this.props.onHeightChanged);
}, this.props.onHeightChanged); // Decryption may have caused a change in size
return;
}
const eventSenderTrust = await this.context.checkEventSenderTrust(mxEvent);
const eventSenderTrust = this.context.checkDeviceTrust(
senderId, encryptionInfo.sender.deviceId,
);
if (!eventSenderTrust) {
this.setState({
verified: E2E_STATE.UNKNOWN,
}, this.props.onHeightChanged); // Decryption may have cause a change in size
}, this.props.onHeightChanged); // Decryption may have caused a change in size
return;
}
if (!eventSenderTrust.isVerified()) {
this.setState({
verified: E2E_STATE.WARNING,
}, this.props.onHeightChanged); // Decryption may have caused a change in size
return;
}
if (!encryptionInfo.authenticated) {
this.setState({
verified: E2E_STATE.UNAUTHENTICATED,
}, this.props.onHeightChanged); // Decryption may have caused a change in size
return;
}
this.setState({
verified: eventSenderTrust.isVerified() ? E2E_STATE.VERIFIED : E2E_STATE.WARNING,
verified: E2E_STATE.VERIFIED,
}, this.props.onHeightChanged); // Decryption may have caused a change in size
},
@ -398,7 +411,7 @@ export default createReactClass({
},
shouldHighlight: function() {
const actions = this.context.getPushActionsForEvent(this.props.mxEvent);
const actions = this.context.getPushActionsForEvent(this.props.mxEvent.replacingEvent() || this.props.mxEvent);
if (!actions || !actions.tweaks) { return false; }
// don't show self-highlights from another of our clients
@ -472,7 +485,7 @@ export default createReactClass({
if (remainder > 0) {
remText = <span className="mx_EventTile_readAvatarRemainder"
onClick={this.toggleAllReadAvatars}
style={{ right: -(left - receiptOffset) }}>{ remainder }+
style={{ right: "calc(" + toRem(-left) + " + " + receiptOffset + "px)" }}>{ remainder }+
</span>;
}
}
@ -530,6 +543,8 @@ export default createReactClass({
return; // no icon if we've not even cross-signed the user
} else if (this.state.verified === E2E_STATE.VERIFIED) {
return; // no icon for verified
} else if (this.state.verified === E2E_STATE.UNAUTHENTICATED) {
return (<E2ePadlockUnauthenticated />);
} else if (this.state.verified === E2E_STATE.UNKNOWN) {
return (<E2ePadlockUnknown />);
} else {
@ -668,11 +683,11 @@ export default createReactClass({
mx_EventTile_unknown: !isBubbleMessage && this.state.verified === E2E_STATE.UNKNOWN,
mx_EventTile_bad: isEncryptionFailure,
mx_EventTile_emote: msgtype === 'm.emote',
mx_EventTile_redacted: isRedacted,
});
// If the tile is in the Sending state, don't speak the message.
const suppressSpeech = (isSending) ? "off" : undefined;
const ariaLive = (isSending) ? "off" : undefined;
const ariaBusy = (isSending) ? "true" : undefined;
let permalink = "#";
if (this.props.permalinkCreator) {
@ -697,6 +712,9 @@ export default createReactClass({
// joins/parts/etc
avatarSize = 14;
needsSenderProfile = false;
} else if (this.props.useIRCLayout) {
avatarSize = 14;
needsSenderProfile = true;
} else if (this.props.continuation && this.props.tileShape !== "file_grid") {
// no avatar or sender profile for continuation messages
avatarSize = 0;
@ -788,11 +806,24 @@ export default createReactClass({
/>;
}
const linkedTimestamp = <a
href={permalink}
onClick={this.onPermalinkClicked}
aria-label={formatTime(new Date(this.props.mxEvent.getTs()), this.props.isTwelveHour)}
>
{ timestamp }
</a>;
const groupTimestamp = !this.props.useIRCLayout ? linkedTimestamp : null;
const ircTimestamp = this.props.useIRCLayout ? linkedTimestamp : null;
const groupPadlock = !this.props.useIRCLayout && !isBubbleMessage && this._renderE2EPadlock();
const ircPadlock = this.props.useIRCLayout && !isBubbleMessage && this._renderE2EPadlock();
switch (this.props.tileShape) {
case 'notif': {
const room = this.context.getRoom(this.props.mxEvent.getRoomId());
return (
<div className={classes} aria-live={suppressSpeech}>
<div className={classes} aria-live={ariaLive} aria-busy={ariaBusy}>
<div className="mx_EventTile_roomName">
<a href={permalink} onClick={this.onPermalinkClicked}>
{ room ? room.name : '' }
@ -818,7 +849,7 @@ export default createReactClass({
}
case 'file_grid': {
return (
<div className={classes} aria-live={suppressSpeech}>
<div className={classes} aria-live={ariaLive} aria-busy={ariaBusy}>
<div className="mx_EventTile_line">
<EventTileType ref={this._tile}
mxEvent={this.props.mxEvent}
@ -854,14 +885,14 @@ export default createReactClass({
);
}
return (
<div className={classes} aria-live={suppressSpeech}>
<div className={classes} aria-live={ariaLive} aria-busy={ariaBusy}>
{ ircTimestamp }
{ avatar }
{ sender }
{ ircPadlock }
<div className="mx_EventTile_reply">
<a href={permalink} onClick={this.onPermalinkClicked}>
{ timestamp }
</a>
{ !isBubbleMessage && this._renderE2EPadlock() }
{ groupTimestamp }
{ groupPadlock }
{ thread }
<EventTileType ref={this._tile}
mxEvent={this.props.mxEvent}
@ -879,23 +910,21 @@ export default createReactClass({
this.props.onHeightChanged,
this.props.permalinkCreator,
this._replyThread,
this.props.useIRCLayout,
);
// tab-index=-1 to allow it to be focusable but do not add tab stop for it, primarily for screen readers
return (
<div className={classes} tabIndex={-1} aria-live={suppressSpeech}>
<div className={classes} tabIndex={-1} aria-live={ariaLive} aria-busy={ariaBusy}>
{ ircTimestamp }
<div className="mx_EventTile_msgOption">
{ readAvatars }
</div>
{ sender }
{ ircPadlock }
<div className="mx_EventTile_line">
<a
href={permalink}
onClick={this.onPermalinkClicked}
aria-label={formatTime(new Date(this.props.mxEvent.getTs()), this.props.isTwelveHour)}
>
{ timestamp }
</a>
{ !isBubbleMessage && this._renderE2EPadlock() }
{ groupTimestamp }
{ groupPadlock }
{ thread }
<EventTileType ref={this._tile}
mxEvent={this.props.mxEvent}
@ -970,6 +999,12 @@ function E2ePadlockUnknown(props) {
);
}
function E2ePadlockUnauthenticated(props) {
return (
<E2ePadlock title={_t("The authenticity of this encrypted message can't be guaranteed on this device.")} icon="unauthenticated" {...props} />
);
}
class E2ePadlock extends React.Component {
static propTypes = {
icon: PropTypes.string.isRequired,