From 9ba33c7f80e3c812825415923994eaf98181524f Mon Sep 17 00:00:00 2001
From: Michael Telatynski <7t3chguy@gmail.com>
Date: Sat, 29 Aug 2020 01:11:08 +0100
Subject: [PATCH] Fix eslint ts override tsx matching and delint

---
 .eslintrc.js                                  |  2 +-
 src/ContentMessages.tsx                       | 20 ++++---
 src/HtmlUtils.tsx                             | 11 +++-
 src/Modal.tsx                                 |  8 +--
 src/SlashCommands.tsx                         | 14 ++---
 src/accessibility/KeyboardShortcuts.tsx       |  2 +-
 src/accessibility/RovingTabIndex.tsx          |  2 +-
 src/accessibility/Toolbar.tsx                 |  3 +-
 .../context_menu/ContextMenuTooltipButton.tsx |  2 +-
 .../roving/RovingAccessibleTooltipButton.tsx  |  3 +-
 .../roving/RovingTabIndexWrapper.tsx          |  1 -
 src/autocomplete/CommandProvider.tsx          |  6 ++-
 src/autocomplete/CommunityProvider.tsx        | 12 ++---
 src/autocomplete/Components.tsx               | 12 ++---
 src/autocomplete/EmojiProvider.tsx            |  6 ++-
 src/autocomplete/RoomProvider.tsx             |  4 +-
 src/autocomplete/UserProvider.tsx             | 15 ++++--
 src/components/structures/ContextMenu.tsx     |  3 +-
 src/components/structures/LeftPanel.tsx       |  2 +-
 src/components/structures/LoggedInView.tsx    | 37 +++++++------
 src/components/structures/MatrixChat.tsx      | 17 +++---
 src/components/structures/RoomSearch.tsx      |  3 +-
 src/components/structures/TabbedView.tsx      |  1 -
 src/components/structures/UserMenu.tsx        | 12 ++---
 src/components/views/avatars/BaseAvatar.tsx   |  4 +-
 .../views/avatars/DecoratedRoomAvatar.tsx     |  2 +-
 src/components/views/avatars/GroupAvatar.tsx  |  2 +-
 src/components/views/avatars/PulsedAvatar.tsx |  2 +-
 .../CommunityPrototypeInviteDialog.tsx        | 52 ++++++++-----------
 .../CreateCommunityPrototypeDialog.tsx        | 10 +++-
 src/components/views/dialogs/ShareDialog.tsx  | 20 +++----
 src/components/views/elements/Draggable.tsx   |  4 +-
 .../views/elements/EventTilePreview.tsx       | 14 +++--
 src/components/views/elements/Field.tsx       |  6 +--
 .../elements/IRCTimelineProfileResizer.tsx    |  7 ++-
 src/components/views/elements/InfoTooltip.tsx |  1 -
 src/components/views/elements/QRCode.tsx      |  2 +-
 src/components/views/elements/Slider.tsx      | 19 ++++---
 .../views/elements/StyledCheckbox.tsx         |  7 ++-
 .../views/right_panel/EncryptionInfo.tsx      |  6 ++-
 .../views/right_panel/HeaderButtons.tsx       | 16 +++---
 .../views/right_panel/VerificationPanel.tsx   | 23 ++++----
 .../views/rooms/NotificationBadge.tsx         |  1 +
 src/components/views/rooms/RoomList.tsx       | 32 ++++++------
 src/components/views/rooms/RoomSublist.tsx    | 25 +++++----
 src/components/views/rooms/RoomTile.tsx       |  6 +--
 src/components/views/rooms/TemporaryTile.tsx  |  2 -
 .../views/settings/UpdateCheckButton.tsx      |  2 +-
 .../tabs/user/AppearanceUserSettingsTab.tsx   |  4 +-
 .../views/toasts/GenericExpiringToast.tsx     | 10 +++-
 src/components/views/toasts/GenericToast.tsx  |  8 ++-
 src/components/views/voip/CallView.tsx        |  5 +-
 src/components/views/voip/IncomingCallBox.tsx |  3 +-
 src/languageHandler.tsx                       |  6 +--
 54 files changed, 268 insertions(+), 231 deletions(-)

