From b293ef067442c157b39760fb7506b6fcf3c770b7 Mon Sep 17 00:00:00 2001 From: "J. Ryan Stinnett" Date: Fri, 14 Aug 2020 13:01:43 +0100 Subject: [PATCH 01/10] Check for .well-known E2EE settings under new key This adds an extra check for `.well-known` E2EE settings under the key `im.vector.e2ee`. The older key `im.vector.riot.e2ee` is kept for historical compatibility. Part of https://github.com/vector-im/element-web/issues/14954 --- src/createRoom.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/createRoom.ts b/src/createRoom.ts index 23a664a4c4..b9f30476e4 100644 --- a/src/createRoom.ts +++ b/src/createRoom.ts @@ -27,7 +27,8 @@ import * as Rooms from "./Rooms"; import DMRoomMap from "./utils/DMRoomMap"; import {getAddressType} from "./UserAddress"; -const E2EE_WK_KEY = "im.vector.riot.e2ee"; +const E2EE_WK_KEY = "im.vector.e2ee"; +const E2EE_WK_KEY_DEPRECATED = "im.vector.riot.e2ee"; // we define a number of interfaces which take their names from the js-sdk /* eslint-disable camelcase */ @@ -300,6 +301,10 @@ export function privateShouldBeEncrypted() { const defaultDisabled = clientWellKnown[E2EE_WK_KEY]["default"] === false; return !defaultDisabled; } + if (clientWellKnown && clientWellKnown[E2EE_WK_KEY_DEPRECATED]) { + const defaultDisabled = clientWellKnown[E2EE_WK_KEY_DEPRECATED]["default"] === false; + return !defaultDisabled; + } return true; } From 2b0865e89c3377ac66035e9c4873757614417835 Mon Sep 17 00:00:00 2001 From: "J. Ryan Stinnett" Date: Fri, 14 Aug 2020 13:27:12 +0100 Subject: [PATCH 02/10] Move E2EE well-known access to utils --- src/createRoom.ts | 17 +++++------------ src/utils/WellKnownUtils.ts | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 12 deletions(-) create mode 100644 src/utils/WellKnownUtils.ts diff --git a/src/createRoom.ts b/src/createRoom.ts index b9f30476e4..78d0cf1356 100644 --- a/src/createRoom.ts +++ b/src/createRoom.ts @@ -26,9 +26,7 @@ import dis from "./dispatcher/dispatcher"; import * as Rooms from "./Rooms"; import DMRoomMap from "./utils/DMRoomMap"; import {getAddressType} from "./UserAddress"; - -const E2EE_WK_KEY = "im.vector.e2ee"; -const E2EE_WK_KEY_DEPRECATED = "im.vector.riot.e2ee"; +import { getE2EEWellKnown } from "./utils/WellKnownUtils"; // we define a number of interfaces which take their names from the js-sdk /* eslint-disable camelcase */ @@ -295,16 +293,11 @@ export async function ensureDMExists(client: MatrixClient, userId: string): Prom return roomId; } -export function privateShouldBeEncrypted() { - const clientWellKnown = MatrixClientPeg.get().getClientWellKnown(); - if (clientWellKnown && clientWellKnown[E2EE_WK_KEY]) { - const defaultDisabled = clientWellKnown[E2EE_WK_KEY]["default"] === false; +export function privateShouldBeEncrypted(): boolean { + const e2eeWellKnown = getE2EEWellKnown(); + if (e2eeWellKnown) { + const defaultDisabled = e2eeWellKnown["default"] === false; return !defaultDisabled; } - if (clientWellKnown && clientWellKnown[E2EE_WK_KEY_DEPRECATED]) { - const defaultDisabled = clientWellKnown[E2EE_WK_KEY_DEPRECATED]["default"] === false; - return !defaultDisabled; - } - return true; } diff --git a/src/utils/WellKnownUtils.ts b/src/utils/WellKnownUtils.ts new file mode 100644 index 0000000000..2712570396 --- /dev/null +++ b/src/utils/WellKnownUtils.ts @@ -0,0 +1,35 @@ +/* +Copyright 2020 The Matrix.org Foundation C.I.C. + +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 {MatrixClientPeg} from '../MatrixClientPeg'; + +const E2EE_WK_KEY = "im.vector.e2ee"; +const E2EE_WK_KEY_DEPRECATED = "im.vector.riot.e2ee"; + +export interface IE2EEWellKnown { + default?: boolean; +} + +export function getE2EEWellKnown(): IE2EEWellKnown { + const clientWellKnown = MatrixClientPeg.get().getClientWellKnown(); + if (clientWellKnown && clientWellKnown[E2EE_WK_KEY]) { + return clientWellKnown[E2EE_WK_KEY]; + } + if (clientWellKnown && clientWellKnown[E2EE_WK_KEY_DEPRECATED]) { + return clientWellKnown[E2EE_WK_KEY_DEPRECATED] + } + return null; +} From 941cbc47c8f6e656a30801e6cb2407b5596780e4 Mon Sep 17 00:00:00 2001 From: "J. Ryan Stinnett" Date: Fri, 14 Aug 2020 16:40:46 +0100 Subject: [PATCH 03/10] Fix casing of Secure Backup to match designs --- .../views/dialogs/secretstorage/CreateSecretStorageDialog.js | 2 +- src/i18n/strings/en_EN.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/async-components/views/dialogs/secretstorage/CreateSecretStorageDialog.js b/src/async-components/views/dialogs/secretstorage/CreateSecretStorageDialog.js index 53b3033330..bb231c24a0 100644 --- a/src/async-components/views/dialogs/secretstorage/CreateSecretStorageDialog.js +++ b/src/async-components/views/dialogs/secretstorage/CreateSecretStorageDialog.js @@ -714,7 +714,7 @@ export default class CreateSecretStorageDialog extends React.PureComponent { _titleForPhase(phase) { switch (phase) { case PHASE_CHOOSE_KEY_PASSPHRASE: - return _t('Set up Secure backup'); + return _t('Set up Secure Backup'); case PHASE_MIGRATE: return _t('Upgrade your encryption'); case PHASE_PASSPHRASE: diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 8bfc3ed703..51132179cf 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -2241,7 +2241,7 @@ "Retry": "Retry", "If you cancel now, you may lose encrypted messages & data if you lose access to your logins.": "If you cancel now, you may lose encrypted messages & data if you lose access to your logins.", "You can also set up Secure Backup & manage your keys in Settings.": "You can also set up Secure Backup & manage your keys in Settings.", - "Set up Secure backup": "Set up Secure backup", + "Set up Secure Backup": "Set up Secure Backup", "Upgrade your encryption": "Upgrade your encryption", "Set a Security Phrase": "Set a Security Phrase", "Confirm Security Phrase": "Confirm Security Phrase", From 1932505d3b6cbab5a5035f61d3eae73e91a4c23f Mon Sep 17 00:00:00 2001 From: "J. Ryan Stinnett" Date: Fri, 14 Aug 2020 18:06:35 +0100 Subject: [PATCH 04/10] Enforce Secure Backup completion when requested by HS This removes all buttons to escape the Secure Backup setup flow when the matching `.well-known` setting is set by homeserver. Part of https://github.com/vector-im/element-web/issues/14954 --- src/CrossSigningManager.js | 14 +++++++++++++- .../secretstorage/CreateSecretStorageDialog.js | 9 +++++---- src/utils/WellKnownUtils.ts | 5 +++++ 3 files changed, 23 insertions(+), 5 deletions(-) diff --git a/src/CrossSigningManager.js b/src/CrossSigningManager.js index 676c41d7d7..46f0284776 100644 --- a/src/CrossSigningManager.js +++ b/src/CrossSigningManager.js @@ -21,6 +21,7 @@ import { deriveKey } from 'matrix-js-sdk/src/crypto/key_passphrase'; import { decodeRecoveryKey } from 'matrix-js-sdk/src/crypto/recoverykey'; import { _t } from './languageHandler'; import {encodeBase64} from "matrix-js-sdk/src/crypto/olmlib"; +import { isSecureBackupRequired } from './utils/WellKnownUtils'; // This stores the secret storage private keys in memory for the JS SDK. This is // only meant to act as a cache to avoid prompting the user multiple times @@ -208,7 +209,18 @@ export async function accessSecretStorage(func = async () => { }, forceReset = f { force: forceReset, }, - null, /* priority = */ false, /* static = */ true, + null, + /* priority = */ false, + /* static = */ true, + /* options = */ { + onBeforeClose(reason) { + // If Secure Backup is required, you cannot leave the modal. + if (reason === "backgroundClick") { + return !isSecureBackupRequired(); + } + return true; + }, + }, ); const [confirmed] = await finished; if (!confirmed) { diff --git a/src/async-components/views/dialogs/secretstorage/CreateSecretStorageDialog.js b/src/async-components/views/dialogs/secretstorage/CreateSecretStorageDialog.js index bb231c24a0..47faa35df4 100644 --- a/src/async-components/views/dialogs/secretstorage/CreateSecretStorageDialog.js +++ b/src/async-components/views/dialogs/secretstorage/CreateSecretStorageDialog.js @@ -30,6 +30,7 @@ import StyledRadioButton from '../../../../components/views/elements/StyledRadio import AccessibleButton from "../../../../components/views/elements/AccessibleButton"; import DialogButtons from "../../../../components/views/elements/DialogButtons"; import InlineSpinner from "../../../../components/views/elements/InlineSpinner"; +import { isSecureBackupRequired } from '../../../../utils/WellKnownUtils'; const PHASE_LOADING = 0; const PHASE_LOADERROR = 1; @@ -85,8 +86,8 @@ export default class CreateSecretStorageDialog extends React.PureComponent { canUploadKeysWithPasswordOnly: null, accountPassword: props.accountPassword || "", accountPasswordCorrect: null, - passPhraseKeySelected: CREATE_STORAGE_OPTION_KEY, + canSkip: !isSecureBackupRequired(), }; this._passphraseField = createRef(); @@ -470,7 +471,7 @@ export default class CreateSecretStorageDialog extends React.PureComponent { primaryButton={_t("Continue")} onPrimaryButtonClick={this._onChooseKeyPassphraseFormSubmit} onCancel={this._onCancelClick} - hasCancel={true} + hasCancel={this.state.canSkip} /> ; } @@ -687,7 +688,7 @@ export default class CreateSecretStorageDialog extends React.PureComponent {
@@ -742,7 +743,7 @@ export default class CreateSecretStorageDialog extends React.PureComponent {
diff --git a/src/utils/WellKnownUtils.ts b/src/utils/WellKnownUtils.ts index 2712570396..f16acdb408 100644 --- a/src/utils/WellKnownUtils.ts +++ b/src/utils/WellKnownUtils.ts @@ -33,3 +33,8 @@ export function getE2EEWellKnown(): IE2EEWellKnown { } return null; } + +export function isSecureBackupRequired(): boolean { + const wellKnown = getE2EEWellKnown(); + return wellKnown && wellKnown["secure_backup_required"] === true; +} From fed7ebb6bc3a9549b62cedaa94041d220a7c5605 Mon Sep 17 00:00:00 2001 From: "J. Ryan Stinnett" Date: Mon, 17 Aug 2020 16:00:30 +0100 Subject: [PATCH 05/10] Hide Delete Backup button when Secure Backup required If Secure Backup is required by the HS admin, then this hides the Delete Backup button in Settings to ensure everyone keeps their backup per policy. Part of https://github.com/vector-im/element-web/issues/14954 --- src/components/views/settings/KeyBackupPanel.js | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/components/views/settings/KeyBackupPanel.js b/src/components/views/settings/KeyBackupPanel.js index a7a2c768db..8a74276f58 100644 --- a/src/components/views/settings/KeyBackupPanel.js +++ b/src/components/views/settings/KeyBackupPanel.js @@ -21,6 +21,7 @@ import * as sdk from '../../../index'; import {MatrixClientPeg} from '../../../MatrixClientPeg'; import { _t } from '../../../languageHandler'; import Modal from '../../../Modal'; +import { isSecureBackupRequired } from '../../../utils/WellKnownUtils'; export default class KeyBackupPanel extends React.PureComponent { constructor(props) { @@ -315,14 +316,19 @@ export default class KeyBackupPanel extends React.PureComponent { trustedLocally = _t("This backup is trusted because it has been restored on this session"); } + let deleteBackupButton; + if (!isSecureBackupRequired()) { + deleteBackupButton = + {_t("Delete Backup")} + ; + } + const buttonRow = (
{restoreButtonCaption}     - - {_t("Delete Backup")} - + {deleteBackupButton}
); From e8e691b746b2c8e4b6573c6407d6caec09a69db1 Mon Sep 17 00:00:00 2001 From: "J. Ryan Stinnett" Date: Wed, 19 Aug 2020 13:28:03 +0100 Subject: [PATCH 06/10] Avoid adding setup toast in the middle of setup This improves the experience of going through secret storage setup / reset flows by avoiding intermittent toasts that appear and disappear in the middle of the operation. --- src/CrossSigningManager.js | 11 +++++++++++ src/DeviceListener.ts | 6 +++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/CrossSigningManager.js b/src/CrossSigningManager.js index 46f0284776..da09a436e9 100644 --- a/src/CrossSigningManager.js +++ b/src/CrossSigningManager.js @@ -35,6 +35,17 @@ function isCachingAllowed() { return secretStorageBeingAccessed; } +/** + * This can be used by other components to check if secret storage access is in + * progress, so that we can e.g. avoid intermittently showing toasts during + * secret storage setup. + * + * @returns {bool} + */ +export function isSecretStorageBeingAccessed() { + return secretStorageBeingAccessed; +} + export class AccessCancelledError extends Error { constructor() { super("Secret storage access canceled"); diff --git a/src/DeviceListener.ts b/src/DeviceListener.ts index a37521118f..aa9580834f 100644 --- a/src/DeviceListener.ts +++ b/src/DeviceListener.ts @@ -28,7 +28,8 @@ import { hideToast as hideUnverifiedSessionsToast, showToast as showUnverifiedSessionsToast, } from "./toasts/UnverifiedSessionToast"; -import {privateShouldBeEncrypted} from "./createRoom"; +import { privateShouldBeEncrypted } from "./createRoom"; +import { isSecretStorageBeingAccessed } from "./CrossSigningManager"; const KEY_BACKUP_POLL_INTERVAL = 5 * 60 * 1000; @@ -170,6 +171,9 @@ export default class DeviceListener { } private shouldShowSetupEncryptionToast() { + // If we're in the middle of a secret storage operation, we're likely + // modifying the state involved here, so don't add new toasts to setup. + if (isSecretStorageBeingAccessed()) return false; // In a default configuration, show the toasts. If the well-known config causes e2ee default to be false // then do not show the toasts until user is in at least one encrypted room. if (privateShouldBeEncrypted()) return true; From e56a61ec68a5baf63295ac22fd95697324f53620 Mon Sep 17 00:00:00 2001 From: "J. Ryan Stinnett" Date: Wed, 19 Aug 2020 16:13:29 +0100 Subject: [PATCH 07/10] Invoke Secure Backup flow inside the app when requested by HS If the Secure Backup required mode is set the client `.well-known` file, then this will ensure that everyone already inside the app is required to complete setup matching that policy. Fixes https://github.com/vector-im/element-web/issues/14954 --- src/@types/global.d.ts | 2 ++ src/DeviceListener.ts | 27 ++++++++++++++++++++++-- src/components/structures/MatrixChat.tsx | 7 ++++++ src/utils/WellKnownUtils.ts | 8 +++++++ 4 files changed, 42 insertions(+), 2 deletions(-) diff --git a/src/@types/global.d.ts b/src/@types/global.d.ts index 86ee995a13..84340d8219 100644 --- a/src/@types/global.d.ts +++ b/src/@types/global.d.ts @@ -27,10 +27,12 @@ import {ModalManager} from "../Modal"; import SettingsStore from "../settings/SettingsStore"; import {ActiveRoomObserver} from "../ActiveRoomObserver"; import {Notifier} from "../Notifier"; +import type {Renderer} from "react-dom"; declare global { interface Window { Modernizr: ModernizrStatic; + matrixChat: ReturnType; mxMatrixClientPeg: IMatrixClientPeg; Olm: { init: () => Promise; diff --git a/src/DeviceListener.ts b/src/DeviceListener.ts index aa9580834f..41daa74376 100644 --- a/src/DeviceListener.ts +++ b/src/DeviceListener.ts @@ -15,6 +15,7 @@ limitations under the License. */ import {MatrixClientPeg} from './MatrixClientPeg'; +import dis from "./dispatcher/dispatcher"; import { hideToast as hideBulkUnverifiedSessionsToast, showToast as showBulkUnverifiedSessionsToast, @@ -29,11 +30,15 @@ import { showToast as showUnverifiedSessionsToast, } from "./toasts/UnverifiedSessionToast"; import { privateShouldBeEncrypted } from "./createRoom"; -import { isSecretStorageBeingAccessed } from "./CrossSigningManager"; +import { isSecretStorageBeingAccessed, accessSecretStorage } from "./CrossSigningManager"; +import { ensureClientWellKnown, isSecureBackupRequired } from './utils/WellKnownUtils'; +import { isLoggedIn } from './components/structures/MatrixChat'; + const KEY_BACKUP_POLL_INTERVAL = 5 * 60 * 1000; export default class DeviceListener { + private dispatcherRef: string; // device IDs for which the user has dismissed the verify toast ('Later') private dismissed = new Set(); // has the user dismissed any of the various nag toasts to setup encryption on this device? @@ -61,6 +66,7 @@ export default class DeviceListener { MatrixClientPeg.get().on('crossSigning.keysChanged', this._onCrossSingingKeysChanged); MatrixClientPeg.get().on('accountData', this._onAccountData); MatrixClientPeg.get().on('sync', this._onSync); + this.dispatcherRef = dis.register(this._onAction); this._recheck(); } @@ -74,6 +80,10 @@ export default class DeviceListener { MatrixClientPeg.get().removeListener('accountData', this._onAccountData); MatrixClientPeg.get().removeListener('sync', this._onSync); } + if (this.dispatcherRef) { + dis.unregister(this.dispatcherRef); + this.dispatcherRef = null; + } this.dismissed.clear(); this.dismissedThisDeviceToast = false; this.keyBackupInfo = null; @@ -159,6 +169,11 @@ export default class DeviceListener { if (state === 'PREPARED' && prevState === null) this._recheck(); }; + _onAction = ({ action }) => { + if (action !== "on_logged_in") return; + this._recheck(); + }; + // The server doesn't tell us when key backup is set up, so we poll // & cache the result async _getKeyBackupInfo() { @@ -211,7 +226,15 @@ export default class DeviceListener { showSetupEncryptionToast(SetupKind.UPGRADE_ENCRYPTION); } else { // No cross-signing or key backup on account (set up encryption) - showSetupEncryptionToast(SetupKind.SET_UP_ENCRYPTION); + await ensureClientWellKnown(); + if (isSecureBackupRequired() && isLoggedIn()) { + // If we're meant to set up, and Secure Backup is required, + // trigger the flow directly without a toast once logged in. + hideSetupEncryptionToast(); + accessSecretStorage(); + } else { + showSetupEncryptionToast(SetupKind.SET_UP_ENCRYPTION); + } } } } diff --git a/src/components/structures/MatrixChat.tsx b/src/components/structures/MatrixChat.tsx index ce96847d28..9929cc523e 100644 --- a/src/components/structures/MatrixChat.tsx +++ b/src/components/structures/MatrixChat.tsx @@ -2085,3 +2085,10 @@ export default class MatrixChat extends React.PureComponent { ; } } + +export function isLoggedIn(): boolean { + // JRS: Maybe we should move the step that writes this to the window out of + // `element-web` and into this file? + const app = window.matrixChat; + return app && (app as MatrixChat).state.view === Views.LOGGED_IN; +} diff --git a/src/utils/WellKnownUtils.ts b/src/utils/WellKnownUtils.ts index f16acdb408..1fe28f2b0c 100644 --- a/src/utils/WellKnownUtils.ts +++ b/src/utils/WellKnownUtils.ts @@ -23,6 +23,14 @@ export interface IE2EEWellKnown { default?: boolean; } +export async function ensureClientWellKnown() { + const cli = MatrixClientPeg.get(); + if (cli.haveAttemptedFetchingClientWellKnown()) return; + return new Promise(resolve => { + cli.once("WellKnown.attempted", resolve); + }); +} + export function getE2EEWellKnown(): IE2EEWellKnown { const clientWellKnown = MatrixClientPeg.get().getClientWellKnown(); if (clientWellKnown && clientWellKnown[E2EE_WK_KEY]) { From 2e2f60c20b2a42e902edadabb6bbcdfd5c0c4299 Mon Sep 17 00:00:00 2001 From: "J. Ryan Stinnett" Date: Mon, 24 Aug 2020 16:11:35 +0100 Subject: [PATCH 08/10] Use updated `waitFor` API with well-known --- src/DeviceListener.ts | 4 ++-- src/utils/WellKnownUtils.ts | 8 -------- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/src/DeviceListener.ts b/src/DeviceListener.ts index 41daa74376..6b667ae54d 100644 --- a/src/DeviceListener.ts +++ b/src/DeviceListener.ts @@ -31,7 +31,7 @@ import { } from "./toasts/UnverifiedSessionToast"; import { privateShouldBeEncrypted } from "./createRoom"; import { isSecretStorageBeingAccessed, accessSecretStorage } from "./CrossSigningManager"; -import { ensureClientWellKnown, isSecureBackupRequired } from './utils/WellKnownUtils'; +import { isSecureBackupRequired } from './utils/WellKnownUtils'; import { isLoggedIn } from './components/structures/MatrixChat'; @@ -226,7 +226,7 @@ export default class DeviceListener { showSetupEncryptionToast(SetupKind.UPGRADE_ENCRYPTION); } else { // No cross-signing or key backup on account (set up encryption) - await ensureClientWellKnown(); + await cli.waitForClientWellKnown(); if (isSecureBackupRequired() && isLoggedIn()) { // If we're meant to set up, and Secure Backup is required, // trigger the flow directly without a toast once logged in. diff --git a/src/utils/WellKnownUtils.ts b/src/utils/WellKnownUtils.ts index 1fe28f2b0c..f16acdb408 100644 --- a/src/utils/WellKnownUtils.ts +++ b/src/utils/WellKnownUtils.ts @@ -23,14 +23,6 @@ export interface IE2EEWellKnown { default?: boolean; } -export async function ensureClientWellKnown() { - const cli = MatrixClientPeg.get(); - if (cli.haveAttemptedFetchingClientWellKnown()) return; - return new Promise(resolve => { - cli.once("WellKnown.attempted", resolve); - }); -} - export function getE2EEWellKnown(): IE2EEWellKnown { const clientWellKnown = MatrixClientPeg.get().getClientWellKnown(); if (clientWellKnown && clientWellKnown[E2EE_WK_KEY]) { From b601a025b58200ac04bedf738fdd9898c462a251 Mon Sep 17 00:00:00 2001 From: "J. Ryan Stinnett" Date: Mon, 24 Aug 2020 16:33:23 +0100 Subject: [PATCH 09/10] Use `io.element` instead of `im.vector` --- src/utils/WellKnownUtils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/WellKnownUtils.ts b/src/utils/WellKnownUtils.ts index f16acdb408..46d9638ecd 100644 --- a/src/utils/WellKnownUtils.ts +++ b/src/utils/WellKnownUtils.ts @@ -16,7 +16,7 @@ limitations under the License. import {MatrixClientPeg} from '../MatrixClientPeg'; -const E2EE_WK_KEY = "im.vector.e2ee"; +const E2EE_WK_KEY = "io.element.e2ee"; const E2EE_WK_KEY_DEPRECATED = "im.vector.riot.e2ee"; export interface IE2EEWellKnown { From 35f19d53a54f0d090fac11c173a2ca55249bd219 Mon Sep 17 00:00:00 2001 From: "J. Ryan Stinnett" Date: Mon, 24 Aug 2020 16:44:47 +0100 Subject: [PATCH 10/10] Mention issue for view state store --- src/components/structures/MatrixChat.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/components/structures/MatrixChat.tsx b/src/components/structures/MatrixChat.tsx index 9929cc523e..b1c3a1c16e 100644 --- a/src/components/structures/MatrixChat.tsx +++ b/src/components/structures/MatrixChat.tsx @@ -2088,7 +2088,9 @@ export default class MatrixChat extends React.PureComponent { export function isLoggedIn(): boolean { // JRS: Maybe we should move the step that writes this to the window out of - // `element-web` and into this file? + // `element-web` and into this file? Better yet, we should probably create a + // store to hold this state. + // See also https://github.com/vector-im/element-web/issues/15034. const app = window.matrixChat; return app && (app as MatrixChat).state.view === Views.LOGGED_IN; }