From 210616c737bdc93fd421c75ec8e554779f4af7fb Mon Sep 17 00:00:00 2001
From: Michael Telatynski <7t3chguy@gmail.com>
Date: Fri, 24 Jan 2020 11:45:39 +0000
Subject: [PATCH 001/163] Phase 1, split out UserInfo into a generic Pane, use
for EncInfo
---
res/css/views/right_panel/_UserInfo.scss | 17 +-
src/components/structures/RightPanel.js | 13 +-
.../views/right_panel/EncryptionInfo.js | 18 +-
.../views/right_panel/EncryptionPanel.js | 25 +-
src/components/views/right_panel/UserInfo.js | 248 +++++++++---------
src/i18n/strings/en_EN.json | 3 +-
6 files changed, 191 insertions(+), 133 deletions(-)
diff --git a/res/css/views/right_panel/_UserInfo.scss b/res/css/views/right_panel/_UserInfo.scss
index d2d9d12c6d..57ffd4982e 100644
--- a/res/css/views/right_panel/_UserInfo.scss
+++ b/res/css/views/right_panel/_UserInfo.scss
@@ -49,12 +49,17 @@ limitations under the License.
}
.mx_UserInfo_container {
- padding: 0 16px 16px 16px;
+ padding: 8px 16px;
+ }
+
+ .mx_UserInfo_separator {
border-bottom: 1px solid lightgray;
}
.mx_UserInfo_memberDetailsContainer {
+ padding-top: 0;
padding-bottom: 0;
+ margin-bottom: 8px;
}
.mx_RoomTile_nameContainer {
@@ -204,10 +209,9 @@ limitations under the License.
padding-bottom: 16px;
}
- .mx_UserInfo_scrollContainer .mx_UserInfo_container {
+ .mx_UserInfo_scrollContainer:not(.mx_UserInfo_separator) {
padding-top: 16px;
padding-bottom: 0;
- border-bottom: none;
> :not(h3) {
margin-left: 8px;
@@ -264,3 +268,10 @@ limitations under the License.
margin: 16px 0;
}
}
+
+.mx_UserInfo.mx_UserInfo_smallAvatar {
+ .mx_UserInfo_avatar > div {
+ max-width: 72px;
+ margin: 0 auto;
+ }
+}
diff --git a/src/components/structures/RightPanel.js b/src/components/structures/RightPanel.js
index dca89d0c35..c01a3709e7 100644
--- a/src/components/structures/RightPanel.js
+++ b/src/components/structures/RightPanel.js
@@ -238,7 +238,18 @@ export default class RightPanel extends React.Component {
} else if (this.state.phase === RIGHT_PANEL_PHASES.FilePanel) {
panel =
{_t("For extra security, verify this user by checking a one-time code on both of your devices.")}
-{_t("For maximum security, do this in person.")}
-{_t("For extra security, verify this user by checking a one-time code on both of your devices.")}
+{_t("For maximum security, do this in person.")}
+Not a member nor request, not sure what to render
; + content =Not a member nor request, not sure what to render
; } + + return ( +{_t("Messages in this room are end-to-end encrypted.")}
+{_t("Your messages are secured and only you and the recipient have the unique keys to unlock them.")}
+{_t("For extra security, verify this user by checking a one-time code on both of your devices.")}
-{_t("For maximum security, do this in person.")}
-{_t("Messages in this room are end-to-end encrypted.")}
+{_t("Your messages are secured and only you and the recipient have the unique keys to unlock them.")}
+{_t("For extra security, verify this user by checking a one-time code on both of your devices.")}
+{_t("For maximum security, do this in person.")}
+ { content } +Not a member nor request, not sure what to render
; - } +}; - return ( -{_t("Messages in this room are end-to-end encrypted.")}
-{_t("Your messages are secured and only you and the recipient have the unique keys to unlock them.")}
-{ text }
+ { verifyButton } + { devicesSection } +{ text }
- { verifyButton } - { devicesSection } -{_t("Ask %(displayName)s to scan your code, or open your camera to scan theirs:", { + displayName: member.displayName || member.name || member.userId, + }, { + a: t => { t }, + })}
+{_t("If you can't scan the code above, verify by comparing unique emoji.")}
+Waiting for {request.otherUserId} to accept ...
{request.otherUserId} is ready, start {verifyButton}
); + const AccessibleButton = sdk.getComponent('elements.AccessibleButton'); + return ( +{_t("You've successfully verified %(displayName)s!", { + displayName: member.displayName || member.name || member.userId, + })}
+Verify all users in a room to ensure it's secure.
+Waiting for {request.otherUserId} to confirm ...
; - } else if (this.state.sasEvent) { + if (this.state.sasEvent) { const VerificationShowSas = sdk.getComponent('views.verification.VerificationShowSas'); - return (Setting up SAS verification...
); } } else if (request.done) { - returnverified {request.otherUserId}!!
; + return this.renderVerifiedPhase(); } else if (request.cancelled) { + // TODO check if this matches target + // TODO should this be a MODAL? returncancelled by {request.cancellingUserId}!
; } + return null; } _startSAS = async () => { @@ -79,7 +117,6 @@ export default class VerificationPanel extends React.PureComponent { }; _onSasMatchesClick = () => { - this.setState({sasWaitingForOtherParty: true}); this.state.sasEvent.confirm(); }; @@ -106,7 +143,7 @@ export default class VerificationPanel extends React.PureComponent { request.verifier.removeListener('show_sas', this._onVerifierShowSas); } this._hasVerifier = !!request.verifier; - this.forceUpdate(); + this.forceUpdate(); // TODO fix this }; componentDidMount() { diff --git a/src/components/views/toasts/VerificationRequestToast.js b/src/components/views/toasts/VerificationRequestToast.js index 479a3e3f93..769e0d36d0 100644 --- a/src/components/views/toasts/VerificationRequestToast.js +++ b/src/components/views/toasts/VerificationRequestToast.js @@ -76,10 +76,14 @@ export default class VerificationRequestToast extends React.PureComponent { } try { await request.accept(); + const cli = MatrixClientPeg.get(); dis.dispatch({ action: "set_right_panel_phase", phase: RIGHT_PANEL_PHASES.EncryptionPanel, - refireParams: {verificationRequest: request}, + refireParams: { + verificationRequest: request, + member: cli.getUser(request.otherUserId), + }, }); } catch (err) { console.error(err.message); diff --git a/src/components/views/verification/VerificationShowSas.js b/src/components/views/verification/VerificationShowSas.js index 8f39457689..693a3769a0 100644 --- a/src/components/views/verification/VerificationShowSas.js +++ b/src/components/views/verification/VerificationShowSas.js @@ -18,6 +18,8 @@ import React from 'react'; import PropTypes from 'prop-types'; import * as sdk from '../../../index'; import { _t, _td } from '../../../languageHandler'; +import {PendingActionSpinner} from "../right_panel/EncryptionInfo"; +import AccessibleButton from "../elements/AccessibleButton"; function capFirst(s) { return s.charAt(0).toUpperCase() + s.slice(1); @@ -25,18 +27,26 @@ function capFirst(s) { export default class VerificationShowSas extends React.Component { static propTypes = { + displayName: PropTypes.string.isRequired, onDone: PropTypes.func.isRequired, onCancel: PropTypes.func.isRequired, sas: PropTypes.object.isRequired, + }; + + constructor(props) { + super(props); + + this.state = { + pending: false, + }; } - constructor() { - super(); - } + onMatchClick = () => { + this.setState({ pending: true }); + this.props.onDone(); + }; render() { - const DialogButtons = sdk.getComponent('views.elements.DialogButtons'); - let sasDisplay; let sasCaption; if (this.props.sas.emoji) { @@ -69,26 +79,33 @@ export default class VerificationShowSas extends React.Component { } else { return{sasCaption}
-{_t( - "For maximum security, we recommend you do this in person or use another " + - "trusted means of communication.", - )}
+{_t("For ultimate security, do this in person or use another way to communicate.")}
{sasDisplay} -request.requestEvent.getId()
; + } + + const qrCodeKeys = [ + [MatrixClientPeg.get().getDeviceId(), MatrixClientPeg.get().getDeviceEd25519Key()], + [MatrixClientPeg.get().getCrossSigningId(), MatrixClientPeg.get().getCrossSigningId()], + ]; + const crossSigningInfo = MatrixClientPeg.get().getStoredCrossSigningForUser(request.otherUserId); + + if (!crossSigningInfo) { + // TODO handle this error case + returncrossSigningInfo
; + } + return{_t("If you can't scan the code above, verify by comparing unique emoji.")}
+request.requestEvent.getId()
; } + const myKeyId = cli.getCrossSigningId(); const qrCodeKeys = [ - [MatrixClientPeg.get().getDeviceId(), MatrixClientPeg.get().getDeviceEd25519Key()], - [MatrixClientPeg.get().getCrossSigningId(), MatrixClientPeg.get().getCrossSigningId()], + [cli.getDeviceId(), cli.getDeviceEd25519Key()], + [myKeyId, myKeyId], ]; - const crossSigningInfo = MatrixClientPeg.get().getStoredCrossSigningForUser(request.otherUserId); - - if (!crossSigningInfo) { - // TODO handle this error case - returncrossSigningInfo
; - } return{_t("Ask %(displayName)s to scan your code, or open your camera to scan theirs:", { +
{_t("Ask %(displayName)s to scan your code:", { displayName: member.displayName || member.name || member.userId, - }, { - a: t => { t }, })}
-request.requestEvent.getId()
; + // for whatever reason we can't generate a QR code, offer only SAS Verification + return{_t("Verify by comparing unique emoji.")}
+ +{_t("Verify by comparing unique emoji.")}
-{_t("If you can't scan the code above, verify by comparing unique emoji.")}
-Verify all users in a room to ensure it's secure.
-{ text }
+ +Setting up SAS verification...
); - } - } else if (request.done) { - return this.renderVerifiedPhase(); - } else if (request.cancelled) { - // TODO check if this matches target - // TODO should this be a MODAL? - returncancelled by {request.cancellingUserId}!
; + switch (this.props.phase) { + case PHASE_READY: + return this.renderQRPhase(); + case PHASE_STARTED: + if (this.state.sasEvent) { + const VerificationShowSas = sdk.getComponent('views.verification.VerificationShowSas'); + return{_t( + "Your new session is now verified. It has access to your " + + "encrypted messages, and other users will see it as trusted.", + )}
; + } else { + message ={_t( + "Your new session is now verified. Other users will see it as trusted.", + )}
; + } body = ({_t( - "Your new session is now verified. It has access to your " + - "encrypted messages, and other users will see it as trusted.", - )}
+ {message}- {_t( - "For maximum security, we recommend you do this in person or " + - "use another trusted means of communication.", - )} + {_t("To be secure, do this in person or use another way to communicate.")}
{_t("For extra security, verify this user by checking a one-time code on both of your devices.")}
-{_t("For maximum security, do this in person.")}
+{_t("To be secure, do this in person or use another way to communicate.")}
{ content }{sasCaption}
-{_t("For ultimate security, do this in person or use another way to communicate.")}
+{_t("To be secure, do this in person or use another way to communicate.")}
{sasDisplay} {confirm}- {_t("To be secure, do this in person or use another way to communicate.")} + {_t("To be secure, do this in person or use a trusted way to communicate.")}
{_t("For extra security, verify this user by checking a one-time code on both of your devices.")}
-{_t("To be secure, do this in person or use another way to communicate.")}
+{_t("To be secure, do this in person or use a trusted way to communicate.")}
{ content }{sasCaption}
-{_t("To be secure, do this in person or use another way to communicate.")}
+{_t("To be secure, do this in person or use a trusted way to communicate.")}
{sasDisplay} {confirm}Verify all users in a room to ensure it's secure.
-{ text }
-{ _t('The signing key you provided matches the signing key you received ' + - 'from %(userId)s\'s device %(deviceId)s. Device marked as verified.', + 'from %(userId)s\'s session %(deviceId)s. Session marked as verified.', {userId, deviceId}) }
diff --git a/src/async-components/views/dialogs/EncryptedEventDialog.js b/src/async-components/views/dialogs/EncryptedEventDialog.js index f6e17b1c84..b602cf60fe 100644 --- a/src/async-components/views/dialogs/EncryptedEventDialog.js +++ b/src/async-components/views/dialogs/EncryptedEventDialog.js @@ -191,7 +191,7 @@ export default createReactClass({{_t( - "This device is encrypting history using the new recovery method.", + "This session is encrypting history using the new recovery method.", )}
{hackWarning}{_t( - "This device has detected that your recovery passphrase and key " + + "This session has detected that your recovery passphrase and key " + "for Secure Messages have been removed.", )}
{_t( "If you did this accidentally, you can setup Secure Messages on " + - "this device which will re-encrypt this device's message " + + "this session which will re-encrypt this session's message " + "history with a new recovery method.", )}
{_t( diff --git a/src/async-components/views/dialogs/secretstorage/CreateSecretStorageDialog.js b/src/async-components/views/dialogs/secretstorage/CreateSecretStorageDialog.js index 4068f72217..c3b74381ff 100644 --- a/src/async-components/views/dialogs/secretstorage/CreateSecretStorageDialog.js +++ b/src/async-components/views/dialogs/secretstorage/CreateSecretStorageDialog.js @@ -424,7 +424,7 @@ export default class CreateSecretStorageDialog extends React.PureComponent { return