SAS verification screen matching design
This commit is contained in:
parent
1d2538a7bc
commit
ec2d51cbbb
6 changed files with 168 additions and 7 deletions
|
@ -60,6 +60,7 @@
|
||||||
@import "./views/elements/_DirectorySearchBox.scss";
|
@import "./views/elements/_DirectorySearchBox.scss";
|
||||||
@import "./views/elements/_Dropdown.scss";
|
@import "./views/elements/_Dropdown.scss";
|
||||||
@import "./views/elements/_EditableItemList.scss";
|
@import "./views/elements/_EditableItemList.scss";
|
||||||
|
@import "./views/elements/_HexVerify.scss";
|
||||||
@import "./views/elements/_ImageView.scss";
|
@import "./views/elements/_ImageView.scss";
|
||||||
@import "./views/elements/_InlineSpinner.scss";
|
@import "./views/elements/_InlineSpinner.scss";
|
||||||
@import "./views/elements/_MemberEventListSummary.scss";
|
@import "./views/elements/_MemberEventListSummary.scss";
|
||||||
|
|
34
res/css/views/elements/_HexVerify.scss
Normal file
34
res/css/views/elements/_HexVerify.scss
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
/*
|
||||||
|
Copyright 2019 New Vector Ltd.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
.mx_HexVerify {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_HexVerify_pair {
|
||||||
|
display: inline-block;
|
||||||
|
font-weight: bold;
|
||||||
|
padding-left: 3px;
|
||||||
|
padding-right: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_HexVerify_pair_verified {
|
||||||
|
color: $accent-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_HexVerify_pair:hover{
|
||||||
|
color: $accent-color;
|
||||||
|
}
|
|
@ -50,6 +50,7 @@ export default class DeviceVerifyDialog extends React.Component {
|
||||||
this.state = {
|
this.state = {
|
||||||
phase: PHASE_START,
|
phase: PHASE_START,
|
||||||
mode: SettingsStore.isFeatureEnabled("feature_sas") ? MODE_SAS : MODE_LEGACY,
|
mode: SettingsStore.isFeatureEnabled("feature_sas") ? MODE_SAS : MODE_LEGACY,
|
||||||
|
sasVerified: false,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,6 +103,10 @@ export default class DeviceVerifyDialog extends React.Component {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_onVerifyStateChanged = (newVal) => {
|
||||||
|
this.setState({sasVerified: newVal});
|
||||||
|
}
|
||||||
|
|
||||||
_onSasMatchesClick = () => {
|
_onSasMatchesClick = () => {
|
||||||
this._showSasEvent.confirm();
|
this._showSasEvent.confirm();
|
||||||
this.setState({
|
this.setState({
|
||||||
|
@ -127,7 +132,6 @@ export default class DeviceVerifyDialog extends React.Component {
|
||||||
body = this._renderSasVerificationPhaseStart();
|
body = this._renderSasVerificationPhaseStart();
|
||||||
break;
|
break;
|
||||||
case PHASE_WAIT_FOR_PARTNER_TO_ACCEPT:
|
case PHASE_WAIT_FOR_PARTNER_TO_ACCEPT:
|
||||||
//body = this._renderSasVerificationPhaseWaitForPartnerToAccept();
|
|
||||||
body = renderSasWaitAccept(this.props.userId);
|
body = renderSasWaitAccept(this.props.userId);
|
||||||
break;
|
break;
|
||||||
case PHASE_SHOW_SAS:
|
case PHASE_SHOW_SAS:
|
||||||
|
@ -180,6 +184,7 @@ export default class DeviceVerifyDialog extends React.Component {
|
||||||
|
|
||||||
_renderSasVerificationPhaseShowSas() {
|
_renderSasVerificationPhaseShowSas() {
|
||||||
const DialogButtons = sdk.getComponent('views.elements.DialogButtons');
|
const DialogButtons = sdk.getComponent('views.elements.DialogButtons');
|
||||||
|
const HexVerify = sdk.getComponent('views.elements.HexVerify');
|
||||||
return <div>
|
return <div>
|
||||||
<p>{_t(
|
<p>{_t(
|
||||||
"Verify this user by confirming the following number appears on their screen"
|
"Verify this user by confirming the following number appears on their screen"
|
||||||
|
@ -188,9 +193,15 @@ export default class DeviceVerifyDialog extends React.Component {
|
||||||
"For maximum security, we reccommend you do this in person or use another " +
|
"For maximum security, we reccommend you do this in person or use another " +
|
||||||
"trusted means of communication"
|
"trusted means of communication"
|
||||||
)}</p>
|
)}</p>
|
||||||
<pre>{this._showSasEvent.sas}</pre>
|
<HexVerify text={this._showSasEvent.sas}
|
||||||
|
onVerifiedStateChange={this._onVerifyStateChanged}
|
||||||
|
/>
|
||||||
|
<p>{_t(
|
||||||
|
"To continue, click on each pair to confirm it's correct.",
|
||||||
|
)}</p>
|
||||||
<DialogButtons onPrimaryButtonClick={this._onSasMatchesClick}
|
<DialogButtons onPrimaryButtonClick={this._onSasMatchesClick}
|
||||||
primaryButton={_t("This Matches")}
|
primaryButton={_t("Continue")}
|
||||||
|
primaryDisabled={!this.state.sasVerified}
|
||||||
hasCancel={true}
|
hasCancel={true}
|
||||||
onCancel={this._onCancelClick}
|
onCancel={this._onCancelClick}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -38,6 +38,7 @@ export default class IncomingSasDialog extends React.Component {
|
||||||
this._showSasEvent = null;
|
this._showSasEvent = null;
|
||||||
this.state = {
|
this.state = {
|
||||||
phase: PHASE_START,
|
phase: PHASE_START,
|
||||||
|
sasVerified: false,
|
||||||
};
|
};
|
||||||
this.props.verifier.on('show_sas', this._onVerifierShowSas);
|
this.props.verifier.on('show_sas', this._onVerifierShowSas);
|
||||||
this.props.verifier.on('cancel', this._onVerifierCancel);
|
this.props.verifier.on('cancel', this._onVerifierCancel);
|
||||||
|
@ -81,6 +82,10 @@ export default class IncomingSasDialog extends React.Component {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_onVerifiedStateChange = (newVal) => {
|
||||||
|
this.setState({sasVerified: newVal});
|
||||||
|
}
|
||||||
|
|
||||||
_onSasMatchesClick = () => {
|
_onSasMatchesClick = () => {
|
||||||
this._showSasEvent.confirm();
|
this._showSasEvent.confirm();
|
||||||
this.setState({
|
this.setState({
|
||||||
|
@ -121,6 +126,7 @@ export default class IncomingSasDialog extends React.Component {
|
||||||
|
|
||||||
_renderPhaseShowSas() {
|
_renderPhaseShowSas() {
|
||||||
const DialogButtons = sdk.getComponent('views.elements.DialogButtons');
|
const DialogButtons = sdk.getComponent('views.elements.DialogButtons');
|
||||||
|
const HexVerify = sdk.getComponent('views.elements.HexVerify');
|
||||||
return <div>
|
return <div>
|
||||||
<p>{_t(
|
<p>{_t(
|
||||||
"Verify this user by confirming the following number appears on their screen"
|
"Verify this user by confirming the following number appears on their screen"
|
||||||
|
@ -129,9 +135,15 @@ export default class IncomingSasDialog extends React.Component {
|
||||||
"For maximum security, we reccommend you do this in person or use another " +
|
"For maximum security, we reccommend you do this in person or use another " +
|
||||||
"trusted means of communication"
|
"trusted means of communication"
|
||||||
)}</p>
|
)}</p>
|
||||||
<pre>{this._showSasEvent.sas}</pre>
|
<HexVerify text={this._showSasEvent.sas}
|
||||||
|
onVerifiedStateChange={this._onVerifiedStateChange}
|
||||||
|
/>
|
||||||
|
<p>{_t(
|
||||||
|
"To continue, click on each pair to confirm it's correct.",
|
||||||
|
)}</p>
|
||||||
<DialogButtons onPrimaryButtonClick={this._onSasMatchesClick}
|
<DialogButtons onPrimaryButtonClick={this._onSasMatchesClick}
|
||||||
primaryButton={_t("This Matches")}
|
primaryButton={_t("Continue")}
|
||||||
|
primaryDisabled={!this.state.sasVerified}
|
||||||
hasCancel={true}
|
hasCancel={true}
|
||||||
onCancel={this._onCancelClick}
|
onCancel={this._onCancelClick}
|
||||||
/>
|
/>
|
||||||
|
@ -184,7 +196,6 @@ export default class IncomingSasDialog extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
console.log("rendering pahse "+this.state.phase);
|
|
||||||
let body;
|
let body;
|
||||||
switch (this.state.phase) {
|
switch (this.state.phase) {
|
||||||
case PHASE_START:
|
case PHASE_START:
|
||||||
|
|
104
src/components/views/elements/HexVerify.js
Normal file
104
src/components/views/elements/HexVerify.js
Normal file
|
@ -0,0 +1,104 @@
|
||||||
|
/*
|
||||||
|
Copyright 2019 New Vector Ltd.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React from "react";
|
||||||
|
import PropTypes from "prop-types";
|
||||||
|
import { _t } from '../../../languageHandler';
|
||||||
|
import classnames from 'classnames';
|
||||||
|
|
||||||
|
import sdk from '../../../index';
|
||||||
|
|
||||||
|
class HexVerifyPair extends React.Component {
|
||||||
|
static propTypes = {
|
||||||
|
text: PropTypes.string.isRequired,
|
||||||
|
index: PropTypes.number,
|
||||||
|
verified: PropTypes.bool,
|
||||||
|
onChange: PropTypes.func.isRequired,
|
||||||
|
}
|
||||||
|
|
||||||
|
_onClick = () => {
|
||||||
|
this.setState({verified: !this.props.verified});
|
||||||
|
this.props.onChange(this.props.index, !this.props.verified);
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const classNames = {
|
||||||
|
mx_HexVerify_pair: true,
|
||||||
|
mx_HexVerify_pair_verified: this.props.verified,
|
||||||
|
};
|
||||||
|
const AccessibleButton = sdk.getComponent('views.elements.AccessibleButton');
|
||||||
|
return <AccessibleButton className={classnames(classNames)}
|
||||||
|
onClick={this._onClick}
|
||||||
|
>
|
||||||
|
{this.props.text}
|
||||||
|
</AccessibleButton>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helps a user verify a hexadecimal code matches one displayed
|
||||||
|
* elsewhere (eg. on a different device)
|
||||||
|
*/
|
||||||
|
export default class HexVerify extends React.Component {
|
||||||
|
static propTypes = {
|
||||||
|
text: PropTypes.string.isRequired,
|
||||||
|
onVerifiedStateChange: PropTypes.func,
|
||||||
|
}
|
||||||
|
|
||||||
|
static defaultProps = {
|
||||||
|
onVerifiedStateChange: function() {},
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.state = {
|
||||||
|
pairsVerified: [],
|
||||||
|
};
|
||||||
|
for (let i = 0; i < props.text.length; i += 2) {
|
||||||
|
this.state.pairsVerified.push(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_onPairChange = (index, newVal) => {
|
||||||
|
const oldVerified = this.state.pairsVerified.reduce((acc, val) => {
|
||||||
|
return acc && val;
|
||||||
|
}, true);
|
||||||
|
const newPairsVerified = this.state.pairsVerified.slice(0);
|
||||||
|
newPairsVerified[index] = newVal;
|
||||||
|
const newVerified = newPairsVerified.reduce((acc, val) => {
|
||||||
|
return acc && val;
|
||||||
|
}, true);
|
||||||
|
this.setState({pairsVerified: newPairsVerified});
|
||||||
|
if (oldVerified !== newVerified) {
|
||||||
|
this.props.onVerifiedStateChange(newVerified);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const pairs = [];
|
||||||
|
|
||||||
|
for (let i = 0; i < this.props.text.length / 2; ++i) {
|
||||||
|
pairs.push(<HexVerifyPair key={i} index={i}
|
||||||
|
text={this.props.text.substr(i * 2, 2)}
|
||||||
|
verified={this.state.pairsVerified[i]}
|
||||||
|
onChange={this._onPairChange}
|
||||||
|
/>);
|
||||||
|
}
|
||||||
|
return <div className="mx_HexVerify">
|
||||||
|
{pairs}
|
||||||
|
</div>;
|
||||||
|
}
|
||||||
|
}
|
|
@ -947,7 +947,7 @@
|
||||||
"Send Verification Request": "Send Verification Request",
|
"Send Verification Request": "Send Verification Request",
|
||||||
"Verify this user by confirming the following number appears on their screen": "Verify this user by confirming the following number appears on their screen",
|
"Verify this user by confirming the following number appears on their screen": "Verify this user by confirming the following number appears on their screen",
|
||||||
"For maximum security, we reccommend you do this in person or use another trusted means of communication": "For maximum security, we reccommend you do this in person or use another trusted means of communication",
|
"For maximum security, we reccommend you do this in person or use another trusted means of communication": "For maximum security, we reccommend you do this in person or use another trusted means of communication",
|
||||||
"This Matches": "This Matches",
|
"To continue, click on each pair to confirm it's correct.": "To continue, click on each pair to confirm it's correct.",
|
||||||
"Verification complete!": "Verification complete!",
|
"Verification complete!": "Verification complete!",
|
||||||
"Done": "Done",
|
"Done": "Done",
|
||||||
"%(userId)s cancelled the verification.": "%(userId)s cancelled the verification.",
|
"%(userId)s cancelled the verification.": "%(userId)s cancelled the verification.",
|
||||||
|
|
Loading…
Reference in a new issue