Convert VerificationPanel to TS
parent
3e64ec11c0
commit
8fac7a8167
|
@ -15,12 +15,15 @@ limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import PropTypes from "prop-types";
|
|
||||||
|
|
||||||
import {MatrixClientPeg} from "../../../MatrixClientPeg";
|
import {MatrixClientPeg} from "../../../MatrixClientPeg";
|
||||||
import * as sdk from '../../../index';
|
import * as sdk from '../../../index';
|
||||||
import {verificationMethods} from 'matrix-js-sdk/src/crypto';
|
import {verificationMethods} from 'matrix-js-sdk/src/crypto';
|
||||||
import {SCAN_QR_CODE_METHOD} from "matrix-js-sdk/src/crypto/verification/QRCode";
|
import {SCAN_QR_CODE_METHOD} from "matrix-js-sdk/src/crypto/verification/QRCode";
|
||||||
|
import {VerificationRequest} from "matrix-js-sdk/src/crypto/verification/request/VerificationRequest";
|
||||||
|
import {RoomMember} from "matrix-js-sdk/src/models/room-member";
|
||||||
|
import {ReciprocateQRCode} from "matrix-js-sdk/src/crypto/verification/QRCode";
|
||||||
|
import {SAS} from "matrix-js-sdk/src/crypto/verification/SAS";
|
||||||
|
|
||||||
import VerificationQRCode from "../elements/crypto/VerificationQRCode";
|
import VerificationQRCode from "../elements/crypto/VerificationQRCode";
|
||||||
import {_t} from "../../../languageHandler";
|
import {_t} from "../../../languageHandler";
|
||||||
|
@ -36,37 +39,67 @@ import {
|
||||||
} from "matrix-js-sdk/src/crypto/verification/request/VerificationRequest";
|
} from "matrix-js-sdk/src/crypto/verification/request/VerificationRequest";
|
||||||
import Spinner from "../elements/Spinner";
|
import Spinner from "../elements/Spinner";
|
||||||
|
|
||||||
export default class VerificationPanel extends React.PureComponent {
|
// XXX: Should be defined in matrix-js-sdk
|
||||||
static propTypes = {
|
enum VerificationPhase {
|
||||||
layout: PropTypes.string,
|
PHASE_UNSENT,
|
||||||
request: PropTypes.object.isRequired,
|
PHASE_REQUESTED,
|
||||||
member: PropTypes.object.isRequired,
|
PHASE_READY,
|
||||||
phase: PropTypes.oneOf([
|
PHASE_DONE,
|
||||||
PHASE_UNSENT,
|
PHASE_STARTED,
|
||||||
PHASE_REQUESTED,
|
PHASE_CANCELLED,
|
||||||
PHASE_READY,
|
}
|
||||||
PHASE_STARTED,
|
|
||||||
PHASE_CANCELLED,
|
|
||||||
PHASE_DONE,
|
|
||||||
]).isRequired,
|
|
||||||
onClose: PropTypes.func.isRequired,
|
|
||||||
isRoomEncrypted: PropTypes.bool,
|
|
||||||
};
|
|
||||||
|
|
||||||
constructor(props) {
|
interface IProps {
|
||||||
|
layout: string;
|
||||||
|
request: VerificationRequest;
|
||||||
|
member: RoomMember;
|
||||||
|
phase: VerificationPhase;
|
||||||
|
onClose: () => void;
|
||||||
|
isRoomEncrypted: boolean;
|
||||||
|
inDialog: boolean;
|
||||||
|
key: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IState {
|
||||||
|
sasEvent?: SAS;
|
||||||
|
emojiButtonClicked?: boolean;
|
||||||
|
reciprocateButtonClicked?: boolean;
|
||||||
|
reciprocateQREvent?: ReciprocateQRCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class VerificationPanel extends React.PureComponent<IProps, IState> {
|
||||||
|
/* static propTypes = { */
|
||||||
|
/* layout: PropTypes.string, */
|
||||||
|
/* request: PropTypes.object.isRequired, */
|
||||||
|
/* member: PropTypes.object.isRequired, */
|
||||||
|
/* phase: PropTypes.oneOf([ */
|
||||||
|
/* PHASE_UNSENT, */
|
||||||
|
/* PHASE_REQUESTED, */
|
||||||
|
/* PHASE_READY, */
|
||||||
|
/* PHASE_STARTED, */
|
||||||
|
/* PHASE_CANCELLED, */
|
||||||
|
/* PHASE_DONE, */
|
||||||
|
/* ]).isRequired, */
|
||||||
|
/* onClose: PropTypes.func.isRequired, */
|
||||||
|
/* isRoomEncrypted: PropTypes.bool, */
|
||||||
|
/* }; */
|
||||||
|
|
||||||
|
private hasVerifier: boolean;
|
||||||
|
|
||||||
|
constructor(props: IProps) {
|
||||||
super(props);
|
super(props);
|
||||||
this.state = {};
|
this.state = {};
|
||||||
this._hasVerifier = false;
|
this.hasVerifier = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
renderQRPhase() {
|
renderQRPhase() {
|
||||||
const {member, request} = this.props;
|
const {member, request} = this.props;
|
||||||
const showSAS = request.otherPartySupportsMethod(verificationMethods.SAS);
|
const showSAS: boolean = request.otherPartySupportsMethod(verificationMethods.SAS);
|
||||||
const showQR = request.otherPartySupportsMethod(SCAN_QR_CODE_METHOD);
|
const showQR: boolean = request.otherPartySupportsMethod(SCAN_QR_CODE_METHOD);
|
||||||
const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
|
const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
|
||||||
const brand = SdkConfig.get().brand;
|
const brand = SdkConfig.get().brand;
|
||||||
|
|
||||||
const noCommonMethodError = !showSAS && !showQR ?
|
const noCommonMethodError: JSX.Element = !showSAS && !showQR ?
|
||||||
<p>{_t(
|
<p>{_t(
|
||||||
"The session you are trying to verify doesn't support scanning a " +
|
"The session you are trying to verify doesn't support scanning a " +
|
||||||
"QR code or emoji verification, which is what %(brand)s supports. Try " +
|
"QR code or emoji verification, which is what %(brand)s supports. Try " +
|
||||||
|
@ -77,8 +110,8 @@ export default class VerificationPanel extends React.PureComponent {
|
||||||
|
|
||||||
if (this.props.layout === 'dialog') {
|
if (this.props.layout === 'dialog') {
|
||||||
// HACK: This is a terrible idea.
|
// HACK: This is a terrible idea.
|
||||||
let qrBlock;
|
let qrBlock: JSX.Element;
|
||||||
let sasBlock;
|
let sasBlock: JSX.Element;
|
||||||
if (showQR) {
|
if (showQR) {
|
||||||
qrBlock =
|
qrBlock =
|
||||||
<div className='mx_VerificationPanel_QRPhase_startOption'>
|
<div className='mx_VerificationPanel_QRPhase_startOption'>
|
||||||
|
@ -91,7 +124,7 @@ export default class VerificationPanel extends React.PureComponent {
|
||||||
<div className='mx_VerificationPanel_QRPhase_startOption'>
|
<div className='mx_VerificationPanel_QRPhase_startOption'>
|
||||||
<p>{_t("Compare unique emoji")}</p>
|
<p>{_t("Compare unique emoji")}</p>
|
||||||
<span className='mx_VerificationPanel_QRPhase_helpText'>{_t("Compare a unique set of emoji if you don't have a camera on either device")}</span>
|
<span className='mx_VerificationPanel_QRPhase_helpText'>{_t("Compare a unique set of emoji if you don't have a camera on either device")}</span>
|
||||||
<AccessibleButton disabled={this.state.emojiButtonClicked} onClick={this._startSAS} kind='primary'>
|
<AccessibleButton disabled={this.state.emojiButtonClicked} onClick={this.startSAS} kind='primary'>
|
||||||
{_t("Start")}
|
{_t("Start")}
|
||||||
</AccessibleButton>
|
</AccessibleButton>
|
||||||
</div>;
|
</div>;
|
||||||
|
@ -111,7 +144,7 @@ export default class VerificationPanel extends React.PureComponent {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let qrBlock;
|
let qrBlock: JSX.Element;
|
||||||
if (showQR) {
|
if (showQR) {
|
||||||
qrBlock = <div className="mx_UserInfo_container">
|
qrBlock = <div className="mx_UserInfo_container">
|
||||||
<h3>{_t("Verify by scanning")}</h3>
|
<h3>{_t("Verify by scanning")}</h3>
|
||||||
|
@ -125,7 +158,7 @@ export default class VerificationPanel extends React.PureComponent {
|
||||||
</div>;
|
</div>;
|
||||||
}
|
}
|
||||||
|
|
||||||
let sasBlock;
|
let sasBlock: JSX.Element;
|
||||||
if (showSAS) {
|
if (showSAS) {
|
||||||
const disabled = this.state.emojiButtonClicked;
|
const disabled = this.state.emojiButtonClicked;
|
||||||
const sasLabel = showQR ?
|
const sasLabel = showQR ?
|
||||||
|
@ -140,7 +173,7 @@ export default class VerificationPanel extends React.PureComponent {
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
kind="primary"
|
kind="primary"
|
||||||
className="mx_UserInfo_wideButton mx_VerificationPanel_verifyByEmojiButton"
|
className="mx_UserInfo_wideButton mx_VerificationPanel_verifyByEmojiButton"
|
||||||
onClick={this._startSAS}
|
onClick={this.startSAS}
|
||||||
>
|
>
|
||||||
{_t("Verify by emoji")}
|
{_t("Verify by emoji")}
|
||||||
</AccessibleButton>
|
</AccessibleButton>
|
||||||
|
@ -159,17 +192,17 @@ export default class VerificationPanel extends React.PureComponent {
|
||||||
</React.Fragment>;
|
</React.Fragment>;
|
||||||
}
|
}
|
||||||
|
|
||||||
_onReciprocateYesClick = () => {
|
private onReciprocateYesClick = () => {
|
||||||
this.setState({reciprocateButtonClicked: true});
|
this.setState({reciprocateButtonClicked: true});
|
||||||
this.state.reciprocateQREvent.confirm();
|
this.state.reciprocateQREvent.confirm();
|
||||||
};
|
};
|
||||||
|
|
||||||
_onReciprocateNoClick = () => {
|
private onReciprocateNoClick = () => {
|
||||||
this.setState({reciprocateButtonClicked: true});
|
this.setState({reciprocateButtonClicked: true});
|
||||||
this.state.reciprocateQREvent.cancel();
|
this.state.reciprocateQREvent.cancel();
|
||||||
};
|
};
|
||||||
|
|
||||||
_getDevice() {
|
private getDevice() {
|
||||||
const deviceId = this.props.request && this.props.request.channel.deviceId;
|
const deviceId = this.props.request && this.props.request.channel.deviceId;
|
||||||
return MatrixClientPeg.get().getStoredDevice(MatrixClientPeg.get().getUserId(), deviceId);
|
return MatrixClientPeg.get().getStoredDevice(MatrixClientPeg.get().getUserId(), deviceId);
|
||||||
}
|
}
|
||||||
|
@ -189,7 +222,7 @@ export default class VerificationPanel extends React.PureComponent {
|
||||||
_t("Almost there! Is %(displayName)s showing the same shield?", {
|
_t("Almost there! Is %(displayName)s showing the same shield?", {
|
||||||
displayName: member.displayName || member.name || member.userId,
|
displayName: member.displayName || member.name || member.userId,
|
||||||
});
|
});
|
||||||
let body;
|
let body: JSX.Element;
|
||||||
if (this.state.reciprocateQREvent) {
|
if (this.state.reciprocateQREvent) {
|
||||||
// riot web doesn't support scanning yet, so assume here we're the client being scanned.
|
// riot web doesn't support scanning yet, so assume here we're the client being scanned.
|
||||||
//
|
//
|
||||||
|
@ -202,11 +235,11 @@ export default class VerificationPanel extends React.PureComponent {
|
||||||
<Button
|
<Button
|
||||||
label={_t("No")} kind="danger"
|
label={_t("No")} kind="danger"
|
||||||
disabled={this.state.reciprocateButtonClicked}
|
disabled={this.state.reciprocateButtonClicked}
|
||||||
onClick={this._onReciprocateNoClick}>{_t("No")}</Button>
|
onClick={this.onReciprocateNoClick}>{_t("No")}</Button>
|
||||||
<Button
|
<Button
|
||||||
label={_t("Yes")} kind="primary"
|
label={_t("Yes")} kind="primary"
|
||||||
disabled={this.state.reciprocateButtonClicked}
|
disabled={this.state.reciprocateButtonClicked}
|
||||||
onClick={this._onReciprocateYesClick}>{_t("Yes")}</Button>
|
onClick={this.onReciprocateYesClick}>{_t("Yes")}</Button>
|
||||||
</div>
|
</div>
|
||||||
</React.Fragment>;
|
</React.Fragment>;
|
||||||
} else {
|
} else {
|
||||||
|
@ -221,7 +254,7 @@ export default class VerificationPanel extends React.PureComponent {
|
||||||
renderVerifiedPhase() {
|
renderVerifiedPhase() {
|
||||||
const {member, request} = this.props;
|
const {member, request} = this.props;
|
||||||
|
|
||||||
let text;
|
let text: string;
|
||||||
if (!request.isSelfVerification) {
|
if (!request.isSelfVerification) {
|
||||||
if (this.props.isRoomEncrypted) {
|
if (this.props.isRoomEncrypted) {
|
||||||
text = _t("Verify all users in a room to ensure it's secure.");
|
text = _t("Verify all users in a room to ensure it's secure.");
|
||||||
|
@ -230,9 +263,9 @@ export default class VerificationPanel extends React.PureComponent {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let description;
|
let description: string;
|
||||||
if (request.isSelfVerification) {
|
if (request.isSelfVerification) {
|
||||||
const device = this._getDevice();
|
const device = this.getDevice();
|
||||||
if (!device) {
|
if (!device) {
|
||||||
// This can happen if the device is logged out while we're still showing verification
|
// This can happen if the device is logged out while we're still showing verification
|
||||||
// UI for it.
|
// UI for it.
|
||||||
|
@ -269,14 +302,14 @@ export default class VerificationPanel extends React.PureComponent {
|
||||||
|
|
||||||
const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
|
const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
|
||||||
|
|
||||||
let startAgainInstruction;
|
let startAgainInstruction: string;
|
||||||
if (request.isSelfVerification) {
|
if (request.isSelfVerification) {
|
||||||
startAgainInstruction = _t("Start verification again from the notification.");
|
startAgainInstruction = _t("Start verification again from the notification.");
|
||||||
} else {
|
} else {
|
||||||
startAgainInstruction = _t("Start verification again from their profile.");
|
startAgainInstruction = _t("Start verification again from their profile.");
|
||||||
}
|
}
|
||||||
|
|
||||||
let text;
|
let text: string;
|
||||||
if (request.cancellationCode === "m.timeout") {
|
if (request.cancellationCode === "m.timeout") {
|
||||||
text = _t("Verification timed out.") + ` ${startAgainInstruction}`;
|
text = _t("Verification timed out.") + ` ${startAgainInstruction}`;
|
||||||
} else if (request.cancellingUserId === request.otherUserId) {
|
} else if (request.cancellingUserId === request.otherUserId) {
|
||||||
|
@ -321,10 +354,10 @@ export default class VerificationPanel extends React.PureComponent {
|
||||||
const emojis = this.state.sasEvent ?
|
const emojis = this.state.sasEvent ?
|
||||||
<VerificationShowSas
|
<VerificationShowSas
|
||||||
displayName={displayName}
|
displayName={displayName}
|
||||||
device={this._getDevice()}
|
device={this.getDevice()}
|
||||||
sas={this.state.sasEvent.sas}
|
sas={this.state.sasEvent.sas}
|
||||||
onCancel={this._onSasMismatchesClick}
|
onCancel={this.onSasMismatchesClick}
|
||||||
onDone={this._onSasMatchesClick}
|
onDone={this.onSasMatchesClick}
|
||||||
inDialog={this.props.inDialog}
|
inDialog={this.props.inDialog}
|
||||||
isSelf={request.isSelfVerification}
|
isSelf={request.isSelfVerification}
|
||||||
/> : <Spinner />;
|
/> : <Spinner />;
|
||||||
|
@ -345,7 +378,7 @@ export default class VerificationPanel extends React.PureComponent {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
_startSAS = async () => {
|
private startSAS = async () => {
|
||||||
this.setState({emojiButtonClicked: true});
|
this.setState({emojiButtonClicked: true});
|
||||||
const verifier = this.props.request.beginKeyVerification(verificationMethods.SAS);
|
const verifier = this.props.request.beginKeyVerification(verificationMethods.SAS);
|
||||||
try {
|
try {
|
||||||
|
@ -355,31 +388,31 @@ export default class VerificationPanel extends React.PureComponent {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
_onSasMatchesClick = () => {
|
private onSasMatchesClick = () => {
|
||||||
this.state.sasEvent.confirm();
|
this.state.sasEvent.confirm();
|
||||||
};
|
};
|
||||||
|
|
||||||
_onSasMismatchesClick = () => {
|
private onSasMismatchesClick = () => {
|
||||||
this.state.sasEvent.mismatch();
|
this.state.sasEvent.mismatch();
|
||||||
};
|
};
|
||||||
|
|
||||||
_updateVerifierState = () => {
|
private updateVerifierState = () => {
|
||||||
const {request} = this.props;
|
const {request} = this.props;
|
||||||
const {sasEvent, reciprocateQREvent} = request.verifier;
|
const {sasEvent, reciprocateQREvent} = request.verifier;
|
||||||
request.verifier.off('show_sas', this._updateVerifierState);
|
request.verifier.off('show_sas', this.updateVerifierState);
|
||||||
request.verifier.off('show_reciprocate_qr', this._updateVerifierState);
|
request.verifier.off('show_reciprocate_qr', this.updateVerifierState);
|
||||||
this.setState({sasEvent, reciprocateQREvent});
|
this.setState({sasEvent, reciprocateQREvent});
|
||||||
};
|
};
|
||||||
|
|
||||||
_onRequestChange = async () => {
|
private onRequestChange = async () => {
|
||||||
const {request} = this.props;
|
const {request} = this.props;
|
||||||
const hadVerifier = this._hasVerifier;
|
const hadVerifier = this.hasVerifier;
|
||||||
this._hasVerifier = !!request.verifier;
|
this.hasVerifier = !!request.verifier;
|
||||||
if (!hadVerifier && this._hasVerifier) {
|
if (!hadVerifier && this.hasVerifier) {
|
||||||
request.verifier.on('show_sas', this._updateVerifierState);
|
request.verifier.on('show_sas', this.updateVerifierState);
|
||||||
request.verifier.on('show_reciprocate_qr', this._updateVerifierState);
|
request.verifier.on('show_reciprocate_qr', this.updateVerifierState);
|
||||||
try {
|
try {
|
||||||
// on the requester side, this is also awaited in _startSAS,
|
// on the requester side, this is also awaited in startSAS,
|
||||||
// but that's ok as verify should return the same promise.
|
// but that's ok as verify should return the same promise.
|
||||||
await request.verifier.verify();
|
await request.verifier.verify();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
@ -390,21 +423,21 @@ export default class VerificationPanel extends React.PureComponent {
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
const {request} = this.props;
|
const {request} = this.props;
|
||||||
request.on("change", this._onRequestChange);
|
request.on("change", this.onRequestChange);
|
||||||
if (request.verifier) {
|
if (request.verifier) {
|
||||||
const {request} = this.props;
|
const {request} = this.props;
|
||||||
const {sasEvent, reciprocateQREvent} = request.verifier;
|
const {sasEvent, reciprocateQREvent} = request.verifier;
|
||||||
this.setState({sasEvent, reciprocateQREvent});
|
this.setState({sasEvent, reciprocateQREvent});
|
||||||
}
|
}
|
||||||
this._onRequestChange();
|
this.onRequestChange();
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
const {request} = this.props;
|
const {request} = this.props;
|
||||||
if (request.verifier) {
|
if (request.verifier) {
|
||||||
request.verifier.off('show_sas', this._updateVerifierState);
|
request.verifier.off('show_sas', this.updateVerifierState);
|
||||||
request.verifier.off('show_reciprocate_qr', this._updateVerifierState);
|
request.verifier.off('show_reciprocate_qr', this.updateVerifierState);
|
||||||
}
|
}
|
||||||
request.off("change", this._onRequestChange);
|
request.off("change", this.onRequestChange);
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue