From 5d1a1b46f3d080c2c836e8c9603cc14f8ff1d7c3 Mon Sep 17 00:00:00 2001
From: Michael Telatynski <7t3chguy@gmail.com>
Date: Thu, 1 Jul 2021 23:48:52 +0100
Subject: [PATCH 01/31] Fix instances of the Edit Message Composer's save
 button being wrongly disabled

---
 .../views/rooms/BasicMessageComposer.tsx      |  3 ++
 .../views/rooms/EditMessageComposer.tsx       | 39 +++++++------------
 2 files changed, 18 insertions(+), 24 deletions(-)

diff --git a/src/components/views/rooms/BasicMessageComposer.tsx b/src/components/views/rooms/BasicMessageComposer.tsx
index d317aa409b..3258674cf6 100644
--- a/src/components/views/rooms/BasicMessageComposer.tsx
+++ b/src/components/views/rooms/BasicMessageComposer.tsx
@@ -711,6 +711,7 @@ export default class BasicMessageEditor extends React.Component<IProps, IState>
     }
 
     public insertMention(userId: string): void {
+        this.modifiedFlag = true;
         const { model } = this.props;
         const { partCreator } = model;
         const member = this.props.room.getMember(userId);
@@ -729,6 +730,7 @@ export default class BasicMessageEditor extends React.Component<IProps, IState>
     }
 
     public insertQuotedMessage(event: MatrixEvent): void {
+        this.modifiedFlag = true;
         const { model } = this.props;
         const { partCreator } = model;
         const quoteParts = parseEvent(event, partCreator, { isQuotedMessage: true });
@@ -744,6 +746,7 @@ export default class BasicMessageEditor extends React.Component<IProps, IState>
     }
 
     public insertPlaintext(text: string): void {
+        this.modifiedFlag = true;
         const { model } = this.props;
         const { partCreator } = model;
         const caret = this.getCaret();
diff --git a/src/components/views/rooms/EditMessageComposer.tsx b/src/components/views/rooms/EditMessageComposer.tsx
index 4e51a0105b..fea6499dd8 100644
--- a/src/components/views/rooms/EditMessageComposer.tsx
+++ b/src/components/views/rooms/EditMessageComposer.tsx
@@ -131,11 +131,12 @@ export default class EditMessageComposer extends React.Component<IProps, IState>
         super(props);
         this.context = context; // otherwise React will only set it prior to render due to type def above
 
+        const isRestored = this.createEditorModel();
+        const ev = this.props.editState.getEvent();
         this.state = {
-            saveDisabled: true,
+            saveDisabled: !isRestored || !this.isContentModified(createEditContent(this.model, ev)["m.new_content"]),
         };
 
-        this.createEditorModel();
         window.addEventListener("beforeunload", this.saveStoredEditorState);
         this.dispatcherRef = dis.register(this.onAction);
     }
@@ -230,12 +231,12 @@ export default class EditMessageComposer extends React.Component<IProps, IState>
         }
     }
 