diff --git a/.eslintrc.js b/.eslintrc.js
index fc82e75ce2..bc2a142c2d 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -19,7 +19,7 @@ module.exports = {
     },
 
     overrides: [{
-        "files": ["src/**/*.{ts, tsx}"],
+        "files": ["src/**/*.{ts,tsx}"],
         "extends": ["matrix-org/ts"],
         "rules": {
             // We disable this while we're transitioning
diff --git a/src/ContentMessages.tsx b/src/ContentMessages.tsx
index 6f55a75d0c..eb8fff0eb1 100644
--- a/src/ContentMessages.tsx
+++ b/src/ContentMessages.tsx
@@ -70,6 +70,7 @@ interface IContent {
 
 interface IThumbnail {
     info: {
+        // eslint-disable-next-line camelcase
         thumbnail_info: {
             w: number;
             h: number;
@@ -104,7 +105,12 @@ interface IAbortablePromise<T> extends Promise<T> {
  * @return {Promise} A promise that resolves with an object with an info key
  *  and a thumbnail key.
  */
-function createThumbnail(element: ThumbnailableElement, inputWidth: number, inputHeight: number, mimeType: string): Promise<IThumbnail> {
+function createThumbnail(
+    element: ThumbnailableElement,
+    inputWidth: number,
+    inputHeight: number,
+    mimeType: string,
+): Promise<IThumbnail> {
     return new Promise((resolve) => {
         let targetWidth = inputWidth;
         let targetHeight = inputHeight;
@@ -437,11 +443,13 @@ export default class ContentMessages {
         for (let i = 0; i < okFiles.length; ++i) {
             const file = okFiles[i];
             if (!uploadAll) {
-                const {finished} = Modal.createTrackedDialog<[boolean, boolean]>('Upload Files confirmation', '', UploadConfirmDialog, {
-                    file,
-                    currentIndex: i,
-                    totalFiles: okFiles.length,
-                });
+                const {finished} = Modal.createTrackedDialog<[boolean, boolean]>('Upload Files confirmation',
+                    '', UploadConfirmDialog, {
+                        file,
+                        currentIndex: i,
+                        totalFiles: okFiles.length,
+                    },
+                );
                 const [shouldContinue, shouldUploadAll] = await finished;
                 if (!shouldContinue) break;
                 if (shouldUploadAll) {
diff --git a/src/HtmlUtils.tsx b/src/HtmlUtils.tsx
index 5d33645bb7..2ce9e40aa6 100644
--- a/src/HtmlUtils.tsx
+++ b/src/HtmlUtils.tsx
@@ -339,6 +339,7 @@ class HtmlHighlighter extends BaseHighlighter<string> {
     }
 }
 
+// eslint-disable-next-line @typescript-eslint/no-unused-vars
 class TextHighlighter extends BaseHighlighter<React.ReactNode> {
     private key = 0;
 
@@ -366,6 +367,7 @@ class TextHighlighter extends BaseHighlighter<React.ReactNode> {
 
 interface IContent {
     format?: string;
+    // eslint-disable-next-line camelcase
     formatted_body?: string;
     body: string;
 }
@@ -474,8 +476,13 @@ export function bodyToHtml(content: IContent, highlights: string[], opts: IOpts
     });
 
     return isDisplayedWithHtml ?
-        <span key="body" ref={opts.ref} className={className} dangerouslySetInnerHTML={{ __html: safeBody }} dir="auto" /> :
-        <span key="body" ref={opts.ref} className={className} dir="auto">{ strippedBody }</span>;
+        <span
+            key="body"
+            ref={opts.ref}
+            className={className}
+            dangerouslySetInnerHTML={{ __html: safeBody }}
+            dir="auto"
+        /> : <span key="body" ref={opts.ref} className={className} dir="auto">{ strippedBody }</span>;
 }
 
 /**
diff --git a/src/Modal.tsx b/src/Modal.tsx
index 82ed33b794..0a36813961 100644
--- a/src/Modal.tsx
+++ b/src/Modal.tsx
@@ -151,7 +151,7 @@ export class ModalManager {
         prom: Promise<React.ComponentType>,
         props?: IProps<T>,
         className?: string,
-        options?: IOptions<T>
+        options?: IOptions<T>,
     ) {
         const modal: IModal<T> = {
             onFinished: props ? props.onFinished : null,
@@ -182,7 +182,7 @@ export class ModalManager {
 
     private getCloseFn<T extends any[]>(
         modal: IModal<T>,
-        props: IProps<T>
+        props: IProps<T>,
     ): [IHandle<T>["close"], IHandle<T>["finished"]] {
         const deferred = defer<T>();
         return [async (...args: T) => {
@@ -264,7 +264,7 @@ export class ModalManager {
         className?: string,
         isPriorityModal = false,
         isStaticModal = false,
-        options: IOptions<T> = {}
+        options: IOptions<T> = {},
     ): IHandle<T> {
         const {modal, closeDialog, onFinishedProm} = this.buildModal<T>(prom, props, className, options);
         if (isPriorityModal) {
@@ -287,7 +287,7 @@ export class ModalManager {
     private appendDialogAsync<T extends any[]>(
         prom: Promise<React.ComponentType>,
         props?: IProps<T>,
-        className?: string
+        className?: string,
     ): IHandle<T> {
         const {modal, closeDialog, onFinishedProm} = this.buildModal<T>(prom, props, className, {});
 
diff --git a/src/SlashCommands.tsx b/src/SlashCommands.tsx
index d674634109..661ab74e6f 100644
--- a/src/SlashCommands.tsx
+++ b/src/SlashCommands.tsx
@@ -860,12 +860,12 @@ export const Commands = [
                                 _t('WARNING: KEY VERIFICATION FAILED! The signing key for %(userId)s and session' +
                                     ' %(deviceId)s is "%(fprint)s" which does not match the provided key ' +
                                     '"%(fingerprint)s". This could mean your communications are being intercepted!',
-                                    {
-                                        fprint,
-                                        userId,
-                                        deviceId,
-                                        fingerprint,
-                                    }));
+                                {
+                                    fprint,
+                                    userId,
+                                    deviceId,
+                                    fingerprint,
+                                }));
                         }
 
                         await cli.setDeviceVerified(userId, deviceId, true);
@@ -879,7 +879,7 @@ export const Commands = [
                                     {
                                         _t('The signing key you provided matches the signing key you received ' +
                                             'from %(userId)s\'s session %(deviceId)s. Session marked as verified.',
-                                            {userId, deviceId})
+                                        {userId, deviceId})
                                     }
                                 </p>
                             </div>,
diff --git a/src/accessibility/KeyboardShortcuts.tsx b/src/accessibility/KeyboardShortcuts.tsx
index f527ab4a14..58d8124122 100644
--- a/src/accessibility/KeyboardShortcuts.tsx
+++ b/src/accessibility/KeyboardShortcuts.tsx
@@ -168,7 +168,7 @@ const shortcuts: Record<Categories, IShortcut[]> = {
                 key: Key.U,
             }],
             description: _td("Upload a file"),
-        }
+        },
     ],
 
     [Categories.ROOM_LIST]: [
diff --git a/src/accessibility/RovingTabIndex.tsx b/src/accessibility/RovingTabIndex.tsx
index 5a650d4b6e..b1dbb56a01 100644
--- a/src/accessibility/RovingTabIndex.tsx
+++ b/src/accessibility/RovingTabIndex.tsx
@@ -190,7 +190,7 @@ export const RovingTabIndexProvider: React.FC<IProps> = ({children, handleHomeEn
             ev.preventDefault();
             ev.stopPropagation();
         } else if (onKeyDown) {
-            return onKeyDown(ev, state);
+            return onKeyDown(ev, context.state);
         }
     }, [context.state, onKeyDown, handleHomeEnd]);
 
diff --git a/src/accessibility/Toolbar.tsx b/src/accessibility/Toolbar.tsx
index 0e968461a8..cc2a1769c7 100644
--- a/src/accessibility/Toolbar.tsx
+++ b/src/accessibility/Toolbar.tsx
@@ -30,6 +30,7 @@ const Toolbar: React.FC<IProps> = ({children, ...props}) => {
         const target = ev.target as HTMLElement;
         let handled = true;
 
+        // HOME and END are handled by RovingTabIndexProvider
         switch (ev.key) {
             case Key.ARROW_UP:
             case Key.ARROW_DOWN:
@@ -47,8 +48,6 @@ const Toolbar: React.FC<IProps> = ({children, ...props}) => {
                 }
                 break;
 
-            // HOME and END are handled by RovingTabIndexProvider
-
             default:
                 handled = false;
         }
diff --git a/src/accessibility/context_menu/ContextMenuTooltipButton.tsx b/src/accessibility/context_menu/ContextMenuTooltipButton.tsx
index abc5412100..49f57ca7b6 100644
--- a/src/accessibility/context_menu/ContextMenuTooltipButton.tsx
+++ b/src/accessibility/context_menu/ContextMenuTooltipButton.tsx
@@ -20,7 +20,7 @@ import React from "react";
 
 import AccessibleTooltipButton from "../../components/views/elements/AccessibleTooltipButton";
 
-interface IProps extends React.ComponentProps<typeof AccessibleTooltipButton>  {
+interface IProps extends React.ComponentProps<typeof AccessibleTooltipButton> {
     // whether or not the context menu is currently open
     isExpanded: boolean;
 }
diff --git a/src/accessibility/roving/RovingAccessibleTooltipButton.tsx b/src/accessibility/roving/RovingAccessibleTooltipButton.tsx
index cc824fef22..2cb974d60e 100644
--- a/src/accessibility/roving/RovingAccessibleTooltipButton.tsx
+++ b/src/accessibility/roving/RovingAccessibleTooltipButton.tsx
@@ -20,7 +20,8 @@ import AccessibleTooltipButton from "../../components/views/elements/AccessibleT
 import {useRovingTabIndex} from "../RovingTabIndex";
 import {Ref} from "./types";
 
-interface IProps extends Omit<React.ComponentProps<typeof AccessibleTooltipButton>, "onFocus" | "inputRef" | "tabIndex"> {
+type ATBProps = React.ComponentProps<typeof AccessibleTooltipButton>;
+interface IProps extends Omit<ATBProps, "onFocus" | "inputRef" | "tabIndex"> {
     inputRef?: Ref;
 }
 
diff --git a/src/accessibility/roving/RovingTabIndexWrapper.tsx b/src/accessibility/roving/RovingTabIndexWrapper.tsx
index c826b74497..5211f30215 100644
--- a/src/accessibility/roving/RovingTabIndexWrapper.tsx
+++ b/src/accessibility/roving/RovingTabIndexWrapper.tsx
@@ -16,7 +16,6 @@ limitations under the License.
 
 import React from "react";
 
-import AccessibleButton from "../../components/views/elements/AccessibleButton";
 import {useRovingTabIndex} from "../RovingTabIndex";
 import {FocusHandler, Ref} from "./types";
 
diff --git a/src/autocomplete/CommandProvider.tsx b/src/autocomplete/CommandProvider.tsx
index e7a6f44536..3ff8ff0469 100644
--- a/src/autocomplete/CommandProvider.tsx
+++ b/src/autocomplete/CommandProvider.tsx
@@ -89,7 +89,11 @@ export default class CommandProvider extends AutocompleteProvider {
 
     renderCompletions(completions: React.ReactNode[]): React.ReactNode {
         return (
-            <div className="mx_Autocomplete_Completion_container_block" role="listbox" aria-label={_t("Command Autocomplete")}>
+            <div
+                className="mx_Autocomplete_Completion_container_block"
+                role="listbox"
+                aria-label={_t("Command Autocomplete")}
+            >
                 { completions }
             </div>
         );
diff --git a/src/autocomplete/CommunityProvider.tsx b/src/autocomplete/CommunityProvider.tsx
index f34fee890e..031fcd6169 100644
--- a/src/autocomplete/CommunityProvider.tsx
+++ b/src/autocomplete/CommunityProvider.tsx
@@ -91,15 +91,15 @@ export default class CommunityProvider extends AutocompleteProvider {
                 href: makeGroupPermalink(groupId),
                 component: (
                     <PillCompletion title={name} description={groupId}>
-                        <BaseAvatar name={name || groupId}
-                                    width={24}
-                                    height={24}
-                                    url={avatarUrl ? cli.mxcUrlToHttp(avatarUrl, 24, 24) : null} />
+                        <BaseAvatar
+                            name={name || groupId}
+                            width={24}
+                            height={24}
+                            url={avatarUrl ? cli.mxcUrlToHttp(avatarUrl, 24, 24) : null} />
                     </PillCompletion>
                 ),
                 range,
-            }))
-            .slice(0, 4);
+            })).slice(0, 4);
         }
         return completions;
     }
diff --git a/src/autocomplete/Components.tsx b/src/autocomplete/Components.tsx
index 6ac2f4db14..4b0d35698d 100644
--- a/src/autocomplete/Components.tsx
+++ b/src/autocomplete/Components.tsx
@@ -34,9 +34,9 @@ export const TextualCompletion = forwardRef<ITextualCompletionProps, any>((props
     const {title, subtitle, description, className, ...restProps} = props;
     return (
         <div {...restProps}
-             className={classNames('mx_Autocomplete_Completion_block', className)}
-             role="option"
-             ref={ref}
+            className={classNames('mx_Autocomplete_Completion_block', className)}
+            role="option"
+            ref={ref}
         >
             <span className="mx_Autocomplete_Completion_title">{ title }</span>
             <span className="mx_Autocomplete_Completion_subtitle">{ subtitle }</span>
@@ -53,9 +53,9 @@ export const PillCompletion = forwardRef<IPillCompletionProps, any>((props, ref)
     const {title, subtitle, description, className, children, ...restProps} = props;
     return (
         <div {...restProps}
-             className={classNames('mx_Autocomplete_Completion_pill', className)}
-             role="option"
-             ref={ref}
+            className={classNames('mx_Autocomplete_Completion_pill', className)}
+            role="option"
+            ref={ref}
         >
             { children }
             <span className="mx_Autocomplete_Completion_title">{ title }</span>
diff --git a/src/autocomplete/EmojiProvider.tsx b/src/autocomplete/EmojiProvider.tsx
index 147d68f5ff..eaca42b0dd 100644
--- a/src/autocomplete/EmojiProvider.tsx
+++ b/src/autocomplete/EmojiProvider.tsx
@@ -139,7 +139,11 @@ export default class EmojiProvider extends AutocompleteProvider {
 
     renderCompletions(completions: React.ReactNode[]): React.ReactNode {
         return (
-            <div className="mx_Autocomplete_Completion_container_pill" role="listbox" aria-label={_t("Emoji Autocomplete")}>
+            <div
+                className="mx_Autocomplete_Completion_container_pill"
+                role="listbox"
+                aria-label={_t("Emoji Autocomplete")}
+            >
                 { completions }
             </div>
         );
diff --git a/src/autocomplete/RoomProvider.tsx b/src/autocomplete/RoomProvider.tsx
index b18b2d132c..defbc8c47f 100644
--- a/src/autocomplete/RoomProvider.tsx
+++ b/src/autocomplete/RoomProvider.tsx
@@ -110,9 +110,7 @@ export default class RoomProvider extends AutocompleteProvider {
                     ),
                     range,
                 };
-            })
-            .filter((completion) => !!completion.completion && completion.completion.length > 0)
-            .slice(0, 4);
+            }).filter((completion) => !!completion.completion && completion.completion.length > 0).slice(0, 4);
         }
         return completions;
     }
diff --git a/src/autocomplete/UserProvider.tsx b/src/autocomplete/UserProvider.tsx
index c957b5e597..3bde4b1d07 100644
--- a/src/autocomplete/UserProvider.tsx
+++ b/src/autocomplete/UserProvider.tsx
@@ -71,8 +71,13 @@ export default class UserProvider extends AutocompleteProvider {
         }
     }
 
-    private onRoomTimeline = (ev: MatrixEvent, room: Room, toStartOfTimeline: boolean, removed: boolean,
-                       data: IRoomTimelineData) => {
+    private onRoomTimeline = (
+        ev: MatrixEvent,
+        room: Room,
+        toStartOfTimeline: boolean,
+        removed: boolean,
+        data: IRoomTimelineData,
+    ) => {
         if (!room) return;
         if (removed) return;
         if (room.roomId !== this.room.roomId) return;
@@ -171,7 +176,11 @@ export default class UserProvider extends AutocompleteProvider {
 
     renderCompletions(completions: React.ReactNode[]): React.ReactNode {
         return (
-            <div className="mx_Autocomplete_Completion_container_pill" role="listbox" aria-label={_t("User Autocomplete")}>
+            <div
+                className="mx_Autocomplete_Completion_container_pill"
+                role="listbox"
+                aria-label={_t("User Autocomplete")}
+            >
                 { completions }
             </div>
         );
diff --git a/src/components/structures/ContextMenu.tsx b/src/components/structures/ContextMenu.tsx
index 587ae2cb6b..64e0160d83 100644
--- a/src/components/structures/ContextMenu.tsx
+++ b/src/components/structures/ContextMenu.tsx
@@ -233,8 +233,7 @@ export class ContextMenu extends React.PureComponent<IProps, IState> {
         switch (ev.key) {
             case Key.TAB:
             case Key.ESCAPE:
-            // close on left and right arrows too for when it is a context menu on a <Toolbar />
-            case Key.ARROW_LEFT:
+            case Key.ARROW_LEFT: // close on left and right arrows too for when it is a context menu on a <Toolbar />
             case Key.ARROW_RIGHT:
                 this.props.onFinished();
                 break;
diff --git a/src/components/structures/LeftPanel.tsx b/src/components/structures/LeftPanel.tsx
index 899dfe222d..1c2295384c 100644
--- a/src/components/structures/LeftPanel.tsx
+++ b/src/components/structures/LeftPanel.tsx
@@ -377,7 +377,7 @@ export default class LeftPanel extends React.Component<IProps, IState> {
     public render(): React.ReactNode {
         const tagPanel = !this.state.showTagPanel ? null : (
             <div className="mx_LeftPanel_tagPanelContainer">
-                <TagPanel/>
+                <TagPanel />
                 {SettingsStore.getValue("feature_custom_tags") ? <CustomRoomTagPanel /> : null}
             </div>
         );
diff --git a/src/components/structures/LoggedInView.tsx b/src/components/structures/LoggedInView.tsx
index d7f2c73a0b..e427eb92cb 100644
--- a/src/components/structures/LoggedInView.tsx
+++ b/src/components/structures/LoggedInView.tsx
@@ -43,11 +43,11 @@ import PlatformPeg from "../../PlatformPeg";
 import { DefaultTagID } from "../../stores/room-list/models";
 import {
     showToast as showSetPasswordToast,
-    hideToast as hideSetPasswordToast
+    hideToast as hideSetPasswordToast,
 } from "../../toasts/SetPasswordToast";
 import {
     showToast as showServerLimitToast,
-    hideToast as hideServerLimitToast
+    hideToast as hideServerLimitToast,
 } from "../../toasts/ServerLimitToast";
 import { Action } from "../../dispatcher/actions";
 import LeftPanel from "./LeftPanel";
@@ -79,6 +79,7 @@ interface IProps {
     initialEventPixelOffset: number;
     leftDisabled: boolean;
     rightDisabled: boolean;
+    // eslint-disable-next-line camelcase
     page_type: string;
     autoJoin: boolean;
     thirdPartyInvite?: object;
@@ -98,7 +99,9 @@ interface IProps {
 }
 
 interface IUsageLimit {
+    // eslint-disable-next-line camelcase
     limit_type: "monthly_active_user" | string;
+    // eslint-disable-next-line camelcase
     admin_contact?: string;
 }
 
@@ -316,10 +319,10 @@ class LoggedInView extends React.Component<IProps, IState> {
         }
     };
 
-    _calculateServerLimitToast(syncErrorData: IState["syncErrorData"], usageLimitEventContent?: IUsageLimit) {
-        const error = syncErrorData && syncErrorData.error && syncErrorData.error.errcode === "M_RESOURCE_LIMIT_EXCEEDED";
+    _calculateServerLimitToast(syncError: IState["syncErrorData"], usageLimitEventContent?: IUsageLimit) {
+        const error = syncError && syncError.error && syncError.error.errcode === "M_RESOURCE_LIMIT_EXCEEDED";
         if (error) {
-            usageLimitEventContent = syncErrorData.error.data;
+            usageLimitEventContent = syncError.error.data;
         }
 
         if (usageLimitEventContent) {
@@ -620,18 +623,18 @@ class LoggedInView extends React.Component<IProps, IState> {
         switch (this.props.page_type) {
             case PageTypes.RoomView:
                 pageElement = <RoomView
-                        ref={this._roomView}
-                        autoJoin={this.props.autoJoin}
-                        onRegistered={this.props.onRegistered}
-                        thirdPartyInvite={this.props.thirdPartyInvite}
-                        oobData={this.props.roomOobData}
-                        viaServers={this.props.viaServers}
-                        eventPixelOffset={this.props.initialEventPixelOffset}
-                        key={this.props.currentRoomId || 'roomview'}
-                        disabled={this.props.middleDisabled}
-                        ConferenceHandler={this.props.ConferenceHandler}
-                        resizeNotifier={this.props.resizeNotifier}
-                    />;
+                    ref={this._roomView}
+                    autoJoin={this.props.autoJoin}
+                    onRegistered={this.props.onRegistered}
+                    thirdPartyInvite={this.props.thirdPartyInvite}
+                    oobData={this.props.roomOobData}
+                    viaServers={this.props.viaServers}
+                    eventPixelOffset={this.props.initialEventPixelOffset}
+                    key={this.props.currentRoomId || 'roomview'}
+                    disabled={this.props.middleDisabled}
+                    ConferenceHandler={this.props.ConferenceHandler}
+                    resizeNotifier={this.props.resizeNotifier}
+                />;
                 break;
 
             case PageTypes.MyGroups:
diff --git a/src/components/structures/MatrixChat.tsx b/src/components/structures/MatrixChat.tsx
index 9d51062b7d..176aaf95a3 100644
--- a/src/components/structures/MatrixChat.tsx
+++ b/src/components/structures/MatrixChat.tsx
@@ -69,7 +69,7 @@ import { ViewUserPayload } from "../../dispatcher/payloads/ViewUserPayload";
 import { Action } from "../../dispatcher/actions";
 import {
     showToast as showAnalyticsToast,
-    hideToast as hideAnalyticsToast
+    hideToast as hideAnalyticsToast,
 } from "../../toasts/AnalyticsToast";
 import {showToast as showNotificationsToast} from "../../toasts/DesktopNotificationsToast";
 import { OpenToTabPayload } from "../../dispatcher/payloads/OpenToTabPayload";
@@ -129,6 +129,7 @@ interface IScreen {
     params?: object;
 }
 
+/* eslint-disable camelcase */
 interface IRoomInfo {
     room_id?: string;
     room_alias?: string;
@@ -140,6 +141,7 @@ interface IRoomInfo {
     oob_data?: object;
     via_servers?: string[];
 }
+/* eslint-enable camelcase */
 
 interface IProps { // TODO type things better
     config: Record<string, any>;
@@ -165,6 +167,7 @@ interface IState {
     // the master view we are showing.
     view: Views;
     // What the LoggedInView would be showing if visible
+    // eslint-disable-next-line camelcase
     page_type?: PageTypes;
     // The ID of the room we're viewing. This is either populated directly
     // in the case where we view a room by ID or by RoomView when it resolves
@@ -180,8 +183,11 @@ interface IState {
     middleDisabled: boolean;
     // the right panel's disabled state is tracked in its store.
     // Parameters used in the registration dance with the IS
+    // eslint-disable-next-line camelcase
     register_client_secret?: string;
+    // eslint-disable-next-line camelcase
     register_session_id?: string;
+    // eslint-disable-next-line camelcase
     register_id_sid?: string;
     // When showing Modal dialogs we need to set aria-hidden on the root app element
     // and disable it when there are no dialogs
@@ -341,6 +347,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
     }
 
     // TODO: [REACT-WARNING] Replace with appropriate lifecycle stage
+    // eslint-disable-next-line camelcase
     UNSAFE_componentWillUpdate(props, state) {
         if (this.shouldTrackPageChange(this.state, state)) {
             this.startPageChangeTimer();
@@ -610,8 +617,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
                 const UserSettingsDialog = sdk.getComponent("dialogs.UserSettingsDialog");
                 Modal.createTrackedDialog('User settings', '', UserSettingsDialog,
                     {initialTabId: tabPayload.initialTabId},
-                    /*className=*/null, /*isPriority=*/false, /*isStatic=*/true
-                );
+                    /*className=*/null, /*isPriority=*/false, /*isStatic=*/true);
 
                 // View the welcome or home page if we need something to look at
                 this.viewSomethingBehindModal();
@@ -1080,7 +1086,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
             title: _t("Leave room"),
             description: (
                 <span>
-                { _t("Are you sure you want to leave the room '%(roomName)s'?", {roomName: roomToLeave.name}) }
+                    { _t("Are you sure you want to leave the room '%(roomName)s'?", {roomName: roomToLeave.name}) }
                     { warnings }
                 </span>
             ),
@@ -1433,7 +1439,6 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
         cli.on("crypto.warning", (type) => {
             switch (type) {
                 case 'CRYPTO_WARNING_OLD_VERSION_DETECTED':
-                    const brand = SdkConfig.get().brand;
                     Modal.createTrackedDialog('Crypto migrated', '', ErrorDialog, {
                         title: _t('Old cryptography data detected'),
                         description: _t(
@@ -1444,7 +1449,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
                             "in this version. This may also cause messages exchanged with this " +
                             "version to fail. If you experience problems, log out and back in " +
                             "again. To retain message history, export and re-import your keys.",
-                            { brand },
+                            { brand: SdkConfig.get().brand },
                         ),
                     });
                     break;
diff --git a/src/components/structures/RoomSearch.tsx b/src/components/structures/RoomSearch.tsx
index f6b8d42c30..768bc38d23 100644
--- a/src/components/structures/RoomSearch.tsx
+++ b/src/components/structures/RoomSearch.tsx
@@ -20,7 +20,6 @@ import classNames from "classnames";
 import defaultDispatcher from "../../dispatcher/dispatcher";
 import { _t } from "../../languageHandler";
 import { ActionPayload } from "../../dispatcher/payloads";
-import { throttle } from 'lodash';
 import { Key } from "../../Keyboard";
 import AccessibleButton from "../views/elements/AccessibleButton";
 import { Action } from "../../dispatcher/actions";
@@ -137,7 +136,7 @@ export default class RoomSearch extends React.PureComponent<IProps, IState> {
         });
 
         let icon = (
-            <div className='mx_RoomSearch_icon'/>
+            <div className='mx_RoomSearch_icon' />
         );
         let input = (
             <input
diff --git a/src/components/structures/TabbedView.tsx b/src/components/structures/TabbedView.tsx
index 704dbf8832..6bc35eb2a4 100644
--- a/src/components/structures/TabbedView.tsx
+++ b/src/components/structures/TabbedView.tsx
@@ -18,7 +18,6 @@ limitations under the License.
 
 import * as React from "react";
 import {_t} from '../../languageHandler';
-import * as PropTypes from "prop-types";
 import * as sdk from "../../index";
 import AutoHideScrollbar from './AutoHideScrollbar';
 import { ReactNode } from "react";
diff --git a/src/components/structures/UserMenu.tsx b/src/components/structures/UserMenu.tsx
index 30be71abcb..69b9c3f26e 100644
--- a/src/components/structures/UserMenu.tsx
+++ b/src/components/structures/UserMenu.tsx
@@ -40,7 +40,7 @@ import AccessibleTooltipButton from "../views/elements/AccessibleTooltipButton";
 import { SettingLevel } from "../../settings/SettingLevel";
 import IconizedContextMenu, {
     IconizedContextMenuOption,
-    IconizedContextMenuOptionList
+    IconizedContextMenuOptionList,
 } from "../views/context_menus/IconizedContextMenu";
 
 interface IProps {
@@ -234,12 +234,12 @@ export default class UserMenu extends React.Component<IProps, IState> {
         >
             <div className="mx_UserMenu_contextMenu_header">
                 <div className="mx_UserMenu_contextMenu_name">
-                        <span className="mx_UserMenu_contextMenu_displayName">
-                            {OwnProfileStore.instance.displayName}
-                        </span>
+                    <span className="mx_UserMenu_contextMenu_displayName">
+                        {OwnProfileStore.instance.displayName}
+                    </span>
                     <span className="mx_UserMenu_contextMenu_userId">
-                            {MatrixClientPeg.get().getUserId()}
-                        </span>
+                        {MatrixClientPeg.get().getUserId()}
+                    </span>
                 </div>
                 <AccessibleTooltipButton
                     className="mx_UserMenu_contextMenu_themeButton"
diff --git a/src/components/views/avatars/BaseAvatar.tsx b/src/components/views/avatars/BaseAvatar.tsx
index 7860857c55..245c50576a 100644
--- a/src/components/views/avatars/BaseAvatar.tsx
+++ b/src/components/views/avatars/BaseAvatar.tsx
@@ -17,7 +17,7 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-import React, {useCallback, useContext, useEffect, useMemo, useState} from 'react';
+import React, {useCallback, useContext, useEffect, useState} from 'react';
 import classNames from 'classnames';
 import * as AvatarLogic from '../../../Avatar';
 import SettingsStore from "../../../settings/SettingsStore";
@@ -96,7 +96,7 @@ const BaseAvatar = (props: IProps) => {
         urls,
         width = 40,
         height = 40,
-        resizeMethod = "crop", // eslint-disable-line no-unused-vars
+        resizeMethod = "crop", // eslint-disable-line @typescript-eslint/no-unused-vars
         defaultToInitialLetter = true,
         onClick,
         inputRef,
diff --git a/src/components/views/avatars/DecoratedRoomAvatar.tsx b/src/components/views/avatars/DecoratedRoomAvatar.tsx
index e6dadf676c..d7e012467b 100644
--- a/src/components/views/avatars/DecoratedRoomAvatar.tsx
+++ b/src/components/views/avatars/DecoratedRoomAvatar.tsx
@@ -126,7 +126,7 @@ export default class DecoratedRoomAvatar extends React.PureComponent<IProps, ISt
     private onPresenceUpdate = () => {
         if (this.isUnmounted) return;
 
-        let newIcon = this.getPresenceIcon();
+        const newIcon = this.getPresenceIcon();
         if (newIcon !== this.state.icon) this.setState({icon: newIcon});
     };
 
diff --git a/src/components/views/avatars/GroupAvatar.tsx b/src/components/views/avatars/GroupAvatar.tsx
index e55e2e6fac..51327605c0 100644
--- a/src/components/views/avatars/GroupAvatar.tsx
+++ b/src/components/views/avatars/GroupAvatar.tsx
@@ -47,7 +47,7 @@ export default class GroupAvatar extends React.Component<IProps> {
     render() {
         // extract the props we use from props so we can pass any others through
         // should consider adding this as a global rule in js-sdk?
-        /*eslint no-unused-vars: ["error", { "ignoreRestSiblings": true }]*/
+        /* eslint @typescript-eslint/no-unused-vars: ["error", { "ignoreRestSiblings": true }] */
         const {groupId, groupAvatarUrl, groupName, ...otherProps} = this.props;
 
         return (
diff --git a/src/components/views/avatars/PulsedAvatar.tsx b/src/components/views/avatars/PulsedAvatar.tsx
index 94a6c87687..b4e876b9f6 100644
--- a/src/components/views/avatars/PulsedAvatar.tsx
+++ b/src/components/views/avatars/PulsedAvatar.tsx
@@ -25,4 +25,4 @@ const PulsedAvatar: React.FC<IProps> = (props) => {
     </div>;
 };
 
-export default PulsedAvatar;
\ No newline at end of file
+export default PulsedAvatar;
diff --git a/src/components/views/dialogs/CommunityPrototypeInviteDialog.tsx b/src/components/views/dialogs/CommunityPrototypeInviteDialog.tsx
index 7a500cd053..4a454c8cbb 100644
--- a/src/components/views/dialogs/CommunityPrototypeInviteDialog.tsx
+++ b/src/components/views/dialogs/CommunityPrototypeInviteDialog.tsx
@@ -21,9 +21,6 @@ import { IDialogProps } from "./IDialogProps";
 import Field from "../elements/Field";
 import AccessibleButton from "../elements/AccessibleButton";
 import { MatrixClientPeg } from "../../../MatrixClientPeg";
-import InfoTooltip from "../elements/InfoTooltip";
-import dis from "../../../dispatcher/dispatcher";
-import {showCommunityRoomInviteDialog} from "../../../RoomInvite";
 import { arrayFastClone } from "../../../utils/arrays";
 import SdkConfig from "../../../SdkConfig";
 import { RoomMember } from "matrix-js-sdk/src/models/room-member";
@@ -31,7 +28,6 @@ import InviteDialog from "./InviteDialog";
 import BaseAvatar from "../avatars/BaseAvatar";
 import {getHttpUriForMxc} from "matrix-js-sdk/src/content-repo";
 import {inviteMultipleToRoom, showAnyInviteErrors} from "../../../RoomInvite";
-import {humanizeTime} from "../../../utils/humanize";
 import StyledCheckbox from "../elements/StyledCheckbox";
 import Modal from "../../../Modal";
 import ErrorDialog from "./ErrorDialog";
@@ -171,44 +167,38 @@ export default class CommunityPrototypeInviteDialog extends React.PureComponent<
     public render() {
         const emailAddresses = [];
         this.state.emailTargets.forEach((address, i) => {
-            emailAddresses.push(
-                <Field
-                    key={i}
-                    value={address}
-                    onChange={(e) => this.onAddressChange(e, i)}
-                    label={_t("Email address")}
-                    placeholder={_t("Email address")}
-                    onBlur={() => this.onAddressBlur(i)}
-                />
-            );
+            emailAddresses.push(<Field
+                key={i}
+                value={address}
+                onChange={(e) => this.onAddressChange(e, i)}
+                label={_t("Email address")}
+                placeholder={_t("Email address")}
+                onBlur={() => this.onAddressBlur(i)}
+            />);
         });
 
         // Push a clean input
-        emailAddresses.push(
-            <Field
-                key={emailAddresses.length}
-                value={""}
-                onChange={(e) => this.onAddressChange(e, emailAddresses.length)}
-                label={emailAddresses.length > 0 ? _t("Add another email") : _t("Email address")}
-                placeholder={emailAddresses.length > 0 ? _t("Add another email") : _t("Email address")}
-            />
-        );
+        emailAddresses.push(<Field
+            key={emailAddresses.length}
+            value={""}
+            onChange={(e) => this.onAddressChange(e, emailAddresses.length)}
+            label={emailAddresses.length > 0 ? _t("Add another email") : _t("Email address")}
+            placeholder={emailAddresses.length > 0 ? _t("Add another email") : _t("Email address")}
+        />);
 
         let peopleIntro = null;
-        let people = [];
+        const people = [];
         if (this.state.showPeople) {
             const humansToPresent = this.state.people.slice(0, this.state.numPeople);
             humansToPresent.forEach((person, i) => {
                 people.push(this.renderPerson(person, i));
             });
             if (humansToPresent.length < this.state.people.length) {
-                people.push(
-                    <AccessibleButton
-                        onClick={this.onShowMorePeople}
-                        kind="link" key="more"
-                        className="mx_CommunityPrototypeInviteDialog_morePeople"
-                    >{_t("Show more")}</AccessibleButton>
-                );
+                people.push(<AccessibleButton
+                    onClick={this.onShowMorePeople}
+                    kind="link" key="more"
+                    className="mx_CommunityPrototypeInviteDialog_morePeople"
+                >{_t("Show more")}</AccessibleButton>);
             }
         }
         if (this.state.people.length > 0) {
diff --git a/src/components/views/dialogs/CreateCommunityPrototypeDialog.tsx b/src/components/views/dialogs/CreateCommunityPrototypeDialog.tsx
index 58412c23d6..dbfc208583 100644
--- a/src/components/views/dialogs/CreateCommunityPrototypeDialog.tsx
+++ b/src/components/views/dialogs/CreateCommunityPrototypeDialog.tsx
@@ -164,7 +164,10 @@ export default class CreateCommunityPrototypeDialog extends React.PureComponent<
         );
         if (this.state.error) {
             helpText = (
-                <span className="mx_CreateCommunityPrototypeDialog_subtext mx_CreateCommunityPrototypeDialog_subtext_error">
+                <span
+                    className={"mx_CreateCommunityPrototypeDialog_subtext " +
+                    "mx_CreateCommunityPrototypeDialog_subtext_error"}
+                >
                     {this.state.error}
                 </span>
             );
@@ -205,7 +208,10 @@ export default class CreateCommunityPrototypeDialog extends React.PureComponent<
                                 ref={this.avatarUploadRef} accept="image/*"
                                 onChange={this.onAvatarChanged}
                             />
-                            <AccessibleButton onClick={this.onChangeAvatar} className="mx_CreateCommunityPrototypeDialog_avatarContainer">
+                            <AccessibleButton
+                                onClick={this.onChangeAvatar}
+                                className="mx_CreateCommunityPrototypeDialog_avatarContainer"
+                            >
                                 {preview}
                             </AccessibleButton>
                             <div className="mx_CreateCommunityPrototypeDialog_tip">
diff --git a/src/components/views/dialogs/ShareDialog.tsx b/src/components/views/dialogs/ShareDialog.tsx
index 22f83d391c..e849f7efe3 100644
--- a/src/components/views/dialogs/ShareDialog.tsx
+++ b/src/components/views/dialogs/ShareDialog.tsx
@@ -186,8 +186,8 @@ export default class ShareDialog extends React.PureComponent<IProps, IState> {
             title = _t('Share Room Message');
             checkbox = <div>
                 <StyledCheckbox
-                       checked={this.state.linkSpecificEvent}
-                       onClick={this.onLinkSpecificEventCheckboxClick}
+                    checked={this.state.linkSpecificEvent}
+                    onClick={this.onLinkSpecificEventCheckboxClick}
                 >
                     { _t('Link to selected message') }
                 </StyledCheckbox>
@@ -198,16 +198,18 @@ export default class ShareDialog extends React.PureComponent<IProps, IState> {
         const encodedUrl = encodeURIComponent(matrixToUrl);
 
         const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
-        return <BaseDialog title={title}
-                           className='mx_ShareDialog'
-                           contentId='mx_Dialog_content'
-                           onFinished={this.props.onFinished}
+        return <BaseDialog
+            title={title}
+            className='mx_ShareDialog'
+            contentId='mx_Dialog_content'
+            onFinished={this.props.onFinished}
         >
             <div className="mx_ShareDialog_content">
                 <div className="mx_ShareDialog_matrixto">
-                    <a href={matrixToUrl}
-                       onClick={ShareDialog.onLinkClick}
-                       className="mx_ShareDialog_matrixto_link"
+                    <a
+                        href={matrixToUrl}
+                        onClick={ShareDialog.onLinkClick}
+                        className="mx_ShareDialog_matrixto_link"
                     >
                         { matrixToUrl }
                     </a>
diff --git a/src/components/views/elements/Draggable.tsx b/src/components/views/elements/Draggable.tsx
index 3397fd901c..a6eb8323f3 100644
--- a/src/components/views/elements/Draggable.tsx
+++ b/src/components/views/elements/Draggable.tsx
@@ -34,7 +34,6 @@ export interface ILocationState {
 }
 
 export default class Draggable extends React.Component<IProps, IState> {
-
     constructor(props: IProps) {
         super(props);
 
@@ -77,5 +76,4 @@ export default class Draggable extends React.Component<IProps, IState> {
     render() {
         return <div className={this.props.className} onMouseDown={this.onMouseDown.bind(this)} />;
     }
-
-}
\ No newline at end of file
+}
diff --git a/src/components/views/elements/EventTilePreview.tsx b/src/components/views/elements/EventTilePreview.tsx
index 7d8b774955..98f6850e6b 100644
--- a/src/components/views/elements/EventTilePreview.tsx
+++ b/src/components/views/elements/EventTilePreview.tsx
@@ -39,6 +39,7 @@ interface IProps {
     className: string;
 }
 
+/* eslint-disable camelcase */
 interface IState {
     userId: string;
     displayname: string;
@@ -72,7 +73,6 @@ export default class EventTilePreview extends React.Component<IProps, IState> {
             displayname: profileInfo.displayname,
             avatar_url,
         });
-
     }
 
     private fakeEvent({userId, displayname, avatar_url}: IState) {
@@ -114,16 +114,14 @@ export default class EventTilePreview extends React.Component<IProps, IState> {
     public render() {
         const event = this.fakeEvent(this.state);
 
-        let className = classnames(
-            this.props.className,
-            {
-                "mx_IRCLayout": this.props.useIRCLayout,
-                "mx_GroupLayout": !this.props.useIRCLayout,
-            }
-        );
+        const className = classnames(this.props.className, {
+            "mx_IRCLayout": this.props.useIRCLayout,
+            "mx_GroupLayout": !this.props.useIRCLayout,
+        });
 
         return <div className={className}>
             <EventTile mxEvent={event} useIRCLayout={this.props.useIRCLayout} />
         </div>;
     }
 }
+/* eslint-enable camelcase */
diff --git a/src/components/views/elements/Field.tsx b/src/components/views/elements/Field.tsx
index d9fd59dc11..d2869f68c8 100644
--- a/src/components/views/elements/Field.tsx
+++ b/src/components/views/elements/Field.tsx
@@ -198,11 +198,9 @@ export default class Field extends React.PureComponent<PropShapes, IState> {
         }
     }
 
-
-
     public render() {
-        const {
-            element, prefixComponent, postfixComponent, className, onValidate, children,
+        /* eslint @typescript-eslint/no-unused-vars: ["error", { "ignoreRestSiblings": true }] */
+        const { element, prefixComponent, postfixComponent, className, onValidate, children,
             tooltipContent, forceValidity, tooltipClassName, list, ...inputProps} = this.props;
 
         // Set some defaults for the <input> element
diff --git a/src/components/views/elements/IRCTimelineProfileResizer.tsx b/src/components/views/elements/IRCTimelineProfileResizer.tsx
index 1098d0293e..ecd63816de 100644
--- a/src/components/views/elements/IRCTimelineProfileResizer.tsx
+++ b/src/components/views/elements/IRCTimelineProfileResizer.tsx
@@ -78,7 +78,12 @@ export default class IRCTimelineProfileResizer extends React.Component<IProps, I
 
     private onMoueUp(event: MouseEvent) {
         if (this.props.roomId) {
-            SettingsStore.setValue("ircDisplayNameWidth", this.props.roomId, SettingLevel.ROOM_DEVICE, this.state.width);
+            SettingsStore.setValue(
+                "ircDisplayNameWidth",
+                this.props.roomId,
+                SettingLevel.ROOM_DEVICE,
+                this.state.width,
+            );
         }
     }
 
diff --git a/src/components/views/elements/InfoTooltip.tsx b/src/components/views/elements/InfoTooltip.tsx
index 645951aab9..dd21c95b74 100644
--- a/src/components/views/elements/InfoTooltip.tsx
+++ b/src/components/views/elements/InfoTooltip.tsx
@@ -18,7 +18,6 @@ limitations under the License.
 import React from 'react';
 import classNames from 'classnames';
 
-import AccessibleButton from "./AccessibleButton";
 import Tooltip from './Tooltip';
 import { _t } from "../../../languageHandler";
 
diff --git a/src/components/views/elements/QRCode.tsx b/src/components/views/elements/QRCode.tsx
index f70ab48fa3..9ce3dc7202 100644
--- a/src/components/views/elements/QRCode.tsx
+++ b/src/components/views/elements/QRCode.tsx
@@ -41,7 +41,7 @@ const QRCode: React.FC<IProps> = ({data, className, ...options}) => {
         return () => {
             cancelled = true;
         };
-    }, [JSON.stringify(data), options]);
+    }, [JSON.stringify(data), options]); // eslint-disable-line react-hooks/exhaustive-deps
 
     return <div className={classNames("mx_QRCode", className)}>
         { dataUri ? <img src={dataUri} className="mx_VerificationQRCode" alt={_t("QR Code")} /> : <Spinner /> }
diff --git a/src/components/views/elements/Slider.tsx b/src/components/views/elements/Slider.tsx
index a88c581d07..b7c8e1b533 100644
--- a/src/components/views/elements/Slider.tsx
+++ b/src/components/views/elements/Slider.tsx
@@ -45,7 +45,7 @@ export default class Slider extends React.Component<IProps> {
     // non linear slider.
     private offset(values: number[], value: number): number {
         // the index of the first number greater than value.
-        let closest = values.reduce((prev, curr) => {
+        const closest = values.reduce((prev, curr) => {
             return (value > curr ? prev + 1 : prev);
         }, 0);
 
@@ -68,17 +68,16 @@ export default class Slider extends React.Component<IProps> {
         const linearInterpolation = (value - closestLessValue) / (closestGreaterValue - closestLessValue);
 
         return 100 * (closest - 1 + linearInterpolation) * intervalWidth;
-
     }
 
     render(): React.ReactNode {
-        const dots = this.props.values.map(v =>
-            <Dot active={v <= this.props.value}
-                 label={this.props.displayFunc(v)}
-                 onClick={this.props.disabled ? () => {} : () => this.props.onSelectionChange(v)}
-                 key={v}
-                 disabled={this.props.disabled}
-            />);
+        const dots = this.props.values.map(v => <Dot
+            active={v <= this.props.value}
+            label={this.props.displayFunc(v)}
+            onClick={this.props.disabled ? () => {} : () => this.props.onSelectionChange(v)}
+            key={v}
+            disabled={this.props.disabled}
+        />);
 
         let selection = null;
 
@@ -93,7 +92,7 @@ export default class Slider extends React.Component<IProps> {
         return <div className="mx_Slider">
             <div>
                 <div className="mx_Slider_bar">
-                    <hr onClick={this.props.disabled ? () => {} : this.onClick.bind(this)}/>
+                    <hr onClick={this.props.disabled ? () => {} : this.onClick.bind(this)} />
                     { selection }
                 </div>
                 <div className="mx_Slider_dotContainer">
diff --git a/src/components/views/elements/StyledCheckbox.tsx b/src/components/views/elements/StyledCheckbox.tsx
index be983828ff..f8d2665d07 100644
--- a/src/components/views/elements/StyledCheckbox.tsx
+++ b/src/components/views/elements/StyledCheckbox.tsx
@@ -17,8 +17,6 @@ limitations under the License.
 import React from "react";
 import { randomString } from "matrix-js-sdk/src/randomstring";
 
-const CHECK_BOX_SVG = require("../../../../res/img/feather-customised/check.svg");
-
 interface IProps extends React.InputHTMLAttributes<HTMLInputElement> {
 }
 
@@ -39,13 +37,14 @@ export default class StyledCheckbox extends React.PureComponent<IProps, IState>
     }
 
     public render() {
+        /* eslint @typescript-eslint/no-unused-vars: ["error", { "ignoreRestSiblings": true }] */
         const { children, className, ...otherProps } = this.props;
         return <span className={"mx_Checkbox " + className}>
             <input id={this.id} {...otherProps} type="checkbox" />
             <label htmlFor={this.id}>
                 {/* Using the div to center the image */}
                 <div className="mx_Checkbox_background">
-                    <img src={CHECK_BOX_SVG}/>
+                    <img src={require("../../../../res/img/feather-customised/check.svg")} />
                 </div>
                 <div>
                     { this.props.children }
@@ -53,4 +52,4 @@ export default class StyledCheckbox extends React.PureComponent<IProps, IState>
             </label>
         </span>;
     }
-}
\ No newline at end of file
+}
diff --git a/src/components/views/right_panel/EncryptionInfo.tsx b/src/components/views/right_panel/EncryptionInfo.tsx
index f62af65543..10d35200bd 100644
--- a/src/components/views/right_panel/EncryptionInfo.tsx
+++ b/src/components/views/right_panel/EncryptionInfo.tsx
@@ -76,14 +76,16 @@ const EncryptionInfo: React.FC<IProps> = ({
         description = (
             <div>
                 <p>{_t("Messages in this room are end-to-end encrypted.")}</p>
-                <p>{_t("Your messages are secured and only you and the recipient have the unique keys to unlock them.")}</p>
+                <p>{_t("Your messages are secured and only you and the recipient have " +
+                    "the unique keys to unlock them.")}</p>
             </div>
         );
     } else {
         description = (
             <div>
                 <p>{_t("Messages in this room are not end-to-end encrypted.")}</p>
-                <p>{_t("In encrypted rooms, your messages are secured and only you and the recipient have the unique keys to unlock them.")}</p>
+                <p>{_t("In encrypted rooms, your messages are secured and only you and the recipient have " +
+                    "the unique keys to unlock them.")}</p>
             </div>
         );
     }
diff --git a/src/components/views/right_panel/HeaderButtons.tsx b/src/components/views/right_panel/HeaderButtons.tsx
index 57d3075739..bbb783ccb9 100644
--- a/src/components/views/right_panel/HeaderButtons.tsx
+++ b/src/components/views/right_panel/HeaderButtons.tsx
@@ -23,7 +23,10 @@ import dis from '../../../dispatcher/dispatcher';
 import RightPanelStore from "../../../stores/RightPanelStore";
 import {RightPanelPhases} from "../../../stores/RightPanelStorePhases";
 import {Action} from '../../../dispatcher/actions';
-import {SetRightPanelPhasePayload, SetRightPanelPhaseRefireParams} from '../../../dispatcher/payloads/SetRightPanelPhasePayload';
+import {
+    SetRightPanelPhasePayload,
+    SetRightPanelPhaseRefireParams,
+} from '../../../dispatcher/payloads/SetRightPanelPhasePayload';
 import {EventSubscription} from "fbemitter";
 
 export enum HeaderKind {
@@ -38,7 +41,7 @@ interface IState {
 
 interface IProps {}
 
-export default class HeaderButtons extends React.Component<IProps, IState> {
+export default abstract class HeaderButtons extends React.Component<IProps, IState> {
     private storeToken: EventSubscription;
     private dispatcherRef: string;
 
@@ -92,14 +95,7 @@ export default class HeaderButtons extends React.Component<IProps, IState> {
     }
 
     // XXX: Make renderButtons a prop
-    public renderButtons(): JSX.Element[] {
-        // Ignore - intended to be overridden by subclasses
-        // Return empty fragment to satisfy the type
-        return [
-          <React.Fragment>
-          </React.Fragment>
-        ];
-    }
+    public abstract renderButtons(): JSX.Element[];
 
     public render() {
         // inline style as this will be swapped around in future commits
diff --git a/src/components/views/right_panel/VerificationPanel.tsx b/src/components/views/right_panel/VerificationPanel.tsx
index 1f0703839f..f584a63209 100644
--- a/src/components/views/right_panel/VerificationPanel.tsx
+++ b/src/components/views/right_panel/VerificationPanel.tsx
@@ -30,8 +30,6 @@ import {_t} from "../../../languageHandler";
 import SdkConfig from "../../../SdkConfig";
 import E2EIcon from "../rooms/E2EIcon";
 import {
-    PHASE_UNSENT,
-    PHASE_REQUESTED,
     PHASE_READY,
     PHASE_DONE,
     PHASE_STARTED,
@@ -104,14 +102,15 @@ export default class VerificationPanel extends React.PureComponent<IProps, IStat
                     </div>;
             }
             if (showSAS) {
-                sasBlockDialog =
-                    <div className='mx_VerificationPanel_QRPhase_startOption'>
-                        <p>{_t("Compare unique emoji")}</p>
-                        <span className='mx_VerificationPanel_QRPhase_helpText'>{_t("Compare a unique set of emoji if you don't have a camera on either device")}</span>
-                        <AccessibleButton disabled={this.state.emojiButtonClicked} onClick={this.startSAS} kind='primary'>
-                            {_t("Start")}
-                        </AccessibleButton>
-                    </div>;
+                sasBlockDialog = <div className='mx_VerificationPanel_QRPhase_startOption'>
+                    <p>{_t("Compare unique emoji")}</p>
+                    <span className='mx_VerificationPanel_QRPhase_helpText'>
+                        {_t("Compare a unique set of emoji if you don't have a camera on either device")}
+                    </span>
+                    <AccessibleButton disabled={this.state.emojiButtonClicked} onClick={this.startSAS} kind='primary'>
+                        {_t("Start")}
+                    </AccessibleButton>
+                </div>;
             }
             const or = qrBlockDialog && sasBlockDialog ?
                 <div className='mx_VerificationPanel_QRPhase_betweenText'>{_t("or")}</div> : null;
@@ -165,8 +164,8 @@ export default class VerificationPanel extends React.PureComponent<IProps, IStat
         }
 
         const noCommonMethodBlock = noCommonMethodError ?
-             <div className="mx_UserInfo_container">{noCommonMethodError}</div> :
-             null;
+            <div className="mx_UserInfo_container">{noCommonMethodError}</div> :
+            null;
 
         // TODO: add way to open camera to scan a QR code
         return <React.Fragment>
diff --git a/src/components/views/rooms/NotificationBadge.tsx b/src/components/views/rooms/NotificationBadge.tsx
index 8253940d4e..2957b25779 100644
--- a/src/components/views/rooms/NotificationBadge.tsx
+++ b/src/components/views/rooms/NotificationBadge.tsx
@@ -92,6 +92,7 @@ export default class NotificationBadge extends React.PureComponent<XOR<IProps, I
     };
 
     public render(): React.ReactElement {
+        /* eslint @typescript-eslint/no-unused-vars: ["error", { "ignoreRestSiblings": true }] */
         const {notification, forceCount, roomId, onClick, ...props} = this.props;
 
         // Don't show a badge if we don't need to
diff --git a/src/components/views/rooms/RoomList.tsx b/src/components/views/rooms/RoomList.tsx
index 92c5982276..ec8c8d6840 100644
--- a/src/components/views/rooms/RoomList.tsx
+++ b/src/components/views/rooms/RoomList.tsx
@@ -218,7 +218,7 @@ export default class RoomList extends React.PureComponent<IProps, IState> {
 
     private getRoomDelta = (roomId: string, delta: number, unread = false) => {
         const lists = RoomListStore.instance.orderedLists;
-        let rooms: Room = [];
+        const rooms: Room = [];
         TAG_ORDER.forEach(t => {
             let listRooms = lists[t];
 
@@ -290,7 +290,7 @@ export default class RoomList extends React.PureComponent<IProps, IState> {
         // TODO: Put community invites in a more sensible place (not in the room list)
         // See https://github.com/vector-im/element-web/issues/14456
         return MatrixClientPeg.get().getGroups().filter(g => {
-           return g.myMembership === 'invite';
+            return g.myMembership === 'invite';
         }).map(g => {
             const avatar = (
                 <GroupAvatar
@@ -346,21 +346,19 @@ export default class RoomList extends React.PureComponent<IProps, IState> {
                 : TAG_AESTHETICS[orderedTagId];
             if (!aesthetics) throw new Error(`Tag ${orderedTagId} does not have aesthetics`);
 
-            components.push(
-                <RoomSublist
-                    key={`sublist-${orderedTagId}`}
-                    tagId={orderedTagId}
-                    forRooms={true}
-                    startAsHidden={aesthetics.defaultHidden}
-                    label={aesthetics.sectionLabelRaw ? aesthetics.sectionLabelRaw : _t(aesthetics.sectionLabel)}
-                    onAddRoom={aesthetics.onAddRoom}
-                    addRoomLabel={aesthetics.addRoomLabel ? _t(aesthetics.addRoomLabel) : aesthetics.addRoomLabel}
-                    addRoomContextMenu={aesthetics.addRoomContextMenu}
-                    isMinimized={this.props.isMinimized}
-                    onResize={this.props.onResize}
-                    extraBadTilesThatShouldntExist={extraTiles}
-                />
-            );
+            components.push(<RoomSublist
+                key={`sublist-${orderedTagId}`}
+                tagId={orderedTagId}
+                forRooms={true}
+                startAsHidden={aesthetics.defaultHidden}
+                label={aesthetics.sectionLabelRaw ? aesthetics.sectionLabelRaw : _t(aesthetics.sectionLabel)}
+                onAddRoom={aesthetics.onAddRoom}
+                addRoomLabel={aesthetics.addRoomLabel ? _t(aesthetics.addRoomLabel) : aesthetics.addRoomLabel}
+                addRoomContextMenu={aesthetics.addRoomContextMenu}
+                isMinimized={this.props.isMinimized}
+                onResize={this.props.onResize}
+                extraBadTilesThatShouldntExist={extraTiles}
+            />);
         }
 
         return components;
diff --git a/src/components/views/rooms/RoomSublist.tsx b/src/components/views/rooms/RoomSublist.tsx
index 1e7ba3f77a..4056f2fbd4 100644
--- a/src/components/views/rooms/RoomSublist.tsx
+++ b/src/components/views/rooms/RoomSublist.tsx
@@ -517,15 +517,13 @@ export default class RoomSublist extends React.Component<IProps, IState> {
         if (this.state.rooms) {
             const visibleRooms = this.state.rooms.slice(0, this.numVisibleTiles);
             for (const room of visibleRooms) {
-                tiles.push(
-                    <RoomTile
-                        room={room}
-                        key={`room-${room.roomId}`}
-                        showMessagePreview={this.layout.showPreviews}
-                        isMinimized={this.props.isMinimized}
-                        tag={this.props.tagId}
-                    />
-                );
+                tiles.push(<RoomTile
+                    room={room}
+                    key={`room-${room.roomId}`}
+                    showMessagePreview={this.layout.showPreviews}
+                    isMinimized={this.props.isMinimized}
+                    tag={this.props.tagId}
+                />);
             }
         }
 
@@ -710,7 +708,12 @@ export default class RoomSublist extends React.Component<IProps, IState> {
                     // doesn't become sticky.
                     // The same applies to the notification badge.
                     return (
-                        <div className={classes} onKeyDown={this.onHeaderKeyDown} onFocus={onFocus} aria-label={this.props.label}>
+                        <div
+                            className={classes}
+                            onKeyDown={this.onHeaderKeyDown}
+                            onFocus={onFocus}
+                            aria-label={this.props.label}
+                        >
                             <div className="mx_RoomSublist_stickable">
                                 <Button
                                     onFocus={onFocus}
@@ -762,7 +765,7 @@ export default class RoomSublist extends React.Component<IProps, IState> {
             const showMoreAtMinHeight = minTiles < this.numTiles;
             const minHeightPadding = RESIZE_HANDLE_HEIGHT + (showMoreAtMinHeight ? SHOW_N_BUTTON_HEIGHT : 0);
             const minTilesPx = layout.tilesToPixelsWithPadding(minTiles, minHeightPadding);
-            let maxTilesPx = layout.tilesToPixelsWithPadding(this.numTiles, this.padding);
+            const maxTilesPx = layout.tilesToPixelsWithPadding(this.numTiles, this.padding);
             const showMoreBtnClasses = classNames({
                 'mx_RoomSublist_showNButton': true,
             });
diff --git a/src/components/views/rooms/RoomTile.tsx b/src/components/views/rooms/RoomTile.tsx
index a09853d762..a241a13991 100644
--- a/src/components/views/rooms/RoomTile.tsx
+++ b/src/components/views/rooms/RoomTile.tsx
@@ -31,7 +31,7 @@ import { ChevronFace, ContextMenuTooltipButton } from "../../structures/ContextM
 import { DefaultTagID, TagID } from "../../../stores/room-list/models";
 import { MessagePreviewStore, ROOM_PREVIEW_CHANGED } from "../../../stores/room-list/MessagePreviewStore";
 import DecoratedRoomAvatar from "../avatars/DecoratedRoomAvatar";
-import { ALL_MESSAGES, ALL_MESSAGES_LOUD, MENTIONS_ONLY, MUTE, } from "../../../RoomNotifs";
+import { ALL_MESSAGES, ALL_MESSAGES_LOUD, MENTIONS_ONLY, MUTE } from "../../../RoomNotifs";
 import { MatrixClientPeg } from "../../../MatrixClientPeg";
 import NotificationBadge from "./NotificationBadge";
 import { Volume } from "../../../RoomNotifsTypes";
@@ -48,7 +48,7 @@ import IconizedContextMenu, {
     IconizedContextMenuCheckbox,
     IconizedContextMenuOption,
     IconizedContextMenuOptionList,
-    IconizedContextMenuRadio
+    IconizedContextMenuRadio,
 } from "../context_menus/IconizedContextMenu";
 import { CommunityPrototypeStore, IRoomProfile } from "../../../stores/CommunityPrototypeStore";
 import { UPDATE_EVENT } from "../../../stores/AsyncStore";
@@ -249,7 +249,7 @@ export default class RoomTile extends React.PureComponent<IProps, IState> {
                 removeTag,
                 addTag,
                 undefined,
-                0
+                0,
             ));
         } else {
             console.warn(`Unexpected tag ${tagId} applied to ${this.props.room.room_id}`);
diff --git a/src/components/views/rooms/TemporaryTile.tsx b/src/components/views/rooms/TemporaryTile.tsx
index a61ff6e1da..eec3105880 100644
--- a/src/components/views/rooms/TemporaryTile.tsx
+++ b/src/components/views/rooms/TemporaryTile.tsx
@@ -19,9 +19,7 @@ import classNames from "classnames";
 import {
     RovingAccessibleButton,
     RovingAccessibleTooltipButton,
-    RovingTabIndexWrapper
 } from "../../../accessibility/RovingTabIndex";
-import AccessibleButton from "../../views/elements/AccessibleButton";
 import NotificationBadge from "./NotificationBadge";
 import { NotificationState } from "../../../stores/notifications/NotificationState";
 
diff --git a/src/components/views/settings/UpdateCheckButton.tsx b/src/components/views/settings/UpdateCheckButton.tsx
index 10e0e29f31..eb1b762423 100644
--- a/src/components/views/settings/UpdateCheckButton.tsx
+++ b/src/components/views/settings/UpdateCheckButton.tsx
@@ -42,7 +42,7 @@ function getStatusText(status: UpdateCheckStatus, errorDetail?: string) {
             return _t('Downloading update...');
         case UpdateCheckStatus.Ready:
             return _t("New version available. <a>Update now.</a>", {}, {
-                a: sub => <AccessibleButton kind="link" onClick={installUpdate}>{sub}</AccessibleButton>
+                a: sub => <AccessibleButton kind="link" onClick={installUpdate}>{sub}</AccessibleButton>,
             });
     }
 }
diff --git a/src/components/views/settings/tabs/user/AppearanceUserSettingsTab.tsx b/src/components/views/settings/tabs/user/AppearanceUserSettingsTab.tsx
index c9ec4a6bc7..b4c05a2ecb 100644
--- a/src/components/views/settings/tabs/user/AppearanceUserSettingsTab.tsx
+++ b/src/components/views/settings/tabs/user/AppearanceUserSettingsTab.tsx
@@ -170,7 +170,7 @@ export default class AppearanceUserSettingsTab extends React.Component<IProps, I
             "baseFontSize",
             null,
             SettingLevel.DEVICE,
-            parseInt(value, 10) - FontWatcher.SIZE_DIFF
+            parseInt(value, 10) - FontWatcher.SIZE_DIFF,
         );
 
         return {valid: true, feedback: _t('Use between %(min)s pt and %(max)s pt', {min, max})};
@@ -294,7 +294,7 @@ export default class AppearanceUserSettingsTab extends React.Component<IProps, I
                     />
                 </div>
                 {customThemeForm}
-           </div>
+            </div>
         );
     }
 
diff --git a/src/components/views/toasts/GenericExpiringToast.tsx b/src/components/views/toasts/GenericExpiringToast.tsx
index 83f43208c4..e63edd8e79 100644
--- a/src/components/views/toasts/GenericExpiringToast.tsx
+++ b/src/components/views/toasts/GenericExpiringToast.tsx
@@ -29,7 +29,15 @@ interface IProps extends IGenericToastProps {
 
 const SECOND = 1000;
 
-const GenericExpiringToast: React.FC<IProps> = ({description, acceptLabel, dismissLabel, onAccept, onDismiss, toastKey, numSeconds}) => {
+const GenericExpiringToast: React.FC<IProps> = ({
+    description,
+    acceptLabel,
+    dismissLabel,
+    onAccept,
+    onDismiss,
+    toastKey,
+    numSeconds,
+}) => {
     const onReject = () => {
         if (onDismiss) onDismiss();
         ToastStore.sharedInstance().dismissToast(toastKey);
diff --git a/src/components/views/toasts/GenericToast.tsx b/src/components/views/toasts/GenericToast.tsx
index 6cd881b9eb..a9c64f1962 100644
--- a/src/components/views/toasts/GenericToast.tsx
+++ b/src/components/views/toasts/GenericToast.tsx
@@ -31,7 +31,13 @@ interface IPropsExtended extends IProps {
     onReject();
 }
 
-const GenericToast: React.FC<XOR<IPropsExtended, IProps>> = ({description, acceptLabel, rejectLabel, onAccept, onReject}) => {
+const GenericToast: React.FC<XOR<IPropsExtended, IProps>> = ({
+    description,
+    acceptLabel,
+    rejectLabel,
+    onAccept,
+    onReject,
+}) => {
     return <div>
         <div className="mx_Toast_description">
             { description }
diff --git a/src/components/views/voip/CallView.tsx b/src/components/views/voip/CallView.tsx
index 8416f56fd9..1d3a62984a 100644
--- a/src/components/views/voip/CallView.tsx
+++ b/src/components/views/voip/CallView.tsx
@@ -97,10 +97,7 @@ export default class CallView extends React.Component<IProps, IState> {
         if (this.props.room) {
             const roomId = this.props.room.roomId;
             call = CallHandler.getCallForRoom(roomId) ||
-                (this.props.ConferenceHandler ?
-                 this.props.ConferenceHandler.getConferenceCallForRoom(roomId) :
-                 null
-                );
+                (this.props.ConferenceHandler ? this.props.ConferenceHandler.getConferenceCallForRoom(roomId) : null);
 
             if (this.call) {
                 this.setState({ call: call });
diff --git a/src/components/views/voip/IncomingCallBox.tsx b/src/components/views/voip/IncomingCallBox.tsx
index 00d49b20f5..b7cba7a70f 100644
--- a/src/components/views/voip/IncomingCallBox.tsx
+++ b/src/components/views/voip/IncomingCallBox.tsx
@@ -51,7 +51,7 @@ export default class IncomingCallBox extends React.Component<IProps, IState> {
 
     private onAction = (payload: ActionPayload) => {
         switch (payload.action) {
-            case 'call_state':
+            case 'call_state': {
                 const call = CallHandler.getCall(payload.room_id);
                 if (call && call.call_state === 'ringing') {
                     this.setState({
@@ -62,6 +62,7 @@ export default class IncomingCallBox extends React.Component<IProps, IState> {
                         incomingCall: null,
                     });
                 }
+            }
         }
     };
 
diff --git a/src/languageHandler.tsx b/src/languageHandler.tsx
index 59edc8766c..d9feec95b1 100644
--- a/src/languageHandler.tsx
+++ b/src/languageHandler.tsx
@@ -442,7 +442,7 @@ export function pickBestLanguage(langs: string[]): string {
 }
 
 function getLangsJson(): Promise<object> {
-    return new Promise(async (resolve, reject) => {
+    return new Promise((resolve, reject) => {
         let url;
         if (typeof(webpackLangJsonUrl) === 'string') { // in Jest this 'url' isn't a URL, so just fall through
             url = webpackLangJsonUrl;
@@ -453,7 +453,7 @@ function getLangsJson(): Promise<object> {
             { method: "GET", url },
             (err, response, body) => {
                 if (err || response.status < 200 || response.status >= 300) {
-                    reject({err: err, response: response});
+                    reject(err);
                     return;
                 }
                 resolve(JSON.parse(body));
@@ -488,7 +488,7 @@ function getLanguage(langPath: string): object {
             { method: "GET", url: langPath },
             (err, response, body) => {
                 if (err || response.status < 200 || response.status >= 300) {
-                    reject({err: err, response: response});
+                    reject(err);
                     return;
                 }
                 resolve(weblateToCounterpart(JSON.parse(body)));