diff --git a/res/css/_components.scss b/res/css/_components.scss index fe331504f2..c82dedc069 100644 --- a/res/css/_components.scss +++ b/res/css/_components.scss @@ -77,7 +77,6 @@ @import "./views/elements/_Dropdown.scss"; @import "./views/elements/_EditableItemList.scss"; @import "./views/elements/_Field.scss"; -@import "./views/elements/_HexVerify.scss"; @import "./views/elements/_ImageView.scss"; @import "./views/elements/_InlineSpinner.scss"; @import "./views/elements/_ManageIntegsButton.scss"; @@ -156,6 +155,7 @@ @import "./views/settings/tabs/_SecuritySettingsTab.scss"; @import "./views/settings/tabs/_SettingsTab.scss"; @import "./views/settings/tabs/_VoiceSettingsTab.scss"; +@import "./views/verification/_VerificationShowSas.scss"; @import "./views/voip/_CallView.scss"; @import "./views/voip/_IncomingCallbox.scss"; @import "./views/voip/_VideoView.scss"; diff --git a/res/css/structures/_CustomRoomTagPanel.scss b/res/css/structures/_CustomRoomTagPanel.scss index f02421db2c..45961d7be1 100644 --- a/res/css/structures/_CustomRoomTagPanel.scss +++ b/res/css/structures/_CustomRoomTagPanel.scss @@ -21,7 +21,11 @@ limitations under the License. .mx_CustomRoomTagPanel { background-color: $tagpanel-bg-color; - max-height: 40%; + max-height: 40vh; +} + +.mx_CustomRoomTagPanel_scroller { + max-height: inherit; } .mx_CustomRoomTagPanel .mx_AccessibleButton { diff --git a/res/css/views/elements/_HexVerify.scss b/res/css/views/verification/_VerificationShowSas.scss similarity index 78% rename from res/css/views/elements/_HexVerify.scss rename to res/css/views/verification/_VerificationShowSas.scss index 3f3ee4b7ea..32ccf6b0bb 100644 --- a/res/css/views/elements/_HexVerify.scss +++ b/res/css/views/verification/_VerificationShowSas.scss @@ -14,21 +14,9 @@ See the License for the specific language governing permissions and limitations under the License. */ -.mx_HexVerify { +.mx_VerificationShowSas_sas { 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; -} diff --git a/src/MatrixClientPeg.js b/src/MatrixClientPeg.js index 882a913452..f283eb84a5 100644 --- a/src/MatrixClientPeg.js +++ b/src/MatrixClientPeg.js @@ -135,14 +135,7 @@ class MatrixClientPeg { const opts = utils.deepCopy(this.opts); // the react sdk doesn't work without this, so don't allow opts.pendingEventOrdering = "detached"; - - const LAZY_LOADING_FEATURE = "feature_lazyloading"; - if (SettingsStore.isFeatureEnabled(LAZY_LOADING_FEATURE)) { - const userId = this.matrixClient.credentials.userId; - if (phasedRollOutExpiredForUser(userId, LAZY_LOADING_FEATURE, Date.now())) { - opts.lazyLoadMembers = true; - } - } + opts.lazyLoadMembers = true; // Connect the matrix client to the dispatcher MatrixActionCreators.start(this.matrixClient); diff --git a/src/components/views/dialogs/keybackup/RestoreKeyBackupDialog.js b/src/components/views/dialogs/keybackup/RestoreKeyBackupDialog.js index e5b82baa92..712d8d2b4e 100644 --- a/src/components/views/dialogs/keybackup/RestoreKeyBackupDialog.js +++ b/src/components/views/dialogs/keybackup/RestoreKeyBackupDialog.js @@ -19,6 +19,8 @@ import sdk from '../../../../index'; import MatrixClientPeg from '../../../../MatrixClientPeg'; import Modal from '../../../../Modal'; +import { MatrixClient } from 'matrix-js-sdk'; + import { _t } from '../../../../languageHandler'; const RESTORE_TYPE_PASSPHRASE = 0; @@ -88,7 +90,7 @@ export default React.createClass({ }); try { const recoverInfo = await MatrixClientPeg.get().restoreKeyBackupWithPassword( - this.state.passPhrase, undefined, undefined, this.state.backupInfo.version, + this.state.passPhrase, undefined, undefined, this.state.backupInfo, ); this.setState({ loading: false, @@ -107,11 +109,11 @@ export default React.createClass({ this.setState({ loading: true, restoreError: null, - restoreType: RESTORE_TYPE_PASSPHRASE, + restoreType: RESTORE_TYPE_RECOVERYKEY, }); try { const recoverInfo = await MatrixClientPeg.get().restoreKeyBackupWithRecoveryKey( - this.state.recoveryKey, undefined, undefined, this.state.backupInfo.version, + this.state.recoveryKey, undefined, undefined, this.state.backupInfo, ); this.setState({ loading: false, @@ -185,32 +187,31 @@ export default React.createClass({ title = _t("Error"); content = _t("Unable to load backup status"); } else if (this.state.restoreError) { - title = _t("Error"); - content = _t("Unable to restore backup"); + if (this.state.restoreError.errcode === MatrixClient.RESTORE_BACKUP_ERROR_BAD_KEY) { + if (this.state.restoreType === RESTORE_TYPE_RECOVERYKEY) { + title = _t("Recovery Key Mismatch"); + content =
+

{_t( + "Backup could not be decrypted with this key: " + + "please verify that you entered the correct recovery key.", + )}

+
; + } else { + title = _t("Incorrect Recovery Passphrase"); + content =
+

{_t( + "Backup could not be decrypted with this passphrase: " + + "please verify that you entered the correct recovery passphrase.", + )}

+
; + } + } else { + title = _t("Error"); + content = _t("Unable to restore backup"); + } } else if (this.state.backupInfo === null) { title = _t("Error"); content = _t("No backup found!"); - } else if ( - this.state.recoverInfo && - this.state.recoverInfo.imported === 0 && - this.state.recoverInfo.total > 0 - ) { - title = _t("Error Restoring Backup"); - if (this.state.restoreType === RESTORE_TYPE_RECOVERYKEY) { - content =
-

{_t( - "Backup could not be decrypted with this key: " + - "please verify that you entered the correct recovery key.", - )}

-
; - } else { - content =
-

{_t( - "Backup could not be decrypted with this passphrase: " + - "please verify that you entered the correct recovery passphrase.", - )}

-
; - } } else if (this.state.recoverInfo) { title = _t("Backup Restored"); let failedToDecrypt; diff --git a/src/components/views/elements/HexVerify.js b/src/components/views/elements/HexVerify.js deleted file mode 100644 index 86ead3adc1..0000000000 --- a/src/components/views/elements/HexVerify.js +++ /dev/null @@ -1,103 +0,0 @@ -/* -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 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 - {this.props.text} - ; - } -} - -/* - * 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(); - } - return
- {pairs} -
; - } -} diff --git a/src/components/views/settings/KeyBackupPanel.js b/src/components/views/settings/KeyBackupPanel.js index 15856a75f3..cbbca42927 100644 --- a/src/components/views/settings/KeyBackupPanel.js +++ b/src/components/views/settings/KeyBackupPanel.js @@ -250,19 +250,26 @@ export default class KeyBackupPanel extends React.PureComponent { backupSigStatuses = _t("Backup is not signed by any of your devices"); } + let trustedLocally; + if (this.state.backupSigStatus.trusted_locally) { + trustedLocally = _t("This backup is trusted because it has been restored on this device"); + } + return
- {_t("Backup version: ")}{this.state.backupInfo.version}
- {_t("Algorithm: ")}{this.state.backupInfo.algorithm}
- {clientBackupStatus}
+
{_t("Backup version: ")}{this.state.backupInfo.version}
+
{_t("Algorithm: ")}{this.state.backupInfo.algorithm}
+
{clientBackupStatus}
{uploadStatus} -
{backupSigStatuses}

-
- - { _t("Restore backup") } -     - - { _t("Delete backup") } - +
{backupSigStatuses}
+
{trustedLocally}
+

+ + { _t("Restore backup") } +     + + { _t("Delete backup") } + +

; } else { return
diff --git a/src/components/views/settings/tabs/LabsSettingsTab.js b/src/components/views/settings/tabs/LabsSettingsTab.js index fc64c1bd04..e06f87460b 100644 --- a/src/components/views/settings/tabs/LabsSettingsTab.js +++ b/src/components/views/settings/tabs/LabsSettingsTab.js @@ -18,9 +18,7 @@ import React from 'react'; import {_t} from "../../../../languageHandler"; import PropTypes from "prop-types"; import SettingsStore, {SettingLevel} from "../../../../settings/SettingsStore"; -import MatrixClientPeg from "../../../../MatrixClientPeg"; import LabelledToggleSwitch from "../../elements/LabelledToggleSwitch"; -const Modal = require("../../../../Modal"); const sdk = require("../../../../index"); export class LabsSettingToggle extends React.Component { @@ -28,38 +26,7 @@ export class LabsSettingToggle extends React.Component { featureId: PropTypes.string.isRequired, }; - async _onLazyLoadChanging(enabling) { - // don't prevent turning LL off when not supported - if (enabling) { - const supported = await MatrixClientPeg.get().doesServerSupportLazyLoading(); - if (!supported) { - await new Promise((resolve) => { - const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog"); - Modal.createDialog(QuestionDialog, { - title: _t("Lazy loading members not supported"), - description: -
- { _t("Lazy loading is not supported by your " + - "current homeserver.") } -
, - button: _t("OK"), - onFinished: resolve, - }); - }); - return false; - } - } - return true; - } - _onChange = async (checked) => { - if (this.props.featureId === "feature_lazyloading") { - const confirmed = await this._onLazyLoadChanging(checked); - if (!confirmed) { - return; - } - } - await SettingsStore.setFeatureEnabled(this.props.featureId, checked); this.forceUpdate(); }; diff --git a/src/components/views/verification/VerificationShowSas.js b/src/components/views/verification/VerificationShowSas.js index 6f3209989e..0224571d9e 100644 --- a/src/components/views/verification/VerificationShowSas.js +++ b/src/components/views/verification/VerificationShowSas.js @@ -28,19 +28,11 @@ export default class VerificationShowSas extends React.Component { constructor() { super(); - this.state = { - sasVerified: false, - }; - } - - _onVerifiedStateChange = (newVal) => { - this.setState({sasVerified: newVal}); } render() { const DialogButtons = sdk.getComponent('views.elements.DialogButtons'); - const HexVerify = sdk.getComponent('views.elements.HexVerify'); - return
+ return

{_t( "Verify this user by confirming the following number appears on their screen.", )}

@@ -48,15 +40,11 @@ export default class VerificationShowSas extends React.Component { "For maximum security, we recommend you do this in person or use another " + "trusted means of communication.", )}

- -

{_t( - "To continue, click on each pair to confirm it's correct.", - )}

+
+ {this.props.sas} +
diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index a5b04f1981..d612ae78ef 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -265,7 +265,6 @@ "Message Pinning": "Message Pinning", "Custom user status messages": "Custom user status messages", "Group & filter rooms by custom tags (refresh to apply changes)": "Group & filter rooms by custom tags (refresh to apply changes)", - "Increase performance by only loading room members on first view": "Increase performance by only loading room members on first view", "Backup of encryption keys to server": "Backup of encryption keys to server", "Render simple counters in room header": "Render simple counters in room header", "Two-way device verification using short text": "Two-way device verification using short text", @@ -386,6 +385,7 @@ "Backup has an invalid signature from unverified device ": "Backup has an invalid signature from unverified device ", "Verify...": "Verify...", "Backup is not signed by any of your devices": "Backup is not signed by any of your devices", + "This backup is trusted because it has been restored on this device": "This backup is trusted because it has been restored on this device", "Backup version: ": "Backup version: ", "Algorithm: ": "Algorithm: ", "Restore backup": "Restore backup", @@ -477,8 +477,6 @@ "Identity Server is": "Identity Server is", "Access Token:": "Access Token:", "click to reveal": "click to reveal", - "Lazy loading members not supported": "Lazy loading members not supported", - "Lazy loading is not supported by your current homeserver.": "Lazy loading is not supported by your current homeserver.", "Labs": "Labs", "Notifications": "Notifications", "Start automatically after system login": "Start automatically after system login", @@ -1096,11 +1094,12 @@ "\"%(RoomName)s\" contains devices that you haven't seen before.": "\"%(RoomName)s\" contains devices that you haven't seen before.", "Unknown devices": "Unknown devices", "Unable to load backup status": "Unable to load backup status", + "Recovery Key Mismatch": "Recovery Key Mismatch", + "Backup could not be decrypted with this key: please verify that you entered the correct recovery key.": "Backup could not be decrypted with this key: please verify that you entered the correct recovery key.", + "Incorrect Recovery Passphrase": "Incorrect Recovery Passphrase", + "Backup could not be decrypted with this passphrase: please verify that you entered the correct recovery passphrase.": "Backup could not be decrypted with this passphrase: please verify that you entered the correct recovery passphrase.", "Unable to restore backup": "Unable to restore backup", "No backup found!": "No backup found!", - "Error Restoring Backup": "Error Restoring Backup", - "Backup could not be decrypted with this key: please verify that you entered the correct recovery key.": "Backup could not be decrypted with this key: please verify that you entered the correct recovery key.", - "Backup could not be decrypted with this passphrase: please verify that you entered the correct recovery passphrase.": "Backup could not be decrypted with this passphrase: please verify that you entered the correct recovery passphrase.", "Backup Restored": "Backup Restored", "Failed to decrypt %(failedCount)s sessions!": "Failed to decrypt %(failedCount)s sessions!", "Restored %(sessionCount)s session keys": "Restored %(sessionCount)s session keys", diff --git a/src/settings/Settings.js b/src/settings/Settings.js index d9363315f5..02c2bad14b 100644 --- a/src/settings/Settings.js +++ b/src/settings/Settings.js @@ -21,7 +21,6 @@ import { NotificationBodyEnabledController, NotificationsEnabledController, } from "./controllers/NotificationControllers"; -import LazyLoadingController from "./controllers/LazyLoadingController"; import CustomStatusController from "./controllers/CustomStatusController"; // These are just a bunch of helper arrays to avoid copy/pasting a bunch of times @@ -106,13 +105,6 @@ export const SETTINGS = { supportedLevels: LEVELS_FEATURE, default: false, }, - "feature_lazyloading": { - isFeature: true, - displayName: _td("Increase performance by only loading room members on first view"), - supportedLevels: LEVELS_FEATURE, - controller: new LazyLoadingController(), - default: true, - }, "feature_keybackup": { isFeature: true, displayName: _td("Backup of encryption keys to server"), diff --git a/src/settings/controllers/LazyLoadingController.js b/src/settings/controllers/LazyLoadingController.js deleted file mode 100644 index 90f095c9ca..0000000000 --- a/src/settings/controllers/LazyLoadingController.js +++ /dev/null @@ -1,29 +0,0 @@ -/* -Copyright 2018 New Vector - -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 SettingController from "./SettingController"; -import MatrixClientPeg from "../../MatrixClientPeg"; -import PlatformPeg from "../../PlatformPeg"; - -export default class LazyLoadingController extends SettingController { - async onChange(level, roomId, newValue) { - if (!PlatformPeg.get()) return; - - MatrixClientPeg.get().stopClient(); - await MatrixClientPeg.get().store.deleteAllData(); - PlatformPeg.get().reload(); - } -}