-    private saveStoredEditorState(): void {
+    private saveStoredEditorState = (): void => {
         const item = SendHistoryManager.createItem(this.model);
         this.clearPreviousEdit();
         localStorage.setItem(this.editorRoomKey, this.props.editState.getEvent().getId());
         localStorage.setItem(this.editorStateKey, JSON.stringify(item));
-    }
+    };
 
     private isSlashCommand(): boolean {
         const parts = this.model.parts;
@@ -256,10 +257,9 @@ export default class EditMessageComposer extends React.Component<IProps, IState>
     private isContentModified(newContent: IContent): boolean {
         // if nothing has changed then bail
         const oldContent = this.props.editState.getEvent().getContent();
-        if (!this.editorRef.current?.isModified() ||
-            (oldContent["msgtype"] === newContent["msgtype"] && oldContent["body"] === newContent["body"] &&
+        if (oldContent["msgtype"] === newContent["msgtype"] && oldContent["body"] === newContent["body"] &&
             oldContent["format"] === newContent["format"] &&
-            oldContent["formatted_body"] === newContent["formatted_body"])) {
+            oldContent["formatted_body"] === newContent["formatted_body"]) {
             return false;
         }
         return true;
@@ -410,36 +410,27 @@ export default class EditMessageComposer extends React.Component<IProps, IState>
         dis.unregister(this.dispatcherRef);
     }
 
-    private createEditorModel(): void {
+    private createEditorModel(): boolean {
         const { editState } = this.props;
         const room = this.getRoom();
         const partCreator = new CommandPartCreator(room, this.context);
+
         let parts;
+        let isRestored = false;
         if (editState.hasEditorState()) {
             // if restoring state from a previous editor,
             // restore serialized parts from the state
             parts = editState.getSerializedParts().map(p => partCreator.deserializePart(p));
         } else {
-            //otherwise, either restore serialized parts from localStorage or parse the body of the event
-            parts = this.restoreStoredEditorState(partCreator) || parseEvent(editState.getEvent(), partCreator);
+            // otherwise, either restore serialized parts from localStorage or parse the body of the event
+            const restoredParts = this.restoreStoredEditorState(partCreator);
+            parts = restoredParts || parseEvent(editState.getEvent(), partCreator);
+            isRestored = !!restoredParts;
         }
         this.model = new EditorModel(parts, partCreator);
         this.saveStoredEditorState();
-    }
 
-    private getInitialCaretPosition(): CaretPosition {
-        const { editState } = this.props;
-        let caretPosition;
-        if (editState.hasEditorState() && editState.getCaret()) {
-            // if restoring state from a previous editor,
-            // restore caret position from the state
-            const caret = editState.getCaret();
-            caretPosition = this.model.positionForOffset(caret.offset, caret.atNodeEnd);
-        } else {
-            // otherwise, set it at the end
-            caretPosition = this.model.getPositionAtEnd();
-        }
-        return caretPosition;
+        return isRestored;
     }
 
     private onChange = (): void => {

From a4fe2f143f84ff7502cc57b2c7db82a879fa21a0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C5=A0imon=20Brandner?= <simon.bra.ag@gmail.com>
Date: Fri, 2 Jul 2021 12:12:41 +0200
Subject: [PATCH 02/31] First batch of burning
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
---
 src/Analytics.tsx                       |  3 +--
 src/AsyncWrapper.tsx                    |  7 +++----
 src/ContentMessages.tsx                 |  9 ++++-----
 src/Lifecycle.ts                        | 13 ++++---------
 src/MatrixClientPeg.ts                  |  4 +---
 src/Notifier.ts                         |  3 +--
 src/RoomInvite.tsx                      |  6 +-----
 src/SecurityManager.ts                  |  4 +---
 src/Terms.ts                            |  3 +--
 src/accessibility/KeyboardShortcuts.tsx |  3 +--
 src/createRoom.ts                       |  8 +++-----
 src/verification.ts                     |  4 +---
 12 files changed, 22 insertions(+), 45 deletions(-)

diff --git a/src/Analytics.tsx b/src/Analytics.tsx
index 8c82639b5f..6a1608b63f 100644
--- a/src/Analytics.tsx
+++ b/src/Analytics.tsx
@@ -21,7 +21,7 @@ import { getCurrentLanguage, _t, _td, IVariables } from './languageHandler';
 import PlatformPeg from './PlatformPeg';
 import SdkConfig from './SdkConfig';
 import Modal from './Modal';
-import * as sdk from './index';
+import ErrorDialog from './components/views/dialogs/ErrorDialog';
 
 const hashRegex = /#\/(groups?|room|user|settings|register|login|forgot_password|home|directory)/;
 const hashVarRegex = /#\/(group|room|user)\/.*$/;
@@ -390,7 +390,6 @@ export class Analytics {
             { expl: _td('Your device resolution'), value: resolution },
         ];
 
-        const ErrorDialog = sdk.getComponent('dialogs.ErrorDialog');
         Modal.createTrackedDialog('Analytics Details', '', ErrorDialog, {
             title: _t('Analytics'),
             description: <div className="mx_AnalyticsModal">
diff --git a/src/AsyncWrapper.tsx b/src/AsyncWrapper.tsx
index 3bbef71093..5d3531be62 100644
--- a/src/AsyncWrapper.tsx
+++ b/src/AsyncWrapper.tsx
@@ -16,9 +16,11 @@ limitations under the License.
 
 import React, { ComponentType } from "react";
 
-import * as sdk from './index';
 import { _t } from './languageHandler';
 import { IDialogProps } from "./components/views/dialogs/IDialogProps";
+import BaseDialog from "./components/views/dialogs/BaseDialog";
+import Spinner from "./components/views/elements/Spinner";
+import DialogButtons from "./components/views/elements/DialogButtons";
 
 type AsyncImport<T> = { default: T };
 
@@ -77,8 +79,6 @@ export default class AsyncWrapper extends React.Component<IProps, IState> {
             const Component = this.state.component;
             return <Component {...this.props} />;
         } else if (this.state.error) {
-            const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
-            const DialogButtons = sdk.getComponent('views.elements.DialogButtons');
             return <BaseDialog onFinished={this.props.onFinished} title={_t("Error")}>
                 { _t("Unable to load! Check your network connectivity and try again.") }
                 <DialogButtons primaryButton={_t("Dismiss")}
@@ -88,7 +88,6 @@ export default class AsyncWrapper extends React.Component<IProps, IState> {
             </BaseDialog>;
         } else {
             // show a spinner until the component is loaded.
-            const Spinner = sdk.getComponent("elements.Spinner");
             return <Spinner />;
         }
     }
diff --git a/src/ContentMessages.tsx b/src/ContentMessages.tsx
index 1b8a3be37e..dd2002dd9a 100644
--- a/src/ContentMessages.tsx
+++ b/src/ContentMessages.tsx
@@ -21,7 +21,6 @@ import { encode } from "blurhash";
 import { MatrixClient } from "matrix-js-sdk/src/client";
 
 import dis from './dispatcher/dispatcher';
-import * as sdk from './index';
 import { _t } from './languageHandler';
 import Modal from './Modal';
 import RoomViewStore from './stores/RoomViewStore';
@@ -40,6 +39,10 @@ import {
 } from "./dispatcher/payloads/UploadPayload";
 import { IUpload } from "./models/IUpload";
 import { IImageInfo } from "matrix-js-sdk/src/@types/partials";
+import QuestionDialog from "./components/views/dialogs/QuestionDialog";
+import ErrorDialog from "./components/views/dialogs/ErrorDialog";
+import UploadConfirmDialog from "./components/views/dialogs/UploadConfirmDialog";
+import UploadFailureDialog from "./components/views/dialogs/UploadFailureDialog";
 
 const MAX_WIDTH = 800;
 const MAX_HEIGHT = 600;
@@ -419,7 +422,6 @@ export default class ContentMessages {
 
         const isQuoting = Boolean(RoomViewStore.getQuotingEvent());
         if (isQuoting) {
-            const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
             const { finished } = Modal.createTrackedDialog<[boolean]>('Upload Reply Warning', '', QuestionDialog, {
                 title: _t('Replying With Files'),
                 description: (
@@ -453,7 +455,6 @@ export default class ContentMessages {
         }
 
         if (tooBigFiles.length > 0) {
-            const UploadFailureDialog = sdk.getComponent("dialogs.UploadFailureDialog");
             const { finished } = Modal.createTrackedDialog<[boolean]>('Upload Failure', '', UploadFailureDialog, {
                 badFiles: tooBigFiles,
                 totalFiles: files.length,
@@ -463,7 +464,6 @@ export default class ContentMessages {
             if (!shouldContinue) return;
         }
 
-        const UploadConfirmDialog = sdk.getComponent("dialogs.UploadConfirmDialog");
         let uploadAll = false;
         // Promise to complete before sending next file into room, used for synchronisation of file-sending
         // to match the order the files were specified in
@@ -606,7 +606,6 @@ export default class ContentMessages {
                         { fileName: upload.fileName },
                     );
                 }
-                const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
                 Modal.createTrackedDialog('Upload failed', '', ErrorDialog, {
                     title: _t('Upload Failed'),
                     description: desc,
diff --git a/src/Lifecycle.ts b/src/Lifecycle.ts
index 76dee5ab55..61ded93833 100644
--- a/src/Lifecycle.ts
+++ b/src/Lifecycle.ts
@@ -33,7 +33,6 @@ import Presence from './Presence';
 import dis from './dispatcher/dispatcher';
 import DMRoomMap from './utils/DMRoomMap';
 import Modal from './Modal';
-import * as sdk from './index';
 import ActiveWidgetStore from './stores/ActiveWidgetStore';
 import PlatformPeg from "./PlatformPeg";
 import { sendLoginRequest } from "./Login";
@@ -52,6 +51,10 @@ import CallHandler from './CallHandler';
 import LifecycleCustomisations from "./customisations/Lifecycle";
 import ErrorDialog from "./components/views/dialogs/ErrorDialog";
 import { _t } from "./languageHandler";
+import LazyLoadingResyncDialog from "./components/views/dialogs/LazyLoadingResyncDialog";
+import LazyLoadingDisabledDialog from "./components/views/dialogs/LazyLoadingDisabledDialog";
+import SessionRestoreErrorDialog from "./components/views/dialogs/SessionRestoreErrorDialog";
+import StorageEvictedDialog from "./components/views/dialogs/StorageEvictedDialog";
 
 const HOMESERVER_URL_KEY = "mx_hs_url";
 const ID_SERVER_URL_KEY = "mx_is_url";
@@ -238,8 +241,6 @@ export function handleInvalidStoreError(e: InvalidStoreError): Promise<void> {
         return Promise.resolve().then(() => {
             const lazyLoadEnabled = e.value;
             if (lazyLoadEnabled) {
-                const LazyLoadingResyncDialog =
-                    sdk.getComponent("views.dialogs.LazyLoadingResyncDialog");
                 return new Promise((resolve) => {
                     Modal.createDialog(LazyLoadingResyncDialog, {
                         onFinished: resolve,
@@ -250,8 +251,6 @@ export function handleInvalidStoreError(e: InvalidStoreError): Promise<void> {
                 // between LL/non-LL version on same host.
                 // as disabling LL when previously enabled
                 // is a strong indicator of this (/develop & /app)
-                const LazyLoadingDisabledDialog =
-                    sdk.getComponent("views.dialogs.LazyLoadingDisabledDialog");
                 return new Promise((resolve) => {
                     Modal.createDialog(LazyLoadingDisabledDialog, {
                         onFinished: resolve,
@@ -451,9 +450,6 @@ export async function restoreFromLocalStorage(opts?: { ignoreGuest?: boolean }):
 async function handleLoadSessionFailure(e: Error): Promise<boolean> {
     console.error("Unable to load session", e);
 
-    const SessionRestoreErrorDialog =
-          sdk.getComponent('views.dialogs.SessionRestoreErrorDialog');
-
     const modal = Modal.createTrackedDialog('Session Restore Error', '', SessionRestoreErrorDialog, {
         error: e.message,
     });
@@ -612,7 +608,6 @@ async function doSetLoggedIn(
 }
 
 function showStorageEvictedDialog(): Promise<boolean> {
-    const StorageEvictedDialog = sdk.getComponent('views.dialogs.StorageEvictedDialog');
     return new Promise(resolve => {
         Modal.createTrackedDialog('Storage evicted', '', StorageEvictedDialog, {
             onFinished: resolve,
diff --git a/src/MatrixClientPeg.ts b/src/MatrixClientPeg.ts
index cb6cb5c65c..db8401baba 100644
--- a/src/MatrixClientPeg.ts
+++ b/src/MatrixClientPeg.ts
@@ -23,7 +23,6 @@ import { MemoryStore } from 'matrix-js-sdk/src/store/memory';
 import * as utils from 'matrix-js-sdk/src/utils';
 import { EventTimeline } from 'matrix-js-sdk/src/models/event-timeline';
 import { EventTimelineSet } from 'matrix-js-sdk/src/models/event-timeline-set';
-import * as sdk from './index';
 import createMatrixClient from './utils/createMatrixClient';
 import SettingsStore from './settings/SettingsStore';
 import MatrixActionCreators from './actions/MatrixActionCreators';
@@ -35,6 +34,7 @@ import IdentityAuthClient from './IdentityAuthClient';
 import { crossSigningCallbacks, tryToUnlockSecretStorageWithDehydrationKey } from './SecurityManager';
 import { SHOW_QR_CODE_METHOD } from "matrix-js-sdk/src/crypto/verification/QRCode";
 import SecurityCustomisations from "./customisations/Security";
+import CryptoStoreTooNewDialog from ".components/views/dialogs/CryptoStoreTooNewDialog";
 
 export interface IMatrixClientCreds {
     homeserverUrl: string;
@@ -219,8 +219,6 @@ class _MatrixClientPeg implements IMatrixClientPeg {
         } catch (e) {
             if (e && e.name === 'InvalidCryptoStoreError') {
                 // The js-sdk found a crypto DB too new for it to use
-                const CryptoStoreTooNewDialog =
-                    sdk.getComponent("views.dialogs.CryptoStoreTooNewDialog");
                 Modal.createDialog(CryptoStoreTooNewDialog);
             }
             // this can happen for a number of reasons, the most likely being
diff --git a/src/Notifier.ts b/src/Notifier.ts
index 2335dc59ac..415adcafc8 100644
--- a/src/Notifier.ts
+++ b/src/Notifier.ts
@@ -27,7 +27,6 @@ import * as TextForEvent from './TextForEvent';
 import Analytics from './Analytics';
 import * as Avatar from './Avatar';
 import dis from './dispatcher/dispatcher';
-import * as sdk from './index';
 import { _t } from './languageHandler';
 import Modal from './Modal';
 import SettingsStore from "./settings/SettingsStore";
@@ -37,6 +36,7 @@ import { isPushNotifyDisabled } from "./settings/controllers/NotificationControl
 import RoomViewStore from "./stores/RoomViewStore";
 import UserActivity from "./UserActivity";
 import { mediaFromMxc } from "./customisations/Media";
+import ErrorDialog from "./components/views/dialogs/ErrorDialog";
 
 /*
  * Dispatches:
@@ -240,7 +240,6 @@ export const Notifier = {
                         ? _t('%(brand)s does not have permission to send you notifications - ' +
                             'please check your browser settings', { brand })
                         : _t('%(brand)s was not given permission to send notifications - please try again', { brand });
-                    const ErrorDialog = sdk.getComponent('dialogs.ErrorDialog');
                     Modal.createTrackedDialog('Unable to enable Notifications', result, ErrorDialog, {
                         title: _t('Unable to enable Notifications'),
                         description,
diff --git a/src/RoomInvite.tsx b/src/RoomInvite.tsx
index c7f377b6e8..7d093f4092 100644
--- a/src/RoomInvite.tsx
+++ b/src/RoomInvite.tsx
@@ -22,13 +22,13 @@ import { User } from "matrix-js-sdk/src/models/user";
 import { MatrixClientPeg } from './MatrixClientPeg';
 import MultiInviter, { CompletionStates } from './utils/MultiInviter';
 import Modal from './Modal';
-import * as sdk from './';
 import { _t } from './languageHandler';
 import InviteDialog, { KIND_DM, KIND_INVITE, Member } from "./components/views/dialogs/InviteDialog";
 import CommunityPrototypeInviteDialog from "./components/views/dialogs/CommunityPrototypeInviteDialog";
 import { CommunityPrototypeStore } from "./stores/CommunityPrototypeStore";
 import BaseAvatar from "./components/views/avatars/BaseAvatar";
 import { mediaFromMxc } from "./customisations/Media";
+import ErrorDialog from "./components/views/dialogs/ErrorDialog";
 
 export interface IInviteResult {
     states: CompletionStates;
@@ -51,7 +51,6 @@ export function inviteMultipleToRoom(roomId: string, addresses: string[]): Promi
 
 export function showStartChatInviteDialog(initialText = ""): void {
     // This dialog handles the room creation internally - we don't need to worry about it.
-    const InviteDialog = sdk.getComponent("dialogs.InviteDialog");
     Modal.createTrackedDialog(
         'Start DM', '', InviteDialog, { kind: KIND_DM, initialText },
         /*className=*/null, /*isPriority=*/false, /*isStatic=*/true,
@@ -111,7 +110,6 @@ export function inviteUsersToRoom(roomId: string, userIds: string[]): Promise<vo
         showAnyInviteErrors(result.states, room, result.inviter);
     }).catch((err) => {
         console.error(err.stack);
-        const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
         Modal.createTrackedDialog('Failed to invite', '', ErrorDialog, {
             title: _t("Failed to invite"),
             description: ((err && err.message) ? err.message : _t("Operation failed")),
@@ -131,7 +129,6 @@ export function showAnyInviteErrors(
         // Just get the first message because there was a fatal problem on the first
         // user. This usually means that no other users were attempted, making it
         // pointless for us to list who failed exactly.
-        const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
         Modal.createTrackedDialog('Failed to invite users to the room', '', ErrorDialog, {
             title: _t("Failed to invite users to the room:", { roomName: room.name }),
             description: inviter.getErrorText(failedUsers[0]),
@@ -178,7 +175,6 @@ export function showAnyInviteErrors(
                 </div>
             </div>;
 
-            const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
             Modal.createTrackedDialog("Some invites could not be sent", "", ErrorDialog, {
                 title: _t("Some invites couldn't be sent"),
                 description,
diff --git a/src/SecurityManager.ts b/src/SecurityManager.ts
index 214047c4fa..8479eadddb 100644
--- a/src/SecurityManager.ts
+++ b/src/SecurityManager.ts
@@ -17,7 +17,6 @@ limitations under the License.
 import { ICryptoCallbacks, ISecretStorageKeyInfo } from 'matrix-js-sdk/src/matrix';
 import { MatrixClient } from 'matrix-js-sdk/src/client';
 import Modal from './Modal';
-import * as sdk from './index';
 import { MatrixClientPeg } from './MatrixClientPeg';
 import { deriveKey } from 'matrix-js-sdk/src/crypto/key_passphrase';
 import { decodeRecoveryKey } from 'matrix-js-sdk/src/crypto/recoverykey';
@@ -29,6 +28,7 @@ import RestoreKeyBackupDialog from './components/views/dialogs/security/RestoreK
 import SettingsStore from "./settings/SettingsStore";
 import SecurityCustomisations from "./customisations/Security";
 import { DeviceTrustLevel } from 'matrix-js-sdk/src/crypto/CrossSigning';
+import InteractiveAuthDialog from "./components/views/dialogs/InteractiveAuthDialog";
 
 // 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
@@ -68,7 +68,6 @@ export class AccessCancelledError extends Error {
 }
 
 async function confirmToDismiss(): Promise<boolean> {
-    const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
     const [sure] = await Modal.createDialog(QuestionDialog, {
         title: _t("Cancel entering passphrase?"),
         description: _t("Are you sure you want to cancel entering passphrase?"),
@@ -354,7 +353,6 @@ export async function accessSecretStorage(func = async () => { }, forceReset = f
                 throw new Error("Secret storage creation canceled");
             }
         } else {
-            const InteractiveAuthDialog = sdk.getComponent("dialogs.InteractiveAuthDialog");
             await cli.bootstrapCrossSigning({
                 authUploadDeviceSigningKeys: async (makeRequest) => {
                     const { finished } = Modal.createTrackedDialog(
diff --git a/src/Terms.ts b/src/Terms.ts
index 0189810e7c..5a6d96b798 100644
--- a/src/Terms.ts
+++ b/src/Terms.ts
@@ -17,8 +17,8 @@ limitations under the License.
 import classNames from 'classnames';
 
 import { MatrixClientPeg } from './MatrixClientPeg';
-import * as sdk from '.';
 import Modal from './Modal';
+import TermsDialog from './components/views/dialogs/TermsDialog';
 
 export class TermsNotSignedError extends Error {}
 
@@ -188,7 +188,6 @@ export function dialogTermsInteractionCallback(
 ): Promise<string[]> {
     return new Promise((resolve, reject) => {
         console.log("Terms that need agreement", policiesAndServicePairs);
-        const TermsDialog = sdk.getComponent("views.dialogs.TermsDialog");
 
         Modal.createTrackedDialog('Terms of Service', '', TermsDialog, {
             policiesAndServicePairs,
diff --git a/src/accessibility/KeyboardShortcuts.tsx b/src/accessibility/KeyboardShortcuts.tsx
index 25c41f9db5..c5cf85facd 100644
--- a/src/accessibility/KeyboardShortcuts.tsx
+++ b/src/accessibility/KeyboardShortcuts.tsx
@@ -17,10 +17,10 @@ limitations under the License.
 import * as React from "react";
 import classNames from "classnames";
 
-import * as sdk from "../index";
 import Modal from "../Modal";
 import { _t, _td } from "../languageHandler";
 import { isMac, Key } from "../Keyboard";
+import InfoDialog from "../components/views/dialogs/InfoDialog";
 
 // TS: once languageHandler is TS we can probably inline this into the enum
 _td("Navigation");
@@ -375,7 +375,6 @@ export const toggleDialog = () => {
         </div>;
     });
 
-    const InfoDialog = sdk.getComponent('dialogs.InfoDialog');
     activeModal = Modal.createTrackedDialog("Keyboard Shortcuts", "", InfoDialog, {
         className: "mx_KeyboardShortcutsDialog",
         title: _t("Keyboard Shortcuts"),
diff --git a/src/createRoom.ts b/src/createRoom.ts
index 94efecaa6c..afbeb7fdb9 100644
--- a/src/createRoom.ts
+++ b/src/createRoom.ts
@@ -21,7 +21,6 @@ import { EventType } from "matrix-js-sdk/src/@types/event";
 
 import { MatrixClientPeg } from './MatrixClientPeg';
 import Modal from './Modal';
-import * as sdk from './index';
 import { _t } from './languageHandler';
 import dis from "./dispatcher/dispatcher";
 import * as Rooms from "./Rooms";
@@ -37,6 +36,8 @@ import { makeSpaceParentEvent } from "./utils/space";
 import { Action } from "./dispatcher/actions";
 import { ICreateRoomOpts } from "matrix-js-sdk/src/@types/requests";
 import { Preset, Visibility } from "matrix-js-sdk/src/@types/partials";
+import ErrorDialog from "./components/views/dialogs/ErrorDialog";
+import Spinner from "./components/views/elements/Spinner";
 
 // we define a number of interfaces which take their names from the js-sdk
 /* eslint-disable camelcase */
@@ -80,9 +81,6 @@ export default function createRoom(opts: IOpts): Promise<string | null> {
 
     const startTime = CountlyAnalytics.getTimestamp();
 
-    const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
-    const Loader = sdk.getComponent("elements.Spinner");
-
     const client = MatrixClientPeg.get();
     if (client.isGuest()) {
         dis.dispatch({ action: 'require_registration' });
@@ -153,7 +151,7 @@ export default function createRoom(opts: IOpts): Promise<string | null> {
     }
 
     let modal;
-    if (opts.spinner) modal = Modal.createDialog(Loader, null, 'mx_Dialog_spinner');
+    if (opts.spinner) modal = Modal.createDialog(Spinner, null, 'mx_Dialog_spinner');
 
     let roomId;
     return client.createRoom(createOpts).finally(function() {
diff --git a/src/verification.ts b/src/verification.ts
index 22b62461a1..719c0ec5b3 100644
--- a/src/verification.ts
+++ b/src/verification.ts
@@ -19,7 +19,6 @@ import { User } from "matrix-js-sdk/src/models/user";
 import { MatrixClientPeg } from './MatrixClientPeg';
 import dis from "./dispatcher/dispatcher";
 import Modal from './Modal';
-import * as sdk from './index';
 import { RightPanelPhases } from "./stores/RightPanelStorePhases";
 import { findDMForUser } from './createRoom';
 import { accessSecretStorage } from './SecurityManager';
@@ -27,6 +26,7 @@ import { verificationMethods } from 'matrix-js-sdk/src/crypto';
 import { Action } from './dispatcher/actions';
 import UntrustedDeviceDialog from "./components/views/dialogs/UntrustedDeviceDialog";
 import { IDevice } from "./components/views/right_panel/UserInfo";
+import ManualDeviceKeyVerificationDialog from "./components/views/dialogs/ManualDeviceKeyVerificationDialog";
 
 async function enable4SIfNeeded() {
     const cli = MatrixClientPeg.get();
@@ -71,8 +71,6 @@ export async function verifyDevice(user: User, device: IDevice) {
                     refireParams: { member: user, verificationRequestPromise },
                 });
             } else if (action === "legacy") {
-                const ManualDeviceKeyVerificationDialog =
-                    sdk.getComponent("dialogs.ManualDeviceKeyVerificationDialog");
                 Modal.createTrackedDialog("Legacy verify session", "legacy verify session",
                     ManualDeviceKeyVerificationDialog,
                     {

From 9d569c378e5240554780fb52336184136eb10204 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C5=A0imon=20Brandner?= <simon.bra.ag@gmail.com>
Date: Fri, 2 Jul 2021 17:08:27 +0200
Subject: [PATCH 03/31] Second batch of burning
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
---
 src/actions/RoomListActions.ts                         |  5 +----
 .../dialogs/eventindex/ManageEventIndexDialog.tsx      |  8 +++-----
 src/autocomplete/CommunityProvider.tsx                 |  4 +---
 src/autocomplete/NotifProvider.tsx                     |  4 +---
 src/autocomplete/UserProvider.tsx                      |  4 +---
 src/components/structures/FilePanel.tsx                | 10 +++++-----
 src/components/structures/HomePage.tsx                 |  3 +--
 src/components/structures/TabbedView.tsx               |  4 +---
 src/components/structures/TimelinePanel.tsx            |  3 +--
 src/components/structures/auth/Login.tsx               |  5 ++---
 src/components/views/auth/RegistrationForm.tsx         |  3 +--
 src/components/views/dialogs/AskInviteAnywayDialog.tsx |  4 +---
 src/components/views/dialogs/ChangelogDialog.tsx       |  6 ++----
 src/components/views/dialogs/ConfirmRedactDialog.tsx   |  3 +--
 .../views/dialogs/DeactivateAccountDialog.tsx          |  4 +---
 src/components/views/dialogs/ErrorDialog.tsx           |  3 +--
 16 files changed, 24 insertions(+), 49 deletions(-)

diff --git a/src/actions/RoomListActions.ts b/src/actions/RoomListActions.ts
index 81e05f8678..a7f629c40d 100644
--- a/src/actions/RoomListActions.ts
+++ b/src/actions/RoomListActions.ts
@@ -19,13 +19,13 @@ import { asyncAction } from './actionCreators';
 import Modal from '../Modal';
 import * as Rooms from '../Rooms';
 import { _t } from '../languageHandler';
-import * as sdk from '../index';
 import { MatrixClient } from "matrix-js-sdk/src/client";
 import { Room } from "matrix-js-sdk/src/models/room";
 import { AsyncActionPayload } from "../dispatcher/payloads";
 import RoomListStore from "../stores/room-list/RoomListStore";
 import { SortAlgorithm } from "../stores/room-list/algorithms/models";
 import { DefaultTagID } from "../stores/room-list/models";
+import ErrorDialog from '../components/views/dialogs/ErrorDialog';
 
 export default class RoomListActions {
     /**
@@ -88,7 +88,6 @@ export default class RoomListActions {
                 return Rooms.guessAndSetDMRoom(
                     room, newTag === DefaultTagID.DM,
                 ).catch((err) => {
-                    const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
                     console.error("Failed to set direct chat tag " + err);
                     Modal.createTrackedDialog('Failed to set direct chat tag', '', ErrorDialog, {
                         title: _t('Failed to set direct chat tag'),
@@ -109,7 +108,6 @@ export default class RoomListActions {
                 const promiseToDelete = matrixClient.deleteRoomTag(
                     roomId, oldTag,
                 ).catch(function(err) {
-                    const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
                     console.error("Failed to remove tag " + oldTag + " from room: " + err);
                     Modal.createTrackedDialog('Failed to remove tag from room', '', ErrorDialog, {
                         title: _t('Failed to remove tag %(tagName)s from room', { tagName: oldTag }),
@@ -129,7 +127,6 @@ export default class RoomListActions {
                 metaData = metaData || {};
 
                 const promiseToAdd = matrixClient.setRoomTag(roomId, newTag, metaData).catch(function(err) {
-                    const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
                     console.error("Failed to add tag " + newTag + " to room: " + err);
                     Modal.createTrackedDialog('Failed to add tag to room', '', ErrorDialog, {
                         title: _t('Failed to add tag %(tagName)s to room', { tagName: newTag }),
diff --git a/src/async-components/views/dialogs/eventindex/ManageEventIndexDialog.tsx b/src/async-components/views/dialogs/eventindex/ManageEventIndexDialog.tsx
index 76c3373ba4..9da724b535 100644
--- a/src/async-components/views/dialogs/eventindex/ManageEventIndexDialog.tsx
+++ b/src/async-components/views/dialogs/eventindex/ManageEventIndexDialog.tsx
@@ -15,7 +15,6 @@ limitations under the License.
 */
 
 import React from 'react';
-import * as sdk from '../../../../index';
 import { _t } from '../../../../languageHandler';
 import SdkConfig from '../../../../SdkConfig';
 import SettingsStore from "../../../../settings/SettingsStore";
@@ -24,6 +23,9 @@ import Modal from '../../../../Modal';
 import { formatBytes, formatCountLong } from "../../../../utils/FormattingUtils";
 import EventIndexPeg from "../../../../indexing/EventIndexPeg";
 import { SettingLevel } from "../../../../settings/SettingLevel";
+import Field from '../../../../components/views/elements/Field';
+import BaseDialog from "../../../../components/views/dialogs/BaseDialog";
+import DialogButtons from "../../../../components/views/elements/DialogButtons";
 
 interface IProps {
     onFinished: (confirmed: boolean) => void;
@@ -145,7 +147,6 @@ export default class ManageEventIndexDialog extends React.Component<IProps, ISta
 
     render() {
         const brand = SdkConfig.get().brand;
-        const Field = sdk.getComponent('views.elements.Field');
 
         let crawlerState;
         if (this.state.currentRoom === null) {
@@ -182,9 +183,6 @@ export default class ManageEventIndexDialog extends React.Component<IProps, ISta
             </div>
         );
 
-        const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
-        const DialogButtons = sdk.getComponent('views.elements.DialogButtons');
-
         return (
             <BaseDialog className='mx_ManageEventIndexDialog'
                 onFinished={this.props.onFinished}
diff --git a/src/autocomplete/CommunityProvider.tsx b/src/autocomplete/CommunityProvider.tsx
index 48c1921539..de99675b4b 100644
--- a/src/autocomplete/CommunityProvider.tsx
+++ b/src/autocomplete/CommunityProvider.tsx
@@ -22,12 +22,12 @@ import AutocompleteProvider from './AutocompleteProvider';
 import { MatrixClientPeg } from '../MatrixClientPeg';
 import QueryMatcher from './QueryMatcher';
 import { PillCompletion } from './Components';
-import * as sdk from '../index';
 import { sortBy } from "lodash";
 import { makeGroupPermalink } from "../utils/permalinks/Permalinks";
 import { ICompletion, ISelectionRange } from "./Autocompleter";
 import FlairStore from "../stores/FlairStore";
 import { mediaFromMxc } from "../customisations/Media";
+import BaseAvatar from '../components/views/avatars/BaseAvatar';
 
 const COMMUNITY_REGEX = /\B\+\S*/g;
 
@@ -56,8 +56,6 @@ export default class CommunityProvider extends AutocompleteProvider {
         force = false,
         limit = -1,
     ): Promise<ICompletion[]> {
-        const BaseAvatar = sdk.getComponent('views.avatars.BaseAvatar');
-
         // Disable autocompletions when composing commands because of various issues
         // (see https://github.com/vector-im/element-web/issues/4762)
         if (/^(\/join|\/leave)/.test(query)) {
diff --git a/src/autocomplete/NotifProvider.tsx b/src/autocomplete/NotifProvider.tsx
index 1d42915ec9..31b834ccfe 100644
--- a/src/autocomplete/NotifProvider.tsx
+++ b/src/autocomplete/NotifProvider.tsx
@@ -21,8 +21,8 @@ import AutocompleteProvider from './AutocompleteProvider';
 import { _t } from '../languageHandler';
 import { MatrixClientPeg } from '../MatrixClientPeg';
 import { PillCompletion } from './Components';
-import * as sdk from '../index';
 import { ICompletion, ISelectionRange } from "./Autocompleter";
+import RoomAvatar from '../components/views/avatars/RoomAvatar';
 
 const AT_ROOM_REGEX = /@\S*/g;
 
@@ -40,8 +40,6 @@ export default class NotifProvider extends AutocompleteProvider {
         force = false,
         limit = -1,
     ): Promise<ICompletion[]> {
-        const RoomAvatar = sdk.getComponent('views.avatars.RoomAvatar');
-
         const client = MatrixClientPeg.get();
 
         if (!this.room.currentState.mayTriggerNotifOfType('room', client.credentials.userId)) return [];
diff --git a/src/autocomplete/UserProvider.tsx b/src/autocomplete/UserProvider.tsx
index 470e018e22..d8f17c54d0 100644
--- a/src/autocomplete/UserProvider.tsx
+++ b/src/autocomplete/UserProvider.tsx
@@ -21,7 +21,6 @@ import React from 'react';
 import { _t } from '../languageHandler';
 import AutocompleteProvider from './AutocompleteProvider';
 import { PillCompletion } from './Components';
-import * as sdk from '../index';
 import QueryMatcher from './QueryMatcher';
 import { sortBy } from 'lodash';
 import { MatrixClientPeg } from '../MatrixClientPeg';
@@ -33,6 +32,7 @@ import { RoomState } from "matrix-js-sdk/src/models/room-state";
 import { EventTimeline } from "matrix-js-sdk/src/models/event-timeline";
 import { makeUserPermalink } from "../utils/permalinks/Permalinks";
 import { ICompletion, ISelectionRange } from "./Autocompleter";
+import MemberAvatar from '../components/views/avatars/MemberAvatar';
 
 const USER_REGEX = /\B@\S*/g;
 
@@ -108,8 +108,6 @@ export default class UserProvider extends AutocompleteProvider {
         force = false,
         limit = -1,
     ): Promise<ICompletion[]> {
-        const MemberAvatar = sdk.getComponent('views.avatars.MemberAvatar');
-
         // lazy-load user list into matcher
         if (!this.users) this._makeUsers();
 
diff --git a/src/components/structures/FilePanel.tsx b/src/components/structures/FilePanel.tsx
index 5865201069..36f774a130 100644
--- a/src/components/structures/FilePanel.tsx
+++ b/src/components/structures/FilePanel.tsx
@@ -24,7 +24,6 @@ import { MatrixEvent } from "matrix-js-sdk/src/models/event";
 import { Room } from 'matrix-js-sdk/src/models/room';
 import { TimelineWindow } from 'matrix-js-sdk/src/timeline-window';
 
-import * as sdk from '../../index';
 import { MatrixClientPeg } from '../../MatrixClientPeg';
 import EventIndexPeg from "../../indexing/EventIndexPeg";
 import { _t } from '../../languageHandler';
@@ -34,6 +33,9 @@ import DesktopBuildsNotice, { WarningKind } from "../views/elements/DesktopBuild
 import { replaceableComponent } from "../../utils/replaceableComponent";
 
 import ResizeNotifier from '../../utils/ResizeNotifier';
+import TimelinePanel from "./TimelinePanel";
+import Spinner from "../views/elements/Spinner";
+import { TileShape } from '../views/rooms/EventTile';
 
 interface IProps {
     roomId: string;
@@ -237,8 +239,6 @@ class FilePanel extends React.Component<IProps, IState> {
         }
 
         // wrap a TimelinePanel with the jump-to-event bits turned off.
-        const TimelinePanel = sdk.getComponent("structures.TimelinePanel");
-        const Loader = sdk.getComponent("elements.Spinner");
 
         const emptyState = (<div className="mx_RightPanel_empty mx_FilePanel_empty">
             <h2>{_t('No files visible in this room')}</h2>
@@ -264,7 +264,7 @@ class FilePanel extends React.Component<IProps, IState> {
                         timelineSet={this.state.timelineSet}
                         showUrlPreview = {false}
                         onPaginationRequest={this.onPaginationRequest}
-                        tileShape="file_grid"
+                        tileShape={TileShape.FileGrid}
                         resizeNotifier={this.props.resizeNotifier}
                         empty={emptyState}
                     />
@@ -277,7 +277,7 @@ class FilePanel extends React.Component<IProps, IState> {
                     onClose={this.props.onClose}
                     previousPhase={RightPanelPhases.RoomSummary}
                 >
-                    <Loader />
+                    <Spinner />
                 </BaseCard>
             );
         }
diff --git a/src/components/structures/HomePage.tsx b/src/components/structures/HomePage.tsx
index 046e07f455..94239ea603 100644
--- a/src/components/structures/HomePage.tsx
+++ b/src/components/structures/HomePage.tsx
@@ -21,7 +21,6 @@ import AutoHideScrollbar from './AutoHideScrollbar';
 import { getHomePageUrl } from "../../utils/pages";
 import { _t } from "../../languageHandler";
 import SdkConfig from "../../SdkConfig";
-import * as sdk from "../../index";
 import dis from "../../dispatcher/dispatcher";
 import { Action } from "../../dispatcher/actions";
 import BaseAvatar from "../views/avatars/BaseAvatar";
@@ -33,6 +32,7 @@ import MatrixClientContext from "../../contexts/MatrixClientContext";
 import MiniAvatarUploader, { AVATAR_SIZE } from "../views/elements/MiniAvatarUploader";
 import Analytics from "../../Analytics";
 import CountlyAnalytics from "../../CountlyAnalytics";
+import EmbeddedPage from "./EmbeddedPage";
 
 const onClickSendDm = () => {
     Analytics.trackEvent('home_page', 'button', 'dm');
@@ -96,7 +96,6 @@ const HomePage: React.FC<IProps> = ({ justRegistered = false }) => {
     const pageUrl = getHomePageUrl(config);
 
     if (pageUrl) {
-        const EmbeddedPage = sdk.getComponent('structures.EmbeddedPage');
         return <EmbeddedPage className="mx_HomePage" url={pageUrl} scrollbar={true} />;
     }
 
diff --git a/src/components/structures/TabbedView.tsx b/src/components/structures/TabbedView.tsx
index 3d77eaeac1..dcfde94811 100644
--- a/src/components/structures/TabbedView.tsx
+++ b/src/components/structures/TabbedView.tsx
@@ -18,9 +18,9 @@ limitations under the License.
 
 import * as React from "react";
 import { _t } from '../../languageHandler';
-import * as sdk from "../../index";
 import AutoHideScrollbar from './AutoHideScrollbar';
 import { replaceableComponent } from "../../utils/replaceableComponent";
+import AccessibleButton from "../views/elements/AccessibleButton";
 
 /**
  * Represents a tab for the TabbedView.
@@ -82,8 +82,6 @@ export default class TabbedView extends React.Component<IProps, IState> {
     }
 
     private _renderTabLabel(tab: Tab) {
-        const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
-
         let classes = "mx_TabbedView_tabLabel ";
 
         const idx = this.props.tabs.indexOf(tab);
diff --git a/src/components/structures/TimelinePanel.tsx b/src/components/structures/TimelinePanel.tsx
index 0b6d33b409..85a048e9b8 100644
--- a/src/components/structures/TimelinePanel.tsx
+++ b/src/components/structures/TimelinePanel.tsx
@@ -32,7 +32,6 @@ import RoomContext from "../../contexts/RoomContext";
 import UserActivity from "../../UserActivity";
 import Modal from "../../Modal";
 import dis from "../../dispatcher/dispatcher";
-import * as sdk from "../../index";
 import { Key } from '../../Keyboard';
 import Timer from '../../utils/Timer';
 import shouldHideEvent from '../../shouldHideEvent';
@@ -47,6 +46,7 @@ import ResizeNotifier from "../../utils/ResizeNotifier";
 import { RoomPermalinkCreator } from "../../utils/permalinks/Permalinks";
 import Spinner from "../views/elements/Spinner";
 import EditorStateTransfer from '../../utils/EditorStateTransfer';
+import ErrorDialog from '../views/dialogs/ErrorDialog';
 
 const PAGINATE_SIZE = 20;
 const INITIAL_SIZE = 20;
@@ -1096,7 +1096,6 @@ class TimelinePanel extends React.Component<IProps, IState> {
             console.error(
                 `Error loading timeline panel at ${eventId}: ${error}`,
             );
-            const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
 
             let onFinished;
 
diff --git a/src/components/structures/auth/Login.tsx b/src/components/structures/auth/Login.tsx
index 61d3759dee..9f12521a34 100644
--- a/src/components/structures/auth/Login.tsx
+++ b/src/components/structures/auth/Login.tsx
@@ -18,7 +18,6 @@ import React, { ReactNode } from 'react';
 import { MatrixError } from "matrix-js-sdk/src/http-api";
 
 import { _t, _td } from '../../../languageHandler';
-import * as sdk from '../../../index';
 import Login, { ISSOFlow, LoginFlow } from '../../../Login';
 import SdkConfig from '../../../SdkConfig';
 import { messageForResourceLimitError } from '../../../utils/ErrorUtils';
@@ -36,6 +35,8 @@ import Spinner from "../../views/elements/Spinner";
 import SSOButtons from "../../views/elements/SSOButtons";
 import ServerPicker from "../../views/elements/ServerPicker";
 import { replaceableComponent } from "../../../utils/replaceableComponent";
+import AuthBody from "../../views/auth/AuthBody";
+import AuthHeader from "../../views/auth/AuthHeader";
 
 // These are used in several places, and come from the js-sdk's autodiscovery
 // stuff. We define them here so that they'll be picked up by i18n.
@@ -541,8 +542,6 @@ export default class LoginComponent extends React.PureComponent<IProps, IState>
     };
 
     render() {
-        const AuthHeader = sdk.getComponent("auth.AuthHeader");
-        const AuthBody = sdk.getComponent("auth.AuthBody");
         const loader = this.isBusy() && !this.state.busyLoggingIn ?
             <div className="mx_Login_loader"><Spinner /></div> : null;
 
diff --git a/src/components/views/auth/RegistrationForm.tsx b/src/components/views/auth/RegistrationForm.tsx
index be6e29a493..25ea347d24 100644
--- a/src/components/views/auth/RegistrationForm.tsx
+++ b/src/components/views/auth/RegistrationForm.tsx
@@ -17,7 +17,6 @@ limitations under the License.
 
 import React from 'react';
 
-import * as sdk from '../../../index';
 import * as Email from '../../../email';
 import { looksValid as phoneNumberLooksValid } from '../../../phonenumber';
 import Modal from '../../../Modal';
@@ -31,6 +30,7 @@ import CountlyAnalytics from "../../../CountlyAnalytics";
 import Field from '../elements/Field';
 import RegistrationEmailPromptDialog from '../dialogs/RegistrationEmailPromptDialog';
 import { replaceableComponent } from "../../../utils/replaceableComponent";
+import CountryDropdown from "./CountryDropdown";
 
 enum RegistrationField {
     Email = "field_email",
@@ -471,7 +471,6 @@ export default class RegistrationForm extends React.PureComponent<IProps, IState
         if (!this.showPhoneNumber()) {
             return null;
         }
-        const CountryDropdown = sdk.getComponent('views.auth.CountryDropdown');
         const phoneLabel = this.authStepIsRequired('m.login.msisdn') ?
             _t("Phone") :
             _t("Phone (optional)");
diff --git a/src/components/views/dialogs/AskInviteAnywayDialog.tsx b/src/components/views/dialogs/AskInviteAnywayDialog.tsx
index 970883aca2..26fad0c724 100644
--- a/src/components/views/dialogs/AskInviteAnywayDialog.tsx
+++ b/src/components/views/dialogs/AskInviteAnywayDialog.tsx
@@ -15,11 +15,11 @@ limitations under the License.
 */
 
 import React from 'react';
-import * as sdk from '../../../index';
 import { _t } from '../../../languageHandler';
 import SettingsStore from "../../../settings/SettingsStore";
 import { SettingLevel } from "../../../settings/SettingLevel";
 import { replaceableComponent } from "../../../utils/replaceableComponent";
+import BaseDialog from "./BaseDialog";
 
 interface IProps {
     unknownProfileUsers: Array<{
@@ -50,8 +50,6 @@ export default class AskInviteAnywayDialog extends React.Component<IProps> {
     };
 
     public render() {
-        const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
-
         const errorList = this.props.unknownProfileUsers
             .map(address => <li key={address.userId}>{address.userId}: {address.errorText}</li>);
 
diff --git a/src/components/views/dialogs/ChangelogDialog.tsx b/src/components/views/dialogs/ChangelogDialog.tsx
index 8acacd8e73..d484d94249 100644
--- a/src/components/views/dialogs/ChangelogDialog.tsx
+++ b/src/components/views/dialogs/ChangelogDialog.tsx
@@ -16,9 +16,10 @@ Copyright 2019 Michael Telatynski <7t3chguy@gmail.com>
  */
 
 import React from 'react';
-import * as sdk from '../../../index';
 import request from 'browser-request';
 import { _t } from '../../../languageHandler';
+import QuestionDialog from "./QuestionDialog";
+import Spinner from "../elements/Spinner";
 
 interface IProps {
     newVersion: string;
@@ -65,9 +66,6 @@ export default class ChangelogDialog extends React.Component<IProps> {
     }
 
     public render() {
-        const Spinner = sdk.getComponent('views.elements.Spinner');
-        const QuestionDialog = sdk.getComponent('dialogs.QuestionDialog');
-
         const logs = REPOS.map(repo => {
             let content;
             if (this.state[repo] == null) {
diff --git a/src/components/views/dialogs/ConfirmRedactDialog.tsx b/src/components/views/dialogs/ConfirmRedactDialog.tsx
index 94f29a71fc..a2f2b10144 100644
--- a/src/components/views/dialogs/ConfirmRedactDialog.tsx
+++ b/src/components/views/dialogs/ConfirmRedactDialog.tsx
@@ -15,9 +15,9 @@ limitations under the License.
 */
 
 import React from 'react';
-import * as sdk from '../../../index';
 import { _t } from '../../../languageHandler';
 import { replaceableComponent } from "../../../utils/replaceableComponent";
+import TextInputDialog from "./TextInputDialog";
 
 interface IProps {
     onFinished: (success: boolean) => void;
@@ -29,7 +29,6 @@ interface IProps {
 @replaceableComponent("views.dialogs.ConfirmRedactDialog")
 export default class ConfirmRedactDialog extends React.Component<IProps> {
     render() {
-        const TextInputDialog = sdk.getComponent('views.dialogs.TextInputDialog');
         return (
             <TextInputDialog onFinished={this.props.onFinished}
                 title={_t("Confirm Removal")}
diff --git a/src/components/views/dialogs/DeactivateAccountDialog.tsx b/src/components/views/dialogs/DeactivateAccountDialog.tsx
index 6df6056670..b2ac849314 100644
--- a/src/components/views/dialogs/DeactivateAccountDialog.tsx
+++ b/src/components/views/dialogs/DeactivateAccountDialog.tsx
@@ -17,7 +17,6 @@ limitations under the License.
 
 import React from 'react';
 
-import * as sdk from '../../../index';
 import Analytics from '../../../Analytics';
 import { MatrixClientPeg } from '../../../MatrixClientPeg';
 import * as Lifecycle from '../../../Lifecycle';
@@ -26,6 +25,7 @@ import InteractiveAuth, { ERROR_USER_CANCELLED } from "../../structures/Interact
 import { DEFAULT_PHASE, PasswordAuthEntry, SSOAuthEntry } from "../auth/InteractiveAuthEntryComponents";
 import StyledCheckbox from "../elements/StyledCheckbox";
 import { replaceableComponent } from "../../../utils/replaceableComponent";
+import BaseDialog from "./BaseDialog";
 
 interface IProps {
     onFinished: (success: boolean) => void;
@@ -165,8 +165,6 @@ export default class DeactivateAccountDialog extends React.Component<IProps, ISt
     }
 
     public render() {
-        const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
-
         let error = null;
         if (this.state.errStr) {
             error = <div className="error">
diff --git a/src/components/views/dialogs/ErrorDialog.tsx b/src/components/views/dialogs/ErrorDialog.tsx
index 0f675f0df7..56cd76237f 100644
--- a/src/components/views/dialogs/ErrorDialog.tsx
+++ b/src/components/views/dialogs/ErrorDialog.tsx
@@ -26,9 +26,9 @@ limitations under the License.
  */
 
 import React from 'react';
-import * as sdk from '../../../index';
 import { _t } from '../../../languageHandler';
 import { replaceableComponent } from "../../../utils/replaceableComponent";
+import BaseDialog from "./BaseDialog";
 
 interface IProps {
     onFinished: (success: boolean) => void;
@@ -57,7 +57,6 @@ export default class ErrorDialog extends React.Component<IProps, IState> {
     };
 
     public render() {
-        const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
         return (
             <BaseDialog
                 className="mx_ErrorDialog"

From 7325abebd9ee210f17e504a4d84b44d4d98d5701 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C5=A0imon=20Brandner?= <simon.bra.ag@gmail.com>
Date: Fri, 2 Jul 2021 17:19:01 +0200
Subject: [PATCH 04/31]  Third batch of burning
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
---
 .../views/dialogs/ConfirmWipeDeviceDialog.tsx        |  6 ++----
 src/components/views/dialogs/CreateGroupDialog.tsx   |  6 ++----
 .../views/dialogs/CryptoStoreTooNewDialog.tsx        |  7 +++----
 src/components/views/dialogs/DevtoolsDialog.tsx      |  5 ++---
 src/components/views/dialogs/ReportEventDialog.tsx   | 12 +++++-------
 src/components/views/dialogs/RoomSettingsDialog.tsx  |  4 +---
 src/components/views/dialogs/UploadConfirmDialog.tsx |  6 ++----
 7 files changed, 17 insertions(+), 29 deletions(-)

diff --git a/src/components/views/dialogs/ConfirmWipeDeviceDialog.tsx b/src/components/views/dialogs/ConfirmWipeDeviceDialog.tsx
index 2978179817..544d0df1c9 100644
--- a/src/components/views/dialogs/ConfirmWipeDeviceDialog.tsx
+++ b/src/components/views/dialogs/ConfirmWipeDeviceDialog.tsx
@@ -16,8 +16,9 @@ limitations under the License.
 
 import React from 'react';
 import { _t } from "../../../languageHandler";
-import * as sdk from "../../../index";
 import { replaceableComponent } from "../../../utils/replaceableComponent";
+import BaseDialog from "./BaseDialog";
+import DialogButtons from "../elements/DialogButtons";
 
 interface IProps {
     onFinished: (success: boolean) => void;
@@ -34,9 +35,6 @@ export default class ConfirmWipeDeviceDialog extends React.Component<IProps> {
     };
 
     render() {
-        const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
-        const DialogButtons = sdk.getComponent('views.elements.DialogButtons');
-
         return (
             <BaseDialog
                 className='mx_ConfirmWipeDeviceDialog'
diff --git a/src/components/views/dialogs/CreateGroupDialog.tsx b/src/components/views/dialogs/CreateGroupDialog.tsx
index f03a40ddc5..d6bb582079 100644
--- a/src/components/views/dialogs/CreateGroupDialog.tsx
+++ b/src/components/views/dialogs/CreateGroupDialog.tsx
@@ -15,11 +15,12 @@ limitations under the License.
 */
 
 import React from 'react';
-import * as sdk from '../../../index';
 import dis from '../../../dispatcher/dispatcher';
 import { _t } from '../../../languageHandler';
 import { MatrixClientPeg } from '../../../MatrixClientPeg';
 import { replaceableComponent } from "../../../utils/replaceableComponent";
+import BaseDialog from "./BaseDialog";
+import Spinner from "../elements/Spinner";
 
 interface IProps {
     onFinished: (success: boolean) => void;
@@ -106,9 +107,6 @@ export default class CreateGroupDialog extends React.Component<IProps, IState> {
     };
 
     render() {
-        const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
-        const Spinner = sdk.getComponent('elements.Spinner');
-
         if (this.state.creating) {
             return <Spinner />;
         }
diff --git a/src/components/views/dialogs/CryptoStoreTooNewDialog.tsx b/src/components/views/dialogs/CryptoStoreTooNewDialog.tsx
index 2cdaf9cf4f..b1c3ff229a 100644
--- a/src/components/views/dialogs/CryptoStoreTooNewDialog.tsx
+++ b/src/components/views/dialogs/CryptoStoreTooNewDialog.tsx
@@ -16,11 +16,13 @@ limitations under the License.
 */
 
 import React from 'react';
-import * as sdk from '../../../index';
 import dis from '../../../dispatcher/dispatcher';
 import { _t } from '../../../languageHandler';
 import SdkConfig from '../../../SdkConfig';
 import Modal from '../../../Modal';
+import BaseDialog from "./BaseDialog";
+import DialogButtons from "../elements/DialogButtons";
+import QuestionDialog from "./QuestionDialog";
 
 interface IProps {
     onFinished: (success: boolean) => void;
@@ -30,7 +32,6 @@ export default (props: IProps) => {
     const brand = SdkConfig.get().brand;
 
     const _onLogoutClicked = () => {
-        const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
         Modal.createTrackedDialog('Logout e2e db too new', '', QuestionDialog, {
             title: _t("Sign out"),
             description: _t(
@@ -58,8 +59,6 @@ export default (props: IProps) => {
             { brand },
         );
 
-    const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
-    const DialogButtons = sdk.getComponent('views.elements.DialogButtons');
     return (<BaseDialog className="mx_CryptoStoreTooNewDialog"
         contentId='mx_Dialog_content'
         title={_t("Incompatible Database")}
diff --git a/src/components/views/dialogs/DevtoolsDialog.tsx b/src/components/views/dialogs/DevtoolsDialog.tsx
index de958f8e9a..86b8f93d7b 100644
--- a/src/components/views/dialogs/DevtoolsDialog.tsx
+++ b/src/components/views/dialogs/DevtoolsDialog.tsx
@@ -16,7 +16,6 @@ limitations under the License.
 */
 
 import React, { useState, useEffect, ChangeEvent, MouseEvent } from 'react';
-import * as sdk from '../../../index';
 import SyntaxHighlight from '../elements/SyntaxHighlight';
 import { _t } from '../../../languageHandler';
 import Field from "../elements/Field";
@@ -42,6 +41,8 @@ import { replaceableComponent } from "../../../utils/replaceableComponent";
 import { Room } from "matrix-js-sdk/src/models/room";
 import { MatrixEvent } from "matrix-js-sdk/src/models/event";
 import { SettingLevel } from '../../../settings/SettingLevel';
+import BaseDialog from "./BaseDialog";
+import TruncatedList from "../elements/TruncatedList";
 
 interface IGenericEditorProps {
     onBack: () => void;
@@ -369,7 +370,6 @@ class FilteredList extends React.PureComponent<IFilteredListProps, IFilteredList
     };
 
     render() {
-        const TruncatedList = sdk.getComponent("elements.TruncatedList");
         return <div>
             <Field label={_t('Filter results')} autoFocus={true} size={64}
                 type="text" autoComplete="off" value={this.props.query} onChange={this.onQuery}
@@ -1261,7 +1261,6 @@ export default class DevtoolsDialog extends React.PureComponent<IProps, IState>
             </React.Fragment>;
         }
 
-        const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
         return (
             <BaseDialog className="mx_QuestionDialog" onFinished={this.props.onFinished} title={_t('Developer Tools')}>
                 { body }
diff --git a/src/components/views/dialogs/ReportEventDialog.tsx b/src/components/views/dialogs/ReportEventDialog.tsx
index 81a7d569fe..494fd59082 100644
--- a/src/components/views/dialogs/ReportEventDialog.tsx
+++ b/src/components/views/dialogs/ReportEventDialog.tsx
@@ -15,7 +15,6 @@ limitations under the License.
 */
 
 import React from 'react';
-import * as sdk from '../../../index';
 import { _t } from '../../../languageHandler';
 import { ensureDMExists } from "../../../createRoom";
 import { IDialogProps } from "./IDialogProps";
@@ -26,6 +25,10 @@ import Markdown from '../../../Markdown';
 import { replaceableComponent } from "../../../utils/replaceableComponent";
 import SettingsStore from "../../../settings/SettingsStore";
 import StyledRadioButton from "../elements/StyledRadioButton";
+import BaseDialog from "./BaseDialog";
+import DialogButtons from "../elements/DialogButtons";
+import Field from "../elements/Field";
+import Spinner from "../elements/Spinner";
 
 interface IProps extends IDialogProps {
     mxEvent: MatrixEvent;
@@ -239,11 +242,6 @@ export default class ReportEventDialog extends React.Component<IProps, IState> {
     };
 
     render() {
-        const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
-        const DialogButtons = sdk.getComponent('views.elements.DialogButtons');
-        const Loader = sdk.getComponent('elements.Spinner');
-        const Field = sdk.getComponent('elements.Field');
-
         let error = null;
         if (this.state.err) {
             error = <div className="error">
@@ -255,7 +253,7 @@ export default class ReportEventDialog extends React.Component<IProps, IState> {
         if (this.state.busy) {
             progress = (
                 <div className="progress">
-                    <Loader />
+                    <Spinner />
                 </div>
             );
         }
diff --git a/src/components/views/dialogs/RoomSettingsDialog.tsx b/src/components/views/dialogs/RoomSettingsDialog.tsx
index 005222a94e..a426dce5c7 100644
--- a/src/components/views/dialogs/RoomSettingsDialog.tsx
+++ b/src/components/views/dialogs/RoomSettingsDialog.tsx
@@ -24,12 +24,12 @@ import GeneralRoomSettingsTab from "../settings/tabs/room/GeneralRoomSettingsTab
 import SecurityRoomSettingsTab from "../settings/tabs/room/SecurityRoomSettingsTab";
 import NotificationSettingsTab from "../settings/tabs/room/NotificationSettingsTab";
 import BridgeSettingsTab from "../settings/tabs/room/BridgeSettingsTab";
-import * as sdk from "../../../index";
 import { MatrixClientPeg } from "../../../MatrixClientPeg";
 import dis from "../../../dispatcher/dispatcher";
 import SettingsStore from "../../../settings/SettingsStore";
 import { UIFeature } from "../../../settings/UIFeature";
 import { replaceableComponent } from "../../../utils/replaceableComponent";
+import BaseDialog from "./BaseDialog";
 
 export const ROOM_GENERAL_TAB = "ROOM_GENERAL_TAB";
 export const ROOM_SECURITY_TAB = "ROOM_SECURITY_TAB";
@@ -119,8 +119,6 @@ export default class RoomSettingsDialog extends React.Component<IProps> {
     }
 
     render() {
-        const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
-
         const roomName = MatrixClientPeg.get().getRoom(this.props.roomId).name;
         return (
             <BaseDialog
diff --git a/src/components/views/dialogs/UploadConfirmDialog.tsx b/src/components/views/dialogs/UploadConfirmDialog.tsx
index 5024880c1c..e68067cd2b 100644
--- a/src/components/views/dialogs/UploadConfirmDialog.tsx
+++ b/src/components/views/dialogs/UploadConfirmDialog.tsx
@@ -16,11 +16,12 @@ limitations under the License.
 */
 
 import React from 'react';
-import * as sdk from '../../../index';
 import { _t } from '../../../languageHandler';
 import filesize from "filesize";
 import { replaceableComponent } from "../../../utils/replaceableComponent";
 import { getBlobSafeMimeType } from '../../../utils/blobs';
+import BaseDialog from "./BaseDialog";
+import DialogButtons from "../elements/DialogButtons";
 
 interface IProps {
     file: File;
@@ -67,9 +68,6 @@ export default class UploadConfirmDialog extends React.Component<IProps> {
     };
 
     render() {
-        const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
-        const DialogButtons = sdk.getComponent('views.elements.DialogButtons');
-
         let title;
         if (this.props.totalFiles > 1 && this.props.currentIndex !== undefined) {
             title = _t(

From 426c79f47ddc4ea749913cd6be8b09b44fe9720a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C5=A0imon=20Brandner?= <simon.bra.ag@gmail.com>
Date: Fri, 2 Jul 2021 17:25:30 +0200
Subject: [PATCH 05/31] Delint
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
---
 src/MatrixClientPeg.ts                                   | 2 +-
 src/SecurityManager.ts                                   | 1 +
 src/components/views/dialogs/CryptoStoreTooNewDialog.tsx | 4 +++-
 3 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/src/MatrixClientPeg.ts b/src/MatrixClientPeg.ts
index db8401baba..7b3c069412 100644
--- a/src/MatrixClientPeg.ts
+++ b/src/MatrixClientPeg.ts
@@ -34,7 +34,7 @@ import IdentityAuthClient from './IdentityAuthClient';
 import { crossSigningCallbacks, tryToUnlockSecretStorageWithDehydrationKey } from './SecurityManager';
 import { SHOW_QR_CODE_METHOD } from "matrix-js-sdk/src/crypto/verification/QRCode";
 import SecurityCustomisations from "./customisations/Security";
-import CryptoStoreTooNewDialog from ".components/views/dialogs/CryptoStoreTooNewDialog";
+import CryptoStoreTooNewDialog from "./components/views/dialogs/CryptoStoreTooNewDialog";
 
 export interface IMatrixClientCreds {
     homeserverUrl: string;
diff --git a/src/SecurityManager.ts b/src/SecurityManager.ts
index 8479eadddb..b6736cb69c 100644
--- a/src/SecurityManager.ts
+++ b/src/SecurityManager.ts
@@ -29,6 +29,7 @@ import SettingsStore from "./settings/SettingsStore";
 import SecurityCustomisations from "./customisations/Security";
 import { DeviceTrustLevel } from 'matrix-js-sdk/src/crypto/CrossSigning';
 import InteractiveAuthDialog from "./components/views/dialogs/InteractiveAuthDialog";
+import QuestionDialog from "./components/views/dialogs/QuestionDialog";
 
 // 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
diff --git a/src/components/views/dialogs/CryptoStoreTooNewDialog.tsx b/src/components/views/dialogs/CryptoStoreTooNewDialog.tsx
index b1c3ff229a..134c4ab79e 100644
--- a/src/components/views/dialogs/CryptoStoreTooNewDialog.tsx
+++ b/src/components/views/dialogs/CryptoStoreTooNewDialog.tsx
@@ -28,7 +28,7 @@ interface IProps {
     onFinished: (success: boolean) => void;
 }
 
-export default (props: IProps) => {
+const CryptoStoreTooNewDialog: React.FC<IProps> = (props: IProps) => {
     const brand = SdkConfig.get().brand;
 
     const _onLogoutClicked = () => {
@@ -78,3 +78,5 @@ export default (props: IProps) => {
         </DialogButtons>
     </BaseDialog>);
 };
+
+export default CryptoStoreTooNewDialog;

From dcb555784864e7d9b9f901c7f2ffa66cabca520a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C5=A0imon=20Brandner?= <simon.bra.ag@gmail.com>
Date: Fri, 2 Jul 2021 18:00:07 +0200
Subject: [PATCH 06/31] Revert some changes due to failing tests
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
---
 src/Analytics.tsx      | 4 +++-
 src/AsyncWrapper.tsx   | 8 +++++---
 src/MatrixClientPeg.ts | 5 ++++-
 src/SecurityManager.ts | 6 ++++--
 src/Terms.ts           | 4 +++-
 5 files changed, 19 insertions(+), 8 deletions(-)

diff --git a/src/Analytics.tsx b/src/Analytics.tsx
index 6a1608b63f..ce8287de56 100644
--- a/src/Analytics.tsx
+++ b/src/Analytics.tsx
@@ -21,7 +21,7 @@ import { getCurrentLanguage, _t, _td, IVariables } from './languageHandler';
 import PlatformPeg from './PlatformPeg';
 import SdkConfig from './SdkConfig';
 import Modal from './Modal';
-import ErrorDialog from './components/views/dialogs/ErrorDialog';
+import * as sdk from './index';
 
 const hashRegex = /#\/(groups?|room|user|settings|register|login|forgot_password|home|directory)/;
 const hashVarRegex = /#\/(group|room|user)\/.*$/;
@@ -390,6 +390,8 @@ export class Analytics {
             { expl: _td('Your device resolution'), value: resolution },
         ];
 
+        // FIXME: Using an import will result in test failures
+        const ErrorDialog = sdk.getComponent('dialogs.ErrorDialog');
         Modal.createTrackedDialog('Analytics Details', '', ErrorDialog, {
             title: _t('Analytics'),
             description: <div className="mx_AnalyticsModal">
diff --git a/src/AsyncWrapper.tsx b/src/AsyncWrapper.tsx
index 5d3531be62..ef8924add8 100644
--- a/src/AsyncWrapper.tsx
+++ b/src/AsyncWrapper.tsx
@@ -16,11 +16,9 @@ limitations under the License.
 
 import React, { ComponentType } from "react";
 
+import * as sdk from './index';
 import { _t } from './languageHandler';
 import { IDialogProps } from "./components/views/dialogs/IDialogProps";
-import BaseDialog from "./components/views/dialogs/BaseDialog";
-import Spinner from "./components/views/elements/Spinner";
-import DialogButtons from "./components/views/elements/DialogButtons";
 
 type AsyncImport<T> = { default: T };
 
@@ -79,6 +77,9 @@ export default class AsyncWrapper extends React.Component<IProps, IState> {
             const Component = this.state.component;
             return <Component {...this.props} />;
         } else if (this.state.error) {
+            // FIXME: Using an import will result in test failures
+            const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
+            const DialogButtons = sdk.getComponent('views.elements.DialogButtons');
             return <BaseDialog onFinished={this.props.onFinished} title={_t("Error")}>
                 { _t("Unable to load! Check your network connectivity and try again.") }
                 <DialogButtons primaryButton={_t("Dismiss")}
@@ -88,6 +89,7 @@ export default class AsyncWrapper extends React.Component<IProps, IState> {
             </BaseDialog>;
         } else {
             // show a spinner until the component is loaded.
+            const Spinner = sdk.getComponent("elements.Spinner");
             return <Spinner />;
         }
     }
diff --git a/src/MatrixClientPeg.ts b/src/MatrixClientPeg.ts
index 7b3c069412..063c5f4cad 100644
--- a/src/MatrixClientPeg.ts
+++ b/src/MatrixClientPeg.ts
@@ -23,6 +23,7 @@ import { MemoryStore } from 'matrix-js-sdk/src/store/memory';
 import * as utils from 'matrix-js-sdk/src/utils';
 import { EventTimeline } from 'matrix-js-sdk/src/models/event-timeline';
 import { EventTimelineSet } from 'matrix-js-sdk/src/models/event-timeline-set';
+import * as sdk from './index';
 import createMatrixClient from './utils/createMatrixClient';
 import SettingsStore from './settings/SettingsStore';
 import MatrixActionCreators from './actions/MatrixActionCreators';
@@ -34,7 +35,6 @@ import IdentityAuthClient from './IdentityAuthClient';
 import { crossSigningCallbacks, tryToUnlockSecretStorageWithDehydrationKey } from './SecurityManager';
 import { SHOW_QR_CODE_METHOD } from "matrix-js-sdk/src/crypto/verification/QRCode";
 import SecurityCustomisations from "./customisations/Security";
-import CryptoStoreTooNewDialog from "./components/views/dialogs/CryptoStoreTooNewDialog";
 
 export interface IMatrixClientCreds {
     homeserverUrl: string;
@@ -219,6 +219,9 @@ class _MatrixClientPeg implements IMatrixClientPeg {
         } catch (e) {
             if (e && e.name === 'InvalidCryptoStoreError') {
                 // The js-sdk found a crypto DB too new for it to use
+                // FIXME: Using an import will result in test failures
+                const CryptoStoreTooNewDialog =
+                    sdk.getComponent("views.dialogs.CryptoStoreTooNewDialog");
                 Modal.createDialog(CryptoStoreTooNewDialog);
             }
             // this can happen for a number of reasons, the most likely being
diff --git a/src/SecurityManager.ts b/src/SecurityManager.ts
index b6736cb69c..6805dfde19 100644
--- a/src/SecurityManager.ts
+++ b/src/SecurityManager.ts
@@ -17,6 +17,7 @@ limitations under the License.
 import { ICryptoCallbacks, ISecretStorageKeyInfo } from 'matrix-js-sdk/src/matrix';
 import { MatrixClient } from 'matrix-js-sdk/src/client';
 import Modal from './Modal';
+import * as sdk from './index';
 import { MatrixClientPeg } from './MatrixClientPeg';
 import { deriveKey } from 'matrix-js-sdk/src/crypto/key_passphrase';
 import { decodeRecoveryKey } from 'matrix-js-sdk/src/crypto/recoverykey';
@@ -28,8 +29,6 @@ import RestoreKeyBackupDialog from './components/views/dialogs/security/RestoreK
 import SettingsStore from "./settings/SettingsStore";
 import SecurityCustomisations from "./customisations/Security";
 import { DeviceTrustLevel } from 'matrix-js-sdk/src/crypto/CrossSigning';
-import InteractiveAuthDialog from "./components/views/dialogs/InteractiveAuthDialog";
-import QuestionDialog from "./components/views/dialogs/QuestionDialog";
 
 // 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
@@ -69,6 +68,7 @@ export class AccessCancelledError extends Error {
 }
 
 async function confirmToDismiss(): Promise<boolean> {
+    const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
     const [sure] = await Modal.createDialog(QuestionDialog, {
         title: _t("Cancel entering passphrase?"),
         description: _t("Are you sure you want to cancel entering passphrase?"),
@@ -354,6 +354,8 @@ export async function accessSecretStorage(func = async () => { }, forceReset = f
                 throw new Error("Secret storage creation canceled");
             }
         } else {
+            // FIXME: Using an import will result in test failures
+            const InteractiveAuthDialog = sdk.getComponent("dialogs.InteractiveAuthDialog");
             await cli.bootstrapCrossSigning({
                 authUploadDeviceSigningKeys: async (makeRequest) => {
                     const { finished } = Modal.createTrackedDialog(
diff --git a/src/Terms.ts b/src/Terms.ts
index d07555e567..351d1c0951 100644
--- a/src/Terms.ts
+++ b/src/Terms.ts
@@ -18,8 +18,8 @@ import classNames from 'classnames';
 import { SERVICE_TYPES } from 'matrix-js-sdk/src/service-types';
 
 import { MatrixClientPeg } from './MatrixClientPeg';
+import * as sdk from '.';
 import Modal from './Modal';
-import TermsDialog from './components/views/dialogs/TermsDialog';
 
 export class TermsNotSignedError extends Error {}
 
@@ -189,6 +189,8 @@ export function dialogTermsInteractionCallback(
 ): Promise<string[]> {
     return new Promise((resolve, reject) => {
         console.log("Terms that need agreement", policiesAndServicePairs);
+        // FIXME: Using an import will result in test failures
+        const TermsDialog = sdk.getComponent("views.dialogs.TermsDialog");
 
         Modal.createTrackedDialog('Terms of Service', '', TermsDialog, {
             policiesAndServicePairs,

From b40027a19303886b533182ebc53214375c706882 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C5=A0imon=20Brandner?= <simon.bra.ag@gmail.com>
Date: Fri, 2 Jul 2021 18:02:41 +0200
Subject: [PATCH 07/31] Delint
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
---
 .../views/dialogs/eventindex/ManageEventIndexDialog.tsx         | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/async-components/views/dialogs/eventindex/ManageEventIndexDialog.tsx b/src/async-components/views/dialogs/eventindex/ManageEventIndexDialog.tsx
index 9da724b535..c5c8022346 100644
--- a/src/async-components/views/dialogs/eventindex/ManageEventIndexDialog.tsx
+++ b/src/async-components/views/dialogs/eventindex/ManageEventIndexDialog.tsx
@@ -177,7 +177,7 @@ export default class ManageEventIndexDialog extends React.Component<IProps, ISta
                     <Field
                         label={_t('Message downloading sleep time(ms)')}
                         type='number'
-                        value={this.state.crawlerSleepTime}
+                        value={this.state.crawlerSleepTime.toString()}
                         onChange={this.onCrawlerSleepTimeChange} />
                 </div>
             </div>

From b36a727a09931e17174232ef205069ec82f3954d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C5=A0imon=20Brandner?= <simon.bra.ag@gmail.com>
Date: Fri, 2 Jul 2021 18:15:05 +0200
Subject: [PATCH 08/31] Fourth batch of burning
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
---
 .../views/settings/tabs/room/SecurityRoomSettingsTab.tsx  | 4 +---
 .../views/settings/tabs/user/HelpUserSettingsTab.tsx      | 8 ++------
 .../settings/tabs/user/PreferencesUserSettingsTab.tsx     | 3 +--
 src/toasts/SetupEncryptionToast.ts                        | 3 +--
 test/components/views/rooms/MemberList-test.tsx           | 5 +++--
 5 files changed, 8 insertions(+), 15 deletions(-)

diff --git a/src/components/views/settings/tabs/room/SecurityRoomSettingsTab.tsx b/src/components/views/settings/tabs/room/SecurityRoomSettingsTab.tsx
index 4868ffd4fc..312d7f21a0 100644
--- a/src/components/views/settings/tabs/room/SecurityRoomSettingsTab.tsx
+++ b/src/components/views/settings/tabs/room/SecurityRoomSettingsTab.tsx
@@ -18,7 +18,6 @@ import React from 'react';
 import { MatrixEvent } from "matrix-js-sdk/src/models/event";
 import { _t } from "../../../../../languageHandler";
 import { MatrixClientPeg } from "../../../../../MatrixClientPeg";
-import * as sdk from "../../../../..";
 import LabelledToggleSwitch from "../../../elements/LabelledToggleSwitch";
 import Modal from "../../../../../Modal";
 import QuestionDialog from "../../../dialogs/QuestionDialog";
@@ -27,6 +26,7 @@ import { SettingLevel } from "../../../../../settings/SettingLevel";
 import SettingsStore from "../../../../../settings/SettingsStore";
 import { UIFeature } from "../../../../../settings/UIFeature";
 import { replaceableComponent } from "../../../../../utils/replaceableComponent";
+import SettingsFlag from '../../../elements/SettingsFlag';
 
 // Knock and private are reserved keywords which are not yet implemented.
 export enum JoinRule {
@@ -385,8 +385,6 @@ export default class SecurityRoomSettingsTab extends React.Component<IProps, ISt
     }
 
     render() {
-        const SettingsFlag = sdk.getComponent("elements.SettingsFlag");
-
         const client = MatrixClientPeg.get();
         const room = client.getRoom(this.props.roomId);
         const isEncrypted = this.state.encrypted;
diff --git a/src/components/views/settings/tabs/user/HelpUserSettingsTab.tsx b/src/components/views/settings/tabs/user/HelpUserSettingsTab.tsx
index 57602c5f1b..608d973992 100644
--- a/src/components/views/settings/tabs/user/HelpUserSettingsTab.tsx
+++ b/src/components/views/settings/tabs/user/HelpUserSettingsTab.tsx
@@ -22,7 +22,6 @@ import AccessibleTooltipButton from '../../../elements/AccessibleTooltipButton';
 import SdkConfig from "../../../../../SdkConfig";
 import createRoom from "../../../../../createRoom";
 import Modal from "../../../../../Modal";
-import * as sdk from "../../../../..";
 import PlatformPeg from "../../../../../PlatformPeg";
 import * as KeyboardShortcuts from "../../../../../accessibility/KeyboardShortcuts";
 import UpdateCheckButton from "../../UpdateCheckButton";
@@ -30,6 +29,8 @@ import { replaceableComponent } from "../../../../../utils/replaceableComponent"
 import { copyPlaintext } from "../../../../../utils/strings";
 import * as ContextMenu from "../../../../structures/ContextMenu";
 import { toRightOf } from "../../../../structures/ContextMenu";
+import BugReportDialog from '../../../dialogs/BugReportDialog';
+import GenericTextContextMenu from "../../../context_menus/GenericTextContextMenu";
 
 interface IProps {
     closeSettingsFn: () => void;
@@ -81,10 +82,6 @@ export default class HelpUserSettingsTab extends React.Component<IProps, IState>
     };
 
     private onBugReport = (e) => {
-        const BugReportDialog = sdk.getComponent("dialogs.BugReportDialog");
-        if (!BugReportDialog) {
-            return;
-        }
         Modal.createTrackedDialog('Bug Report Dialog', '', BugReportDialog, {});
     };
 
@@ -171,7 +168,6 @@ export default class HelpUserSettingsTab extends React.Component<IProps, IState>
 
         const successful = await copyPlaintext(MatrixClientPeg.get().getAccessToken());
         const buttonRect = target.getBoundingClientRect();
-        const GenericTextContextMenu = sdk.getComponent('context_menus.GenericTextContextMenu');
         const { close } = ContextMenu.createMenu(GenericTextContextMenu, {
             ...toRightOf(buttonRect, 2),
             message: successful ? _t('Copied!') : _t('Failed to copy'),
diff --git a/src/components/views/settings/tabs/user/PreferencesUserSettingsTab.tsx b/src/components/views/settings/tabs/user/PreferencesUserSettingsTab.tsx
index 1988ec50ac..ebef2b96bf 100644
--- a/src/components/views/settings/tabs/user/PreferencesUserSettingsTab.tsx
+++ b/src/components/views/settings/tabs/user/PreferencesUserSettingsTab.tsx
@@ -20,10 +20,10 @@ import { _t } from "../../../../../languageHandler";
 import LabelledToggleSwitch from "../../../elements/LabelledToggleSwitch";
 import SettingsStore from "../../../../../settings/SettingsStore";
 import Field from "../../../elements/Field";
-import * as sdk from "../../../../..";
 import PlatformPeg from "../../../../../PlatformPeg";
 import { SettingLevel } from "../../../../../settings/SettingLevel";
 import { replaceableComponent } from "../../../../../utils/replaceableComponent";
+import SettingsFlag from '../../../elements/SettingsFlag';
 
 interface IState {
     autoLaunch: boolean;
@@ -174,7 +174,6 @@ export default class PreferencesUserSettingsTab extends React.Component<{}, ISta
     };
 
     private renderGroup(settingIds: string[]): React.ReactNodeArray {
-        const SettingsFlag = sdk.getComponent("views.elements.SettingsFlag");
         return settingIds.filter(SettingsStore.isEnabled).map(i => {
             return <SettingsFlag key={i} name={i} level={SettingLevel.ACCOUNT} />;
         });
diff --git a/src/toasts/SetupEncryptionToast.ts b/src/toasts/SetupEncryptionToast.ts
index ade7dfe3f0..bdaeb5142f 100644
--- a/src/toasts/SetupEncryptionToast.ts
+++ b/src/toasts/SetupEncryptionToast.ts
@@ -15,7 +15,6 @@ limitations under the License.
 */
 
 import Modal from "../Modal";
-import * as sdk from "../index";
 import { _t } from "../languageHandler";
 import DeviceListener from "../DeviceListener";
 import SetupEncryptionDialog from "../components/views/dialogs/security/SetupEncryptionDialog";
@@ -23,6 +22,7 @@ import { accessSecretStorage } from "../SecurityManager";
 import ToastStore from "../stores/ToastStore";
 import GenericToast from "../components/views/toasts/GenericToast";
 import SecurityCustomisations from "../customisations/Security";
+import Spinner from "../components/views/elements/Spinner";
 
 const TOAST_KEY = "setupencryption";
 
@@ -88,7 +88,6 @@ export const showToast = (kind: Kind) => {
             Modal.createTrackedDialog("Verify session", "Verify session", SetupEncryptionDialog,
                 {}, null, /* priority = */ false, /* static = */ true);
         } else {
-            const Spinner = sdk.getComponent("elements.Spinner");
             const modal = Modal.createDialog(
                 Spinner, null, "mx_Dialog_spinner", /* priority */ false, /* static */ true,
             );
diff --git a/test/components/views/rooms/MemberList-test.tsx b/test/components/views/rooms/MemberList-test.tsx
index a169cd08e6..f720bc7a6d 100644
--- a/test/components/views/rooms/MemberList-test.tsx
+++ b/test/components/views/rooms/MemberList-test.tsx
@@ -14,18 +14,20 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
+import "../../../skinned-sdk";
+
 import React from 'react';
 import ReactTestUtils from 'react-dom/test-utils';
 import ReactDOM from 'react-dom';
 
 import * as TestUtils from '../../../test-utils';
-import sdk from '../../../skinned-sdk';
 import { MatrixClientPeg } from '../../../../src/MatrixClientPeg';
 import { Room } from 'matrix-js-sdk/src/models/room';
 import { RoomMember } from 'matrix-js-sdk/src/models/room-member';
 import { User } from "matrix-js-sdk/src/models/user";
 import { compare } from "../../../../src/utils/strings";
 import MemberList from "../../../../src/components/views/rooms/MemberList";
+import MemberTile from '../../../../src/components/views/rooms/MemberTile';
 
 function generateRoomId() {
     return '!' + Math.random().toString().slice(2, 10) + ':domain';
@@ -206,7 +208,6 @@ describe('MemberList', () => {
     }
 
     function itDoesOrderMembersCorrectly(enablePresence) {
-        const MemberTile = sdk.getComponent("rooms.MemberTile");
         describe('does order members correctly', () => {
             // Note: even if presence is disabled, we still expect that the presence
             // tests will pass. All expectOrderedByPresenceAndPowerLevel does is ensure

From be4c29b27cb3416e72d90cf91bbe05b90223e0e1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C5=A0imon=20Brandner?= <simon.bra.ag@gmail.com>
Date: Sat, 3 Jul 2021 08:50:45 +0200
Subject: [PATCH 09/31] Revert some changes due to them breaking Element
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
---
 src/ContentMessages.tsx | 13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/src/ContentMessages.tsx b/src/ContentMessages.tsx
index dd2002dd9a..66ca8a559f 100644
--- a/src/ContentMessages.tsx
+++ b/src/ContentMessages.tsx
@@ -21,6 +21,7 @@ import { encode } from "blurhash";
 import { MatrixClient } from "matrix-js-sdk/src/client";
 
 import dis from './dispatcher/dispatcher';
+import * as sdk from './index';
 import { _t } from './languageHandler';
 import Modal from './Modal';
 import RoomViewStore from './stores/RoomViewStore';
@@ -39,10 +40,6 @@ import {
 } from "./dispatcher/payloads/UploadPayload";
 import { IUpload } from "./models/IUpload";
 import { IImageInfo } from "matrix-js-sdk/src/@types/partials";
-import QuestionDialog from "./components/views/dialogs/QuestionDialog";
-import ErrorDialog from "./components/views/dialogs/ErrorDialog";
-import UploadConfirmDialog from "./components/views/dialogs/UploadConfirmDialog";
-import UploadFailureDialog from "./components/views/dialogs/UploadFailureDialog";
 
 const MAX_WIDTH = 800;
 const MAX_HEIGHT = 600;
@@ -422,6 +419,8 @@ export default class ContentMessages {
 
         const isQuoting = Boolean(RoomViewStore.getQuotingEvent());
         if (isQuoting) {
+            // FIXME: Using an import will result in Element crashing
+            const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
             const { finished } = Modal.createTrackedDialog<[boolean]>('Upload Reply Warning', '', QuestionDialog, {
                 title: _t('Replying With Files'),
                 description: (
@@ -455,6 +454,8 @@ export default class ContentMessages {
         }
 
         if (tooBigFiles.length > 0) {
+            // FIXME: Using an import will result in Element crashing
+            const UploadFailureDialog = sdk.getComponent("dialogs.UploadFailureDialog");
             const { finished } = Modal.createTrackedDialog<[boolean]>('Upload Failure', '', UploadFailureDialog, {
                 badFiles: tooBigFiles,
                 totalFiles: files.length,
@@ -471,6 +472,8 @@ export default class ContentMessages {
         for (let i = 0; i < okFiles.length; ++i) {
             const file = okFiles[i];
             if (!uploadAll) {
+                // FIXME: Using an import will result in Element crashing
+                const UploadConfirmDialog = sdk.getComponent("dialogs.UploadConfirmDialog");
                 const { finished } = Modal.createTrackedDialog<[boolean, boolean]>('Upload Files confirmation',
                     '', UploadConfirmDialog, {
                         file,
@@ -606,6 +609,8 @@ export default class ContentMessages {
                         { fileName: upload.fileName },
                     );
                 }
+                // FIXME: Using an import will result in Element crashing
+                const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
                 Modal.createTrackedDialog('Upload failed', '', ErrorDialog, {
                     title: _t('Upload Failed'),
                     description: desc,

From 6702e68778639fa2be3c4e9879bce39b6ab37ac6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C5=A0imon=20Brandner?= <simon.bra.ag@gmail.com>
Date: Sat, 3 Jul 2021 09:36:18 +0200
Subject: [PATCH 10/31] Revert some changes due to them breaking tests (and
 hope it will work now)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
---
 src/components/structures/HomePage.tsx | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/src/components/structures/HomePage.tsx b/src/components/structures/HomePage.tsx
index 94239ea603..4ed160d493 100644
--- a/src/components/structures/HomePage.tsx
+++ b/src/components/structures/HomePage.tsx
@@ -21,6 +21,7 @@ import AutoHideScrollbar from './AutoHideScrollbar';
 import { getHomePageUrl } from "../../utils/pages";
 import { _t } from "../../languageHandler";
 import SdkConfig from "../../SdkConfig";
+import * as sdk from "../../index";
 import dis from "../../dispatcher/dispatcher";
 import { Action } from "../../dispatcher/actions";
 import BaseAvatar from "../views/avatars/BaseAvatar";
@@ -32,7 +33,6 @@ import MatrixClientContext from "../../contexts/MatrixClientContext";
 import MiniAvatarUploader, { AVATAR_SIZE } from "../views/elements/MiniAvatarUploader";
 import Analytics from "../../Analytics";
 import CountlyAnalytics from "../../CountlyAnalytics";
-import EmbeddedPage from "./EmbeddedPage";
 
 const onClickSendDm = () => {
     Analytics.trackEvent('home_page', 'button', 'dm');
@@ -96,6 +96,8 @@ const HomePage: React.FC<IProps> = ({ justRegistered = false }) => {
     const pageUrl = getHomePageUrl(config);
 
     if (pageUrl) {
+        // FIXME: Using an import will result in wrench-element-tests failures
+        const EmbeddedPage = sdk.getComponent('structures.EmbeddedPage');
         return <EmbeddedPage className="mx_HomePage" url={pageUrl} scrollbar={true} />;
     }
 

From b7ef7d2a47ae43af14b1f6a7f301aef518cacb33 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C5=A0imon=20Brandner?= <simon.bra.ag@gmail.com>
Date: Sat, 3 Jul 2021 10:06:42 +0200
Subject: [PATCH 11/31] Fifth batch of burning
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
---
 .../views/emojipicker/EmojiPicker.tsx           |  2 +-
 src/components/views/rooms/MessageComposer.tsx  |  7 ++-----
 .../views/rooms/ThirdPartyMemberInfo.tsx        |  6 ++----
 .../views/settings/E2eAdvancedPanel.tsx         |  3 +--
 .../views/settings/EventIndexPanel.tsx          |  3 +--
 src/components/views/settings/SetIdServer.tsx   | 11 ++++-------
 .../settings/tabs/room/RolesRoomSettingsTab.tsx |  8 ++------
 .../tabs/user/MjolnirUserSettingsTab.tsx        | 17 ++++-------------
 src/stores/RoomViewStore.tsx                    |  2 ++
 9 files changed, 19 insertions(+), 40 deletions(-)

diff --git a/src/components/views/emojipicker/EmojiPicker.tsx b/src/components/views/emojipicker/EmojiPicker.tsx
index 47e3823116..9b2e771e64 100644
--- a/src/components/views/emojipicker/EmojiPicker.tsx
+++ b/src/components/views/emojipicker/EmojiPicker.tsx
@@ -33,7 +33,7 @@ export const EMOJI_HEIGHT = 37;
 export const EMOJIS_PER_ROW = 8;
 
 interface IProps {
-    selectedEmojis: Set<string>;
+    selectedEmojis?: Set<string>;
     showQuickReactions?: boolean;
     onChoose(unicode: string): boolean;
 }
diff --git a/src/components/views/rooms/MessageComposer.tsx b/src/components/views/rooms/MessageComposer.tsx
index 7d61ba5ec6..2ce753cb8d 100644
--- a/src/components/views/rooms/MessageComposer.tsx
+++ b/src/components/views/rooms/MessageComposer.tsx
@@ -17,7 +17,6 @@ import React from 'react';
 import classNames from 'classnames';
 import { _t } from '../../../languageHandler';
 import { MatrixClientPeg } from '../../../MatrixClientPeg';
-import * as sdk from '../../../index';
 import { MatrixEvent } from "matrix-js-sdk/src/models/event";
 import { Room } from "matrix-js-sdk/src/models/room";
 import { RoomMember } from "matrix-js-sdk/src/models/room-member";
@@ -44,13 +43,14 @@ import SendMessageComposer from "./SendMessageComposer";
 import { ComposerInsertPayload } from "../../../dispatcher/payloads/ComposerInsertPayload";
 import { Action } from "../../../dispatcher/actions";
 import EditorModel from "../../../editor/model";
+import EmojiPicker from '../emojipicker/EmojiPicker';
+import MemberStatusMessageAvatar from "../avatars/MemberStatusMessageAvatar";
 
 interface IComposerAvatarProps {
     me: object;
 }
 
 function ComposerAvatar(props: IComposerAvatarProps) {
-    const MemberStatusMessageAvatar = sdk.getComponent('avatars.MemberStatusMessageAvatar');
     return <div className="mx_MessageComposer_avatar">
         <MemberStatusMessageAvatar member={props.me} width={24} height={24} />
     </div>;
@@ -76,7 +76,6 @@ const EmojiButton = ({ addEmoji }) => {
     let contextMenu;
     if (menuDisplayed) {
         const buttonRect = button.current.getBoundingClientRect();
-        const EmojiPicker = sdk.getComponent('emojipicker.EmojiPicker');
         contextMenu = <ContextMenu {...aboveLeftOf(buttonRect)} onFinished={closeMenu} managed={false}>
             <EmojiPicker onChoose={addEmoji} showQuickReactions={true} />
         </ContextMenu>;
@@ -366,8 +365,6 @@ export default class MessageComposer extends React.Component<IProps, IState> {
         ];
 
         if (!this.state.tombstone && this.state.canSendMessages) {
-            const SendMessageComposer = sdk.getComponent("rooms.SendMessageComposer");
-
             controls.push(
                 <SendMessageComposer
                     ref={(c) => this.messageComposerInput = c}
diff --git a/src/components/views/rooms/ThirdPartyMemberInfo.tsx b/src/components/views/rooms/ThirdPartyMemberInfo.tsx
index 4cdabede2f..2bcc3ead57 100644
--- a/src/components/views/rooms/ThirdPartyMemberInfo.tsx
+++ b/src/components/views/rooms/ThirdPartyMemberInfo.tsx
@@ -20,13 +20,14 @@ import { MatrixEvent } from "matrix-js-sdk/src/models/event";
 import { Room } from "matrix-js-sdk/src/models/room";
 import { _t } from "../../../languageHandler";
 import dis from "../../../dispatcher/dispatcher";
-import * as sdk from "../../../index";
 import Modal from "../../../Modal";
 import { isValid3pidInvite } from "../../../RoomInvite";
 import RoomAvatar from "../avatars/RoomAvatar";
 import RoomName from "../elements/RoomName";
 import { replaceableComponent } from "../../../utils/replaceableComponent";
 import SettingsStore from "../../../settings/SettingsStore";
+import ErrorDialog from '../dialogs/ErrorDialog';
+import AccessibleButton from '../elements/AccessibleButton';
 
 interface IProps {
     event: MatrixEvent;
@@ -104,7 +105,6 @@ export default class ThirdPartyMemberInfo extends React.Component<IProps, IState
                 // Revert echo because of error
                 this.setState({ invited: true });
 
-                const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
                 Modal.createTrackedDialog('Revoke 3pid invite failed', '', ErrorDialog, {
                     title: _t("Failed to revoke invite"),
                     description: _t(
@@ -119,8 +119,6 @@ export default class ThirdPartyMemberInfo extends React.Component<IProps, IState
     };
 
     render() {
-        const AccessibleButton = sdk.getComponent("elements.AccessibleButton");
-
         let adminTools = null;
         if (this.state.canKick && this.state.invited) {
             adminTools = (
diff --git a/src/components/views/settings/E2eAdvancedPanel.tsx b/src/components/views/settings/E2eAdvancedPanel.tsx
index ca7b71697e..f8746682d7 100644
--- a/src/components/views/settings/E2eAdvancedPanel.tsx
+++ b/src/components/views/settings/E2eAdvancedPanel.tsx
@@ -16,15 +16,14 @@ limitations under the License.
 
 import React from 'react';
 
-import * as sdk from '../../../index';
 import { _t } from "../../../languageHandler";
 import { SettingLevel } from "../../../settings/SettingLevel";
 import SettingsStore from "../../../settings/SettingsStore";
+import SettingsFlag from '../elements/SettingsFlag';
 
 const SETTING_MANUALLY_VERIFY_ALL_SESSIONS = "e2ee.manuallyVerifyAllSessions";
 
 const E2eAdvancedPanel = props => {
-    const SettingsFlag = sdk.getComponent('views.elements.SettingsFlag');
     return <div className="mx_SettingsTab_section">
         <span className="mx_SettingsTab_subheading">{_t("Encryption")}</span>
 
diff --git a/src/components/views/settings/EventIndexPanel.tsx b/src/components/views/settings/EventIndexPanel.tsx
index 59b4a166c0..73b324b739 100644
--- a/src/components/views/settings/EventIndexPanel.tsx
+++ b/src/components/views/settings/EventIndexPanel.tsx
@@ -18,7 +18,6 @@ import React from 'react';
 
 import { _t } from '../../../languageHandler';
 import SdkConfig from "../../../SdkConfig";
-import * as sdk from '../../../index';
 import Modal from '../../../Modal';
 import SettingsStore from "../../../settings/SettingsStore";
 import AccessibleButton from "../elements/AccessibleButton";
@@ -27,6 +26,7 @@ import EventIndexPeg from "../../../indexing/EventIndexPeg";
 import { SettingLevel } from "../../../settings/SettingLevel";
 import { replaceableComponent } from "../../../utils/replaceableComponent";
 import SeshatResetDialog from '../dialogs/SeshatResetDialog';
+import InlineSpinner from '../elements/InlineSpinner';
 
 interface IState {
     enabling: boolean;
@@ -147,7 +147,6 @@ export default class EventIndexPanel extends React.Component<{}, IState> {
 
     render() {
         let eventIndexingSettings = null;
-        const InlineSpinner = sdk.getComponent('elements.InlineSpinner');
         const brand = SdkConfig.get().brand;
 
         if (EventIndexPeg.get() !== null) {
diff --git a/src/components/views/settings/SetIdServer.tsx b/src/components/views/settings/SetIdServer.tsx
index 4a73c82d9b..9180c98101 100644
--- a/src/components/views/settings/SetIdServer.tsx
+++ b/src/components/views/settings/SetIdServer.tsx
@@ -17,7 +17,6 @@ limitations under the License.
 import url from 'url';
 import React from 'react';
 import { _t } from "../../../languageHandler";
-import * as sdk from '../../../index';
 import { MatrixClientPeg } from "../../../MatrixClientPeg";
 import Modal from '../../../Modal';
 import dis from "../../../dispatcher/dispatcher";
@@ -28,6 +27,10 @@ import { getDefaultIdentityServerUrl, doesIdentityServerHaveTerms } from '../../
 import { timeout } from "../../../utils/promise";
 import { replaceableComponent } from "../../../utils/replaceableComponent";
 import { ActionPayload } from '../../../dispatcher/payloads';
+import InlineSpinner from '../elements/InlineSpinner';
+import AccessibleButton from '../elements/AccessibleButton';
+import Field from '../elements/Field';
+import QuestionDialog from "../dialogs/QuestionDialog";
 
 // We'll wait up to this long when checking for 3PID bindings on the IS.
 const REACHABILITY_TIMEOUT = 10000; // ms
@@ -126,7 +129,6 @@ export default class SetIdServer extends React.Component<IProps, IState> {
 
     private getTooltip = () => {
         if (this.state.checking) {
-            const InlineSpinner = sdk.getComponent('views.elements.InlineSpinner');
             return <div>
                 <InlineSpinner />
                 { _t("Checking server") }
@@ -217,7 +219,6 @@ export default class SetIdServer extends React.Component<IProps, IState> {
     };
 
     private showNoTermsWarning(fullUrl) {
-        const QuestionDialog = sdk.getComponent("views.dialogs.QuestionDialog");
         const { finished } = Modal.createTrackedDialog('No Terms Warning', '', QuestionDialog, {
             title: _t("Identity server has no terms of service"),
             description: (
@@ -319,7 +320,6 @@ export default class SetIdServer extends React.Component<IProps, IState> {
             message = unboundMessage;
         }
 
-        const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
         const { finished } = Modal.createTrackedDialog('Identity Server Bound Warning', '', QuestionDialog, {
             title,
             description: message,
@@ -352,8 +352,6 @@ export default class SetIdServer extends React.Component<IProps, IState> {
     };
 
     render() {
-        const AccessibleButton = sdk.getComponent('views.elements.AccessibleButton');
-        const Field = sdk.getComponent('elements.Field');
         const idServerUrl = this.state.currentClientIdServer;
         let sectionTitle;
         let bodyText;
@@ -398,7 +396,6 @@ export default class SetIdServer extends React.Component<IProps, IState> {
                 discoButtonContent = _t("Do not use an identity server");
             }
             if (this.state.disconnectBusy) {
-                const InlineSpinner = sdk.getComponent('views.elements.InlineSpinner');
                 discoButtonContent = <InlineSpinner />;
             }
             discoSection = <div>
diff --git a/src/components/views/settings/tabs/room/RolesRoomSettingsTab.tsx b/src/components/views/settings/tabs/room/RolesRoomSettingsTab.tsx
index 67c7998751..f12499e7f9 100644
--- a/src/components/views/settings/tabs/room/RolesRoomSettingsTab.tsx
+++ b/src/components/views/settings/tabs/room/RolesRoomSettingsTab.tsx
@@ -17,7 +17,6 @@ limitations under the License.
 import React from 'react';
 import { _t, _td } from "../../../../../languageHandler";
 import { MatrixClientPeg } from "../../../../../MatrixClientPeg";
-import * as sdk from "../../../../..";
 import AccessibleButton from "../../../elements/AccessibleButton";
 import Modal from "../../../../../Modal";
 import { replaceableComponent } from "../../../../../utils/replaceableComponent";
@@ -26,6 +25,8 @@ import { RoomMember } from "matrix-js-sdk/src/models/room-member";
 import { MatrixEvent } from "matrix-js-sdk/src/models/event";
 import { RoomState } from "matrix-js-sdk/src/models/room-state";
 import { compare } from "../../../../../utils/strings";
+import ErrorDialog from '../../../dialogs/ErrorDialog';
+import PowerSelector from "../../../elements/PowerSelector";
 
 const plEventsToLabels = {
     // These will be translated for us later.
@@ -76,7 +77,6 @@ interface IBannedUserProps {
 export class BannedUser extends React.Component<IBannedUserProps> {
     private onUnbanClick = (e) => {
         MatrixClientPeg.get().unban(this.props.member.roomId, this.props.member.userId).catch((err) => {
-            const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
             console.error("Failed to unban: " + err);
             Modal.createTrackedDialog('Failed to unban', '', ErrorDialog, {
                 title: _t('Error'),
@@ -176,7 +176,6 @@ export default class RolesRoomSettingsTab extends React.Component<IProps> {
         client.sendStateEvent(this.props.roomId, "m.room.power_levels", plContent).catch(e => {
             console.error(e);
 
-            const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
             Modal.createTrackedDialog('Power level requirement change failed', '', ErrorDialog, {
                 title: _t('Error changing power level requirement'),
                 description: _t(
@@ -203,7 +202,6 @@ export default class RolesRoomSettingsTab extends React.Component<IProps> {
         client.sendStateEvent(this.props.roomId, "m.room.power_levels", plContent).catch(e => {
             console.error(e);
 
-            const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
             Modal.createTrackedDialog('Power level change failed', '', ErrorDialog, {
                 title: _t('Error changing power level'),
                 description: _t(
@@ -215,8 +213,6 @@ export default class RolesRoomSettingsTab extends React.Component<IProps> {
     };
 
     render() {
-        const PowerSelector = sdk.getComponent('elements.PowerSelector');
-
         const client = MatrixClientPeg.get();
         const room = client.getRoom(this.props.roomId);
         const plEvent = room.currentState.getStateEvents('m.room.power_levels', '');
diff --git a/src/components/views/settings/tabs/user/MjolnirUserSettingsTab.tsx b/src/components/views/settings/tabs/user/MjolnirUserSettingsTab.tsx
index 0a2b9f3212..41c44e65a0 100644
--- a/src/components/views/settings/tabs/user/MjolnirUserSettingsTab.tsx
+++ b/src/components/views/settings/tabs/user/MjolnirUserSettingsTab.tsx
@@ -22,8 +22,11 @@ import { ListRule } from "../../../../../mjolnir/ListRule";
 import { BanList, RULE_SERVER, RULE_USER } from "../../../../../mjolnir/BanList";
 import Modal from "../../../../../Modal";
 import { MatrixClientPeg } from "../../../../../MatrixClientPeg";
-import * as sdk from "../../../../../index";
 import { replaceableComponent } from "../../../../../utils/replaceableComponent";
+import ErrorDialog from "../../../dialogs/ErrorDialog";
+import QuestionDialog from "../../../dialogs/QuestionDialog";
+import AccessibleButton from "../../../elements/AccessibleButton";
+import Field from "../../../elements/Field";
 
 interface IState {
     busy: boolean;
@@ -68,7 +71,6 @@ export default class MjolnirUserSettingsTab extends React.Component<{}, IState>
         } catch (e) {
             console.error(e);
 
-            const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
             Modal.createTrackedDialog('Failed to add Mjolnir rule', '', ErrorDialog, {
                 title: _t('Error adding ignored user/server'),
                 description: _t('Something went wrong. Please try again or view your console for hints.'),
@@ -90,7 +92,6 @@ export default class MjolnirUserSettingsTab extends React.Component<{}, IState>
         } catch (e) {
             console.error(e);
 
-            const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
             Modal.createTrackedDialog('Failed to subscribe to Mjolnir list', '', ErrorDialog, {
                 title: _t('Error subscribing to list'),
                 description: _t('Please verify the room ID or address and try again.'),
@@ -108,7 +109,6 @@ export default class MjolnirUserSettingsTab extends React.Component<{}, IState>
         } catch (e) {
             console.error(e);
 
-            const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
             Modal.createTrackedDialog('Failed to remove Mjolnir rule', '', ErrorDialog, {
                 title: _t('Error removing ignored user/server'),
                 description: _t('Something went wrong. Please try again or view your console for hints.'),
@@ -126,7 +126,6 @@ export default class MjolnirUserSettingsTab extends React.Component<{}, IState>
         } catch (e) {
             console.error(e);
 
-            const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
             Modal.createTrackedDialog('Failed to unsubscribe from Mjolnir list', '', ErrorDialog, {
                 title: _t('Error unsubscribing from list'),
                 description: _t('Please try again or view your console for hints.'),
@@ -137,8 +136,6 @@ export default class MjolnirUserSettingsTab extends React.Component<{}, IState>
     }
 
     private viewListRules(list: BanList) {
-        const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
-
         const room = MatrixClientPeg.get().getRoom(list.roomId);
         const name = room ? room.name : list.roomId;
 
@@ -168,8 +165,6 @@ export default class MjolnirUserSettingsTab extends React.Component<{}, IState>
     }
 
     private renderPersonalBanListRules() {
-        const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
-
         const list = Mjolnir.sharedInstance().getPersonalList();
         const rules = list ? [...list.userRules, ...list.serverRules] : [];
         if (!list || rules.length <= 0) return <i>{_t("You have not ignored anyone.")}</i>;
@@ -199,8 +194,6 @@ export default class MjolnirUserSettingsTab extends React.Component<{}, IState>
     }
 
     private renderSubscribedBanLists() {
-        const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
-
         const personalList = Mjolnir.sharedInstance().getPersonalList();
         const lists = Mjolnir.sharedInstance().lists.filter(b => {
             return personalList? personalList.roomId !== b.roomId : true;
@@ -241,8 +234,6 @@ export default class MjolnirUserSettingsTab extends React.Component<{}, IState>
     }
 
     render() {
-        const Field = sdk.getComponent('elements.Field');
-        const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
         const brand = SdkConfig.get().brand;
 
         return (
diff --git a/src/stores/RoomViewStore.tsx b/src/stores/RoomViewStore.tsx
index 87978df471..10f42f3166 100644
--- a/src/stores/RoomViewStore.tsx
+++ b/src/stores/RoomViewStore.tsx
@@ -164,6 +164,7 @@ class RoomViewStore extends Store<ActionPayload> {
                 }
                 break;
             case 'open_room_settings': {
+                // FIXME: Using an import will result in test failures
                 const RoomSettingsDialog = sdk.getComponent("dialogs.RoomSettingsDialog");
                 Modal.createTrackedDialog('Room settings', '', RoomSettingsDialog, {
                     roomId: payload.room_id || this.state.roomId,
@@ -340,6 +341,7 @@ class RoomViewStore extends Store<ActionPayload> {
             }
         }
 
+        // FIXME: Using an import will result in test failures
         const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
         Modal.createTrackedDialog('Failed to join room', '', ErrorDialog, {
             title: _t("Failed to join room"),

From ab4cd9d0fdd1a4960bd1026fb59745d1325008a7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C5=A0imon=20Brandner?= <simon.bra.ag@gmail.com>
Date: Sat, 3 Jul 2021 10:10:17 +0200
Subject: [PATCH 12/31] Delint
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
---
 src/components/views/rooms/MessageComposer.tsx | 1 -
 1 file changed, 1 deletion(-)

diff --git a/src/components/views/rooms/MessageComposer.tsx b/src/components/views/rooms/MessageComposer.tsx
index 2ce753cb8d..b7015d2275 100644
--- a/src/components/views/rooms/MessageComposer.tsx
+++ b/src/components/views/rooms/MessageComposer.tsx
@@ -371,7 +371,6 @@ export default class MessageComposer extends React.Component<IProps, IState> {
                     key="controls_input"
                     room={this.props.room}
                     placeholder={this.renderPlaceholderText()}
-                    resizeNotifier={this.props.resizeNotifier}
                     permalinkCreator={this.props.permalinkCreator}
                     replyToEvent={this.props.replyToEvent}
                     onChange={this.onChange}

From 914de71e9c351e8617f8385f44faca35d75c8c3d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C5=A0imon=20Brandner?= <simon.bra.ag@gmail.com>
Date: Sat, 3 Jul 2021 10:44:03 +0200
Subject: [PATCH 13/31] Sixth batch of burning
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
---
 src/components/views/dialogs/BugReportDialog.tsx   | 14 ++++++--------
 src/components/views/dialogs/InviteDialog.tsx      | 10 +++-------
 src/components/views/dialogs/ShareDialog.tsx       |  5 ++---
 .../views/dialogs/UserSettingsDialog.tsx           |  4 +---
 src/components/views/elements/Field.tsx            |  1 +
 .../views/elements/SpellCheckLanguagesDropdown.tsx |  3 +--
 src/components/views/elements/ToggleSwitch.tsx     |  3 +--
 src/components/views/elements/TooltipButton.tsx    |  3 +--
 .../views/messages/MKeyVerificationRequest.tsx     |  4 +---
 .../views/right_panel/EncryptionInfo.tsx           |  5 ++---
 .../views/right_panel/EncryptionPanel.tsx          |  1 +
 .../views/right_panel/VerificationPanel.tsx        |  9 ++-------
 12 files changed, 22 insertions(+), 40 deletions(-)

diff --git a/src/components/views/dialogs/BugReportDialog.tsx b/src/components/views/dialogs/BugReportDialog.tsx
index eeb3769bf9..6baf24f797 100644
--- a/src/components/views/dialogs/BugReportDialog.tsx
+++ b/src/components/views/dialogs/BugReportDialog.tsx
@@ -18,13 +18,17 @@ limitations under the License.
 */
 
 import React from 'react';
-import * as sdk from '../../../index';
 import SdkConfig from '../../../SdkConfig';
 import Modal from '../../../Modal';
 import { _t } from '../../../languageHandler';
 import sendBugReport, { downloadBugReport } from '../../../rageshake/submit-rageshake';
 import AccessibleButton from "../elements/AccessibleButton";
 import { replaceableComponent } from "../../../utils/replaceableComponent";
+import QuestionDialog from "./QuestionDialog";
+import BaseDialog from "./BaseDialog";
+import Field from '../elements/Field';
+import Spinner from "../elements/Spinner";
+import DialogButtons from "../elements/DialogButtons";
 
 interface IProps {
     onFinished: (success: boolean) => void;
@@ -93,7 +97,6 @@ export default class BugReportDialog extends React.Component<IProps, IState> {
         }).then(() => {
             if (!this.unmounted) {
                 this.props.onFinished(false);
-                const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
                 // N.B. first param is passed to piwik and so doesn't want i18n
                 Modal.createTrackedDialog('Bug report sent', '', QuestionDialog, {
                     title: _t('Logs sent'),
@@ -160,11 +163,6 @@ export default class BugReportDialog extends React.Component<IProps, IState> {
     };
 
     public render() {
-        const Loader = sdk.getComponent("elements.Spinner");
-        const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
-        const DialogButtons = sdk.getComponent('views.elements.DialogButtons');
-        const Field = sdk.getComponent('elements.Field');
-
         let error = null;
         if (this.state.err) {
             error = <div className="error">
@@ -176,7 +174,7 @@ export default class BugReportDialog extends React.Component<IProps, IState> {
         if (this.state.busy) {
             progress = (
                 <div className="progress">
-                    <Loader />
+                    <Spinner />
                     {this.state.progress} ...
                 </div>
             );
diff --git a/src/components/views/dialogs/InviteDialog.tsx b/src/components/views/dialogs/InviteDialog.tsx
index bbb5f24162..1df5f35ae9 100644
--- a/src/components/views/dialogs/InviteDialog.tsx
+++ b/src/components/views/dialogs/InviteDialog.tsx
@@ -18,7 +18,6 @@ import React, { createRef } from 'react';
 import classNames from 'classnames';
 
 import { _t, _td } from "../../../languageHandler";
-import * as sdk from "../../../index";
 import { MatrixClientPeg } from "../../../MatrixClientPeg";
 import { makeRoomPermalink, makeUserPermalink } from "../../../utils/permalinks/Permalinks";
 import DMRoomMap from "../../../utils/DMRoomMap";
@@ -65,6 +64,9 @@ import { copyPlaintext, selectText } from "../../../utils/strings";
 import * as ContextMenu from "../../structures/ContextMenu";
 import { toRightOf } from "../../structures/ContextMenu";
 import GenericTextContextMenu from "../context_menus/GenericTextContextMenu";
+import QuestionDialog from "./QuestionDialog";
+import Spinner from "../elements/Spinner";
+import BaseDialog from "./BaseDialog";
 
 // we have a number of types defined from the Matrix spec which can't reasonably be altered here.
 /* eslint-disable camelcase */
@@ -1046,7 +1048,6 @@ export default class InviteDialog extends React.PureComponent<IInviteDialogProps
         if (this.unmounted) return;
 
         if (failed.length > 0) {
-            const QuestionDialog = sdk.getComponent('dialogs.QuestionDialog');
             Modal.createTrackedDialog('Invite Paste Fail', '', QuestionDialog, {
                 title: _t('Failed to find the following users'),
                 description: _t(
@@ -1158,7 +1159,6 @@ export default class InviteDialog extends React.PureComponent<IInviteDialogProps
         const toRender = sourceMembers.slice(0, showNum);
         const hasMore = toRender.length < sourceMembers.length;
 
-        const AccessibleButton = sdk.getComponent("elements.AccessibleButton");
         let showMore = null;
         if (hasMore) {
             showMore = (
@@ -1269,10 +1269,6 @@ export default class InviteDialog extends React.PureComponent<IInviteDialogProps
     };
 
     render() {
-        const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
-        const AccessibleButton = sdk.getComponent("elements.AccessibleButton");
-        const Spinner = sdk.getComponent("elements.Spinner");
-
         let spinner = null;
         if (this.state.busy) {
             spinner = <Spinner w={20} h={20} />;
diff --git a/src/components/views/dialogs/ShareDialog.tsx b/src/components/views/dialogs/ShareDialog.tsx
index fb43db1a25..a3443ada02 100644
--- a/src/components/views/dialogs/ShareDialog.tsx
+++ b/src/components/views/dialogs/ShareDialog.tsx
@@ -22,7 +22,6 @@ import { User } from "matrix-js-sdk/src/models/user";
 import { Group } from "matrix-js-sdk/src/models/group";
 import { RoomMember } from "matrix-js-sdk/src/models/room-member";
 import { MatrixEvent } from "matrix-js-sdk/src/models/event";
-import * as sdk from '../../../index';
 import { _t } from '../../../languageHandler';
 import QRCode from "../elements/QRCode";
 import { RoomPermalinkCreator, makeGroupPermalink, makeUserPermalink } from "../../../utils/permalinks/Permalinks";
@@ -35,6 +34,8 @@ import { IDialogProps } from "./IDialogProps";
 import SettingsStore from "../../../settings/SettingsStore";
 import { UIFeature } from "../../../settings/UIFeature";
 import { replaceableComponent } from "../../../utils/replaceableComponent";
+import BaseDialog from "./BaseDialog";
+import GenericTextContextMenu from "../context_menus/GenericTextContextMenu.js";
 
 const socials = [
     {
@@ -119,7 +120,6 @@ export default class ShareDialog extends React.PureComponent<IProps, IState> {
 
         const successful = await copyPlaintext(this.getUrl());
         const buttonRect = target.getBoundingClientRect();
-        const GenericTextContextMenu = sdk.getComponent('context_menus.GenericTextContextMenu');
         const { close } = ContextMenu.createMenu(GenericTextContextMenu, {
             ...toRightOf(buttonRect, 2),
             message: successful ? _t('Copied!') : _t('Failed to copy'),
@@ -230,7 +230,6 @@ export default class ShareDialog extends React.PureComponent<IProps, IState> {
             </>;
         }
 
-        const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
         return <BaseDialog
             title={title}
             className='mx_ShareDialog'
diff --git a/src/components/views/dialogs/UserSettingsDialog.tsx b/src/components/views/dialogs/UserSettingsDialog.tsx
index 2878a07d35..e85938afe0 100644
--- a/src/components/views/dialogs/UserSettingsDialog.tsx
+++ b/src/components/views/dialogs/UserSettingsDialog.tsx
@@ -28,11 +28,11 @@ import PreferencesUserSettingsTab from "../settings/tabs/user/PreferencesUserSet
 import VoiceUserSettingsTab from "../settings/tabs/user/VoiceUserSettingsTab";
 import HelpUserSettingsTab from "../settings/tabs/user/HelpUserSettingsTab";
 import FlairUserSettingsTab from "../settings/tabs/user/FlairUserSettingsTab";
-import * as sdk from "../../../index";
 import SdkConfig from "../../../SdkConfig";
 import MjolnirUserSettingsTab from "../settings/tabs/user/MjolnirUserSettingsTab";
 import { UIFeature } from "../../../settings/UIFeature";
 import { replaceableComponent } from "../../../utils/replaceableComponent";
+import BaseDialog from "./BaseDialog";
 
 export enum UserTab {
     General = "USER_GENERAL_TAB",
@@ -162,8 +162,6 @@ export default class UserSettingsDialog extends React.Component<IProps, IState>
     }
 
     render() {
-        const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
-
         return (
             <BaseDialog
                 className='mx_UserSettingsDialog'
diff --git a/src/components/views/elements/Field.tsx b/src/components/views/elements/Field.tsx
index 297044e422..60f029c32e 100644
--- a/src/components/views/elements/Field.tsx
+++ b/src/components/views/elements/Field.tsx
@@ -260,6 +260,7 @@ export default class Field extends React.PureComponent<PropShapes, IState> {
         });
 
         // Handle displaying feedback on validity
+        // FIXME: Using an import will result in test failures
         const Tooltip = sdk.getComponent("elements.Tooltip");
         let fieldTooltip;
         if (tooltipContent || this.state.feedback) {
diff --git a/src/components/views/elements/SpellCheckLanguagesDropdown.tsx b/src/components/views/elements/SpellCheckLanguagesDropdown.tsx
index 1678bdb33a..5230042c38 100644
--- a/src/components/views/elements/SpellCheckLanguagesDropdown.tsx
+++ b/src/components/views/elements/SpellCheckLanguagesDropdown.tsx
@@ -17,11 +17,11 @@ limitations under the License.
 import React from 'react';
 
 import Dropdown from "../../views/elements/Dropdown";
-import * as sdk from '../../../index';
 import PlatformPeg from "../../../PlatformPeg";
 import SettingsStore from "../../../settings/SettingsStore";
 import { _t } from "../../../languageHandler";
 import { replaceableComponent } from "../../../utils/replaceableComponent";
+import Spinner from "./Spinner";
 
 function languageMatchesSearchQuery(query, language) {
     if (language.label.toUpperCase().includes(query.toUpperCase())) return true;
@@ -84,7 +84,6 @@ export default class SpellCheckLanguagesDropdown extends React.Component<SpellCh
 
     render() {
         if (this.state.languages === null) {
-            const Spinner = sdk.getComponent('elements.Spinner');
             return <Spinner />;
         }
 
diff --git a/src/components/views/elements/ToggleSwitch.tsx b/src/components/views/elements/ToggleSwitch.tsx
index 7315cc6383..c439ef4f85 100644
--- a/src/components/views/elements/ToggleSwitch.tsx
+++ b/src/components/views/elements/ToggleSwitch.tsx
@@ -17,7 +17,7 @@ limitations under the License.
 
 import React from "react";
 import classNames from "classnames";
-import * as sdk from "../../../index";
+import AccessibleButton from "./AccessibleButton";
 
 interface IProps {
     // Whether or not this toggle is in the 'on' position.
@@ -43,7 +43,6 @@ export default ({ checked, disabled = false, onChange, ...props }: IProps) => {
         "mx_ToggleSwitch_enabled": !disabled,
     });
 
-    const AccessibleButton = sdk.getComponent("elements.AccessibleButton");
     return (
         <AccessibleButton {...props}
             className={classes}
diff --git a/src/components/views/elements/TooltipButton.tsx b/src/components/views/elements/TooltipButton.tsx
index 87bf04c2ea..d60b8a341b 100644
--- a/src/components/views/elements/TooltipButton.tsx
+++ b/src/components/views/elements/TooltipButton.tsx
@@ -16,8 +16,8 @@ limitations under the License.
 */
 
 import React from 'react';
-import * as sdk from '../../../index';
 import { replaceableComponent } from "../../../utils/replaceableComponent";
+import Tooltip from './Tooltip';
 
 interface IProps {
     helpText: string;
@@ -49,7 +49,6 @@ export default class TooltipButton extends React.Component<IProps, IState> {
     };
 
     render() {
-        const Tooltip = sdk.getComponent("elements.Tooltip");
         const tip = this.state.hover ? <Tooltip
             className="mx_TooltipButton_container"
             tooltipClassName="mx_TooltipButton_helpText"
diff --git a/src/components/views/messages/MKeyVerificationRequest.tsx b/src/components/views/messages/MKeyVerificationRequest.tsx
index fc550845e2..c57cb5932d 100644
--- a/src/components/views/messages/MKeyVerificationRequest.tsx
+++ b/src/components/views/messages/MKeyVerificationRequest.tsx
@@ -17,7 +17,6 @@ limitations under the License.
 import React from 'react';
 import { MatrixEvent } from 'matrix-js-sdk/src';
 import { MatrixClientPeg } from '../../../MatrixClientPeg';
-import * as sdk from '../../../index';
 import { _t } from '../../../languageHandler';
 import { getNameForEventRoom, userLabelForEventRoom }
     from '../../../utils/KeyVerificationStateObserver';
@@ -26,6 +25,7 @@ import { RightPanelPhases } from "../../../stores/RightPanelStorePhases";
 import { Action } from "../../../dispatcher/actions";
 import EventTileBubble from "./EventTileBubble";
 import { replaceableComponent } from "../../../utils/replaceableComponent";
+import AccessibleButton from '../elements/AccessibleButton';
 
 interface IProps {
     mxEvent: MatrixEvent;
@@ -115,8 +115,6 @@ export default class MKeyVerificationRequest extends React.Component<IProps> {
     }
 
     public render() {
-        const AccessibleButton = sdk.getComponent("elements.AccessibleButton");
-
         const { mxEvent } = this.props;
         const request = mxEvent.verificationRequest;
 
diff --git a/src/components/views/right_panel/EncryptionInfo.tsx b/src/components/views/right_panel/EncryptionInfo.tsx
index c34cf18710..e74caf8457 100644
--- a/src/components/views/right_panel/EncryptionInfo.tsx
+++ b/src/components/views/right_panel/EncryptionInfo.tsx
@@ -16,13 +16,13 @@ limitations under the License.
 
 import React from "react";
 
-import * as sdk from "../../../index";
 import { _t } from "../../../languageHandler";
 import { RoomMember } from "matrix-js-sdk/src/models/room-member";
 import { User } from "matrix-js-sdk/src/models/user";
+import AccessibleButton from "../elements/AccessibleButton";
+import Spinner from "../elements/Spinner";
 
 export const PendingActionSpinner = ({ text }) => {
-    const Spinner = sdk.getComponent('elements.Spinner');
     return <div className="mx_EncryptionInfo_spinner">
         <Spinner />
         { text }
@@ -64,7 +64,6 @@ const EncryptionInfo: React.FC<IProps> = ({
         }
         content = <PendingActionSpinner text={text} />;
     } else {
-        const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
         content = (
             <AccessibleButton kind="primary" className="mx_UserInfo_wideButton" onClick={onStartVerification}>
                 {_t("Start Verification")}
diff --git a/src/components/views/right_panel/EncryptionPanel.tsx b/src/components/views/right_panel/EncryptionPanel.tsx
index 251c04d3cc..9ed791c229 100644
--- a/src/components/views/right_panel/EncryptionPanel.tsx
+++ b/src/components/views/right_panel/EncryptionPanel.tsx
@@ -81,6 +81,7 @@ const EncryptionPanel: React.FC<IProps> = (props: IProps) => {
     const changeHandler = useCallback(() => {
         // handle transitions -> cancelled for mismatches which fire a modal instead of showing a card
         if (request && request.cancelled && MISMATCHES.includes(request.cancellationCode)) {
+            // FIXME: Using an import will result in test failures
             const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
             Modal.createTrackedDialog("Verification failed", "insecure", ErrorDialog, {
                 headerImage: require("../../../../res/img/e2e/warning.svg"),
diff --git a/src/components/views/right_panel/VerificationPanel.tsx b/src/components/views/right_panel/VerificationPanel.tsx
index 6087923057..a4d4d2fa30 100644
--- a/src/components/views/right_panel/VerificationPanel.tsx
+++ b/src/components/views/right_panel/VerificationPanel.tsx
@@ -17,7 +17,6 @@ limitations under the License.
 import React from "react";
 
 import { MatrixClientPeg } from "../../../MatrixClientPeg";
-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 { VerificationRequest } from "matrix-js-sdk/src/crypto/verification/request/VerificationRequest";
@@ -38,6 +37,8 @@ import {
 } from "matrix-js-sdk/src/crypto/verification/request/VerificationRequest";
 import Spinner from "../elements/Spinner";
 import { replaceableComponent } from "../../../utils/replaceableComponent";
+import AccessibleButton from "../elements/AccessibleButton";
+import VerificationShowSas from "../verification/VerificationShowSas";
 
 // XXX: Should be defined in matrix-js-sdk
 enum VerificationPhase {
@@ -81,7 +82,6 @@ export default class VerificationPanel extends React.PureComponent<IProps, IStat
         const { member, request } = this.props;
         const showSAS: boolean = request.otherPartySupportsMethod(verificationMethods.SAS);
         const showQR: boolean = request.otherPartySupportsMethod(SCAN_QR_CODE_METHOD);
-        const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
         const brand = SdkConfig.get().brand;
 
         const noCommonMethodError: JSX.Element = !showSAS && !showQR ?
@@ -195,7 +195,6 @@ export default class VerificationPanel extends React.PureComponent<IProps, IStat
 
     private renderQRReciprocatePhase() {
         const { member, request } = this.props;
-        const AccessibleButton = sdk.getComponent("elements.AccessibleButton");
         const description = request.isSelfVerification ?
             _t("Almost there! Is your other session showing the same shield?") :
             _t("Almost there! Is %(displayName)s showing the same shield?", {
@@ -265,7 +264,6 @@ export default class VerificationPanel extends React.PureComponent<IProps, IStat
             });
         }
 
-        const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
         return (
             <div className="mx_UserInfo_container mx_VerificationPanel_verified_section">
                 <h3>{_t("Verified")}</h3>
@@ -282,8 +280,6 @@ export default class VerificationPanel extends React.PureComponent<IProps, IStat
     private renderCancelledPhase() {
         const { member, request } = this.props;
 
-        const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
-
         let startAgainInstruction: string;
         if (request.isSelfVerification) {
             startAgainInstruction = _t("Start verification again from the notification.");
@@ -332,7 +328,6 @@ export default class VerificationPanel extends React.PureComponent<IProps, IStat
                     case verificationMethods.RECIPROCATE_QR_CODE:
                         return this.renderQRReciprocatePhase();
                     case verificationMethods.SAS: {
-                        const VerificationShowSas = sdk.getComponent('views.verification.VerificationShowSas');
                         const emojis = this.state.sasEvent ?
                             <VerificationShowSas
                                 displayName={displayName}

From 6e14c290c8b238ca120e996c9c40ef137a6599a4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C5=A0imon=20Brandner?= <simon.bra.ag@gmail.com>
Date: Sat, 3 Jul 2021 10:59:57 +0200
Subject: [PATCH 14/31] Seventh batch of burning
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
---
 src/components/views/elements/TooltipButton.tsx |  2 +-
 src/components/views/messages/SenderProfile.tsx |  2 +-
 src/components/views/rooms/EventTile.tsx        | 17 ++++++++---------
 3 files changed, 10 insertions(+), 11 deletions(-)

diff --git a/src/components/views/elements/TooltipButton.tsx b/src/components/views/elements/TooltipButton.tsx
index d60b8a341b..26e46c7da8 100644
--- a/src/components/views/elements/TooltipButton.tsx
+++ b/src/components/views/elements/TooltipButton.tsx
@@ -20,7 +20,7 @@ import { replaceableComponent } from "../../../utils/replaceableComponent";
 import Tooltip from './Tooltip';
 
 interface IProps {
-    helpText: string;
+    helpText: React.ReactNode | string;
 }
 
 interface IState {
diff --git a/src/components/views/messages/SenderProfile.tsx b/src/components/views/messages/SenderProfile.tsx
index 11c3ca4e3c..bdae9cec4a 100644
--- a/src/components/views/messages/SenderProfile.tsx
+++ b/src/components/views/messages/SenderProfile.tsx
@@ -24,7 +24,7 @@ import { MatrixEvent } from "matrix-js-sdk/src/models/event";
 
 interface IProps {
     mxEvent: MatrixEvent;
-    onClick(): void;
+    onClick?(): void;
     enableFlair: boolean;
 }
 
diff --git a/src/components/views/rooms/EventTile.tsx b/src/components/views/rooms/EventTile.tsx
index c9d1040433..7cceef4a86 100644
--- a/src/components/views/rooms/EventTile.tsx
+++ b/src/components/views/rooms/EventTile.tsx
@@ -47,6 +47,13 @@ import { StaticNotificationState } from "../../../stores/notifications/StaticNot
 import NotificationBadge from "./NotificationBadge";
 import { ComposerInsertPayload } from "../../../dispatcher/payloads/ComposerInsertPayload";
 import { Action } from '../../../dispatcher/actions';
+import MemberAvatar from '../avatars/MemberAvatar';
+import SenderProfile from '../messages/SenderProfile';
+import MessageTimestamp from '../messages/MessageTimestamp';
+import TooltipButton from '../elements/TooltipButton';
+import ReadReceiptMarker from "./ReadReceiptMarker";
+import MessageActionBar from "../messages/MessageActionBar";
+import ReactionsRow from '../messages/ReactionsRow';
 
 const eventTileTypes = {
     [EventType.RoomMessage]: 'messages.MessageEvent',
@@ -666,7 +673,6 @@ export default class EventTile extends React.Component<IProps, IState> {
             );
         }
 
-        const ReadReceiptMarker = sdk.getComponent('rooms.ReadReceiptMarker');
         const avatars = [];
         const receiptOffset = 15;
         let left = 0;
@@ -733,7 +739,7 @@ export default class EventTile extends React.Component<IProps, IState> {
         );
     }
 
-    onSenderProfileClick = event => {
+    onSenderProfileClick = () => {
         const mxEvent = this.props.mxEvent;
         dis.dispatch<ComposerInsertPayload>({
             action: Action.ComposerInsert,
@@ -841,10 +847,6 @@ export default class EventTile extends React.Component<IProps, IState> {
     };
 
     render() {
-        const MessageTimestamp = sdk.getComponent('messages.MessageTimestamp');
-        const SenderProfile = sdk.getComponent('messages.SenderProfile');
-        const MemberAvatar = sdk.getComponent('avatars.MemberAvatar');
-
         //console.info("EventTile showUrlPreview for %s is %s", this.props.mxEvent.getId(), this.props.showUrlPreview);
 
         const content = this.props.mxEvent.getContent();
@@ -987,7 +989,6 @@ export default class EventTile extends React.Component<IProps, IState> {
             }
         }
 
-        const MessageActionBar = sdk.getComponent('messages.MessageActionBar');
         const actionBar = !isEditing ? <MessageActionBar
             mxEvent={this.props.mxEvent}
             reactions={this.state.reactions}
@@ -1027,7 +1028,6 @@ export default class EventTile extends React.Component<IProps, IState> {
                 { 'requestLink': (sub) => <a onClick={this.onRequestKeysClick}>{ sub }</a> },
             );
 
-        const TooltipButton = sdk.getComponent('elements.TooltipButton');
         const keyRequestInfo = isEncryptionFailure && !isRedacted ?
             <div className="mx_EventTile_keyRequestInfo">
                 <span className="mx_EventTile_keyRequestInfo_text">
@@ -1038,7 +1038,6 @@ export default class EventTile extends React.Component<IProps, IState> {
 
         let reactionsRow;
         if (!isRedacted) {
-            const ReactionsRow = sdk.getComponent('messages.ReactionsRow');
             reactionsRow = <ReactionsRow
                 mxEvent={this.props.mxEvent}
                 reactions={this.state.reactions}

From 916589e2b902b99056bc0a52ecdd76ded38dda38 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C5=A0imon=20Brandner?= <simon.bra.ag@gmail.com>
Date: Sat, 3 Jul 2021 11:24:33 +0200
Subject: [PATCH 15/31] Eighth batch of burning
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
---
 src/SlashCommands.tsx                         | 19 ++++++-------------
 src/components/structures/auth/SoftLogout.tsx | 16 ++++++----------
 .../auth/InteractiveAuthEntryComponents.tsx   | 18 ++++++------------
 .../dialogs/ConfirmAndWaitRedactDialog.tsx    |  9 ++++-----
 .../views/dialogs/ConfirmUserActionDialog.tsx | 10 ++++------
 src/components/views/dialogs/TermsDialog.tsx  |  6 ++----
 .../ConfirmDestroyCrossSigningDialog.tsx      |  6 ++----
 7 files changed, 30 insertions(+), 54 deletions(-)

diff --git a/src/SlashCommands.tsx b/src/SlashCommands.tsx
index 128ca9e5e2..7753ff6f75 100644
--- a/src/SlashCommands.tsx
+++ b/src/SlashCommands.tsx
@@ -23,7 +23,6 @@ import { User } from "matrix-js-sdk/src/models/user";
 import * as ContentHelpers from 'matrix-js-sdk/src/content-helpers';
 import { MatrixClientPeg } from './MatrixClientPeg';
 import dis from './dispatcher/dispatcher';
-import * as sdk from './index';
 import { _t, _td } from './languageHandler';
 import Modal from './Modal';
 import MultiInviter from './utils/MultiInviter';
@@ -50,6 +49,12 @@ import { UIFeature } from "./settings/UIFeature";
 import { CHAT_EFFECTS } from "./effects";
 import CallHandler from "./CallHandler";
 import { guessAndSetDMRoom } from "./Rooms";
+import UploadConfirmDialog from './components/views/dialogs/UploadConfirmDialog';
+import ErrorDialog from './components/views/dialogs/ErrorDialog';
+import DevtoolsDialog from './components/views/dialogs/DevtoolsDialog';
+import RoomUpgradeWarningDialog from "./components/views/dialogs/RoomUpgradeWarningDialog";
+import InfoDialog from "./components/views/dialogs/InfoDialog";
+import SlashCommandHelpDialog from "./components/views/dialogs/SlashCommandHelpDialog";
 
 // XXX: workaround for https://github.com/microsoft/TypeScript/issues/31816
 interface HTMLInputEvent extends Event {
@@ -63,7 +68,6 @@ const singleMxcUpload = async (): Promise<any> => {
         fileSelector.onchange = (ev: HTMLInputEvent) => {
             const file = ev.target.files[0];
 
-            const UploadConfirmDialog = sdk.getComponent("dialogs.UploadConfirmDialog");
             Modal.createTrackedDialog('Upload Files confirmation', '', UploadConfirmDialog, {
                 file,
                 onFinished: (shouldContinue) => {
@@ -246,7 +250,6 @@ export const Commands = [
         args: '<query>',
         description: _td('Searches DuckDuckGo for results'),
         runFn: function() {
-            const ErrorDialog = sdk.getComponent('dialogs.ErrorDialog');
             // TODO Don't explain this away, actually show a search UI here.
             Modal.createTrackedDialog('Slash Commands', '/ddg is not a command', ErrorDialog, {
                 title: _t('/ddg is not a command'),
@@ -269,8 +272,6 @@ export const Commands = [
                     return reject(_t("You do not have the required permissions to use this command."));
                 }
 
-                const RoomUpgradeWarningDialog = sdk.getComponent("dialogs.RoomUpgradeWarningDialog");
-
                 const { finished } = Modal.createTrackedDialog('Slash Commands', 'upgrade room confirmation',
                     RoomUpgradeWarningDialog, { roomId: roomId, targetVersion: args }, /*className=*/null,
                     /*isPriority=*/false, /*isStatic=*/true);
@@ -314,7 +315,6 @@ export const Commands = [
 
                         if (checkForUpgradeFn) cli.removeListener('Room', checkForUpgradeFn);
 
-                        const ErrorDialog = sdk.getComponent('dialogs.ErrorDialog');
                         Modal.createTrackedDialog('Slash Commands', 'room upgrade error', ErrorDialog, {
                             title: _t('Error upgrading room'),
                             description: _t(
@@ -434,7 +434,6 @@ export const Commands = [
             const topic = topicEvents && topicEvents.getContent().topic;
             const topicHtml = topic ? linkifyAndSanitizeHtml(topic) : _t('This room has no topic.');
 
-            const InfoDialog = sdk.getComponent('dialogs.InfoDialog');
             Modal.createTrackedDialog('Slash Commands', 'Topic', InfoDialog, {
                 title: room.name,
                 description: <div dangerouslySetInnerHTML={{ __html: topicHtml }} />,
@@ -737,7 +736,6 @@ export const Commands = [
                     ignoredUsers.push(userId); // de-duped internally in the js-sdk
                     return success(
                         cli.setIgnoredUsers(ignoredUsers).then(() => {
-                            const InfoDialog = sdk.getComponent('dialogs.InfoDialog');
                             Modal.createTrackedDialog('Slash Commands', 'User ignored', InfoDialog, {
                                 title: _t('Ignored user'),
                                 description: <div>
@@ -768,7 +766,6 @@ export const Commands = [
                     if (index !== -1) ignoredUsers.splice(index, 1);
                     return success(
                         cli.setIgnoredUsers(ignoredUsers).then(() => {
-                            const InfoDialog = sdk.getComponent('dialogs.InfoDialog');
                             Modal.createTrackedDialog('Slash Commands', 'User unignored', InfoDialog, {
                                 title: _t('Unignored user'),
                                 description: <div>
@@ -838,7 +835,6 @@ export const Commands = [
         command: 'devtools',
         description: _td('Opens the Developer Tools dialog'),
         runFn: function(roomId) {
-            const DevtoolsDialog = sdk.getComponent('dialogs.DevtoolsDialog');
             Modal.createDialog(DevtoolsDialog, { roomId });
             return success();
         },
@@ -943,7 +939,6 @@ export const Commands = [
                         await cli.setDeviceVerified(userId, deviceId, true);
 
                         // Tell the user we verified everything
-                        const InfoDialog = sdk.getComponent('dialogs.InfoDialog');
                         Modal.createTrackedDialog('Slash Commands', 'Verified key', InfoDialog, {
                             title: _t('Verified key'),
                             description: <div>
@@ -1000,8 +995,6 @@ export const Commands = [
         command: "help",
         description: _td("Displays list of commands with usages and descriptions"),
         runFn: function() {
-            const SlashCommandHelpDialog = sdk.getComponent('dialogs.SlashCommandHelpDialog');
-
             Modal.createTrackedDialog('Slash Commands', 'Help', SlashCommandHelpDialog);
             return success();
         },
diff --git a/src/components/structures/auth/SoftLogout.tsx b/src/components/structures/auth/SoftLogout.tsx
index 3790028fea..d232f55dd1 100644
--- a/src/components/structures/auth/SoftLogout.tsx
+++ b/src/components/structures/auth/SoftLogout.tsx
@@ -16,7 +16,6 @@ limitations under the License.
 
 import React from 'react';
 import { _t } from '../../../languageHandler';
-import * as sdk from '../../../index';
 import dis from '../../../dispatcher/dispatcher';
 import * as Lifecycle from '../../../Lifecycle';
 import Modal from '../../../Modal';
@@ -26,6 +25,12 @@ import AuthPage from "../../views/auth/AuthPage";
 import { SSO_HOMESERVER_URL_KEY, SSO_ID_SERVER_URL_KEY } from "../../../BasePlatform";
 import SSOButtons from "../../views/elements/SSOButtons";
 import { replaceableComponent } from "../../../utils/replaceableComponent";
+import ConfirmWipeDeviceDialog from '../../views/dialogs/ConfirmWipeDeviceDialog';
+import Field from '../../views/elements/Field';
+import AccessibleButton from '../../views/elements/AccessibleButton';
+import Spinner from "../../views/elements/Spinner";
+import AuthHeader from "../../views/auth/AuthHeader";
+import AuthBody from "../../views/auth/AuthBody";
 
 const LOGIN_VIEW = {
     LOADING: 1,
@@ -94,7 +99,6 @@ export default class SoftLogout extends React.Component<IProps, IState> {
     }
 
     onClearAll = () => {
-        const ConfirmWipeDeviceDialog = sdk.getComponent('dialogs.ConfirmWipeDeviceDialog');
         Modal.createTrackedDialog('Clear Data', 'Soft Logout', ConfirmWipeDeviceDialog, {
             onFinished: (wipeData) => {
                 if (!wipeData) return;
@@ -202,7 +206,6 @@ export default class SoftLogout extends React.Component<IProps, IState> {
 
     private renderSignInSection() {
         if (this.state.loginView === LOGIN_VIEW.LOADING) {
-            const Spinner = sdk.getComponent("elements.Spinner");
             return <Spinner />;
         }
 
@@ -214,9 +217,6 @@ export default class SoftLogout extends React.Component<IProps, IState> {
         }
 
         if (this.state.loginView === LOGIN_VIEW.PASSWORD) {
-            const Field = sdk.getComponent("elements.Field");
-            const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
-
             let error = null;
             if (this.state.errorText) {
                 error = <span className='mx_Login_error'>{this.state.errorText}</span>;
@@ -286,10 +286,6 @@ export default class SoftLogout extends React.Component<IProps, IState> {
     }
 
     render() {
-        const AuthHeader = sdk.getComponent("auth.AuthHeader");
-        const AuthBody = sdk.getComponent("auth.AuthBody");
-        const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
-
         return (
             <AuthPage>
                 <AuthHeader />
diff --git a/src/components/views/auth/InteractiveAuthEntryComponents.tsx b/src/components/views/auth/InteractiveAuthEntryComponents.tsx
index e002eb5717..4b1ecec740 100644
--- a/src/components/views/auth/InteractiveAuthEntryComponents.tsx
+++ b/src/components/views/auth/InteractiveAuthEntryComponents.tsx
@@ -18,7 +18,6 @@ import React, { ChangeEvent, createRef, FormEvent, MouseEvent } from 'react';
 import classNames from 'classnames';
 import { MatrixClient } from "matrix-js-sdk/src/client";
 
-import * as sdk from '../../../index';
 import { _t } from '../../../languageHandler';
 import SettingsStore from "../../../settings/SettingsStore";
 import AccessibleButton from "../elements/AccessibleButton";
@@ -26,6 +25,8 @@ import Spinner from "../elements/Spinner";
 import CountlyAnalytics from "../../../CountlyAnalytics";
 import { replaceableComponent } from "../../../utils/replaceableComponent";
 import { LocalisedPolicy, Policies } from '../../../Terms';
+import Field from '../elements/Field';
+import CaptchaForm from "./CaptchaForm";
 
 /* This file contains a collection of components which are used by the
  * InteractiveAuth to prompt the user to enter the information needed
@@ -164,8 +165,7 @@ export class PasswordAuthEntry extends React.Component<IAuthEntryProps, IPasswor
 
         let submitButtonOrSpinner;
         if (this.props.busy) {
-            const Loader = sdk.getComponent("elements.Spinner");
-            submitButtonOrSpinner = <Loader />;
+            submitButtonOrSpinner = <Spinner />;
         } else {
             submitButtonOrSpinner = (
                 <input type="submit"
@@ -185,8 +185,6 @@ export class PasswordAuthEntry extends React.Component<IAuthEntryProps, IPasswor
             );
         }
 
-        const Field = sdk.getComponent('elements.Field');
-
         return (
             <div>
                 <p>{ _t("Confirm your identity by entering your account password below.") }</p>
@@ -236,13 +234,11 @@ export class RecaptchaAuthEntry extends React.Component<IRecaptchaAuthEntryProps
 
     render() {
         if (this.props.busy) {
-            const Loader = sdk.getComponent("elements.Spinner");
-            return <Loader />;
+            return <Spinner />;
         }
 
         let errorText = this.props.errorText;
 
-        const CaptchaForm = sdk.getComponent("views.auth.CaptchaForm");
         let sitePublicKey;
         if (!this.props.stageParams || !this.props.stageParams.public_key) {
             errorText = _t(
@@ -390,8 +386,7 @@ export class TermsAuthEntry extends React.Component<ITermsAuthEntryProps, ITerms
 
     render() {
         if (this.props.busy) {
-            const Loader = sdk.getComponent("elements.Spinner");
-            return <Loader />;
+            return <Spinner />;
         }
 
         const checkboxes = [];
@@ -590,8 +585,7 @@ export class MsisdnAuthEntry extends React.Component<IMsisdnAuthEntryProps, IMsi
 
     render() {
         if (this.state.requestingToken) {
-            const Loader = sdk.getComponent("elements.Spinner");
-            return <Loader />;
+            return <Spinner />;
         } else {
             const enableSubmit = Boolean(this.state.token);
             const submitClasses = classNames({
diff --git a/src/components/views/dialogs/ConfirmAndWaitRedactDialog.tsx b/src/components/views/dialogs/ConfirmAndWaitRedactDialog.tsx
index 90b749b959..d21fde329c 100644
--- a/src/components/views/dialogs/ConfirmAndWaitRedactDialog.tsx
+++ b/src/components/views/dialogs/ConfirmAndWaitRedactDialog.tsx
@@ -15,9 +15,12 @@ limitations under the License.
 */
 
 import React from 'react';
-import * as sdk from '../../../index';
 import { _t } from '../../../languageHandler';
 import { replaceableComponent } from "../../../utils/replaceableComponent";
+import ConfirmRedactDialog from './ConfirmRedactDialog';
+import ErrorDialog from './ErrorDialog';
+import BaseDialog from "./BaseDialog";
+import Spinner from "../elements/Spinner";
 
 interface IProps {
     redact: () => Promise<void>;
@@ -73,7 +76,6 @@ export default class ConfirmAndWaitRedactDialog extends React.PureComponent<IPro
     public render() {
         if (this.state.isRedacting) {
             if (this.state.redactionErrorCode) {
-                const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
                 const code = this.state.redactionErrorCode;
                 return (
                     <ErrorDialog
@@ -83,8 +85,6 @@ export default class ConfirmAndWaitRedactDialog extends React.PureComponent<IPro
                     />
                 );
             } else {
-                const BaseDialog = sdk.getComponent("dialogs.BaseDialog");
-                const Spinner = sdk.getComponent('elements.Spinner');
                 return (
                     <BaseDialog
                         onFinished={this.props.onFinished}
@@ -95,7 +95,6 @@ export default class ConfirmAndWaitRedactDialog extends React.PureComponent<IPro
                 );
             }
         } else {
-            const ConfirmRedactDialog = sdk.getComponent("dialogs.ConfirmRedactDialog");
             return <ConfirmRedactDialog onFinished={this.onParentFinished} />;
         }
     }
diff --git a/src/components/views/dialogs/ConfirmUserActionDialog.tsx b/src/components/views/dialogs/ConfirmUserActionDialog.tsx
index 78fae390b5..cbef474c69 100644
--- a/src/components/views/dialogs/ConfirmUserActionDialog.tsx
+++ b/src/components/views/dialogs/ConfirmUserActionDialog.tsx
@@ -17,11 +17,14 @@ limitations under the License.
 import React from 'react';
 import { MatrixClient } from 'matrix-js-sdk/src/client';
 import { RoomMember } from "matrix-js-sdk/src/models/room-member";
-import * as sdk from '../../../index';
 import { _t } from '../../../languageHandler';
 import { GroupMemberType } from '../../../groups';
 import { replaceableComponent } from "../../../utils/replaceableComponent";
 import { mediaFromMxc } from "../../../customisations/Media";
+import MemberAvatar from '../avatars/MemberAvatar';
+import BaseAvatar from '../avatars/BaseAvatar';
+import BaseDialog from "./BaseDialog";
+import DialogButtons from "../elements/DialogButtons";
 
 interface IProps {
     // matrix-js-sdk (room) member object. Supply either this or 'groupMember'
@@ -67,11 +70,6 @@ export default class ConfirmUserActionDialog extends React.Component<IProps> {
     };
 
     public render() {
-        const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
-        const DialogButtons = sdk.getComponent('views.elements.DialogButtons');
-        const MemberAvatar = sdk.getComponent("views.avatars.MemberAvatar");
-        const BaseAvatar = sdk.getComponent("views.avatars.BaseAvatar");
-
         const confirmButtonClass = this.props.danger ? 'danger' : '';
 
         let reasonBox;
diff --git a/src/components/views/dialogs/TermsDialog.tsx b/src/components/views/dialogs/TermsDialog.tsx
index 02a779743b..afa732033f 100644
--- a/src/components/views/dialogs/TermsDialog.tsx
+++ b/src/components/views/dialogs/TermsDialog.tsx
@@ -16,11 +16,12 @@ limitations under the License.
 
 import url from 'url';
 import React from 'react';
-import * as sdk from '../../../index';
 import { _t, pickBestLanguage } from '../../../languageHandler';
 
 import { replaceableComponent } from "../../../utils/replaceableComponent";
 import { SERVICE_TYPES } from "matrix-js-sdk/src/service-types";
+import DialogButtons from "../elements/DialogButtons";
+import BaseDialog from "./BaseDialog";
 
 interface ITermsCheckboxProps {
     onChange: (url: string, checked: boolean) => void;
@@ -117,9 +118,6 @@ export default class TermsDialog extends React.PureComponent<ITermsDialogProps,
     };
 
     public render() {
-        const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
-        const DialogButtons = sdk.getComponent('views.elements.DialogButtons');
-
         const rows = [];
         for (const policiesAndService of this.props.policiesAndServicePairs) {
             const parsedBaseUrl = url.parse(policiesAndService.service.baseUrl);
diff --git a/src/components/views/dialogs/security/ConfirmDestroyCrossSigningDialog.tsx b/src/components/views/dialogs/security/ConfirmDestroyCrossSigningDialog.tsx
index 6272302a76..c0530a35ea 100644
--- a/src/components/views/dialogs/security/ConfirmDestroyCrossSigningDialog.tsx
+++ b/src/components/views/dialogs/security/ConfirmDestroyCrossSigningDialog.tsx
@@ -16,8 +16,9 @@ limitations under the License.
 
 import React from 'react';
 import { _t } from "../../../../languageHandler";
-import * as sdk from "../../../../index";
 import { replaceableComponent } from "../../../../utils/replaceableComponent";
+import BaseDialog from "../BaseDialog";
+import DialogButtons from "../../elements/DialogButtons";
 
 interface IProps {
     onFinished: (success: boolean) => void;
@@ -34,9 +35,6 @@ export default class ConfirmDestroyCrossSigningDialog extends React.Component<IP
     };
 
     render() {
-        const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
-        const DialogButtons = sdk.getComponent('views.elements.DialogButtons');
-
         return (
             <BaseDialog
                 className='mx_ConfirmDestroyCrossSigningDialog'

From d99874318ca80b009cb74f1a991e0cc5dc6a7c80 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C5=A0imon=20Brandner?= <simon.bra.ag@gmail.com>
Date: Sat, 3 Jul 2021 11:51:23 +0200
Subject: [PATCH 16/31] Ninth batch of burning
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
---
 src/components/structures/LoggedInView.tsx | 12 +++++-------
 src/components/structures/RoomView.tsx     | 22 ++++++++--------------
 2 files changed, 13 insertions(+), 21 deletions(-)

diff --git a/src/components/structures/LoggedInView.tsx b/src/components/structures/LoggedInView.tsx
index 1f870da900..171de4e3bd 100644
--- a/src/components/structures/LoggedInView.tsx
+++ b/src/components/structures/LoggedInView.tsx
@@ -24,7 +24,6 @@ import { Key } from '../../Keyboard';
 import PageTypes from '../../PageTypes';
 import MediaDeviceHandler from '../../MediaDeviceHandler';
 import { fixupColorFonts } from '../../utils/FontManager';
-import * as sdk from '../../index';
 import dis from '../../dispatcher/dispatcher';
 import { IMatrixClientCreds } from '../../MatrixClientPeg';
 import SettingsStore from "../../settings/SettingsStore";
@@ -59,6 +58,11 @@ import { replaceableComponent } from "../../utils/replaceableComponent";
 import CallHandler, { CallHandlerEvent } from '../../CallHandler';
 import { MatrixCall } from 'matrix-js-sdk/src/webrtc/call';
 import AudioFeedArrayForCall from '../views/voip/AudioFeedArrayForCall';
+import RoomView from './RoomView';
+import ToastContainer from './ToastContainer';
+import MyGroups from "./MyGroups";
+import UserView from "./UserView";
+import GroupView from "./GroupView";
 
 // We need to fetch each pinned message individually (if we don't already have it)
 // so each pinned message may trigger a request. Limit the number per room for sanity.
@@ -567,12 +571,6 @@ class LoggedInView extends React.Component<IProps, IState> {
     };
 
     render() {
-        const RoomView = sdk.getComponent('structures.RoomView');
-        const UserView = sdk.getComponent('structures.UserView');
-        const GroupView = sdk.getComponent('structures.GroupView');
-        const MyGroups = sdk.getComponent('structures.MyGroups');
-        const ToastContainer = sdk.getComponent('structures.ToastContainer');
-
         let pageElement;
 
         switch (this.props.page_type) {
diff --git a/src/components/structures/RoomView.tsx b/src/components/structures/RoomView.tsx
index 2c8fc08dac..5c6d032596 100644
--- a/src/components/structures/RoomView.tsx
+++ b/src/components/structures/RoomView.tsx
@@ -34,7 +34,6 @@ import { RoomPermalinkCreator } from '../../utils/permalinks/Permalinks';
 import ResizeNotifier from '../../utils/ResizeNotifier';
 import ContentMessages from '../../ContentMessages';
 import Modal from '../../Modal';
-import * as sdk from '../../index';
 import CallHandler, { PlaceCallType } from '../../CallHandler';
 import dis from '../../dispatcher/dispatcher';
 import * as Rooms from '../../Rooms';
@@ -82,6 +81,14 @@ import { replaceableComponent } from "../../utils/replaceableComponent";
 import UIStore from "../../stores/UIStore";
 import EditorStateTransfer from "../../utils/EditorStateTransfer";
 import { throttle } from "lodash";
+import ErrorDialog from '../views/dialogs/ErrorDialog';
+import SearchResultTile from '../views/rooms/SearchResultTile';
+import Spinner from "../views/elements/Spinner";
+import UploadBar from './UploadBar';
+import RoomStatusBar from "./RoomStatusBar";
+import MessageComposer from '../views/rooms/MessageComposer';
+import JumpToBottomButton from "../views/rooms/JumpToBottomButton";
+import TopUnreadMessagesBar from "../views/rooms/TopUnreadMessagesBar";
 
 const DEBUG = false;
 let debuglog = function(msg: string) {};
@@ -1328,7 +1335,6 @@ export default class RoomView extends React.Component<IProps, IState> {
                 searchResults: results,
             });
         }, (error) => {
-            const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
             console.error("Search failed", error);
             Modal.createTrackedDialog('Search failed', '', ErrorDialog, {
                 title: _t("Search failed"),
@@ -1344,9 +1350,6 @@ export default class RoomView extends React.Component<IProps, IState> {
     }
 
     private getSearchResultTiles() {
-        const SearchResultTile = sdk.getComponent('rooms.SearchResultTile');
-        const Spinner = sdk.getComponent("elements.Spinner");
-
         // XXX: todo: merge overlapping results somehow?
         // XXX: why doesn't searching on name work?
 
@@ -1466,7 +1469,6 @@ export default class RoomView extends React.Component<IProps, IState> {
             console.error("Failed to reject invite: %s", error);
 
             const msg = error.message ? error.message : JSON.stringify(error);
-            const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
             Modal.createTrackedDialog('Failed to reject invite', '', ErrorDialog, {
                 title: _t("Failed to reject invite"),
                 description: msg,
@@ -1500,7 +1502,6 @@ export default class RoomView extends React.Component<IProps, IState> {
             console.error("Failed to reject invite: %s", error);
 
             const msg = error.message ? error.message : JSON.stringify(error);
-            const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
             Modal.createTrackedDialog('Failed to reject invite', '', ErrorDialog, {
                 title: _t("Failed to reject invite"),
                 description: msg,
@@ -1834,10 +1835,8 @@ export default class RoomView extends React.Component<IProps, IState> {
         let isStatusAreaExpanded = true;
 
         if (ContentMessages.sharedInstance().getCurrentUploads().length > 0) {
-            const UploadBar = sdk.getComponent('structures.UploadBar');
             statusBar = <UploadBar room={this.state.room} />;
         } else if (!this.state.searchResults) {
-            const RoomStatusBar = sdk.getComponent('structures.RoomStatusBar');
             isStatusAreaExpanded = this.state.statusBarVisible;
             statusBar = <RoomStatusBar
                 room={this.state.room}
@@ -1943,12 +1942,9 @@ export default class RoomView extends React.Component<IProps, IState> {
             myMembership === 'join' && !this.state.searchResults
         );
         if (canSpeak) {
-            const MessageComposer = sdk.getComponent('rooms.MessageComposer');
             messageComposer =
                 <MessageComposer
                     room={this.state.room}
-                    callState={this.state.callState}
-                    showApps={this.state.showApps}
                     e2eStatus={this.state.e2eStatus}
                     resizeNotifier={this.props.resizeNotifier}
                     replyToEvent={this.state.replyToEvent}
@@ -2034,7 +2030,6 @@ export default class RoomView extends React.Component<IProps, IState> {
         let topUnreadMessagesBar = null;
         // Do not show TopUnreadMessagesBar if we have search results showing, it makes no sense
         if (this.state.showTopUnreadMessagesBar && !this.state.searchResults) {
-            const TopUnreadMessagesBar = sdk.getComponent('rooms.TopUnreadMessagesBar');
             topUnreadMessagesBar = (
                 <TopUnreadMessagesBar onScrollUpClick={this.jumpToReadMarker} onCloseClick={this.forgetReadMarker} />
             );
@@ -2042,7 +2037,6 @@ export default class RoomView extends React.Component<IProps, IState> {
         let jumpToBottom;
         // Do not show JumpToBottomButton if we have search results showing, it makes no sense
         if (!this.state.atEndOfLiveTimeline && !this.state.searchResults) {
-            const JumpToBottomButton = sdk.getComponent('rooms.JumpToBottomButton');
             jumpToBottom = (<JumpToBottomButton
                 highlight={this.state.room.getUnreadNotificationCount(NotificationCountType.Highlight) > 0}
                 numUnreadMessages={this.state.numUnreadMessages}

From 5d054519dc1269baee1aba99dacb1195c544e2fc Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C5=A0imon=20Brandner?= <simon.bra.ag@gmail.com>
Date: Sat, 3 Jul 2021 11:57:05 +0200
Subject: [PATCH 17/31] Tenth batch of burning
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
---
 src/components/structures/LoggedInView.tsx    |  4 +-
 src/components/structures/MatrixChat.tsx      | 62 +++++++++----------
 .../structures/auth/Registration.tsx          | 10 +--
 3 files changed, 35 insertions(+), 41 deletions(-)

diff --git a/src/components/structures/LoggedInView.tsx b/src/components/structures/LoggedInView.tsx
index 171de4e3bd..5a26967cb0 100644
--- a/src/components/structures/LoggedInView.tsx
+++ b/src/components/structures/LoggedInView.tsx
@@ -82,8 +82,8 @@ interface IProps {
     hideToSRUsers: boolean;
     resizeNotifier: ResizeNotifier;
     // eslint-disable-next-line camelcase
-    page_type: string;
-    autoJoin: boolean;
+    page_type?: string;
+    autoJoin?: boolean;
     threepidInvite?: IThreepidInvite;
     roomOobData?: IOOBData;
     currentRoomId: string;
diff --git a/src/components/structures/MatrixChat.tsx b/src/components/structures/MatrixChat.tsx
index 06c7bfac8b..64d32bbe62 100644
--- a/src/components/structures/MatrixChat.tsx
+++ b/src/components/structures/MatrixChat.tsx
@@ -85,9 +85,26 @@ import RoomListStore from "../../stores/room-list/RoomListStore";
 import { RoomUpdateCause } from "../../stores/room-list/models";
 import defaultDispatcher from "../../dispatcher/dispatcher";
 import SecurityCustomisations from "../../customisations/Security";
+import Spinner from "../views/elements/Spinner";
+import QuestionDialog from "../views/dialogs/QuestionDialog";
+import UserSettingsDialog from '../views/dialogs/UserSettingsDialog';
+import CreateGroupDialog from '../views/dialogs/CreateGroupDialog';
+import CreateRoomDialog from '../views/dialogs/CreateRoomDialog';
+import RoomDirectory from './RoomDirectory';
+import KeySignatureUploadFailedDialog from "../views/dialogs/KeySignatureUploadFailedDialog";
+import IncomingSasDialog from "../views/dialogs/IncomingSasDialog";
+import CompleteSecurity from "./auth/CompleteSecurity";
+import LoggedInView from './LoggedInView';
+import Welcome from "../views/auth/Welcome";
+import ForgotPassword from "./auth/ForgotPassword";
+import E2eSetup from "./auth/E2eSetup";
+import Registration from './auth/Registration';
+import Login from "./auth/Login";
+import ErrorBoundary from '../views/elements/ErrorBoundary';
 
 import PerformanceMonitor, { PerformanceEntryNames } from "../../performance";
 import UIStore, { UI_EVENTS } from "../../stores/UIStore";
+import SoftLogout from './auth/SoftLogout';
 
 /** constants for MatrixChat.state.view */
 export enum Views {
@@ -156,7 +173,12 @@ interface IRoomInfo {
 /* eslint-enable camelcase */
 
 interface IProps { // TODO type things better
-    config: Record<string, any>;
+    config: {
+        piwik: {
+            policyUrl: string;
+        };
+        [key: string]: any;
+    };
     serverConfig?: ValidatedServerConfig;
     onNewScreen: (screen: string, replaceLast: boolean) => void;
     enableGuest?: boolean;
@@ -519,7 +541,6 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
 
     onAction = (payload) => {
         // console.log(`MatrixClientPeg.onAction: ${payload.action}`);
-        const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
 
         // Start the onboarding process for certain actions
         if (MatrixClientPeg.get() && MatrixClientPeg.get().isGuest() &&
@@ -613,8 +634,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
                     onFinished: (confirm) => {
                         if (confirm) {
                             // FIXME: controller shouldn't be loading a view :(
-                            const Loader = sdk.getComponent("elements.Spinner");
-                            const modal = Modal.createDialog(Loader, null, 'mx_Dialog_spinner');
+                            const modal = Modal.createDialog(Spinner, null, 'mx_Dialog_spinner');
 
                             MatrixClientPeg.get().leave(payload.room_id).then(() => {
                                 modal.close();
@@ -650,7 +670,6 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
             }
             case Action.ViewUserSettings: {
                 const tabPayload = payload as OpenToTabPayload;
-                const UserSettingsDialog = sdk.getComponent("dialogs.UserSettingsDialog");
                 Modal.createTrackedDialog('User settings', '', UserSettingsDialog,
                     { initialTabId: tabPayload.initialTabId },
                     /*className=*/null, /*isPriority=*/false, /*isStatic=*/true);
@@ -663,11 +682,12 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
                 this.createRoom(payload.public, payload.defaultName);
                 break;
             case 'view_create_group': {
-                let CreateGroupDialog = sdk.getComponent("dialogs.CreateGroupDialog");
-                if (SettingsStore.getValue("feature_communities_v2_prototypes")) {
-                    CreateGroupDialog = CreateCommunityPrototypeDialog;
-                }
-                Modal.createTrackedDialog('Create Community', '', CreateGroupDialog);
+                const prototype = SettingsStore.getValue("feature_communities_v2_prototypes");
+                Modal.createTrackedDialog(
+                    'Create Community',
+                    '',
+                    prototype ? CreateCommunityPrototypeDialog : CreateGroupDialog,
+                );
                 break;
             }
             case Action.ViewRoomDirectory: {
@@ -677,7 +697,6 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
                         room_id: SpaceStore.instance.activeSpace.roomId,
                     });
                 } else {
-                    const RoomDirectory = sdk.getComponent("structures.RoomDirectory");
                     Modal.createTrackedDialog('Room directory', '', RoomDirectory, {
                         initialText: payload.initialText,
                     }, 'mx_RoomDirectory_dialogWrapper', false, true);
@@ -1019,7 +1038,6 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
             }
         }
 
-        const CreateRoomDialog = sdk.getComponent('dialogs.CreateRoomDialog');
         const modal = Modal.createTrackedDialog('Create Room', '', CreateRoomDialog, {
             defaultPublic,
             defaultName,
@@ -1116,7 +1134,6 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
     }
 
     private leaveRoom(roomId: string) {
-        const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
         const roomToLeave = MatrixClientPeg.get().getRoom(roomId);
         const warnings = this.leaveRoomWarnings(roomId);
 
@@ -1143,8 +1160,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
                     const d = leaveRoomBehaviour(roomId);
 
                     // FIXME: controller shouldn't be loading a view :(
-                    const Loader = sdk.getComponent("elements.Spinner");
-                    const modal = Modal.createDialog(Loader, null, 'mx_Dialog_spinner');
+                    const modal = Modal.createDialog(Spinner, null, 'mx_Dialog_spinner');
 
                     d.finally(() => modal.close());
                     dis.dispatch({
@@ -1439,7 +1455,6 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
             });
         });
         cli.on('no_consent', function(message, consentUri) {
-            const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
             Modal.createTrackedDialog('No Consent Dialog', '', QuestionDialog, {
                 title: _t('Terms and Conditions'),
                 description: <div>
@@ -1548,8 +1563,6 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
         });
 
         cli.on("crypto.keySignatureUploadFailure", (failures, source, continuation) => {
-            const KeySignatureUploadFailedDialog =
-                sdk.getComponent('views.dialogs.KeySignatureUploadFailedDialog');
             Modal.createTrackedDialog(
                 'Failed to upload key signatures',
                 'Failed to upload key signatures',
@@ -1559,7 +1572,6 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
 
         cli.on("crypto.verification.request", request => {
             if (request.verifier) {
-                const IncomingSasDialog = sdk.getComponent("views.dialogs.IncomingSasDialog");
                 Modal.createTrackedDialog('Incoming Verification', '', IncomingSasDialog, {
                     verifier: request.verifier,
                 }, null, /* priority = */ false, /* static = */ true);
@@ -1977,21 +1989,18 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
         let view = null;
 
         if (this.state.view === Views.LOADING) {
-            const Spinner = sdk.getComponent('elements.Spinner');
             view = (
                 <div className="mx_MatrixChat_splash">
                     <Spinner />
                 </div>
             );
         } else if (this.state.view === Views.COMPLETE_SECURITY) {
-            const CompleteSecurity = sdk.getComponent('structures.auth.CompleteSecurity');
             view = (
                 <CompleteSecurity
                     onFinished={this.onCompleteSecurityE2eSetupFinished}
                 />
             );
         } else if (this.state.view === Views.E2E_SETUP) {
-            const E2eSetup = sdk.getComponent('structures.auth.E2eSetup');
             view = (
                 <E2eSetup
                     onFinished={this.onCompleteSecurityE2eSetupFinished}
@@ -2012,7 +2021,6 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
                  * we should go through and figure out what we actually need to pass down, as well
                  * as using something like redux to avoid having a billion bits of state kicking around.
                  */
-                const LoggedInView = sdk.getComponent('structures.LoggedInView');
                 view = (
                     <LoggedInView
                         {...this.props}
@@ -2020,14 +2028,12 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
                         ref={this.loggedInView}
                         matrixClient={MatrixClientPeg.get()}
                         onRoomCreated={this.onRoomCreated}
-                        onCloseAllSettings={this.onCloseAllSettings}
                         onRegistered={this.onRegistered}
                         currentRoomId={this.state.currentRoomId}
                     />
                 );
             } else {
                 // we think we are logged in, but are still waiting for the /sync to complete
-                const Spinner = sdk.getComponent('elements.Spinner');
                 let errorBox;
                 if (this.state.syncError && !isStoreError) {
                     errorBox = <div className="mx_MatrixChat_syncError">
@@ -2045,10 +2051,8 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
                 );
             }
         } else if (this.state.view === Views.WELCOME) {
-            const Welcome = sdk.getComponent('auth.Welcome');
             view = <Welcome />;
         } else if (this.state.view === Views.REGISTER && SettingsStore.getValue(UIFeature.Registration)) {
-            const Registration = sdk.getComponent('structures.auth.Registration');
             const email = ThreepidInviteStore.instance.pickBestInvite()?.toEmail;
             view = (
                 <Registration
@@ -2067,7 +2071,6 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
                 />
             );
         } else if (this.state.view === Views.FORGOT_PASSWORD && SettingsStore.getValue(UIFeature.PasswordReset)) {
-            const ForgotPassword = sdk.getComponent('structures.auth.ForgotPassword');
             view = (
                 <ForgotPassword
                     onComplete={this.onLoginClick}
@@ -2078,7 +2081,6 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
             );
         } else if (this.state.view === Views.LOGIN) {
             const showPasswordReset = SettingsStore.getValue(UIFeature.PasswordReset);
-            const Login = sdk.getComponent('structures.auth.Login');
             view = (
                 <Login
                     isSyncing={this.state.pendingInitialSync}
@@ -2094,7 +2096,6 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
                 />
             );
         } else if (this.state.view === Views.SOFT_LOGOUT) {
-            const SoftLogout = sdk.getComponent('structures.auth.SoftLogout');
             view = (
                 <SoftLogout
                     realQueryParams={this.props.realQueryParams}
@@ -2106,7 +2107,6 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
             console.error(`Unknown view ${this.state.view}`);
         }
 
-        const ErrorBoundary = sdk.getComponent('elements.ErrorBoundary');
         return <ErrorBoundary>
             {view}
         </ErrorBoundary>;
diff --git a/src/components/structures/auth/Registration.tsx b/src/components/structures/auth/Registration.tsx
index 57b758091a..652d42bde5 100644
--- a/src/components/structures/auth/Registration.tsx
+++ b/src/components/structures/auth/Registration.tsx
@@ -24,7 +24,7 @@ import { messageForResourceLimitError } from '../../../utils/ErrorUtils';
 import AutoDiscoveryUtils, { ValidatedServerConfig } from "../../../utils/AutoDiscoveryUtils";
 import classNames from "classnames";
 import * as Lifecycle from '../../../Lifecycle';
-import { MatrixClientPeg } from "../../../MatrixClientPeg";
+import { IMatrixClientCreds, MatrixClientPeg } from "../../../MatrixClientPeg";
 import AuthPage from "../../views/auth/AuthPage";
 import Login, { ISSOFlow } from "../../../Login";
 import dis from "../../../dispatcher/dispatcher";
@@ -47,13 +47,7 @@ interface IProps {
     // - The user's password, if available and applicable (may be cached in memory
     //   for a short time so the user is not required to re-enter their password
     //   for operations like uploading cross-signing keys).
-    onLoggedIn(params: {
-        userId: string;
-        deviceId: string;
-        homeserverUrl: string;
-        identityServerUrl?: string;
-        accessToken: string;
-    }, password: string): void;
+    onLoggedIn(params: IMatrixClientCreds, password: string): void;
     makeRegistrationUrl(params: {
         /* eslint-disable camelcase */
         client_secret: string;

From 68011056cc5a80ef1c80696a93746c09e741a14b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C5=A0imon=20Brandner?= <simon.bra.ag@gmail.com>
Date: Sat, 3 Jul 2021 12:24:07 +0200
Subject: [PATCH 18/31] Eleventh and final batch of burning
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
---
 src/components/structures/MatrixChat.tsx        |  4 ++--
 src/components/structures/auth/Registration.tsx | 17 +++++++----------
 2 files changed, 9 insertions(+), 12 deletions(-)

diff --git a/src/components/structures/MatrixChat.tsx b/src/components/structures/MatrixChat.tsx
index 64d32bbe62..c7a200239c 100644
--- a/src/components/structures/MatrixChat.tsx
+++ b/src/components/structures/MatrixChat.tsx
@@ -36,7 +36,6 @@ import dis from "../../dispatcher/dispatcher";
 import Notifier from '../../Notifier';
 
 import Modal from "../../Modal";
-import * as sdk from '../../index';
 import { showRoomInviteDialog, showStartChatInviteDialog } from '../../RoomInvite';
 import * as Rooms from '../../Rooms';
 import linkifyMatrix from "../../linkify-matrix";
@@ -101,6 +100,7 @@ import E2eSetup from "./auth/E2eSetup";
 import Registration from './auth/Registration';
 import Login from "./auth/Login";
 import ErrorBoundary from '../views/elements/ErrorBoundary';
+import VerificationRequestToast from '../views/toasts/VerificationRequestToast';
 
 import PerformanceMonitor, { PerformanceEntryNames } from "../../performance";
 import UIStore, { UI_EVENTS } from "../../stores/UIStore";
@@ -1581,7 +1581,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
                     title: _t("Verification requested"),
                     icon: "verification",
                     props: { request },
-                    component: sdk.getComponent("toasts.VerificationRequestToast"),
+                    component: VerificationRequestToast,
                     priority: 90,
                 });
             }
diff --git a/src/components/structures/auth/Registration.tsx b/src/components/structures/auth/Registration.tsx
index 652d42bde5..8d32981e57 100644
--- a/src/components/structures/auth/Registration.tsx
+++ b/src/components/structures/auth/Registration.tsx
@@ -18,7 +18,6 @@ import { createClient } from 'matrix-js-sdk/src/matrix';
 import React, { ReactNode } from 'react';
 import { MatrixClient } from "matrix-js-sdk/src/client";
 
-import * as sdk from '../../../index';
 import { _t, _td } from '../../../languageHandler';
 import { messageForResourceLimitError } from '../../../utils/ErrorUtils';
 import AutoDiscoveryUtils, { ValidatedServerConfig } from "../../../utils/AutoDiscoveryUtils";
@@ -31,6 +30,12 @@ import dis from "../../../dispatcher/dispatcher";
 import SSOButtons from "../../views/elements/SSOButtons";
 import ServerPicker from '../../views/elements/ServerPicker';
 import { replaceableComponent } from "../../../utils/replaceableComponent";
+import RegistrationForm from '../../views/auth/RegistrationForm';
+import AccessibleButton from '../../views/elements/AccessibleButton';
+import AuthBody from "../../views/auth/AuthBody";
+import AuthHeader from "../../views/auth/AuthHeader";
+import InteractiveAuth from "../InteractiveAuth";
+import Spinner from "../../views/elements/Spinner";
 
 interface IProps {
     serverConfig: ValidatedServerConfig;
@@ -240,7 +245,7 @@ export default class Registration extends React.Component<IProps, IState> {
         }
     }
 
-    private onFormSubmit = formVals => {
+    private onFormSubmit = async (formVals): Promise<void> => {
         this.setState({
             errorText: "",
             busy: true,
@@ -436,10 +441,6 @@ export default class Registration extends React.Component<IProps, IState> {
     };
 
     private renderRegisterComponent() {
-        const InteractiveAuth = sdk.getComponent('structures.InteractiveAuth');
-        const Spinner = sdk.getComponent('elements.Spinner');
-        const RegistrationForm = sdk.getComponent('auth.RegistrationForm');
-
         if (this.state.matrixClient && this.state.doingUIAuth) {
             return <InteractiveAuth
                 matrixClient={this.state.matrixClient}
@@ -510,10 +511,6 @@ export default class Registration extends React.Component<IProps, IState> {
     }
 
     render() {
-        const AuthHeader = sdk.getComponent('auth.AuthHeader');
-        const AuthBody = sdk.getComponent("auth.AuthBody");
-        const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
-
         let errorText;
         const err = this.state.errorText;
         if (err) {

From 8c1721fc351dd4d799ff074c6dd9694a1740ea9c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C5=A0imon=20Brandner?= <simon.bra.ag@gmail.com>
Date: Wed, 7 Jul 2021 08:32:06 +0200
Subject: [PATCH 19/31] Remove the old codeblock code
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
---
 res/css/views/rooms/_EventTile.scss          |  7 -----
 res/themes/dark/css/_dark.scss               | 33 --------------------
 res/themes/legacy-dark/css/_legacy-dark.scss | 15 ++-------
 3 files changed, 2 insertions(+), 53 deletions(-)

diff --git a/res/css/views/rooms/_EventTile.scss b/res/css/views/rooms/_EventTile.scss
index 27a83e58f8..e48f378d9d 100644
--- a/res/css/views/rooms/_EventTile.scss
+++ b/res/css/views/rooms/_EventTile.scss
@@ -477,8 +477,6 @@ $hover-select-border: 4px;
 
     pre, code {
         font-family: $monospace-font-family !important;
-        // deliberate constants as we're behind an invert filter
-        color: #333;
     }
 
     pre {
@@ -488,11 +486,6 @@ $hover-select-border: 4px;
         overflow-x: overlay;
         overflow-y: visible;
     }
-
-    code {
-        // deliberate constants as we're behind an invert filter
-        background-color: #f8f8f8;
-    }
 }
 
 .mx_EventTile_lineNumbers {
diff --git a/res/themes/dark/css/_dark.scss b/res/themes/dark/css/_dark.scss
index 81fd3c892a..2aca4c767e 100644
--- a/res/themes/dark/css/_dark.scss
+++ b/res/themes/dark/css/_dark.scss
@@ -119,8 +119,6 @@ $voipcall-plinth-color: #394049;
 
 $theme-button-bg-color: #e3e8f0;
 $dialpad-button-bg-color: #6F7882;
-;
-
 
 $roomlist-button-bg-color: rgba(141, 151, 165, 0.2); // Buttons include the filter box, explore button, and sublist buttons
 $roomlist-filter-active-bg-color: $bg-color;
@@ -274,24 +272,7 @@ $composer-shadow-color: rgba(0, 0, 0, 0.28);
 }
 
 // markdown overrides:
-.mx_EventTile_content .markdown-body pre:hover {
-    border-color: #808080 !important; // inverted due to rules below
-    scrollbar-color: rgba(0, 0, 0, 0.2) transparent; // copied from light theme due to inversion below
-    // the code above works only in Firefox, this is for other browsers
-    // see https://developer.mozilla.org/en-US/docs/Web/CSS/scrollbar-color
-    &::-webkit-scrollbar-thumb {
-        background-color: rgba(0, 0, 0, 0.2); // copied from light theme due to inversion below
-    }
-}
 .mx_EventTile_content .markdown-body {
-    pre, code {
-        filter: invert(1);
-    }
-
-    pre code {
-        filter: none;
-    }
-
     table {
         tr {
             background-color: #000000;
@@ -301,18 +282,4 @@ $composer-shadow-color: rgba(0, 0, 0, 0.28);
             background-color: #080808;
         }
     }
-
-    blockquote {
-        color: #919191;
-    }
-}
-
-// diff highlight colors
-// intentionally swapped to avoid inversion
-.hljs-addition {
-    background: #fdd;
-}
-
-.hljs-deletion {
-    background: #dfd;
 }
diff --git a/res/themes/legacy-dark/css/_legacy-dark.scss b/res/themes/legacy-dark/css/_legacy-dark.scss
index df01efbe1e..fa56d24c81 100644
--- a/res/themes/legacy-dark/css/_legacy-dark.scss
+++ b/res/themes/legacy-dark/css/_legacy-dark.scss
@@ -118,7 +118,7 @@ $voipcall-plinth-color: #394049;
 
 $theme-button-bg-color: #e3e8f0;
 $dialpad-button-bg-color: #6F7882;
-;
+
 
 $roomlist-button-bg-color: #1A1D23; // Buttons include the filter box, explore button, and sublist buttons
 $roomlist-filter-active-bg-color: $roomlist-button-bg-color;
@@ -249,7 +249,7 @@ $composer-shadow-color: tranparent;
 @define-mixin mx_DialogButton_secondary {
     // flip colours for the secondary ones
     font-weight: 600;
-    border: 1px solid $accent-color ! important;
+    border: 1px solid $accent-color !important;
     color: $accent-color;
     background-color: $button-secondary-bg-color;
 }
@@ -267,18 +267,7 @@ $composer-shadow-color: tranparent;
 }
 
 // markdown overrides:
-.mx_EventTile_content .markdown-body pre:hover {
-    border-color: #808080 !important; // inverted due to rules below
-}
 .mx_EventTile_content .markdown-body {
-    pre, code {
-        filter: invert(1);
-    }
-
-    pre code {
-        filter: none;
-    }
-
     table {
         tr {
             background-color: #000000;

From 9d12439ee71a14df0ce73602dfad7ce145d6f91a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C5=A0imon=20Brandner?= <simon.bra.ag@gmail.com>
Date: Wed, 7 Jul 2021 08:42:16 +0200
Subject: [PATCH 20/31] Give codeblocks a background color
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
---
 res/css/views/rooms/_EventTile.scss | 1 +
 1 file changed, 1 insertion(+)

diff --git a/res/css/views/rooms/_EventTile.scss b/res/css/views/rooms/_EventTile.scss
index e48f378d9d..55f73c0315 100644
--- a/res/css/views/rooms/_EventTile.scss
+++ b/res/css/views/rooms/_EventTile.scss
@@ -477,6 +477,7 @@ $hover-select-border: 4px;
 
     pre, code {
         font-family: $monospace-font-family !important;
+        background-color: $header-panel-bg-color;
     }
 
     pre {

From f8307a92d88b84d986e8ef488538cf91f8c4fb48 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C5=A0imon=20Brandner?= <simon.bra.ag@gmail.com>
Date: Wed, 7 Jul 2021 09:22:12 +0200
Subject: [PATCH 21/31] Use atom-one-dark for dark theme
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
---
 res/themes/dark/css/_dark.scss               |  5 +++++
 res/themes/dark/css/dark.scss                |  1 +
 res/themes/legacy-dark/css/_legacy-dark.scss | 11 +++--------
 res/themes/legacy-dark/css/legacy-dark.scss  |  1 +
 4 files changed, 10 insertions(+), 8 deletions(-)

diff --git a/res/themes/dark/css/_dark.scss b/res/themes/dark/css/_dark.scss
index 2aca4c767e..f5b23d2c3d 100644
--- a/res/themes/dark/css/_dark.scss
+++ b/res/themes/dark/css/_dark.scss
@@ -283,3 +283,8 @@ $composer-shadow-color: rgba(0, 0, 0, 0.28);
         }
     }
 }
+
+// highlight.js overrides
+.hljs-tag {
+    color: inherit;
+}
diff --git a/res/themes/dark/css/dark.scss b/res/themes/dark/css/dark.scss
index f9695018e4..600cfd528a 100644
--- a/res/themes/dark/css/dark.scss
+++ b/res/themes/dark/css/dark.scss
@@ -9,3 +9,4 @@
 @import "_dark.scss";
 @import "../../light/css/_mods.scss";
 @import "../../../../res/css/_components.scss";
+@import url("highlight.js/styles/atom-one-dark.css");
diff --git a/res/themes/legacy-dark/css/_legacy-dark.scss b/res/themes/legacy-dark/css/_legacy-dark.scss
index fa56d24c81..ec4c3094de 100644
--- a/res/themes/legacy-dark/css/_legacy-dark.scss
+++ b/res/themes/legacy-dark/css/_legacy-dark.scss
@@ -279,12 +279,7 @@ $composer-shadow-color: tranparent;
     }
 }
 
-// diff highlight colors
-// intentionally swapped to avoid inversion
-.hljs-addition {
-    background: #fdd;
-}
-
-.hljs-deletion {
-    background: #dfd;
+// highlight.js overrides:
+.hljs-tag {
+    color: inherit;
 }
diff --git a/res/themes/legacy-dark/css/legacy-dark.scss b/res/themes/legacy-dark/css/legacy-dark.scss
index 2a4d432d26..840794f7c0 100644
--- a/res/themes/legacy-dark/css/legacy-dark.scss
+++ b/res/themes/legacy-dark/css/legacy-dark.scss
@@ -4,3 +4,4 @@
 @import "../../legacy-light/css/_legacy-light.scss";
 @import "_legacy-dark.scss";
 @import "../../../../res/css/_components.scss";
+@import url("highlight.js/styles/atom-one-dark.css");

From 2cd2015e3673cf21a18ac88aba6eb0659a64dbec Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C5=A0imon=20Brandner?= <simon.bra.ag@gmail.com>
Date: Wed, 7 Jul 2021 10:24:26 +0200
Subject: [PATCH 22/31] Use atom-one-light for light theme
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
---
 res/themes/legacy-light/css/legacy-light.scss | 1 +
 res/themes/light/css/light.scss               | 1 +
 2 files changed, 2 insertions(+)

diff --git a/res/themes/legacy-light/css/legacy-light.scss b/res/themes/legacy-light/css/legacy-light.scss
index e39a1765f3..347d240fc6 100644
--- a/res/themes/legacy-light/css/legacy-light.scss
+++ b/res/themes/legacy-light/css/legacy-light.scss
@@ -3,3 +3,4 @@
 @import "_fonts.scss";
 @import "_legacy-light.scss";
 @import "../../../../res/css/_components.scss";
+@import url("highlight.js/styles/atom-one-light.css");
diff --git a/res/themes/light/css/light.scss b/res/themes/light/css/light.scss
index f31ce5c139..4e912bc756 100644
--- a/res/themes/light/css/light.scss
+++ b/res/themes/light/css/light.scss
@@ -4,3 +4,4 @@
 @import "_light.scss";
 @import "_mods.scss";
 @import "../../../../res/css/_components.scss";
+@import url("highlight.js/styles/atom-one-light.css");

From b5bad0cc237a6cf22ffe53cbd0d66eaf3919f38b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C5=A0imon=20Brandner?= <simon.bra.ag@gmail.com>
Date: Wed, 7 Jul 2021 10:28:29 +0200
Subject: [PATCH 23/31] Add comments
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
---
 res/themes/dark/css/_dark.scss               | 2 +-
 res/themes/legacy-dark/css/_legacy-dark.scss | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/res/themes/dark/css/_dark.scss b/res/themes/dark/css/_dark.scss
index f5b23d2c3d..57cbc7efa9 100644
--- a/res/themes/dark/css/_dark.scss
+++ b/res/themes/dark/css/_dark.scss
@@ -286,5 +286,5 @@ $composer-shadow-color: rgba(0, 0, 0, 0.28);
 
 // highlight.js overrides
 .hljs-tag {
-    color: inherit;
+    color: inherit; // Without this they'd be weirdly blue which doesn't match the theme
 }
diff --git a/res/themes/legacy-dark/css/_legacy-dark.scss b/res/themes/legacy-dark/css/_legacy-dark.scss
index ec4c3094de..555ef4f66c 100644
--- a/res/themes/legacy-dark/css/_legacy-dark.scss
+++ b/res/themes/legacy-dark/css/_legacy-dark.scss
@@ -281,5 +281,5 @@ $composer-shadow-color: tranparent;
 
 // highlight.js overrides:
 .hljs-tag {
-    color: inherit;
+    color: inherit; // Without this they'd be weirdly blue which doesn't match the theme
 }

From 984dc40f9cb10bf360acbc200f33b485eb59dc52 Mon Sep 17 00:00:00 2001
From: David Baker <dave@matrix.org>
Date: Wed, 7 Jul 2021 10:54:21 +0100
Subject: [PATCH 24/31] Clarify the keys we use when submitting rageshakes

'pk' is a bit opaque in a context with both private keys and public keys
---
 src/rageshake/submit-rageshake.ts | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/src/rageshake/submit-rageshake.ts b/src/rageshake/submit-rageshake.ts
index 5e0b2c3c4d..b629ddafd8 100644
--- a/src/rageshake/submit-rageshake.ts
+++ b/src/rageshake/submit-rageshake.ts
@@ -93,15 +93,15 @@ async function collectBugReport(opts: IOpts = {}, gzipLogs = true) {
             body.append("cross_signing_supported_by_hs",
                 String(await client.doesServerSupportUnstableFeature("org.matrix.e2e_cross_signing")));
             body.append("cross_signing_key", crossSigning.getId());
-            body.append("cross_signing_pk_in_secret_storage",
+            body.append("cross_signing_privkey_in_secret_storage",
                 String(!!(await crossSigning.isStoredInSecretStorage(secretStorage))));
 
             const pkCache = client.getCrossSigningCacheCallbacks();
-            body.append("cross_signing_master_pk_cached",
+            body.append("cross_signing_master_privkey_cached",
                 String(!!(pkCache && await pkCache.getCrossSigningKeyCache("master"))));
-            body.append("cross_signing_self_signing_pk_cached",
+            body.append("cross_signing_self_signing_privkey_cached",
                 String(!!(pkCache && await pkCache.getCrossSigningKeyCache("self_signing"))));
-            body.append("cross_signing_user_signing_pk_cached",
+            body.append("cross_signing_user_signing_privkey_cached",
                 String(!!(pkCache && await pkCache.getCrossSigningKeyCache("user_signing"))));
 
             body.append("secret_storage_ready", String(await client.isSecretStorageReady()));

From 06337e72fa875657640d19dedd26c555b742d5b5 Mon Sep 17 00:00:00 2001
From: Germain Souquet <germain@souquet.com>
Date: Wed, 7 Jul 2021 12:10:35 +0200
Subject: [PATCH 25/31] Update lockfile with correct dependencies

---
 yarn.lock | 27 +++++++++++++++++++++++----
 1 file changed, 23 insertions(+), 4 deletions(-)

diff --git a/yarn.lock b/yarn.lock
index c8c3315855..ea4adfb09f 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1677,6 +1677,11 @@
     "@types/scheduler" "*"
     csstype "^3.0.2"
 
+"@types/retry@^0.12.0":
+  version "0.12.0"
+  resolved "https://registry.yarnpkg.com/@types/retry/-/retry-0.12.0.tgz#2b35eccfcee7d38cd72ad99232fbd58bffb3c84d"
+  integrity sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==
+
 "@types/sanitize-html@^2.3.1":
   version "2.3.1"
   resolved "https://registry.yarnpkg.com/@types/sanitize-html/-/sanitize-html-2.3.1.tgz#094d696b83b7394b016e96342bbffa6a028795ce"
@@ -5445,10 +5450,10 @@ mathml-tag-names@^2.1.3:
   resolved "https://registry.yarnpkg.com/mathml-tag-names/-/mathml-tag-names-2.1.3.tgz#4ddadd67308e780cf16a47685878ee27b736a0a3"
   integrity sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg==
 
-matrix-js-sdk@12.0.0:
-  version "12.0.0"
-  resolved "https://registry.yarnpkg.com/matrix-js-sdk/-/matrix-js-sdk-12.0.0.tgz#8ee7cc37661476341d0c792a1a12bc78b19f9fdd"
-  integrity sha512-DHeq87Sx9Dv37FYyvZkmA1VYsQUNaVgc3QzMUkFwoHt1T4EZzgyYpdsp3uYruJzUW0ACvVJcwFdrU4e1VS97dQ==
+matrix-js-sdk@12.0.1:
+  version "12.0.1"
+  resolved "https://registry.yarnpkg.com/matrix-js-sdk/-/matrix-js-sdk-12.0.1.tgz#3a63881f743420a4d39474daa39bd0fb90930d43"
+  integrity sha512-HkOWv8QHojceo3kPbC+vAIFUjsRAig6MBvEY35UygS3g2dL0UcJ5Qx09/2wcXtu6dowlDnWsz2HHk62tS2cklA==
   dependencies:
     "@babel/runtime" "^7.12.5"
     another-json "^0.2.0"
@@ -5456,6 +5461,7 @@ matrix-js-sdk@12.0.0:
     bs58 "^4.0.1"
     content-type "^1.0.4"
     loglevel "^1.7.1"
+    p-retry "^4.5.0"
     qs "^6.9.6"
     request "^2.88.2"
     unhomoglyph "^1.0.6"
@@ -6007,6 +6013,14 @@ p-locate@^4.1.0:
   dependencies:
     p-limit "^2.2.0"
 
+p-retry@^4.5.0:
+  version "4.6.0"
+  resolved "https://registry.yarnpkg.com/p-retry/-/p-retry-4.6.0.tgz#9de15ae696278cffe86fce2d8f73b7f894f8bc9e"
+  integrity sha512-SAHbQEwg3X5DRNaLmWjT+DlGc93ba5i+aP3QLfVNDncQEQO4xjbYW4N/lcVTSuP0aJietGfx2t94dJLzfBMpXw==
+  dependencies:
+    "@types/retry" "^0.12.0"
+    retry "^0.13.1"
+
 p-try@^2.0.0:
   version "2.2.0"
   resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6"
@@ -6816,6 +6830,11 @@ ret@~0.1.10:
   resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc"
   integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==
 
+retry@^0.13.1:
+  version "0.13.1"
+  resolved "https://registry.yarnpkg.com/retry/-/retry-0.13.1.tgz#185b1587acf67919d63b357349e03537b2484658"
+  integrity sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==
+
 reusify@^1.0.4:
   version "1.0.4"
   resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76"

From 5fb7dbee3e83ee1e3b7b2d09df8424c6fa45cf14 Mon Sep 17 00:00:00 2001
From: Germain Souquet <germain@souquet.com>
Date: Wed, 7 Jul 2021 16:11:47 +0200
Subject: [PATCH 26/31] Do not generate a lockfile when running in CI

---
 scripts/ci/install-deps.sh               | 4 ++--
 scripts/ci/layered.sh                    | 6 +++---
 test/end-to-end-tests/element/install.sh | 2 +-
 test/end-to-end-tests/install.sh         | 2 +-
 4 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/scripts/ci/install-deps.sh b/scripts/ci/install-deps.sh
index bbda74ef9d..fcbf6b1198 100755
--- a/scripts/ci/install-deps.sh
+++ b/scripts/ci/install-deps.sh
@@ -6,8 +6,8 @@ scripts/fetchdep.sh matrix-org matrix-js-sdk
 
 pushd matrix-js-sdk
 yarn link
-yarn install $@
+yarn install --pure-lockfile $@
 popd
 
 yarn link matrix-js-sdk
-yarn install $@
+yarn install --pure-lockfile $@
diff --git a/scripts/ci/layered.sh b/scripts/ci/layered.sh
index 039f90c7df..2e163456fe 100755
--- a/scripts/ci/layered.sh
+++ b/scripts/ci/layered.sh
@@ -13,13 +13,13 @@
 scripts/fetchdep.sh matrix-org matrix-js-sdk
 pushd matrix-js-sdk
 yarn link
-yarn install
+yarn install --pure-lockfile
 popd
 
 # Now set up the react-sdk
 yarn link matrix-js-sdk
 yarn link
-yarn install
+yarn install --pure-lockfile
 yarn reskindex
 
 # Finally, set up element-web
@@ -27,6 +27,6 @@ scripts/fetchdep.sh vector-im element-web
 pushd element-web
 yarn link matrix-js-sdk
 yarn link matrix-react-sdk
-yarn install
+yarn install --pure-lockfile
 yarn build:res
 popd
diff --git a/test/end-to-end-tests/element/install.sh b/test/end-to-end-tests/element/install.sh
index e38f795df1..e1df709c68 100755
--- a/test/end-to-end-tests/element/install.sh
+++ b/test/end-to-end-tests/element/install.sh
@@ -12,5 +12,5 @@ unzip -q element.zip
 rm element.zip
 mv element-web-${ELEMENT_BRANCH} element-web
 cd element-web
-yarn install
+yarn install --pure-lockfile
 yarn run build
diff --git a/test/end-to-end-tests/install.sh b/test/end-to-end-tests/install.sh
index bbe7a24c9b..b2254a4ea7 100755
--- a/test/end-to-end-tests/install.sh
+++ b/test/end-to-end-tests/install.sh
@@ -4,4 +4,4 @@ set -e
 ./synapse/install.sh
 # local testing doesn't need a Element fetched from master,
 # so not installing that by default
-yarn install
+yarn install --pure-lockfile

From 14303a4ca8da6b93451d4895e292c44ac4c97cc6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C5=A0imon=20Brandner?= <simon.bra.ag@gmail.com>
Date: Wed, 7 Jul 2021 17:20:31 +0200
Subject: [PATCH 27/31] Delint
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
---
 src/components/structures/auth/ForgotPassword.tsx | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/components/structures/auth/ForgotPassword.tsx b/src/components/structures/auth/ForgotPassword.tsx
index 432f69fd1b..6382e143f9 100644
--- a/src/components/structures/auth/ForgotPassword.tsx
+++ b/src/components/structures/auth/ForgotPassword.tsx
@@ -45,7 +45,7 @@ enum Phase {
 
 interface IProps {
     serverConfig: ValidatedServerConfig;
-    onServerConfigChange: () => void;
+    onServerConfigChange: (serverConfig: ValidatedServerConfig) => void;
     onLoginClick?: () => void;
     onComplete: () => void;
 }

From 06d589d76933cd4483c26122432887c52b8786e5 Mon Sep 17 00:00:00 2001
From: Michael Telatynski <7t3chguy@gmail.com>
Date: Wed, 7 Jul 2021 19:43:12 +0100
Subject: [PATCH 28/31] Lower number of blurhash components and apply image
 ratio to it

---
 src/ContentMessages.tsx | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/src/ContentMessages.tsx b/src/ContentMessages.tsx
index 66ca8a559f..670c175a48 100644
--- a/src/ContentMessages.tsx
+++ b/src/ContentMessages.tsx
@@ -49,8 +49,6 @@ const MAX_HEIGHT = 600;
 const PHYS_HIDPI = [0x00, 0x00, 0x16, 0x25, 0x00, 0x00, 0x16, 0x25, 0x01];
 
 export const BLURHASH_FIELD = "xyz.amorgan.blurhash"; // MSC2448
-const BLURHASH_X_COMPONENTS = 6;
-const BLURHASH_Y_COMPONENTS = 6;
 
 export class UploadCanceledError extends Error {}
 
@@ -137,8 +135,9 @@ function createThumbnail(
             imageData.data,
             imageData.width,
             imageData.height,
-            BLURHASH_X_COMPONENTS,
-            BLURHASH_Y_COMPONENTS,
+            // use 4 components on the longer dimension, if square then both
+            imageData.width >= imageData.height ? 4 : 3,
+            imageData.height >= imageData.width ? 4 : 3,
         );
         canvas.toBlob(function(thumbnail) {
             resolve({

From 4ce3723e84db6a9b5771f9adf73fca36abc2620d Mon Sep 17 00:00:00 2001
From: Michael Telatynski <7t3chguy@gmail.com>
Date: Wed, 7 Jul 2021 20:00:31 +0100
Subject: [PATCH 29/31] Switch to blurhash-react instead of homegrown component

this has the advantage of resolution scaling logic to do more gpu accelerated scaling
---
 package.json                                  |  1 +
 .../views/elements/BlurhashPlaceholder.tsx    | 56 -------------------
 src/components/views/messages/MImageBody.js   |  4 +-
 yarn.lock                                     |  5 ++
 4 files changed, 8 insertions(+), 58 deletions(-)
 delete mode 100644 src/components/views/elements/BlurhashPlaceholder.tsx

diff --git a/package.json b/package.json
index 610404ba0d..54425a1f74 100644
--- a/package.json
+++ b/package.json
@@ -92,6 +92,7 @@
     "re-resizable": "^6.9.0",
     "react": "^17.0.2",
     "react-beautiful-dnd": "^13.1.0",
+    "react-blurhash": "^0.1.3",
     "react-dom": "^17.0.2",
     "react-focus-lock": "^2.5.0",
     "react-transition-group": "^4.4.1",
diff --git a/src/components/views/elements/BlurhashPlaceholder.tsx b/src/components/views/elements/BlurhashPlaceholder.tsx
deleted file mode 100644
index 0e59253fe8..0000000000
--- a/src/components/views/elements/BlurhashPlaceholder.tsx
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- 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 React from 'react';
-import { decode } from "blurhash";
-
-interface IProps {
-    blurhash: string;
-    width: number;
-    height: number;
-}
-
-export default class BlurhashPlaceholder extends React.PureComponent<IProps> {
-    private canvas: React.RefObject<HTMLCanvasElement> = React.createRef();
-
-    public componentDidMount() {
-        this.draw();
-    }
-
-    public componentDidUpdate() {
-        this.draw();
-    }
-
-    private draw() {
-        if (!this.canvas.current) return;
-
-        try {
-            const { width, height } = this.props;
-
-            const pixels = decode(this.props.blurhash, Math.ceil(width), Math.ceil(height));
-            const ctx = this.canvas.current.getContext("2d");
-            const imgData = ctx.createImageData(width, height);
-            imgData.data.set(pixels);
-            ctx.putImageData(imgData, 0, 0);
-        } catch (e) {
-            console.error("Error rendering blurhash: ", e);
-        }
-    }
-
-    public render() {
-        return <canvas height={this.props.height} width={this.props.width} ref={this.canvas} />;
-    }
-}
diff --git a/src/components/views/messages/MImageBody.js b/src/components/views/messages/MImageBody.js
index 5566f5aec0..6da4aa1494 100644
--- a/src/components/views/messages/MImageBody.js
+++ b/src/components/views/messages/MImageBody.js
@@ -18,6 +18,7 @@ limitations under the License.
 
 import React, { createRef } from 'react';
 import PropTypes from 'prop-types';
+import { Blurhash } from "react-blurhash";
 
 import MFileBody from './MFileBody';
 import Modal from '../../../Modal';
@@ -29,7 +30,6 @@ import MatrixClientContext from "../../../contexts/MatrixClientContext";
 import InlineSpinner from '../elements/InlineSpinner';
 import { replaceableComponent } from "../../../utils/replaceableComponent";
 import { mediaFromContent } from "../../../customisations/Media";
-import BlurhashPlaceholder from "../elements/BlurhashPlaceholder";
 import { BLURHASH_FIELD } from "../../../ContentMessages";
 
 @replaceableComponent("views.messages.MImageBody")
@@ -436,7 +436,7 @@ export default class MImageBody extends React.Component {
     // Overidden by MStickerBody
     getPlaceholder(width, height) {
         const blurhash = this.props.mxEvent.getContent().info[BLURHASH_FIELD];
-        if (blurhash) return <BlurhashPlaceholder blurhash={blurhash} width={width} height={height} />;
+        if (blurhash) return <Blurhash hash={blurhash} width={width} height={height} />;
         return <div className="mx_MImageBody_thumbnail_spinner">
             <InlineSpinner w={32} h={32} />
         </div>;
diff --git a/yarn.lock b/yarn.lock
index ea4adfb09f..90f415673d 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -6454,6 +6454,11 @@ react-beautiful-dnd@^13.1.0:
     redux "^4.0.4"
     use-memo-one "^1.1.1"
 
+react-blurhash@^0.1.3:
+  version "0.1.3"
+  resolved "https://registry.yarnpkg.com/react-blurhash/-/react-blurhash-0.1.3.tgz#735f28f8f07fb358d7efe7e7e6dc65a7272bf89e"
+  integrity sha512-Q9lqbXg92NU6/2DoIl/cBM8YWL+Z4X66OiG4aT9ozOgjBwx104LHFCH5stf6aF+s0Q9Wf310Ul+dG+VXJltmPg==
+
 react-clientside-effect@^1.2.2:
   version "1.2.3"
   resolved "https://registry.yarnpkg.com/react-clientside-effect/-/react-clientside-effect-1.2.3.tgz#95c95f520addfb71743608b990bfe01eb002012b"

From d8bf618d73983515bc08f9038975b267c3cd00e9 Mon Sep 17 00:00:00 2001
From: Michael Telatynski <7t3chguy@gmail.com>
Date: Wed, 7 Jul 2021 20:08:52 +0100
Subject: [PATCH 30/31] unrelated: move @types/commonmark to devDeps

---
 package.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/package.json b/package.json
index 54425a1f74..bb92ad11d8 100644
--- a/package.json
+++ b/package.json
@@ -54,7 +54,6 @@
   },
   "dependencies": {
     "@babel/runtime": "^7.12.5",
-    "@types/commonmark": "^0.27.4",
     "await-lock": "^2.1.0",
     "blurhash": "^1.1.3",
     "browser-encrypt-attachment": "^0.3.0",
@@ -125,6 +124,7 @@
     "@peculiar/webcrypto": "^1.1.4",
     "@sinonjs/fake-timers": "^7.0.2",
     "@types/classnames": "^2.2.11",
+    "@types/commonmark": "^0.27.4",
     "@types/counterpart": "^0.18.1",
     "@types/diff-match-patch": "^1.0.32",
     "@types/flux": "^3.1.9",

From 086a8cbbb39bdd6e68a597a6bab5ef05031a6047 Mon Sep 17 00:00:00 2001
From: David Baker <dave@matrix.org>
Date: Wed, 7 Jul 2021 20:19:52 +0100
Subject: [PATCH 31/31] Update import location for types

Apparently all the types themselves are fine, even though some of
the function signatures have been updated to return Promises... we
were alreaady await-ing on them.
---
 src/SecurityManager.ts                                         | 3 ++-
 src/components/structures/auth/SetupEncryptionBody.tsx         | 2 +-
 .../views/dialogs/security/AccessSecretStorageDialog.tsx       | 2 +-
 src/customisations/Security.ts                                 | 2 +-
 src/stores/SetupEncryptionStore.ts                             | 2 +-
 5 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/src/SecurityManager.ts b/src/SecurityManager.ts
index 214047c4fa..854457db50 100644
--- a/src/SecurityManager.ts
+++ b/src/SecurityManager.ts
@@ -14,7 +14,8 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-import { ICryptoCallbacks, ISecretStorageKeyInfo } from 'matrix-js-sdk/src/matrix';
+import { ICryptoCallbacks } from 'matrix-js-sdk/src/matrix';
+import { ISecretStorageKeyInfo } from 'matrix-js-sdk/src/crypto/api';
 import { MatrixClient } from 'matrix-js-sdk/src/client';
 import Modal from './Modal';
 import * as sdk from './index';
diff --git a/src/components/structures/auth/SetupEncryptionBody.tsx b/src/components/structures/auth/SetupEncryptionBody.tsx
index 13790c2e47..c7ce74077b 100644
--- a/src/components/structures/auth/SetupEncryptionBody.tsx
+++ b/src/components/structures/auth/SetupEncryptionBody.tsx
@@ -21,7 +21,7 @@ import Modal from '../../../Modal';
 import VerificationRequestDialog from '../../views/dialogs/VerificationRequestDialog';
 import { SetupEncryptionStore, Phase } from '../../../stores/SetupEncryptionStore';
 import { replaceableComponent } from "../../../utils/replaceableComponent";
-import { ISecretStorageKeyInfo } from 'matrix-js-sdk';
+import { ISecretStorageKeyInfo } from 'matrix-js-sdk/src/crypto/api';
 import EncryptionPanel from "../../views/right_panel/EncryptionPanel";
 import AccessibleButton from '../../views/elements/AccessibleButton';
 import Spinner from '../../views/elements/Spinner';
diff --git a/src/components/views/dialogs/security/AccessSecretStorageDialog.tsx b/src/components/views/dialogs/security/AccessSecretStorageDialog.tsx
index d614cc0956..90c640977c 100644
--- a/src/components/views/dialogs/security/AccessSecretStorageDialog.tsx
+++ b/src/components/views/dialogs/security/AccessSecretStorageDialog.tsx
@@ -17,7 +17,7 @@ limitations under the License.
 import { debounce } from "lodash";
 import classNames from 'classnames';
 import React, { ChangeEvent, FormEvent } from 'react';
-import { ISecretStorageKeyInfo } from "matrix-js-sdk/src";
+import { ISecretStorageKeyInfo } from "matrix-js-sdk/src/crypto/api";
 
 import * as sdk from '../../../../index';
 import { MatrixClientPeg } from '../../../../MatrixClientPeg';
diff --git a/src/customisations/Security.ts b/src/customisations/Security.ts
index c2262e5f71..9083274aa5 100644
--- a/src/customisations/Security.ts
+++ b/src/customisations/Security.ts
@@ -16,7 +16,7 @@ limitations under the License.
 
 import { IMatrixClientCreds } from "../MatrixClientPeg";
 import { Kind as SetupEncryptionKind } from "../toasts/SetupEncryptionToast";
-import { ISecretStorageKeyInfo } from 'matrix-js-sdk/src/matrix';
+import { ISecretStorageKeyInfo } from 'matrix-js-sdk/src/crypto/api';
 
 /* eslint-disable-next-line @typescript-eslint/no-unused-vars */
 function examineLoginResponse(
diff --git a/src/stores/SetupEncryptionStore.ts b/src/stores/SetupEncryptionStore.ts
index e969c64853..7197374502 100644
--- a/src/stores/SetupEncryptionStore.ts
+++ b/src/stores/SetupEncryptionStore.ts
@@ -17,7 +17,7 @@ limitations under the License.
 import EventEmitter from 'events';
 import { VerificationRequest } from "matrix-js-sdk/src/crypto/verification/request/VerificationRequest";
 import { IKeyBackupInfo } from "matrix-js-sdk/src/crypto/keybackup";
-import { ISecretStorageKeyInfo } from "matrix-js-sdk/src/matrix";
+import { ISecretStorageKeyInfo } from "matrix-js-sdk/src/crypto/api";
 import { PHASE_DONE as VERIF_PHASE_DONE } from "matrix-js-sdk/src/crypto/verification/request/VerificationRequest";
 
 import { MatrixClientPeg } from '../MatrixClientPeg';