diff --git a/src/components/views/right_panel/VerificationPanel.js b/src/components/views/right_panel/VerificationPanel.js index 08c3935a2c..262d1c873b 100644 --- a/src/components/views/right_panel/VerificationPanel.js +++ b/src/components/views/right_panel/VerificationPanel.js @@ -19,6 +19,8 @@ import PropTypes from "prop-types"; import * as sdk from '../../../index'; import {verificationMethods} from 'matrix-js-sdk/src/crypto'; +import {SCAN_QR_CODE_METHOD} from "matrix-js-sdk/src/crypto/verification/QRCode"; + import VerificationQRCode from "../elements/crypto/VerificationQRCode"; import {_t} from "../../../languageHandler"; import E2EIcon from "../rooms/E2EIcon"; @@ -54,7 +56,9 @@ export default class VerificationPanel extends React.PureComponent { qrCodeProps: null, // generated by the VerificationQRCode component itself }; this._hasVerifier = false; - this._generateQRCodeProps(props.request); + if (this.props.request.otherPartySupportsMethod(SCAN_QR_CODE_METHOD)) { + this._generateQRCodeProps(props.request); + } } async _generateQRCodeProps(verificationRequest: VerificationRequest) { @@ -67,59 +71,60 @@ export default class VerificationPanel extends React.PureComponent { } renderQRPhase(pending) { - const {member} = this.props; + const {member, request} = this.props; + const showSAS = request.methods.includes(verificationMethods.SAS); + const showQR = this.props.request.otherPartySupportsMethod(SCAN_QR_CODE_METHOD); const AccessibleButton = sdk.getComponent('elements.AccessibleButton'); + const noCommonMethodError = !showSAS && !showQR ? + <p>{_t("The session you are trying to verify doesn't support scanning a QR code or emoji verification, which is what Riot supports. Try with a different client.")}</p> : + null; + if (this.props.layout === 'dialog') { // HACK: This is a terrible idea. - let qrCode = <div className='mx_VerificationPanel_QRPhase_noQR'><Spinner /></div>; - if (this.state.qrCodeProps) { - qrCode = <VerificationQRCode {...this.state.qrCodeProps} />; + let qrBlock; + let sasBlock; + if (showQR) { + let qrCode; + if (this.state.qrCodeProps) { + qrCode = <VerificationQRCode {...this.state.qrCodeProps} />; + } else { + qrCode = <div className='mx_VerificationPanel_QRPhase_noQR'><Spinner /></div>; + } + qrBlock = + <div className='mx_VerificationPanel_QRPhase_startOption'> + <p>{_t("Scan this unique code")}</p> + {qrCode} + </div>; } + if (showSAS) { + sasBlock = + <div className='mx_VerificationPanel_QRPhase_startOption'> + <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> + <AccessibleButton disabled={this.state.emojiButtonClicked} onClick={this._startSAS} kind='primary'> + {_t("Start")} + </AccessibleButton> + </div>; + } + const or = qrBlock && sasBlock ? + <div className='mx_VerificationPanel_QRPhase_betweenText'>{_t("or")}</div> : null; return ( <div> {_t("Verify this session by completing one of the following:")} <div className='mx_VerificationPanel_QRPhase_startOptions'> - <div className='mx_VerificationPanel_QRPhase_startOption'> - <p>{_t("Scan this unique code")}</p> - {qrCode} - </div> - <div className='mx_VerificationPanel_QRPhase_betweenText'>{_t("or")}</div> - <div className='mx_VerificationPanel_QRPhase_startOption'> - <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> - <AccessibleButton disabled={this.state.emojiButtonClicked} onClick={this._startSAS} kind='primary'> - {_t("Start")} - </AccessibleButton> - </div> + {qrBlock} + {or} + {sasBlock} + {noCommonMethodError} </div> </div> ); } - let button; - if (pending) { - button = <Spinner />; - } else { - const disabled = this.state.emojiButtonClicked; - button = ( - <AccessibleButton disabled={disabled} kind="primary" className="mx_UserInfo_wideButton" onClick={this._startSAS}> - {_t("Verify by emoji")} - </AccessibleButton> - ); - } - - if (!this.state.qrCodeProps) { - return <div className="mx_UserInfo_container"> - <h3>{_t("Verify by emoji")}</h3> - <p>{_t("Verify by comparing unique emoji.")}</p> - { button } - </div>; - } - - // TODO: add way to open camera to scan a QR code - return <React.Fragment> - <div className="mx_UserInfo_container"> + let qrBlock; + if (this.state.qrCodeProps) { + qrBlock = <div className="mx_UserInfo_container"> <h3>{_t("Verify by scanning")}</h3> <p>{_t("Ask %(displayName)s to scan your code:", { displayName: member.displayName || member.name || member.userId, @@ -128,14 +133,41 @@ export default class VerificationPanel extends React.PureComponent { <div className="mx_VerificationPanel_qrCode"> <VerificationQRCode {...this.state.qrCodeProps} /> </div> - </div> + </div>; + } - <div className="mx_UserInfo_container"> + let sasBlock; + if (showSAS) { + let button; + if (pending) { + button = <Spinner />; + } else { + const disabled = this.state.emojiButtonClicked; + button = ( + <AccessibleButton disabled={disabled} kind="primary" className="mx_UserInfo_wideButton" onClick={this._startSAS}> + {_t("Verify by emoji")} + </AccessibleButton> + ); + } + const sasLabel = this.state.qrCodeProps ? + _t("If you can't scan the code above, verify by comparing unique emoji.") : + _t("Verify by comparing unique emoji."); + sasBlock = <div className="mx_UserInfo_container"> <h3>{_t("Verify by emoji")}</h3> - <p>{_t("If you can't scan the code above, verify by comparing unique emoji.")}</p> - + <p>{sasLabel}</p> { button } - </div> + </div>; + } + + const noCommonMethodBlock = noCommonMethodError ? + <div className="mx_UserInfo_container">{noCommonMethodError}</div> : + null; + + // TODO: add way to open camera to scan a QR code + return <React.Fragment> + {qrBlock} + {sasBlock} + {noCommonMethodBlock} </React.Fragment>; } diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 7a8642be95..00d8d426d0 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -1197,11 +1197,12 @@ "This client does not support end-to-end encryption.": "This client does not support end-to-end encryption.", "Messages in this room are not end-to-end encrypted.": "Messages in this room are not end-to-end encrypted.", "Security": "Security", - "Verify by emoji": "Verify by emoji", - "Verify by comparing unique emoji.": "Verify by comparing unique emoji.", + "The session you are trying to verify doesn't support scanning a QR code or emoji verification, which is what Riot supports. Try with a different client.": "The session you are trying to verify doesn't support scanning a QR code or emoji verification, which is what Riot supports. Try with a different client.", "Verify by scanning": "Verify by scanning", "Ask %(displayName)s to scan your code:": "Ask %(displayName)s to scan your code:", + "Verify by emoji": "Verify by emoji", "If you can't scan the code above, verify by comparing unique emoji.": "If you can't scan the code above, verify by comparing unique emoji.", + "Verify by comparing unique emoji.": "Verify by comparing unique emoji.", "You've successfully verified %(displayName)s!": "You've successfully verified %(displayName)s!", "Got it": "Got it", "Verification timed out. Start verification again from their profile.": "Verification timed out. Start verification again from their profile.",