Merge pull request #2620 from matrix-org/bwindels/e2eiconsanddialog

Fixes and styling related to e2e icons and dialogs
This commit is contained in:
Bruno Windels 2019-02-13 09:18:58 +01:00 committed by GitHub
commit 875f792728
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 67 additions and 53 deletions

View file

@ -28,28 +28,28 @@ limitations under the License.
flex-direction: column; flex-direction: column;
} }
.mx_UnknownDeviceDialog ul {
list-style: none;
padding: 0;
}
// userid
.mx_UnknownDeviceDialog p {
font-weight: bold;
font-size: 16px;
}
.mx_UnknownDeviceDialog .mx_DeviceVerifyButtons { .mx_UnknownDeviceDialog .mx_DeviceVerifyButtons {
float: right; flex-direction: row !important;
} }
.mx_UnknownDeviceDialog .mx_Dialog_content { .mx_UnknownDeviceDialog .mx_Dialog_content {
margin-bottom: 24px; margin-bottom: 24px;
} }
.mx_UnknownDeviceDialog .mx_MemberDeviceInfo { .mx_UnknownDeviceDialog_deviceList > li {
float: right; padding: 4px;
clear: both;
padding: 0px;
padding-top: 8px;
} }
.mx_UnknownDeviceDialog .mx_MemberDeviceInfo_textButton { .mx_UnknownDeviceDialog_deviceList > li > * {
@mixin mx_DialogButton_small; padding-bottom: 0;
background-color: $primary-bg-color;
color: $accent-color;
}
.mx_UnknownDeviceDialog .mx_UnknownDeviceDialog_deviceList li {
height: 40px;
border-bottom: 1px solid $primary-hairline-color;
} }

View file

@ -533,7 +533,7 @@ limitations under the License.
} }
.mx_EventTile_e2eIcon { .mx_EventTile_e2eIcon {
top: 7px; top: 3px;
} }
.mx_EventTile_editButton { .mx_EventTile_editButton {

View file

@ -793,6 +793,7 @@ module.exports = React.createClass({
this._updateConfCallNotification(); this._updateConfCallNotification();
this._updateDMState(); this._updateDMState();
this._checkIfAlone(this.state.room); this._checkIfAlone(this.state.room);
this._updateE2EStatus(this.state.room);
}, 500), }, 500),
_checkIfAlone: function(room) { _checkIfAlone: function(room) {

View file

@ -90,6 +90,11 @@ module.exports = React.createClass({
this.closeMenu(); this.closeMenu();
}, },
e2eInfoClicked: function() {
this.props.e2eInfoCallback();
this.closeMenu();
},
onViewSourceClick: function() { onViewSourceClick: function() {
const ViewSource = sdk.getComponent('structures.ViewSource'); const ViewSource = sdk.getComponent('structures.ViewSource');
Modal.createTrackedDialog('View Event Source', '', ViewSource, { Modal.createTrackedDialog('View Event Source', '', ViewSource, {
@ -332,6 +337,13 @@ module.exports = React.createClass({
); );
} }
let e2eInfo;
if (this.props.e2eInfoCallback) {
e2eInfo = <div className="mx_MessageContextMenu_field" onClick={this.e2eInfoClicked}>
{ _t('End-to-end encryption information') }
</div>;
}
return ( return (
<div className="mx_MessageContextMenu"> <div className="mx_MessageContextMenu">
{ resendButton } { resendButton }
@ -347,6 +359,7 @@ module.exports = React.createClass({
{ replyButton } { replyButton }
{ externalURLButton } { externalURLButton }
{ collapseReplyThread } { collapseReplyThread }
{ e2eInfo }
</div> </div>
); );
}, },

View file

@ -25,35 +25,12 @@ import { _t } from '../../../languageHandler';
import SettingsStore from "../../../settings/SettingsStore"; import SettingsStore from "../../../settings/SettingsStore";
import { markAllDevicesKnown } from '../../../cryptodevices'; import { markAllDevicesKnown } from '../../../cryptodevices';
function DeviceListEntry(props) {
const {userId, device} = props;
const DeviceVerifyButtons = sdk.getComponent('elements.DeviceVerifyButtons');
return (
<li>
{ device.deviceId }
<DeviceVerifyButtons device={device} userId={userId} />
<br />
{ device.getDisplayName() }
</li>
);
}
DeviceListEntry.propTypes = {
userId: PropTypes.string.isRequired,
// deviceinfo
device: PropTypes.object.isRequired,
};
function UserUnknownDeviceList(props) { function UserUnknownDeviceList(props) {
const MemberDeviceInfo = sdk.getComponent('rooms.MemberDeviceInfo');
const {userId, userDevices} = props; const {userId, userDevices} = props;
const deviceListEntries = Object.keys(userDevices).map((deviceId) => const deviceListEntries = Object.keys(userDevices).map((deviceId) =>
<DeviceListEntry key={deviceId} userId={userId} <li key={deviceId}><MemberDeviceInfo device={userDevices[deviceId]} userId={userId} showDeviceId={true} /></li>,
device={userDevices[deviceId]} />,
); );
return ( return (

View file

@ -16,6 +16,7 @@ limitations under the License.
import classNames from 'classnames'; import classNames from 'classnames';
import { _t } from '../../../languageHandler'; import { _t } from '../../../languageHandler';
import AccessibleButton from '../elements/AccessibleButton';
export default function(props) { export default function(props) {
const isWarning = props.status === "warning"; const isWarning = props.status === "warning";
@ -35,5 +36,10 @@ export default function(props) {
_t("All devices for this user are trusted") : _t("All devices for this user are trusted") :
_t("All devices in this encrypted room are trusted"); _t("All devices in this encrypted room are trusted");
} }
return (<div className={e2eIconClasses} title={e2eTitle} />); const icon = (<div className={e2eIconClasses} title={e2eTitle} />);
if (props.onClick) {
return (<AccessibleButton onClick={props.onClick}>{ icon }</AccessibleButton>);
} else {
return icon;
}
} }

View file

@ -327,6 +327,7 @@ module.exports = withMatrixClient(React.createClass({
top: y, top: y,
eventTileOps: tile && tile.getEventTileOps ? tile.getEventTileOps() : undefined, eventTileOps: tile && tile.getEventTileOps ? tile.getEventTileOps() : undefined,
collapseReplyThread: replyThread && replyThread.canCollapse() ? replyThread.collapse : undefined, collapseReplyThread: replyThread && replyThread.canCollapse() ? replyThread.collapse : undefined,
e2eInfoCallback: () => this.onCryptoClicked(),
onFinished: function() { onFinished: function() {
self.setState({menu: false}); self.setState({menu: false});
}, },
@ -773,29 +774,31 @@ module.exports.haveTileForEvent = function(e) {
function E2ePadlockUndecryptable(props) { function E2ePadlockUndecryptable(props) {
return ( return (
<E2ePadlock title={_t("Undecryptable")} icon="undecryptable" /> <E2ePadlock title={_t("Undecryptable")} icon="undecryptable" {...props} />
); );
} }
function E2ePadlockUnverified(props) { function E2ePadlockUnverified(props) {
return ( return (
<E2ePadlock title={_t("Encrypted by an unverified device")} icon="unverified" /> <E2ePadlock title={_t("Encrypted by an unverified device")} icon="unverified" {...props} />
); );
} }
function E2ePadlockUnencrypted(props) { function E2ePadlockUnencrypted(props) {
return ( return (
<E2ePadlock title={_t("Unencrypted message")} icon="unencrypted" /> <E2ePadlock title={_t("Unencrypted message")} icon="unencrypted" {...props} />
); );
} }
function E2ePadlock(props) { function E2ePadlock(props) {
if (SettingsStore.getValue("alwaysShowEncryptionIcons")) { if (SettingsStore.getValue("alwaysShowEncryptionIcons")) {
return <div return (<div
className={`mx_EventTile_e2eIcon mx_EventTile_e2eIcon_${props.icon}`} className={`mx_EventTile_e2eIcon mx_EventTile_e2eIcon_${props.icon}`}
title={props.title} onClick={props.onClick} />; title={props.title} onClick={props.onClick} />);
} else { } else {
return <div className="mx_EventTile_e2eIcon mx_EventTile_e2eIcon_hidden" onClick={props.onClick} />; return (<div
className={`mx_EventTile_e2eIcon mx_EventTile_e2eIcon_hidden mx_EventTile_e2eIcon_${props.icon}`}
onClick={props.onClick} />);
} }
} }

View file

@ -30,7 +30,7 @@ export default class MemberDeviceInfo extends React.Component {
mx_MemberDeviceInfo_icon_unverified: this.props.device.isUnverified(), mx_MemberDeviceInfo_icon_unverified: this.props.device.isUnverified(),
}); });
const indicator = (<div className={iconClasses} />); const indicator = (<div className={iconClasses} />);
const deviceName = this.props.device.ambiguous ? const deviceName = (this.props.device.ambiguous || this.props.showDeviceId) ?
(this.props.device.getDisplayName() ? this.props.device.getDisplayName() : "") + " (" + this.props.device.deviceId + ")" : (this.props.device.getDisplayName() ? this.props.device.getDisplayName() : "") + " (" + this.props.device.deviceId + ")" :
this.props.device.getDisplayName(); this.props.device.getDisplayName();

View file

@ -941,6 +941,8 @@ module.exports = withMatrixClient(React.createClass({
} }
let roomMemberDetails = null; let roomMemberDetails = null;
let e2eIconElement;
if (this.props.member.roomId) { // is in room if (this.props.member.roomId) { // is in room
const PowerSelector = sdk.getComponent('elements.PowerSelector'); const PowerSelector = sdk.getComponent('elements.PowerSelector');
roomMemberDetails = <div> roomMemberDetails = <div>
@ -959,6 +961,11 @@ module.exports = withMatrixClient(React.createClass({
{statusLabel} {statusLabel}
</div> </div>
</div>; </div>;
const isEncrypted = this.props.matrixClient.isRoomEncrypted(this.props.member.roomId);
if (this.state.e2eStatus && isEncrypted) {
e2eIconElement = (<E2EIcon status={this.state.e2eStatus} isUser={true} />);
}
} }
const avatarUrl = this.props.member.getMxcAvatarUrl(); const avatarUrl = this.props.member.getMxcAvatarUrl();
@ -967,7 +974,7 @@ module.exports = withMatrixClient(React.createClass({
const httpUrl = this.props.matrixClient.mxcUrlToHttp(avatarUrl, 800, 800); const httpUrl = this.props.matrixClient.mxcUrlToHttp(avatarUrl, 800, 800);
avatarElement = <div className="mx_MemberInfo_avatar"> avatarElement = <div className="mx_MemberInfo_avatar">
<img src={httpUrl} /> <img src={httpUrl} />
</div> </div>;
} }
const GeminiScrollbarWrapper = sdk.getComponent("elements.GeminiScrollbarWrapper"); const GeminiScrollbarWrapper = sdk.getComponent("elements.GeminiScrollbarWrapper");
@ -979,7 +986,7 @@ module.exports = withMatrixClient(React.createClass({
<AccessibleButton className="mx_MemberInfo_cancel" onClick={this.onCancel}> <AccessibleButton className="mx_MemberInfo_cancel" onClick={this.onCancel}>
<img src={require("../../../../res/img/minimise.svg")} width="10" height="16" className="mx_filterFlipColor" alt={_t('Close')} /> <img src={require("../../../../res/img/minimise.svg")} width="10" height="16" className="mx_filterFlipColor" alt={_t('Close')} />
</AccessibleButton> </AccessibleButton>
{ this.state.e2eStatus ? <E2EIcon status={this.state.e2eStatus} isUser={true} /> : undefined } { e2eIconElement }
<EmojiText element="h2">{ memberName }</EmojiText> <EmojiText element="h2">{ memberName }</EmojiText>
</div> </div>
{ avatarElement } { avatarElement }

View file

@ -32,6 +32,7 @@ import {CancelButton} from './SimpleRoomHeader';
import SettingsStore from "../../../settings/SettingsStore"; import SettingsStore from "../../../settings/SettingsStore";
import RoomHeaderButtons from '../right_panel/RoomHeaderButtons'; import RoomHeaderButtons from '../right_panel/RoomHeaderButtons';
import E2EIcon from './E2EIcon'; import E2EIcon from './E2EIcon';
import * as cryptodevices from '../../../cryptodevices';
module.exports = React.createClass({ module.exports = React.createClass({
displayName: 'RoomHeader', displayName: 'RoomHeader',
@ -145,6 +146,12 @@ module.exports = React.createClass({
return !(currentPinEvent.getContent().pinned && currentPinEvent.getContent().pinned.length <= 0); return !(currentPinEvent.getContent().pinned && currentPinEvent.getContent().pinned.length <= 0);
}, },
_onShowDevicesClick: function() {
if (this.props.e2eStatus === "warning") {
cryptodevices.showUnknownDeviceDialogForMessages(MatrixClientPeg.get(), this.props.room);
}
},
render: function() { render: function() {
const RoomAvatar = sdk.getComponent("avatars.RoomAvatar"); const RoomAvatar = sdk.getComponent("avatars.RoomAvatar");
const TintableSvg = sdk.getComponent("elements.TintableSvg"); const TintableSvg = sdk.getComponent("elements.TintableSvg");
@ -156,7 +163,7 @@ module.exports = React.createClass({
let pinnedEventsButton = null; let pinnedEventsButton = null;
const e2eIcon = this.props.e2eStatus ? const e2eIcon = this.props.e2eStatus ?
<E2EIcon status={this.props.e2eStatus} /> : <E2EIcon status={this.props.e2eStatus} onClick={this._onShowDevicesClick} /> :
undefined; undefined;
if (this.props.onCancelClick) { if (this.props.onCancelClick) {