diff --git a/.eslintrc.js b/.eslintrc.js index c759eae9e3..bf6e245b93 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,7 +1,9 @@ module.exports = { - extends: ["matrix-org", "matrix-org/react-legacy"], - parser: "babel-eslint", - + plugins: ["matrix-org"], + extends: [ + "plugin:matrix-org/babel", + "plugin:matrix-org/react", + ], env: { browser: true, node: true, @@ -15,12 +17,32 @@ module.exports = { "prefer-promise-reject-errors": "off", "no-async-promise-executor": "off", "quotes": "off", - }, + "no-extra-boolean-cast": "off", + // Bind or arrow functions in props causes performance issues (but we + // currently use them in some places). + // It's disabled here, but we should using it sparingly. + "react/jsx-no-bind": "off", + "react/jsx-key": ["error"], + }, overrides: [{ - "files": ["src/**/*.{ts,tsx}", "test/**/*.{ts,tsx}"], - "extends": ["matrix-org/ts"], - "rules": { + files: [ + "src/**/*.{ts,tsx}", + "test/**/*.{ts,tsx}", + ], + extends: [ + "plugin:matrix-org/typescript", + "plugin:matrix-org/react", + ], + rules: { + // Things we do that break the ideal style + "prefer-promise-reject-errors": "off", + "quotes": "off", + "no-extra-boolean-cast": "off", + + // Remove Babel things manually due to override limitations + "@babel/no-invalid-this": ["off"], + // We're okay being explicit at the moment "@typescript-eslint/no-empty-interface": "off", // We disable this while we're transitioning @@ -28,8 +50,6 @@ module.exports = { // We'd rather not do this but we do "@typescript-eslint/ban-ts-comment": "off", - "quotes": "off", - "no-extra-boolean-cast": "off", "no-restricted-properties": [ "error", ...buildRestrictedPropertiesOptions( diff --git a/.flowconfig b/.flowconfig deleted file mode 100644 index 81770c6585..0000000000 --- a/.flowconfig +++ /dev/null @@ -1,6 +0,0 @@ -[include] -src/**/*.js -test/**/*.js - -[ignore] -node_modules/ diff --git a/babel.config.js b/babel.config.js index 0a3a34a391..f00e83652c 100644 --- a/babel.config.js +++ b/babel.config.js @@ -10,7 +10,6 @@ module.exports = { ], }], "@babel/preset-typescript", - "@babel/preset-flow", "@babel/preset-react", ], "plugins": [ @@ -19,7 +18,6 @@ module.exports = { "@babel/plugin-proposal-numeric-separator", "@babel/plugin-proposal-class-properties", "@babel/plugin-proposal-object-rest-spread", - "@babel/plugin-transform-flow-comments", "@babel/plugin-syntax-dynamic-import", "@babel/plugin-transform-runtime", ], diff --git a/package.json b/package.json index 4eb5649c53..1487437bfe 100644 --- a/package.json +++ b/package.json @@ -107,16 +107,16 @@ "devDependencies": { "@babel/cli": "^7.12.10", "@babel/core": "^7.12.10", + "@babel/eslint-parser": "^7.12.10", + "@babel/eslint-plugin": "^7.12.10", "@babel/parser": "^7.12.11", "@babel/plugin-proposal-class-properties": "^7.12.1", "@babel/plugin-proposal-decorators": "^7.12.12", "@babel/plugin-proposal-export-default-from": "^7.12.1", "@babel/plugin-proposal-numeric-separator": "^7.12.7", "@babel/plugin-proposal-object-rest-spread": "^7.12.1", - "@babel/plugin-transform-flow-comments": "^7.12.1", "@babel/plugin-transform-runtime": "^7.12.10", "@babel/preset-env": "^7.12.11", - "@babel/preset-flow": "^7.12.1", "@babel/preset-react": "^7.12.10", "@babel/preset-typescript": "^7.12.7", "@babel/register": "^7.12.10", @@ -142,18 +142,16 @@ "@types/react-transition-group": "^4.4.0", "@types/sanitize-html": "^2.3.1", "@types/zxcvbn": "^4.4.0", - "@typescript-eslint/eslint-plugin": "^4.14.0", - "@typescript-eslint/parser": "^4.14.0", + "@typescript-eslint/eslint-plugin": "^4.17.0", + "@typescript-eslint/parser": "^4.17.0", "@wojtekmaj/enzyme-adapter-react-17": "^0.6.1", - "babel-eslint": "^10.1.0", "babel-jest": "^26.6.3", "chokidar": "^3.5.1", "concurrently": "^5.3.0", "enzyme": "^3.11.0", "eslint": "7.18.0", - "eslint-config-matrix-org": "^0.2.0", - "eslint-plugin-babel": "^5.3.1", - "eslint-plugin-flowtype": "^5.2.0", + "eslint-config-google": "^0.14.0", + "eslint-plugin-matrix-org": "github:matrix-org/eslint-plugin-matrix-org#main", "eslint-plugin-react": "^7.22.0", "eslint-plugin-react-hooks": "^4.2.0", "glob": "^7.1.6", diff --git a/res/css/structures/_ToastContainer.scss b/res/css/structures/_ToastContainer.scss index 35d6087a1b..d248568740 100644 --- a/res/css/structures/_ToastContainer.scss +++ b/res/css/structures/_ToastContainer.scss @@ -134,12 +134,15 @@ limitations under the License. .mx_Toast_buttons { float: right; display: flex; - gap: 5px; .mx_AccessibleButton { min-width: 96px; box-sizing: border-box; } + + .mx_AccessibleButton + .mx_AccessibleButton { + margin-left: 5px; + } } .mx_Toast_description { diff --git a/res/css/views/context_menus/_MessageContextMenu.scss b/res/css/views/context_menus/_MessageContextMenu.scss index 2ecb93e734..338841cce4 100644 --- a/res/css/views/context_menus/_MessageContextMenu.scss +++ b/res/css/views/context_menus/_MessageContextMenu.scss @@ -1,5 +1,6 @@ /* Copyright 2015, 2016 OpenMarket Ltd +Copyright 2021 Michael Weimann Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -15,16 +16,69 @@ limitations under the License. */ .mx_MessageContextMenu { - padding: 6px; -} -.mx_MessageContextMenu_field { - display: block; - padding: 3px 6px 3px 6px; - cursor: pointer; - white-space: nowrap; -} + .mx_IconizedContextMenu_icon { + width: 16px; + height: 16px; + display: block; -.mx_MessageContextMenu_field.mx_MessageContextMenu_fieldSet { - font-weight: bold; + &::before { + content: ''; + width: 16px; + height: 16px; + display: block; + mask-position: center; + mask-size: contain; + mask-repeat: no-repeat; + background: $primary-fg-color; + } + } + + .mx_MessageContextMenu_iconCollapse::before { + mask-image: url('$(res)/img/element-icons/message/chevron-up.svg'); + } + + .mx_MessageContextMenu_iconReport::before { + mask-image: url('$(res)/img/element-icons/warning-badge.svg'); + } + + .mx_MessageContextMenu_iconLink::before { + mask-image: url('$(res)/img/element-icons/link.svg'); + } + + .mx_MessageContextMenu_iconPermalink::before { + mask-image: url('$(res)/img/element-icons/room/share.svg'); + } + + .mx_MessageContextMenu_iconUnhidePreview::before { + mask-image: url('$(res)/img/element-icons/settings/appearance.svg'); + } + + .mx_MessageContextMenu_iconForward::before { + mask-image: url('$(res)/img/element-icons/message/fwd.svg'); + } + + .mx_MessageContextMenu_iconRedact::before { + mask-image: url('$(res)/img/element-icons/trashcan.svg'); + } + + .mx_MessageContextMenu_iconResend::before { + mask-image: url('$(res)/img/element-icons/retry.svg'); + } + + .mx_MessageContextMenu_iconSource::before { + mask-image: url('$(res)/img/element-icons/room/format-bar/code.svg'); + } + + .mx_MessageContextMenu_iconQuote::before { + mask-image: url('$(res)/img/element-icons/room/format-bar/quote.svg'); + } + + .mx_MessageContextMenu_iconPin::before { + mask-image: url('$(res)/img/element-icons/room/pin-upright.svg'); + } + + .mx_MessageContextMenu_iconUnpin::before { + mask-image: url('$(res)/img/element-icons/room/pin.svg'); + } } diff --git a/res/img/element-icons/message/chevron-up.svg b/res/img/element-icons/message/chevron-up.svg new file mode 100644 index 0000000000..4eb5ecc33e --- /dev/null +++ b/res/img/element-icons/message/chevron-up.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/res/img/element-icons/message/corner-up-right.svg b/res/img/element-icons/message/corner-up-right.svg new file mode 100644 index 0000000000..0b8f961b7b --- /dev/null +++ b/res/img/element-icons/message/corner-up-right.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/res/img/element-icons/message/fwd.svg b/res/img/element-icons/message/fwd.svg new file mode 100644 index 0000000000..8bcc70d092 --- /dev/null +++ b/res/img/element-icons/message/fwd.svg @@ -0,0 +1,3 @@ + + + diff --git a/res/img/element-icons/message/link.svg b/res/img/element-icons/message/link.svg new file mode 100644 index 0000000000..c89dd41c23 --- /dev/null +++ b/res/img/element-icons/message/link.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/res/img/element-icons/message/repeat.svg b/res/img/element-icons/message/repeat.svg new file mode 100644 index 0000000000..c7657b08ed --- /dev/null +++ b/res/img/element-icons/message/repeat.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/res/img/element-icons/message/share.svg b/res/img/element-icons/message/share.svg new file mode 100644 index 0000000000..df38c14d63 --- /dev/null +++ b/res/img/element-icons/message/share.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/res/img/element-icons/warning-badge.svg b/res/img/element-icons/warning-badge.svg index 1ae4e40ffe..1c8da9aa8e 100644 --- a/res/img/element-icons/warning-badge.svg +++ b/res/img/element-icons/warning-badge.svg @@ -1,5 +1,32 @@ - - - - + + + + + + image/svg+xml + + + + + + + diff --git a/src/@types/common.ts b/src/@types/common.ts index b887bd4090..1fb9ba4303 100644 --- a/src/@types/common.ts +++ b/src/@types/common.ts @@ -17,7 +17,7 @@ limitations under the License. import { JSXElementConstructor } from "react"; // Based on https://stackoverflow.com/a/53229857/3532235 -export type Without = {[P in Exclude] ? : never}; +export type Without = {[P in Exclude]?: never}; export type XOR = (T | U) extends object ? (Without & U) | (Without & T) : T | U; export type Writeable = { -readonly [P in keyof T]: T[P] }; diff --git a/src/@types/global.d.ts b/src/@types/global.d.ts index 7eff341095..f75c17aaf4 100644 --- a/src/@types/global.d.ts +++ b/src/@types/global.d.ts @@ -16,6 +16,7 @@ limitations under the License. import "matrix-js-sdk/src/@types/global"; // load matrix-js-sdk's type extensions first import * as ModernizrStatic from "modernizr"; + import ContentMessages from "../ContentMessages"; import { IMatrixClientPeg } from "../MatrixClientPeg"; import ToastStore from "../stores/ToastStore"; @@ -23,25 +24,25 @@ import DeviceListener from "../DeviceListener"; import { RoomListStoreClass } from "../stores/room-list/RoomListStore"; import { PlatformPeg } from "../PlatformPeg"; import RoomListLayoutStore from "../stores/room-list/RoomListLayoutStore"; -import {IntegrationManagers} from "../integrations/IntegrationManagers"; -import {ModalManager} from "../Modal"; +import { IntegrationManagers } from "../integrations/IntegrationManagers"; +import { ModalManager } from "../Modal"; import SettingsStore from "../settings/SettingsStore"; -import {ActiveRoomObserver} from "../ActiveRoomObserver"; -import {Notifier} from "../Notifier"; -import type {Renderer} from "react-dom"; +import { ActiveRoomObserver } from "../ActiveRoomObserver"; +import { Notifier } from "../Notifier"; +import type { Renderer } from "react-dom"; import RightPanelStore from "../stores/RightPanelStore"; import WidgetStore from "../stores/WidgetStore"; import CallHandler from "../CallHandler"; -import {Analytics} from "../Analytics"; +import { Analytics } from "../Analytics"; import CountlyAnalytics from "../CountlyAnalytics"; import UserActivity from "../UserActivity"; -import {ModalWidgetStore} from "../stores/ModalWidgetStore"; +import { ModalWidgetStore } from "../stores/ModalWidgetStore"; import { WidgetLayoutStore } from "../stores/widgets/WidgetLayoutStore"; import VoipUserMapper from "../VoipUserMapper"; -import {SpaceStoreClass} from "../stores/SpaceStore"; +import { SpaceStoreClass } from "../stores/SpaceStore"; import TypingStore from "../stores/TypingStore"; import { EventIndexPeg } from "../indexing/EventIndexPeg"; -import {VoiceRecordingStore} from "../stores/VoiceRecordingStore"; +import { VoiceRecordingStore } from "../stores/VoiceRecordingStore"; import PerformanceMonitor from "../performance"; import UIStore from "../stores/UIStore"; import { SetupEncryptionStore } from "../stores/SetupEncryptionStore"; @@ -127,11 +128,24 @@ declare global { setSinkId(outputId: string); } + // Add Chrome-specific `instant` ScrollBehaviour + type _ScrollBehavior = ScrollBehavior | "instant"; + + interface _ScrollOptions { + behavior?: _ScrollBehavior; + } + + interface _ScrollIntoViewOptions extends _ScrollOptions { + block?: ScrollLogicalPosition; + inline?: ScrollLogicalPosition; + } + interface Element { // Safari & IE11 only have this prefixed: we used prefixed versions // previously so let's continue to support them for now webkitRequestFullScreen(options?: FullscreenOptions): Promise; msRequestFullscreen(options?: FullscreenOptions): Promise; + scrollIntoView(arg?: boolean | _ScrollIntoViewOptions): void; } interface Error { diff --git a/src/AddThreepid.js b/src/AddThreepid.js index f06f7c187d..eb822c6d75 100644 --- a/src/AddThreepid.js +++ b/src/AddThreepid.js @@ -16,12 +16,12 @@ See the License for the specific language governing permissions and limitations under the License. */ -import {MatrixClientPeg} from './MatrixClientPeg'; +import { MatrixClientPeg } from './MatrixClientPeg'; import * as sdk from './index'; import Modal from './Modal'; import { _t } from './languageHandler'; import IdentityAuthClient from './IdentityAuthClient'; -import {SSOAuthEntry} from "./components/views/auth/InteractiveAuthEntryComponents"; +import { SSOAuthEntry } from "./components/views/auth/InteractiveAuthEntryComponents"; function getIdServerDomain() { return MatrixClientPeg.get().idBaseUrl.split("://")[1]; @@ -189,7 +189,6 @@ export default class AddThreepid { // pop up an interactive auth dialog const InteractiveAuthDialog = sdk.getComponent("dialogs.InteractiveAuthDialog"); - const dialogAesthetics = { [SSOAuthEntry.PHASE_PREAUTH]: { title: _t("Use Single Sign On to continue"), diff --git a/src/Analytics.tsx b/src/Analytics.tsx index 212bfd3757..8c82639b5f 100644 --- a/src/Analytics.tsx +++ b/src/Analytics.tsx @@ -17,7 +17,7 @@ limitations under the License. import React from 'react'; -import {getCurrentLanguage, _t, _td, IVariables} from './languageHandler'; +import { getCurrentLanguage, _t, _td, IVariables } from './languageHandler'; import PlatformPeg from './PlatformPeg'; import SdkConfig from './SdkConfig'; import Modal from './Modal'; diff --git a/src/BasePlatform.ts b/src/BasePlatform.ts index 5483ea6874..5b4b15cc67 100644 --- a/src/BasePlatform.ts +++ b/src/BasePlatform.ts @@ -17,16 +17,16 @@ See the License for the specific language governing permissions and limitations under the License. */ -import {MatrixClient} from "matrix-js-sdk/src/client"; -import {encodeUnpaddedBase64} from "matrix-js-sdk/src/crypto/olmlib"; +import { MatrixClient } from "matrix-js-sdk/src/client"; +import { encodeUnpaddedBase64 } from "matrix-js-sdk/src/crypto/olmlib"; import dis from './dispatcher/dispatcher'; import BaseEventIndexManager from './indexing/BaseEventIndexManager'; -import {ActionPayload} from "./dispatcher/payloads"; -import {CheckUpdatesPayload} from "./dispatcher/payloads/CheckUpdatesPayload"; -import {Action} from "./dispatcher/actions"; -import {hideToast as hideUpdateToast} from "./toasts/UpdateToast"; -import {MatrixClientPeg} from "./MatrixClientPeg"; -import {idbLoad, idbSave, idbDelete} from "./utils/StorageManager"; +import { ActionPayload } from "./dispatcher/payloads"; +import { CheckUpdatesPayload } from "./dispatcher/payloads/CheckUpdatesPayload"; +import { Action } from "./dispatcher/actions"; +import { hideToast as hideUpdateToast } from "./toasts/UpdateToast"; +import { MatrixClientPeg } from "./MatrixClientPeg"; +import { idbLoad, idbSave, idbDelete } from "./utils/StorageManager"; export const SSO_HOMESERVER_URL_KEY = "mx_sso_hs_url"; export const SSO_ID_SERVER_URL_KEY = "mx_sso_is_url"; @@ -335,7 +335,7 @@ export default abstract class BasePlatform { try { const key = await crypto.subtle.decrypt( - {name: "AES-GCM", iv: data.iv, additionalData}, data.cryptoKey, + { name: "AES-GCM", iv: data.iv, additionalData }, data.cryptoKey, data.encrypted, ); return encodeUnpaddedBase64(key); @@ -348,7 +348,7 @@ export default abstract class BasePlatform { /** * Create and store a pickle key for encrypting libolm objects. * @param {string} userId the user ID for the user that the pickle key is for. - * @param {string} userId the device ID that the pickle key is for. + * @param {string} deviceId the device ID that the pickle key is for. * @returns {string|null} the pickle key, or null if the platform does not * support storing pickle keys. */ @@ -360,7 +360,7 @@ export default abstract class BasePlatform { const randomArray = new Uint8Array(32); crypto.getRandomValues(randomArray); const cryptoKey = await crypto.subtle.generateKey( - {name: "AES-GCM", length: 256}, false, ["encrypt", "decrypt"], + { name: "AES-GCM", length: 256 }, false, ["encrypt", "decrypt"], ); const iv = new Uint8Array(32); crypto.getRandomValues(iv); @@ -375,11 +375,11 @@ export default abstract class BasePlatform { } const encrypted = await crypto.subtle.encrypt( - {name: "AES-GCM", iv, additionalData}, cryptoKey, randomArray, + { name: "AES-GCM", iv, additionalData }, cryptoKey, randomArray, ); try { - await idbSave("pickleKey", [userId, deviceId], {encrypted, iv, cryptoKey}); + await idbSave("pickleKey", [userId, deviceId], { encrypted, iv, cryptoKey }); } catch (e) { return null; } diff --git a/src/CallHandler.tsx b/src/CallHandler.tsx index 448b1cb780..cb54db3f8a 100644 --- a/src/CallHandler.tsx +++ b/src/CallHandler.tsx @@ -55,7 +55,7 @@ limitations under the License. import React from 'react'; -import {MatrixClientPeg} from './MatrixClientPeg'; +import { MatrixClientPeg } from './MatrixClientPeg'; import PlatformPeg from './PlatformPeg'; import Modal from './Modal'; import { _t } from './languageHandler'; @@ -63,11 +63,11 @@ import dis from './dispatcher/dispatcher'; import WidgetUtils from './utils/WidgetUtils'; import WidgetEchoStore from './stores/WidgetEchoStore'; import SettingsStore from './settings/SettingsStore'; -import {Jitsi} from "./widgets/Jitsi"; -import {WidgetType} from "./widgets/WidgetType"; -import {SettingLevel} from "./settings/SettingLevel"; +import { Jitsi } from "./widgets/Jitsi"; +import { WidgetType } from "./widgets/WidgetType"; +import { SettingLevel } from "./settings/SettingLevel"; import { ActionPayload } from "./dispatcher/payloads"; -import {base32} from "rfc4648"; +import { base32 } from "rfc4648"; import QuestionDialog from "./components/views/dialogs/QuestionDialog"; import ErrorDialog from "./components/views/dialogs/ErrorDialog"; @@ -77,10 +77,10 @@ import { ElementWidgetActions } from "./stores/widgets/ElementWidgetActions"; import { MatrixCall, CallErrorCode, CallState, CallEvent, CallParty, CallType } from "matrix-js-sdk/src/webrtc/call"; import Analytics from './Analytics'; import CountlyAnalytics from "./CountlyAnalytics"; -import {UIFeature} from "./settings/UIFeature"; +import { UIFeature } from "./settings/UIFeature"; import { CallError } from "matrix-js-sdk/src/webrtc/call"; import { logger } from 'matrix-js-sdk/src/logger'; -import DesktopCapturerSourcePicker from "./components/views/elements/DesktopCapturerSourcePicker" +import DesktopCapturerSourcePicker from "./components/views/elements/DesktopCapturerSourcePicker"; import { Action } from './dispatcher/actions'; import VoipUserMapper from './VoipUserMapper'; import { addManagedHybridWidget, isManagedHybridWidgetEnabled } from './widgets/ManagedHybrid'; @@ -166,7 +166,7 @@ export default class CallHandler extends EventEmitter { static sharedInstance() { if (!window.mxCallHandler) { - window.mxCallHandler = new CallHandler() + window.mxCallHandler = new CallHandler(); } return window.mxCallHandler; @@ -185,7 +185,7 @@ export default class CallHandler extends EventEmitter { const nativeUser = this.assertedIdentityNativeUsers[call.callId]; if (nativeUser) { const room = findDMForUser(MatrixClientPeg.get(), nativeUser); - if (room) return room.roomId + if (room) return room.roomId; } } @@ -238,7 +238,7 @@ export default class CallHandler extends EventEmitter { this.supportsPstnProtocol = null; } - dis.dispatch({action: Action.PstnSupportUpdated}); + dis.dispatch({ action: Action.PstnSupportUpdated }); if (protocols[PROTOCOL_SIP_NATIVE] !== undefined && protocols[PROTOCOL_SIP_VIRTUAL] !== undefined) { this.supportsSipNativeVirtual = Boolean( @@ -246,7 +246,7 @@ export default class CallHandler extends EventEmitter { ); } - dis.dispatch({action: Action.VirtualRoomSupportUpdated}); + dis.dispatch({ action: Action.VirtualRoomSupportUpdated }); } catch (e) { if (maxTries === 1) { console.log("Failed to check for protocol support and no retries remain: assuming no support", e); @@ -299,7 +299,7 @@ export default class CallHandler extends EventEmitter { action: 'incoming_call', call: call, }, true); - } + }; getCallForRoom(roomId: string): MatrixCall { return this.calls.get(roomId) || null; @@ -711,7 +711,7 @@ export default class CallHandler extends EventEmitter { call.placeScreenSharingCall( async (): Promise => { - const {finished} = Modal.createDialog(DesktopCapturerSourcePicker); + const { finished } = Modal.createDialog(DesktopCapturerSourcePicker); const [source] = await finished; return source; }, @@ -816,7 +816,7 @@ export default class CallHandler extends EventEmitter { Analytics.trackEvent('voip', 'receiveCall', 'type', call.type); console.log("Adding call for room ", mappedRoomId); - this.calls.set(mappedRoomId, call) + this.calls.set(mappedRoomId, call); this.emit(CallHandlerEvent.CallsChanged, this.calls); this.setCallListeners(call); @@ -872,7 +872,7 @@ export default class CallHandler extends EventEmitter { this.dialNumber(payload.number); break; } - } + }; private async dialNumber(number: string) { const results = await this.pstnLookup(number); @@ -966,7 +966,7 @@ export default class CallHandler extends EventEmitter { confId = 'Jitsi' + random; } - let widgetUrl = WidgetUtils.getLocalJitsiWrapperUrl({auth: jitsiAuth}); + let widgetUrl = WidgetUtils.getLocalJitsiWrapperUrl({ auth: jitsiAuth }); // TODO: Remove URL hacks when the mobile clients eventually support v2 widgets const parsedUrl = new URL(widgetUrl); diff --git a/src/ContentMessages.tsx b/src/ContentMessages.tsx index 7a3cf5d50f..ef0a89a690 100644 --- a/src/ContentMessages.tsx +++ b/src/ContentMessages.tsx @@ -18,8 +18,8 @@ limitations under the License. import React from "react"; import dis from './dispatcher/dispatcher'; -import {MatrixClientPeg} from './MatrixClientPeg'; -import {MatrixClient} from "matrix-js-sdk/src/client"; +import { MatrixClientPeg } from './MatrixClientPeg'; +import { MatrixClient } from "matrix-js-sdk/src/client"; import * as sdk from './index'; import { _t } from './languageHandler'; import Modal from './Modal'; @@ -37,7 +37,7 @@ import { UploadProgressPayload, UploadStartedPayload, } from "./dispatcher/payloads/UploadPayload"; -import {IUpload} from "./models/IUpload"; +import { IUpload } from "./models/IUpload"; import { IImageInfo } from "matrix-js-sdk/src/@types/partials"; const MAX_WIDTH = 800; @@ -189,7 +189,7 @@ async function loadImageElement(imageFile: File) { const [hidpi] = await Promise.all([parsePromise, imgPromise]); const width = hidpi ? (img.width >> 1) : img.width; const height = hidpi ? (img.height >> 1) : img.height; - return {width, height, img}; + return { width, height, img }; } /** @@ -343,7 +343,7 @@ export function uploadFile( if (file.type) { encryptInfo.mimetype = file.type; } - return {"file": encryptInfo}; + return { "file": encryptInfo }; }); (prom as IAbortablePromise).abort = () => { canceled = true; @@ -357,7 +357,7 @@ export function uploadFile( const promise1 = basePromise.then(function(url) { if (canceled) throw new UploadCanceledError(); // If the attachment isn't encrypted then include the URL directly. - return {"url": url}; + return { "url": url }; }); (promise1 as any).abort = () => { canceled = true; @@ -377,7 +377,7 @@ export default class ContentMessages { console.warn(`Failed to send content with URL ${url} to room ${roomId}`, e); throw e; }); - CountlyAnalytics.instance.trackSendMessage(startTime, prom, roomId, false, false, {msgtype: "m.sticker"}); + CountlyAnalytics.instance.trackSendMessage(startTime, prom, roomId, false, false, { msgtype: "m.sticker" }); return prom; } @@ -391,14 +391,14 @@ export default class ContentMessages { async sendContentListToRoom(files: File[], roomId: string, matrixClient: MatrixClient) { if (matrixClient.isGuest()) { - dis.dispatch({action: 'require_registration'}); + dis.dispatch({ action: 'require_registration' }); return; } const isQuoting = Boolean(RoomViewStore.getQuotingEvent()); if (isQuoting) { const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog"); - const {finished} = Modal.createTrackedDialog<[boolean]>('Upload Reply Warning', '', QuestionDialog, { + const { finished } = Modal.createTrackedDialog<[boolean]>('Upload Reply Warning', '', QuestionDialog, { title: _t('Replying With Files'), description: (
{_t( @@ -432,7 +432,7 @@ export default class ContentMessages { if (tooBigFiles.length > 0) { const UploadFailureDialog = sdk.getComponent("dialogs.UploadFailureDialog"); - const {finished} = Modal.createTrackedDialog<[boolean]>('Upload Failure', '', UploadFailureDialog, { + const { finished } = Modal.createTrackedDialog<[boolean]>('Upload Failure', '', UploadFailureDialog, { badFiles: tooBigFiles, totalFiles: files.length, contentMessages: this, @@ -449,7 +449,7 @@ 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', + const { finished } = Modal.createTrackedDialog<[boolean, boolean]>('Upload Files confirmation', '', UploadConfirmDialog, { file, currentIndex: i, @@ -481,7 +481,7 @@ export default class ContentMessages { if (upload) { upload.canceled = true; MatrixClientPeg.get().cancelUpload(upload.promise); - dis.dispatch({action: Action.UploadCanceled, upload}); + dis.dispatch({ action: Action.UploadCanceled, upload }); } } @@ -542,7 +542,7 @@ export default class ContentMessages { promise: prom, }; this.inprogress.push(upload); - dis.dispatch({action: Action.UploadStarted, upload}); + dis.dispatch({ action: Action.UploadStarted, upload }); // Focus the composer view dis.fire(Action.FocusComposer); @@ -550,7 +550,7 @@ export default class ContentMessages { function onProgress(ev) { upload.total = ev.total; upload.loaded = ev.loaded; - dis.dispatch({action: Action.UploadProgress, upload}); + dis.dispatch({ action: Action.UploadProgress, upload }); } let error; @@ -577,11 +577,11 @@ export default class ContentMessages { }, function(err) { error = err; if (!upload.canceled) { - let desc = _t("The file '%(fileName)s' failed to upload.", {fileName: upload.fileName}); + let desc = _t("The file '%(fileName)s' failed to upload.", { fileName: upload.fileName }); if (err.http_status === 413) { desc = _t( "The file '%(fileName)s' exceeds this homeserver's size limit for uploads", - {fileName: upload.fileName}, + { fileName: upload.fileName }, ); } const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog"); @@ -604,10 +604,10 @@ export default class ContentMessages { if (error && error.http_status === 413) { this.mediaConfig = null; } - dis.dispatch({action: Action.UploadFailed, upload, error}); + dis.dispatch({ action: Action.UploadFailed, upload, error }); } else { - dis.dispatch({action: Action.UploadFinished, upload}); - dis.dispatch({action: 'message_sent'}); + dis.dispatch({ action: Action.UploadFinished, upload }); + dis.dispatch({ action: 'message_sent' }); } }); } diff --git a/src/CountlyAnalytics.ts b/src/CountlyAnalytics.ts index f494c1eb22..39dcac4048 100644 --- a/src/CountlyAnalytics.ts +++ b/src/CountlyAnalytics.ts @@ -14,13 +14,13 @@ See the License for the specific language governing permissions and limitations under the License. */ -import {randomString} from "matrix-js-sdk/src/randomstring"; +import { randomString } from "matrix-js-sdk/src/randomstring"; -import {getCurrentLanguage} from './languageHandler'; +import { getCurrentLanguage } from './languageHandler'; import PlatformPeg from './PlatformPeg'; import SdkConfig from './SdkConfig'; -import {MatrixClientPeg} from "./MatrixClientPeg"; -import {sleep} from "./utils/promise"; +import { MatrixClientPeg } from "./MatrixClientPeg"; +import { sleep } from "./utils/promise"; import RoomViewStore from "./stores/RoomViewStore"; import { Action } from "./dispatcher/actions"; @@ -338,8 +338,8 @@ const getRoomStats = (roomId: string) => { "is_encrypted": cli?.isRoomEncrypted(roomId), // eslint-disable-next-line camelcase "is_public": room?.currentState.getStateEvents("m.room.join_rules", "")?.getContent()?.join_rule === "public", - } -} + }; +}; // async wrapper for regex-powered String.prototype.replace const strReplaceAsync = async (str: string, regex: RegExp, fn: (...args: string[]) => Promise) => { @@ -414,7 +414,7 @@ export default class CountlyAnalytics { this.anonymous = anonymous; if (anonymous) { - await this.changeUserKey(randomString(64)) + await this.changeUserKey(randomString(64)); } else { await this.changeUserKey(await hashHex(MatrixClientPeg.get().getUserId()), true); } @@ -438,7 +438,7 @@ export default class CountlyAnalytics { await this.track("Opt-Out" ); this.endSession(); window.clearInterval(this.heartbeatIntervalId); - window.clearTimeout(this.activityIntervalId) + window.clearTimeout(this.activityIntervalId); this.baseUrl = null; // remove listeners bound in trackSessions() window.removeEventListener("beforeunload", this.endSession); @@ -662,14 +662,14 @@ export default class CountlyAnalytics { } private queue(args: Omit & Partial>) { - const {count = 1, ...rest} = args; + const { count = 1, ...rest } = args; const ev = { ...this.getTimeParams(), ...rest, count, platform: this.appPlatform, app_version: this.appVersion, - } + }; this.pendingEvents.push(ev); if (this.pendingEvents.length > MAX_PENDING_EVENTS) { @@ -680,7 +680,7 @@ export default class CountlyAnalytics { private getOrientation = (): Orientation => { return window.matchMedia("(orientation: landscape)").matches ? Orientation.Landscape - : Orientation.Portrait + : Orientation.Portrait; }; private reportOrientation = () => { @@ -749,7 +749,7 @@ export default class CountlyAnalytics { const request: Parameters[0] = { begin_session: 1, user_details: JSON.stringify(userDetails), - } + }; const metrics = this.getMetrics(); if (metrics) { @@ -773,7 +773,7 @@ export default class CountlyAnalytics { private endSession = () => { if (this.sessionStarted) { - window.removeEventListener("resize", this.reportOrientation) + window.removeEventListener("resize", this.reportOrientation); this.reportViewDuration(); this.request({ diff --git a/src/DecryptionFailureTracker.ts b/src/DecryptionFailureTracker.ts index 07c0c546fe..d40574a6db 100644 --- a/src/DecryptionFailureTracker.ts +++ b/src/DecryptionFailureTracker.ts @@ -168,7 +168,7 @@ export class DecryptionFailureTracker { const trackedEventIds = [...dedupedFailuresMap.keys()]; this.trackedEventHashMap = trackedEventIds.reduce( - (result, eventId) => ({...result, [eventId]: true}), + (result, eventId) => ({ ...result, [eventId]: true }), this.trackedEventHashMap, ); diff --git a/src/DeviceListener.ts b/src/DeviceListener.ts index df494e6bdd..d70585e5ec 100644 --- a/src/DeviceListener.ts +++ b/src/DeviceListener.ts @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import {MatrixClientPeg} from './MatrixClientPeg'; +import { MatrixClientPeg } from './MatrixClientPeg'; import dis from "./dispatcher/dispatcher"; import { hideToast as hideBulkUnverifiedSessionsToast, diff --git a/src/GroupAddressPicker.js b/src/GroupAddressPicker.js index 9497d9de4c..ea1813876c 100644 --- a/src/GroupAddressPicker.js +++ b/src/GroupAddressPicker.js @@ -19,7 +19,7 @@ import Modal from './Modal'; import * as sdk from './'; import MultiInviter from './utils/MultiInviter'; import { _t } from './languageHandler'; -import {MatrixClientPeg} from './MatrixClientPeg'; +import { MatrixClientPeg } from './MatrixClientPeg'; import GroupStore from './stores/GroupStore'; import StyledCheckbox from './components/views/elements/StyledCheckbox'; @@ -103,7 +103,7 @@ function _onGroupInviteFinished(groupId, addrs) { if (errorList.length > 0) { const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog"); Modal.createTrackedDialog('Failed to invite the following users to the group', '', ErrorDialog, { - title: _t("Failed to invite the following users to %(groupId)s:", {groupId: groupId}), + title: _t("Failed to invite the following users to %(groupId)s:", { groupId: groupId }), description: errorList.join(", "), }); } @@ -111,7 +111,7 @@ function _onGroupInviteFinished(groupId, addrs) { const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog"); Modal.createTrackedDialog('Failed to invite users to group', '', ErrorDialog, { title: _t("Failed to invite users to community"), - description: _t("Failed to invite users to %(groupId)s", {groupId: groupId}), + description: _t("Failed to invite users to %(groupId)s", { groupId: groupId }), }); }); } @@ -137,7 +137,7 @@ function _onGroupAddRoomFinished(groupId, addrs, addRoomsPublicly) { // Add this group as related if (!groups.includes(groupId)) { groups.push(groupId); - return MatrixClientPeg.get().sendStateEvent(roomId, 'm.room.related_groups', {groups}, ''); + return MatrixClientPeg.get().sendStateEvent(roomId, 'm.room.related_groups', { groups }, ''); } }); })).then(() => { @@ -152,7 +152,7 @@ function _onGroupAddRoomFinished(groupId, addrs, addRoomsPublicly) { { title: _t( "Failed to add the following rooms to %(groupId)s:", - {groupId}, + { groupId }, ), description: errorList.join(", "), }, diff --git a/src/HtmlUtils.tsx b/src/HtmlUtils.tsx index 983538d65b..c80b50c566 100644 --- a/src/HtmlUtils.tsx +++ b/src/HtmlUtils.tsx @@ -138,7 +138,7 @@ export function getHtmlText(insaneHtml: string): string { selfClosing: [], allowedSchemes: [], disallowedTagsMode: 'discard', - }) + }); } /** @@ -183,7 +183,7 @@ const transformTags: IExtendedSanitizeOptions["transformTags"] = { // custom to // images" preference is disabled. Future work might expose some UI to reveal them // like standalone image events have. if (!attribs.src || !attribs.src.startsWith('mxc://') || !SettingsStore.getValue("showImages")) { - return { tagName, attribs: {}}; + return { tagName, attribs: {} }; } const width = Number(attribs.width) || 800; const height = Number(attribs.height) || 600; diff --git a/src/IdentityAuthClient.js b/src/IdentityAuthClient.js index 9239c1bc75..31a5021317 100644 --- a/src/IdentityAuthClient.js +++ b/src/IdentityAuthClient.js @@ -17,7 +17,7 @@ limitations under the License. import { SERVICE_TYPES } from 'matrix-js-sdk/src/service-types'; import { createClient } from 'matrix-js-sdk/src/matrix'; -import {MatrixClientPeg} from './MatrixClientPeg'; +import { MatrixClientPeg } from './MatrixClientPeg'; import Modal from './Modal'; import * as sdk from './index'; import { _t } from './languageHandler'; diff --git a/src/KeyBindingsDefaults.ts b/src/KeyBindingsDefaults.ts index 63c4ac0f86..b2f70abff7 100644 --- a/src/KeyBindingsDefaults.ts +++ b/src/KeyBindingsDefaults.ts @@ -156,7 +156,7 @@ const messageComposerBindings = (): KeyBinding[] => { } } return bindings; -} +}; const autocompleteBindings = (): KeyBinding[] => { return [ @@ -207,7 +207,7 @@ const autocompleteBindings = (): KeyBinding[] => { }, }, ]; -} +}; const roomListBindings = (): KeyBinding[] => { return [ @@ -248,7 +248,7 @@ const roomListBindings = (): KeyBinding[] => { }, }, ]; -} +}; const roomBindings = (): KeyBinding[] => { const bindings: KeyBinding[] = [ @@ -312,7 +312,7 @@ const roomBindings = (): KeyBinding[] => { } return bindings; -} +}; const navigationBindings = (): KeyBinding[] => { return [ @@ -396,7 +396,7 @@ const navigationBindings = (): KeyBinding[] => { }, }, ]; -} +}; export const defaultBindingsProvider: IKeyBindingsProvider = { getMessageComposerBindings: messageComposerBindings, @@ -404,4 +404,4 @@ export const defaultBindingsProvider: IKeyBindingsProvider = { getRoomListBindings: roomListBindings, getRoomBindings: roomBindings, getNavigationBindings: navigationBindings, -} +}; diff --git a/src/KeyBindingsManager.ts b/src/KeyBindingsManager.ts index aac14bde20..4225d2f449 100644 --- a/src/KeyBindingsManager.ts +++ b/src/KeyBindingsManager.ts @@ -140,12 +140,12 @@ export type KeyCombo = { ctrlKey?: boolean; metaKey?: boolean; shiftKey?: boolean; -} +}; export type KeyBinding = { action: T; keyCombo: KeyCombo; -} +}; /** * Helper method to check if a KeyboardEvent matches a KeyCombo diff --git a/src/Lifecycle.ts b/src/Lifecycle.ts index b0a1292ba1..76dee5ab55 100644 --- a/src/Lifecycle.ts +++ b/src/Lifecycle.ts @@ -20,9 +20,9 @@ limitations under the License. import { createClient } from 'matrix-js-sdk/src/matrix'; import { InvalidStoreError } from "matrix-js-sdk/src/errors"; import { MatrixClient } from "matrix-js-sdk/src/client"; -import {decryptAES, encryptAES} from "matrix-js-sdk/src/crypto/aes"; +import { decryptAES, encryptAES, IEncryptedPayload } from "matrix-js-sdk/src/crypto/aes"; -import {IMatrixClientCreds, MatrixClientPeg} from './MatrixClientPeg'; +import { IMatrixClientCreds, MatrixClientPeg } from './MatrixClientPeg'; import SecurityCustomisations from "./customisations/Security"; import EventIndexPeg from './indexing/EventIndexPeg'; import createMatrixClient from './utils/createMatrixClient'; @@ -41,17 +41,17 @@ import * as StorageManager from './utils/StorageManager'; import SettingsStore from "./settings/SettingsStore"; import TypingStore from "./stores/TypingStore"; import ToastStore from "./stores/ToastStore"; -import {IntegrationManagers} from "./integrations/IntegrationManagers"; -import {Mjolnir} from "./mjolnir/Mjolnir"; +import { IntegrationManagers } from "./integrations/IntegrationManagers"; +import { Mjolnir } from "./mjolnir/Mjolnir"; import DeviceListener from "./DeviceListener"; -import {Jitsi} from "./widgets/Jitsi"; -import {SSO_HOMESERVER_URL_KEY, SSO_ID_SERVER_URL_KEY, SSO_IDP_ID_KEY} from "./BasePlatform"; +import { Jitsi } from "./widgets/Jitsi"; +import { SSO_HOMESERVER_URL_KEY, SSO_ID_SERVER_URL_KEY, SSO_IDP_ID_KEY } from "./BasePlatform"; import ThreepidInviteStore from "./stores/ThreepidInviteStore"; import CountlyAnalytics from "./CountlyAnalytics"; import CallHandler from './CallHandler'; import LifecycleCustomisations from "./customisations/Lifecycle"; import ErrorDialog from "./components/views/dialogs/ErrorDialog"; -import {_t} from "./languageHandler"; +import { _t } from "./languageHandler"; const HOMESERVER_URL_KEY = "mx_hs_url"; const ID_SERVER_URL_KEY = "mx_is_url"; @@ -154,7 +154,7 @@ export async function loadSession(opts: ILoadSessionOpts = {}): Promise * return [null, null]. */ export async function getStoredSessionOwner(): Promise<[string, boolean]> { - const {hsUrl, userId, hasAccessToken, isGuest} = await getStoredSessionVars(); + const { hsUrl, userId, hasAccessToken, isGuest } = await getStoredSessionVars(); return hsUrl && userId && hasAccessToken ? [userId, isGuest] : [null, null]; } @@ -303,7 +303,7 @@ export interface IStoredSession { hsUrl: string; isUrl: string; hasAccessToken: boolean; - accessToken: string | object; + accessToken: string | IEncryptedPayload; userId: string; deviceId: string; isGuest: boolean; @@ -346,11 +346,11 @@ export async function getStoredSessionVars(): Promise { isGuest = localStorage.getItem("matrix-is-guest") === "true"; } - return {hsUrl, isUrl, hasAccessToken, accessToken, userId, deviceId, isGuest}; + return { hsUrl, isUrl, hasAccessToken, accessToken, userId, deviceId, isGuest }; } // The pickle key is a string of unspecified length and format. For AES, we -// need a 256-bit Uint8Array. So we HKDF the pickle key to generate the AES +// need a 256-bit Uint8Array. So we HKDF the pickle key to generate the AES // key. The AES key should be zeroed after it is used. async function pickleKeyToAesKey(pickleKey: string): Promise { const pickleKeyBuffer = new Uint8Array(pickleKey.length); @@ -402,7 +402,7 @@ export async function restoreFromLocalStorage(opts?: { ignoreGuest?: boolean }): return false; } - const {hsUrl, isUrl, hasAccessToken, accessToken, userId, deviceId, isGuest} = await getStoredSessionVars(); + const { hsUrl, isUrl, hasAccessToken, accessToken, userId, deviceId, isGuest } = await getStoredSessionVars(); if (hasAccessToken && !accessToken) { abortLogin(); @@ -495,7 +495,7 @@ export async function setLoggedIn(credentials: IMatrixClientCreds): Promise { // to add listeners for the 'sync' event so otherwise we'd have // a race condition (and we need to dispatch synchronously for this // to work). - dis.dispatch({action: 'will_start_client'}, true); + dis.dispatch({ action: 'will_start_client' }, true); // reset things first just in case TypingStore.sharedInstance().reset(); @@ -814,7 +814,7 @@ async function startMatrixClient(startSyncing = true): Promise { // dispatch that we finished starting up to wire up any other bits // of the matrix client that cannot be set prior to starting up. - dis.dispatch({action: 'client_started'}); + dis.dispatch({ action: 'client_started' }); if (isSoftLogout()) { softLogout(); @@ -830,9 +830,9 @@ export async function onLoggedOut(): Promise { // Ensure that we dispatch a view change **before** stopping the client so // so that React components unmount first. This avoids React soft crashes // that can occur when components try to use a null client. - dis.dispatch({action: 'on_logged_out'}, true); + dis.dispatch({ action: 'on_logged_out' }, true); stopMatrixClient(); - await clearStorage({deleteEverything: true}); + await clearStorage({ deleteEverything: true }); LifecycleCustomisations.onLoggedOutAndStorageCleared?.(); } diff --git a/src/Login.ts b/src/Login.ts index 7caab22d88..a8848210be 100644 --- a/src/Login.ts +++ b/src/Login.ts @@ -16,7 +16,7 @@ limitations under the License. */ // @ts-ignore - XXX: tsc doesn't like this: our js-sdk imports are complex so this isn't surprising -import {createClient} from "matrix-js-sdk/src/matrix"; +import { createClient } from "matrix-js-sdk/src/matrix"; import { MatrixClient } from "matrix-js-sdk/src/client"; import { IMatrixClientCreds } from "./MatrixClientPeg"; import SecurityCustomisations from "./customisations/Security"; @@ -190,7 +190,6 @@ export default class Login { } } - /** * Send a login request to the given server, and format the response * as a MatrixClientCreds diff --git a/src/MatrixClientPeg.ts b/src/MatrixClientPeg.ts index 7db5ed1a4e..cb6cb5c65c 100644 --- a/src/MatrixClientPeg.ts +++ b/src/MatrixClientPeg.ts @@ -18,22 +18,22 @@ limitations under the License. */ import { ICreateClientOpts } from 'matrix-js-sdk/src/matrix'; -import {MatrixClient} from 'matrix-js-sdk/src/client'; -import {MemoryStore} from 'matrix-js-sdk/src/store/memory'; +import { MatrixClient } from 'matrix-js-sdk/src/client'; +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 { 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'; import Modal from './Modal'; -import {verificationMethods} from 'matrix-js-sdk/src/crypto'; +import { verificationMethods } from 'matrix-js-sdk/src/crypto'; import MatrixClientBackedSettingsHandler from "./settings/handlers/MatrixClientBackedSettingsHandler"; import * as StorageManager from './utils/StorageManager'; import IdentityAuthClient from './IdentityAuthClient'; import { crossSigningCallbacks, tryToUnlockSecretStorageWithDehydrationKey } from './SecurityManager'; -import {SHOW_QR_CODE_METHOD} from "matrix-js-sdk/src/crypto/verification/QRCode"; +import { SHOW_QR_CODE_METHOD } from "matrix-js-sdk/src/crypto/verification/QRCode"; import SecurityCustomisations from "./customisations/Security"; export interface IMatrixClientCreds { diff --git a/src/Modal.tsx b/src/Modal.tsx index 2f2d5a2d52..0b0e621e89 100644 --- a/src/Modal.tsx +++ b/src/Modal.tsx @@ -15,14 +15,13 @@ See the License for the specific language governing permissions and limitations under the License. */ - import React from 'react'; import ReactDOM from 'react-dom'; import classNames from 'classnames'; import Analytics from './Analytics'; import dis from './dispatcher/dispatcher'; -import {defer} from './utils/promise'; +import { defer } from './utils/promise'; import AsyncWrapper from './AsyncWrapper'; const DIALOG_CONTAINER_ID = "mx_Dialog_Container"; @@ -193,7 +192,7 @@ export class ModalManager { modal.elem = ; modal.close = closeDialog; - return {modal, closeDialog, onFinishedProm}; + return { modal, closeDialog, onFinishedProm }; } private getCloseFn( @@ -282,7 +281,7 @@ export class ModalManager { isStaticModal = false, options: IOptions = {}, ): IHandle { - const {modal, closeDialog, onFinishedProm} = this.buildModal(prom, props, className, options); + const { modal, closeDialog, onFinishedProm } = this.buildModal(prom, props, className, options); if (isPriorityModal) { // XXX: This is destructive this.priorityModal = modal; @@ -305,7 +304,7 @@ export class ModalManager { props?: IProps, className?: string, ): IHandle { - const {modal, closeDialog, onFinishedProm} = this.buildModal(prom, props, className, {}); + const { modal, closeDialog, onFinishedProm } = this.buildModal(prom, props, className, {}); this.modals.push(modal); this.reRender(); diff --git a/src/Notifier.ts b/src/Notifier.ts index 2afc7d9901..2335dc59ac 100644 --- a/src/Notifier.ts +++ b/src/Notifier.ts @@ -32,11 +32,11 @@ import { _t } from './languageHandler'; import Modal from './Modal'; import SettingsStore from "./settings/SettingsStore"; import { hideToast as hideNotificationsToast } from "./toasts/DesktopNotificationsToast"; -import {SettingLevel} from "./settings/SettingLevel"; -import {isPushNotifyDisabled} from "./settings/controllers/NotificationControllers"; +import { SettingLevel } from "./settings/SettingLevel"; +import { isPushNotifyDisabled } from "./settings/controllers/NotificationControllers"; import RoomViewStore from "./stores/RoomViewStore"; import UserActivity from "./UserActivity"; -import {mediaFromMxc} from "./customisations/Media"; +import { mediaFromMxc } from "./customisations/Media"; /* * Dispatches: diff --git a/src/Presence.ts b/src/Presence.ts index 8f2e127cb4..af35060363 100644 --- a/src/Presence.ts +++ b/src/Presence.ts @@ -16,10 +16,10 @@ See the License for the specific language governing permissions and limitations under the License. */ -import {MatrixClientPeg} from "./MatrixClientPeg"; +import { MatrixClientPeg } from "./MatrixClientPeg"; import dis from "./dispatcher/dispatcher"; import Timer from './utils/Timer'; -import {ActionPayload} from "./dispatcher/payloads"; +import { ActionPayload } from "./dispatcher/payloads"; // Time in ms after that a user is considered as unavailable/away const UNAVAILABLE_TIME_MS = 3 * 60 * 1000; // 3 mins @@ -78,7 +78,7 @@ class Presence { this.setState(State.Online); this.unavailableTimer.restart(); } - } + }; /** * Set the presence state. @@ -98,7 +98,7 @@ class Presence { } try { - await MatrixClientPeg.get().setPresence({presence: this.state}); + await MatrixClientPeg.get().setPresence({ presence: this.state }); console.info("Presence:", newState); } catch (err) { console.error("Failed to set presence:", err); diff --git a/src/Registration.js b/src/Registration.js index 0df2ec3eb3..70dcd38454 100644 --- a/src/Registration.js +++ b/src/Registration.js @@ -53,16 +53,16 @@ export async function startAnyRegistrationFlow(options) { extraButtons: [ , ], onFinished: (proceed) => { if (proceed) { - dis.dispatch({action: 'start_registration', screenAfterLogin: options.screen_after}); + dis.dispatch({ action: 'start_registration', screenAfterLogin: options.screen_after }); } else if (options.go_home_on_cancel) { - dis.dispatch({action: 'view_home_page'}); + dis.dispatch({ action: 'view_home_page' }); } else if (options.go_welcome_on_cancel) { - dis.dispatch({action: 'view_welcome_page'}); + dis.dispatch({ action: 'view_welcome_page' }); } }, }); diff --git a/src/Roles.ts b/src/Roles.ts index b4be97fdce..ae0d316d30 100644 --- a/src/Roles.ts +++ b/src/Roles.ts @@ -31,6 +31,6 @@ export function textualPowerLevel(level: number, usersDefault: number): string { if (LEVEL_ROLE_MAP[level]) { return LEVEL_ROLE_MAP[level]; } else { - return _t("Custom (%(level)s)", {level}); + return _t("Custom (%(level)s)", { level }); } } diff --git a/src/RoomInvite.tsx b/src/RoomInvite.tsx index c86f832b90..c7f377b6e8 100644 --- a/src/RoomInvite.tsx +++ b/src/RoomInvite.tsx @@ -53,7 +53,7 @@ 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}, + 'Start DM', '', InviteDialog, { kind: KIND_DM, initialText }, /*className=*/null, /*isPriority=*/false, /*isStatic=*/true, ); } @@ -72,7 +72,7 @@ export function showRoomInviteDialog(roomId: string, initialText = ""): void { export function showCommunityRoomInviteDialog(roomId: string, communityName: string): void { Modal.createTrackedDialog( - 'Invite Users to Community', '', CommunityPrototypeInviteDialog, {communityName, roomId}, + 'Invite Users to Community', '', CommunityPrototypeInviteDialog, { communityName, roomId }, /*className=*/null, /*isPriority=*/false, /*isStatic=*/true, ); } @@ -133,7 +133,7 @@ export function showAnyInviteErrors( // 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}), + title: _t("Failed to invite users to the room:", { roomName: room.name }), description: inviter.getErrorText(failedUsers[0]), }); return false; diff --git a/src/RoomNotifs.js b/src/RoomNotifs.js index 600655f635..5d109094af 100644 --- a/src/RoomNotifs.js +++ b/src/RoomNotifs.js @@ -15,8 +15,8 @@ See the License for the specific language governing permissions and limitations under the License. */ -import {MatrixClientPeg} from './MatrixClientPeg'; -import {PushProcessor} from 'matrix-js-sdk/src/pushprocessor'; +import { MatrixClientPeg } from './MatrixClientPeg'; +import { PushProcessor } from 'matrix-js-sdk/src/pushprocessor'; export const ALL_MESSAGES_LOUD = 'all_messages_loud'; export const ALL_MESSAGES = 'all_messages'; @@ -52,7 +52,7 @@ export function aggregateNotificationCount(rooms) { } } return result; - }, {count: 0, highlight: false}); + }, { count: 0, highlight: false }); } export function getRoomHasBadge(room) { diff --git a/src/Rooms.ts b/src/Rooms.ts index 19d1c9ee05..4d1682660b 100644 --- a/src/Rooms.ts +++ b/src/Rooms.ts @@ -104,7 +104,6 @@ export function setDMRoom(roomId: string, userId: string): Promise { dmRoomMap[userId] = roomList; } - return MatrixClientPeg.get().setAccountData('m.direct', dmRoomMap); } diff --git a/src/ScalarAuthClient.ts b/src/ScalarAuthClient.ts index a09c3494a8..86dd4b7a0f 100644 --- a/src/ScalarAuthClient.ts +++ b/src/ScalarAuthClient.ts @@ -17,12 +17,12 @@ limitations under the License. import url from 'url'; import SettingsStore from "./settings/SettingsStore"; import { Service, startTermsFlow, TermsInteractionCallback, TermsNotSignedError } from './Terms'; -import {MatrixClientPeg} from "./MatrixClientPeg"; +import { MatrixClientPeg } from "./MatrixClientPeg"; import request from "browser-request"; import SdkConfig from "./SdkConfig"; -import {WidgetType} from "./widgets/WidgetType"; -import {SERVICE_TYPES} from "matrix-js-sdk/src/service-types"; +import { WidgetType } from "./widgets/WidgetType"; +import { SERVICE_TYPES } from "matrix-js-sdk/src/service-types"; import { Room } from "matrix-js-sdk/src/models/room"; // The version of the integration manager API we're intending to work with @@ -109,7 +109,7 @@ export default class ScalarAuthClient { request({ method: "GET", uri: url, - qs: {scalar_token: token, v: imApiVersion}, + qs: { scalar_token: token, v: imApiVersion }, json: true, }, (err, response, body) => { if (err) { @@ -189,7 +189,7 @@ export default class ScalarAuthClient { request({ method: 'POST', uri: scalarRestUrl + '/register', - qs: {v: imApiVersion}, + qs: { v: imApiVersion }, body: openidTokenObject, json: true, }, (err, response, body) => { diff --git a/src/ScalarMessaging.js b/src/ScalarMessaging.js index 3f75b3788c..600241bc06 100644 --- a/src/ScalarMessaging.js +++ b/src/ScalarMessaging.js @@ -208,7 +208,6 @@ Example: ] } - membership_state AND bot_options -------------------------------- Get the content of the "m.room.member" or "m.room.bot.options" state event respectively. @@ -236,15 +235,15 @@ Example: } */ -import {MatrixClientPeg} from './MatrixClientPeg'; +import { MatrixClientPeg } from './MatrixClientPeg'; import { MatrixEvent } from 'matrix-js-sdk/src/models/event'; import dis from './dispatcher/dispatcher'; import WidgetUtils from './utils/WidgetUtils'; import RoomViewStore from './stores/RoomViewStore'; import { _t } from './languageHandler'; -import {IntegrationManagers} from "./integrations/IntegrationManagers"; -import {WidgetType} from "./widgets/WidgetType"; -import {objectClone} from "./utils/objects"; +import { IntegrationManagers } from "./integrations/IntegrationManagers"; +import { WidgetType } from "./widgets/WidgetType"; +import { objectClone } from "./utils/objects"; function sendResponse(event, res) { const data = objectClone(event.data); @@ -608,7 +607,7 @@ const onMessage = function(event) { } if (roomId !== RoomViewStore.getRoomId()) { - sendError(event, _t('Room %(roomId)s not visible', {roomId: roomId})); + sendError(event, _t('Room %(roomId)s not visible', { roomId: roomId })); return; } diff --git a/src/Searching.js b/src/Searching.js index 596dd2f3d4..d0666b1760 100644 --- a/src/Searching.js +++ b/src/Searching.js @@ -15,7 +15,7 @@ limitations under the License. */ import EventIndexPeg from "./indexing/EventIndexPeg"; -import {MatrixClientPeg} from "./MatrixClientPeg"; +import { MatrixClientPeg } from "./MatrixClientPeg"; const SEARCH_LIMIT = 10; @@ -43,7 +43,7 @@ async function serverSideSearch(term, roomId = undefined) { }, }; - const response = await client.search({body: body}); + const response = await client.search({ body: body }); const result = { response: response, @@ -498,7 +498,7 @@ async function combinedPagination(searchResult) { // Fetch events from the server if we have a token for it and if it's the // local indexes turn or the local index has exhausted its results. if (searchResult.serverSideNextBatch && (oldestEventFrom === "local" || !searchArgs.next_batch)) { - const body = {body: searchResult._query, next_batch: searchResult.serverSideNextBatch}; + const body = { body: searchResult._query, next_batch: searchResult.serverSideNextBatch }; serverSideResult = await client.search(body); } diff --git a/src/SecurityManager.ts b/src/SecurityManager.ts index 1ba0d6439b..6b372bba28 100644 --- a/src/SecurityManager.ts +++ b/src/SecurityManager.ts @@ -18,7 +18,7 @@ import { ICryptoCallbacks, ISecretStorageKeyInfo } from 'matrix-js-sdk/src/matri import { MatrixClient } from 'matrix-js-sdk/src/client'; import Modal from './Modal'; import * as sdk from './index'; -import {MatrixClientPeg} from './MatrixClientPeg'; +import { MatrixClientPeg } from './MatrixClientPeg'; import { deriveKey } from 'matrix-js-sdk/src/crypto/key_passphrase'; import { decodeRecoveryKey } from 'matrix-js-sdk/src/crypto/recoverykey'; import { _t } from './languageHandler'; @@ -135,7 +135,7 @@ async function getSecretStorageKey( const keyFromCustomisations = SecurityCustomisations.getSecretStorageKey?.(); if (keyFromCustomisations) { - console.log("Using key from security customisations (secret storage)") + console.log("Using key from security customisations (secret storage)"); cacheSecretStorageKey(keyId, keyInfo, keyFromCustomisations); return [keyId, keyFromCustomisations]; } @@ -185,7 +185,7 @@ export async function getDehydrationKey( ): Promise { const keyFromCustomisations = SecurityCustomisations.getSecretStorageKey?.(); if (keyFromCustomisations) { - console.log("Using key from security customisations (dehydration)") + console.log("Using key from security customisations (dehydration)"); return keyFromCustomisations; } @@ -224,7 +224,7 @@ export async function getDehydrationKey( const key = await inputToKey(input); // need to copy the key because rehydration (unpickling) will clobber it - dehydrationCache = {key: new Uint8Array(key), keyInfo}; + dehydrationCache = { key: new Uint8Array(key), keyInfo }; return key; } diff --git a/src/SendHistoryManager.ts b/src/SendHistoryManager.ts index e9268ad642..eeba643d81 100644 --- a/src/SendHistoryManager.ts +++ b/src/SendHistoryManager.ts @@ -1,4 +1,3 @@ -//@flow /* Copyright 2017 Aviral Dasgupta @@ -15,10 +14,10 @@ See the License for the specific language governing permissions and limitations under the License. */ -import {clamp} from "lodash"; -import {MatrixEvent} from "matrix-js-sdk/src/models/event"; +import { clamp } from "lodash"; +import { MatrixEvent } from "matrix-js-sdk/src/models/event"; -import {SerializedPart} from "./editor/parts"; +import { SerializedPart } from "./editor/parts"; import EditorModel from "./editor/model"; interface IHistoryItem { diff --git a/src/SlashCommands.tsx b/src/SlashCommands.tsx index bd2133f3d9..0f38c5fffc 100644 --- a/src/SlashCommands.tsx +++ b/src/SlashCommands.tsx @@ -21,21 +21,21 @@ import * as React from 'react'; import { User } from "matrix-js-sdk/src/models/user"; import * as ContentHelpers from 'matrix-js-sdk/src/content-helpers'; -import {MatrixClientPeg} from './MatrixClientPeg'; +import { MatrixClientPeg } from './MatrixClientPeg'; import dis from './dispatcher/dispatcher'; import * as sdk from './index'; -import {_t, _td} from './languageHandler'; +import { _t, _td } from './languageHandler'; import Modal from './Modal'; import MultiInviter from './utils/MultiInviter'; import { linkifyAndSanitizeHtml } from './HtmlUtils'; import QuestionDialog from "./components/views/dialogs/QuestionDialog"; import WidgetUtils from "./utils/WidgetUtils"; -import {textToHtmlRainbow} from "./utils/colour"; +import { textToHtmlRainbow } from "./utils/colour"; import { getAddressType } from './UserAddress'; import { abbreviateUrl } from './utils/UrlUtils'; import { getDefaultIdentityServerUrl, useDefaultIdentityServer } from './utils/IdentityServerUtils'; -import {isPermalinkHost, parsePermalink} from "./utils/permalinks/Permalinks"; -import {inviteUsersToRoom} from "./RoomInvite"; +import { isPermalinkHost, parsePermalink } from "./utils/permalinks/Permalinks"; +import { inviteUsersToRoom } from "./RoomInvite"; import { WidgetType } from "./widgets/WidgetType"; import { Jitsi } from "./widgets/Jitsi"; import { parseFragment as parseHtml, Element as ChildElement } from "parse5"; @@ -46,10 +46,10 @@ import { Action } from "./dispatcher/actions"; import { EffectiveMembership, getEffectiveMembership, leaveRoomBehaviour } from "./utils/membership"; import SdkConfig from "./SdkConfig"; import SettingsStore from "./settings/SettingsStore"; -import {UIFeature} from "./settings/UIFeature"; -import {CHAT_EFFECTS} from "./effects" +import { UIFeature } from "./settings/UIFeature"; +import { CHAT_EFFECTS } from "./effects"; import CallHandler from "./CallHandler"; -import {guessAndSetDMRoom} from "./Rooms"; +import { guessAndSetDMRoom } from "./Rooms"; // XXX: workaround for https://github.com/microsoft/TypeScript/issues/31816 interface HTMLInputEvent extends Event { @@ -143,11 +143,11 @@ export class Command { } function reject(error) { - return {error}; + return { error }; } function success(promise?: Promise) { - return {promise}; + return { promise }; } function successSync(value: any) { @@ -271,8 +271,8 @@ export const Commands = [ const RoomUpgradeWarningDialog = sdk.getComponent("dialogs.RoomUpgradeWarningDialog"); - const {finished} = Modal.createTrackedDialog('Slash Commands', 'upgrade room confirmation', - RoomUpgradeWarningDialog, {roomId: roomId, targetVersion: args}, /*className=*/null, + const { finished } = Modal.createTrackedDialog('Slash Commands', 'upgrade room confirmation', + RoomUpgradeWarningDialog, { roomId: roomId, targetVersion: args }, /*className=*/null, /*isPriority=*/false, /*isStatic=*/true); return success(finished.then(async ([resp]) => { @@ -288,7 +288,7 @@ export const Commands = [ if (resp.invite) { checkForUpgradeFn = async (newRoom) => { // The upgradePromise should be done by the time we await it here. - const {replacement_room: newRoomId} = await upgradePromise; + const { replacement_room: newRoomId } = await upgradePromise; if (newRoom.roomId !== newRoomId) return; const toInvite = [ @@ -370,7 +370,7 @@ export const Commands = [ return success(promise.then((url) => { if (!url) return; - return MatrixClientPeg.get().sendStateEvent(roomId, 'm.room.avatar', {url}, ''); + return MatrixClientPeg.get().sendStateEvent(roomId, 'm.room.avatar', { url }, ''); })); }, category: CommandCategories.actions, @@ -741,7 +741,7 @@ export const Commands = [ Modal.createTrackedDialog('Slash Commands', 'User ignored', InfoDialog, { title: _t('Ignored user'), description:
-

{ _t('You are now ignoring %(userId)s', {userId}) }

+

{ _t('You are now ignoring %(userId)s', { userId }) }

, }); }), @@ -772,7 +772,7 @@ export const Commands = [ Modal.createTrackedDialog('Slash Commands', 'User unignored', InfoDialog, { title: _t('Unignored user'), description:
-

{ _t('You are no longer ignoring %(userId)s', {userId}) }

+

{ _t('You are no longer ignoring %(userId)s', { userId }) }

, }); }), @@ -839,7 +839,7 @@ export const Commands = [ description: _td('Opens the Developer Tools dialog'), runFn: function(roomId) { const DevtoolsDialog = sdk.getComponent('dialogs.DevtoolsDialog'); - Modal.createDialog(DevtoolsDialog, {roomId}); + Modal.createDialog(DevtoolsDialog, { roomId }); return success(); }, category: CommandCategories.advanced, @@ -951,7 +951,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 }) }

, @@ -1172,11 +1172,11 @@ export const Commands = [ }; MatrixClientPeg.get().sendMessage(roomId, content); } - dis.dispatch({action: `effects.${effect.command}`}); + dis.dispatch({ action: `effects.${effect.command}` }); })()); }, category: CommandCategories.effects, - }) + }); }), ]; @@ -1205,7 +1205,7 @@ export function parseCommandString(input: string) { cmd = input; } - return {cmd, args}; + return { cmd, args }; } /** @@ -1217,7 +1217,7 @@ export function parseCommandString(input: string) { * Returns null if the input didn't match a command. */ export function getCommand(input: string) { - const {cmd, args} = parseCommandString(input); + const { cmd, args } = parseCommandString(input); if (CommandMap.has(cmd) && CommandMap.get(cmd).isEnabled()) { return { diff --git a/src/Terms.ts b/src/Terms.ts index a6ea40a6e8..3859cc1c73 100644 --- a/src/Terms.ts +++ b/src/Terms.ts @@ -16,7 +16,7 @@ limitations under the License. import classNames from 'classnames'; -import {MatrixClientPeg} from './MatrixClientPeg'; +import { MatrixClientPeg } from './MatrixClientPeg'; import * as sdk from '.'; import Modal from './Modal'; @@ -117,7 +117,7 @@ export async function startTermsFlow( // but that is not a thing the API supports, so probably best to just show // things they've not agreed to yet. const unagreedPoliciesAndServicePairs = []; - for (const {service, policies} of policiesAndServicePairs) { + for (const { service, policies } of policiesAndServicePairs) { const unagreedPolicies = {}; for (const [policyName, policy] of Object.entries(policies)) { let policyAgreed = false; @@ -131,7 +131,7 @@ export async function startTermsFlow( if (!policyAgreed) unagreedPolicies[policyName] = policy; } if (Object.keys(unagreedPolicies).length > 0) { - unagreedPoliciesAndServicePairs.push({service, policies: unagreedPolicies}); + unagreedPoliciesAndServicePairs.push({ service, policies: unagreedPolicies }); } } @@ -148,7 +148,7 @@ export async function startTermsFlow( // We only ever add to the set of URLs, so if anything has changed then we'd see a different length if (agreedUrlSet.size !== numAcceptedBeforeAgreement) { - const newAcceptedTerms = {accepted: Array.from(agreedUrlSet)}; + const newAcceptedTerms = { accepted: Array.from(agreedUrlSet) }; await MatrixClientPeg.get().setAccountData('m.accepted_terms', newAcceptedTerms); } diff --git a/src/TextForEvent.tsx b/src/TextForEvent.tsx index ac09060e22..32e4a2d1fa 100644 --- a/src/TextForEvent.tsx +++ b/src/TextForEvent.tsx @@ -15,13 +15,13 @@ limitations under the License. */ import React from 'react'; -import {MatrixClientPeg} from './MatrixClientPeg'; +import { MatrixClientPeg } from './MatrixClientPeg'; import { _t } from './languageHandler'; import * as Roles from './Roles'; import { isValid3pidInvite } from "./RoomInvite"; import SettingsStore from "./settings/SettingsStore"; -import {ALL_RULE_TYPES, ROOM_RULE_TYPES, SERVER_RULE_TYPES, USER_RULE_TYPES} from "./mjolnir/BanList"; -import {WIDGET_LAYOUT_EVENT_TYPE} from "./stores/widgets/WidgetLayoutStore"; +import { ALL_RULE_TYPES, ROOM_RULE_TYPES, SERVER_RULE_TYPES, USER_RULE_TYPES } from "./mjolnir/BanList"; +import { WIDGET_LAYOUT_EVENT_TYPE } from "./stores/widgets/WidgetLayoutStore"; import { RightPanelPhases } from './stores/RightPanelStorePhases'; import { Action } from './dispatcher/actions'; import defaultDispatcher from './dispatcher/dispatcher'; @@ -112,7 +112,7 @@ function textForMemberEvent(ev): () => string | null { targetName, reason, }) - : _t('%(senderName)s withdrew %(targetName)s\'s invitation', { senderName, targetName }) + : _t('%(senderName)s withdrew %(targetName)s\'s invitation', { senderName, targetName }); } else if (prevContent.membership === "join") { return () => reason ? _t('%(senderName)s kicked %(targetName)s: %(reason)s', { @@ -144,7 +144,7 @@ function textForRoomNameEvent(ev): () => string | null { const senderDisplayName = ev.sender && ev.sender.name ? ev.sender.name : ev.getSender(); if (!ev.getContent().name || ev.getContent().name.trim().length === 0) { - return () => _t('%(senderDisplayName)s removed the room name.', {senderDisplayName}); + return () => _t('%(senderDisplayName)s removed the room name.', { senderDisplayName }); } if (ev.getPrevContent().name) { return () => _t('%(senderDisplayName)s changed the room name from %(oldRoomName)s to %(newRoomName)s.', { @@ -161,7 +161,7 @@ function textForRoomNameEvent(ev): () => string | null { function textForTombstoneEvent(ev): () => string | null { const senderDisplayName = ev.sender && ev.sender.name ? ev.sender.name : ev.getSender(); - return () => _t('%(senderDisplayName)s upgraded this room.', {senderDisplayName}); + return () => _t('%(senderDisplayName)s upgraded this room.', { senderDisplayName }); } function textForJoinRulesEvent(ev): () => string | null { @@ -188,9 +188,9 @@ function textForGuestAccessEvent(ev): () => string | null { const senderDisplayName = ev.sender && ev.sender.name ? ev.sender.name : ev.getSender(); switch (ev.getContent().guest_access) { case "can_join": - return () => _t('%(senderDisplayName)s has allowed guests to join the room.', {senderDisplayName}); + return () => _t('%(senderDisplayName)s has allowed guests to join the room.', { senderDisplayName }); case "forbidden": - return () => _t('%(senderDisplayName)s has prevented guests from joining the room.', {senderDisplayName}); + return () => _t('%(senderDisplayName)s has prevented guests from joining the room.', { senderDisplayName }); default: // There's no other options we can expect, however just for safety's sake we'll do this. return () => _t('%(senderDisplayName)s changed guest access to %(rule)s', { @@ -242,9 +242,9 @@ function textForServerACLEvent(ev): () => string | null { let getText = null; if (prev.deny.length === 0 && prev.allow.length === 0) { - getText = () => _t("%(senderDisplayName)s set the server ACLs for this room.", {senderDisplayName}); + getText = () => _t("%(senderDisplayName)s set the server ACLs for this room.", { senderDisplayName }); } else { - getText = () => _t("%(senderDisplayName)s changed the server ACLs for this room.", {senderDisplayName}); + getText = () => _t("%(senderDisplayName)s changed the server ACLs for this room.", { senderDisplayName }); } if (!Array.isArray(current.allow)) { @@ -340,7 +340,7 @@ function textForCallAnswerEvent(event): () => string | null { return () => { const senderName = event.sender ? event.sender.name : _t('Someone'); const supported = MatrixClientPeg.get().supportsVoip() ? '' : _t('(not supported by this browser)'); - return _t('%(senderName)s answered the call.', {senderName}) + ' ' + supported; + return _t('%(senderName)s answered the call.', { senderName }) + ' ' + supported; }; } @@ -375,16 +375,16 @@ function textForCallHangupEvent(event): () => string | null { // Also the correct hangup code as of VoIP v1 (with underscore) getReason = () => ''; } else { - getReason = () => _t('(unknown failure: %(reason)s)', {reason: eventContent.reason}); + getReason = () => _t('(unknown failure: %(reason)s)', { reason: eventContent.reason }); } } - return () => _t('%(senderName)s ended the call.', {senderName: getSenderName()}) + ' ' + getReason(); + return () => _t('%(senderName)s ended the call.', { senderName: getSenderName() }) + ' ' + getReason(); } function textForCallRejectEvent(event): () => string | null { return () => { const senderName = event.sender ? event.sender.name : _t('Someone'); - return _t('%(senderName)s declined the call.', {senderName}); + return _t('%(senderName)s declined the call.', { senderName }); }; } @@ -441,14 +441,14 @@ function textForHistoryVisibilityEvent(event): () => string | null { switch (event.getContent().history_visibility) { case 'invited': return () => _t('%(senderName)s made future room history visible to all room members, ' - + 'from the point they are invited.', {senderName}); + + 'from the point they are invited.', { senderName }); case 'joined': return () => _t('%(senderName)s made future room history visible to all room members, ' - + 'from the point they joined.', {senderName}); + + 'from the point they joined.', { senderName }); case 'shared': - return () => _t('%(senderName)s made future room history visible to all room members.', {senderName}); + return () => _t('%(senderName)s made future room history visible to all room members.', { senderName }); case 'world_readable': - return () => _t('%(senderName)s made future room history visible to anyone.', {senderName}); + return () => _t('%(senderName)s made future room history visible to anyone.', { senderName }); default: return () => _t('%(senderName)s made future room history visible to unknown (%(visibility)s).', { senderName, @@ -509,7 +509,7 @@ const onPinnedMessagesClick = (): void => { phase: RightPanelPhases.PinnedMessages, allowClose: false, }); -} +}; function textForPinnedEvent(event: MatrixEvent, allowJSX: boolean): () => string | JSX.Element | null { if (!SettingsStore.getValue("feature_pinning")) return null; @@ -534,8 +534,8 @@ function textForPinnedEvent(event: MatrixEvent, allowJSX: boolean): () => string function textForWidgetEvent(event): () => string | null { const senderName = event.getSender(); - const {name: prevName, type: prevType, url: prevUrl} = event.getPrevContent(); - const {name, type, url} = event.getContent() || {}; + const { name: prevName, type: prevType, url: prevUrl } = event.getPrevContent(); + const { name, type, url } = event.getContent() || {}; let widgetName = name || prevName || type || prevType || ''; // Apply sentence case to widget name @@ -564,68 +564,68 @@ function textForWidgetEvent(event): () => string | null { function textForWidgetLayoutEvent(event): () => string | null { const senderName = event.sender?.name || event.getSender(); - return () => _t("%(senderName)s has updated the widget layout", {senderName}); + return () => _t("%(senderName)s has updated the widget layout", { senderName }); } function textForMjolnirEvent(event): () => string | null { const senderName = event.getSender(); - const {entity: prevEntity} = event.getPrevContent(); - const {entity, recommendation, reason} = event.getContent(); + const { entity: prevEntity } = event.getPrevContent(); + const { entity, recommendation, reason } = event.getContent(); // Rule removed if (!entity) { if (USER_RULE_TYPES.includes(event.getType())) { return () => _t("%(senderName)s removed the rule banning users matching %(glob)s", - {senderName, glob: prevEntity}); + { senderName, glob: prevEntity }); } else if (ROOM_RULE_TYPES.includes(event.getType())) { return () => _t("%(senderName)s removed the rule banning rooms matching %(glob)s", - {senderName, glob: prevEntity}); + { senderName, glob: prevEntity }); } else if (SERVER_RULE_TYPES.includes(event.getType())) { return () => _t("%(senderName)s removed the rule banning servers matching %(glob)s", - {senderName, glob: prevEntity}); + { senderName, glob: prevEntity }); } // Unknown type. We'll say something, but we shouldn't end up here. - return () => _t("%(senderName)s removed a ban rule matching %(glob)s", {senderName, glob: prevEntity}); + return () => _t("%(senderName)s removed a ban rule matching %(glob)s", { senderName, glob: prevEntity }); } // Invalid rule - if (!recommendation || !reason) return () => _t(`%(senderName)s updated an invalid ban rule`, {senderName}); + if (!recommendation || !reason) return () => _t(`%(senderName)s updated an invalid ban rule`, { senderName }); // Rule updated if (entity === prevEntity) { if (USER_RULE_TYPES.includes(event.getType())) { return () => _t("%(senderName)s updated the rule banning users matching %(glob)s for %(reason)s", - {senderName, glob: entity, reason}); + { senderName, glob: entity, reason }); } else if (ROOM_RULE_TYPES.includes(event.getType())) { return () => _t("%(senderName)s updated the rule banning rooms matching %(glob)s for %(reason)s", - {senderName, glob: entity, reason}); + { senderName, glob: entity, reason }); } else if (SERVER_RULE_TYPES.includes(event.getType())) { return () => _t("%(senderName)s updated the rule banning servers matching %(glob)s for %(reason)s", - {senderName, glob: entity, reason}); + { senderName, glob: entity, reason }); } // Unknown type. We'll say something but we shouldn't end up here. return () => _t("%(senderName)s updated a ban rule matching %(glob)s for %(reason)s", - {senderName, glob: entity, reason}); + { senderName, glob: entity, reason }); } // New rule if (!prevEntity) { if (USER_RULE_TYPES.includes(event.getType())) { return () => _t("%(senderName)s created a rule banning users matching %(glob)s for %(reason)s", - {senderName, glob: entity, reason}); + { senderName, glob: entity, reason }); } else if (ROOM_RULE_TYPES.includes(event.getType())) { return () => _t("%(senderName)s created a rule banning rooms matching %(glob)s for %(reason)s", - {senderName, glob: entity, reason}); + { senderName, glob: entity, reason }); } else if (SERVER_RULE_TYPES.includes(event.getType())) { return () => _t("%(senderName)s created a rule banning servers matching %(glob)s for %(reason)s", - {senderName, glob: entity, reason}); + { senderName, glob: entity, reason }); } // Unknown type. We'll say something but we shouldn't end up here. return () => _t("%(senderName)s created a ban rule matching %(glob)s for %(reason)s", - {senderName, glob: entity, reason}); + { senderName, glob: entity, reason }); } // else the entity !== prevEntity - count as a removal & add @@ -633,25 +633,25 @@ function textForMjolnirEvent(event): () => string | null { return () => _t( "%(senderName)s changed a rule that was banning users matching %(oldGlob)s to matching " + "%(newGlob)s for %(reason)s", - {senderName, oldGlob: prevEntity, newGlob: entity, reason}, + { senderName, oldGlob: prevEntity, newGlob: entity, reason }, ); } else if (ROOM_RULE_TYPES.includes(event.getType())) { return () => _t( "%(senderName)s changed a rule that was banning rooms matching %(oldGlob)s to matching " + "%(newGlob)s for %(reason)s", - {senderName, oldGlob: prevEntity, newGlob: entity, reason}, + { senderName, oldGlob: prevEntity, newGlob: entity, reason }, ); } else if (SERVER_RULE_TYPES.includes(event.getType())) { return () => _t( "%(senderName)s changed a rule that was banning servers matching %(oldGlob)s to matching " + "%(newGlob)s for %(reason)s", - {senderName, oldGlob: prevEntity, newGlob: entity, reason}, + { senderName, oldGlob: prevEntity, newGlob: entity, reason }, ); } // Unknown type. We'll say something but we shouldn't end up here. return () => _t("%(senderName)s updated a ban rule that was matching %(oldGlob)s to matching %(newGlob)s " + - "for %(reason)s", {senderName, oldGlob: prevEntity, newGlob: entity, reason}); + "for %(reason)s", { senderName, oldGlob: prevEntity, newGlob: entity, reason }); } interface IHandlers { diff --git a/src/Tinter.js b/src/Tinter.js deleted file mode 100644 index ca5a460e16..0000000000 --- a/src/Tinter.js +++ /dev/null @@ -1,458 +0,0 @@ -/* -Copyright 2015 OpenMarket Ltd -Copyright 2017 New Vector Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -const DEBUG = 0; - -// utility to turn #rrggbb or rgb(r,g,b) into [red,green,blue] -function colorToRgb(color) { - if (!color) { - return [0, 0, 0]; - } - - if (color[0] === '#') { - color = color.slice(1); - if (color.length === 3) { - color = color[0] + color[0] + - color[1] + color[1] + - color[2] + color[2]; - } - const val = parseInt(color, 16); - const r = (val >> 16) & 255; - const g = (val >> 8) & 255; - const b = val & 255; - return [r, g, b]; - } else { - const match = color.match(/rgb\((.*?),(.*?),(.*?)\)/); - if (match) { - return [ - parseInt(match[1]), - parseInt(match[2]), - parseInt(match[3]), - ]; - } - } - return [0, 0, 0]; -} - -// utility to turn [red,green,blue] into #rrggbb -function rgbToColor(rgb) { - const val = (rgb[0] << 16) | (rgb[1] << 8) | rgb[2]; - return '#' + (0x1000000 + val).toString(16).slice(1); -} - -class Tinter { - constructor() { - // The default colour keys to be replaced as referred to in CSS - // (should be overridden by .mx_theme_accentColor and .mx_theme_secondaryAccentColor) - this.keyRgb = [ - "rgb(118, 207, 166)", // Vector Green - "rgb(234, 245, 240)", // Vector Light Green - "rgb(211, 239, 225)", // roomsublist-label-bg-color (20% Green overlaid on Light Green) - ]; - - // Some algebra workings for calculating the tint % of Vector Green & Light Green - // x * 118 + (1 - x) * 255 = 234 - // x * 118 + 255 - 255 * x = 234 - // x * 118 - x * 255 = 234 - 255 - // (255 - 118) x = 255 - 234 - // x = (255 - 234) / (255 - 118) = 0.16 - - // The colour keys to be replaced as referred to in SVGs - this.keyHex = [ - "#76CFA6", // Vector Green - "#EAF5F0", // Vector Light Green - "#D3EFE1", // roomsublist-label-bg-color (20% Green overlaid on Light Green) - "#FFFFFF", // white highlights of the SVGs (for switching to dark theme) - "#000000", // black lowlights of the SVGs (for switching to dark theme) - ]; - - // track the replacement colours actually being used - // defaults to our keys. - this.colors = [ - this.keyHex[0], - this.keyHex[1], - this.keyHex[2], - this.keyHex[3], - this.keyHex[4], - ]; - - // track the most current tint request inputs (which may differ from the - // end result stored in this.colors - this.currentTint = [ - undefined, - undefined, - undefined, - undefined, - undefined, - ]; - - this.cssFixups = [ - // { theme: { - // style: a style object that should be fixed up taken from a stylesheet - // attr: name of the attribute to be clobbered, e.g. 'color' - // index: ordinal of primary, secondary or tertiary - // }, - // } - ]; - - // CSS attributes to be fixed up - this.cssAttrs = [ - "color", - "backgroundColor", - "borderColor", - "borderTopColor", - "borderBottomColor", - "borderLeftColor", - ]; - - this.svgAttrs = [ - "fill", - "stroke", - ]; - - // List of functions to call when the tint changes. - this.tintables = []; - - // the currently loaded theme (if any) - this.theme = undefined; - - // whether to force a tint (e.g. after changing theme) - this.forceTint = false; - } - - /** - * Register a callback to fire when the tint changes. - * This is used to rewrite the tintable SVGs with the new tint. - * - * It's not possible to unregister a tintable callback. So this can only be - * used to register a static callback. If a set of tintables will change - * over time then the best bet is to register a single callback for the - * entire set. - * - * To ensure the tintable work happens at least once, it is also called as - * part of registration. - * - * @param {Function} tintable Function to call when the tint changes. - */ - registerTintable(tintable) { - this.tintables.push(tintable); - tintable(); - } - - getKeyRgb() { - return this.keyRgb; - } - - tint(primaryColor, secondaryColor, tertiaryColor) { - return; - // eslint-disable-next-line no-unreachable - this.currentTint[0] = primaryColor; - this.currentTint[1] = secondaryColor; - this.currentTint[2] = tertiaryColor; - - this.calcCssFixups(); - - if (DEBUG) { - console.log("Tinter.tint(" + primaryColor + ", " + - secondaryColor + ", " + - tertiaryColor + ")"); - } - - if (!primaryColor) { - primaryColor = this.keyRgb[0]; - secondaryColor = this.keyRgb[1]; - tertiaryColor = this.keyRgb[2]; - } - - if (!secondaryColor) { - const x = 0.16; // average weighting factor calculated from vector green & light green - const rgb = colorToRgb(primaryColor); - rgb[0] = x * rgb[0] + (1 - x) * 255; - rgb[1] = x * rgb[1] + (1 - x) * 255; - rgb[2] = x * rgb[2] + (1 - x) * 255; - secondaryColor = rgbToColor(rgb); - } - - if (!tertiaryColor) { - const x = 0.19; - const rgb1 = colorToRgb(primaryColor); - const rgb2 = colorToRgb(secondaryColor); - rgb1[0] = x * rgb1[0] + (1 - x) * rgb2[0]; - rgb1[1] = x * rgb1[1] + (1 - x) * rgb2[1]; - rgb1[2] = x * rgb1[2] + (1 - x) * rgb2[2]; - tertiaryColor = rgbToColor(rgb1); - } - - if (this.forceTint == false && - this.colors[0] === primaryColor && - this.colors[1] === secondaryColor && - this.colors[2] === tertiaryColor) { - return; - } - - this.forceTint = false; - - this.colors[0] = primaryColor; - this.colors[1] = secondaryColor; - this.colors[2] = tertiaryColor; - - if (DEBUG) { - console.log("Tinter.tint final: (" + primaryColor + ", " + - secondaryColor + ", " + - tertiaryColor + ")"); - } - - // go through manually fixing up the stylesheets. - this.applyCssFixups(); - - // tell all the SVGs to go fix themselves up - // we don't do this as a dispatch otherwise it will visually lag - this.tintables.forEach(function(tintable) { - tintable(); - }); - } - - tintSvgWhite(whiteColor) { - this.currentTint[3] = whiteColor; - - if (!whiteColor) { - whiteColor = this.colors[3]; - } - if (this.colors[3] === whiteColor) { - return; - } - this.colors[3] = whiteColor; - this.tintables.forEach(function(tintable) { - tintable(); - }); - } - - tintSvgBlack(blackColor) { - this.currentTint[4] = blackColor; - - if (!blackColor) { - blackColor = this.colors[4]; - } - if (this.colors[4] === blackColor) { - return; - } - this.colors[4] = blackColor; - this.tintables.forEach(function(tintable) { - tintable(); - }); - } - - - setTheme(theme) { - this.theme = theme; - - // update keyRgb from the current theme CSS itself, if it defines it - if (document.getElementById('mx_theme_accentColor')) { - this.keyRgb[0] = window.getComputedStyle( - document.getElementById('mx_theme_accentColor')).color; - } - if (document.getElementById('mx_theme_secondaryAccentColor')) { - this.keyRgb[1] = window.getComputedStyle( - document.getElementById('mx_theme_secondaryAccentColor')).color; - } - if (document.getElementById('mx_theme_tertiaryAccentColor')) { - this.keyRgb[2] = window.getComputedStyle( - document.getElementById('mx_theme_tertiaryAccentColor')).color; - } - - this.calcCssFixups(); - this.forceTint = true; - - this.tint(this.currentTint[0], this.currentTint[1], this.currentTint[2]); - - if (theme === 'dark') { - // abuse the tinter to change all the SVG's #fff to #2d2d2d - // XXX: obviously this shouldn't be hardcoded here. - this.tintSvgWhite('#2d2d2d'); - this.tintSvgBlack('#dddddd'); - } else { - this.tintSvgWhite('#ffffff'); - this.tintSvgBlack('#000000'); - } - } - - calcCssFixups() { - // cache our fixups - if (this.cssFixups[this.theme]) return; - - if (DEBUG) { - console.debug("calcCssFixups start for " + this.theme + " (checking " + - document.styleSheets.length + - " stylesheets)"); - } - - this.cssFixups[this.theme] = []; - - for (let i = 0; i < document.styleSheets.length; i++) { - const ss = document.styleSheets[i]; - try { - if (!ss) continue; // well done safari >:( - // Chromium apparently sometimes returns null here; unsure why. - // see $14534907369972FRXBx:matrix.org in HQ - // ...ah, it's because there's a third party extension like - // privacybadger inserting its own stylesheet in there with a - // resource:// URI or something which results in a XSS error. - // See also #vector:matrix.org/$145357669685386ebCfr:matrix.org - // ...except some browsers apparently return stylesheets without - // hrefs, which we have no choice but ignore right now - - // XXX seriously? we are hardcoding the name of vector's CSS file in - // here? - // - // Why do we need to limit it to vector's CSS file anyway - if there - // are other CSS files affecting the doc don't we want to apply the - // same transformations to them? - // - // Iterating through the CSS looking for matches to hack on feels - // pretty horrible anyway. And what if the application skin doesn't use - // Vector Green as its primary color? - // --richvdh - - // Yes, tinting assumes that you are using the Element skin for now. - // The right solution will be to move the CSS over to react-sdk. - // And yes, the default assets for the base skin might as well use - // Vector Green as any other colour. - // --matthew - - // stylesheets we don't have permission to access (eg. ones from extensions) have a null - // href and will throw exceptions if we try to access their rules. - if (!ss.href || !ss.href.match(new RegExp('/theme-' + this.theme + '.css$'))) continue; - if (ss.disabled) continue; - if (!ss.cssRules) continue; - - if (DEBUG) console.debug("calcCssFixups checking " + ss.cssRules.length + " rules for " + ss.href); - - for (let j = 0; j < ss.cssRules.length; j++) { - const rule = ss.cssRules[j]; - if (!rule.style) continue; - if (rule.selectorText && rule.selectorText.match(/#mx_theme/)) continue; - for (let k = 0; k < this.cssAttrs.length; k++) { - const attr = this.cssAttrs[k]; - for (let l = 0; l < this.keyRgb.length; l++) { - if (rule.style[attr] === this.keyRgb[l]) { - this.cssFixups[this.theme].push({ - style: rule.style, - attr: attr, - index: l, - }); - } - } - } - } - } catch (e) { - // Catch any random exceptions that happen here: all sorts of things can go - // wrong with this (nulls, SecurityErrors) and mostly it's for other - // stylesheets that we don't want to proces anyway. We should not propagate an - // exception out since this will cause the app to fail to start. - console.log("Failed to calculate CSS fixups for a stylesheet: " + ss.href, e); - } - } - if (DEBUG) { - console.log("calcCssFixups end (" + - this.cssFixups[this.theme].length + - " fixups)"); - } - } - - applyCssFixups() { - if (DEBUG) { - console.log("applyCssFixups start (" + - this.cssFixups[this.theme].length + - " fixups)"); - } - for (let i = 0; i < this.cssFixups[this.theme].length; i++) { - const cssFixup = this.cssFixups[this.theme][i]; - try { - cssFixup.style[cssFixup.attr] = this.colors[cssFixup.index]; - } catch (e) { - // Firefox Quantum explodes if you manually edit the CSS in the - // inspector and then try to do a tint, as apparently all the - // fixups are then stale. - console.error("Failed to apply cssFixup in Tinter! ", e.name); - } - } - if (DEBUG) console.log("applyCssFixups end"); - } - - // XXX: we could just move this all into TintableSvg, but as it's so similar - // to the CSS fixup stuff in Tinter (just that the fixups are stored in TintableSvg) - // keeping it here for now. - calcSvgFixups(svgs) { - // go through manually fixing up SVG colours. - // we could do this by stylesheets, but keeping the stylesheets - // updated would be a PITA, so just brute-force search for the - // key colour; cache the element and apply. - - if (DEBUG) console.log("calcSvgFixups start for " + svgs); - const fixups = []; - for (let i = 0; i < svgs.length; i++) { - let svgDoc; - try { - svgDoc = svgs[i].contentDocument; - } catch (e) { - let msg = 'Failed to get svg.contentDocument of ' + svgs[i].toString(); - if (e.message) { - msg += e.message; - } - if (e.stack) { - msg += ' | stack: ' + e.stack; - } - console.error(msg); - } - if (!svgDoc) continue; - const tags = svgDoc.getElementsByTagName("*"); - for (let j = 0; j < tags.length; j++) { - const tag = tags[j]; - for (let k = 0; k < this.svgAttrs.length; k++) { - const attr = this.svgAttrs[k]; - for (let l = 0; l < this.keyHex.length; l++) { - if (tag.getAttribute(attr) && - tag.getAttribute(attr).toUpperCase() === this.keyHex[l]) { - fixups.push({ - node: tag, - attr: attr, - index: l, - }); - } - } - } - } - } - if (DEBUG) console.log("calcSvgFixups end"); - - return fixups; - } - - applySvgFixups(fixups) { - if (DEBUG) console.log("applySvgFixups start for " + fixups); - for (let i = 0; i < fixups.length; i++) { - const svgFixup = fixups[i]; - svgFixup.node.setAttribute(svgFixup.attr, this.colors[svgFixup.index]); - } - if (DEBUG) console.log("applySvgFixups end"); - } -} - -if (global.singletonTinter === undefined) { - global.singletonTinter = new Tinter(); -} -export default global.singletonTinter; diff --git a/src/UserActivity.ts b/src/UserActivity.ts index 606075ec7c..c35ced0cc4 100644 --- a/src/UserActivity.ts +++ b/src/UserActivity.ts @@ -191,10 +191,10 @@ export default class UserActivity { this.lastScreenY = event.screenY; } - dis.dispatch({action: 'user_activity'}); + dis.dispatch({ action: 'user_activity' }); if (!this.activeNowTimeout.isRunning()) { this.activeNowTimeout.start(); - dis.dispatch({action: 'user_activity_start'}); + dis.dispatch({ action: 'user_activity_start' }); UserActivity.runTimersUntilTimeout(this.attachedActiveNowTimers, this.activeNowTimeout); } else { diff --git a/src/WhoIsTyping.ts b/src/WhoIsTyping.ts index a8ca425ea8..938218d270 100644 --- a/src/WhoIsTyping.ts +++ b/src/WhoIsTyping.ts @@ -14,10 +14,10 @@ See the License for the specific language governing permissions and limitations under the License. */ -import {Room} from "matrix-js-sdk/src/models/room"; -import {RoomMember} from "matrix-js-sdk/src/models/room-member"; +import { Room } from "matrix-js-sdk/src/models/room"; +import { RoomMember } from "matrix-js-sdk/src/models/room-member"; -import {MatrixClientPeg} from "./MatrixClientPeg"; +import { MatrixClientPeg } from "./MatrixClientPeg"; import { _t } from './languageHandler'; export function usersTypingApartFromMeAndIgnored(room: Room): RoomMember[] { @@ -61,7 +61,7 @@ export function whoIsTypingString(whoIsTyping: RoomMember[], limit: number): str if (whoIsTyping.length === 0) { return ''; } else if (whoIsTyping.length === 1) { - return _t('%(displayName)s is typing …', {displayName: whoIsTyping[0].name}); + return _t('%(displayName)s is typing …', { displayName: whoIsTyping[0].name }); } const names = whoIsTyping.map(m => m.name); @@ -73,6 +73,6 @@ export function whoIsTypingString(whoIsTyping: RoomMember[], limit: number): str }); } else { const lastPerson = names.pop(); - return _t('%(names)s and %(lastPerson)s are typing …', {names: names.join(', '), lastPerson: lastPerson}); + return _t('%(names)s and %(lastPerson)s are typing …', { names: names.join(', '), lastPerson: lastPerson }); } } diff --git a/src/accessibility/KeyboardShortcuts.tsx b/src/accessibility/KeyboardShortcuts.tsx index 1cd5408210..25c41f9db5 100644 --- a/src/accessibility/KeyboardShortcuts.tsx +++ b/src/accessibility/KeyboardShortcuts.tsx @@ -20,7 +20,7 @@ import classNames from "classnames"; import * as sdk from "../index"; import Modal from "../Modal"; import { _t, _td } from "../languageHandler"; -import {isMac, Key} from "../Keyboard"; +import { isMac, Key } from "../Keyboard"; // TS: once languageHandler is TS we can probably inline this into the enum _td("Navigation"); @@ -332,7 +332,7 @@ const keyIcon: Record = { const Shortcut: React.FC<{ shortcut: IShortcut; -}> = ({shortcut}) => { +}> = ({ shortcut }) => { const classes = classNames({ "mx_KeyboardShortcutsDialog_inline": shortcut.keybinds.every(k => !k.modifiers || k.modifiers.length === 0), }); diff --git a/src/accessibility/RovingTabIndex.tsx b/src/accessibility/RovingTabIndex.tsx index 4cb537f318..87f525bdfc 100644 --- a/src/accessibility/RovingTabIndex.tsx +++ b/src/accessibility/RovingTabIndex.tsx @@ -26,8 +26,8 @@ import React, { Dispatch, } from "react"; -import {Key} from "../Keyboard"; -import {FocusHandler, Ref} from "./roving/types"; +import { Key } from "../Keyboard"; +import { FocusHandler, Ref } from "./roving/types"; /** * Module to simplify implementing the Roving TabIndex accessibility technique @@ -156,13 +156,13 @@ interface IProps { onKeyDown?(ev: React.KeyboardEvent, state: IState); } -export const RovingTabIndexProvider: React.FC = ({children, handleHomeEnd, onKeyDown}) => { +export const RovingTabIndexProvider: React.FC = ({ children, handleHomeEnd, onKeyDown }) => { const [state, dispatch] = useReducer>(reducer, { activeRef: null, refs: [], }); - const context = useMemo(() => ({state, dispatch}), [state]); + const context = useMemo(() => ({ state, dispatch }), [state]); const onKeyDownHandler = useCallback((ev) => { let handled = false; @@ -196,7 +196,7 @@ export const RovingTabIndexProvider: React.FC = ({children, handleHomeEn }, [context.state, onKeyDown, handleHomeEnd]); return - { children({onKeyDownHandler}) } + { children({ onKeyDownHandler }) } ; }; @@ -218,13 +218,13 @@ export const useRovingTabIndex = (inputRef?: Ref): [FocusHandler, boolean, Ref] useLayoutEffect(() => { context.dispatch({ type: Type.Register, - payload: {ref}, + payload: { ref }, }); // teardown return () => { context.dispatch({ type: Type.Unregister, - payload: {ref}, + payload: { ref }, }); }; }, []); // eslint-disable-line react-hooks/exhaustive-deps @@ -232,7 +232,7 @@ export const useRovingTabIndex = (inputRef?: Ref): [FocusHandler, boolean, Ref] const onFocus = useCallback(() => { context.dispatch({ type: Type.SetFocus, - payload: {ref}, + payload: { ref }, }); }, [ref, context]); @@ -241,6 +241,6 @@ export const useRovingTabIndex = (inputRef?: Ref): [FocusHandler, boolean, Ref] }; // re-export the semantic helper components for simplicity -export {RovingTabIndexWrapper} from "./roving/RovingTabIndexWrapper"; -export {RovingAccessibleButton} from "./roving/RovingAccessibleButton"; -export {RovingAccessibleTooltipButton} from "./roving/RovingAccessibleTooltipButton"; +export { RovingTabIndexWrapper } from "./roving/RovingTabIndexWrapper"; +export { RovingAccessibleButton } from "./roving/RovingAccessibleButton"; +export { RovingAccessibleTooltipButton } from "./roving/RovingAccessibleTooltipButton"; diff --git a/src/accessibility/Toolbar.tsx b/src/accessibility/Toolbar.tsx index e756d948e5..8d882fadea 100644 --- a/src/accessibility/Toolbar.tsx +++ b/src/accessibility/Toolbar.tsx @@ -16,8 +16,8 @@ limitations under the License. import React from "react"; -import {IState, RovingTabIndexProvider} from "./RovingTabIndex"; -import {Key} from "../Keyboard"; +import { IState, RovingTabIndexProvider } from "./RovingTabIndex"; +import { Key } from "../Keyboard"; interface IProps extends Omit, "onKeyDown"> { } @@ -25,7 +25,7 @@ interface IProps extends Omit, "onKeyDown"> { // This component implements the Toolbar design pattern from the WAI-ARIA Authoring Practices guidelines. // https://www.w3.org/TR/wai-aria-practices-1.1/#toolbar // All buttons passed in children must use RovingTabIndex to set `onFocus`, `isActive`, `ref` -const Toolbar: React.FC = ({children, ...props}) => { +const Toolbar: React.FC = ({ children, ...props }) => { const onKeyDown = (ev: React.KeyboardEvent, state: IState) => { const target = ev.target as HTMLElement; // Don't interfere with input default keydown behaviour @@ -62,7 +62,7 @@ const Toolbar: React.FC = ({children, ...props}) => { }; return - {({onKeyDownHandler}) =>
+ {({ onKeyDownHandler }) =>
{ children }
} ; diff --git a/src/accessibility/context_menu/MenuGroup.tsx b/src/accessibility/context_menu/MenuGroup.tsx index 9334e17a18..97f9694f83 100644 --- a/src/accessibility/context_menu/MenuGroup.tsx +++ b/src/accessibility/context_menu/MenuGroup.tsx @@ -23,7 +23,7 @@ interface IProps extends React.HTMLAttributes { } // Semantic component for representing a role=group for grouping menu radios/checkboxes -export const MenuGroup: React.FC = ({children, label, ...props}) => { +export const MenuGroup: React.FC = ({ children, label, ...props }) => { return
{ children }
; diff --git a/src/accessibility/context_menu/MenuItem.tsx b/src/accessibility/context_menu/MenuItem.tsx index 9a7c1d1f0a..9c0b248274 100644 --- a/src/accessibility/context_menu/MenuItem.tsx +++ b/src/accessibility/context_menu/MenuItem.tsx @@ -27,7 +27,7 @@ interface IProps extends React.ComponentProps { } // Semantic component for representing a role=menuitem -export const MenuItem: React.FC = ({children, label, tooltip, ...props}) => { +export const MenuItem: React.FC = ({ children, label, tooltip, ...props }) => { const ariaLabel = props["aria-label"] || label; if (tooltip) { diff --git a/src/accessibility/context_menu/MenuItemCheckbox.tsx b/src/accessibility/context_menu/MenuItemCheckbox.tsx index 5eb8cc4819..67da4cc85a 100644 --- a/src/accessibility/context_menu/MenuItemCheckbox.tsx +++ b/src/accessibility/context_menu/MenuItemCheckbox.tsx @@ -26,7 +26,7 @@ interface IProps extends React.ComponentProps { } // Semantic component for representing a role=menuitemcheckbox -export const MenuItemCheckbox: React.FC = ({children, label, active, disabled, ...props}) => { +export const MenuItemCheckbox: React.FC = ({ children, label, active, disabled, ...props }) => { return ( { } // Semantic component for representing a role=menuitemradio -export const MenuItemRadio: React.FC = ({children, label, active, disabled, ...props}) => { +export const MenuItemRadio: React.FC = ({ children, label, active, disabled, ...props }) => { return ( { @@ -28,7 +28,7 @@ interface IProps extends React.ComponentProps { } // Semantic component for representing a styled role=menuitemcheckbox -export const StyledMenuItemCheckbox: React.FC = ({children, label, onChange, onClose, ...props}) => { +export const StyledMenuItemCheckbox: React.FC = ({ children, label, onChange, onClose, ...props }) => { const onKeyDown = (e: React.KeyboardEvent) => { if (e.key === Key.ENTER || e.key === Key.SPACE) { e.stopPropagation(); diff --git a/src/accessibility/context_menu/StyledMenuItemRadio.tsx b/src/accessibility/context_menu/StyledMenuItemRadio.tsx index 5e5aa90a38..e3d340ef3e 100644 --- a/src/accessibility/context_menu/StyledMenuItemRadio.tsx +++ b/src/accessibility/context_menu/StyledMenuItemRadio.tsx @@ -18,7 +18,7 @@ limitations under the License. import React from "react"; -import {Key} from "../../Keyboard"; +import { Key } from "../../Keyboard"; import StyledRadioButton from "../../components/views/elements/StyledRadioButton"; interface IProps extends React.ComponentProps { @@ -28,7 +28,7 @@ interface IProps extends React.ComponentProps { } // Semantic component for representing a styled role=menuitemradio -export const StyledMenuItemRadio: React.FC = ({children, label, onChange, onClose, ...props}) => { +export const StyledMenuItemRadio: React.FC = ({ children, label, onChange, onClose, ...props }) => { const onKeyDown = (e: React.KeyboardEvent) => { if (e.key === Key.ENTER || e.key === Key.SPACE) { e.stopPropagation(); diff --git a/src/accessibility/roving/RovingAccessibleButton.tsx b/src/accessibility/roving/RovingAccessibleButton.tsx index 3473ef1bc9..f9ce87db6a 100644 --- a/src/accessibility/roving/RovingAccessibleButton.tsx +++ b/src/accessibility/roving/RovingAccessibleButton.tsx @@ -17,15 +17,15 @@ limitations under the License. import React from "react"; import AccessibleButton from "../../components/views/elements/AccessibleButton"; -import {useRovingTabIndex} from "../RovingTabIndex"; -import {Ref} from "./types"; +import { useRovingTabIndex } from "../RovingTabIndex"; +import { Ref } from "./types"; interface IProps extends Omit, "onFocus" | "inputRef" | "tabIndex"> { inputRef?: Ref; } // Wrapper to allow use of useRovingTabIndex for simple AccessibleButtons outside of React Functional Components. -export const RovingAccessibleButton: React.FC = ({inputRef, ...props}) => { +export const RovingAccessibleButton: React.FC = ({ inputRef, ...props }) => { const [onFocus, isActive, ref] = useRovingTabIndex(inputRef); return ; }; diff --git a/src/accessibility/roving/RovingAccessibleTooltipButton.tsx b/src/accessibility/roving/RovingAccessibleTooltipButton.tsx index 2cb974d60e..d9e393d728 100644 --- a/src/accessibility/roving/RovingAccessibleTooltipButton.tsx +++ b/src/accessibility/roving/RovingAccessibleTooltipButton.tsx @@ -17,8 +17,8 @@ limitations under the License. import React from "react"; import AccessibleTooltipButton from "../../components/views/elements/AccessibleTooltipButton"; -import {useRovingTabIndex} from "../RovingTabIndex"; -import {Ref} from "./types"; +import { useRovingTabIndex } from "../RovingTabIndex"; +import { Ref } from "./types"; type ATBProps = React.ComponentProps; interface IProps extends Omit { @@ -26,7 +26,7 @@ interface IProps extends Omit { } // Wrapper to allow use of useRovingTabIndex for simple AccessibleTooltipButtons outside of React Functional Components. -export const RovingAccessibleTooltipButton: React.FC = ({inputRef, ...props}) => { +export const RovingAccessibleTooltipButton: React.FC = ({ inputRef, ...props }) => { const [onFocus, isActive, ref] = useRovingTabIndex(inputRef); return ; }; diff --git a/src/accessibility/roving/RovingTabIndexWrapper.tsx b/src/accessibility/roving/RovingTabIndexWrapper.tsx index 5211f30215..974bb9a388 100644 --- a/src/accessibility/roving/RovingTabIndexWrapper.tsx +++ b/src/accessibility/roving/RovingTabIndexWrapper.tsx @@ -16,8 +16,8 @@ limitations under the License. import React from "react"; -import {useRovingTabIndex} from "../RovingTabIndex"; -import {FocusHandler, Ref} from "./types"; +import { useRovingTabIndex } from "../RovingTabIndex"; +import { FocusHandler, Ref } from "./types"; interface IProps { inputRef?: Ref; @@ -29,7 +29,7 @@ interface IProps { } // Wrapper to allow use of useRovingTabIndex outside of React Functional Components. -export const RovingTabIndexWrapper: React.FC = ({children, inputRef}) => { +export const RovingTabIndexWrapper: React.FC = ({ children, inputRef }) => { const [onFocus, isActive, ref] = useRovingTabIndex(inputRef); - return children({onFocus, isActive, ref}); + return children({ onFocus, isActive, ref }); }; diff --git a/src/accessibility/roving/types.ts b/src/accessibility/roving/types.ts index f0a43e5fb8..cc6a98e1d7 100644 --- a/src/accessibility/roving/types.ts +++ b/src/accessibility/roving/types.ts @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import {RefObject} from "react"; +import { RefObject } from "react"; export type Ref = RefObject; diff --git a/src/actions/MatrixActionCreators.ts b/src/actions/MatrixActionCreators.ts index 33e72becd2..70b86f8ee5 100644 --- a/src/actions/MatrixActionCreators.ts +++ b/src/actions/MatrixActionCreators.ts @@ -20,7 +20,7 @@ import { Room } from "matrix-js-sdk/src/models/room"; import { EventTimeline } from "matrix-js-sdk/src/models/event-timeline"; import dis from "../dispatcher/dispatcher"; -import {ActionPayload} from "../dispatcher/payloads"; +import { ActionPayload } from "../dispatcher/payloads"; // TODO: migrate from sync_state to MatrixActions.sync so that more js-sdk events // become dispatches in the same place. diff --git a/src/actions/RoomListActions.ts b/src/actions/RoomListActions.ts index 88946ee26f..81e05f8678 100644 --- a/src/actions/RoomListActions.ts +++ b/src/actions/RoomListActions.ts @@ -112,7 +112,7 @@ export default class RoomListActions { 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}), + title: _t('Failed to remove tag %(tagName)s from room', { tagName: oldTag }), description: ((err && err.message) ? err.message : _t('Operation failed')), }); }); @@ -132,7 +132,7 @@ export default class RoomListActions { 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}), + title: _t('Failed to add tag %(tagName)s to room', { tagName: newTag }), description: ((err && err.message) ? err.message : _t('Operation failed')), }); diff --git a/src/actions/TagOrderActions.ts b/src/actions/TagOrderActions.ts index 021cd11b55..dc538134a1 100644 --- a/src/actions/TagOrderActions.ts +++ b/src/actions/TagOrderActions.ts @@ -53,11 +53,11 @@ export default class TagOrderActions { Analytics.trackEvent('TagOrderActions', 'commitTagOrdering'); return matrixClient.setAccountData( 'im.vector.web.tag_ordering', - {tags, removedTags, _storeId: storeId}, + { tags, removedTags, _storeId: storeId }, ); }, () => { // For an optimistic update - return {tags, removedTags}; + return { tags, removedTags }; }); } @@ -100,11 +100,11 @@ export default class TagOrderActions { Analytics.trackEvent('TagOrderActions', 'removeTag'); return matrixClient.setAccountData( 'im.vector.web.tag_ordering', - {tags, removedTags, _storeId: storeId}, + { tags, removedTags, _storeId: storeId }, ); }, () => { // For an optimistic update - return {removedTags}; + return { removedTags }; }); } } diff --git a/src/actions/actionCreators.ts b/src/actions/actionCreators.ts index c789e3cd07..81e0b95098 100644 --- a/src/actions/actionCreators.ts +++ b/src/actions/actionCreators.ts @@ -51,9 +51,9 @@ export function asyncAction(id: string, fn: () => Promise, pendingFn: () => request: typeof pendingFn === 'function' ? pendingFn() : undefined, }); fn().then((result) => { - dispatch({action: id + '.success', result}); + dispatch({ action: id + '.success', result }); }).catch((err) => { - dispatch({action: id + '.failure', err}); + dispatch({ action: id + '.failure', err }); }); }; return new AsyncActionPayload(helper); diff --git a/src/async-components/views/dialogs/eventindex/DisableEventIndexDialog.js b/src/async-components/views/dialogs/eventindex/DisableEventIndexDialog.js index de50feaedb..a19494c753 100644 --- a/src/async-components/views/dialogs/eventindex/DisableEventIndexDialog.js +++ b/src/async-components/views/dialogs/eventindex/DisableEventIndexDialog.js @@ -22,8 +22,8 @@ import { _t } from '../../../../languageHandler'; import SettingsStore from "../../../../settings/SettingsStore"; import EventIndexPeg from "../../../../indexing/EventIndexPeg"; -import {Action} from "../../../../dispatcher/actions"; -import {SettingLevel} from "../../../../settings/SettingLevel"; +import { Action } from "../../../../dispatcher/actions"; +import { SettingLevel } from "../../../../settings/SettingLevel"; /* * Allows the user to disable the Event Index. diff --git a/src/async-components/views/dialogs/eventindex/ManageEventIndexDialog.tsx b/src/async-components/views/dialogs/eventindex/ManageEventIndexDialog.tsx index 0710c513da..76c3373ba4 100644 --- a/src/async-components/views/dialogs/eventindex/ManageEventIndexDialog.tsx +++ b/src/async-components/views/dialogs/eventindex/ManageEventIndexDialog.tsx @@ -21,9 +21,9 @@ import SdkConfig from '../../../../SdkConfig'; import SettingsStore from "../../../../settings/SettingsStore"; import Modal from '../../../../Modal'; -import {formatBytes, formatCountLong} from "../../../../utils/FormattingUtils"; +import { formatBytes, formatCountLong } from "../../../../utils/FormattingUtils"; import EventIndexPeg from "../../../../indexing/EventIndexPeg"; -import {SettingLevel} from "../../../../settings/SettingLevel"; +import { SettingLevel } from "../../../../settings/SettingLevel"; interface IProps { onFinished: (confirmed: boolean) => void; @@ -139,7 +139,7 @@ export default class ManageEventIndexDialog extends React.Component { - this.setState({crawlerSleepTime: e.target.value}); + this.setState({ crawlerSleepTime: e.target.value }); SettingsStore.setValue("crawlerSleepTime", null, SettingLevel.DEVICE, e.target.value); }; diff --git a/src/async-components/views/dialogs/security/CreateKeyBackupDialog.js b/src/async-components/views/dialogs/security/CreateKeyBackupDialog.js index 549494b5cb..92fb37ef16 100644 --- a/src/async-components/views/dialogs/security/CreateKeyBackupDialog.js +++ b/src/async-components/views/dialogs/security/CreateKeyBackupDialog.js @@ -15,15 +15,15 @@ See the License for the specific language governing permissions and limitations under the License. */ -import React, {createRef} from 'react'; +import React, { createRef } from 'react'; import FileSaver from 'file-saver'; import * as sdk from '../../../../index'; -import {MatrixClientPeg} from '../../../../MatrixClientPeg'; +import { MatrixClientPeg } from '../../../../MatrixClientPeg'; import PropTypes from 'prop-types'; -import {_t, _td} from '../../../../languageHandler'; +import { _t, _td } from '../../../../languageHandler'; import { accessSecretStorage } from '../../../../SecurityManager'; import AccessibleButton from "../../../../components/views/elements/AccessibleButton"; -import {copyNode} from "../../../../utils/strings"; +import { copyNode } from "../../../../utils/strings"; import PassphraseField from "../../../../components/views/auth/PassphraseField"; const PHASE_PASSPHRASE = 0; @@ -152,11 +152,11 @@ export default class CreateKeyBackupDialog extends React.PureComponent { } _onOptOutClick = () => { - this.setState({phase: PHASE_OPTOUT_CONFIRM}); + this.setState({ phase: PHASE_OPTOUT_CONFIRM }); } _onSetUpClick = () => { - this.setState({phase: PHASE_PASSPHRASE}); + this.setState({ phase: PHASE_PASSPHRASE }); } _onSkipPassPhraseClick = async () => { @@ -179,7 +179,7 @@ export default class CreateKeyBackupDialog extends React.PureComponent { return; } - this.setState({phase: PHASE_PASSPHRASE_CONFIRM}); + this.setState({ phase: PHASE_PASSPHRASE_CONFIRM }); }; _onPassPhraseConfirmNextClick = async (e) => { @@ -370,21 +370,21 @@ export default class CreateKeyBackupDialog extends React.PureComponent { if (this.state.copied) { introText = _t( "Your Security Key has been copied to your clipboard, paste it to:", - {}, {b: s => {s}}, + {}, { b: s => {s} }, ); } else if (this.state.downloaded) { introText = _t( "Your Security Key is in your Downloads folder.", - {}, {b: s => {s}}, + {}, { b: s => {s} }, ); } const DialogButtons = sdk.getComponent('views.elements.DialogButtons'); return
{introText}
    -
  • {_t("Print it and store it somewhere safe", {}, {b: s => {s}})}
  • -
  • {_t("Save it on a USB key or backup drive", {}, {b: s => {s}})}
  • -
  • {_t("Copy it to your personal cloud storage", {}, {b: s => {s}})}
  • +
  • {_t("Print it and store it somewhere safe", {}, { b: s => {s} })}
  • +
  • {_t("Save it on a USB key or backup drive", {}, { b: s => {s} })}
  • +
  • {_t("Copy it to your personal cloud storage", {}, { b: s => {s} })}
{ - this.setState({phase: PHASE_LOADING}); + this.setState({ phase: PHASE_LOADING }); this._fetchBackupInfo(); } @@ -394,11 +394,11 @@ export default class CreateSecretStorageDialog extends React.PureComponent { } _onCancelClick = () => { - this.setState({phase: PHASE_CONFIRM_SKIP}); + this.setState({ phase: PHASE_CONFIRM_SKIP }); } _onGoBackClick = () => { - this.setState({phase: PHASE_CHOOSE_KEY_PASSPHRASE}); + this.setState({ phase: PHASE_CHOOSE_KEY_PASSPHRASE }); } _onPassPhraseNextClick = async (e) => { @@ -412,7 +412,7 @@ export default class CreateSecretStorageDialog extends React.PureComponent { return; } - this.setState({phase: PHASE_PASSPHRASE_CONFIRM}); + this.setState({ phase: PHASE_PASSPHRASE_CONFIRM }); }; _onPassPhraseConfirmNextClick = async (e) => { diff --git a/src/async-components/views/dialogs/security/ExportE2eKeysDialog.js b/src/async-components/views/dialogs/security/ExportE2eKeysDialog.js index 60f2ca9168..0435d81968 100644 --- a/src/async-components/views/dialogs/security/ExportE2eKeysDialog.js +++ b/src/async-components/views/dialogs/security/ExportE2eKeysDialog.js @@ -15,7 +15,7 @@ limitations under the License. */ import FileSaver from 'file-saver'; -import React, {createRef} from 'react'; +import React, { createRef } from 'react'; import PropTypes from 'prop-types'; import { _t } from '../../../../languageHandler'; @@ -55,11 +55,11 @@ export default class ExportE2eKeysDialog extends React.Component { const passphrase = this._passphrase1.current.value; if (passphrase !== this._passphrase2.current.value) { - this.setState({errStr: _t('Passphrases must match')}); + this.setState({ errStr: _t('Passphrases must match') }); return false; } if (!passphrase) { - this.setState({errStr: _t('Passphrase must not be empty')}); + this.setState({ errStr: _t('Passphrase must not be empty') }); return false; } diff --git a/src/async-components/views/dialogs/security/ImportE2eKeysDialog.js b/src/async-components/views/dialogs/security/ImportE2eKeysDialog.js index 70fc997230..6017d07047 100644 --- a/src/async-components/views/dialogs/security/ImportE2eKeysDialog.js +++ b/src/async-components/views/dialogs/security/ImportE2eKeysDialog.js @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import React, {createRef} from 'react'; +import React, { createRef } from 'react'; import PropTypes from 'prop-types'; import { MatrixClient } from 'matrix-js-sdk/src/client'; diff --git a/src/async-components/views/dialogs/security/NewRecoveryMethodDialog.js b/src/async-components/views/dialogs/security/NewRecoveryMethodDialog.js index 8c09cc6d16..4a0aa37da0 100644 --- a/src/async-components/views/dialogs/security/NewRecoveryMethodDialog.js +++ b/src/async-components/views/dialogs/security/NewRecoveryMethodDialog.js @@ -18,12 +18,12 @@ limitations under the License. import React from "react"; import PropTypes from "prop-types"; import * as sdk from "../../../../index"; -import {MatrixClientPeg} from '../../../../MatrixClientPeg'; +import { MatrixClientPeg } from '../../../../MatrixClientPeg'; import dis from "../../../../dispatcher/dispatcher"; import { _t } from "../../../../languageHandler"; import Modal from "../../../../Modal"; import RestoreKeyBackupDialog from "../../../../components/views/dialogs/security/RestoreKeyBackupDialog"; -import {Action} from "../../../../dispatcher/actions"; +import { Action } from "../../../../dispatcher/actions"; export default class NewRecoveryMethodDialog extends React.PureComponent { static propTypes = { diff --git a/src/async-components/views/dialogs/security/RecoveryMethodRemovedDialog.js b/src/async-components/views/dialogs/security/RecoveryMethodRemovedDialog.js index b60e6fd3cb..f0f8a5273b 100644 --- a/src/async-components/views/dialogs/security/RecoveryMethodRemovedDialog.js +++ b/src/async-components/views/dialogs/security/RecoveryMethodRemovedDialog.js @@ -21,7 +21,7 @@ import * as sdk from "../../../../index"; import dis from "../../../../dispatcher/dispatcher"; import { _t } from "../../../../languageHandler"; import Modal from "../../../../Modal"; -import {Action} from "../../../../dispatcher/actions"; +import { Action } from "../../../../dispatcher/actions"; export default class RecoveryMethodRemovedDialog extends React.PureComponent { static propTypes = { diff --git a/src/autocomplete/AutocompleteProvider.tsx b/src/autocomplete/AutocompleteProvider.tsx index 2242fec914..51ab2e2cf7 100644 --- a/src/autocomplete/AutocompleteProvider.tsx +++ b/src/autocomplete/AutocompleteProvider.tsx @@ -17,7 +17,7 @@ limitations under the License. */ import React from 'react'; -import type {ICompletion, ISelectionRange} from './Autocompleter'; +import type { ICompletion, ISelectionRange } from './Autocompleter'; export interface ICommand { command: string | null; diff --git a/src/autocomplete/Autocompleter.ts b/src/autocomplete/Autocompleter.ts index 7f3f5d2c01..7ab2ae70ea 100644 --- a/src/autocomplete/Autocompleter.ts +++ b/src/autocomplete/Autocompleter.ts @@ -26,7 +26,7 @@ import UserProvider from './UserProvider'; import EmojiProvider from './EmojiProvider'; import NotifProvider from './NotifProvider'; import { timeout } from "../utils/promise"; -import AutocompleteProvider, {ICommand} from "./AutocompleteProvider"; +import AutocompleteProvider, { ICommand } from "./AutocompleteProvider"; import SettingsStore from "../settings/SettingsStore"; import SpaceProvider from "./SpaceProvider"; diff --git a/src/autocomplete/CommandProvider.tsx b/src/autocomplete/CommandProvider.tsx index 9de25c0d84..e9a7742dee 100644 --- a/src/autocomplete/CommandProvider.tsx +++ b/src/autocomplete/CommandProvider.tsx @@ -18,12 +18,12 @@ limitations under the License. */ import React from 'react'; -import {_t} from '../languageHandler'; +import { _t } from '../languageHandler'; import AutocompleteProvider from './AutocompleteProvider'; import QueryMatcher from './QueryMatcher'; -import {TextualCompletion} from './Components'; -import {ICompletion, ISelectionRange} from "./Autocompleter"; -import {Command, Commands, CommandMap} from '../SlashCommands'; +import { TextualCompletion } from './Components'; +import { ICompletion, ISelectionRange } from "./Autocompleter"; +import { Command, Commands, CommandMap } from '../SlashCommands'; const COMMAND_RE = /(^\/\w*)(?: .*)?/g; @@ -34,7 +34,7 @@ export default class CommandProvider extends AutocompleteProvider { super(COMMAND_RE); this.matcher = new QueryMatcher(Commands, { keys: ['command', 'args', 'description'], - funcs: [({aliases}) => aliases.join(" ")], // aliases + funcs: [({ aliases }) => aliases.join(" ")], // aliases }); } @@ -44,7 +44,7 @@ export default class CommandProvider extends AutocompleteProvider { force?: boolean, limit = -1, ): Promise { - const {command, range} = this.getCurrentCommand(query, selection); + const { command, range } = this.getCurrentCommand(query, selection); if (!command) return []; let matches = []; @@ -68,7 +68,6 @@ export default class CommandProvider extends AutocompleteProvider { } } - return matches.filter(cmd => cmd.isEnabled()).map((result) => { let completion = result.getCommand() + ' '; const usedAlias = result.aliases.find(alias => `/${alias}` === command[1]); diff --git a/src/autocomplete/CommunityProvider.tsx b/src/autocomplete/CommunityProvider.tsx index c9358b0c61..48c1921539 100644 --- a/src/autocomplete/CommunityProvider.tsx +++ b/src/autocomplete/CommunityProvider.tsx @@ -19,15 +19,15 @@ import React from 'react'; import Group from "matrix-js-sdk/src/models/group"; import { _t } from '../languageHandler'; import AutocompleteProvider from './AutocompleteProvider'; -import {MatrixClientPeg} from '../MatrixClientPeg'; +import { MatrixClientPeg } from '../MatrixClientPeg'; import QueryMatcher from './QueryMatcher'; -import {PillCompletion} from './Components'; +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 { 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 { mediaFromMxc } from "../customisations/Media"; const COMMUNITY_REGEX = /\B\+\S*/g; @@ -66,11 +66,11 @@ export default class CommunityProvider extends AutocompleteProvider { const cli = MatrixClientPeg.get(); let completions = []; - const {command, range} = this.getCurrentCommand(query, selection, force); + const { command, range } = this.getCurrentCommand(query, selection, force); if (command) { - const joinedGroups = cli.getGroups().filter(({myMembership}) => myMembership === 'join'); + const joinedGroups = cli.getGroups().filter(({ myMembership }) => myMembership === 'join'); - const groups = (await Promise.all(joinedGroups.map(async ({groupId}) => { + const groups = (await Promise.all(joinedGroups.map(async ({ groupId }) => { try { return FlairStore.getGroupProfileCached(cli, groupId); } catch (e) { // if FlairStore failed, fall back to just groupId @@ -90,7 +90,7 @@ export default class CommunityProvider extends AutocompleteProvider { completions = sortBy(completions, [ (c) => score(matchedString, c.groupId), (c) => c.groupId.length, - ]).map(({avatarUrl, groupId, name}) => ({ + ]).map(({ avatarUrl, groupId, name }) => ({ completion: groupId, suffix: ' ', type: "community", diff --git a/src/autocomplete/Components.tsx b/src/autocomplete/Components.tsx index 4b0d35698d..8f155f7f55 100644 --- a/src/autocomplete/Components.tsx +++ b/src/autocomplete/Components.tsx @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import React, {forwardRef} from 'react'; +import React, { forwardRef } from 'react'; import classNames from 'classnames'; /* These were earlier stateless functional components but had to be converted @@ -31,7 +31,7 @@ interface ITextualCompletionProps { } export const TextualCompletion = forwardRef((props, ref) => { - const {title, subtitle, description, className, ...restProps} = props; + const { title, subtitle, description, className, ...restProps } = props; return (
((props, ref) => { - const {title, subtitle, description, className, children, ...restProps} = props; + const { title, subtitle, description, className, children, ...restProps } = props; return (
{ - const {command, range} = this.getCurrentCommand(query, selection); + const { command, range } = this.getCurrentCommand(query, selection); if (!query || !command) { return []; } diff --git a/src/autocomplete/EmojiProvider.tsx b/src/autocomplete/EmojiProvider.tsx index b7c4a5120a..2fc77e9a17 100644 --- a/src/autocomplete/EmojiProvider.tsx +++ b/src/autocomplete/EmojiProvider.tsx @@ -21,9 +21,9 @@ import React from 'react'; import { _t } from '../languageHandler'; import AutocompleteProvider from './AutocompleteProvider'; import QueryMatcher from './QueryMatcher'; -import {PillCompletion} from './Components'; -import {ICompletion, ISelectionRange} from './Autocompleter'; -import {uniq, sortBy} from 'lodash'; +import { PillCompletion } from './Components'; +import { ICompletion, ISelectionRange } from './Autocompleter'; +import { uniq, sortBy } from 'lodash'; import SettingsStore from "../settings/SettingsStore"; import { shortcodeToUnicode } from '../HtmlUtils'; import { EMOJI, IEmoji } from '../emoji'; @@ -95,7 +95,7 @@ export default class EmojiProvider extends AutocompleteProvider { } let completions = []; - const {command, range} = this.getCurrentCommand(query, selection); + const { command, range } = this.getCurrentCommand(query, selection); if (command) { const matchedString = command[0]; completions = this.matcher.match(matchedString, limit); @@ -121,7 +121,7 @@ export default class EmojiProvider extends AutocompleteProvider { sorters.push((c) => c._orderBy); completions = sortBy(uniq(completions), sorters); - completions = completions.map(({shortname}) => { + completions = completions.map(({ shortname }) => { const unicode = shortcodeToUnicode(shortname); return { completion: unicode, diff --git a/src/autocomplete/NotifProvider.tsx b/src/autocomplete/NotifProvider.tsx index 827f4aa885..1d42915ec9 100644 --- a/src/autocomplete/NotifProvider.tsx +++ b/src/autocomplete/NotifProvider.tsx @@ -19,10 +19,10 @@ import { Room } from "matrix-js-sdk/src/models/room"; import AutocompleteProvider from './AutocompleteProvider'; import { _t } from '../languageHandler'; -import {MatrixClientPeg} from '../MatrixClientPeg'; -import {PillCompletion} from './Components'; +import { MatrixClientPeg } from '../MatrixClientPeg'; +import { PillCompletion } from './Components'; import * as sdk from '../index'; -import {ICompletion, ISelectionRange} from "./Autocompleter"; +import { ICompletion, ISelectionRange } from "./Autocompleter"; const AT_ROOM_REGEX = /@\S*/g; @@ -46,7 +46,7 @@ export default class NotifProvider extends AutocompleteProvider { if (!this.room.currentState.mayTriggerNotifOfType('room', client.credentials.userId)) return []; - const {command, range} = this.getCurrentCommand(query, selection, force); + const { command, range } = this.getCurrentCommand(query, selection, force); if (command && command[0] && '@room'.startsWith(command[0]) && command[0].length > 1) { return [{ completion: '@room', diff --git a/src/autocomplete/QueryMatcher.ts b/src/autocomplete/QueryMatcher.ts index 73bb37ff0f..3948be301c 100644 --- a/src/autocomplete/QueryMatcher.ts +++ b/src/autocomplete/QueryMatcher.ts @@ -16,8 +16,8 @@ See the License for the specific language governing permissions and limitations under the License. */ -import {at, uniq} from 'lodash'; -import {removeHiddenChars} from "matrix-js-sdk/src/utils"; +import { at, uniq } from 'lodash'; +import { removeHiddenChars } from "matrix-js-sdk/src/utils"; interface IOptions { keys: Array; @@ -112,7 +112,7 @@ export default class QueryMatcher { const index = resultKey.indexOf(query); if (index !== -1) { matches.push( - ...candidates.map((candidate) => ({index, ...candidate})), + ...candidates.map((candidate) => ({ index, ...candidate })), ); } } diff --git a/src/autocomplete/RoomProvider.tsx b/src/autocomplete/RoomProvider.tsx index 5240db6955..7865a76daa 100644 --- a/src/autocomplete/RoomProvider.tsx +++ b/src/autocomplete/RoomProvider.tsx @@ -73,7 +73,7 @@ export default class RoomProvider extends AutocompleteProvider { limit = -1, ): Promise { let completions = []; - const {command, range} = this.getCurrentCommand(query, selection, force); + const { command, range } = this.getCurrentCommand(query, selection, force); if (command) { // the only reason we need to do this is because Fuse only matches on properties let matcherObjects = this.getRooms().reduce((aliases, room) => { diff --git a/src/autocomplete/SpaceProvider.tsx b/src/autocomplete/SpaceProvider.tsx index 0361a2c91e..1c99aee5ac 100644 --- a/src/autocomplete/SpaceProvider.tsx +++ b/src/autocomplete/SpaceProvider.tsx @@ -17,7 +17,7 @@ limitations under the License. import React from "react"; import { _t } from '../languageHandler'; -import {MatrixClientPeg} from '../MatrixClientPeg'; +import { MatrixClientPeg } from '../MatrixClientPeg'; import RoomProvider from "./RoomProvider"; export default class SpaceProvider extends RoomProvider { diff --git a/src/autocomplete/UserProvider.tsx b/src/autocomplete/UserProvider.tsx index 687b477133..470e018e22 100644 --- a/src/autocomplete/UserProvider.tsx +++ b/src/autocomplete/UserProvider.tsx @@ -114,7 +114,7 @@ export default class UserProvider extends AutocompleteProvider { if (!this.users) this._makeUsers(); let completions = []; - const {command, range} = this.getCurrentCommand(rawQuery, selection, force); + const { command, range } = this.getCurrentCommand(rawQuery, selection, force); if (!command) return completions; @@ -158,7 +158,7 @@ export default class UserProvider extends AutocompleteProvider { } const currentUserId = MatrixClientPeg.get().credentials.userId; - this.users = this.room.getJoinedMembers().filter(({userId}) => userId !== currentUserId); + this.users = this.room.getJoinedMembers().filter(({ userId }) => userId !== currentUserId); this.users = this.users.concat(this.room.getMembersWithMembership("invite")); this.users = sortBy(this.users, (member) => 1E20 - lastSpoken[member.userId] || 1E20); diff --git a/src/components/structures/AutoHideScrollbar.tsx b/src/components/structures/AutoHideScrollbar.tsx index 8650224fb3..e8a9872b48 100644 --- a/src/components/structures/AutoHideScrollbar.tsx +++ b/src/components/structures/AutoHideScrollbar.tsx @@ -15,12 +15,12 @@ See the License for the specific language governing permissions and limitations under the License. */ -import React, { HTMLAttributes } from "react"; +import React, { HTMLAttributes, WheelEvent } from "react"; -interface IProps extends HTMLAttributes { +interface IProps extends Omit, "onScroll"> { className?: string; - onScroll?: () => void; - onWheel?: () => void; + onScroll?: (event: Event) => void; + onWheel?: (event: WheelEvent) => void; style?: React.CSSProperties tabIndex?: number, wrappedRef?: (ref: HTMLDivElement) => void; diff --git a/src/components/structures/ContextMenu.tsx b/src/components/structures/ContextMenu.tsx index 9d8665c176..407dc6f04c 100644 --- a/src/components/structures/ContextMenu.tsx +++ b/src/components/structures/ContextMenu.tsx @@ -16,13 +16,13 @@ See the License for the specific language governing permissions and limitations under the License. */ -import React, {CSSProperties, RefObject, useRef, useState} from "react"; +import React, { CSSProperties, RefObject, useRef, useState } from "react"; import ReactDOM from "react-dom"; import classNames from "classnames"; -import {Key} from "../../Keyboard"; -import {Writeable} from "../../@types/common"; -import {replaceableComponent} from "../../utils/replaceableComponent"; +import { Key } from "../../Keyboard"; +import { Writeable } from "../../@types/common"; +import { replaceableComponent } from "../../utils/replaceableComponent"; import UIStore from "../../stores/UIStore"; // Shamelessly ripped off Modal.js. There's probably a better way @@ -371,7 +371,7 @@ export class ContextMenu extends React.PureComponent { return (
@@ -399,7 +399,7 @@ export const toRightOf = (elementRect: Pick const left = elementRect.right + window.pageXOffset + 3; let top = elementRect.top + (elementRect.height / 2) + window.pageYOffset; top -= chevronOffset + 8; // where 8 is half the height of the chevron - return {left, top, chevronOffset}; + return { left, top, chevronOffset }; }; // Placement method for to position context menu right-aligned and flowing to the left of elementRect, @@ -498,15 +498,15 @@ export function createMenu(ElementClass, props) { ReactDOM.render(menu, getOrCreateContainer()); - return {close: onFinished}; + return { close: onFinished }; } // re-export the semantic helper components for simplicity -export {ContextMenuButton} from "../../accessibility/context_menu/ContextMenuButton"; -export {ContextMenuTooltipButton} from "../../accessibility/context_menu/ContextMenuTooltipButton"; -export {MenuGroup} from "../../accessibility/context_menu/MenuGroup"; -export {MenuItem} from "../../accessibility/context_menu/MenuItem"; -export {MenuItemCheckbox} from "../../accessibility/context_menu/MenuItemCheckbox"; -export {MenuItemRadio} from "../../accessibility/context_menu/MenuItemRadio"; -export {StyledMenuItemCheckbox} from "../../accessibility/context_menu/StyledMenuItemCheckbox"; -export {StyledMenuItemRadio} from "../../accessibility/context_menu/StyledMenuItemRadio"; +export { ContextMenuButton } from "../../accessibility/context_menu/ContextMenuButton"; +export { ContextMenuTooltipButton } from "../../accessibility/context_menu/ContextMenuTooltipButton"; +export { MenuGroup } from "../../accessibility/context_menu/MenuGroup"; +export { MenuItem } from "../../accessibility/context_menu/MenuItem"; +export { MenuItemCheckbox } from "../../accessibility/context_menu/MenuItemCheckbox"; +export { MenuItemRadio } from "../../accessibility/context_menu/MenuItemRadio"; +export { StyledMenuItemCheckbox } from "../../accessibility/context_menu/StyledMenuItemCheckbox"; +export { StyledMenuItemRadio } from "../../accessibility/context_menu/StyledMenuItemRadio"; diff --git a/src/components/structures/CustomRoomTagPanel.js b/src/components/structures/CustomRoomTagPanel.js index 73359f17a5..037d7c251c 100644 --- a/src/components/structures/CustomRoomTagPanel.js +++ b/src/components/structures/CustomRoomTagPanel.js @@ -21,7 +21,7 @@ import * as sdk from '../../index'; import dis from '../../dispatcher/dispatcher'; import classNames from 'classnames'; import * as FormattingUtils from '../../utils/FormattingUtils'; -import {replaceableComponent} from "../../utils/replaceableComponent"; +import { replaceableComponent } from "../../utils/replaceableComponent"; @replaceableComponent("structures.CustomRoomTagPanel") class CustomRoomTagPanel extends React.Component { @@ -34,7 +34,7 @@ class CustomRoomTagPanel extends React.Component { componentDidMount() { this._tagStoreToken = CustomRoomTagStore.addListener(() => { - this.setState({tags: CustomRoomTagStore.getSortedTags()}); + this.setState({ tags: CustomRoomTagStore.getSortedTags() }); }); } @@ -64,7 +64,7 @@ class CustomRoomTagPanel extends React.Component { class CustomRoomTagTile extends React.Component { onClick = () => { - dis.dispatch({action: 'select_custom_room_tag', tag: this.props.tag.name}); + dis.dispatch({ action: 'select_custom_room_tag', tag: this.props.tag.name }); }; render() { diff --git a/src/components/structures/EmbeddedPage.js b/src/components/structures/EmbeddedPage.js index c37ab3df48..628c16f322 100644 --- a/src/components/structures/EmbeddedPage.js +++ b/src/components/structures/EmbeddedPage.js @@ -22,7 +22,7 @@ import request from 'browser-request'; import { _t } from '../../languageHandler'; import sanitizeHtml from 'sanitize-html'; import dis from '../../dispatcher/dispatcher'; -import {MatrixClientPeg} from '../../MatrixClientPeg'; +import { MatrixClientPeg } from '../../MatrixClientPeg'; import classnames from 'classnames'; import MatrixClientContext from "../../contexts/MatrixClientContext"; import AutoHideScrollbar from "./AutoHideScrollbar"; diff --git a/src/components/structures/FilePanel.js b/src/components/structures/FilePanel.tsx similarity index 85% rename from src/components/structures/FilePanel.js rename to src/components/structures/FilePanel.tsx index bb7c1f9642..21ef0c4f31 100644 --- a/src/components/structures/FilePanel.js +++ b/src/components/structures/FilePanel.tsx @@ -16,37 +16,49 @@ limitations under the License. */ import React from 'react'; -import PropTypes from 'prop-types'; -import {Filter} from 'matrix-js-sdk/src/filter'; +import { Filter } from 'matrix-js-sdk/src/filter'; +import { EventTimelineSet } from "matrix-js-sdk/src/models/event-timeline-set"; +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 { MatrixClientPeg } from '../../MatrixClientPeg'; import EventIndexPeg from "../../indexing/EventIndexPeg"; import { _t } from '../../languageHandler'; import BaseCard from "../views/right_panel/BaseCard"; -import {RightPanelPhases} from "../../stores/RightPanelStorePhases"; -import DesktopBuildsNotice, {WarningKind} from "../views/elements/DesktopBuildsNotice"; -import {replaceableComponent} from "../../utils/replaceableComponent"; +import { RightPanelPhases } from "../../stores/RightPanelStorePhases"; +import DesktopBuildsNotice, { WarningKind } from "../views/elements/DesktopBuildsNotice"; +import { replaceableComponent } from "../../utils/replaceableComponent"; + +import ResizeNotifier from '../../utils/ResizeNotifier'; + +interface IProps { + roomId: string; + onClose: () => void; + resizeNotifier: ResizeNotifier +} + +interface IState { + timelineSet: EventTimelineSet; +} /* * Component which shows the filtered file using a TimelinePanel */ @replaceableComponent("structures.FilePanel") -class FilePanel extends React.Component { - static propTypes = { - roomId: PropTypes.string.isRequired, - onClose: PropTypes.func.isRequired, - }; - +class FilePanel extends React.Component { // This is used to track if a decrypted event was a live event and should be // added to the timeline. - decryptingEvents = new Set(); + private decryptingEvents = new Set(); + public noRoom: boolean; state = { timelineSet: null, }; - onRoomTimeline = (ev, room, toStartOfTimeline, removed, data) => { + private onRoomTimeline = (ev: MatrixEvent, room: Room, toStartOfTimeline: true, removed: true, data: any): void => { if (room?.roomId !== this.props?.roomId) return; if (toStartOfTimeline || !data || !data.liveEvent || ev.isRedacted()) return; @@ -60,7 +72,7 @@ class FilePanel extends React.Component { } }; - onEventDecrypted = (ev, err) => { + private onEventDecrypted = (ev: MatrixEvent, err?: any): void => { if (ev.getRoomId() !== this.props.roomId) return; const eventId = ev.getId(); @@ -70,7 +82,7 @@ class FilePanel extends React.Component { this.addEncryptedLiveEvent(ev); }; - addEncryptedLiveEvent(ev, toStartOfTimeline) { + public addEncryptedLiveEvent(ev: MatrixEvent): void { if (!this.state.timelineSet) return; const timeline = this.state.timelineSet.getLiveTimeline(); @@ -84,7 +96,7 @@ class FilePanel extends React.Component { } } - async componentDidMount() { + public async componentDidMount(): Promise { const client = MatrixClientPeg.get(); await this.updateTimelineSet(this.props.roomId); @@ -105,7 +117,7 @@ class FilePanel extends React.Component { } } - componentWillUnmount() { + public componentWillUnmount(): void { const client = MatrixClientPeg.get(); if (client === null) return; @@ -117,7 +129,7 @@ class FilePanel extends React.Component { } } - async fetchFileEventsServer(room) { + public async fetchFileEventsServer(room: Room): Promise { const client = MatrixClientPeg.get(); const filter = new Filter(client.credentials.userId); @@ -141,7 +153,7 @@ class FilePanel extends React.Component { return timelineSet; } - onPaginationRequest = (timelineWindow, direction, limit) => { + private onPaginationRequest = (timelineWindow: TimelineWindow, direction: string, limit: number): void => { const client = MatrixClientPeg.get(); const eventIndex = EventIndexPeg.get(); const roomId = this.props.roomId; @@ -159,7 +171,7 @@ class FilePanel extends React.Component { } }; - async updateTimelineSet(roomId: string) { + public async updateTimelineSet(roomId: string): Promise { const client = MatrixClientPeg.get(); const room = client.getRoom(roomId); const eventIndex = EventIndexPeg.get(); @@ -195,7 +207,7 @@ class FilePanel extends React.Component { } } - render() { + public render() { if (MatrixClientPeg.get().isGuest()) { return { // only dispatch if its not a no-op if (this.state.selectedTags.length > 0) { - dis.dispatch({action: 'deselect_tags'}); + dis.dispatch({ action: 'deselect_tags' }); } }; onClearFilterClick = ev => { - dis.dispatch({action: 'deselect_tags'}); + dis.dispatch({ action: 'deselect_tags' }); }; renderGlobalIcon() { diff --git a/src/components/structures/GroupView.js b/src/components/structures/GroupView.js index 3a2c611cc9..93c44c4e50 100644 --- a/src/components/structures/GroupView.js +++ b/src/components/structures/GroupView.js @@ -18,7 +18,7 @@ limitations under the License. import React from 'react'; import PropTypes from 'prop-types'; -import {MatrixClientPeg} from '../../MatrixClientPeg'; +import { MatrixClientPeg } from '../../MatrixClientPeg'; import * as sdk from '../../index'; import dis from '../../dispatcher/dispatcher'; import { getHostingLink } from '../../utils/HostingLink'; @@ -34,13 +34,13 @@ import classnames from 'classnames'; import GroupStore from '../../stores/GroupStore'; import FlairStore from '../../stores/FlairStore'; import { showGroupAddRoomDialog } from '../../GroupAddressPicker'; -import {makeGroupPermalink, makeUserPermalink} from "../../utils/permalinks/Permalinks"; -import {Group} from "matrix-js-sdk/src/models/group"; -import {sleep} from "../../utils/promise"; +import { makeGroupPermalink, makeUserPermalink } from "../../utils/permalinks/Permalinks"; +import { Group } from "matrix-js-sdk/src/models/group"; +import { sleep } from "../../utils/promise"; import RightPanelStore from "../../stores/RightPanelStore"; import AutoHideScrollbar from "./AutoHideScrollbar"; -import {mediaFromMxc} from "../../customisations/Media"; -import {replaceableComponent} from "../../utils/replaceableComponent"; +import { mediaFromMxc } from "../../customisations/Media"; +import { replaceableComponent } from "../../utils/replaceableComponent"; const LONG_DESC_PLACEHOLDER = _td( `

HTML for your community's page

@@ -115,7 +115,7 @@ class CategoryRoomList extends React.Component { { title: _t( "Failed to add the following rooms to the summary of %(groupId)s:", - {groupId: this.props.groupId}, + { groupId: this.props.groupId }, ), description: errorList.join(", "), }, @@ -126,12 +126,11 @@ class CategoryRoomList extends React.Component { }; render() { - const TintableSvg = sdk.getComponent("elements.TintableSvg"); const addButton = this.props.editing ? ( - +
{ _t('Add a Room') }
@@ -195,9 +194,9 @@ class FeaturedRoom extends React.Component { { title: _t( "Failed to remove the room from the summary of %(groupId)s", - {groupId: this.props.groupId}, + { groupId: this.props.groupId }, ), - description: _t("The room '%(roomName)s' could not be removed from the summary.", {roomName}), + description: _t("The room '%(roomName)s' could not be removed from the summary.", { roomName }), }, ); }); @@ -289,7 +288,7 @@ class RoleUserList extends React.Component { { title: _t( "Failed to add the following users to the summary of %(groupId)s:", - {groupId: this.props.groupId}, + { groupId: this.props.groupId }, ), description: errorList.join(", "), }, @@ -300,10 +299,9 @@ class RoleUserList extends React.Component { }; render() { - const TintableSvg = sdk.getComponent("elements.TintableSvg"); const addButton = this.props.editing ? ( - +
{ _t('Add a User') }
@@ -361,9 +359,12 @@ class FeaturedUser extends React.Component { { title: _t( "Failed to remove a user from the summary of %(groupId)s", - {groupId: this.props.groupId}, + { groupId: this.props.groupId }, + ), + description: _t( + "The user '%(displayName)s' could not be removed from the summary.", + { displayName }, ), - description: _t("The user '%(displayName)s' could not be removed from the summary.", {displayName}), }, ); }); @@ -470,7 +471,7 @@ export default class GroupView extends React.Component { // Leave settings - the user might have clicked the "Leave" button this._closeSettings(); } - this.setState({membershipBusy: false}); + this.setState({ membershipBusy: false }); }; _initGroupStore(groupId, firstInit) { @@ -491,7 +492,7 @@ export default class GroupView extends React.Component { group_id: groupId, }, }); - dis.dispatch({action: 'require_registration', screen_after: {screen: `group/${groupId}`}}); + dis.dispatch({ action: 'require_registration', screen_after: { screen: `group/${groupId}` } }); willDoOnboarding = true; } if (stateKey === GroupStore.STATE_KEY.Summary) { @@ -592,7 +593,7 @@ export default class GroupView extends React.Component { }; _closeSettings = () => { - dis.dispatch({action: 'close_settings'}); + dis.dispatch({ action: 'close_settings' }); }; _onNameChange = (value) => { @@ -620,7 +621,7 @@ export default class GroupView extends React.Component { const file = ev.target.files[0]; if (!file) return; - this.setState({uploadingAvatar: true}); + this.setState({ uploadingAvatar: true }); this._matrixClient.uploadContent(file).then((url) => { const newProfileForm = Object.assign(this.state.profileForm, { avatar_url: url }); this.setState({ @@ -632,7 +633,7 @@ export default class GroupView extends React.Component { avatarChanged: true, }); }).catch((e) => { - this.setState({uploadingAvatar: false}); + this.setState({ uploadingAvatar: false }); const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog"); console.error("Failed to upload avatar image", e); Modal.createTrackedDialog('Failed to upload image', '', ErrorDialog, { @@ -649,7 +650,7 @@ export default class GroupView extends React.Component { }; _onSaveClick = () => { - this.setState({saving: true}); + this.setState({ saving: true }); const savePromise = this.state.isUserPrivileged ? this._saveGroup() : Promise.resolve(); savePromise.then((result) => { this.setState({ @@ -688,7 +689,7 @@ export default class GroupView extends React.Component { } _onAcceptInviteClick = async () => { - this.setState({membershipBusy: true}); + this.setState({ membershipBusy: true }); // Wait 500ms to prevent flashing. Do this before sending a request otherwise we risk the // spinner disappearing after we have fetched new group data. @@ -697,7 +698,7 @@ export default class GroupView extends React.Component { GroupStore.acceptGroupInvite(this.props.groupId).then(() => { // don't reset membershipBusy here: wait for the membership change to come down the sync }).catch((e) => { - this.setState({membershipBusy: false}); + this.setState({ membershipBusy: false }); const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog"); Modal.createTrackedDialog('Error accepting invite', '', ErrorDialog, { title: _t("Error"), @@ -707,7 +708,7 @@ export default class GroupView extends React.Component { }; _onRejectInviteClick = async () => { - this.setState({membershipBusy: true}); + this.setState({ membershipBusy: true }); // Wait 500ms to prevent flashing. Do this before sending a request otherwise we risk the // spinner disappearing after we have fetched new group data. @@ -716,7 +717,7 @@ export default class GroupView extends React.Component { GroupStore.leaveGroup(this.props.groupId).then(() => { // don't reset membershipBusy here: wait for the membership change to come down the sync }).catch((e) => { - this.setState({membershipBusy: false}); + this.setState({ membershipBusy: false }); const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog"); Modal.createTrackedDialog('Error rejecting invite', '', ErrorDialog, { title: _t("Error"), @@ -727,11 +728,11 @@ export default class GroupView extends React.Component { _onJoinClick = async () => { if (this._matrixClient.isGuest()) { - dis.dispatch({action: 'require_registration', screen_after: {screen: `group/${this.props.groupId}`}}); + dis.dispatch({ action: 'require_registration', screen_after: { screen: `group/${this.props.groupId}` } }); return; } - this.setState({membershipBusy: true}); + this.setState({ membershipBusy: true }); // Wait 500ms to prevent flashing. Do this before sending a request otherwise we risk the // spinner disappearing after we have fetched new group data. @@ -740,7 +741,7 @@ export default class GroupView extends React.Component { GroupStore.joinGroup(this.props.groupId).then(() => { // don't reset membershipBusy here: wait for the membership change to come down the sync }).catch((e) => { - this.setState({membershipBusy: false}); + this.setState({ membershipBusy: false }); const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog"); Modal.createTrackedDialog('Error joining room', '', ErrorDialog, { title: _t("Error"), @@ -773,7 +774,7 @@ export default class GroupView extends React.Component { title: _t("Leave Community"), description: ( - { _t("Leave %(groupName)s?", {groupName: this.props.groupId}) } + { _t("Leave %(groupName)s?", { groupName: this.props.groupId }) } { warnings } ), @@ -782,7 +783,7 @@ export default class GroupView extends React.Component { onFinished: async (confirmed) => { if (!confirmed) return; - this.setState({membershipBusy: true}); + this.setState({ membershipBusy: true }); // Wait 500ms to prevent flashing. Do this before sending a request otherwise we risk the // spinner disappearing after we have fetched new group data. @@ -791,7 +792,7 @@ export default class GroupView extends React.Component { GroupStore.leaveGroup(this.props.groupId).then(() => { // don't reset membershipBusy here: wait for the membership change to come down the sync }).catch((e) => { - this.setState({membershipBusy: false}); + this.setState({ membershipBusy: false }); const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog"); Modal.createTrackedDialog('Error leaving community', '', ErrorDialog, { title: _t("Error"), @@ -855,7 +856,6 @@ export default class GroupView extends React.Component { _getRoomsNode() { const RoomDetailList = sdk.getComponent('rooms.RoomDetailList'); const AccessibleButton = sdk.getComponent('elements.AccessibleButton'); - const TintableSvg = sdk.getComponent('elements.TintableSvg'); const Spinner = sdk.getComponent('elements.Spinner'); const TooltipButton = sdk.getComponent('elements.TooltipButton'); @@ -871,7 +871,7 @@ export default class GroupView extends React.Component { onClick={this._onAddRoomsClick} >
- +
{ _t('Add rooms to this community') } @@ -1336,7 +1336,7 @@ export default class GroupView extends React.Component { if (this.state.error.httpStatus === 404) { return (
- { _t('Community %(groupId)s not found', {groupId: this.props.groupId}) } + { _t('Community %(groupId)s not found', { groupId: this.props.groupId }) }
); } else { @@ -1346,7 +1346,7 @@ export default class GroupView extends React.Component { } return (
- { _t('Failed to load %(groupId)s', {groupId: this.props.groupId }) } + { _t('Failed to load %(groupId)s', { groupId: this.props.groupId }) } { extraText }
); diff --git a/src/components/structures/HomePage.tsx b/src/components/structures/HomePage.tsx index 68bb4322e6..046e07f455 100644 --- a/src/components/structures/HomePage.tsx +++ b/src/components/structures/HomePage.tsx @@ -15,29 +15,29 @@ limitations under the License. */ import * as React from "react"; -import {useContext, useState} from "react"; +import { useContext, useState } from "react"; import AutoHideScrollbar from './AutoHideScrollbar'; -import {getHomePageUrl} from "../../utils/pages"; -import {_t} from "../../languageHandler"; +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 { Action } from "../../dispatcher/actions"; import BaseAvatar from "../views/avatars/BaseAvatar"; -import {OwnProfileStore} from "../../stores/OwnProfileStore"; +import { OwnProfileStore } from "../../stores/OwnProfileStore"; import AccessibleButton from "../views/elements/AccessibleButton"; -import {UPDATE_EVENT} from "../../stores/AsyncStore"; -import {useEventEmitter} from "../../hooks/useEventEmitter"; +import { UPDATE_EVENT } from "../../stores/AsyncStore"; +import { useEventEmitter } from "../../hooks/useEventEmitter"; import MatrixClientContext from "../../contexts/MatrixClientContext"; -import MiniAvatarUploader, {AVATAR_SIZE} from "../views/elements/MiniAvatarUploader"; +import MiniAvatarUploader, { AVATAR_SIZE } from "../views/elements/MiniAvatarUploader"; import Analytics from "../../Analytics"; import CountlyAnalytics from "../../CountlyAnalytics"; const onClickSendDm = () => { Analytics.trackEvent('home_page', 'button', 'dm'); CountlyAnalytics.instance.track("home_page_button", { button: "dm" }); - dis.dispatch({action: 'view_create_chat'}); + dis.dispatch({ action: 'view_create_chat' }); }; const onClickExplore = () => { @@ -49,7 +49,7 @@ const onClickExplore = () => { const onClickNewRoom = () => { Analytics.trackEvent('home_page', 'button', 'create_room'); CountlyAnalytics.instance.track("home_page_button", { button: "create_room" }); - dis.dispatch({action: 'view_create_room'}); + dis.dispatch({ action: 'view_create_room' }); }; interface IProps { @@ -117,7 +117,6 @@ const HomePage: React.FC = ({ justRegistered = false }) => { ; } - return
{ introSection } diff --git a/src/components/structures/HostSignupAction.tsx b/src/components/structures/HostSignupAction.tsx index 46e158d6c8..41dc8a6da8 100644 --- a/src/components/structures/HostSignupAction.tsx +++ b/src/components/structures/HostSignupAction.tsx @@ -22,7 +22,7 @@ import { import { _t } from "../../languageHandler"; import { HostSignupStore } from "../../stores/HostSignupStore"; import SdkConfig from "../../SdkConfig"; -import {replaceableComponent} from "../../utils/replaceableComponent"; +import { replaceableComponent } from "../../utils/replaceableComponent"; interface IProps { onClick?(): void; @@ -35,7 +35,7 @@ export default class HostSignupAction extends React.PureComponent { this.props.onClick?.(); await HostSignupStore.instance.setHostSignupActive(true); - } + }; public render(): React.ReactNode { const hostSignupConfig = SdkConfig.get().hostSignup; diff --git a/src/components/structures/IndicatorScrollbar.js b/src/components/structures/IndicatorScrollbar.js index 25dcaeed39..3e1940955b 100644 --- a/src/components/structures/IndicatorScrollbar.js +++ b/src/components/structures/IndicatorScrollbar.js @@ -17,7 +17,7 @@ limitations under the License. import React from "react"; import PropTypes from "prop-types"; import AutoHideScrollbar from "./AutoHideScrollbar"; -import {replaceableComponent} from "../../utils/replaceableComponent"; +import { replaceableComponent } from "../../utils/replaceableComponent"; @replaceableComponent("structures.IndicatorScrollbar") export default class IndicatorScrollbar extends React.Component { @@ -70,7 +70,6 @@ export default class IndicatorScrollbar extends React.Component { this._autoHideScrollbar = autoHideScrollbar; } - componentDidUpdate(prevProps) { const prevLen = prevProps && prevProps.children && prevProps.children.length || 0; const curLen = this.props.children && this.props.children.length || 0; @@ -188,8 +187,8 @@ export default class IndicatorScrollbar extends React.Component { // eslint-disable-next-line no-unused-vars const { children, trackHorizontalOverflow, verticalScrollsHorizontally, ...otherProps } = this.props; - const leftIndicatorStyle = {left: this.state.leftIndicatorOffset}; - const rightIndicatorStyle = {right: this.state.rightIndicatorOffset}; + const leftIndicatorStyle = { left: this.state.leftIndicatorOffset }; + const rightIndicatorStyle = { right: this.state.rightIndicatorOffset }; const leftOverflowIndicator = trackHorizontalOverflow ?
: null; const rightOverflowIndicator = trackHorizontalOverflow diff --git a/src/components/structures/InteractiveAuth.js b/src/components/structures/InteractiveAuth.js index d419c9de6e..9ff830f66a 100644 --- a/src/components/structures/InteractiveAuth.js +++ b/src/components/structures/InteractiveAuth.js @@ -15,14 +15,14 @@ See the License for the specific language governing permissions and limitations under the License. */ -import {InteractiveAuth} from "matrix-js-sdk/src/interactive-auth"; -import React, {createRef} from 'react'; +import { InteractiveAuth } from "matrix-js-sdk/src/interactive-auth"; +import React, { createRef } from 'react'; import PropTypes from 'prop-types'; import getEntryComponentForLoginType from '../views/auth/InteractiveAuthEntryComponents'; import * as sdk from '../../index'; -import {replaceableComponent} from "../../utils/replaceableComponent"; +import { replaceableComponent } from "../../utils/replaceableComponent"; export const ERROR_USER_CANCELLED = new Error("User cancelled auth session"); diff --git a/src/components/structures/LeftPanel.tsx b/src/components/structures/LeftPanel.tsx index dec4e4c13e..3d5e386b00 100644 --- a/src/components/structures/LeftPanel.tsx +++ b/src/components/structures/LeftPanel.tsx @@ -40,9 +40,9 @@ import AccessibleTooltipButton from "../views/elements/AccessibleTooltipButton"; import { OwnProfileStore } from "../../stores/OwnProfileStore"; import RoomListNumResults from "../views/rooms/RoomListNumResults"; import LeftPanelWidget from "./LeftPanelWidget"; -import {replaceableComponent} from "../../utils/replaceableComponent"; -import {mediaFromMxc} from "../../customisations/Media"; -import SpaceStore, {UPDATE_SELECTED_SPACE} from "../../stores/SpaceStore"; +import { replaceableComponent } from "../../utils/replaceableComponent"; +import { mediaFromMxc } from "../../customisations/Media"; +import SpaceStore, { UPDATE_SELECTED_SPACE } from "../../stores/SpaceStore"; import { getKeyBindingsManager, RoomListAction } from "../../KeyBindingsManager"; import UIStore from "../../stores/UIStore"; @@ -91,7 +91,7 @@ export default class LeftPanel extends React.Component { this.bgImageWatcherRef = SettingsStore.watchSetting( "RoomList.backgroundImage", null, this.onBackgroundImageUpdate); this.groupFilterPanelWatcherRef = SettingsStore.watchSetting("TagPanel.enableTagPanel", null, () => { - this.setState({showGroupFilterPanel: SettingsStore.getValue("TagPanel.enableTagPanel")}); + this.setState({ showGroupFilterPanel: SettingsStore.getValue("TagPanel.enableTagPanel") }); }); } @@ -127,7 +127,7 @@ export default class LeftPanel extends React.Component { private onDialPad = () => { dis.fire(Action.OpenDialPad); - } + }; private onExplore = () => { dis.fire(Action.ViewRoomDirectory); @@ -136,12 +136,12 @@ export default class LeftPanel extends React.Component { private refreshStickyHeaders = () => { if (!this.listContainerRef.current) return; // ignore: no headers to sticky this.handleStickyHeaders(this.listContainerRef.current); - } + }; private onBreadcrumbsUpdate = () => { const newVal = BreadcrumbsStore.instance.visible; if (newVal !== this.state.showBreadcrumbs) { - this.setState({showBreadcrumbs: newVal}); + this.setState({ showBreadcrumbs: newVal }); // Update the sticky headers too as the breadcrumbs will be popping in or out. if (!this.listContainerRef.current) return; // ignore: no headers to sticky diff --git a/src/components/structures/LeftPanelWidget.tsx b/src/components/structures/LeftPanelWidget.tsx index 16142069c4..e0b597b883 100644 --- a/src/components/structures/LeftPanelWidget.tsx +++ b/src/components/structures/LeftPanelWidget.tsx @@ -14,19 +14,19 @@ See the License for the specific language governing permissions and limitations under the License. */ -import React, {useContext, useMemo} from "react"; -import {Resizable} from "re-resizable"; +import React, { useContext, useMemo } from "react"; +import { Resizable } from "re-resizable"; import classNames from "classnames"; import AccessibleButton from "../views/elements/AccessibleButton"; -import {useRovingTabIndex} from "../../accessibility/RovingTabIndex"; -import {Key} from "../../Keyboard"; -import {useLocalStorageState} from "../../hooks/useLocalStorageState"; +import { useRovingTabIndex } from "../../accessibility/RovingTabIndex"; +import { Key } from "../../Keyboard"; +import { useLocalStorageState } from "../../hooks/useLocalStorageState"; import MatrixClientContext from "../../contexts/MatrixClientContext"; -import WidgetUtils, {IWidgetEvent} from "../../utils/WidgetUtils"; -import {useAccountData} from "../../hooks/useAccountData"; +import WidgetUtils, { IWidgetEvent } from "../../utils/WidgetUtils"; +import { useAccountData } from "../../hooks/useAccountData"; import AppTile from "../views/elements/AppTile"; -import {useSettingValue} from "../../hooks/useSettings"; +import { useSettingValue } from "../../hooks/useSettings"; import UIStore from "../../stores/UIStore"; const MIN_HEIGHT = 100; @@ -62,14 +62,14 @@ const LeftPanelWidget: React.FC = () => { let content; if (expanded) { content = { setHeight(height + d.height); }} handleWrapperClass="mx_LeftPanelWidget_resizerHandles" - handleClasses={{top: "mx_LeftPanelWidget_resizerHandle"}} + handleClasses={{ top: "mx_LeftPanelWidget_resizerHandle" }} className="mx_LeftPanelWidget_resizeBox" enable={{ top: true }} > diff --git a/src/components/structures/LoggedInView.tsx b/src/components/structures/LoggedInView.tsx index 5ad67232a4..26bb0fe24a 100644 --- a/src/components/structures/LoggedInView.tsx +++ b/src/components/structures/LoggedInView.tsx @@ -20,7 +20,7 @@ import * as React from 'react'; import * as PropTypes from 'prop-types'; import { MatrixClient } from 'matrix-js-sdk/src/client'; -import {Key} from '../../Keyboard'; +import { Key } from '../../Keyboard'; import PageTypes from '../../PageTypes'; import MediaDeviceHandler from '../../MediaDeviceHandler'; import { fixupColorFonts } from '../../utils/FontManager'; @@ -30,7 +30,7 @@ import { IMatrixClientCreds } from '../../MatrixClientPeg'; import SettingsStore from "../../settings/SettingsStore"; import ResizeHandle from '../views/elements/ResizeHandle'; -import {Resizer, CollapseDistributor} from '../../resizer'; +import { Resizer, CollapseDistributor } from '../../resizer'; import MatrixClientContext from "../../contexts/MatrixClientContext"; import * as KeyboardShortcuts from "../../accessibility/KeyboardShortcuts"; import HomePage from "./HomePage"; @@ -55,7 +55,7 @@ import HostSignupContainer from '../views/host_signup/HostSignupContainer'; import { getKeyBindingsManager, NavigationAction, RoomAction } from '../../KeyBindingsManager'; import { IOpts } from "../../createRoom"; import SpacePanel from "../views/spaces/SpacePanel"; -import {replaceableComponent} from "../../utils/replaceableComponent"; +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'; @@ -232,10 +232,10 @@ class LoggedInView extends React.Component { onCollapsed: (_collapsed) => { collapsed = _collapsed; if (_collapsed) { - dis.dispatch({action: "hide_left_panel"}); + dis.dispatch({ action: "hide_left_panel" }); window.localStorage.setItem("mx_lhs_size", '0'); } else { - dis.dispatch({action: "show_left_panel"}); + dis.dispatch({ action: "show_left_panel" }); } }, onResized: (_size) => { @@ -272,7 +272,7 @@ class LoggedInView extends React.Component { onAccountData = (event) => { if (event.getType() === "m.ignored_user_list") { - dis.dispatch({action: "ignore_state_changed"}); + dis.dispatch({ action: "ignore_state_changed" }); } }; @@ -319,7 +319,7 @@ class LoggedInView extends React.Component { this.setState({ usageLimitDismissed: true, }); - } + }; _calculateServerLimitToast(syncError: IState["syncErrorData"], usageLimitEventContent?: IUsageLimit) { const error = syncError && syncError.error && syncError.error.errcode === "M_RESOURCE_LIMIT_EXCEEDED"; diff --git a/src/components/structures/MainSplit.js b/src/components/structures/MainSplit.js index 5818d303fc..69d3bd0b51 100644 --- a/src/components/structures/MainSplit.js +++ b/src/components/structures/MainSplit.js @@ -17,7 +17,7 @@ limitations under the License. import React from 'react'; import { Resizable } from 're-resizable'; -import {replaceableComponent} from "../../utils/replaceableComponent"; +import { replaceableComponent } from "../../utils/replaceableComponent"; @replaceableComponent("structures.MainSplit") export default class MainSplit extends React.Component { @@ -73,7 +73,7 @@ export default class MainSplit extends React.Component { onResize={this._onResize} onResizeStop={this._onResizeStop} className="mx_RightPanel_ResizeWrapper" - handleClasses={{left: "mx_RightPanel_ResizeHandle"}} + handleClasses={{ left: "mx_RightPanel_ResizeHandle" }} > { panelView } ; diff --git a/src/components/structures/MatrixChat.tsx b/src/components/structures/MatrixChat.tsx index 7986da203d..c1e0b8d7cb 100644 --- a/src/components/structures/MatrixChat.tsx +++ b/src/components/structures/MatrixChat.tsx @@ -34,7 +34,6 @@ import dis from "../../dispatcher/dispatcher"; import Notifier from '../../Notifier'; import Modal from "../../Modal"; -import Tinter from "../../Tinter"; import * as sdk from '../../index'; import { showRoomInviteDialog, showStartChatInviteDialog } from '../../RoomInvite'; import * as Rooms from '../../Rooms'; @@ -44,8 +43,8 @@ import * as Lifecycle from '../../Lifecycle'; import '../../stores/LifecycleStore'; import PageTypes from '../../PageTypes'; -import createRoom, {IOpts} from "../../createRoom"; -import {_t, _td, getCurrentLanguage} from '../../languageHandler'; +import createRoom, { IOpts } from "../../createRoom"; +import { _t, _td, getCurrentLanguage } from '../../languageHandler'; import SettingsStore from "../../settings/SettingsStore"; import ThemeController from "../../settings/controllers/ThemeController"; import { startAnyRegistrationFlow } from "../../Registration"; @@ -66,7 +65,7 @@ import { showToast as showAnalyticsToast, hideToast as hideAnalyticsToast, } from "../../toasts/AnalyticsToast"; -import {showToast as showNotificationsToast} from "../../toasts/DesktopNotificationsToast"; +import { showToast as showNotificationsToast } from "../../toasts/DesktopNotificationsToast"; import { OpenToTabPayload } from "../../dispatcher/payloads/OpenToTabPayload"; import ErrorDialog from "../views/dialogs/ErrorDialog"; import { RoomNotificationStateStore } from "../../stores/notifications/RoomNotificationStateStore"; @@ -74,15 +73,15 @@ import { SettingLevel } from "../../settings/SettingLevel"; import { leaveRoomBehaviour } from "../../utils/membership"; import CreateCommunityPrototypeDialog from "../views/dialogs/CreateCommunityPrototypeDialog"; import ThreepidInviteStore, { IThreepidInvite, IThreepidInviteWireFormat } from "../../stores/ThreepidInviteStore"; -import {UIFeature} from "../../settings/UIFeature"; +import { UIFeature } from "../../settings/UIFeature"; import { CommunityPrototypeStore } from "../../stores/CommunityPrototypeStore"; import DialPadModal from "../views/voip/DialPadModal"; import { showToast as showMobileGuideToast } from '../../toasts/MobileGuideToast'; import { shouldUseLoginForWelcome } from "../../utils/pages"; import SpaceStore from "../../stores/SpaceStore"; -import {replaceableComponent} from "../../utils/replaceableComponent"; +import { replaceableComponent } from "../../utils/replaceableComponent"; import RoomListStore from "../../stores/room-list/RoomListStore"; -import {RoomUpdateCause} from "../../stores/room-list/models"; +import { RoomUpdateCause } from "../../stores/room-list/models"; import defaultDispatcher from "../../dispatcher/dispatcher"; import SecurityCustomisations from "../../customisations/Security"; @@ -283,11 +282,6 @@ export default class MatrixChat extends React.PureComponent { this.pageChanging = false; - // check we have the right tint applied for this theme. - // N.B. we don't call the whole of setTheme() here as we may be - // racing with the theme CSS download finishing from index.js - Tinter.tint(); - // For PersistentElement this.state.resizeNotifier.on("middlePanelResized", this.dispatchTimelineResize); @@ -401,7 +395,7 @@ export default class MatrixChat extends React.PureComponent { if (SecurityCustomisations.SHOW_ENCRYPTION_SETUP_UI === false) { this.onLoggedIn(); } else { - this.setStateForNewView({view: Views.COMPLETE_SECURITY}); + this.setStateForNewView({ view: Views.COMPLETE_SECURITY }); } } else if (await cli.doesServerSupportUnstableFeature("org.matrix.e2e_cross_signing")) { this.setStateForNewView({ view: Views.E2E_SETUP }); @@ -454,7 +448,7 @@ export default class MatrixChat extends React.PureComponent { let props = this.state.serverConfig; if (!props) props = this.props.serverConfig; // for unit tests if (!props) props = SdkConfig.get()["validated_server_config"]; - return {serverConfig: props}; + return { serverConfig: props }; } private loadSession() { @@ -472,9 +466,9 @@ export default class MatrixChat extends React.PureComponent { if (!loadedSession) { // fall back to showing the welcome screen... unless we have a 3pid invite pending if (ThreepidInviteStore.instance.pickBestInvite()) { - dis.dispatch({action: 'start_registration'}); + dis.dispatch({ action: 'start_registration' }); } else { - dis.dispatch({action: "view_welcome_page"}); + dis.dispatch({ action: "view_welcome_page" }); } } else if (SettingsStore.getValue("analyticsOptIn")) { CountlyAnalytics.instance.enable(/* anonymous = */ false); @@ -538,7 +532,7 @@ export default class MatrixChat extends React.PureComponent { action: 'do_after_sync_prepared', deferred_action: payload, }); - dis.dispatch({action: 'require_registration'}); + dis.dispatch({ action: 'require_registration' }); return; } @@ -563,11 +557,11 @@ export default class MatrixChat extends React.PureComponent { } // redispatch the change with a more specific action - dis.dispatch({action: 'id_server_changed'}); + dis.dispatch({ action: 'id_server_changed' }); } break; case 'logout': - dis.dispatch({action: "hangup_all"}); + dis.dispatch({ action: "hangup_all" }); Lifecycle.logout(); break; case 'require_registration': @@ -624,7 +618,7 @@ export default class MatrixChat extends React.PureComponent { MatrixClientPeg.get().leave(payload.room_id).then(() => { modal.close(); if (this.state.currentRoomId === payload.room_id) { - dis.dispatch({action: 'view_home_page'}); + dis.dispatch({ action: 'view_home_page' }); } }, (err) => { modal.close(); @@ -657,7 +651,7 @@ export default class MatrixChat extends React.PureComponent { const tabPayload = payload as OpenToTabPayload; const UserSettingsDialog = sdk.getComponent("dialogs.UserSettingsDialog"); Modal.createTrackedDialog('User settings', '', UserSettingsDialog, - {initialTabId: tabPayload.initialTabId}, + { initialTabId: tabPayload.initialTabId }, /*className=*/null, /*isPriority=*/false, /*isStatic=*/true); // View the welcome or home page if we need something to look at @@ -668,7 +662,7 @@ export default class MatrixChat extends React.PureComponent { this.createRoom(payload.public, payload.defaultName); break; case 'view_create_group': { - let CreateGroupDialog = sdk.getComponent("dialogs.CreateGroupDialog") + let CreateGroupDialog = sdk.getComponent("dialogs.CreateGroupDialog"); if (SettingsStore.getValue("feature_communities_v2_prototypes")) { CreateGroupDialog = CreateCommunityPrototypeDialog; } @@ -727,9 +721,9 @@ export default class MatrixChat extends React.PureComponent { // We just dispatch the page change rather than have to worry about // what the logic is for each of these branches. if (this.state.page_type === PageTypes.MyGroups) { - dis.dispatch({action: 'view_last_screen'}); + dis.dispatch({ action: 'view_last_screen' }); } else { - dis.dispatch({action: 'view_my_groups'}); + dis.dispatch({ action: 'view_my_groups' }); } break; case 'hide_left_panel': @@ -770,7 +764,7 @@ export default class MatrixChat extends React.PureComponent { this.onLoggedOut(); break; case 'will_start_client': - this.setState({ready: false}, () => { + this.setState({ ready: false }, () => { // if the client is about to start, we are, by definition, not ready. // Set ready to false now, then it'll be set to true when the sync // listener we set below fires. @@ -1006,7 +1000,7 @@ export default class MatrixChat extends React.PureComponent { return; } this.notifyNewScreen('user/' + userId); - this.setState({currentUserId: userId}); + this.setState({ currentUserId: userId }); this.setPage(PageTypes.UserView); }); } @@ -1131,8 +1125,14 @@ export default class MatrixChat extends React.PureComponent { description: ( { isSpace - ? _t("Are you sure you want to leave the space '%(spaceName)s'?", {spaceName: roomToLeave.name}) - : _t("Are you sure you want to leave the room '%(roomName)s'?", {roomName: roomToLeave.name}) } + ? _t( + "Are you sure you want to leave the space '%(spaceName)s'?", + { spaceName: roomToLeave.name }, + ) + : _t( + "Are you sure you want to leave the room '%(roomName)s'?", + { roomName: roomToLeave.name }, + )} { warnings } ), @@ -1170,7 +1170,7 @@ export default class MatrixChat extends React.PureComponent { }).catch((err) => { const errCode = err.errcode || _td("unknown error code"); Modal.createTrackedDialog("Failed to forget room", '', ErrorDialog, { - title: _t("Failed to forget room %(errCode)s", {errCode}), + title: _t("Failed to forget room %(errCode)s", { errCode }), description: ((err && err.message) ? err.message : _t("Operation failed")), }); }); @@ -1254,7 +1254,7 @@ export default class MatrixChat extends React.PureComponent { if (welcomeUserRoom === null) { // We didn't redirect to the welcome user room, so show // the homepage. - dis.dispatch({action: 'view_home_page', justRegistered: true}); + dis.dispatch({ action: 'view_home_page', justRegistered: true }); } } else if (ThreepidInviteStore.instance.pickBestInvite()) { // The user has a 3pid invite pending - show them that @@ -1263,11 +1263,11 @@ export default class MatrixChat extends React.PureComponent { // HACK: This is a pretty brutal way of threading the invite back through // our systems, but it's the safest we have for now. const params = ThreepidInviteStore.instance.translateToWireFormat(threepidInvite); - this.showScreen(`room/${threepidInvite.roomId}`, params) + this.showScreen(`room/${threepidInvite.roomId}`, params); } else { // The user has just logged in after registering, // so show the homepage. - dis.dispatch({action: 'view_home_page', justRegistered: true}); + dis.dispatch({ action: 'view_home_page', justRegistered: true }); } } else { this.showScreenAfterLogin(); @@ -1303,9 +1303,9 @@ export default class MatrixChat extends React.PureComponent { this.viewLastRoom(); } else { if (MatrixClientPeg.get().isGuest()) { - dis.dispatch({action: 'view_welcome_page'}); + dis.dispatch({ action: 'view_welcome_page' }); } else { - dis.dispatch({action: 'view_home_page'}); + dis.dispatch({ action: 'view_home_page' }); } } } @@ -1385,15 +1385,15 @@ export default class MatrixChat extends React.PureComponent { // So dispatch directly from here. Ideally we'd use a SyncStateStore that // would do this dispatch and expose the sync state itself (by listening to // its own dispatch). - dis.dispatch({action: 'sync_state', prevState, state}); + dis.dispatch({ action: 'sync_state', prevState, state }); if (state === "ERROR" || state === "RECONNECTING") { if (data.error instanceof InvalidStoreError) { Lifecycle.handleInvalidStoreError(data.error); } - this.setState({syncError: data.error || true}); + this.setState({ syncError: data.error || true }); } else if (this.state.syncError) { - this.setState({syncError: null}); + this.setState({ syncError: null }); } this.updateStatusIndicator(state, prevState); @@ -1567,16 +1567,12 @@ export default class MatrixChat extends React.PureComponent { key: 'verifreq_' + request.channel.transactionId, title: _t("Verification requested"), icon: "verification", - props: {request}, + props: { request }, component: sdk.getComponent("toasts.VerificationRequestToast"), priority: 90, }); } }); - // Fire the tinter right on startup to ensure the default theme is applied - // A later sync can/will correct the tint to be the right value for the user - const colorScheme = SettingsStore.getValue("roomColor"); - Tinter.tint(colorScheme.primary_color, colorScheme.secondary_color); } /** @@ -1668,7 +1664,7 @@ export default class MatrixChat extends React.PureComponent { // TODO if logged in, skip SSO let cli = MatrixClientPeg.get(); if (!cli) { - const {hsUrl, isUrl} = this.props.serverConfig; + const { hsUrl, isUrl } = this.props.serverConfig; cli = createClient({ baseUrl: hsUrl, idBaseUrl: isUrl, @@ -1792,7 +1788,7 @@ export default class MatrixChat extends React.PureComponent { onAliasClick(event: MouseEvent, alias: string) { event.preventDefault(); - dis.dispatch({action: 'view_room', room_alias: alias}); + dis.dispatch({ action: 'view_room', room_alias: alias }); } onUserClick(event: MouseEvent, userId: string) { @@ -1808,7 +1804,7 @@ export default class MatrixChat extends React.PureComponent { onGroupClick(event: MouseEvent, groupId: string) { event.preventDefault(); - dis.dispatch({action: 'view_group', group_id: groupId}); + dis.dispatch({ action: 'view_group', group_id: groupId }); } onLogoutClick(event: React.MouseEvent) { @@ -1870,14 +1866,14 @@ export default class MatrixChat extends React.PureComponent { onSendEvent(roomId: string, event: MatrixEvent) { const cli = MatrixClientPeg.get(); if (!cli) { - dis.dispatch({action: 'message_send_failed'}); + dis.dispatch({ action: 'message_send_failed' }); return; } cli.sendEvent(roomId, event.getType(), event.getContent()).then(() => { - dis.dispatch({action: 'message_sent'}); + dis.dispatch({ action: 'message_sent' }); }, (err) => { - dis.dispatch({action: 'message_send_failed'}); + dis.dispatch({ action: 'message_send_failed' }); }); } @@ -1924,7 +1920,7 @@ export default class MatrixChat extends React.PureComponent { } onServerConfigChange = (serverConfig: ValidatedServerConfig) => { - this.setState({serverConfig}); + this.setState({ serverConfig }); }; private makeRegistrationUrl = (params: {[key: string]: string}) => { diff --git a/src/components/structures/MessagePanel.js b/src/components/structures/MessagePanel.tsx similarity index 64% rename from src/components/structures/MessagePanel.js rename to src/components/structures/MessagePanel.tsx index 18ca91874b..d980df60ee 100644 --- a/src/components/structures/MessagePanel.js +++ b/src/components/structures/MessagePanel.tsx @@ -1,7 +1,5 @@ /* -Copyright 2016 OpenMarket Ltd -Copyright 2018 New Vector Ltd -Copyright 2019 The Matrix.org Foundation C.I.C. +Copyright 2016 - 2021 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. @@ -16,32 +14,47 @@ See the License for the specific language governing permissions and limitations under the License. */ -import React, {createRef} from 'react'; +import React, { createRef, KeyboardEvent, ReactNode, SyntheticEvent, TransitionEvent } from 'react'; import ReactDOM from 'react-dom'; -import PropTypes from 'prop-types'; -import shouldHideEvent from '../../shouldHideEvent'; -import {wantsDateSeparator} from '../../DateUtils'; -import * as sdk from '../../index'; +import { Room } from 'matrix-js-sdk/src/models/room'; +import { EventType } from 'matrix-js-sdk/src/@types/event'; +import { MatrixEvent } from 'matrix-js-sdk/src/models/event'; +import { Relations } from "matrix-js-sdk/src/models/relations"; +import { RoomMember } from 'matrix-js-sdk/src/models/room-member'; -import {MatrixClientPeg} from '../../MatrixClientPeg'; +import shouldHideEvent from '../../shouldHideEvent'; +import { wantsDateSeparator } from '../../DateUtils'; +import { MatrixClientPeg } from '../../MatrixClientPeg'; import SettingsStore from '../../settings/SettingsStore'; import RoomContext from "../../contexts/RoomContext"; -import {Layout, LayoutPropType} from "../../settings/Layout"; -import {_t} from "../../languageHandler"; -import {haveTileForEvent} from "../views/rooms/EventTile"; -import {hasText} from "../../TextForEvent"; +import { Layout } from "../../settings/Layout"; +import { _t } from "../../languageHandler"; +import EventTile, { haveTileForEvent, IReadReceiptProps, TileShape } from "../views/rooms/EventTile"; +import { hasText } from "../../TextForEvent"; import IRCTimelineProfileResizer from "../views/elements/IRCTimelineProfileResizer"; import DMRoomMap from "../../utils/DMRoomMap"; import NewRoomIntro from "../views/rooms/NewRoomIntro"; -import {replaceableComponent} from "../../utils/replaceableComponent"; +import { replaceableComponent } from "../../utils/replaceableComponent"; import defaultDispatcher from '../../dispatcher/dispatcher'; +import WhoIsTypingTile from '../views/rooms/WhoIsTypingTile'; +import ScrollPanel, { IScrollState } from "./ScrollPanel"; +import EventListSummary from '../views/elements/EventListSummary'; +import MemberEventListSummary from '../views/elements/MemberEventListSummary'; +import DateSeparator from '../views/messages/DateSeparator'; +import ErrorBoundary from '../views/elements/ErrorBoundary'; +import ResizeNotifier from "../../utils/ResizeNotifier"; +import Spinner from "../views/elements/Spinner"; +import TileErrorBoundary from '../views/messages/TileErrorBoundary'; +import { RoomPermalinkCreator } from "../../utils/permalinks/Permalinks"; +import EditorStateTransfer from "../../utils/EditorStateTransfer"; const CONTINUATION_MAX_INTERVAL = 5 * 60 * 1000; // 5 minutes -const continuedTypes = ['m.sticker', 'm.room.message']; +const continuedTypes = [EventType.Sticker, EventType.RoomMessage]; +const membershipTypes = [EventType.RoomMember, EventType.RoomThirdPartyInvite, EventType.RoomServerAcl]; // check if there is a previous event and it has the same sender as this event // and the types are the same/is in continuedTypes and the time between them is <= CONTINUATION_MAX_INTERVAL -export function shouldFormContinuation(prevEvent, mxEvent) { +export function shouldFormContinuation(prevEvent: MatrixEvent, mxEvent: MatrixEvent): boolean { // sanity check inputs if (!prevEvent || !prevEvent.sender || !mxEvent.sender) return false; // check if within the max continuation period @@ -52,8 +65,8 @@ export function shouldFormContinuation(prevEvent, mxEvent) { // Some events should appear as continuations from previous events of different types. if (mxEvent.getType() !== prevEvent.getType() && - (!continuedTypes.includes(mxEvent.getType()) || - !continuedTypes.includes(prevEvent.getType()))) return false; + (!continuedTypes.includes(mxEvent.getType() as EventType) || + !continuedTypes.includes(prevEvent.getType() as EventType))) return false; // Check if the sender is the same and hasn't changed their displayname/avatar between these events if (mxEvent.sender.userId !== prevEvent.sender.userId || @@ -66,96 +79,157 @@ export function shouldFormContinuation(prevEvent, mxEvent) { return true; } -const isMembershipChange = (e) => e.getType() === 'm.room.member' || e.getType() === 'm.room.third_party_invite'; +interface IProps { + // the list of MatrixEvents to display + events: MatrixEvent[]; + + // true to give the component a 'display: none' style. + hidden?: boolean; + + // true to show a spinner at the top of the timeline to indicate + // back-pagination in progress + backPaginating?: boolean; + + // true to show a spinner at the end of the timeline to indicate + // forward-pagination in progress + forwardPaginating?: boolean; + + // ID of an event to highlight. If undefined, no event will be highlighted. + highlightedEventId?: string; + + // The room these events are all in together, if any. + // (The notification panel won't have a room here, for example.) + room?: Room; + + // Should we show URL Previews + showUrlPreview?: boolean; + + // event after which we should show a read marker + readMarkerEventId?: string; + + // whether the read marker should be visible + readMarkerVisible?: boolean; + + // the userid of our user. This is used to suppress the read marker + // for pending messages. + ourUserId?: string; + + // true to suppress the date at the start of the timeline + suppressFirstDateSeparator?: boolean; + + // whether to show read receipts + showReadReceipts?: boolean; + + // true if updates to the event list should cause the scroll panel to + // scroll down when we are at the bottom of the window. See ScrollPanel + // for more details. + stickyBottom?: boolean; + + // className for the panel + className: string; + + // shape parameter to be passed to EventTiles + tileShape?: TileShape; + + // show twelve hour timestamps + isTwelveHour?: boolean; + + // show timestamps always + alwaysShowTimestamps?: boolean; + + // whether to show reactions for an event + showReactions?: boolean; + + // which layout to use + layout?: Layout; + + // whether or not to show flair at all + enableFlair?: boolean; + + resizeNotifier: ResizeNotifier; + permalinkCreator?: RoomPermalinkCreator; + editState?: EditorStateTransfer; + + // callback which is called when the panel is scrolled. + onScroll?(event: Event): void; + + // callback which is called when the user interacts with the room timeline + onUserScroll(event: SyntheticEvent): void; + + // callback which is called when more content is needed. + onFillRequest?(backwards: boolean): Promise; + + // helper function to access relations for an event + onUnfillRequest?(backwards: boolean, scrollToken: string): void; + + getRelationsForEvent?(eventId: string, relationType: string, eventType: string): Relations; +} + +interface IState { + ghostReadMarkers: string[]; + showTypingNotifications: boolean; +} + +interface IReadReceiptForUser { + lastShownEventId: string; + receipt: IReadReceiptProps; +} /* (almost) stateless UI component which builds the event tiles in the room timeline. */ @replaceableComponent("structures.MessagePanel") -export default class MessagePanel extends React.Component { - static propTypes = { - // true to give the component a 'display: none' style. - hidden: PropTypes.bool, - - // true to show a spinner at the top of the timeline to indicate - // back-pagination in progress - backPaginating: PropTypes.bool, - - // true to show a spinner at the end of the timeline to indicate - // forward-pagination in progress - forwardPaginating: PropTypes.bool, - - // the list of MatrixEvents to display - events: PropTypes.array.isRequired, - - // ID of an event to highlight. If undefined, no event will be highlighted. - highlightedEventId: PropTypes.string, - - // The room these events are all in together, if any. - // (The notification panel won't have a room here, for example.) - room: PropTypes.object, - - // Should we show URL Previews - showUrlPreview: PropTypes.bool, - - // event after which we should show a read marker - readMarkerEventId: PropTypes.string, - - // whether the read marker should be visible - readMarkerVisible: PropTypes.bool, - - // the userid of our user. This is used to suppress the read marker - // for pending messages. - ourUserId: PropTypes.string, - - // true to suppress the date at the start of the timeline - suppressFirstDateSeparator: PropTypes.bool, - - // whether to show read receipts - showReadReceipts: PropTypes.bool, - - // true if updates to the event list should cause the scroll panel to - // scroll down when we are at the bottom of the window. See ScrollPanel - // for more details. - stickyBottom: PropTypes.bool, - - // callback which is called when the panel is scrolled. - onScroll: PropTypes.func, - - // callback which is called when the user interacts with the room timeline - onUserScroll: PropTypes.func, - - // callback which is called when more content is needed. - onFillRequest: PropTypes.func, - - // className for the panel - className: PropTypes.string.isRequired, - - // shape parameter to be passed to EventTiles - tileShape: PropTypes.string, - - // show twelve hour timestamps - isTwelveHour: PropTypes.bool, - - // show timestamps always - alwaysShowTimestamps: PropTypes.bool, - - // helper function to access relations for an event - getRelationsForEvent: PropTypes.func, - - // whether to show reactions for an event - showReactions: PropTypes.bool, - - // which layout to use - layout: LayoutPropType, - - // whether or not to show flair at all - enableFlair: PropTypes.bool, - }; - +export default class MessagePanel extends React.Component { static contextType = RoomContext; - constructor(props) { - super(props); + // opaque readreceipt info for each userId; used by ReadReceiptMarker + // to manage its animations + private readonly readReceiptMap: Record = {}; + + // Track read receipts by event ID. For each _shown_ event ID, we store + // the list of read receipts to display: + // [ + // { + // userId: string, + // member: RoomMember, + // ts: number, + // }, + // ] + // This is recomputed on each render. It's only stored on the component + // for ease of passing the data around since it's computed in one pass + // over all events. + private readReceiptsByEvent: Record = {}; + + // Track read receipts by user ID. For each user ID we've ever shown a + // a read receipt for, we store an object: + // { + // lastShownEventId: string, + // receipt: { + // userId: string, + // member: RoomMember, + // ts: number, + // }, + // } + // so that we can always keep receipts displayed by reverting back to + // the last shown event for that user ID when needed. This may feel like + // it duplicates the receipt storage in the room, but at this layer, we + // are tracking _shown_ event IDs, which the JS SDK knows nothing about. + // This is recomputed on each render, using the data from the previous + // render as our fallback for any user IDs we can't match a receipt to a + // displayed event in the current render cycle. + private readReceiptsByUserId: Record = {}; + + private readonly showHiddenEventsInTimeline: boolean; + private isMounted = false; + + private readMarkerNode = createRef(); + private whoIsTyping = createRef(); + private scrollPanel = createRef(); + + private readonly showTypingNotificationsWatcherRef: string; + private eventNodes: Record; + + constructor(props, context) { + super(props, context); this.state = { // previous positions the read marker has been in, so we can @@ -164,65 +238,21 @@ export default class MessagePanel extends React.Component { showTypingNotifications: SettingsStore.getValue("showTypingNotifications"), }; - // opaque readreceipt info for each userId; used by ReadReceiptMarker - // to manage its animations - this._readReceiptMap = {}; - - // Track read receipts by event ID. For each _shown_ event ID, we store - // the list of read receipts to display: - // [ - // { - // userId: string, - // member: RoomMember, - // ts: number, - // }, - // ] - // This is recomputed on each render. It's only stored on the component - // for ease of passing the data around since it's computed in one pass - // over all events. - this._readReceiptsByEvent = {}; - - // Track read receipts by user ID. For each user ID we've ever shown a - // a read receipt for, we store an object: - // { - // lastShownEventId: string, - // receipt: { - // userId: string, - // member: RoomMember, - // ts: number, - // }, - // } - // so that we can always keep receipts displayed by reverting back to - // the last shown event for that user ID when needed. This may feel like - // it duplicates the receipt storage in the room, but at this layer, we - // are tracking _shown_ event IDs, which the JS SDK knows nothing about. - // This is recomputed on each render, using the data from the previous - // render as our fallback for any user IDs we can't match a receipt to a - // displayed event in the current render cycle. - this._readReceiptsByUserId = {}; - // Cache hidden events setting on mount since Settings is expensive to // query, and we check this in a hot code path. - this._showHiddenEventsInTimeline = - SettingsStore.getValue("showHiddenEventsInTimeline"); + this.showHiddenEventsInTimeline = SettingsStore.getValue("showHiddenEventsInTimeline"); - this._isMounted = false; - - this._readMarkerNode = createRef(); - this._whoIsTyping = createRef(); - this._scrollPanel = createRef(); - - this._showTypingNotificationsWatcherRef = + this.showTypingNotificationsWatcherRef = SettingsStore.watchSetting("showTypingNotifications", null, this.onShowTypingNotificationsChange); } componentDidMount() { - this._isMounted = true; + this.isMounted = true; } componentWillUnmount() { - this._isMounted = false; - SettingsStore.unwatchSetting(this._showTypingNotificationsWatcherRef); + this.isMounted = false; + SettingsStore.unwatchSetting(this.showTypingNotificationsWatcherRef); } componentDidUpdate(prevProps, prevState) { @@ -235,14 +265,14 @@ export default class MessagePanel extends React.Component { } } - onShowTypingNotificationsChange = () => { + private onShowTypingNotificationsChange = (): void => { this.setState({ showTypingNotifications: SettingsStore.getValue("showTypingNotifications"), }); }; /* get the DOM node representing the given event */ - getNodeForEventId(eventId) { + public getNodeForEventId(eventId: string): HTMLElement { if (!this.eventNodes) { return undefined; } @@ -252,8 +282,8 @@ export default class MessagePanel extends React.Component { /* return true if the content is fully scrolled down right now; else false. */ - isAtBottom() { - return this._scrollPanel.current && this._scrollPanel.current.isAtBottom(); + public isAtBottom(): boolean { + return this.scrollPanel.current?.isAtBottom(); } /* get the current scroll state. See ScrollPanel.getScrollState for @@ -261,8 +291,8 @@ export default class MessagePanel extends React.Component { * * returns null if we are not mounted. */ - getScrollState() { - return this._scrollPanel.current ? this._scrollPanel.current.getScrollState() : null; + public getScrollState(): IScrollState { + return this.scrollPanel.current?.getScrollState() ?? null; } // returns one of: @@ -271,15 +301,15 @@ export default class MessagePanel extends React.Component { // -1: read marker is above the window // 0: read marker is within the window // +1: read marker is below the window - getReadMarkerPosition() { - const readMarker = this._readMarkerNode.current; - const messageWrapper = this._scrollPanel.current; + public getReadMarkerPosition(): number { + const readMarker = this.readMarkerNode.current; + const messageWrapper = this.scrollPanel.current; if (!readMarker || !messageWrapper) { return null; } - const wrapperRect = ReactDOM.findDOMNode(messageWrapper).getBoundingClientRect(); + const wrapperRect = (ReactDOM.findDOMNode(messageWrapper) as HTMLElement).getBoundingClientRect(); const readMarkerRect = readMarker.getBoundingClientRect(); // the read-marker pretends to have zero height when it is actually @@ -295,17 +325,17 @@ export default class MessagePanel extends React.Component { /* jump to the top of the content. */ - scrollToTop() { - if (this._scrollPanel.current) { - this._scrollPanel.current.scrollToTop(); + public scrollToTop(): void { + if (this.scrollPanel.current) { + this.scrollPanel.current.scrollToTop(); } } /* jump to the bottom of the content. */ - scrollToBottom() { - if (this._scrollPanel.current) { - this._scrollPanel.current.scrollToBottom(); + public scrollToBottom(): void { + if (this.scrollPanel.current) { + this.scrollPanel.current.scrollToBottom(); } } @@ -314,9 +344,9 @@ export default class MessagePanel extends React.Component { * * @param {number} mult: -1 to page up, +1 to page down */ - scrollRelative(mult) { - if (this._scrollPanel.current) { - this._scrollPanel.current.scrollRelative(mult); + public scrollRelative(mult: number): void { + if (this.scrollPanel.current) { + this.scrollPanel.current.scrollRelative(mult); } } @@ -325,9 +355,9 @@ export default class MessagePanel extends React.Component { * * @param {KeyboardEvent} ev: the keyboard event to handle */ - handleScrollKey(ev) { - if (this._scrollPanel.current) { - this._scrollPanel.current.handleScrollKey(ev); + public handleScrollKey(ev: KeyboardEvent): void { + if (this.scrollPanel.current) { + this.scrollPanel.current.handleScrollKey(ev); } } @@ -341,38 +371,41 @@ export default class MessagePanel extends React.Component { * node (specifically, the bottom of it) will be positioned. If omitted, it * defaults to 0. */ - scrollToEvent(eventId, pixelOffset, offsetBase) { - if (this._scrollPanel.current) { - this._scrollPanel.current.scrollToToken(eventId, pixelOffset, offsetBase); + public scrollToEvent(eventId: string, pixelOffset: number, offsetBase: number): void { + if (this.scrollPanel.current) { + this.scrollPanel.current.scrollToToken(eventId, pixelOffset, offsetBase); } } - scrollToEventIfNeeded(eventId) { + public scrollToEventIfNeeded(eventId: string): void { const node = this.eventNodes[eventId]; if (node) { - node.scrollIntoView({block: "nearest", behavior: "instant"}); + node.scrollIntoView({ + block: "nearest", + behavior: "instant", + }); } } /* check the scroll state and send out pagination requests if necessary. */ - checkFillState() { - if (this._scrollPanel.current) { - this._scrollPanel.current.checkFillState(); + public checkFillState(): void { + if (this.scrollPanel.current) { + this.scrollPanel.current.checkFillState(); } } - _isUnmounting = () => { - return !this._isMounted; + private isUnmounting = (): boolean => { + return !this.isMounted; }; // TODO: Implement granular (per-room) hide options - _shouldShowEvent(mxEv) { + public shouldShowEvent(mxEv: MatrixEvent): boolean { if (mxEv.sender && MatrixClientPeg.get().isUserIgnored(mxEv.sender.userId)) { return false; // ignored = no show (only happens if the ignore happens after an event was received) } - if (this._showHiddenEventsInTimeline) { + if (this.showHiddenEventsInTimeline) { return true; } @@ -386,7 +419,7 @@ export default class MessagePanel extends React.Component { return !shouldHideEvent(mxEv, this.context); } - _readMarkerForEvent(eventId, isLastEvent) { + public readMarkerForEvent(eventId: string, isLastEvent: boolean): ReactNode { const visible = !isLastEvent && this.props.readMarkerVisible; if (this.props.readMarkerEventId === eventId) { @@ -399,13 +432,13 @@ export default class MessagePanel extends React.Component { // confused. if (visible) { hr =
; } return (
  • @@ -424,8 +457,8 @@ export default class MessagePanel extends React.Component { // transition (ie. the read markers do but the event tiles do not) // and TransitionGroup requires that all its children are Transitions. const hr =
    ; @@ -445,7 +478,7 @@ export default class MessagePanel extends React.Component { return null; } - _collectGhostReadMarker = (node) => { + private collectGhostReadMarker = (node: HTMLElement): void => { if (node) { // now the element has appeared, change the style which will trigger the CSS transition requestAnimationFrame(() => { @@ -455,15 +488,15 @@ export default class MessagePanel extends React.Component { } }; - _onGhostTransitionEnd = (ev) => { + private onGhostTransitionEnd = (ev: TransitionEvent): void => { // we can now clean up the ghost element - const finishedEventId = ev.target.dataset.eventid; + const finishedEventId = (ev.target as HTMLElement).dataset.eventid; this.setState({ ghostReadMarkers: this.state.ghostReadMarkers.filter(eid => eid !== finishedEventId), }); }; - _getNextEventInfo(arr, i) { + private getNextEventInfo(arr: MatrixEvent[], i: number): { nextEvent: MatrixEvent, nextTile: MatrixEvent } { const nextEvent = i < arr.length - 1 ? arr[i + 1] : null; @@ -472,16 +505,16 @@ export default class MessagePanel extends React.Component { // when rendering the tile. The shouldShowEvent function is pretty quick at what // it does, so this should have no significant cost even when a room is used for // not-chat purposes. - const nextTile = arr.slice(i + 1).find(e => this._shouldShowEvent(e)); + const nextTile = arr.slice(i + 1).find(e => this.shouldShowEvent(e)); - return {nextEvent, nextTile}; + return { nextEvent, nextTile }; } - get _roomHasPendingEdit() { + private get roomHasPendingEdit(): string { return this.props.room && localStorage.getItem(`mx_edit_room_${this.props.room.roomId}`); } - _getEventTiles() { + private getEventTiles(): ReactNode[] { this.eventNodes = {}; let i; @@ -497,7 +530,7 @@ export default class MessagePanel extends React.Component { let lastShownNonLocalEchoIndex = -1; for (i = this.props.events.length-1; i >= 0; i--) { const mxEv = this.props.events[i]; - if (!this._shouldShowEvent(mxEv)) { + if (!this.shouldShowEvent(mxEv)) { continue; } @@ -521,18 +554,18 @@ export default class MessagePanel extends React.Component { // Note: the EventTile might still render a "sent/sending receipt" independent of // this information. When not providing read receipt information, the tile is likely // to assume that sent receipts are to be shown more often. - this._readReceiptsByEvent = {}; + this.readReceiptsByEvent = {}; if (this.props.showReadReceipts) { - this._readReceiptsByEvent = this._getReadReceiptsByShownEvent(); + this.readReceiptsByEvent = this.getReadReceiptsByShownEvent(); } - let grouper = null; + let grouper: BaseGrouper = null; for (i = 0; i < this.props.events.length; i++) { const mxEv = this.props.events[i]; const eventId = mxEv.getId(); const last = (mxEv === lastShownEvent); - const {nextEvent, nextTile} = this._getNextEventInfo(this.props.events, i); + const { nextEvent, nextTile } = this.getNextEventInfo(this.props.events, i); if (grouper) { if (grouper.shouldGroup(mxEv)) { @@ -553,26 +586,25 @@ export default class MessagePanel extends React.Component { } } if (!grouper) { - const wantTile = this._shouldShowEvent(mxEv); + const wantTile = this.shouldShowEvent(mxEv); const isGrouped = false; if (wantTile) { - // make sure we unpack the array returned by _getTilesForEvent, + // make sure we unpack the array returned by getTilesForEvent, // otherwise react will auto-generate keys and we will end up // replacing all of the DOM elements every time we paginate. - ret.push(...this._getTilesForEvent(prevEvent, mxEv, last, isGrouped, - nextEvent, nextTile)); + ret.push(...this.getTilesForEvent(prevEvent, mxEv, last, isGrouped, nextEvent, nextTile)); prevEvent = mxEv; } - const readMarker = this._readMarkerForEvent(eventId, i >= lastShownNonLocalEchoIndex); + const readMarker = this.readMarkerForEvent(eventId, i >= lastShownNonLocalEchoIndex); if (readMarker) ret.push(readMarker); } } - if (!this.props.editState && this._roomHasPendingEdit) { + if (!this.props.editState && this.roomHasPendingEdit) { defaultDispatcher.dispatch({ action: "edit_event", - event: this.props.room.findEventById(this._roomHasPendingEdit), + event: this.props.room.findEventById(this.roomHasPendingEdit), }); } @@ -583,10 +615,14 @@ export default class MessagePanel extends React.Component { return ret; } - _getTilesForEvent(prevEvent, mxEv, last, isGrouped=false, nextEvent, nextEventWithTile) { - const TileErrorBoundary = sdk.getComponent('messages.TileErrorBoundary'); - const EventTile = sdk.getComponent('rooms.EventTile'); - const DateSeparator = sdk.getComponent('messages.DateSeparator'); + public getTilesForEvent( + prevEvent: MatrixEvent, + mxEv: MatrixEvent, + last = false, + isGrouped = false, + nextEvent?: MatrixEvent, + nextEventWithTile?: MatrixEvent, + ): ReactNode[] { const ret = []; const isEditing = this.props.editState && @@ -601,7 +637,7 @@ export default class MessagePanel extends React.Component { } // do we need a date separator since the last event? - const wantsDateSeparator = this._wantsDateSeparator(prevEvent, eventDate); + const wantsDateSeparator = this.wantsDateSeparator(prevEvent, eventDate); if (wantsDateSeparator && !isGrouped) { const dateSeparator =
  • ; ret.push(dateSeparator); @@ -609,7 +645,7 @@ export default class MessagePanel extends React.Component { let willWantDateSeparator = false; if (nextEvent) { - willWantDateSeparator = this._wantsDateSeparator(mxEv, nextEvent.getDate() || new Date()); + willWantDateSeparator = this.wantsDateSeparator(mxEv, nextEvent.getDate() || new Date()); } // is this a continuation of the previous message? @@ -618,12 +654,12 @@ export default class MessagePanel extends React.Component { const eventId = mxEv.getId(); const highlight = (eventId === this.props.highlightedEventId); - const readReceipts = this._readReceiptsByEvent[eventId]; + const readReceipts = this.readReceiptsByEvent[eventId]; let isLastSuccessful = false; const isSentState = s => !s || s === 'sent'; const isSent = isSentState(mxEv.getAssociatedStatus()); - const hasNextEvent = nextEvent && this._shouldShowEvent(nextEvent); + const hasNextEvent = nextEvent && this.shouldShowEvent(nextEvent); if (!hasNextEvent && isSent) { isLastSuccessful = true; } else if (hasNextEvent && isSent && !isSentState(nextEvent.getAssociatedStatus())) { @@ -649,18 +685,18 @@ export default class MessagePanel extends React.Component { { if (!r.userId || r.type !== "m.read" || r.userId === myUserId) { return; // ignore non-read receipts and receipts from self. @@ -721,13 +757,13 @@ export default class MessagePanel extends React.Component { // Get an object that maps from event ID to a list of read receipts that // should be shown next to that event. If a hidden event has read receipts, // they are folded into the receipts of the last shown event. - _getReadReceiptsByShownEvent() { + private getReadReceiptsByShownEvent(): Record { const receiptsByEvent = {}; const receiptsByUserId = {}; let lastShownEventId; for (const event of this.props.events) { - if (this._shouldShowEvent(event)) { + if (this.shouldShowEvent(event)) { lastShownEventId = event.getId(); } if (!lastShownEventId) { @@ -735,7 +771,7 @@ export default class MessagePanel extends React.Component { } const existingReceipts = receiptsByEvent[lastShownEventId] || []; - const newReceipts = this._getReadReceiptsForEvent(event); + const newReceipts = this.getReadReceiptsForEvent(event); receiptsByEvent[lastShownEventId] = existingReceipts.concat(newReceipts); // Record these receipts along with their last shown event ID for @@ -754,16 +790,16 @@ export default class MessagePanel extends React.Component { // someone which had one in the last. By looking through our previous // mapping of receipts by user ID, we can cover recover any receipts // that would have been lost by using the same event ID from last time. - for (const userId in this._readReceiptsByUserId) { + for (const userId in this.readReceiptsByUserId) { if (receiptsByUserId[userId]) { continue; } - const { lastShownEventId, receipt } = this._readReceiptsByUserId[userId]; + const { lastShownEventId, receipt } = this.readReceiptsByUserId[userId]; const existingReceipts = receiptsByEvent[lastShownEventId] || []; receiptsByEvent[lastShownEventId] = existingReceipts.concat(receipt); receiptsByUserId[userId] = { lastShownEventId, receipt }; } - this._readReceiptsByUserId = receiptsByUserId; + this.readReceiptsByUserId = receiptsByUserId; // After grouping receipts by shown events, do another pass to sort each // receipt list. @@ -776,21 +812,21 @@ export default class MessagePanel extends React.Component { return receiptsByEvent; } - _collectEventNode = (eventId, node) => { + private collectEventNode = (eventId: string, node: EventTile): void => { this.eventNodes[eventId] = node?.ref?.current; - } + }; // once dynamic content in the events load, make the scrollPanel check the // scroll offsets. - _onHeightChanged = () => { - const scrollPanel = this._scrollPanel.current; + public onHeightChanged = (): void => { + const scrollPanel = this.scrollPanel.current; if (scrollPanel) { scrollPanel.checkScroll(); } }; - _onTypingShown = () => { - const scrollPanel = this._scrollPanel.current; + private onTypingShown = (): void => { + const scrollPanel = this.scrollPanel.current; // this will make the timeline grow, so checkScroll scrollPanel.checkScroll(); if (scrollPanel && scrollPanel.getScrollState().stuckAtBottom) { @@ -798,8 +834,8 @@ export default class MessagePanel extends React.Component { } }; - _onTypingHidden = () => { - const scrollPanel = this._scrollPanel.current; + private onTypingHidden = (): void => { + const scrollPanel = this.scrollPanel.current; if (scrollPanel) { // as hiding the typing notifications doesn't // update the scrollPanel, we tell it to apply @@ -811,12 +847,12 @@ export default class MessagePanel extends React.Component { } }; - updateTimelineMinHeight() { - const scrollPanel = this._scrollPanel.current; + public updateTimelineMinHeight(): void { + const scrollPanel = this.scrollPanel.current; if (scrollPanel) { const isAtBottom = scrollPanel.isAtBottom(); - const whoIsTyping = this._whoIsTyping.current; + const whoIsTyping = this.whoIsTyping.current; const isTypingVisible = whoIsTyping && whoIsTyping.isVisible(); // when messages get added to the timeline, // but somebody else is still typing, @@ -828,18 +864,14 @@ export default class MessagePanel extends React.Component { } } - onTimelineReset() { - const scrollPanel = this._scrollPanel.current; + public onTimelineReset(): void { + const scrollPanel = this.scrollPanel.current; if (scrollPanel) { scrollPanel.clearPreventShrinking(); } } render() { - const ErrorBoundary = sdk.getComponent('elements.ErrorBoundary'); - const ScrollPanel = sdk.getComponent("structures.ScrollPanel"); - const WhoIsTypingTile = sdk.getComponent("rooms.WhoIsTypingTile"); - const Spinner = sdk.getComponent("elements.Spinner"); let topSpinner; let bottomSpinner; if (this.props.backPaginating) { @@ -855,9 +887,9 @@ export default class MessagePanel extends React.Component { if (this.props.room && !this.props.tileShape && this.state.showTypingNotifications) { whoIsTyping = ( + onShown={this.onTypingShown} + onHidden={this.onTypingHidden} + ref={this.whoIsTyping} /> ); } @@ -873,11 +905,10 @@ export default class MessagePanel extends React.Component { return ( { topSpinner } - { this._getEventTiles() } + { this.getEventTiles() } { whoIsTyping } { bottomSpinner } @@ -895,6 +926,31 @@ export default class MessagePanel extends React.Component { } } +abstract class BaseGrouper { + static canStartGroup = (panel: MessagePanel, ev: MatrixEvent): boolean => true; + + public events: MatrixEvent[] = []; + // events that we include in the group but then eject out and place above the group. + public ejectedEvents: MatrixEvent[] = []; + public readMarker: ReactNode; + + constructor( + public readonly panel: MessagePanel, + public readonly event: MatrixEvent, + public readonly prevEvent: MatrixEvent, + public readonly lastShownEvent: MatrixEvent, + public readonly nextEvent?: MatrixEvent, + public readonly nextEventTile?: MatrixEvent, + ) { + this.readMarker = panel.readMarkerForEvent(event.getId(), event === lastShownEvent); + } + + public abstract shouldGroup(ev: MatrixEvent): boolean; + public abstract add(ev: MatrixEvent): void; + public abstract getTiles(): ReactNode[]; + public abstract getNewPrevEvent(): MatrixEvent; +} + /* Grouper classes determine when events can be grouped together in a summary. * Groupers should have the following methods: * - canStartGroup (static): determines if a new group should be started with the @@ -910,36 +966,21 @@ export default class MessagePanel extends React.Component { // Wrap initial room creation events into an EventListSummary // Grouping only events sent by the same user that sent the `m.room.create` and only until // the first non-state event or membership event which is not regarding the sender of the `m.room.create` event -class CreationGrouper { - static canStartGroup = function(panel, ev) { - return ev.getType() === "m.room.create"; +class CreationGrouper extends BaseGrouper { + static canStartGroup = function(panel: MessagePanel, ev: MatrixEvent): boolean { + return ev.getType() === EventType.RoomCreate; }; - constructor(panel, createEvent, prevEvent, lastShownEvent) { - this.panel = panel; - this.createEvent = createEvent; - this.prevEvent = prevEvent; - this.lastShownEvent = lastShownEvent; - this.events = []; - // events that we include in the group but then eject out and place - // above the group. - this.ejectedEvents = []; - this.readMarker = panel._readMarkerForEvent( - createEvent.getId(), - createEvent === lastShownEvent, - ); - } - - shouldGroup(ev) { + public shouldGroup(ev: MatrixEvent): boolean { const panel = this.panel; - const createEvent = this.createEvent; - if (!panel._shouldShowEvent(ev)) { + const createEvent = this.event; + if (!panel.shouldShowEvent(ev)) { return true; } - if (panel._wantsDateSeparator(this.createEvent, ev.getDate())) { + if (panel.wantsDateSeparator(this.event, ev.getDate())) { return false; } - if (ev.getType() === "m.room.member" + if (ev.getType() === EventType.RoomMember && (ev.getStateKey() !== createEvent.getSender() || ev.getContent()["membership"] !== "join")) { return false; } @@ -949,37 +990,35 @@ class CreationGrouper { return false; } - add(ev) { + public add(ev: MatrixEvent): void { const panel = this.panel; - this.readMarker = this.readMarker || panel._readMarkerForEvent( + this.readMarker = this.readMarker || panel.readMarkerForEvent( ev.getId(), ev === this.lastShownEvent, ); - if (!panel._shouldShowEvent(ev)) { + if (!panel.shouldShowEvent(ev)) { return; } - if (ev.getType() === "m.room.encryption") { + if (ev.getType() === EventType.RoomEncryption) { this.ejectedEvents.push(ev); } else { this.events.push(ev); } } - getTiles() { + public getTiles(): ReactNode[] { // If we don't have any events to group, don't even try to group them. The logic // below assumes that we have a group of events to deal with, but we might not if // the events we were supposed to group were redacted. if (!this.events || !this.events.length) return []; - const DateSeparator = sdk.getComponent('messages.DateSeparator'); - const EventListSummary = sdk.getComponent('views.elements.EventListSummary'); const panel = this.panel; const ret = []; const isGrouped = true; - const createEvent = this.createEvent; + const createEvent = this.event; const lastShownEvent = this.lastShownEvent; - if (panel._wantsDateSeparator(this.prevEvent, createEvent.getDate())) { + if (panel.wantsDateSeparator(this.prevEvent, createEvent.getDate())) { const ts = createEvent.getTs(); ret.push(
  • , @@ -987,13 +1026,13 @@ class CreationGrouper { } // If this m.room.create event should be shown (room upgrade) then show it before the summary - if (panel._shouldShowEvent(createEvent)) { + if (panel.shouldShowEvent(createEvent)) { // pass in the createEvent as prevEvent as well so no extra DateSeparator is rendered - ret.push(...panel._getTilesForEvent(createEvent, createEvent)); + ret.push(...panel.getTilesForEvent(createEvent, createEvent)); } for (const ejected of this.ejectedEvents) { - ret.push(...panel._getTilesForEvent( + ret.push(...panel.getTilesForEvent( createEvent, ejected, createEvent === lastShownEvent, isGrouped, )); } @@ -1003,7 +1042,7 @@ class CreationGrouper { // of EventListSummary, render each member event as if the previous // one was itself. This way, the timestamp of the previous event === the // timestamp of the current event, and no DateSeparator is inserted. - return panel._getTilesForEvent(e, e, e === lastShownEvent, isGrouped); + return panel.getTilesForEvent(e, e, e === lastShownEvent, isGrouped); }).reduce((a, b) => a.concat(b), []); // Get sender profile from the latest event in the summary as the m.room.create doesn't contain one const ev = this.events[this.events.length - 1]; @@ -1023,7 +1062,7 @@ class CreationGrouper { @@ -1038,62 +1077,59 @@ class CreationGrouper { return ret; } - getNewPrevEvent() { - return this.createEvent; + public getNewPrevEvent(): MatrixEvent { + return this.event; } } -class RedactionGrouper { - static canStartGroup = function(panel, ev) { - return panel._shouldShowEvent(ev) && ev.isRedacted(); - } +class RedactionGrouper extends BaseGrouper { + static canStartGroup = function(panel: MessagePanel, ev: MatrixEvent): boolean { + return panel.shouldShowEvent(ev) && ev.isRedacted(); + }; - constructor(panel, ev, prevEvent, lastShownEvent, nextEvent, nextEventTile) { - this.panel = panel; - this.readMarker = panel._readMarkerForEvent( - ev.getId(), - ev === lastShownEvent, - ); + constructor( + panel: MessagePanel, + ev: MatrixEvent, + prevEvent: MatrixEvent, + lastShownEvent: MatrixEvent, + nextEvent: MatrixEvent, + nextEventTile: MatrixEvent, + ) { + super(panel, ev, prevEvent, lastShownEvent, nextEvent, nextEventTile); this.events = [ev]; - this.prevEvent = prevEvent; - this.lastShownEvent = lastShownEvent; - this.nextEvent = nextEvent; - this.nextEventTile = nextEventTile; } - shouldGroup(ev) { + public shouldGroup(ev: MatrixEvent): boolean { // absorb hidden events so that they do not break up streams of messages & redaction events being grouped - if (!this.panel._shouldShowEvent(ev)) { + if (!this.panel.shouldShowEvent(ev)) { return true; } - if (this.panel._wantsDateSeparator(this.events[0], ev.getDate())) { + if (this.panel.wantsDateSeparator(this.events[0], ev.getDate())) { return false; } return ev.isRedacted(); } - add(ev) { - this.readMarker = this.readMarker || this.panel._readMarkerForEvent( + public add(ev: MatrixEvent): void { + this.readMarker = this.readMarker || this.panel.readMarkerForEvent( ev.getId(), ev === this.lastShownEvent, ); - if (!this.panel._shouldShowEvent(ev)) { + if (!this.panel.shouldShowEvent(ev)) { return; } this.events.push(ev); } - getTiles() { + public getTiles(): ReactNode[] { if (!this.events || !this.events.length) return []; - const DateSeparator = sdk.getComponent('messages.DateSeparator'); - const EventListSummary = sdk.getComponent('views.elements.EventListSummary'); const isGrouped = true; const panel = this.panel; const ret = []; const lastShownEvent = this.lastShownEvent; - if (panel._wantsDateSeparator(this.prevEvent, this.events[0].getDate())) { + if (panel.wantsDateSeparator(this.prevEvent, this.events[0].getDate())) { const ts = this.events[0].getTs(); ret.push(
  • , @@ -1104,11 +1140,11 @@ class RedactionGrouper { this.prevEvent ? this.events[0].getId() : "initial" ); - const senders = new Set(); + const senders = new Set(); let eventTiles = this.events.map((e, i) => { senders.add(e.sender); const prevEvent = i === 0 ? this.prevEvent : this.events[i - 1]; - return panel._getTilesForEvent( + return panel.getTilesForEvent( prevEvent, e, e === lastShownEvent, isGrouped, this.nextEvent, this.nextEventTile); }).reduce((a, b) => a.concat(b), []); @@ -1121,7 +1157,7 @@ class RedactionGrouper { key={key} threshold={2} events={this.events} - onToggle={panel._onHeightChanged} // Update scroll state + onToggle={panel.onHeightChanged} // Update scroll state summaryMembers={Array.from(senders)} summaryText={_t("%(count)s messages deleted.", { count: eventTiles.length })} > @@ -1136,61 +1172,58 @@ class RedactionGrouper { return ret; } - getNewPrevEvent() { + public getNewPrevEvent(): MatrixEvent { return this.events[this.events.length - 1]; } } // Wrap consecutive member events in a ListSummary, ignore if redacted -class MemberGrouper { - static canStartGroup = function(panel, ev) { - return panel._shouldShowEvent(ev) && isMembershipChange(ev); +class MemberGrouper extends BaseGrouper { + static canStartGroup = function(panel: MessagePanel, ev: MatrixEvent): boolean { + return panel.shouldShowEvent(ev) && membershipTypes.includes(ev.getType() as EventType); + }; + + constructor( + public readonly panel: MessagePanel, + public readonly event: MatrixEvent, + public readonly prevEvent: MatrixEvent, + public readonly lastShownEvent: MatrixEvent, + ) { + super(panel, event, prevEvent, lastShownEvent); + this.events = [event]; } - constructor(panel, ev, prevEvent, lastShownEvent) { - this.panel = panel; - this.readMarker = panel._readMarkerForEvent( - ev.getId(), - ev === lastShownEvent, - ); - this.events = [ev]; - this.prevEvent = prevEvent; - this.lastShownEvent = lastShownEvent; - } - - shouldGroup(ev) { - if (this.panel._wantsDateSeparator(this.events[0], ev.getDate())) { + public shouldGroup(ev: MatrixEvent): boolean { + if (this.panel.wantsDateSeparator(this.events[0], ev.getDate())) { return false; } - return isMembershipChange(ev); + return membershipTypes.includes(ev.getType() as EventType); } - add(ev) { - if (ev.getType() === 'm.room.member') { + public add(ev: MatrixEvent): void { + if (ev.getType() === EventType.RoomMember) { // We can ignore any events that don't actually have a message to display if (!hasText(ev)) return; } - this.readMarker = this.readMarker || this.panel._readMarkerForEvent( + this.readMarker = this.readMarker || this.panel.readMarkerForEvent( ev.getId(), ev === this.lastShownEvent, ); this.events.push(ev); } - getTiles() { + public getTiles(): ReactNode[] { // If we don't have any events to group, don't even try to group them. The logic // below assumes that we have a group of events to deal with, but we might not if // the events we were supposed to group were redacted. if (!this.events || !this.events.length) return []; - const DateSeparator = sdk.getComponent('messages.DateSeparator'); - const MemberEventListSummary = sdk.getComponent('views.elements.MemberEventListSummary'); const isGrouped = true; const panel = this.panel; const lastShownEvent = this.lastShownEvent; const ret = []; - if (panel._wantsDateSeparator(this.prevEvent, this.events[0].getDate())) { + if (panel.wantsDateSeparator(this.prevEvent, this.events[0].getDate())) { const ts = this.events[0].getTs(); ret.push(
  • , @@ -1218,7 +1251,7 @@ class MemberGrouper { // of MemberEventListSummary, render each member event as if the previous // one was itself. This way, the timestamp of the previous event === the // timestamp of the current event, and no DateSeparator is inserted. - return panel._getTilesForEvent(e, e, e === lastShownEvent, isGrouped); + return panel.getTilesForEvent(e, e, e === lastShownEvent, isGrouped); }).reduce((a, b) => a.concat(b), []); if (eventTiles.length === 0) { @@ -1226,9 +1259,10 @@ class MemberGrouper { } ret.push( - { eventTiles } @@ -1242,7 +1276,7 @@ class MemberGrouper { return ret; } - getNewPrevEvent() { + public getNewPrevEvent(): MatrixEvent { return this.events[0]; } } diff --git a/src/components/structures/MyGroups.js b/src/components/structures/MyGroups.js index d0a2fbff41..87447b6aba 100644 --- a/src/components/structures/MyGroups.js +++ b/src/components/structures/MyGroups.js @@ -24,7 +24,7 @@ import dis from '../../dispatcher/dispatcher'; import AccessibleButton from '../views/elements/AccessibleButton'; import MatrixClientContext from "../../contexts/MatrixClientContext"; import AutoHideScrollbar from "./AutoHideScrollbar"; -import {replaceableComponent} from "../../utils/replaceableComponent"; +import { replaceableComponent } from "../../utils/replaceableComponent"; import BetaCard from "../views/beta/BetaCard"; @replaceableComponent("structures.MyGroups") @@ -41,19 +41,19 @@ export default class MyGroups extends React.Component { } _onCreateGroupClick = () => { - dis.dispatch({action: 'view_create_group'}); + dis.dispatch({ action: 'view_create_group' }); }; _fetch() { this.context.getJoinedGroups().then((result) => { - this.setState({groups: result.groups, error: null}); + this.setState({ groups: result.groups, error: null }); }, (err) => { if (err.errcode === 'M_GUEST_ACCESS_FORBIDDEN') { // Indicate that the guest isn't in any groups (which should be true) - this.setState({groups: [], error: null}); + this.setState({ groups: [], error: null }); return; } - this.setState({groups: null, error: err}); + this.setState({ groups: null, error: err }); }); } @@ -123,7 +123,7 @@ export default class MyGroups extends React.Component {
    {/*
    - +
    diff --git a/src/components/structures/NonUrgentToastContainer.tsx b/src/components/structures/NonUrgentToastContainer.tsx index 7c193ec9d7..b1424a2974 100644 --- a/src/components/structures/NonUrgentToastContainer.tsx +++ b/src/components/structures/NonUrgentToastContainer.tsx @@ -18,7 +18,7 @@ import * as React from "react"; import { ComponentClass } from "../../@types/common"; import NonUrgentToastStore from "../../stores/NonUrgentToastStore"; import { UPDATE_EVENT } from "../../stores/AsyncStore"; -import {replaceableComponent} from "../../utils/replaceableComponent"; +import { replaceableComponent } from "../../utils/replaceableComponent"; interface IProps { } @@ -44,7 +44,7 @@ export default class NonUrgentToastContainer extends React.PureComponent { - this.setState({toasts: NonUrgentToastStore.instance.components}); + this.setState({ toasts: NonUrgentToastStore.instance.components }); }; public render() { diff --git a/src/components/structures/NotificationPanel.tsx b/src/components/structures/NotificationPanel.tsx index 6c22835447..8c8fab7ece 100644 --- a/src/components/structures/NotificationPanel.tsx +++ b/src/components/structures/NotificationPanel.tsx @@ -22,6 +22,7 @@ import BaseCard from "../views/right_panel/BaseCard"; import { replaceableComponent } from "../../utils/replaceableComponent"; import TimelinePanel from "./TimelinePanel"; import Spinner from "../views/elements/Spinner"; +import { TileShape } from "../views/rooms/EventTile"; interface IProps { onClose(): void; @@ -48,7 +49,7 @@ export default class NotificationPanel extends React.PureComponent { manageReadMarkers={false} timelineSet={timelineSet} showUrlPreview={false} - tileShape="notif" + tileShape={TileShape.Notif} empty={emptyState} alwaysShowTimestamps={true} /> diff --git a/src/components/structures/RightPanel.tsx b/src/components/structures/RightPanel.tsx index 294865fe08..c608f0eee9 100644 --- a/src/components/structures/RightPanel.tsx +++ b/src/components/structures/RightPanel.tsx @@ -104,7 +104,7 @@ export default class RightPanel extends React.Component { const userForPanel = this.getUserForPanel(); if (this.props.groupId) { if (!RIGHT_PANEL_PHASES_NO_ARGS.includes(rps.groupPanelPhase)) { - dis.dispatch({action: Action.SetRightPanelPhase, phase: RightPanelPhases.GroupMemberList}); + dis.dispatch({ action: Action.SetRightPanelPhase, phase: RightPanelPhases.GroupMemberList }); return RightPanelPhases.GroupMemberList; } return rps.groupPanelPhase; diff --git a/src/components/structures/RoomDirectory.tsx b/src/components/structures/RoomDirectory.tsx index 62944a9d98..2ac990436f 100644 --- a/src/components/structures/RoomDirectory.tsx +++ b/src/components/structures/RoomDirectory.tsx @@ -25,7 +25,7 @@ import { _t } from '../../languageHandler'; import SdkConfig from '../../SdkConfig'; import { instanceForInstanceId, protocolNameForInstanceId } from '../../utils/DirectoryUtils'; import Analytics from '../../Analytics'; -import {ALL_ROOMS, IFieldType, IInstance, IProtocol, Protocols} from "../views/directory/NetworkDropdown"; +import { ALL_ROOMS, IFieldType, IInstance, IProtocol, Protocols } from "../views/directory/NetworkDropdown"; import SettingsStore from "../../settings/SettingsStore"; import GroupFilterOrderStore from "../../stores/GroupFilterOrderStore"; import GroupStore from "../../stores/GroupStore"; @@ -34,7 +34,7 @@ import CountlyAnalytics from "../../CountlyAnalytics"; import { replaceableComponent } from "../../utils/replaceableComponent"; import { mediaFromMxc } from "../../customisations/Media"; import { IDialogProps } from "../views/dialogs/IDialogProps"; -import AccessibleButton, {ButtonEvent} from "../views/elements/AccessibleButton"; +import AccessibleButton, { ButtonEvent } from "../views/elements/AccessibleButton"; import BaseAvatar from "../views/avatars/BaseAvatar"; import ErrorDialog from "../views/dialogs/ErrorDialog"; import QuestionDialog from "../views/dialogs/QuestionDialog"; @@ -45,7 +45,6 @@ import ScrollPanel from "./ScrollPanel"; import Spinner from "../views/elements/Spinner"; import { ActionPayload } from "../../dispatcher/payloads"; - const MAX_NAME_LENGTH = 80; const MAX_TOPIC_LENGTH = 800; @@ -95,7 +94,7 @@ interface IPublicRoomsRequest { @replaceableComponent("structures.RoomDirectory") export default class RoomDirectory extends React.Component { private readonly startTime: number; - private unmounted = false + private unmounted = false; private nextBatch: string = null; private filterTimeout: NodeJS.Timeout; private protocols: Protocols; @@ -207,9 +206,9 @@ export default class RoomDirectory extends React.Component { this.getMoreRooms(); }; - private getMoreRooms() { - if (this.state.selectedCommunityId) return Promise.resolve(); // no more rooms - if (!MatrixClientPeg.get()) return Promise.resolve(); + private getMoreRooms(): Promise { + if (this.state.selectedCommunityId) return Promise.resolve(false); // no more rooms + if (!MatrixClientPeg.get()) return Promise.resolve(false); this.setState({ loading: true, @@ -239,12 +238,12 @@ export default class RoomDirectory extends React.Component { // if the filter or server has changed since this request was sent, // throw away the result (don't even clear the busy flag // since we must still have a request in flight) - return; + return false; } if (this.unmounted) { // if we've been unmounted, we don't care either. - return; + return false; } if (this.state.filterString) { @@ -264,14 +263,13 @@ export default class RoomDirectory extends React.Component { filterString != this.state.filterString || roomServer != this.state.roomServer || nextBatch != this.nextBatch) { - // as above: we don't care about errors for old - // requests either - return; + // as above: we don't care about errors for old requests either + return false; } if (this.unmounted) { // if we've been unmounted, we don't care either. - return; + return false; } console.error("Failed to get publicRooms: %s", JSON.stringify(err)); @@ -300,9 +298,9 @@ export default class RoomDirectory extends React.Component { let desc; if (alias) { - desc = _t('Delete the room address %(alias)s and remove %(name)s from the directory?', {alias, name}); + desc = _t('Delete the room address %(alias)s and remove %(name)s from the directory?', { alias, name }); } else { - desc = _t('Remove %(name)s from the directory?', {name: name}); + desc = _t('Remove %(name)s from the directory?', { name: name }); } Modal.createTrackedDialog('Remove from Directory', '', QuestionDialog, { @@ -312,7 +310,7 @@ export default class RoomDirectory extends React.Component { if (!shouldDelete) return; const modal = Modal.createDialog(Spinner); - let step = _t('remove %(name)s from the directory.', {name: name}); + let step = _t('remove %(name)s from the directory.', { name: name }); MatrixClientPeg.get().setRoomDirectoryVisibility(room.room_id, 'private').then(() => { if (!alias) return; @@ -483,7 +481,7 @@ export default class RoomDirectory extends React.Component { // to the directory. if (MatrixClientPeg.get().isGuest()) { if (!room.world_readable && !room.guest_can_join) { - dis.dispatch({action: 'require_registration'}); + dis.dispatch({ action: 'require_registration' }); return; } } @@ -782,11 +780,11 @@ export default class RoomDirectory extends React.Component { } const explanation = _t("If you can't find the room you're looking for, ask for an invite or Create a new room.", null, - {a: sub => ( + { a: sub => ( { sub } - )}, + ) }, ); const title = this.state.selectedCommunityId diff --git a/src/components/structures/RoomSearch.tsx b/src/components/structures/RoomSearch.tsx index bda46aef07..9cdd1efe7e 100644 --- a/src/components/structures/RoomSearch.tsx +++ b/src/components/structures/RoomSearch.tsx @@ -108,22 +108,22 @@ export default class RoomSearch extends React.PureComponent { }; private openSearch = () => { - defaultDispatcher.dispatch({action: "show_left_panel"}); - defaultDispatcher.dispatch({action: "focus_room_filter"}); + defaultDispatcher.dispatch({ action: "show_left_panel" }); + defaultDispatcher.dispatch({ action: "focus_room_filter" }); }; private onChange = () => { if (!this.inputRef.current) return; - this.setState({query: this.inputRef.current.value}); + this.setState({ query: this.inputRef.current.value }); }; private onFocus = (ev: React.FocusEvent) => { - this.setState({focused: true}); + this.setState({ focused: true }); ev.target.select(); }; private onBlur = (ev: React.FocusEvent) => { - this.setState({focused: false}); + this.setState({ focused: false }); }; private onKeyDown = (ev: React.KeyboardEvent) => { diff --git a/src/components/structures/RoomStatusBar.js b/src/components/structures/RoomStatusBar.js index 7d74229421..f6e42a4f9c 100644 --- a/src/components/structures/RoomStatusBar.js +++ b/src/components/structures/RoomStatusBar.js @@ -17,15 +17,15 @@ limitations under the License. import React from 'react'; import PropTypes from 'prop-types'; import { _t, _td } from '../../languageHandler'; -import {MatrixClientPeg} from '../../MatrixClientPeg'; +import { MatrixClientPeg } from '../../MatrixClientPeg'; import Resend from '../../Resend'; import dis from '../../dispatcher/dispatcher'; -import {messageForResourceLimitError} from '../../utils/ErrorUtils'; -import {Action} from "../../dispatcher/actions"; -import {replaceableComponent} from "../../utils/replaceableComponent"; -import {EventStatus} from "matrix-js-sdk/src/models/event"; +import { messageForResourceLimitError } from '../../utils/ErrorUtils'; +import { Action } from "../../dispatcher/actions"; +import { replaceableComponent } from "../../utils/replaceableComponent"; +import { EventStatus } from "matrix-js-sdk/src/models/event"; import NotificationBadge from "../views/rooms/NotificationBadge"; -import {StaticNotificationState} from "../../stores/notifications/StaticNotificationState"; +import { StaticNotificationState } from "../../stores/notifications/StaticNotificationState"; import AccessibleButton from "../views/elements/AccessibleButton"; import InlineSpinner from "../views/elements/InlineSpinner"; @@ -115,9 +115,9 @@ export default class RoomStatusBar extends React.PureComponent { _onResendAllClick = () => { Resend.resendUnsentEvents(this.props.room).then(() => { - this.setState({isResending: false}); + this.setState({ isResending: false }); }); - this.setState({isResending: true}); + this.setState({ isResending: true }); dis.fire(Action.FocusComposer); }; diff --git a/src/components/structures/RoomView.tsx b/src/components/structures/RoomView.tsx index 3e6cfa864a..61685e7ba8 100644 --- a/src/components/structures/RoomView.tsx +++ b/src/components/structures/RoomView.tsx @@ -37,7 +37,6 @@ import Modal from '../../Modal'; import * as sdk from '../../index'; import CallHandler, { PlaceCallType } from '../../CallHandler'; import dis from '../../dispatcher/dispatcher'; -import Tinter from '../../Tinter'; import rateLimitedFunc from '../../ratelimitedfunc'; import * as Rooms from '../../Rooms'; import eventSearch, { searchPagination } from '../../Searching'; @@ -287,7 +286,7 @@ export default class RoomView extends React.Component { if (this.state.room) { this.checkWidgets(this.state.room); } - } + }; private checkWidgets = (room) => { this.setState({ @@ -530,7 +529,7 @@ export default class RoomView extends React.Component { } else if (room) { // Stop peeking because we have joined this room previously this.context.stopPeeking(); - this.setState({isPeeking: false}); + this.setState({ isPeeking: false }); } } } @@ -679,10 +678,6 @@ export default class RoomView extends React.Component { // cancel any pending calls to the rate_limited_funcs this.updateRoomMembers.cancelPendingCall(); - // no need to do this as Dir & Settings are now overlays. It just burnt CPU. - // console.log("Tinter.tint from RoomView.unmount"); - // Tinter.tint(); // reset colourscheme - for (const watcher of this.settingWatchers) { SettingsStore.unwatchSetting(watcher); } @@ -698,7 +693,7 @@ export default class RoomView extends React.Component { replyingToEvent: this.state.replyToEvent, }); } - } + }; private onRightPanelStoreUpdate = () => { this.setState({ @@ -882,7 +877,7 @@ export default class RoomView extends React.Component { // no change } else if (!shouldHideEvent(ev, this.state)) { this.setState((state, props) => { - return {numUnreadMessages: state.numUnreadMessages + 1}; + return { numUnreadMessages: state.numUnreadMessages + 1 }; }); } } @@ -907,7 +902,7 @@ export default class RoomView extends React.Component { CHAT_EFFECTS.forEach(effect => { if (containsEmoji(ev.getContent(), effect.emojis) || ev.getContent().msgtype === effect.msgType) { - dis.dispatch({action: `effects.${effect.command}`}); + dis.dispatch({ action: `effects.${effect.command}` }); } }); }; @@ -960,7 +955,7 @@ export default class RoomView extends React.Component { try { await room.loadMembersIfNeeded(); if (!this.unmounted) { - this.setState({membersLoaded: true}); + this.setState({ membersLoaded: true }); } } catch (err) { const errorMessage = `Fetching room members for ${room.roomId} failed.` + @@ -988,7 +983,7 @@ export default class RoomView extends React.Component { } } - private updatePreviewUrlVisibility({roomId}: Room) { + private updatePreviewUrlVisibility({ roomId }: Room) { // URL Previews in E2EE rooms can be a privacy leak so use a different setting which is per-room explicit const key = this.context.isRoomEncrypted(roomId) ? 'urlPreviewsEnabled_e2ee' : 'urlPreviewsEnabled'; this.setState({ @@ -1062,10 +1057,6 @@ export default class RoomView extends React.Component { private updateTint() { const room = this.state.room; if (!room) return; - - console.log("Tinter.tint from updateTint"); - const colorScheme = SettingsStore.getValue("roomColor", room.roomId); - Tinter.tint(colorScheme.primary_color, colorScheme.secondary_color); } private onAccountData = (event: MatrixEvent) => { @@ -1079,12 +1070,7 @@ export default class RoomView extends React.Component { private onRoomAccountData = (event: MatrixEvent, room: Room) => { if (room.roomId == this.state.roomId) { const type = event.getType(); - if (type === "org.matrix.room.color_scheme") { - const colorScheme = event.getContent(); - // XXX: we should validate the event - console.log("Tinter.tint from onRoomAccountData"); - Tinter.tint(colorScheme.primary_color, colorScheme.secondary_color); - } else if (type === "org.matrix.room.preview_urls" || type === "im.vector.web.settings") { + if (type === "org.matrix.room.preview_urls" || type === "im.vector.web.settings") { // non-e2ee url previews are stored in legacy event type `org.matrix.room.preview_urls` this.updatePreviewUrlVisibility(room); } @@ -1128,7 +1114,7 @@ export default class RoomView extends React.Component { const canReact = room.getMyMembership() === "join" && room.currentState.maySendEvent("m.reaction", me); const canReply = room.maySendMessage(); - this.setState({canReact, canReply}); + this.setState({ canReact, canReply }); } } @@ -1157,7 +1143,7 @@ export default class RoomView extends React.Component { } } - private onSearchResultsFillRequest = (backwards: boolean) => { + private onSearchResultsFillRequest = (backwards: boolean): Promise => { if (!backwards) { return Promise.resolve(false); } @@ -1192,7 +1178,7 @@ export default class RoomView extends React.Component { room_id: this.getRoomId(), }, }); - dis.dispatch({action: 'require_registration'}); + dis.dispatch({ action: 'require_registration' }); } else { Promise.resolve().then(() => { const signUrl = this.props.threepidInvite?.signUrl; @@ -1227,13 +1213,13 @@ export default class RoomView extends React.Component { // We always increment the counter no matter the types, because dragging is // still happening. If we didn't, the drag counter would get out of sync. - this.setState({dragCounter: this.state.dragCounter + 1}); + this.setState({ dragCounter: this.state.dragCounter + 1 }); // See: // https://docs.w3cub.com/dom/datatransfer/types // https://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API/Recommended_drag_types#file if (ev.dataTransfer.types.includes("Files") || ev.dataTransfer.types.includes("application/x-moz-file")) { - this.setState({draggingFile: true}); + this.setState({ draggingFile: true }); } }; @@ -1282,7 +1268,7 @@ export default class RoomView extends React.Component { private injectSticker(url, info, text) { if (this.context.isGuest()) { - dis.dispatch({action: 'require_registration'}); + dis.dispatch({ action: 'require_registration' }); return; } @@ -1323,7 +1309,7 @@ export default class RoomView extends React.Component { this.handleSearchResult(searchPromise); }; - private handleSearchResult(searchPromise: Promise) { + private handleSearchResult(searchPromise: Promise): Promise { // keep a record of the current search id, so that if the search terms // change before we get a response, we can ignore the results. const localSearchId = this.searchId; @@ -1336,7 +1322,7 @@ export default class RoomView extends React.Component { debuglog("search complete"); if (this.unmounted || !this.state.searching || this.searchId != localSearchId) { console.error("Discarding stale search results"); - return; + return false; } // postgres on synapse returns us precise details of the strings @@ -1368,6 +1354,7 @@ export default class RoomView extends React.Component { description: ((error && error.message) ? error.message : _t("Server may be unavailable, overloaded, or search timed out :(")), }); + return false; }).finally(() => { this.setState({ searchInProgress: false, @@ -1609,7 +1596,7 @@ export default class RoomView extends React.Component { const showBar = this.messagePanel.canJumpToReadMarker(); if (this.state.showTopUnreadMessagesBar != showBar) { - this.setState({showTopUnreadMessagesBar: showBar}); + this.setState({ showTopUnreadMessagesBar: showBar }); } }; @@ -1740,7 +1727,7 @@ export default class RoomView extends React.Component { onHiddenHighlightsClick = () => { const oldRoom = this.getOldRoom(); if (!oldRoom) return; - dis.dispatch({action: "view_room", room_id: oldRoom.roomId}); + dis.dispatch({ action: "view_room", room_id: oldRoom.roomId }); }; render() { @@ -1948,7 +1935,7 @@ export default class RoomView extends React.Component { > {_t( "You have %(count)s unread notifications in a prior version of this room.", - {count: hiddenHighlightCount}, + { count: hiddenHighlightCount }, )} ); @@ -2071,6 +2058,7 @@ export default class RoomView extends React.Component { resizeNotifier={this.props.resizeNotifier} showReactions={true} layout={this.state.layout} + editState={this.state.editState} />); let topUnreadMessagesBar = null; diff --git a/src/components/structures/ScrollPanel.js b/src/components/structures/ScrollPanel.tsx similarity index 72% rename from src/components/structures/ScrollPanel.js rename to src/components/structures/ScrollPanel.tsx index f6e1530537..df885575df 100644 --- a/src/components/structures/ScrollPanel.js +++ b/src/components/structures/ScrollPanel.tsx @@ -1,5 +1,5 @@ /* -Copyright 2015, 2016 OpenMarket Ltd +Copyright 2015 - 2021 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. @@ -14,17 +14,17 @@ See the License for the specific language governing permissions and limitations under the License. */ -import React, {createRef} from "react"; -import PropTypes from 'prop-types'; +import React, { createRef, CSSProperties, ReactNode, SyntheticEvent, KeyboardEvent } from "react"; import Timer from '../../utils/Timer'; import AutoHideScrollbar from "./AutoHideScrollbar"; -import {replaceableComponent} from "../../utils/replaceableComponent"; -import {getKeyBindingsManager, RoomAction} from "../../KeyBindingsManager"; +import { replaceableComponent } from "../../utils/replaceableComponent"; +import { getKeyBindingsManager, RoomAction } from "../../KeyBindingsManager"; +import ResizeNotifier from "../../utils/ResizeNotifier"; const DEBUG_SCROLL = false; // The amount of extra scroll distance to allow prior to unfilling. -// See _getExcessHeight. +// See getExcessHeight. const UNPAGINATION_PADDING = 6000; // The number of milliseconds to debounce calls to onUnfillRequest, to prevent // many scroll events causing many unfilling requests. @@ -43,6 +43,75 @@ if (DEBUG_SCROLL) { debuglog = function() {}; } +interface IProps { + /* stickyBottom: if set to true, then once the user hits the bottom of + * the list, any new children added to the list will cause the list to + * scroll down to show the new element, rather than preserving the + * existing view. + */ + stickyBottom?: boolean; + + /* startAtBottom: if set to true, the view is assumed to start + * scrolled to the bottom. + * XXX: It's likely this is unnecessary and can be derived from + * stickyBottom, but I'm adding an extra parameter to ensure + * behaviour stays the same for other uses of ScrollPanel. + * If so, let's remove this parameter down the line. + */ + startAtBottom?: boolean; + + /* className: classnames to add to the top-level div + */ + className?: string; + + /* style: styles to add to the top-level div + */ + style?: CSSProperties; + + /* resizeNotifier: ResizeNotifier to know when middle column has changed size + */ + resizeNotifier?: ResizeNotifier; + + /* fixedChildren: allows for children to be passed which are rendered outside + * of the wrapper + */ + fixedChildren?: ReactNode; + + /* onFillRequest(backwards): a callback which is called on scroll when + * the user nears the start (backwards = true) or end (backwards = + * false) of the list. + * + * This should return a promise; no more calls will be made until the + * promise completes. + * + * The promise should resolve to true if there is more data to be + * retrieved in this direction (in which case onFillRequest may be + * called again immediately), or false if there is no more data in this + * directon (at this time) - which will stop the pagination cycle until + * the user scrolls again. + */ + onFillRequest?(backwards: boolean): Promise; + + /* onUnfillRequest(backwards): a callback which is called on scroll when + * there are children elements that are far out of view and could be removed + * without causing pagination to occur. + * + * This function should accept a boolean, which is true to indicate the back/top + * of the panel and false otherwise, and a scroll token, which refers to the + * first element to remove if removing from the front/bottom, and last element + * to remove if removing from the back/top. + */ + onUnfillRequest?(backwards: boolean, scrollToken: string): void; + + /* onScroll: a callback which is called whenever any scroll happens. + */ + onScroll?(event: Event): void; + + /* onUserScroll: callback which is called when the user interacts with the room timeline + */ + onUserScroll?(event: SyntheticEvent): void; +} + /* This component implements an intelligent scrolling list. * * It wraps a list of
  • children; when items are added to the start or end @@ -84,97 +153,54 @@ if (DEBUG_SCROLL) { * offset as normal. */ +export interface IScrollState { + stuckAtBottom: boolean; + trackedNode?: HTMLElement; + trackedScrollToken?: string; + bottomOffset?: number; + pixelOffset?: number; +} + +interface IPreventShrinkingState { + offsetFromBottom: number; + offsetNode: HTMLElement; +} + @replaceableComponent("structures.ScrollPanel") -export default class ScrollPanel extends React.Component { - static propTypes = { - /* stickyBottom: if set to true, then once the user hits the bottom of - * the list, any new children added to the list will cause the list to - * scroll down to show the new element, rather than preserving the - * existing view. - */ - stickyBottom: PropTypes.bool, - - /* startAtBottom: if set to true, the view is assumed to start - * scrolled to the bottom. - * XXX: It's likely this is unnecessary and can be derived from - * stickyBottom, but I'm adding an extra parameter to ensure - * behaviour stays the same for other uses of ScrollPanel. - * If so, let's remove this parameter down the line. - */ - startAtBottom: PropTypes.bool, - - /* onFillRequest(backwards): a callback which is called on scroll when - * the user nears the start (backwards = true) or end (backwards = - * false) of the list. - * - * This should return a promise; no more calls will be made until the - * promise completes. - * - * The promise should resolve to true if there is more data to be - * retrieved in this direction (in which case onFillRequest may be - * called again immediately), or false if there is no more data in this - * directon (at this time) - which will stop the pagination cycle until - * the user scrolls again. - */ - onFillRequest: PropTypes.func, - - /* onUnfillRequest(backwards): a callback which is called on scroll when - * there are children elements that are far out of view and could be removed - * without causing pagination to occur. - * - * This function should accept a boolean, which is true to indicate the back/top - * of the panel and false otherwise, and a scroll token, which refers to the - * first element to remove if removing from the front/bottom, and last element - * to remove if removing from the back/top. - */ - onUnfillRequest: PropTypes.func, - - /* onScroll: a callback which is called whenever any scroll happens. - */ - onScroll: PropTypes.func, - - /* onUserScroll: callback which is called when the user interacts with the room timeline - */ - onUserScroll: PropTypes.func, - - /* className: classnames to add to the top-level div - */ - className: PropTypes.string, - - /* style: styles to add to the top-level div - */ - style: PropTypes.object, - - /* resizeNotifier: ResizeNotifier to know when middle column has changed size - */ - resizeNotifier: PropTypes.object, - - /* fixedChildren: allows for children to be passed which are rendered outside - * of the wrapper - */ - fixedChildren: PropTypes.node, - }; - +export default class ScrollPanel extends React.Component { static defaultProps = { stickyBottom: true, startAtBottom: true, - onFillRequest: function(backwards) { return Promise.resolve(false); }, - onUnfillRequest: function(backwards, scrollToken) {}, + onFillRequest: function(backwards: boolean) { return Promise.resolve(false); }, + onUnfillRequest: function(backwards: boolean, scrollToken: string) {}, onScroll: function() {}, }; - constructor(props) { - super(props); + private readonly pendingFillRequests: Record<"b" | "f", boolean> = { + b: null, + f: null, + }; + private readonly itemlist = createRef(); + private unmounted = false; + private scrollTimeout: Timer; + private isFilling: boolean; + private fillRequestWhileRunning: boolean; + private scrollState: IScrollState; + private preventShrinkingState: IPreventShrinkingState; + private unfillDebouncer: NodeJS.Timeout; + private bottomGrowth: number; + private pages: number; + private heightUpdateInProgress: boolean; + private divScroll: HTMLDivElement; - this._pendingFillRequests = {b: null, f: null}; + constructor(props, context) { + super(props, context); if (this.props.resizeNotifier) { this.props.resizeNotifier.on("middlePanelResizedNoisy", this.onResize); } this.resetScrollState(); - - this._itemlist = createRef(); } componentDidMount() { @@ -203,18 +229,18 @@ export default class ScrollPanel extends React.Component { } } - onScroll = ev => { + private onScroll = ev => { // skip scroll events caused by resizing if (this.props.resizeNotifier && this.props.resizeNotifier.isResizing) return; - debuglog("onScroll", this._getScrollNode().scrollTop); - this._scrollTimeout.restart(); - this._saveScrollState(); + debuglog("onScroll", this.getScrollNode().scrollTop); + this.scrollTimeout.restart(); + this.saveScrollState(); this.updatePreventShrinking(); this.props.onScroll(ev); this.checkFillState(); }; - onResize = () => { + private onResize = () => { debuglog("onResize"); this.checkScroll(); // update preventShrinkingState if present @@ -225,11 +251,11 @@ export default class ScrollPanel extends React.Component { // after an update to the contents of the panel, check that the scroll is // where it ought to be, and set off pagination requests if necessary. - checkScroll = () => { + public checkScroll = () => { if (this.unmounted) { return; } - this._restoreSavedScrollState(); + this.restoreSavedScrollState(); this.checkFillState(); }; @@ -238,8 +264,8 @@ export default class ScrollPanel extends React.Component { // note that this is independent of the 'stuckAtBottom' state - it is simply // about whether the content is scrolled down right now, irrespective of // whether it will stay that way when the children update. - isAtBottom = () => { - const sn = this._getScrollNode(); + public isAtBottom = () => { + const sn = this.getScrollNode(); // fractional values (both too big and too small) // for scrollTop happen on certain browsers/platforms // when scrolled all the way down. E.g. Chrome 72 on debian. @@ -278,10 +304,10 @@ export default class ScrollPanel extends React.Component { // |#########| - | // |#########| | // `---------' - - _getExcessHeight(backwards) { - const sn = this._getScrollNode(); - const contentHeight = this._getMessagesHeight(); - const listHeight = this._getListHeight(); + private getExcessHeight(backwards: boolean): number { + const sn = this.getScrollNode(); + const contentHeight = this.getMessagesHeight(); + const listHeight = this.getListHeight(); const clippedHeight = contentHeight - listHeight; const unclippedScrollTop = sn.scrollTop + clippedHeight; @@ -293,13 +319,13 @@ export default class ScrollPanel extends React.Component { } // check the scroll state and send out backfill requests if necessary. - checkFillState = async (depth=0) => { + public checkFillState = async (depth = 0): Promise => { if (this.unmounted) { return; } const isFirstCall = depth === 0; - const sn = this._getScrollNode(); + const sn = this.getScrollNode(); // if there is less than a screenful of messages above or below the // viewport, try to get some more messages. @@ -330,17 +356,17 @@ export default class ScrollPanel extends React.Component { // do make a note when a new request comes in while already running one, // so we can trigger a new chain of calls once done. if (isFirstCall) { - if (this._isFilling) { - debuglog("_isFilling: not entering while request is ongoing, marking for a subsequent request"); - this._fillRequestWhileRunning = true; + if (this.isFilling) { + debuglog("isFilling: not entering while request is ongoing, marking for a subsequent request"); + this.fillRequestWhileRunning = true; return; } - debuglog("_isFilling: setting"); - this._isFilling = true; + debuglog("isFilling: setting"); + this.isFilling = true; } - const itemlist = this._itemlist.current; - const firstTile = itemlist && itemlist.firstElementChild; + const itemlist = this.itemlist.current; + const firstTile = itemlist && itemlist.firstElementChild as HTMLElement; const contentTop = firstTile && firstTile.offsetTop; const fillPromises = []; @@ -348,13 +374,13 @@ export default class ScrollPanel extends React.Component { // try backward filling if (!firstTile || (sn.scrollTop - contentTop) < sn.clientHeight) { // need to back-fill - fillPromises.push(this._maybeFill(depth, true)); + fillPromises.push(this.maybeFill(depth, true)); } // if scrollTop gets to 2 screens from the end (so 1 screen below viewport), // try forward filling if ((sn.scrollHeight - sn.scrollTop) < sn.clientHeight * 2) { // need to forward-fill - fillPromises.push(this._maybeFill(depth, false)); + fillPromises.push(this.maybeFill(depth, false)); } if (fillPromises.length) { @@ -365,26 +391,26 @@ export default class ScrollPanel extends React.Component { } } if (isFirstCall) { - debuglog("_isFilling: clearing"); - this._isFilling = false; + debuglog("isFilling: clearing"); + this.isFilling = false; } - if (this._fillRequestWhileRunning) { - this._fillRequestWhileRunning = false; + if (this.fillRequestWhileRunning) { + this.fillRequestWhileRunning = false; this.checkFillState(); } }; // check if unfilling is possible and send an unfill request if necessary - _checkUnfillState(backwards) { - let excessHeight = this._getExcessHeight(backwards); + private checkUnfillState(backwards: boolean): void { + let excessHeight = this.getExcessHeight(backwards); if (excessHeight <= 0) { return; } const origExcessHeight = excessHeight; - const tiles = this._itemlist.current.children; + const tiles = this.itemlist.current.children; // The scroll token of the first/last tile to be unpaginated let markerScrollToken = null; @@ -413,11 +439,11 @@ export default class ScrollPanel extends React.Component { if (markerScrollToken) { // Use a debouncer to prevent multiple unfill calls in quick succession // This is to make the unfilling process less aggressive - if (this._unfillDebouncer) { - clearTimeout(this._unfillDebouncer); + if (this.unfillDebouncer) { + clearTimeout(this.unfillDebouncer); } - this._unfillDebouncer = setTimeout(() => { - this._unfillDebouncer = null; + this.unfillDebouncer = setTimeout(() => { + this.unfillDebouncer = null; debuglog("unfilling now", backwards, origExcessHeight); this.props.onUnfillRequest(backwards, markerScrollToken); }, UNFILL_REQUEST_DEBOUNCE_MS); @@ -425,9 +451,9 @@ export default class ScrollPanel extends React.Component { } // check if there is already a pending fill request. If not, set one off. - _maybeFill(depth, backwards) { + private maybeFill(depth: number, backwards: boolean): Promise { const dir = backwards ? 'b' : 'f'; - if (this._pendingFillRequests[dir]) { + if (this.pendingFillRequests[dir]) { debuglog("Already a "+dir+" fill in progress - not starting another"); return; } @@ -436,7 +462,7 @@ export default class ScrollPanel extends React.Component { // onFillRequest can end up calling us recursively (via onScroll // events) so make sure we set this before firing off the call. - this._pendingFillRequests[dir] = true; + this.pendingFillRequests[dir] = true; // wait 1ms before paginating, because otherwise // this will block the scroll event handler for +700ms @@ -445,13 +471,13 @@ export default class ScrollPanel extends React.Component { return new Promise(resolve => setTimeout(resolve, 1)).then(() => { return this.props.onFillRequest(backwards); }).finally(() => { - this._pendingFillRequests[dir] = false; + this.pendingFillRequests[dir] = false; }).then((hasMoreResults) => { if (this.unmounted) { return; } // Unpaginate once filling is complete - this._checkUnfillState(!backwards); + this.checkUnfillState(!backwards); debuglog(""+dir+" fill complete; hasMoreResults:"+hasMoreResults); if (hasMoreResults) { @@ -477,7 +503,7 @@ export default class ScrollPanel extends React.Component { * the number of pixels the bottom of the tracked child is above the * bottom of the scroll panel. */ - getScrollState = () => this.scrollState; + public getScrollState = (): IScrollState => this.scrollState; /* reset the saved scroll state. * @@ -491,35 +517,35 @@ export default class ScrollPanel extends React.Component { * no use if no children exist yet, or if you are about to replace the * child list.) */ - resetScrollState = () => { + public resetScrollState = (): void => { this.scrollState = { stuckAtBottom: this.props.startAtBottom, }; - this._bottomGrowth = 0; - this._pages = 0; - this._scrollTimeout = new Timer(100); - this._heightUpdateInProgress = false; + this.bottomGrowth = 0; + this.pages = 0; + this.scrollTimeout = new Timer(100); + this.heightUpdateInProgress = false; }; /** * jump to the top of the content. */ - scrollToTop = () => { - this._getScrollNode().scrollTop = 0; - this._saveScrollState(); + public scrollToTop = (): void => { + this.getScrollNode().scrollTop = 0; + this.saveScrollState(); }; /** * jump to the bottom of the content. */ - scrollToBottom = () => { + public scrollToBottom = (): void => { // the easiest way to make sure that the scroll state is correctly // saved is to do the scroll, then save the updated state. (Calculating // it ourselves is hard, and we can't rely on an onScroll callback // happening, since there may be no user-visible change here). - const sn = this._getScrollNode(); + const sn = this.getScrollNode(); sn.scrollTop = sn.scrollHeight; - this._saveScrollState(); + this.saveScrollState(); }; /** @@ -527,18 +553,18 @@ export default class ScrollPanel extends React.Component { * * @param {number} mult: -1 to page up, +1 to page down */ - scrollRelative = mult => { - const scrollNode = this._getScrollNode(); + public scrollRelative = (mult: number): void => { + const scrollNode = this.getScrollNode(); const delta = mult * scrollNode.clientHeight * 0.9; scrollNode.scrollBy(0, delta); - this._saveScrollState(); + this.saveScrollState(); }; /** * Scroll up/down in response to a scroll key * @param {object} ev the keyboard event */ - handleScrollKey = ev => { + public handleScrollKey = (ev: KeyboardEvent) => { let isScrolling = false; const roomAction = getKeyBindingsManager().getRoomAction(ev); switch (roomAction) { @@ -575,17 +601,17 @@ export default class ScrollPanel extends React.Component { * node (specifically, the bottom of it) will be positioned. If omitted, it * defaults to 0. */ - scrollToToken = (scrollToken, pixelOffset, offsetBase) => { + public scrollToToken = (scrollToken: string, pixelOffset: number, offsetBase: number): void => { pixelOffset = pixelOffset || 0; offsetBase = offsetBase || 0; - // set the trackedScrollToken so we can get the node through _getTrackedNode + // set the trackedScrollToken so we can get the node through getTrackedNode this.scrollState = { stuckAtBottom: false, trackedScrollToken: scrollToken, }; - const trackedNode = this._getTrackedNode(); - const scrollNode = this._getScrollNode(); + const trackedNode = this.getTrackedNode(); + const scrollNode = this.getScrollNode(); if (trackedNode) { // set the scrollTop to the position we want. // note though, that this might not succeed if the combination of offsetBase and pixelOffset @@ -593,36 +619,36 @@ export default class ScrollPanel extends React.Component { // This because when setting the scrollTop only 10 or so events might be loaded, // not giving enough content below the trackedNode to scroll downwards // enough so it ends up in the top of the viewport. - debuglog("scrollToken: setting scrollTop", {offsetBase, pixelOffset, offsetTop: trackedNode.offsetTop}); + debuglog("scrollToken: setting scrollTop", { offsetBase, pixelOffset, offsetTop: trackedNode.offsetTop }); scrollNode.scrollTop = (trackedNode.offsetTop - (scrollNode.clientHeight * offsetBase)) + pixelOffset; - this._saveScrollState(); + this.saveScrollState(); } }; - _saveScrollState() { + private saveScrollState(): void { if (this.props.stickyBottom && this.isAtBottom()) { this.scrollState = { stuckAtBottom: true }; debuglog("saved stuckAtBottom state"); return; } - const scrollNode = this._getScrollNode(); + const scrollNode = this.getScrollNode(); const viewportBottom = scrollNode.scrollHeight - (scrollNode.scrollTop + scrollNode.clientHeight); - const itemlist = this._itemlist.current; + const itemlist = this.itemlist.current; const messages = itemlist.children; let node = null; // TODO: do a binary search here, as items are sorted by offsetTop // loop backwards, from bottom-most message (as that is the most common case) - for (let i = messages.length-1; i >= 0; --i) { - if (!messages[i].dataset.scrollTokens) { + for (let i = messages.length - 1; i >= 0; --i) { + if (!(messages[i] as HTMLElement).dataset.scrollTokens) { continue; } node = messages[i]; // break at the first message (coming from the bottom) // that has it's offsetTop above the bottom of the viewport. - if (this._topFromBottom(node) > viewportBottom) { + if (this.topFromBottom(node) > viewportBottom) { // Use this node as the scrollToken break; } @@ -634,7 +660,7 @@ export default class ScrollPanel extends React.Component { } const scrollToken = node.dataset.scrollTokens.split(',')[0]; debuglog("saving anchored scroll state to message", node && node.innerText, scrollToken); - const bottomOffset = this._topFromBottom(node); + const bottomOffset = this.topFromBottom(node); this.scrollState = { stuckAtBottom: false, trackedNode: node, @@ -644,35 +670,35 @@ export default class ScrollPanel extends React.Component { }; } - async _restoreSavedScrollState() { + private async restoreSavedScrollState(): Promise { const scrollState = this.scrollState; if (scrollState.stuckAtBottom) { - const sn = this._getScrollNode(); + const sn = this.getScrollNode(); if (sn.scrollTop !== sn.scrollHeight) { sn.scrollTop = sn.scrollHeight; } } else if (scrollState.trackedScrollToken) { - const itemlist = this._itemlist.current; - const trackedNode = this._getTrackedNode(); + const itemlist = this.itemlist.current; + const trackedNode = this.getTrackedNode(); if (trackedNode) { - const newBottomOffset = this._topFromBottom(trackedNode); + const newBottomOffset = this.topFromBottom(trackedNode); const bottomDiff = newBottomOffset - scrollState.bottomOffset; - this._bottomGrowth += bottomDiff; + this.bottomGrowth += bottomDiff; scrollState.bottomOffset = newBottomOffset; - const newHeight = `${this._getListHeight()}px`; + const newHeight = `${this.getListHeight()}px`; if (itemlist.style.height !== newHeight) { itemlist.style.height = newHeight; } debuglog("balancing height because messages below viewport grew by", bottomDiff); } } - if (!this._heightUpdateInProgress) { - this._heightUpdateInProgress = true; + if (!this.heightUpdateInProgress) { + this.heightUpdateInProgress = true; try { - await this._updateHeight(); + await this.updateHeight(); } finally { - this._heightUpdateInProgress = false; + this.heightUpdateInProgress = false; } } else { debuglog("not updating height because request already in progress"); @@ -680,11 +706,11 @@ export default class ScrollPanel extends React.Component { } // need a better name that also indicates this will change scrollTop? Rebalance height? Reveal content? - async _updateHeight() { + private async updateHeight(): Promise { // wait until user has stopped scrolling - if (this._scrollTimeout.isRunning()) { + if (this.scrollTimeout.isRunning()) { debuglog("updateHeight waiting for scrolling to end ... "); - await this._scrollTimeout.finished(); + await this.scrollTimeout.finished(); } else { debuglog("updateHeight getting straight to business, no scrolling going on."); } @@ -694,14 +720,14 @@ export default class ScrollPanel extends React.Component { return; } - const sn = this._getScrollNode(); - const itemlist = this._itemlist.current; - const contentHeight = this._getMessagesHeight(); + const sn = this.getScrollNode(); + const itemlist = this.itemlist.current; + const contentHeight = this.getMessagesHeight(); const minHeight = sn.clientHeight; const height = Math.max(minHeight, contentHeight); - this._pages = Math.ceil(height / PAGE_SIZE); - this._bottomGrowth = 0; - const newHeight = `${this._getListHeight()}px`; + this.pages = Math.ceil(height / PAGE_SIZE); + this.bottomGrowth = 0; + const newHeight = `${this.getListHeight()}px`; const scrollState = this.scrollState; if (scrollState.stuckAtBottom) { @@ -713,7 +739,7 @@ export default class ScrollPanel extends React.Component { } debuglog("updateHeight to", newHeight); } else if (scrollState.trackedScrollToken) { - const trackedNode = this._getTrackedNode(); + const trackedNode = this.getTrackedNode(); // if the timeline has been reloaded // this can be called before scrollToBottom or whatever has been called // so don't do anything if the node has disappeared from @@ -730,22 +756,22 @@ export default class ScrollPanel extends React.Component { // yield out of date values and cause a jump // when setting it sn.scrollBy(0, topDiff); - debuglog("updateHeight to", {newHeight, topDiff}); + debuglog("updateHeight to", { newHeight, topDiff }); } } } - _getTrackedNode() { + private getTrackedNode(): HTMLElement { const scrollState = this.scrollState; const trackedNode = scrollState.trackedNode; if (!trackedNode || !trackedNode.parentElement) { let node; - const messages = this._itemlist.current.children; + const messages = this.itemlist.current.children; const scrollToken = scrollState.trackedScrollToken; for (let i = messages.length-1; i >= 0; --i) { - const m = messages[i]; + const m = messages[i] as HTMLElement; // 'data-scroll-tokens' is a DOMString of comma-separated scroll tokens // There might only be one scroll token if (m.dataset.scrollTokens && @@ -768,45 +794,45 @@ export default class ScrollPanel extends React.Component { return scrollState.trackedNode; } - _getListHeight() { - return this._bottomGrowth + (this._pages * PAGE_SIZE); + private getListHeight(): number { + return this.bottomGrowth + (this.pages * PAGE_SIZE); } - _getMessagesHeight() { - const itemlist = this._itemlist.current; - const lastNode = itemlist.lastElementChild; + private getMessagesHeight(): number { + const itemlist = this.itemlist.current; + const lastNode = itemlist.lastElementChild as HTMLElement; const lastNodeBottom = lastNode ? lastNode.offsetTop + lastNode.clientHeight : 0; - const firstNodeTop = itemlist.firstElementChild ? itemlist.firstElementChild.offsetTop : 0; + const firstNodeTop = itemlist.firstElementChild ? (itemlist.firstElementChild as HTMLElement).offsetTop : 0; // 18 is itemlist padding return lastNodeBottom - firstNodeTop + (18 * 2); } - _topFromBottom(node) { + private topFromBottom(node: HTMLElement): number { // current capped height - distance from top = distance from bottom of container to top of tracked element - return this._itemlist.current.clientHeight - node.offsetTop; + return this.itemlist.current.clientHeight - node.offsetTop; } /* get the DOM node which has the scrollTop property we care about for our * message panel. */ - _getScrollNode() { + private getScrollNode(): HTMLDivElement { if (this.unmounted) { // this shouldn't happen, but when it does, turn the NPE into // something more meaningful. - throw new Error("ScrollPanel._getScrollNode called when unmounted"); + throw new Error("ScrollPanel.getScrollNode called when unmounted"); } - if (!this._divScroll) { + if (!this.divScroll) { // Likewise, we should have the ref by this point, but if not // turn the NPE into something meaningful. - throw new Error("ScrollPanel._getScrollNode called before AutoHideScrollbar ref collected"); + throw new Error("ScrollPanel.getScrollNode called before AutoHideScrollbar ref collected"); } - return this._divScroll; + return this.divScroll; } - _collectScroll = divScroll => { - this._divScroll = divScroll; + private collectScroll = (divScroll: HTMLDivElement) => { + this.divScroll = divScroll; }; /** @@ -814,15 +840,15 @@ export default class ScrollPanel extends React.Component { anything below it changes, by calling updatePreventShrinking, to keep the same minimum bottom offset, effectively preventing the timeline to shrink. */ - preventShrinking = () => { - const messageList = this._itemlist.current; + public preventShrinking = (): void => { + const messageList = this.itemlist.current; const tiles = messageList && messageList.children; if (!messageList) { return; } let lastTileNode; for (let i = tiles.length - 1; i >= 0; i--) { - const node = tiles[i]; + const node = tiles[i] as HTMLElement; if (node.dataset.scrollTokens) { lastTileNode = node; break; @@ -841,8 +867,8 @@ export default class ScrollPanel extends React.Component { }; /** Clear shrinking prevention. Used internally, and when the timeline is reloaded. */ - clearPreventShrinking = () => { - const messageList = this._itemlist.current; + public clearPreventShrinking = (): void => { + const messageList = this.itemlist.current; const balanceElement = messageList && messageList.parentElement; if (balanceElement) balanceElement.style.paddingBottom = null; this.preventShrinkingState = null; @@ -857,12 +883,12 @@ export default class ScrollPanel extends React.Component { from the bottom of the marked tile grows larger than what it was when marking. */ - updatePreventShrinking = () => { + public updatePreventShrinking = (): void => { if (this.preventShrinkingState) { - const sn = this._getScrollNode(); + const sn = this.getScrollNode(); const scrollState = this.scrollState; - const messageList = this._itemlist.current; - const {offsetNode, offsetFromBottom} = this.preventShrinkingState; + const messageList = this.itemlist.current; + const { offsetNode, offsetFromBottom } = this.preventShrinkingState; // element used to set paddingBottom to balance the typing notifs disappearing const balanceElement = messageList.parentElement; // if the offsetNode got unmounted, clear @@ -898,13 +924,15 @@ export default class ScrollPanel extends React.Component { // list-style-type: none; is no longer a list return ( + className={`mx_ScrollPanel ${this.props.className}`} + style={this.props.style} + > { this.props.fixedChildren }
    -
      +
        { this.props.children }
    diff --git a/src/components/structures/SearchBox.js b/src/components/structures/SearchBox.js index abeb858274..5c966d2d3a 100644 --- a/src/components/structures/SearchBox.js +++ b/src/components/structures/SearchBox.js @@ -15,14 +15,14 @@ See the License for the specific language governing permissions and limitations under the License. */ -import React, {createRef} from 'react'; +import React, { createRef } from 'react'; import PropTypes from 'prop-types'; import { Key } from '../../Keyboard'; import dis from '../../dispatcher/dispatcher'; -import {throttle} from 'lodash'; +import { throttle } from 'lodash'; import AccessibleButton from '../../components/views/elements/AccessibleButton'; import classNames from 'classnames'; -import {replaceableComponent} from "../../utils/replaceableComponent"; +import { replaceableComponent } from "../../utils/replaceableComponent"; @replaceableComponent("structures.SearchBox") export default class SearchBox extends React.Component { @@ -89,7 +89,7 @@ export default class SearchBox extends React.Component { onSearch = throttle(() => { this.props.onSearch(this._search.current.value); - }, 200, {trailing: true, leading: true}); + }, 200, { trailing: true, leading: true }); _onKeyDown = ev => { switch (ev.key) { @@ -101,7 +101,7 @@ export default class SearchBox extends React.Component { }; _onFocus = ev => { - this.setState({blurred: false}); + this.setState({ blurred: false }); ev.target.select(); if (this.props.onFocus) { this.props.onFocus(ev); @@ -109,7 +109,7 @@ export default class SearchBox extends React.Component { }; _onBlur = ev => { - this.setState({blurred: true}); + this.setState({ blurred: true }); if (this.props.onBlur) { this.props.onBlur(ev); } @@ -147,7 +147,7 @@ export default class SearchBox extends React.Component { this.props.placeholder; const className = this.props.className || ""; return ( -
    +
    = ({ ev.preventDefault(); ev.stopPropagation(); onViewRoomClick(false); - } + }; const onJoinClick = (ev: ButtonEvent) => { ev.preventDefault(); ev.stopPropagation(); onViewRoomClick(true); - } + }; let button; if (joinedRoom) { @@ -137,7 +137,7 @@ const Tile: React.FC = ({ } else { checkbox = { ev.stopPropagation() }} + onClick={ev => { ev.stopPropagation(); }} > ; @@ -340,7 +340,7 @@ export const HierarchyLevel = ({ )) } - + ; }; // mutate argument refreshToken to force a reload @@ -635,9 +635,9 @@ const SpaceRoomDirectory: React.FC = ({ space, onFinished, initialText }
    { _t("If you can't find the room you're looking for, ask for an invite or create a new room.", null, - {a: sub => { + { a: sub => { return {sub}; - }}, + } }, ) } { ) : null} } -
    +
    ; }; const onBetaClick = () => { @@ -592,14 +592,14 @@ const SpaceSetupPrivateScope = ({ space, justCreatedOpts, onFinished }) => { { onFinished(false) }} + onClick={() => { onFinished(false); }} >

    { _t("Just me") }

    { _t("A private space to organise your rooms") }
    { onFinished(true) }} + onClick={() => { onFinished(true); }} >

    { _t("Me and my teammates") }

    { _t("A private space for you and your teammates") }
    @@ -686,7 +686,7 @@ const SpaceSetupPrivateInvite = ({ space, onFinished }) => { let buttonLabel = _t("Skip for now"); if (emailAddresses.some(name => name.trim())) { onClick = onNextClick; - buttonLabel = busy ? _t("Inviting...") : _t("Continue") + buttonLabel = busy ? _t("Inviting...") : _t("Continue"); } return
    diff --git a/src/components/structures/TabbedView.tsx b/src/components/structures/TabbedView.tsx index 0097d55cf5..3d77eaeac1 100644 --- a/src/components/structures/TabbedView.tsx +++ b/src/components/structures/TabbedView.tsx @@ -17,10 +17,10 @@ limitations under the License. */ import * as React from "react"; -import {_t} from '../../languageHandler'; +import { _t } from '../../languageHandler'; import * as sdk from "../../index"; import AutoHideScrollbar from './AutoHideScrollbar'; -import {replaceableComponent} from "../../utils/replaceableComponent"; +import { replaceableComponent } from "../../utils/replaceableComponent"; /** * Represents a tab for the TabbedView. @@ -75,7 +75,7 @@ export default class TabbedView extends React.Component { private _setActiveTab(tab: Tab) { const idx = this.props.tabs.indexOf(tab); if (idx !== -1) { - this.setState({activeTabIndex: idx}); + this.setState({ activeTabIndex: idx }); } else { console.error("Could not find tab " + tab.label + " in tabs"); } diff --git a/src/components/structures/TimelinePanel.js b/src/components/structures/TimelinePanel.tsx similarity index 74% rename from src/components/structures/TimelinePanel.js rename to src/components/structures/TimelinePanel.tsx index ad20d38139..e4c7d15596 100644 --- a/src/components/structures/TimelinePanel.js +++ b/src/components/structures/TimelinePanel.tsx @@ -1,8 +1,5 @@ /* -Copyright 2016 OpenMarket Ltd -Copyright 2017 Vector Creations Ltd -Copyright 2019 New Vector Ltd -Copyright 2019-2020 The Matrix.org Foundation C.I.C. +Copyright 2016 - 2021 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. @@ -17,13 +14,16 @@ See the License for the specific language governing permissions and limitations under the License. */ -import SettingsStore from "../../settings/SettingsStore"; -import { LayoutPropType } from "../../settings/Layout"; -import React, { createRef } from 'react'; +import React, { createRef, ReactNode, SyntheticEvent } from 'react'; import ReactDOM from "react-dom"; -import PropTypes from 'prop-types'; +import { Room } from "matrix-js-sdk/src/models/room"; +import { MatrixEvent } from "matrix-js-sdk/src/models/event"; +import { TimelineSet } from "matrix-js-sdk/src/models/event-timeline-set"; import { EventTimeline } from "matrix-js-sdk/src/models/event-timeline"; import { TimelineWindow } from "matrix-js-sdk/src/timeline-window"; + +import SettingsStore from "../../settings/SettingsStore"; +import { Layout } from "../../settings/Layout"; import { _t } from '../../languageHandler'; import { MatrixClientPeg } from "../../MatrixClientPeg"; import RoomContext from "../../contexts/RoomContext"; @@ -34,10 +34,19 @@ import * as sdk from "../../index"; import { Key } from '../../Keyboard'; import Timer from '../../utils/Timer'; import shouldHideEvent from '../../shouldHideEvent'; -import { haveTileForEvent } from "../views/rooms/EventTile"; +import { haveTileForEvent, TileShape } from "../views/rooms/EventTile"; import { UIFeature } from "../../settings/UIFeature"; import { replaceableComponent } from "../../utils/replaceableComponent"; import { arrayFastClone } from "../../utils/arrays"; +import MessagePanel from "./MessagePanel"; +import { SyncState } from 'matrix-js-sdk/src/sync.api'; +import { IScrollState } from "./ScrollPanel"; +import { ActionPayload } from "../../dispatcher/payloads"; +import { EventType } from 'matrix-js-sdk/src/@types/event'; +import ResizeNotifier from "../../utils/ResizeNotifier"; +import { RoomPermalinkCreator } from "../../utils/permalinks/Permalinks"; +import Spinner from "../views/elements/Spinner"; +import EditorStateTransfer from '../../utils/EditorStateTransfer'; const PAGINATE_SIZE = 20; const INITIAL_SIZE = 20; @@ -45,92 +54,159 @@ const READ_RECEIPT_INTERVAL_MS = 500; const DEBUG = false; -let debuglog = function() {}; +let debuglog = function(...s: any[]) {}; if (DEBUG) { // using bind means that we get to keep useful line numbers in the console debuglog = console.log.bind(console); } +interface IProps { + // The js-sdk EventTimelineSet object for the timeline sequence we are + // representing. This may or may not have a room, depending on what it's + // a timeline representing. If it has a room, we maintain RRs etc for + // that room. + timelineSet: TimelineSet; + showReadReceipts?: boolean; + // Enable managing RRs and RMs. These require the timelineSet to have a room. + manageReadReceipts?: boolean; + sendReadReceiptOnLoad?: boolean; + manageReadMarkers?: boolean; + + // true to give the component a 'display: none' style. + hidden?: boolean; + + // ID of an event to highlight. If undefined, no event will be highlighted. + // typically this will be either 'eventId' or undefined. + highlightedEventId?: string; + + // id of an event to jump to. If not given, will go to the end of the live timeline. + eventId?: string; + + // where to position the event given by eventId, in pixels from the bottom of the viewport. + // If not given, will try to put the event half way down the viewport. + eventPixelOffset?: number; + + // Should we show URL Previews + showUrlPreview?: boolean; + + // maximum number of events to show in a timeline + timelineCap?: number; + + // classname to use for the messagepanel + className?: string; + + // shape property to be passed to EventTiles + tileShape?: TileShape; + + // placeholder to use if the timeline is empty + empty?: ReactNode; + + // whether to show reactions for an event + showReactions?: boolean; + + // which layout to use + layout?: Layout; + + // whether to always show timestamps for an event + alwaysShowTimestamps?: boolean; + + resizeNotifier?: ResizeNotifier; + editState?: EditorStateTransfer; + permalinkCreator?: RoomPermalinkCreator; + membersLoaded?: boolean; + + // callback which is called when the panel is scrolled. + onScroll?(event: Event): void; + + // callback which is called when the user interacts with the room timeline + onUserScroll?(event: SyntheticEvent): void; + + // callback which is called when the read-up-to mark is updated. + onReadMarkerUpdated?(): void; + + // callback which is called when we wish to paginate the timeline window. + onPaginationRequest?(timelineWindow: TimelineWindow, direction: string, size: number): Promise, +} + +interface IState { + events: MatrixEvent[]; + liveEvents: MatrixEvent[]; + // track whether our room timeline is loading + timelineLoading: boolean; + + // the index of the first event that is to be shown + firstVisibleEventIndex: number; + + // canBackPaginate == false may mean: + // + // * we haven't (successfully) loaded the timeline yet, or: + // + // * we have got to the point where the room was created, or: + // + // * the server indicated that there were no more visible events + // (normally implying we got to the start of the room), or: + // + // * we gave up asking the server for more events + canBackPaginate: boolean; + + // canForwardPaginate == false may mean: + // + // * we haven't (successfully) loaded the timeline yet + // + // * we have got to the end of time and are now tracking the live + // timeline, or: + // + // * the server indicated that there were no more visible events + // (not sure if this ever happens when we're not at the live + // timeline), or: + // + // * we are looking at some historical point, but gave up asking + // the server for more events + canForwardPaginate: boolean; + + // start with the read-marker visible, so that we see its animated + // disappearance when switching into the room. + readMarkerVisible: boolean; + + readMarkerEventId: string; + + backPaginating: boolean; + forwardPaginating: boolean; + + // cache of matrixClient.getSyncState() (but from the 'sync' event) + clientSyncState: SyncState; + + // should the event tiles have twelve hour times + isTwelveHour: boolean; + + // always show timestamps on event tiles? + alwaysShowTimestamps: boolean; + + // how long to show the RM for when it's visible in the window + readMarkerInViewThresholdMs: number; + + // how long to show the RM for when it's scrolled off-screen + readMarkerOutOfViewThresholdMs: number; + + editState?: EditorStateTransfer; +} + +interface IEventIndexOpts { + ignoreOwn?: boolean; + allowPartial?: boolean; +} + /* * Component which shows the event timeline in a room view. * * Also responsible for handling and sending read receipts. */ @replaceableComponent("structures.TimelinePanel") -class TimelinePanel extends React.Component { - static propTypes = { - // The js-sdk EventTimelineSet object for the timeline sequence we are - // representing. This may or may not have a room, depending on what it's - // a timeline representing. If it has a room, we maintain RRs etc for - // that room. - timelineSet: PropTypes.object.isRequired, - - showReadReceipts: PropTypes.bool, - // Enable managing RRs and RMs. These require the timelineSet to have a room. - manageReadReceipts: PropTypes.bool, - sendReadReceiptOnLoad: PropTypes.bool, - manageReadMarkers: PropTypes.bool, - // with this enabled it'll listen and react to Action.ComposerInsert and `edit_event` - manageComposerDispatches: PropTypes.bool, - - // true to give the component a 'display: none' style. - hidden: PropTypes.bool, - - // ID of an event to highlight. If undefined, no event will be highlighted. - // typically this will be either 'eventId' or undefined. - highlightedEventId: PropTypes.string, - - // id of an event to jump to. If not given, will go to the end of the - // live timeline. - eventId: PropTypes.string, - - // where to position the event given by eventId, in pixels from the - // bottom of the viewport. If not given, will try to put the event - // half way down the viewport. - eventPixelOffset: PropTypes.number, - - // Should we show URL Previews - showUrlPreview: PropTypes.bool, - - // callback which is called when the panel is scrolled. - onScroll: PropTypes.func, - - // callback which is called when the user interacts with the room timeline - onUserScroll: PropTypes.func, - - // callback which is called when the read-up-to mark is updated. - onReadMarkerUpdated: PropTypes.func, - - // callback which is called when we wish to paginate the timeline - // window. - onPaginationRequest: PropTypes.func, - - // maximum number of events to show in a timeline - timelineCap: PropTypes.number, - - // classname to use for the messagepanel - className: PropTypes.string, - - // shape property to be passed to EventTiles - tileShape: PropTypes.string, - - // placeholder to use if the timeline is empty - empty: PropTypes.node, - - // whether to show reactions for an event - showReactions: PropTypes.bool, - - // which layout to use - layout: LayoutPropType, - - // whether to always show timestamps for an event - alwaysShowTimestamps: PropTypes.bool, - } - +class TimelinePanel extends React.Component { static contextType = RoomContext; // a map from room id to read marker event timestamp - static roomReadMarkerTsMap = {}; + static roomReadMarkerTsMap: Record = {}; static defaultProps = { // By default, disable the timelineCap in favour of unpaginating based on @@ -140,16 +216,21 @@ class TimelinePanel extends React.Component { sendReadReceiptOnLoad: true, }; - constructor(props) { - super(props); + private lastRRSentEventId: string = undefined; + private lastRMSentEventId: string = undefined; + + private readonly messagePanel = createRef(); + private readonly dispatcherRef: string; + private timelineWindow?: TimelineWindow; + private unmounted = false; + private readReceiptActivityTimer: Timer; + private readMarkerActivityTimer: Timer; + + constructor(props, context) { + super(props, context); debuglog("TimelinePanel: mounting"); - this.lastRRSentEventId = undefined; - this.lastRMSentEventId = undefined; - - this._messagePanel = createRef(); - // XXX: we could track RM per TimelineSet rather than per Room. // but for now we just do it per room for simplicity. let initialReadMarker = null; @@ -158,82 +239,41 @@ class TimelinePanel extends React.Component { if (readmarker) { initialReadMarker = readmarker.getContent().event_id; } else { - initialReadMarker = this._getCurrentReadReceipt(); + initialReadMarker = this.getCurrentReadReceipt(); } } this.state = { events: [], liveEvents: [], - timelineLoading: true, // track whether our room timeline is loading - - // the index of the first event that is to be shown + timelineLoading: true, firstVisibleEventIndex: 0, - - // canBackPaginate == false may mean: - // - // * we haven't (successfully) loaded the timeline yet, or: - // - // * we have got to the point where the room was created, or: - // - // * the server indicated that there were no more visible events - // (normally implying we got to the start of the room), or: - // - // * we gave up asking the server for more events canBackPaginate: false, - - // canForwardPaginate == false may mean: - // - // * we haven't (successfully) loaded the timeline yet - // - // * we have got to the end of time and are now tracking the live - // timeline, or: - // - // * the server indicated that there were no more visible events - // (not sure if this ever happens when we're not at the live - // timeline), or: - // - // * we are looking at some historical point, but gave up asking - // the server for more events canForwardPaginate: false, - - // start with the read-marker visible, so that we see its animated - // disappearance when switching into the room. readMarkerVisible: true, - readMarkerEventId: initialReadMarker, - backPaginating: false, forwardPaginating: false, - - // cache of matrixClient.getSyncState() (but from the 'sync' event) clientSyncState: MatrixClientPeg.get().getSyncState(), - - // should the event tiles have twelve hour times isTwelveHour: SettingsStore.getValue("showTwelveHourTimestamps"), - - // always show timestamps on event tiles? alwaysShowTimestamps: SettingsStore.getValue("alwaysShowTimestamps"), - - // how long to show the RM for when it's visible in the window readMarkerInViewThresholdMs: SettingsStore.getValue("readMarkerInViewThresholdMs"), - - // how long to show the RM for when it's scrolled off-screen readMarkerOutOfViewThresholdMs: SettingsStore.getValue("readMarkerOutOfViewThresholdMs"), }; this.dispatcherRef = dis.register(this.onAction); - MatrixClientPeg.get().on("Room.timeline", this.onRoomTimeline); - MatrixClientPeg.get().on("Room.timelineReset", this.onRoomTimelineReset); - MatrixClientPeg.get().on("Room.redaction", this.onRoomRedaction); + const cli = MatrixClientPeg.get(); + cli.on("Room.timeline", this.onRoomTimeline); + cli.on("Room.timelineReset", this.onRoomTimelineReset); + cli.on("Room.redaction", this.onRoomRedaction); // same event handler as Room.redaction as for both we just do forceUpdate - MatrixClientPeg.get().on("Room.redactionCancelled", this.onRoomRedaction); - MatrixClientPeg.get().on("Room.receipt", this.onRoomReceipt); - MatrixClientPeg.get().on("Room.localEchoUpdated", this.onLocalEchoUpdated); - MatrixClientPeg.get().on("Room.accountData", this.onAccountData); - MatrixClientPeg.get().on("Event.decrypted", this.onEventDecrypted); - MatrixClientPeg.get().on("Event.replaced", this.onEventReplaced); - MatrixClientPeg.get().on("sync", this.onSync); + cli.on("Room.redactionCancelled", this.onRoomRedaction); + cli.on("Room.receipt", this.onRoomReceipt); + cli.on("Room.localEchoUpdated", this.onLocalEchoUpdated); + cli.on("Room.accountData", this.onAccountData); + cli.on("Event.decrypted", this.onEventDecrypted); + cli.on("Event.replaced", this.onEventReplaced); + cli.on("sync", this.onSync); } // TODO: [REACT-WARNING] Move into constructor @@ -246,7 +286,7 @@ class TimelinePanel extends React.Component { this.updateReadMarkerOnUserActivity(); } - this._initTimeline(this.props); + this.initTimeline(this.props); } // TODO: [REACT-WARNING] Replace with appropriate lifecycle event @@ -272,7 +312,7 @@ class TimelinePanel extends React.Component { if (differentEventId || differentHighlightedEventId) { console.log("TimelinePanel switching to eventId " + newProps.eventId + " (was " + this.props.eventId + ")"); - return this._initTimeline(newProps); + return this.initTimeline(newProps); } } @@ -282,13 +322,13 @@ class TimelinePanel extends React.Component { // // (We could use isMounted, but facebook have deprecated that.) this.unmounted = true; - if (this._readReceiptActivityTimer) { - this._readReceiptActivityTimer.abort(); - this._readReceiptActivityTimer = null; + if (this.readReceiptActivityTimer) { + this.readReceiptActivityTimer.abort(); + this.readReceiptActivityTimer = null; } - if (this._readMarkerActivityTimer) { - this._readMarkerActivityTimer.abort(); - this._readMarkerActivityTimer = null; + if (this.readMarkerActivityTimer) { + this.readMarkerActivityTimer.abort(); + this.readMarkerActivityTimer = null; } dis.unregister(this.dispatcherRef); @@ -308,7 +348,7 @@ class TimelinePanel extends React.Component { } } - onMessageListUnfillRequest = (backwards, scrollToken) => { + private onMessageListUnfillRequest = (backwards: boolean, scrollToken: string): void => { // If backwards, unpaginate from the back (i.e. the start of the timeline) const dir = backwards ? EventTimeline.BACKWARDS : EventTimeline.FORWARDS; debuglog("TimelinePanel: unpaginating events in direction", dir); @@ -327,21 +367,30 @@ class TimelinePanel extends React.Component { if (count > 0) { debuglog("TimelinePanel: Unpaginating", count, "in direction", dir); - this._timelineWindow.unpaginate(count, backwards); + this.timelineWindow.unpaginate(count, backwards); - // We can now paginate in the unpaginated direction - const canPaginateKey = (backwards) ? 'canBackPaginate' : 'canForwardPaginate'; - const { events, liveEvents, firstVisibleEventIndex } = this._getEvents(); - this.setState({ - [canPaginateKey]: true, + const { events, liveEvents, firstVisibleEventIndex } = this.getEvents(); + const newState: Partial = { events, liveEvents, firstVisibleEventIndex, - }); + }; + + // We can now paginate in the unpaginated direction + if (backwards) { + newState.canBackPaginate = true; + } else { + newState.canForwardPaginate = true; + } + this.setState(newState); } }; - onPaginationRequest = (timelineWindow, direction, size) => { + private onPaginationRequest = ( + timelineWindow: TimelineWindow, + direction: string, + size: number, + ): Promise => { if (this.props.onPaginationRequest) { return this.props.onPaginationRequest(timelineWindow, direction, size); } else { @@ -350,8 +399,8 @@ class TimelinePanel extends React.Component { }; // set off a pagination request. - onMessageListFillRequest = backwards => { - if (!this._shouldPaginate()) return Promise.resolve(false); + private onMessageListFillRequest = (backwards: boolean): Promise => { + if (!this.shouldPaginate()) return Promise.resolve(false); const dir = backwards ? EventTimeline.BACKWARDS : EventTimeline.FORWARDS; const canPaginateKey = backwards ? 'canBackPaginate' : 'canForwardPaginate'; @@ -362,9 +411,9 @@ class TimelinePanel extends React.Component { return Promise.resolve(false); } - if (!this._timelineWindow.canPaginate(dir)) { + if (!this.timelineWindow.canPaginate(dir)) { debuglog("TimelinePanel: can't", dir, "paginate any further"); - this.setState({[canPaginateKey]: false}); + this.setState({ [canPaginateKey]: false }); return Promise.resolve(false); } @@ -374,15 +423,15 @@ class TimelinePanel extends React.Component { } debuglog("TimelinePanel: Initiating paginate; backwards:"+backwards); - this.setState({[paginatingKey]: true}); + this.setState({ [paginatingKey]: true }); - return this.onPaginationRequest(this._timelineWindow, dir, PAGINATE_SIZE).then((r) => { + return this.onPaginationRequest(this.timelineWindow, dir, PAGINATE_SIZE).then((r) => { if (this.unmounted) { return; } debuglog("TimelinePanel: paginate complete backwards:"+backwards+"; success:"+r); - const { events, liveEvents, firstVisibleEventIndex } = this._getEvents(); - const newState = { + const { events, liveEvents, firstVisibleEventIndex } = this.getEvents(); + const newState: Partial = { [paginatingKey]: false, [canPaginateKey]: r, events, @@ -395,7 +444,7 @@ class TimelinePanel extends React.Component { const otherDirection = backwards ? EventTimeline.FORWARDS : EventTimeline.BACKWARDS; const canPaginateOtherWayKey = backwards ? 'canForwardPaginate' : 'canBackPaginate'; if (!this.state[canPaginateOtherWayKey] && - this._timelineWindow.canPaginate(otherDirection)) { + this.timelineWindow.canPaginate(otherDirection)) { debuglog('TimelinePanel: can now', otherDirection, 'paginate again'); newState[canPaginateOtherWayKey] = true; } @@ -406,9 +455,9 @@ class TimelinePanel extends React.Component { // has in memory because we never gave the component a chance to scroll // itself into the right place return new Promise((resolve) => { - this.setState(newState, () => { + this.setState(newState, () => { // we can continue paginating in the given direction if: - // - _timelineWindow.paginate says we can + // - timelineWindow.paginate says we can // - we're paginating forwards, or we won't be trying to // paginate backwards past the first visible event resolve(r && (!backwards || firstVisibleEventIndex === 0)); @@ -417,7 +466,7 @@ class TimelinePanel extends React.Component { }); }; - onMessageListScroll = e => { + private onMessageListScroll = e => { if (this.props.onScroll) { this.props.onScroll(e); } @@ -428,18 +477,18 @@ class TimelinePanel extends React.Component { // it goes back off the top of the screen (presumably because the user // clicks on the 'jump to bottom' button), we need to re-enable it. if (rmPosition < 0) { - this.setState({readMarkerVisible: true}); + this.setState({ readMarkerVisible: true }); } // if read marker position goes between 0 and -1/1, // (and user is active), switch timeout - const timeout = this._readMarkerTimeout(rmPosition); + const timeout = this.readMarkerTimeout(rmPosition); // NO-OP when timeout already has set to the given value - this._readMarkerActivityTimer.changeTimeout(timeout); + this.readMarkerActivityTimer.changeTimeout(timeout); } }; - onAction = payload => { + private onAction = (payload: ActionPayload): void => { switch (payload.action) { case "ignore_state_changed": this.forceUpdate(); @@ -447,7 +496,16 @@ class TimelinePanel extends React.Component { } }; - onRoomTimeline = (ev, room, toStartOfTimeline, removed, data) => { + private onRoomTimeline = ( + ev: MatrixEvent, + room: Room, + toStartOfTimeline: boolean, + removed: boolean, + data: { + timeline: EventTimeline; + liveEvent?: boolean; + }, + ): void => { // ignore events for other timeline sets if (data.timeline.getTimelineSet() !== this.props.timelineSet) return; @@ -455,13 +513,13 @@ class TimelinePanel extends React.Component { // updates from pagination will happen when the paginate completes. if (toStartOfTimeline || !data || !data.liveEvent) return; - if (!this._messagePanel.current) return; + if (!this.messagePanel.current) return; - if (!this._messagePanel.current.getScrollState().stuckAtBottom) { + if (!this.messagePanel.current.getScrollState().stuckAtBottom) { // we won't load this event now, because we don't want to push any // events off the other end of the timeline. But we need to note // that we can now paginate. - this.setState({canForwardPaginate: true}); + this.setState({ canForwardPaginate: true }); return; } @@ -474,13 +532,13 @@ class TimelinePanel extends React.Component { // timeline window. // // see https://github.com/vector-im/vector-web/issues/1035 - this._timelineWindow.paginate(EventTimeline.FORWARDS, 1, false).then(() => { + this.timelineWindow.paginate(EventTimeline.FORWARDS, 1, false).then(() => { if (this.unmounted) { return; } - const { events, liveEvents, firstVisibleEventIndex } = this._getEvents(); + const { events, liveEvents, firstVisibleEventIndex } = this.getEvents(); const lastLiveEvent = liveEvents[liveEvents.length - 1]; - const updatedState = { + const updatedState: Partial = { events, liveEvents, firstVisibleEventIndex, @@ -505,15 +563,15 @@ class TimelinePanel extends React.Component { // we know we're stuckAtBottom, so we can advance the RM // immediately, to save a later render cycle - this._setReadMarker(lastLiveEvent.getId(), lastLiveEvent.getTs(), true); + this.setReadMarker(lastLiveEvent.getId(), lastLiveEvent.getTs(), true); updatedState.readMarkerVisible = false; updatedState.readMarkerEventId = lastLiveEvent.getId(); callRMUpdated = true; } } - this.setState(updatedState, () => { - this._messagePanel.current.updateTimelineMinHeight(); + this.setState(updatedState, () => { + this.messagePanel.current.updateTimelineMinHeight(); if (callRMUpdated) { this.props.onReadMarkerUpdated(); } @@ -521,17 +579,17 @@ class TimelinePanel extends React.Component { }); }; - onRoomTimelineReset = (room, timelineSet) => { + private onRoomTimelineReset = (room: Room, timelineSet: TimelineSet): void => { if (timelineSet !== this.props.timelineSet) return; - if (this._messagePanel.current && this._messagePanel.current.isAtBottom()) { - this._loadTimeline(); + if (this.messagePanel.current && this.messagePanel.current.isAtBottom()) { + this.loadTimeline(); } }; - canResetTimeline = () => this._messagePanel.current && this._messagePanel.current.isAtBottom(); + public canResetTimeline = () => this.messagePanel?.current.isAtBottom(); - onRoomRedaction = (ev, room) => { + private onRoomRedaction = (ev: MatrixEvent, room: Room): void => { if (this.unmounted) return; // ignore events for other rooms @@ -542,7 +600,7 @@ class TimelinePanel extends React.Component { this.forceUpdate(); }; - onEventReplaced = (replacedEvent, room) => { + private onEventReplaced = (replacedEvent: MatrixEvent, room: Room): void => { if (this.unmounted) return; // ignore events for other rooms @@ -553,7 +611,7 @@ class TimelinePanel extends React.Component { this.forceUpdate(); }; - onRoomReceipt = (ev, room) => { + private onRoomReceipt = (ev: MatrixEvent, room: Room): void => { if (this.unmounted) return; // ignore events for other rooms @@ -562,22 +620,22 @@ class TimelinePanel extends React.Component { this.forceUpdate(); }; - onLocalEchoUpdated = (ev, room, oldEventId) => { + private onLocalEchoUpdated = (ev: MatrixEvent, room: Room, oldEventId: string): void => { if (this.unmounted) return; // ignore events for other rooms if (room !== this.props.timelineSet.room) return; - this._reloadEvents(); + this.reloadEvents(); }; - onAccountData = (ev, room) => { + private onAccountData = (ev: MatrixEvent, room: Room): void => { if (this.unmounted) return; // ignore events for other rooms if (room !== this.props.timelineSet.room) return; - if (ev.getType() !== "m.fully_read") return; + if (ev.getType() !== EventType.FullyRead) return; // XXX: roomReadMarkerTsMap not updated here so it is now inconsistent. Replace // this mechanism of determining where the RM is relative to the view-port with @@ -587,7 +645,7 @@ class TimelinePanel extends React.Component { }, this.props.onReadMarkerUpdated); }; - onEventDecrypted = ev => { + private onEventDecrypted = (ev: MatrixEvent): void => { // Can be null for the notification timeline, etc. if (!this.props.timelineSet.room) return; @@ -602,46 +660,46 @@ class TimelinePanel extends React.Component { } }; - onSync = (state, prevState, data) => { - this.setState({clientSyncState: state}); + private onSync = (clientSyncState: SyncState, prevState: SyncState, data: object): void => { + this.setState({ clientSyncState }); }; - _readMarkerTimeout(readMarkerPosition) { + private readMarkerTimeout(readMarkerPosition: number): number { return readMarkerPosition === 0 ? this.state.readMarkerInViewThresholdMs : this.state.readMarkerOutOfViewThresholdMs; } - async updateReadMarkerOnUserActivity() { - const initialTimeout = this._readMarkerTimeout(this.getReadMarkerPosition()); - this._readMarkerActivityTimer = new Timer(initialTimeout); + private async updateReadMarkerOnUserActivity(): Promise { + const initialTimeout = this.readMarkerTimeout(this.getReadMarkerPosition()); + this.readMarkerActivityTimer = new Timer(initialTimeout); - while (this._readMarkerActivityTimer) { //unset on unmount - UserActivity.sharedInstance().timeWhileActiveRecently(this._readMarkerActivityTimer); + while (this.readMarkerActivityTimer) { //unset on unmount + UserActivity.sharedInstance().timeWhileActiveRecently(this.readMarkerActivityTimer); try { - await this._readMarkerActivityTimer.finished(); + await this.readMarkerActivityTimer.finished(); } catch (e) { continue; /* aborted */ } // outside of try/catch to not swallow errors this.updateReadMarker(); } } - async updateReadReceiptOnUserActivity() { - this._readReceiptActivityTimer = new Timer(READ_RECEIPT_INTERVAL_MS); - while (this._readReceiptActivityTimer) { //unset on unmount - UserActivity.sharedInstance().timeWhileActiveNow(this._readReceiptActivityTimer); + private async updateReadReceiptOnUserActivity(): Promise { + this.readReceiptActivityTimer = new Timer(READ_RECEIPT_INTERVAL_MS); + while (this.readReceiptActivityTimer) { //unset on unmount + UserActivity.sharedInstance().timeWhileActiveNow(this.readReceiptActivityTimer); try { - await this._readReceiptActivityTimer.finished(); + await this.readReceiptActivityTimer.finished(); } catch (e) { continue; /* aborted */ } // outside of try/catch to not swallow errors this.sendReadReceipt(); } } - sendReadReceipt = () => { + private sendReadReceipt = (): void => { if (SettingsStore.getValue("lowBandwidth")) return; - if (!this._messagePanel.current) return; + if (!this.messagePanel.current) return; if (!this.props.manageReadReceipts) return; // This happens on user_activity_end which is delayed, and it's // very possible have logged out within that timeframe, so check @@ -652,8 +710,8 @@ class TimelinePanel extends React.Component { let shouldSendRR = true; - const currentRREventId = this._getCurrentReadReceipt(true); - const currentRREventIndex = this._indexForEventId(currentRREventId); + const currentRREventId = this.getCurrentReadReceipt(true); + const currentRREventIndex = this.indexForEventId(currentRREventId); // We want to avoid sending out read receipts when we are looking at // events in the past which are before the latest RR. // @@ -668,11 +726,11 @@ class TimelinePanel extends React.Component { // the user eventually hits the live timeline. // if (currentRREventId && currentRREventIndex === null && - this._timelineWindow.canPaginate(EventTimeline.FORWARDS)) { + this.timelineWindow.canPaginate(EventTimeline.FORWARDS)) { shouldSendRR = false; } - const lastReadEventIndex = this._getLastDisplayedEventIndex({ + const lastReadEventIndex = this.getLastDisplayedEventIndex({ ignoreOwn: true, }); if (lastReadEventIndex === null) { @@ -746,7 +804,7 @@ class TimelinePanel extends React.Component { // if the read marker is on the screen, we can now assume we've caught up to the end // of the screen, so move the marker down to the bottom of the screen. - updateReadMarker = () => { + private updateReadMarker = (): void => { if (!this.props.manageReadMarkers) return; if (this.getReadMarkerPosition() === 1) { // the read marker is at an event below the viewport, @@ -756,7 +814,7 @@ class TimelinePanel extends React.Component { // move the RM to *after* the message at the bottom of the screen. This // avoids a problem whereby we never advance the RM if there is a huge // message which doesn't fit on the screen. - const lastDisplayedIndex = this._getLastDisplayedEventIndex({ + const lastDisplayedIndex = this.getLastDisplayedEventIndex({ allowPartial: true, }); @@ -764,7 +822,7 @@ class TimelinePanel extends React.Component { return; } const lastDisplayedEvent = this.state.events[lastDisplayedIndex]; - this._setReadMarker( + this.setReadMarker( lastDisplayedEvent.getId(), lastDisplayedEvent.getTs(), ); @@ -781,15 +839,14 @@ class TimelinePanel extends React.Component { this.sendReadReceipt(); }; - // advance the read marker past any events we sent ourselves. - _advanceReadMarkerPastMyEvents() { + private advanceReadMarkerPastMyEvents(): void { if (!this.props.manageReadMarkers) return; - // we call `_timelineWindow.getEvents()` rather than using + // we call `timelineWindow.getEvents()` rather than using // `this.state.liveEvents`, because React batches the update to the // latter, so it may not have been updated yet. - const events = this._timelineWindow.getEvents(); + const events = this.timelineWindow.getEvents(); // first find where the current RM is let i; @@ -814,51 +871,47 @@ class TimelinePanel extends React.Component { i--; const ev = events[i]; - this._setReadMarker(ev.getId(), ev.getTs()); + this.setReadMarker(ev.getId(), ev.getTs()); } /* jump down to the bottom of this room, where new events are arriving */ - jumpToLiveTimeline = () => { + public jumpToLiveTimeline = (): void => { // if we can't forward-paginate the existing timeline, then there // is no point reloading it - just jump straight to the bottom. // // Otherwise, reload the timeline rather than trying to paginate // through all of space-time. - if (this._timelineWindow.canPaginate(EventTimeline.FORWARDS)) { - this._loadTimeline(); + if (this.timelineWindow.canPaginate(EventTimeline.FORWARDS)) { + this.loadTimeline(); } else { - if (this._messagePanel.current) { - this._messagePanel.current.scrollToBottom(); - } + this.messagePanel.current?.scrollToBottom(); } }; - scrollToEventIfNeeded = (eventId) => { - if (this._messagePanel.current) { - this._messagePanel.current.scrollToEventIfNeeded(eventId); - } - } + public scrollToEventIfNeeded = (eventId: string): void => { + this.messagePanel.current?.scrollToEventIfNeeded(eventId); + }; /* scroll to show the read-up-to marker. We put it 1/3 of the way down * the container. */ - jumpToReadMarker = () => { + public jumpToReadMarker = (): void => { if (!this.props.manageReadMarkers) return; - if (!this._messagePanel.current) return; + if (!this.messagePanel.current) return; if (!this.state.readMarkerEventId) return; // we may not have loaded the event corresponding to the read-marker - // into the _timelineWindow. In that case, attempts to scroll to it + // into the timelineWindow. In that case, attempts to scroll to it // will fail. // // a quick way to figure out if we've loaded the relevant event is // simply to check if the messagepanel knows where the read-marker is. - const ret = this._messagePanel.current.getReadMarkerPosition(); + const ret = this.messagePanel.current.getReadMarkerPosition(); if (ret !== null) { // The messagepanel knows where the RM is, so we must have loaded // the relevant event. - this._messagePanel.current.scrollToEvent(this.state.readMarkerEventId, + this.messagePanel.current.scrollToEvent(this.state.readMarkerEventId, 0, 1/3); return; } @@ -866,15 +919,15 @@ class TimelinePanel extends React.Component { // Looks like we haven't loaded the event corresponding to the read-marker. // As with jumpToLiveTimeline, we want to reload the timeline around the // read-marker. - this._loadTimeline(this.state.readMarkerEventId, 0, 1/3); + this.loadTimeline(this.state.readMarkerEventId, 0, 1/3); }; /* update the read-up-to marker to match the read receipt */ - forgetReadMarker = () => { + public forgetReadMarker = (): void => { if (!this.props.manageReadMarkers) return; - const rmId = this._getCurrentReadReceipt(); + const rmId = this.getCurrentReadReceipt(); // see if we know the timestamp for the rr event const tl = this.props.timelineSet.getTimelineForEvent(rmId); @@ -886,28 +939,26 @@ class TimelinePanel extends React.Component { } } - this._setReadMarker(rmId, rmTs); + this.setReadMarker(rmId, rmTs); }; /* return true if the content is fully scrolled down and we are * at the end of the live timeline. */ - isAtEndOfLiveTimeline = () => { - return this._messagePanel.current - && this._messagePanel.current.isAtBottom() - && this._timelineWindow - && !this._timelineWindow.canPaginate(EventTimeline.FORWARDS); - } - + public isAtEndOfLiveTimeline = (): boolean => { + return this.messagePanel.current?.isAtBottom() + && this.timelineWindow + && !this.timelineWindow.canPaginate(EventTimeline.FORWARDS); + }; /* get the current scroll state. See ScrollPanel.getScrollState for * details. * * returns null if we are not mounted. */ - getScrollState = () => { - if (!this._messagePanel.current) { return null; } - return this._messagePanel.current.getScrollState(); + public getScrollState = (): IScrollState => { + if (!this.messagePanel.current) { return null; } + return this.messagePanel.current.getScrollState(); }; // returns one of: @@ -916,11 +967,11 @@ class TimelinePanel extends React.Component { // -1: read marker is above the window // 0: read marker is visible // +1: read marker is below the window - getReadMarkerPosition = () => { + public getReadMarkerPosition = (): number => { if (!this.props.manageReadMarkers) return null; - if (!this._messagePanel.current) return null; + if (!this.messagePanel.current) return null; - const ret = this._messagePanel.current.getReadMarkerPosition(); + const ret = this.messagePanel.current.getReadMarkerPosition(); if (ret !== null) { return ret; } @@ -939,7 +990,7 @@ class TimelinePanel extends React.Component { return null; }; - canJumpToReadMarker = () => { + public canJumpToReadMarker = (): boolean => { // 1. Do not show jump bar if neither the RM nor the RR are set. // 3. We want to show the bar if the read-marker is off the top of the screen. // 4. Also, if pos === null, the event might not be paginated - show the unread bar @@ -954,19 +1005,19 @@ class TimelinePanel extends React.Component { * * We pass it down to the scroll panel. */ - handleScrollKey = ev => { - if (!this._messagePanel.current) { return; } + public handleScrollKey = ev => { + if (!this.messagePanel.current) { return; } // jump to the live timeline on ctrl-end, rather than the end of the // timeline window. if (ev.ctrlKey && !ev.shiftKey && !ev.altKey && !ev.metaKey && ev.key === Key.END) { this.jumpToLiveTimeline(); } else { - this._messagePanel.current.handleScrollKey(ev); + this.messagePanel.current.handleScrollKey(ev); } }; - _initTimeline(props) { + private initTimeline(props: IProps): void { const initialEvent = props.eventId; const pixelOffset = props.eventPixelOffset; @@ -977,7 +1028,7 @@ class TimelinePanel extends React.Component { offsetBase = 0.5; } - return this._loadTimeline(initialEvent, pixelOffset, offsetBase); + return this.loadTimeline(initialEvent, pixelOffset, offsetBase); } /** @@ -993,34 +1044,32 @@ class TimelinePanel extends React.Component { * @param {number?} offsetBase the reference point for the pixelOffset. 0 * means the top of the container, 1 means the bottom, and fractional * values mean somewhere in the middle. If omitted, it defaults to 0. - * - * returns a promise which will resolve when the load completes. */ - _loadTimeline(eventId, pixelOffset, offsetBase) { - this._timelineWindow = new TimelineWindow( + private loadTimeline(eventId?: string, pixelOffset?: number, offsetBase?: number): void { + this.timelineWindow = new TimelineWindow( MatrixClientPeg.get(), this.props.timelineSet, - {windowLimit: this.props.timelineCap}); + { windowLimit: this.props.timelineCap }); const onLoaded = () => { // clear the timeline min-height when // (re)loading the timeline - if (this._messagePanel.current) { - this._messagePanel.current.onTimelineReset(); + if (this.messagePanel.current) { + this.messagePanel.current.onTimelineReset(); } - this._reloadEvents(); + this.reloadEvents(); // If we switched away from the room while there were pending // outgoing events, the read-marker will be before those events. // We need to skip over any which have subsequently been sent. - this._advanceReadMarkerPastMyEvents(); + this.advanceReadMarkerPastMyEvents(); this.setState({ - canBackPaginate: this._timelineWindow.canPaginate(EventTimeline.BACKWARDS), - canForwardPaginate: this._timelineWindow.canPaginate(EventTimeline.FORWARDS), + canBackPaginate: this.timelineWindow.canPaginate(EventTimeline.BACKWARDS), + canForwardPaginate: this.timelineWindow.canPaginate(EventTimeline.FORWARDS), timelineLoading: false, }, () => { // initialise the scroll state of the message panel - if (!this._messagePanel.current) { + if (!this.messagePanel.current) { // this shouldn't happen - we know we're mounted because // we're in a setState callback, and we know // timelineLoading is now false, so render() should have @@ -1030,10 +1079,10 @@ class TimelinePanel extends React.Component { return; } if (eventId) { - this._messagePanel.current.scrollToEvent(eventId, pixelOffset, + this.messagePanel.current.scrollToEvent(eventId, pixelOffset, offsetBase); } else { - this._messagePanel.current.scrollToBottom(); + this.messagePanel.current.scrollToBottom(); } if (this.props.sendReadReceiptOnLoad) { @@ -1095,10 +1144,10 @@ class TimelinePanel extends React.Component { if (timeline) { // This is a hot-path optimization by skipping a promise tick // by repeating a no-op sync branch in TimelineSet.getTimelineForEvent & MatrixClient.getEventTimeline - this._timelineWindow.load(eventId, INITIAL_SIZE); // in this branch this method will happen in sync time + this.timelineWindow.load(eventId, INITIAL_SIZE); // in this branch this method will happen in sync time onLoaded(); } else { - const prom = this._timelineWindow.load(eventId, INITIAL_SIZE); + const prom = this.timelineWindow.load(eventId, INITIAL_SIZE); this.setState({ events: [], liveEvents: [], @@ -1113,17 +1162,17 @@ class TimelinePanel extends React.Component { // handle the completion of a timeline load or localEchoUpdate, by // reloading the events from the timelinewindow and pending event list into // the state. - _reloadEvents() { + private reloadEvents(): void { // we might have switched rooms since the load started - just bin // the results if so. if (this.unmounted) return; - this.setState(this._getEvents()); + this.setState(this.getEvents()); } // get the list of events from the timeline window and the pending event list - _getEvents() { - const events = this._timelineWindow.getEvents(); + private getEvents(): Pick { + const events: MatrixEvent[] = this.timelineWindow.getEvents(); // `arrayFastClone` performs a shallow copy of the array // we want the last event to be decrypted first but displayed last @@ -1135,14 +1184,14 @@ class TimelinePanel extends React.Component { client.decryptEventIfNeeded(event); }); - const firstVisibleEventIndex = this._checkForPreJoinUISI(events); + const firstVisibleEventIndex = this.checkForPreJoinUISI(events); // Hold onto the live events separately. The read receipt and read marker // should use this list, so that they don't advance into pending events. const liveEvents = [...events]; // if we're at the end of the live timeline, append the pending events - if (!this._timelineWindow.canPaginate(EventTimeline.FORWARDS)) { + if (!this.timelineWindow.canPaginate(EventTimeline.FORWARDS)) { events.push(...this.props.timelineSet.getPendingEvents()); } @@ -1163,7 +1212,7 @@ class TimelinePanel extends React.Component { * undecryptable event that was sent while the user was not in the room. If no * such events were found, then it returns 0. */ - _checkForPreJoinUISI(events) { + private checkForPreJoinUISI(events: MatrixEvent[]): number { const room = this.props.timelineSet.room; if (events.length === 0 || !room || @@ -1227,7 +1276,7 @@ class TimelinePanel extends React.Component { return 0; } - _indexForEventId(evId) { + private indexForEventId(evId: string): number | null { for (let i = 0; i < this.state.events.length; ++i) { if (evId == this.state.events[i].getId()) { return i; @@ -1236,15 +1285,14 @@ class TimelinePanel extends React.Component { return null; } - _getLastDisplayedEventIndex(opts) { - opts = opts || {}; + private getLastDisplayedEventIndex(opts: IEventIndexOpts = {}): number | null { const ignoreOwn = opts.ignoreOwn || false; const allowPartial = opts.allowPartial || false; - const messagePanel = this._messagePanel.current; + const messagePanel = this.messagePanel.current; if (!messagePanel) return null; - const messagePanelNode = ReactDOM.findDOMNode(messagePanel); + const messagePanelNode = ReactDOM.findDOMNode(messagePanel) as HTMLElement; if (!messagePanelNode) return null; // sometimes this happens for fresh rooms/post-sync const wrapperRect = messagePanelNode.getBoundingClientRect(); const myUserId = MatrixClientPeg.get().credentials.userId; @@ -1321,7 +1369,7 @@ class TimelinePanel extends React.Component { * SDK. * @return {String} the event ID */ - _getCurrentReadReceipt(ignoreSynthesized) { + private getCurrentReadReceipt(ignoreSynthesized = false): string { const client = MatrixClientPeg.get(); // the client can be null on logout if (client == null) { @@ -1332,7 +1380,7 @@ class TimelinePanel extends React.Component { return this.props.timelineSet.room.getEventReadUpTo(myUserId, ignoreSynthesized); } - _setReadMarker(eventId, eventTs, inhibitSetState) { + private setReadMarker(eventId: string, eventTs: number, inhibitSetState = false): void { const roomId = this.props.timelineSet.room.roomId; // don't update the state (and cause a re-render) if there is @@ -1357,7 +1405,7 @@ class TimelinePanel extends React.Component { }, this.props.onReadMarkerUpdated); } - _shouldPaginate() { + private shouldPaginate(): boolean { // don't try to paginate while events in the timeline are // still being decrypted. We don't render events while they're // being decrypted, so they don't take up space in the timeline. @@ -1368,12 +1416,9 @@ class TimelinePanel extends React.Component { }); } - getRelationsForEvent = (...args) => this.props.timelineSet.getRelationsForEvent(...args); + private getRelationsForEvent = (...args) => this.props.timelineSet.getRelationsForEvent(...args); render() { - const MessagePanel = sdk.getComponent("structures.MessagePanel"); - const Loader = sdk.getComponent("elements.Spinner"); - // just show a spinner while the timeline loads. // // put it in a div of the right class (mx_RoomView_messagePanel) so @@ -1388,7 +1433,7 @@ class TimelinePanel extends React.Component { if (this.state.timelineLoading) { return (
    - +
    ); } @@ -1409,7 +1454,7 @@ class TimelinePanel extends React.Component { // forwards, otherwise if somebody hits the bottom of the loaded // events when viewing historical messages, we get stuck in a loop // of paginating our way through the entire history of the room. - const stickyBottom = !this._timelineWindow.canPaginate(EventTimeline.FORWARDS); + const stickyBottom = !this.timelineWindow.canPaginate(EventTimeline.FORWARDS); // If the state is PREPARED or CATCHUP, we're still waiting for the js-sdk to sync with // the HS and fetch the latest events, so we are effectively forward paginating. @@ -1422,7 +1467,7 @@ class TimelinePanel extends React.Component { : this.state.events; return (
    - ) + ); } else if (hostSignupConfig) { if (hostSignupConfig && hostSignupConfig.url) { // If hostSignup.domains is set to a non-empty array, only show @@ -509,7 +509,7 @@ export default class UserMenu extends React.Component { /> - ) + ); } else if (MatrixClientPeg.get().isGuest()) { primaryOptionList = ( diff --git a/src/components/structures/UserView.js b/src/components/structures/UserView.js index 6b472783bb..eb839be7be 100644 --- a/src/components/structures/UserView.js +++ b/src/components/structures/UserView.js @@ -17,14 +17,14 @@ limitations under the License. import React from "react"; import PropTypes from "prop-types"; -import {MatrixClientPeg} from "../../MatrixClientPeg"; +import { MatrixClientPeg } from "../../MatrixClientPeg"; import * as sdk from "../../index"; import Modal from '../../Modal'; import { _t } from '../../languageHandler'; import HomePage from "./HomePage"; -import {replaceableComponent} from "../../utils/replaceableComponent"; -import {MatrixEvent} from "matrix-js-sdk/src/models/event"; -import {RoomMember} from "matrix-js-sdk/src/models/room-member"; +import { replaceableComponent } from "../../utils/replaceableComponent"; +import { MatrixEvent } from "matrix-js-sdk/src/models/event"; +import { RoomMember } from "matrix-js-sdk/src/models/room-member"; @replaceableComponent("structures.UserView") export default class UserView extends React.Component { @@ -56,7 +56,7 @@ export default class UserView extends React.Component { async _loadProfileInfo() { const cli = MatrixClientPeg.get(); - this.setState({loading: true}); + this.setState({ loading: true }); let profileInfo; try { profileInfo = await cli.getProfileInfo(this.props.userId); @@ -66,13 +66,13 @@ export default class UserView extends React.Component { title: _t('Could not load user profile'), description: ((err && err.message) ? err.message : _t("Operation failed")), }); - this.setState({loading: false}); + this.setState({ loading: false }); return; } - const fakeEvent = new MatrixEvent({type: "m.room.member", content: profileInfo}); + const fakeEvent = new MatrixEvent({ type: "m.room.member", content: profileInfo }); const member = new RoomMember(null, this.props.userId); member.setMembershipEvent(fakeEvent); - this.setState({member, loading: false}); + this.setState({ member, loading: false }); } render() { diff --git a/src/components/structures/auth/CompleteSecurity.js b/src/components/structures/auth/CompleteSecurity.js index 654dd9b6c8..d691f6034b 100644 --- a/src/components/structures/auth/CompleteSecurity.js +++ b/src/components/structures/auth/CompleteSecurity.js @@ -20,7 +20,7 @@ import { _t } from '../../../languageHandler'; import * as sdk from '../../../index'; import { SetupEncryptionStore, Phase } from '../../../stores/SetupEncryptionStore'; import SetupEncryptionBody from "./SetupEncryptionBody"; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; @replaceableComponent("structures.auth.CompleteSecurity") export default class CompleteSecurity extends React.Component { @@ -33,12 +33,12 @@ export default class CompleteSecurity extends React.Component { const store = SetupEncryptionStore.sharedInstance(); store.on("update", this._onStoreUpdate); store.start(); - this.state = {phase: store.phase}; + this.state = { phase: store.phase }; } _onStoreUpdate = () => { const store = SetupEncryptionStore.sharedInstance(); - this.setState({phase: store.phase}); + this.setState({ phase: store.phase }); }; componentWillUnmount() { @@ -50,7 +50,7 @@ export default class CompleteSecurity extends React.Component { render() { const AuthPage = sdk.getComponent("auth.AuthPage"); const CompleteSecurityBody = sdk.getComponent("auth.CompleteSecurityBody"); - const {phase} = this.state; + const { phase } = this.state; let icon; let title; diff --git a/src/components/structures/auth/E2eSetup.js b/src/components/structures/auth/E2eSetup.js index 4e51ae828c..9b627449bc 100644 --- a/src/components/structures/auth/E2eSetup.js +++ b/src/components/structures/auth/E2eSetup.js @@ -19,7 +19,7 @@ import PropTypes from 'prop-types'; import AuthPage from '../../views/auth/AuthPage'; import CompleteSecurityBody from '../../views/auth/CompleteSecurityBody'; import CreateCrossSigningDialog from '../../views/dialogs/security/CreateCrossSigningDialog'; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; @replaceableComponent("structures.auth.E2eSetup") export default class E2eSetup extends React.Component { diff --git a/src/components/structures/auth/ForgotPassword.js b/src/components/structures/auth/ForgotPassword.js index 6188fdb5e4..9f2ac9deed 100644 --- a/src/components/structures/auth/ForgotPassword.js +++ b/src/components/structures/auth/ForgotPassword.js @@ -22,13 +22,13 @@ import { _t, _td } from '../../../languageHandler'; import * as sdk from '../../../index'; import Modal from "../../../Modal"; import PasswordReset from "../../../PasswordReset"; -import AutoDiscoveryUtils, {ValidatedServerConfig} from "../../../utils/AutoDiscoveryUtils"; +import AutoDiscoveryUtils, { ValidatedServerConfig } from "../../../utils/AutoDiscoveryUtils"; import classNames from 'classnames'; import AuthPage from "../../views/auth/AuthPage"; import CountlyAnalytics from "../../../CountlyAnalytics"; import ServerPicker from "../../views/elements/ServerPicker"; import PassphraseField from '../../views/auth/PassphraseField'; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; import { PASSWORD_MIN_SCORE } from '../../views/auth/RegistrationForm'; // Phases diff --git a/src/components/structures/auth/Login.tsx b/src/components/structures/auth/Login.tsx index d34582b0c3..61d3759dee 100644 --- a/src/components/structures/auth/Login.tsx +++ b/src/components/structures/auth/Login.tsx @@ -14,28 +14,28 @@ See the License for the specific language governing permissions and limitations under the License. */ -import React, {ReactNode} from 'react'; -import {MatrixError} from "matrix-js-sdk/src/http-api"; +import React, { ReactNode } from 'react'; +import { MatrixError } from "matrix-js-sdk/src/http-api"; -import {_t, _td} from '../../../languageHandler'; +import { _t, _td } from '../../../languageHandler'; import * as sdk from '../../../index'; -import Login, {ISSOFlow, LoginFlow} from '../../../Login'; +import Login, { ISSOFlow, LoginFlow } from '../../../Login'; import SdkConfig from '../../../SdkConfig'; import { messageForResourceLimitError } from '../../../utils/ErrorUtils'; -import AutoDiscoveryUtils, {ValidatedServerConfig} from "../../../utils/AutoDiscoveryUtils"; +import AutoDiscoveryUtils, { ValidatedServerConfig } from "../../../utils/AutoDiscoveryUtils"; import classNames from "classnames"; import AuthPage from "../../views/auth/AuthPage"; import PlatformPeg from '../../../PlatformPeg'; import SettingsStore from "../../../settings/SettingsStore"; -import {UIFeature} from "../../../settings/UIFeature"; +import { UIFeature } from "../../../settings/UIFeature"; import CountlyAnalytics from "../../../CountlyAnalytics"; -import {IMatrixClientCreds} from "../../../MatrixClientPeg"; +import { IMatrixClientCreds } from "../../../MatrixClientPeg"; import PasswordLogin from "../../views/auth/PasswordLogin"; import InlineSpinner from "../../views/elements/InlineSpinner"; import Spinner from "../../views/elements/Spinner"; import SSOButtons from "../../views/elements/SSOButtons"; import ServerPicker from "../../views/elements/ServerPicker"; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; // 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. @@ -166,7 +166,7 @@ export default class LoginComponent extends React.PureComponent onPasswordLogin = async (username, phoneCountry, phoneNumber, password) => { if (!this.state.serverIsAlive) { - this.setState({busy: true}); + this.setState({ busy: true }); // Do a quick liveliness check on the URLs let aliveAgain = true; try { @@ -174,7 +174,7 @@ export default class LoginComponent extends React.PureComponent this.props.serverConfig.hsUrl, this.props.serverConfig.isUrl, ); - this.setState({serverIsAlive: true, errorText: ""}); + this.setState({ serverIsAlive: true, errorText: "" }); } catch (e) { const componentState = AutoDiscoveryUtils.authComponentStateForError(e); this.setState({ @@ -201,7 +201,7 @@ export default class LoginComponent extends React.PureComponent this.loginLogic.loginViaPassword( username, phoneCountry, phoneNumber, password, ).then((data) => { - this.setState({serverIsAlive: true}); // it must be, we logged in. + this.setState({ serverIsAlive: true }); // it must be, we logged in. this.props.onLoggedIn(data, password); }, (error) => { if (this.unmounted) { @@ -252,7 +252,7 @@ export default class LoginComponent extends React.PureComponent
    {_t( 'Please note you are logging into the %(hs)s server, not matrix.org.', - {hs: this.props.serverConfig.hsName}, + { hs: this.props.serverConfig.hsName }, )}
    @@ -363,7 +363,7 @@ export default class LoginComponent extends React.PureComponent } }; - private async initLoginLogic({hsUrl, isUrl}: ValidatedServerConfig) { + private async initLoginLogic({ hsUrl, isUrl }: ValidatedServerConfig) { let isDefaultServer = false; if (this.props.serverConfig.isDefault && hsUrl === this.props.serverConfig.hsUrl @@ -501,9 +501,9 @@ export default class LoginComponent extends React.PureComponent return { flows.map(flow => { const stepRenderer = this.stepRendererMap[flow.type]; - return { stepRenderer() } + return { stepRenderer() }; }) } - + ; } private renderPasswordStep = () => { diff --git a/src/components/structures/auth/Registration.tsx b/src/components/structures/auth/Registration.tsx index 3a4be6f0d6..f27bed2cc3 100644 --- a/src/components/structures/auth/Registration.tsx +++ b/src/components/structures/auth/Registration.tsx @@ -14,23 +14,23 @@ See the License for the specific language governing permissions and limitations under the License. */ -import {createClient} from 'matrix-js-sdk/src/matrix'; -import React, {ReactNode} from 'react'; -import {MatrixClient} from "matrix-js-sdk/src/client"; +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"; +import AutoDiscoveryUtils, { ValidatedServerConfig } from "../../../utils/AutoDiscoveryUtils"; import classNames from "classnames"; import * as Lifecycle from '../../../Lifecycle'; -import {MatrixClientPeg} from "../../../MatrixClientPeg"; +import { MatrixClientPeg } from "../../../MatrixClientPeg"; import AuthPage from "../../views/auth/AuthPage"; -import Login, {ISSOFlow} from "../../../Login"; +import Login, { ISSOFlow } from "../../../Login"; import dis from "../../../dispatcher/dispatcher"; import SSOButtons from "../../views/elements/SSOButtons"; import ServerPicker from '../../views/elements/ServerPicker'; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; interface IProps { serverConfig: ValidatedServerConfig; @@ -131,7 +131,7 @@ export default class Registration extends React.Component { serverDeadError: "", }; - const {hsUrl, isUrl} = this.props.serverConfig; + const { hsUrl, isUrl } = this.props.serverConfig; this.loginLogic = new Login(hsUrl, isUrl, null, { defaultDeviceDisplayName: "Element login check", // We shouldn't ever be used }); @@ -180,7 +180,7 @@ export default class Registration extends React.Component { } } - const {hsUrl, isUrl} = serverConfig; + const { hsUrl, isUrl } = serverConfig; const cli = createClient({ baseUrl: hsUrl, idBaseUrl: isUrl, @@ -230,7 +230,7 @@ export default class Registration extends React.Component { // the user off to the login page to figure their account out. if (ssoFlow) { // Redirect to login page - server probably expects SSO only - dis.dispatch({action: 'start_login'}); + dis.dispatch({ action: 'start_login' }); } else { this.setState({ serverErrorIsFatal: true, // fatal because user cannot continue on this server @@ -267,7 +267,7 @@ export default class Registration extends React.Component { session_id: sessionId, }), ); - } + }; private onUIAuthFinished = async (success: boolean, response: any) => { if (!success) { @@ -432,7 +432,7 @@ export default class Registration extends React.Component { private onLoginClickWithCheck = async ev => { ev.preventDefault(); - const sessionLoaded = await Lifecycle.loadSession({ignoreGuest: true}); + const sessionLoaded = await Lifecycle.loadSession({ ignoreGuest: true }); if (!sessionLoaded) { // ok fine, there's still no session: really go to the login page this.props.onLoginClick(); @@ -487,7 +487,13 @@ export default class Registration extends React.Component { fragmentAfterLogin={this.props.fragmentAfterLogin} />

    - { _t("%(ssoButtons)s Or %(usernamePassword)s", { ssoButtons: "", usernamePassword: ""}).trim() } + {_t( + "%(ssoButtons)s Or %(usernamePassword)s", + { + ssoButtons: "", + usernamePassword: "", + }, + ).trim()}

    ; } @@ -563,7 +569,7 @@ export default class Registration extends React.Component {

    { const sessionLoaded = await this.onLoginClickWithCheck(event); if (sessionLoaded) { - dis.dispatch({action: "view_welcome_page"}); + dis.dispatch({ action: "view_welcome_page" }); } }}> {_t("Continue with previous account")} diff --git a/src/components/structures/auth/SetupEncryptionBody.js b/src/components/structures/auth/SetupEncryptionBody.js index 90137e084c..f0798b6d1a 100644 --- a/src/components/structures/auth/SetupEncryptionBody.js +++ b/src/components/structures/auth/SetupEncryptionBody.js @@ -22,7 +22,7 @@ import Modal from '../../../Modal'; import VerificationRequestDialog from '../../views/dialogs/VerificationRequestDialog'; import * as sdk from '../../../index'; import { SetupEncryptionStore, Phase } from '../../../stores/SetupEncryptionStore'; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; function keyHasPassphrase(keyInfo) { return ( diff --git a/src/components/structures/auth/SoftLogout.tsx b/src/components/structures/auth/SoftLogout.tsx index fa9207efdd..7fb60a7b5d 100644 --- a/src/components/structures/auth/SoftLogout.tsx +++ b/src/components/structures/auth/SoftLogout.tsx @@ -15,17 +15,17 @@ limitations under the License. */ import React from 'react'; -import {_t} from '../../../languageHandler'; +import { _t } from '../../../languageHandler'; import * as sdk from '../../../index'; import dis from '../../../dispatcher/dispatcher'; import * as Lifecycle from '../../../Lifecycle'; import Modal from '../../../Modal'; -import {MatrixClientPeg} from "../../../MatrixClientPeg"; -import {ISSOFlow, LoginFlow, sendLoginRequest} from "../../../Login"; +import { MatrixClientPeg } from "../../../MatrixClientPeg"; +import { ISSOFlow, LoginFlow, sendLoginRequest } from "../../../Login"; import AuthPage from "../../views/auth/AuthPage"; -import {SSO_HOMESERVER_URL_KEY, SSO_ID_SERVER_URL_KEY} from "../../../BasePlatform"; +import { SSO_HOMESERVER_URL_KEY, SSO_ID_SERVER_URL_KEY } from "../../../BasePlatform"; import SSOButtons from "../../views/elements/SSOButtons"; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; const LOGIN_VIEW = { LOADING: 1, @@ -79,7 +79,7 @@ export default class SoftLogout extends React.Component { componentDidMount(): void { // We've ended up here when we don't need to - navigate to login if (!Lifecycle.isSoftLogout()) { - dis.dispatch({action: "start_login"}); + dis.dispatch({ action: "start_login" }); return; } @@ -109,7 +109,7 @@ export default class SoftLogout extends React.Component { const queryParams = this.props.realQueryParams; const hasAllParams = queryParams && queryParams['loginToken']; if (hasAllParams) { - this.setState({loginView: LOGIN_VIEW.LOADING}); + this.setState({ loginView: LOGIN_VIEW.LOADING }); this.trySsoLogin(); return; } @@ -125,18 +125,18 @@ export default class SoftLogout extends React.Component { } onPasswordChange = (ev) => { - this.setState({password: ev.target.value}); + this.setState({ password: ev.target.value }); }; onForgotPassword = () => { - dis.dispatch({action: 'start_password_recovery'}); + dis.dispatch({ action: 'start_password_recovery' }); }; onPasswordLogin = async (ev) => { ev.preventDefault(); ev.stopPropagation(); - this.setState({busy: true}); + this.setState({ busy: true }); const hsUrl = MatrixClientPeg.get().getHomeserverUrl(); const isUrl = MatrixClientPeg.get().getIdentityServerUrl(); @@ -168,12 +168,12 @@ export default class SoftLogout extends React.Component { Lifecycle.hydrateSession(credentials).catch((e) => { console.error(e); - this.setState({busy: false, errorText: _t("Failed to re-authenticate")}); + this.setState({ busy: false, errorText: _t("Failed to re-authenticate") }); }); }; async trySsoLogin() { - this.setState({busy: true}); + this.setState({ busy: true }); const hsUrl = localStorage.getItem(SSO_HOMESERVER_URL_KEY); const isUrl = localStorage.getItem(SSO_ID_SERVER_URL_KEY) || MatrixClientPeg.get().getIdentityServerUrl(); @@ -188,7 +188,7 @@ export default class SoftLogout extends React.Component { credentials = await sendLoginRequest(hsUrl, isUrl, loginType, loginParams); } catch (e) { console.error(e); - this.setState({busy: false, loginView: LOGIN_VIEW.UNSUPPORTED}); + this.setState({ busy: false, loginView: LOGIN_VIEW.UNSUPPORTED }); return; } @@ -196,7 +196,7 @@ export default class SoftLogout extends React.Component { if (this.props.onTokenLoginCompleted) this.props.onTokenLoginCompleted(); }).catch((e) => { console.error(e); - this.setState({busy: false, loginView: LOGIN_VIEW.UNSUPPORTED}); + this.setState({ busy: false, loginView: LOGIN_VIEW.UNSUPPORTED }); }); } diff --git a/src/components/views/auth/AuthBody.js b/src/components/views/auth/AuthBody.js index 2cb72b5e1d..abe7fd2fd3 100644 --- a/src/components/views/auth/AuthBody.js +++ b/src/components/views/auth/AuthBody.js @@ -15,7 +15,7 @@ limitations under the License. */ import React from 'react'; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; @replaceableComponent("views.auth.AuthBody") export default class AuthBody extends React.PureComponent { diff --git a/src/components/views/auth/AuthFooter.js b/src/components/views/auth/AuthFooter.js index f167e16283..e81d2cd969 100644 --- a/src/components/views/auth/AuthFooter.js +++ b/src/components/views/auth/AuthFooter.js @@ -18,7 +18,7 @@ limitations under the License. import { _t } from '../../../languageHandler'; import React from 'react'; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; @replaceableComponent("views.auth.AuthFooter") export default class AuthFooter extends React.Component { diff --git a/src/components/views/auth/AuthHeader.js b/src/components/views/auth/AuthHeader.js index 323299b3a8..d9bd81adcb 100644 --- a/src/components/views/auth/AuthHeader.js +++ b/src/components/views/auth/AuthHeader.js @@ -18,7 +18,7 @@ limitations under the License. import React from 'react'; import PropTypes from 'prop-types'; import * as sdk from '../../../index'; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; @replaceableComponent("views.auth.AuthHeader") export default class AuthHeader extends React.Component { diff --git a/src/components/views/auth/AuthHeaderLogo.js b/src/components/views/auth/AuthHeaderLogo.js index b4e04799bb..0adf18dc1c 100644 --- a/src/components/views/auth/AuthHeaderLogo.js +++ b/src/components/views/auth/AuthHeaderLogo.js @@ -15,7 +15,7 @@ limitations under the License. */ import React from 'react'; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; @replaceableComponent("views.auth.AuthHeaderLogo") export default class AuthHeaderLogo extends React.PureComponent { diff --git a/src/components/views/auth/AuthPage.js b/src/components/views/auth/AuthPage.js index 82f7270121..6ba47e5288 100644 --- a/src/components/views/auth/AuthPage.js +++ b/src/components/views/auth/AuthPage.js @@ -18,7 +18,7 @@ limitations under the License. import React from 'react'; import * as sdk from '../../../index'; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; @replaceableComponent("views.auth.AuthPage") export default class AuthPage extends React.PureComponent { diff --git a/src/components/views/auth/CaptchaForm.js b/src/components/views/auth/CaptchaForm.js index 50de24d403..bea4f89f53 100644 --- a/src/components/views/auth/CaptchaForm.js +++ b/src/components/views/auth/CaptchaForm.js @@ -14,11 +14,11 @@ See the License for the specific language governing permissions and limitations under the License. */ -import React, {createRef} from 'react'; +import React, { createRef } from 'react'; import PropTypes from 'prop-types'; import { _t } from '../../../languageHandler'; import CountlyAnalytics from "../../../CountlyAnalytics"; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; const DIV_ID = 'mx_recaptcha'; diff --git a/src/components/views/auth/CompleteSecurityBody.js b/src/components/views/auth/CompleteSecurityBody.js index 6647bb1200..745d7abbf2 100644 --- a/src/components/views/auth/CompleteSecurityBody.js +++ b/src/components/views/auth/CompleteSecurityBody.js @@ -15,7 +15,7 @@ limitations under the License. */ import React from 'react'; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; @replaceableComponent("views.auth.CompleteSecurityBody") export default class CompleteSecurityBody extends React.PureComponent { diff --git a/src/components/views/auth/CountryDropdown.js b/src/components/views/auth/CountryDropdown.js index e21f112865..cbc19e0f8d 100644 --- a/src/components/views/auth/CountryDropdown.js +++ b/src/components/views/auth/CountryDropdown.js @@ -19,10 +19,10 @@ import PropTypes from 'prop-types'; import * as sdk from '../../../index'; -import {COUNTRIES, getEmojiFlag} from '../../../phonenumber'; +import { COUNTRIES, getEmojiFlag } from '../../../phonenumber'; import SdkConfig from "../../../SdkConfig"; import { _t } from "../../../languageHandler"; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; const COUNTRIES_BY_ISO2 = {}; for (const c of COUNTRIES) { diff --git a/src/components/views/auth/InteractiveAuthEntryComponents.tsx b/src/components/views/auth/InteractiveAuthEntryComponents.tsx index e819e1e59c..e002eb5717 100644 --- a/src/components/views/auth/InteractiveAuthEntryComponents.tsx +++ b/src/components/views/auth/InteractiveAuthEntryComponents.tsx @@ -24,7 +24,7 @@ import SettingsStore from "../../../settings/SettingsStore"; import AccessibleButton from "../elements/AccessibleButton"; import Spinner from "../elements/Spinner"; import CountlyAnalytics from "../../../CountlyAnalytics"; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; import { LocalisedPolicy, Policies } from '../../../Terms'; /* This file contains a collection of components which are used by the @@ -354,7 +354,6 @@ export class TermsAuthEntry extends React.Component { @@ -382,10 +381,10 @@ export class TermsAuthEntry extends React.Component { this.props.fail(e); }).finally(() => { - this.setState({requestingToken: false}); + this.setState({ requestingToken: false }); }); } @@ -710,7 +709,7 @@ export class SSOAuthEntry extends React.Component; const LanguageDropdown = sdk.getComponent('views.elements.LanguageDropdown'); diff --git a/src/components/views/auth/PassphraseField.tsx b/src/components/views/auth/PassphraseField.tsx index 274c244b2a..bab7e59d2a 100644 --- a/src/components/views/auth/PassphraseField.tsx +++ b/src/components/views/auth/PassphraseField.tsx @@ -14,15 +14,15 @@ See the License for the specific language governing permissions and limitations under the License. */ -import React, {PureComponent, RefCallback, RefObject} from "react"; +import React, { PureComponent, RefCallback, RefObject } from "react"; import classNames from "classnames"; import zxcvbn from "zxcvbn"; import SdkConfig from "../../../SdkConfig"; -import withValidation, {IFieldState, IValidationResult} from "../elements/Validation"; -import {_t, _td} from "../../../languageHandler"; -import Field, {IInputProps} from "../elements/Field"; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import withValidation, { IFieldState, IValidationResult } from "../elements/Validation"; +import { _t, _td } from "../../../languageHandler"; +import Field, { IInputProps } from "../elements/Field"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; interface IProps extends Omit { autoFocus?: boolean; diff --git a/src/components/views/auth/PasswordLogin.tsx b/src/components/views/auth/PasswordLogin.tsx index 2a42804a61..12f55a112c 100644 --- a/src/components/views/auth/PasswordLogin.tsx +++ b/src/components/views/auth/PasswordLogin.tsx @@ -19,14 +19,14 @@ import classNames from 'classnames'; import { _t } from '../../../languageHandler'; import SdkConfig from '../../../SdkConfig'; -import {ValidatedServerConfig} from "../../../utils/AutoDiscoveryUtils"; +import { ValidatedServerConfig } from "../../../utils/AutoDiscoveryUtils"; import AccessibleButton from "../elements/AccessibleButton"; import CountlyAnalytics from "../../../CountlyAnalytics"; import withValidation from "../elements/Validation"; import * as Email from "../../../email"; import Field from "../elements/Field"; import CountryDropdown from "./CountryDropdown"; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; // For validating phone numbers without country codes const PHONE_NUMBER_REGEX = /^[0-9()\-\s]*$/; @@ -166,7 +166,7 @@ export default class PasswordLogin extends React.PureComponent { }; private onPasswordChanged = ev => { - this.setState({password: ev.target.value}); + this.setState({ password: ev.target.value }); }; private async verifyFieldsBeforeSubmit() { @@ -322,7 +322,7 @@ export default class PasswordLogin extends React.PureComponent { const result = await this.validatePasswordRules(fieldState); this.markFieldValid(LoginField.Password, result.valid); return result; - } + }; private renderLoginField(loginType: IState["loginType"], autoFocus: boolean) { const classes = { diff --git a/src/components/views/auth/RegistrationForm.tsx b/src/components/views/auth/RegistrationForm.tsx index 8f0a293a3c..be6e29a493 100644 --- a/src/components/views/auth/RegistrationForm.tsx +++ b/src/components/views/auth/RegistrationForm.tsx @@ -25,12 +25,12 @@ import { _t } from '../../../languageHandler'; import SdkConfig from '../../../SdkConfig'; import { SAFE_LOCALPART_REGEX } from '../../../Registration'; import withValidation from '../elements/Validation'; -import {ValidatedServerConfig} from "../../../utils/AutoDiscoveryUtils"; +import { ValidatedServerConfig } from "../../../utils/AutoDiscoveryUtils"; import PassphraseField from "./PassphraseField"; import CountlyAnalytics from "../../../CountlyAnalytics"; import Field from '../elements/Field'; import RegistrationEmailPromptDialog from '../dialogs/RegistrationEmailPromptDialog'; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; enum RegistrationField { Email = "field_email", diff --git a/src/components/views/auth/Welcome.js b/src/components/views/auth/Welcome.js index fca66fcf9b..e3f7a601f2 100644 --- a/src/components/views/auth/Welcome.js +++ b/src/components/views/auth/Welcome.js @@ -20,11 +20,11 @@ import classNames from "classnames"; import * as sdk from '../../../index'; import SdkConfig from '../../../SdkConfig'; import AuthPage from "./AuthPage"; -import {_td} from "../../../languageHandler"; +import { _td } from "../../../languageHandler"; import SettingsStore from "../../../settings/SettingsStore"; -import {UIFeature} from "../../../settings/UIFeature"; +import { UIFeature } from "../../../settings/UIFeature"; import CountlyAnalytics from "../../../CountlyAnalytics"; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; // translatable strings for Welcome pages _td("Sign in with SSO"); diff --git a/src/components/views/avatars/BaseAvatar.tsx b/src/components/views/avatars/BaseAvatar.tsx index f98f8c88a1..87cdbe7512 100644 --- a/src/components/views/avatars/BaseAvatar.tsx +++ b/src/components/views/avatars/BaseAvatar.tsx @@ -64,7 +64,7 @@ const calculateUrls = (url, urls, lowBandwidth) => { return Array.from(new Set(_urls)); }; -const useImageUrl = ({url, urls}): [string, () => void] => { +const useImageUrl = ({ url, urls }): [string, () => void] => { // Since this is a hot code path and the settings store can be slow, we // use the cached lowBandwidth value from the room context if it exists const roomContext = useContext(RoomContext); @@ -115,7 +115,7 @@ const BaseAvatar = (props: IProps) => { ...otherProps } = props; - const [imageUrl, onError] = useImageUrl({url, urls}); + const [imageUrl, onError] = useImageUrl({ url, urls }); if (!imageUrl && defaultToInitialLetter) { const initialLetter = AvatarLogic.getInitialLetter(name); diff --git a/src/components/views/avatars/DecoratedRoomAvatar.tsx b/src/components/views/avatars/DecoratedRoomAvatar.tsx index dbd9f4e452..4f31d3aca5 100644 --- a/src/components/views/avatars/DecoratedRoomAvatar.tsx +++ b/src/components/views/avatars/DecoratedRoomAvatar.tsx @@ -24,12 +24,12 @@ import RoomAvatar from "./RoomAvatar"; import NotificationBadge from '../rooms/NotificationBadge'; import { RoomNotificationStateStore } from "../../../stores/notifications/RoomNotificationStateStore"; import { NotificationState } from "../../../stores/notifications/NotificationState"; -import {isPresenceEnabled} from "../../../utils/presence"; -import {MatrixClientPeg} from "../../../MatrixClientPeg"; -import {_t} from "../../../languageHandler"; +import { isPresenceEnabled } from "../../../utils/presence"; +import { MatrixClientPeg } from "../../../MatrixClientPeg"; +import { _t } from "../../../languageHandler"; import TextWithTooltip from "../elements/TextWithTooltip"; import DMRoomMap from "../../../utils/DMRoomMap"; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; interface IProps { room: Room; @@ -121,7 +121,7 @@ export default class DecoratedRoomAvatar extends React.PureComponent { // 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 @typescript-eslint/no-unused-vars: ["error", { "ignoreRestSiblings": true }] */ - const {groupId, groupAvatarUrl, groupName, ...otherProps} = this.props; + const { groupId, groupAvatarUrl, groupName, ...otherProps } = this.props; return ( { } render() { - let {member, fallbackUserId, onClick, viewUserOnClick, ...otherProps} = this.props; + let { member, fallbackUserId, onClick, viewUserOnClick, ...otherProps } = this.props; const userId = member ? member.userId : fallbackUserId; otherProps = omit(otherProps, "forExport"); diff --git a/src/components/views/avatars/MemberStatusMessageAvatar.js b/src/components/views/avatars/MemberStatusMessageAvatar.js index acf190f17f..b8b23dc33e 100644 --- a/src/components/views/avatars/MemberStatusMessageAvatar.js +++ b/src/components/views/avatars/MemberStatusMessageAvatar.js @@ -14,16 +14,16 @@ See the License for the specific language governing permissions and limitations under the License. */ -import React, {createRef} from 'react'; +import React, { createRef } from 'react'; import PropTypes from 'prop-types'; -import {MatrixClientPeg} from '../../../MatrixClientPeg'; -import {_t} from "../../../languageHandler"; +import { MatrixClientPeg } from '../../../MatrixClientPeg'; +import { _t } from "../../../languageHandler"; import MemberAvatar from '../avatars/MemberAvatar'; import classNames from 'classnames'; import StatusMessageContextMenu from "../context_menus/StatusMessageContextMenu"; import SettingsStore from "../../../settings/SettingsStore"; -import {ContextMenu, ContextMenuButton} from "../../structures/ContextMenu"; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { ContextMenu, ContextMenuButton } from "../../structures/ContextMenu"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; @replaceableComponent("views.avatars.MemberStatusMessageAvatar") export default class MemberStatusMessageAvatar extends React.Component { diff --git a/src/components/views/avatars/RoomAvatar.tsx b/src/components/views/avatars/RoomAvatar.tsx index bd820509c5..c3f49d4a12 100644 --- a/src/components/views/avatars/RoomAvatar.tsx +++ b/src/components/views/avatars/RoomAvatar.tsx @@ -128,7 +128,7 @@ export default class RoomAvatar extends React.Component { }; public render() { - const {room, oobData, viewAvatarOnClick, onClick, ...otherProps} = this.props; + const { room, oobData, viewAvatarOnClick, onClick, ...otherProps } = this.props; const roomName = room ? room.name : oobData.name; diff --git a/src/components/views/avatars/WidgetAvatar.tsx b/src/components/views/avatars/WidgetAvatar.tsx index cca158269e..264f1f3956 100644 --- a/src/components/views/avatars/WidgetAvatar.tsx +++ b/src/components/views/avatars/WidgetAvatar.tsx @@ -14,12 +14,12 @@ See the License for the specific language governing permissions and limitations under the License. */ -import React, {ComponentProps} from 'react'; +import React, { ComponentProps } from 'react'; import classNames from 'classnames'; -import {IApp} from "../../../stores/WidgetStore"; -import BaseAvatar, {BaseAvatarType} from "./BaseAvatar"; -import {mediaFromMxc} from "../../../customisations/Media"; +import { IApp } from "../../../stores/WidgetStore"; +import BaseAvatar, { BaseAvatarType } from "./BaseAvatar"; +import { mediaFromMxc } from "../../../customisations/Media"; interface IProps extends Omit, "name" | "url" | "urls"> { app: IApp; @@ -49,7 +49,7 @@ const WidgetAvatar: React.FC = ({ app, className, width = 20, height = 2 width={width} height={height} /> - ) + ); }; export default WidgetAvatar; diff --git a/src/components/views/beta/BetaCard.tsx b/src/components/views/beta/BetaCard.tsx index aa4fe49f63..3127e1a915 100644 --- a/src/components/views/beta/BetaCard.tsx +++ b/src/components/views/beta/BetaCard.tsx @@ -17,10 +17,10 @@ limitations under the License. import React from "react"; import classNames from "classnames"; -import {_t} from "../../../languageHandler"; +import { _t } from "../../../languageHandler"; import AccessibleButton from "../elements/AccessibleButton"; import SettingsStore from "../../../settings/SettingsStore"; -import {SettingLevel} from "../../../settings/SettingLevel"; +import { SettingLevel } from "../../../settings/SettingLevel"; import TextWithTooltip from "../elements/TextWithTooltip"; import Modal from "../../../Modal"; import BetaFeedbackDialog from "../dialogs/BetaFeedbackDialog"; diff --git a/src/components/views/context_menus/CallContextMenu.tsx b/src/components/views/context_menus/CallContextMenu.tsx index 97473059a6..428e18ed30 100644 --- a/src/components/views/context_menus/CallContextMenu.tsx +++ b/src/components/views/context_menus/CallContextMenu.tsx @@ -22,7 +22,7 @@ import { MatrixCall } from 'matrix-js-sdk/src/webrtc/call'; import CallHandler from '../../../CallHandler'; import InviteDialog, { KIND_CALL_TRANSFER } from '../dialogs/InviteDialog'; import Modal from '../../../Modal'; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; interface IProps extends IContextMenuProps { call: MatrixCall; @@ -42,21 +42,21 @@ export default class CallContextMenu extends React.Component { onHoldClick = () => { this.props.call.setRemoteOnHold(true); this.props.onFinished(); - } + }; onUnholdClick = () => { CallHandler.sharedInstance().setActiveCallRoomId(this.props.call.roomId); this.props.onFinished(); - } + }; onTransferClick = () => { Modal.createTrackedDialog( - 'Transfer Call', '', InviteDialog, {kind: KIND_CALL_TRANSFER, call: this.props.call}, + 'Transfer Call', '', InviteDialog, { kind: KIND_CALL_TRANSFER, call: this.props.call }, /*className=*/null, /*isPriority=*/false, /*isStatic=*/true, ); this.props.onFinished(); - } + }; render() { const holdUnholdCaption = this.props.call.isRemoteOnHold() ? _t("Resume") : _t("Hold"); diff --git a/src/components/views/context_menus/DialpadContextMenu.tsx b/src/components/views/context_menus/DialpadContextMenu.tsx index 8879629055..28a73ba8d4 100644 --- a/src/components/views/context_menus/DialpadContextMenu.tsx +++ b/src/components/views/context_menus/DialpadContextMenu.tsx @@ -20,7 +20,7 @@ import { ContextMenu, IProps as IContextMenuProps } from '../../structures/Conte import { MatrixCall } from 'matrix-js-sdk/src/webrtc/call'; import Field from "../elements/Field"; import Dialpad from '../voip/DialPad'; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; interface IProps extends IContextMenuProps { call: MatrixCall; @@ -37,18 +37,17 @@ export default class DialpadContextMenu extends React.Component this.state = { value: '', - } + }; } onDigitPress = (digit) => { this.props.call.sendDtmfDigit(digit); - this.setState({value: this.state.value + digit}); - } + this.setState({ value: this.state.value + digit }); + }; onChange = (ev) => { - this.setState({value: ev.target.value}); - } - + this.setState({ value: ev.target.value }); + }; render() { return diff --git a/src/components/views/context_menus/GenericElementContextMenu.js b/src/components/views/context_menus/GenericElementContextMenu.js index e04e3f7695..87d44ef0d3 100644 --- a/src/components/views/context_menus/GenericElementContextMenu.js +++ b/src/components/views/context_menus/GenericElementContextMenu.js @@ -16,14 +16,13 @@ limitations under the License. import React from 'react'; import PropTypes from 'prop-types'; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; /* * This component can be used to display generic HTML content in a contextual * menu. */ - @replaceableComponent("views.context_menus.GenericElementContextMenu") export default class GenericElementContextMenu extends React.Component { static propTypes = { diff --git a/src/components/views/context_menus/GenericTextContextMenu.js b/src/components/views/context_menus/GenericTextContextMenu.js index 3d3add006f..474732e88b 100644 --- a/src/components/views/context_menus/GenericTextContextMenu.js +++ b/src/components/views/context_menus/GenericTextContextMenu.js @@ -16,7 +16,7 @@ limitations under the License. import React from 'react'; import PropTypes from 'prop-types'; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; @replaceableComponent("views.context_menus.GenericTextContextMenu") export default class GenericTextContextMenu extends React.Component { diff --git a/src/components/views/context_menus/GroupInviteTileContextMenu.js b/src/components/views/context_menus/GroupInviteTileContextMenu.js index 15078326b3..1529723ac8 100644 --- a/src/components/views/context_menus/GroupInviteTileContextMenu.js +++ b/src/components/views/context_menus/GroupInviteTileContextMenu.js @@ -20,10 +20,10 @@ import PropTypes from 'prop-types'; import * as sdk from '../../../index'; import { _t } from '../../../languageHandler'; import Modal from '../../../Modal'; -import {Group} from 'matrix-js-sdk/src/models/group'; +import { Group } from 'matrix-js-sdk/src/models/group'; import GroupStore from "../../../stores/GroupStore"; -import {MenuItem} from "../../structures/ContextMenu"; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { MenuItem } from "../../structures/ContextMenu"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; @replaceableComponent("views.context_menus.GroupInviteTileContextMenu") export default class GroupInviteTileContextMenu extends React.Component { diff --git a/src/components/views/context_menus/IconizedContextMenu.tsx b/src/components/views/context_menus/IconizedContextMenu.tsx index a3fb00a9f4..a9c75bf3ba 100644 --- a/src/components/views/context_menus/IconizedContextMenu.tsx +++ b/src/components/views/context_menus/IconizedContextMenu.tsx @@ -90,14 +90,14 @@ export const IconizedContextMenuCheckbox: React.FC = ({ ; }; -export const IconizedContextMenuOption: React.FC = ({label, iconClassName, ...props}) => { +export const IconizedContextMenuOption: React.FC = ({ label, iconClassName, ...props }) => { return { iconClassName && } {label} ; }; -export const IconizedContextMenuOptionList: React.FC = ({first, red, className, children}) => { +export const IconizedContextMenuOptionList: React.FC = ({ first, red, className, children }) => { const classes = classNames("mx_IconizedContextMenu_optionList", className, { mx_IconizedContextMenu_optionList_notFirst: !first, mx_IconizedContextMenu_optionList_red: red, @@ -108,7 +108,7 @@ export const IconizedContextMenuOptionList: React.FC = ({first

  • ; }; -const IconizedContextMenu: React.FC = ({className, children, compact, ...props}) => { +const IconizedContextMenu: React.FC = ({ className, children, compact, ...props }) => { const classes = classNames("mx_IconizedContextMenu", className, { mx_IconizedContextMenu_compact: compact, }); diff --git a/src/components/views/context_menus/MessageContextMenu.js b/src/components/views/context_menus/MessageContextMenu.js index eef10c995a..a2086451cd 100644 --- a/src/components/views/context_menus/MessageContextMenu.js +++ b/src/components/views/context_menus/MessageContextMenu.js @@ -28,7 +28,7 @@ import Resend from '../../../Resend'; import SettingsStore from '../../../settings/SettingsStore'; import { isUrlPermitted } from '../../../HtmlUtils'; import { isContentActionable } from '../../../utils/EventUtils'; -import { MenuItem } from "../../structures/ContextMenu"; +import IconizedContextMenu, { IconizedContextMenuOption, IconizedContextMenuOptionList } from './IconizedContextMenu'; import { EventType } from "matrix-js-sdk/src/@types/event"; import { replaceableComponent } from "../../../utils/replaceableComponent"; import { ReadPinsEventId } from "../right_panel/PinnedMessagesCard"; @@ -90,7 +90,7 @@ export default class MessageContextMenu extends React.Component { // HACK: Intentionally say we can't pin if the user doesn't want to use the functionality if (!SettingsStore.getValue("feature_pinning")) canPin = false; - this.setState({canRedact, canPin}); + this.setState({ canRedact, canPin }); }; _isPinned() { @@ -149,7 +149,7 @@ export default class MessageContextMenu extends React.Component { // display error message stating you couldn't delete this. Modal.createTrackedDialog('You cannot delete this message', '', ErrorDialog, { title: _t('Error'), - description: _t('You cannot delete this message. (%(code)s)', {code}), + description: _t('You cannot delete this message. (%(code)s)', { code }), }); } } @@ -207,7 +207,7 @@ export default class MessageContextMenu extends React.Component { this.closeMenu(); }; - onPermalinkClick = (e: Event) => { + onPermalinkClick = (e) => { e.preventDefault(); const ShareDialog = sdk.getComponent("dialogs.ShareDialog"); Modal.createTrackedDialog('share room message dialog', '', ShareDialog, { @@ -257,55 +257,68 @@ export default class MessageContextMenu extends React.Component { let externalURLButton; let quoteButton; let collapseReplyThread; + let redactItemList; // status is SENT before remote-echo, null after const isSent = !eventStatus || eventStatus === EventStatus.SENT; if (!mxEvent.isRedacted()) { if (unsentReactionsCount !== 0) { resendReactionsButton = ( - - { _t('Resend %(unsentCount)s reaction(s)', {unsentCount: unsentReactionsCount}) } - + ); } } if (isSent && this.state.canRedact) { redactButton = ( - - { _t('Remove') } - + ); } if (isContentActionable(mxEvent)) { forwardButton = ( - - { _t('Forward Message') } - + ); if (this.state.canPin) { pinButton = ( - - { this._isPinned() ? _t('Unpin Message') : _t('Pin Message') } - + ); } } const viewSourceButton = ( - - { _t('View Source') } - + ); if (this.props.eventTileOps) { if (this.props.eventTileOps.isWidgetHidden()) { unhidePreviewButton = ( - - { _t('Unhide Preview') } - + ); } } @@ -316,77 +329,97 @@ export default class MessageContextMenu extends React.Component { } // XXX: if we use room ID, we should also include a server where the event can be found (other than in the domain of the event ID) const permalinkButton = ( - - { mxEvent.isRedacted() || mxEvent.getType() !== 'm.room.message' - ? _t('Share Permalink') : _t('Share Message') } - + /> ); if (this.props.eventTileOps) { // this event is rendered using TextualBody quoteButton = ( - - { _t('Quote') } - + ); } // Bridges can provide a 'external_url' to link back to the source. - if ( - typeof(mxEvent.event.content.external_url) === "string" && + if (typeof (mxEvent.event.content.external_url) === "string" && isUrlPermitted(mxEvent.event.content.external_url) ) { externalURLButton = ( - - { _t('Source URL') } - + /> ); } if (this.props.collapseReplyThread) { collapseReplyThread = ( - - { _t('Collapse Reply Thread') } - + ); } let reportEventButton; if (mxEvent.getSender() !== me) { reportEventButton = ( - - { _t('Report Content') } - + + ); + } + + const commonItemsList = ( + + { quoteButton } + { forwardButton } + { pinButton } + { permalinkButton } + { reportEventButton } + { externalURLButton } + { unhidePreviewButton } + { viewSourceButton } + { resendReactionsButton } + { collapseReplyThread } + + ); + + if (redactButton) { + redactItemList = ( + + { redactButton } + ); } return ( -
    - { resendReactionsButton } - { redactButton } - { forwardButton } - { pinButton } - { viewSourceButton } - { unhidePreviewButton } - { permalinkButton } - { quoteButton } - { externalURLButton } - { collapseReplyThread } - { reportEventButton } -
    + + { commonItemsList } + { redactItemList } + ); } } diff --git a/src/components/views/context_menus/StatusMessageContextMenu.js b/src/components/views/context_menus/StatusMessageContextMenu.js index 41f0e0ba61..23b91fe68f 100644 --- a/src/components/views/context_menus/StatusMessageContextMenu.js +++ b/src/components/views/context_menus/StatusMessageContextMenu.js @@ -17,10 +17,10 @@ limitations under the License. import React from 'react'; import PropTypes from 'prop-types'; import { _t } from '../../../languageHandler'; -import {MatrixClientPeg} from '../../../MatrixClientPeg'; +import { MatrixClientPeg } from '../../../MatrixClientPeg'; import * as sdk from '../../../index'; import AccessibleButton from '../elements/AccessibleButton'; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; @replaceableComponent("views.context_menus.StatusMessageContextMenu") export default class StatusMessageContextMenu extends React.Component { diff --git a/src/components/views/context_menus/TagTileContextMenu.js b/src/components/views/context_menus/TagTileContextMenu.js index 4e381643ba..c40ff4207b 100644 --- a/src/components/views/context_menus/TagTileContextMenu.js +++ b/src/components/views/context_menus/TagTileContextMenu.js @@ -20,9 +20,9 @@ import PropTypes from 'prop-types'; import { _t } from '../../../languageHandler'; import dis from '../../../dispatcher/dispatcher'; import TagOrderActions from '../../../actions/TagOrderActions'; -import {MenuItem} from "../../structures/ContextMenu"; +import { MenuItem } from "../../structures/ContextMenu"; import MatrixClientContext from "../../../contexts/MatrixClientContext"; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; import GroupFilterOrderStore from "../../../stores/GroupFilterOrderStore"; @replaceableComponent("views.context_menus.TagTileContextMenu") diff --git a/src/components/views/context_menus/WidgetContextMenu.tsx b/src/components/views/context_menus/WidgetContextMenu.tsx index 068bfd6497..b21efdceb9 100644 --- a/src/components/views/context_menus/WidgetContextMenu.tsx +++ b/src/components/views/context_menus/WidgetContextMenu.tsx @@ -14,22 +14,22 @@ See the License for the specific language governing permissions and limitations under the License. */ -import React, {useContext} from "react"; -import {MatrixCapabilities} from "matrix-widget-api"; +import React, { useContext } from "react"; +import { MatrixCapabilities } from "matrix-widget-api"; -import IconizedContextMenu, {IconizedContextMenuOption, IconizedContextMenuOptionList} from "./IconizedContextMenu"; -import {ChevronFace} from "../../structures/ContextMenu"; -import {_t} from "../../../languageHandler"; -import {IApp} from "../../../stores/WidgetStore"; +import IconizedContextMenu, { IconizedContextMenuOption, IconizedContextMenuOptionList } from "./IconizedContextMenu"; +import { ChevronFace } from "../../structures/ContextMenu"; +import { _t } from "../../../languageHandler"; +import { IApp } from "../../../stores/WidgetStore"; import WidgetUtils from "../../../utils/WidgetUtils"; -import {WidgetMessagingStore} from "../../../stores/widgets/WidgetMessagingStore"; +import { WidgetMessagingStore } from "../../../stores/widgets/WidgetMessagingStore"; import RoomContext from "../../../contexts/RoomContext"; import dis from "../../../dispatcher/dispatcher"; import SettingsStore from "../../../settings/SettingsStore"; import Modal from "../../../Modal"; import QuestionDialog from "../dialogs/QuestionDialog"; import ErrorDialog from "../dialogs/ErrorDialog"; -import {WidgetType} from "../../../widgets/WidgetType"; +import { WidgetType } from "../../../widgets/WidgetType"; import MatrixClientContext from "../../../contexts/MatrixClientContext"; import { Container, WidgetLayoutStore } from "../../../stores/widgets/WidgetLayoutStore"; import { getConfigLivestreamUrl, startJitsiAudioLivestream } from "../../../Livestream"; @@ -54,7 +54,7 @@ const WidgetContextMenu: React.FC = ({ ...props }) => { const cli = useContext(MatrixClientContext); - const {room, roomId} = useContext(RoomContext); + const { room, roomId } = useContext(RoomContext); const widgetMessaging = WidgetMessagingStore.instance.getMessagingForId(app.id); const canModify = userWidget || WidgetUtils.canUserModifyWidgets(roomId); diff --git a/src/components/views/dialogs/AddExistingToSpaceDialog.tsx b/src/components/views/dialogs/AddExistingToSpaceDialog.tsx index 8997e4a5f8..c09097c4b4 100644 --- a/src/components/views/dialogs/AddExistingToSpaceDialog.tsx +++ b/src/components/views/dialogs/AddExistingToSpaceDialog.tsx @@ -14,29 +14,29 @@ See the License for the specific language governing permissions and limitations under the License. */ -import React, {ReactNode, useContext, useMemo, useState} from "react"; +import React, { ReactNode, useContext, useMemo, useState } from "react"; import classNames from "classnames"; -import {Room} from "matrix-js-sdk/src/models/room"; -import {MatrixClient} from "matrix-js-sdk/src/client"; +import { Room } from "matrix-js-sdk/src/models/room"; +import { MatrixClient } from "matrix-js-sdk/src/client"; -import {_t} from '../../../languageHandler'; -import {IDialogProps} from "./IDialogProps"; +import { _t } from '../../../languageHandler'; +import { IDialogProps } from "./IDialogProps"; import BaseDialog from "./BaseDialog"; import Dropdown from "../elements/Dropdown"; import SearchBox from "../../structures/SearchBox"; import SpaceStore from "../../../stores/SpaceStore"; import RoomAvatar from "../avatars/RoomAvatar"; -import {getDisplayAliasForRoom} from "../../../Rooms"; +import { getDisplayAliasForRoom } from "../../../Rooms"; import AccessibleButton from "../elements/AccessibleButton"; import AutoHideScrollbar from "../../structures/AutoHideScrollbar"; -import {sleep} from "../../../utils/promise"; +import { sleep } from "../../../utils/promise"; import DMRoomMap from "../../../utils/DMRoomMap"; -import {calculateRoomVia} from "../../../utils/permalinks/Permalinks"; +import { calculateRoomVia } from "../../../utils/permalinks/Permalinks"; import StyledCheckbox from "../elements/StyledCheckbox"; import MatrixClientContext from "../../../contexts/MatrixClientContext"; -import {sortRooms} from "../../../stores/room-list/algorithms/tag-sorting/RecentAlgorithm"; +import { sortRooms } from "../../../stores/room-list/algorithms/tag-sorting/RecentAlgorithm"; import ProgressBar from "../elements/ProgressBar"; -import {SpaceFeedbackPrompt} from "../../structures/SpaceRoomView"; +import { SpaceFeedbackPrompt } from "../../structures/SpaceRoomView"; import DecoratedRoomAvatar from "../avatars/DecoratedRoomAvatar"; import QueryMatcher from "../../../autocomplete/QueryMatcher"; import TruncatedList from "../elements/TruncatedList"; diff --git a/src/components/views/dialogs/AddressPickerDialog.js b/src/components/views/dialogs/AddressPickerDialog.js index 77c69abc4e..ad4fc8d672 100644 --- a/src/components/views/dialogs/AddressPickerDialog.js +++ b/src/components/views/dialogs/AddressPickerDialog.js @@ -17,12 +17,12 @@ See the License for the specific language governing permissions and limitations under the License. */ -import React, {createRef} from 'react'; +import React, { createRef } from 'react'; import PropTypes from 'prop-types'; import { _t, _td } from '../../../languageHandler'; import * as sdk from '../../../index'; -import {MatrixClientPeg} from '../../../MatrixClientPeg'; +import { MatrixClientPeg } from '../../../MatrixClientPeg'; import dis from '../../../dispatcher/dispatcher'; import { addressTypes, getAddressType } from '../../../UserAddress'; import GroupStore from '../../../stores/GroupStore'; @@ -30,10 +30,10 @@ import * as Email from '../../../email'; import IdentityAuthClient from '../../../IdentityAuthClient'; import { getDefaultIdentityServerUrl, useDefaultIdentityServer } from '../../../utils/IdentityServerUtils'; import { abbreviateUrl } from '../../../utils/UrlUtils'; -import {sleep} from "../../../utils/promise"; -import {Key} from "../../../Keyboard"; -import {Action} from "../../../dispatcher/actions"; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { sleep } from "../../../utils/promise"; +import { Key } from "../../../Keyboard"; +import { Action } from "../../../dispatcher/actions"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; const TRUNCATE_QUERY_LIST = 40; const QUERY_USER_DIRECTORY_DEBOUNCE_MS = 200; @@ -457,7 +457,7 @@ export default class AddressPickerDialog extends React.Component { const addrType = getAddressType(query); if (this.state.validAddressTypes.includes(addrType)) { if (addrType === 'email' && !Email.looksValid(query)) { - this.setState({searchError: _t("That doesn't look like a valid email address")}); + this.setState({ searchError: _t("That doesn't look like a valid email address") }); return; } suggestedList.unshift({ @@ -573,13 +573,13 @@ export default class AddressPickerDialog extends React.Component { _getFilteredSuggestions() { // map addressType => set of addresses to avoid O(n*m) operation const selectedAddresses = {}; - this.state.selectedList.forEach(({address, addressType}) => { + this.state.selectedList.forEach(({ address, addressType }) => { if (!selectedAddresses[addressType]) selectedAddresses[addressType] = new Set(); selectedAddresses[addressType].add(address); }); // Filter out any addresses in the above already selected addresses (matching both type and address) - return this.state.suggestedList.filter(({address, addressType}) => { + return this.state.suggestedList.filter(({ address, addressType }) => { return !(selectedAddresses[addressType] && selectedAddresses[addressType].has(address)); }); } diff --git a/src/components/views/dialogs/BaseDialog.js b/src/components/views/dialogs/BaseDialog.js index 0858e53e50..e92bd6315e 100644 --- a/src/components/views/dialogs/BaseDialog.js +++ b/src/components/views/dialogs/BaseDialog.js @@ -23,10 +23,10 @@ import classNames from 'classnames'; import { Key } from '../../../Keyboard'; import AccessibleButton from '../elements/AccessibleButton'; -import {MatrixClientPeg} from '../../../MatrixClientPeg'; +import { MatrixClientPeg } from '../../../MatrixClientPeg'; import { _t } from "../../../languageHandler"; import MatrixClientContext from "../../../contexts/MatrixClientContext"; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; /* * Basic container for modal dialogs. diff --git a/src/components/views/dialogs/BetaFeedbackDialog.tsx b/src/components/views/dialogs/BetaFeedbackDialog.tsx index b8ff803627..5a2f16f169 100644 --- a/src/components/views/dialogs/BetaFeedbackDialog.tsx +++ b/src/components/views/dialogs/BetaFeedbackDialog.tsx @@ -14,28 +14,28 @@ See the License for the specific language governing permissions and limitations under the License. */ -import React, {useState} from "react"; +import React, { useState } from "react"; import QuestionDialog from './QuestionDialog'; import { _t } from '../../../languageHandler'; import Field from "../elements/Field"; import SdkConfig from "../../../SdkConfig"; -import {IDialogProps} from "./IDialogProps"; +import { IDialogProps } from "./IDialogProps"; import SettingsStore from "../../../settings/SettingsStore"; -import {submitFeedback} from "../../../rageshake/submit-rageshake"; +import { submitFeedback } from "../../../rageshake/submit-rageshake"; import StyledCheckbox from "../elements/StyledCheckbox"; import Modal from "../../../Modal"; import InfoDialog from "./InfoDialog"; import AccessibleButton from "../elements/AccessibleButton"; import defaultDispatcher from "../../../dispatcher/dispatcher"; -import {Action} from "../../../dispatcher/actions"; +import { Action } from "../../../dispatcher/actions"; import { UserTab } from "./UserSettingsDialog"; interface IProps extends IDialogProps { featureId: string; } -const BetaFeedbackDialog: React.FC = ({featureId, onFinished}) => { +const BetaFeedbackDialog: React.FC = ({ featureId, onFinished }) => { const info = SettingsStore.getBetaInfo(featureId); const [comment, setComment] = useState(""); diff --git a/src/components/views/dialogs/BugReportDialog.tsx b/src/components/views/dialogs/BugReportDialog.tsx index f938340a50..eeb3769bf9 100644 --- a/src/components/views/dialogs/BugReportDialog.tsx +++ b/src/components/views/dialogs/BugReportDialog.tsx @@ -22,9 +22,9 @@ 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 sendBugReport, { downloadBugReport } from '../../../rageshake/submit-rageshake'; import AccessibleButton from "../elements/AccessibleButton"; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; interface IProps { onFinished: (success: boolean) => void; @@ -68,7 +68,7 @@ export default class BugReportDialog extends React.Component { private onCancel = (): void => { this.props.onFinished(false); - } + }; private onSubmit = (): void => { if ((!this.state.text || !this.state.text.trim()) && (!this.state.issueUrl || !this.state.issueUrl.trim())) { @@ -110,7 +110,7 @@ export default class BugReportDialog extends React.Component { }); } }); - } + }; private onDownload = async (): Promise => { this.setState({ downloadBusy: true }); @@ -139,25 +139,25 @@ export default class BugReportDialog extends React.Component { private onTextChange = (ev: React.FormEvent): void => { this.setState({ text: ev.currentTarget.value }); - } + }; private onIssueUrlChange = (ev: React.FormEvent): void => { this.setState({ issueUrl: ev.currentTarget.value }); - } + }; private sendProgressCallback = (progress: string): void => { if (this.unmounted) { return; } this.setState({ progress }); - } + }; private downloadProgressCallback = (downloadProgress: string): void => { if (this.unmounted) { return; } this.setState({ downloadProgress }); - } + }; public render() { const Loader = sdk.getComponent("elements.Spinner"); diff --git a/src/components/views/dialogs/ChangelogDialog.tsx b/src/components/views/dialogs/ChangelogDialog.tsx index 0ded33cdcb..8acacd8e73 100644 --- a/src/components/views/dialogs/ChangelogDialog.tsx +++ b/src/components/views/dialogs/ChangelogDialog.tsx @@ -49,7 +49,7 @@ export default class ChangelogDialog extends React.Component { this.setState({ [REPOS[i]]: response.statusText }); return; } - this.setState({[REPOS[i]]: JSON.parse(body).commits}); + this.setState({ [REPOS[i]]: JSON.parse(body).commits }); }); } } @@ -93,7 +93,6 @@ export default class ChangelogDialog extends React.Component {
    ); - return ( { @@ -122,12 +122,12 @@ export default class CommunityPrototypeInviteDialog extends React.PureComponent< if (index >= targets.length) return; // not important if (targets[index].trim() === "") { targets.splice(index, 1); - this.setState({emailTargets: targets}); + this.setState({ emailTargets: targets }); } }; private onShowPeopleClick = () => { - this.setState({showPeople: !this.state.showPeople}); + this.setState({ showPeople: !this.state.showPeople }); }; private setPersonToggle = (person: IPerson, selected: boolean) => { @@ -137,7 +137,7 @@ export default class CommunityPrototypeInviteDialog extends React.PureComponent< } else if (!selected && targets.includes(person.userId)) { targets.splice(targets.indexOf(person.userId), 1); } - this.setState({userTargets: targets}); + this.setState({ userTargets: targets }); }; private renderPerson(person: IPerson, key: any) { @@ -165,7 +165,7 @@ export default class CommunityPrototypeInviteDialog extends React.PureComponent< } private onShowMorePeople = () => { - this.setState({numPeople: this.state.numPeople + 5}); // arbitrary increase + this.setState({ numPeople: this.state.numPeople + 5 }); // arbitrary increase }; public render() { @@ -214,7 +214,7 @@ export default class CommunityPrototypeInviteDialog extends React.PureComponent< if (this.state.people.length > 0) { peopleIntro = (
    - {_t("People you know on %(brand)s", {brand: SdkConfig.get().brand})} + {_t("People you know on %(brand)s", { brand: SdkConfig.get().brand })} {this.state.showPeople ? _t("Hide") : _t("Show")} @@ -225,14 +225,14 @@ export default class CommunityPrototypeInviteDialog extends React.PureComponent< let buttonText = _t("Skip"); const targetCount = this.state.userTargets.length + this.state.emailTargets.length; if (targetCount > 0) { - buttonText = _t("Send %(count)s invites", {count: targetCount}); + buttonText = _t("Send %(count)s invites", { count: targetCount }); } return (
    diff --git a/src/components/views/dialogs/ConfirmAndWaitRedactDialog.tsx b/src/components/views/dialogs/ConfirmAndWaitRedactDialog.tsx index ae7b23c2c9..90b749b959 100644 --- a/src/components/views/dialogs/ConfirmAndWaitRedactDialog.tsx +++ b/src/components/views/dialogs/ConfirmAndWaitRedactDialog.tsx @@ -53,14 +53,14 @@ export default class ConfirmAndWaitRedactDialog extends React.PureComponent => { if (proceed) { - this.setState({isRedacting: true}); + this.setState({ isRedacting: true }); try { await this.props.redact(); this.props.onFinished(true); } catch (error) { const code = error.errcode || error.statusCode; if (typeof code !== "undefined") { - this.setState({redactionErrorCode: code}); + this.setState({ redactionErrorCode: code }); } else { this.props.onFinished(true); } @@ -79,7 +79,7 @@ export default class ConfirmAndWaitRedactDialog extends React.PureComponent ); } else { diff --git a/src/components/views/dialogs/ConfirmRedactDialog.tsx b/src/components/views/dialogs/ConfirmRedactDialog.tsx index eee05599e8..94f29a71fc 100644 --- a/src/components/views/dialogs/ConfirmRedactDialog.tsx +++ b/src/components/views/dialogs/ConfirmRedactDialog.tsx @@ -17,7 +17,7 @@ limitations under the License. import React from 'react'; import * as sdk from '../../../index'; import { _t } from '../../../languageHandler'; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; interface IProps { onFinished: (success: boolean) => void; diff --git a/src/components/views/dialogs/ConfirmWipeDeviceDialog.tsx b/src/components/views/dialogs/ConfirmWipeDeviceDialog.tsx index d95b1fe358..2978179817 100644 --- a/src/components/views/dialogs/ConfirmWipeDeviceDialog.tsx +++ b/src/components/views/dialogs/ConfirmWipeDeviceDialog.tsx @@ -15,9 +15,9 @@ limitations under the License. */ import React from 'react'; -import {_t} from "../../../languageHandler"; +import { _t } from "../../../languageHandler"; import * as sdk from "../../../index"; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; interface IProps { onFinished: (success: boolean) => void; diff --git a/src/components/views/dialogs/CreateCommunityPrototypeDialog.tsx b/src/components/views/dialogs/CreateCommunityPrototypeDialog.tsx index 9b4484d661..29e9a2ad39 100644 --- a/src/components/views/dialogs/CreateCommunityPrototypeDialog.tsx +++ b/src/components/views/dialogs/CreateCommunityPrototypeDialog.tsx @@ -23,9 +23,9 @@ import AccessibleButton from "../elements/AccessibleButton"; import { MatrixClientPeg } from "../../../MatrixClientPeg"; import InfoTooltip from "../elements/InfoTooltip"; import dis from "../../../dispatcher/dispatcher"; -import {showCommunityRoomInviteDialog} from "../../../RoomInvite"; +import { showCommunityRoomInviteDialog } from "../../../RoomInvite"; import GroupStore from "../../../stores/GroupStore"; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; interface IProps extends IDialogProps { } @@ -58,7 +58,7 @@ export default class CreateCommunityPrototypeDialog extends React.PureComponent< private onNameChange = (ev: ChangeEvent) => { const localpart = (ev.target.value || "").toLowerCase().replace(/[^a-z0-9.\-_]/g, '-'); - this.setState({name: ev.target.value, localpart}); + this.setState({ name: ev.target.value, localpart }); }; private onSubmit = async (ev) => { @@ -69,7 +69,7 @@ export default class CreateCommunityPrototypeDialog extends React.PureComponent< // We'll create the community now to see if it's taken, leaving it active in // the background for the user to look at while they invite people. - this.setState({busy: true}); + this.setState({ busy: true }); try { let avatarUrl = ''; // must be a string for synapse to accept it if (this.state.avatarFile) { @@ -85,7 +85,7 @@ export default class CreateCommunityPrototypeDialog extends React.PureComponent< }); // Ensure the tag gets selected now that we've created it - dis.dispatch({action: 'deselect_tags'}, true); + dis.dispatch({ action: 'deselect_tags' }, true); dis.dispatch({ action: 'select_tag', tag: result.group_id, @@ -123,13 +123,13 @@ export default class CreateCommunityPrototypeDialog extends React.PureComponent< private onAvatarChanged = (e: ChangeEvent) => { if (!e.target.files || !e.target.files.length) { - this.setState({avatarFile: null}); + this.setState({ avatarFile: null }); } else { - this.setState({busy: true}); + this.setState({ busy: true }); const file = e.target.files[0]; const reader = new FileReader(); reader.onload = (ev: ProgressEvent) => { - this.setState({avatarFile: file, busy: false, avatarPreview: ev.target.result as string}); + this.setState({ avatarFile: file, busy: false, avatarPreview: ev.target.result as string }); }; reader.readAsDataURL(file); } @@ -175,7 +175,7 @@ export default class CreateCommunityPrototypeDialog extends React.PureComponent< let preview = ; if (!this.state.avatarPreview) { - preview =
    + preview =
    ; } return ( @@ -204,7 +204,7 @@ export default class CreateCommunityPrototypeDialog extends React.PureComponent<
    diff --git a/src/components/views/dialogs/CreateGroupDialog.tsx b/src/components/views/dialogs/CreateGroupDialog.tsx index 60e4f5efb8..f03a40ddc5 100644 --- a/src/components/views/dialogs/CreateGroupDialog.tsx +++ b/src/components/views/dialogs/CreateGroupDialog.tsx @@ -18,8 +18,8 @@ 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 { MatrixClientPeg } from '../../../MatrixClientPeg'; +import { replaceableComponent } from "../../../utils/replaceableComponent"; interface IProps { onFinished: (success: boolean) => void; @@ -83,7 +83,7 @@ export default class CreateGroupDialog extends React.Component { if (this.state.groupName !== '') { profile.name = this.state.groupName; } - this.setState({creating: true}); + this.setState({ creating: true }); MatrixClientPeg.get().createGroup({ localpart: this.state.groupId, profile: profile, @@ -95,9 +95,9 @@ export default class CreateGroupDialog extends React.Component { }); this.props.onFinished(true); }).catch((e) => { - this.setState({createError: e}); + this.setState({ createError: e }); }).finally(() => { - this.setState({creating: false}); + this.setState({ creating: false }); }); }; diff --git a/src/components/views/dialogs/CreateRoomDialog.tsx b/src/components/views/dialogs/CreateRoomDialog.tsx index 544f593708..b5c0096771 100644 --- a/src/components/views/dialogs/CreateRoomDialog.tsx +++ b/src/components/views/dialogs/CreateRoomDialog.tsx @@ -137,9 +137,9 @@ export default class CreateRoomDialog extends React.Component { if (activeElement) { activeElement.blur(); } - await this.nameField.current.validate({allowEmpty: false}); + await this.nameField.current.validate({ allowEmpty: false }); if (this.aliasField.current) { - await this.aliasField.current.validate({allowEmpty: false}); + await this.aliasField.current.validate({ allowEmpty: false }); } // Validation and state updates are async, so we need to wait for them to complete // first. Queue a `setState` callback and wait for it to resolve. @@ -194,7 +194,7 @@ export default class CreateRoomDialog extends React.Component { private onNameValidate = async (fieldState: IFieldState) => { const result = await CreateRoomDialog.validateRoomName(fieldState); - this.setState({nameIsValid: result.valid}); + this.setState({ nameIsValid: result.valid }); return result; }; @@ -276,7 +276,7 @@ export default class CreateRoomDialog extends React.Component { let title = this.state.isPublic ? _t('Create a public room') : _t('Create a private room'); if (CommunityPrototypeStore.instance.getSelectedCommunityId()) { const name = CommunityPrototypeStore.instance.getSelectedCommunityName(); - title = _t("Create a room in %(communityName)s", {communityName: name}); + title = _t("Create a room in %(communityName)s", { communityName: name }); } return ( { { focus: false, onFinished: (doLogout) => { if (doLogout) { - dis.dispatch({action: 'logout'}); + dis.dispatch({ action: 'logout' }); props.onFinished(true); } }, diff --git a/src/components/views/dialogs/DeactivateAccountDialog.tsx b/src/components/views/dialogs/DeactivateAccountDialog.tsx index cf88802340..6df6056670 100644 --- a/src/components/views/dialogs/DeactivateAccountDialog.tsx +++ b/src/components/views/dialogs/DeactivateAccountDialog.tsx @@ -19,13 +19,13 @@ import React from 'react'; import * as sdk from '../../../index'; import Analytics from '../../../Analytics'; -import {MatrixClientPeg} from '../../../MatrixClientPeg'; +import { MatrixClientPeg } from '../../../MatrixClientPeg'; import * as Lifecycle from '../../../Lifecycle'; import { _t } from '../../../languageHandler'; -import InteractiveAuth, {ERROR_USER_CANCELLED} from "../../structures/InteractiveAuth"; -import {DEFAULT_PHASE, PasswordAuthEntry, SSOAuthEntry} from "../auth/InteractiveAuthEntryComponents"; +import InteractiveAuth, { ERROR_USER_CANCELLED } from "../../structures/InteractiveAuth"; +import { DEFAULT_PHASE, PasswordAuthEntry, SSOAuthEntry } from "../auth/InteractiveAuthEntryComponents"; import StyledCheckbox from "../elements/StyledCheckbox"; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; interface IProps { onFinished: (success: boolean) => void; @@ -100,7 +100,7 @@ export default class DeactivateAccountDialog extends React.Component { @@ -112,7 +112,7 @@ export default class DeactivateAccountDialog extends React.Component { @@ -123,7 +123,7 @@ export default class DeactivateAccountDialog extends React.Component { console.error(e); - this.setState({errStr: _t("There was a problem communicating with the server. Please try again.")}); + this.setState({ errStr: _t("There was a problem communicating with the server. Please try again.") }); }); }; @@ -153,13 +153,13 @@ export default class DeactivateAccountDialog extends React.Component { if (e && e.httpStatus === 401 && e.data) { // Valid UIA response - this.setState({authData: e.data, authEnabled: true}); + this.setState({ authData: e.data, authEnabled: true }); } else { - this.setState({errStr: _t("Server did not return valid authentication information.")}); + this.setState({ errStr: _t("Server did not return valid authentication information.") }); } }); } diff --git a/src/components/views/dialogs/DevtoolsDialog.tsx b/src/components/views/dialogs/DevtoolsDialog.tsx index b1749b370a..de958f8e9a 100644 --- a/src/components/views/dialogs/DevtoolsDialog.tsx +++ b/src/components/views/dialogs/DevtoolsDialog.tsx @@ -62,13 +62,13 @@ abstract class GenericEditor< } else { this.props.onBack(); } - } + }; protected onChange = (e: ChangeEvent) => { // @ts-ignore: Unsure how to convince TS this is okay when the state // type can be extended. - this.setState({[e.target.id]: e.target.type === 'checkbox' ? e.target.checked : e.target.value}); - } + this.setState({ [e.target.id]: e.target.type === 'checkbox' ? e.target.checked : e.target.value }); + }; protected abstract send(); @@ -119,7 +119,7 @@ export class SendCustomEvent extends GenericEditor { !this.state.message && } - { showTglFlip &&
    + { showTglFlip &&
    { !this.state.message && } - { !this.state.message &&
    + { !this.state.message &&
    { this.setState({ editing: true }); - } + }; private onQueryEventType = (filterEventType: string) => { this.setState({ queryEventType: filterEventType }); - } + }; private onQueryStateKey = (filterStateKey: string) => { this.setState({ queryStateKey: filterStateKey }); - } + }; render() { if (this.state.event) { @@ -570,19 +570,19 @@ class AccountDataExplorer extends React.PureComponent) => { - this.setState({[e.target.id]: e.target.type === 'checkbox' ? e.target.checked : e.target.value}); - } + this.setState({ [e.target.id]: e.target.type === 'checkbox' ? e.target.checked : e.target.value }); + }; private editEv = () => { this.setState({ editing: true }); - } + }; private onQueryEventType = (queryEventType: string) => { this.setState({ queryEventType }); - } + }; render() { if (this.state.event) { @@ -630,7 +630,7 @@ class AccountDataExplorer extends React.PureComponent
    -
    +
    { this.setState({ query }); - } + }; render() { return
    @@ -704,7 +704,7 @@ const PHASE_MAP = { const VerificationRequestExplorer: React.FC<{ txnId: string; request: VerificationRequest; -}> = ({txnId, request}) => { +}> = ({ txnId, request }) => { const [, updateState] = useState(); const [timeout, setRequestTimeout] = useState(request.timeout); @@ -739,7 +739,7 @@ const VerificationRequestExplorer: React.FC<{
    {JSON.stringify(request.observeOnly)}
    ); -} +}; class VerificationExplorer extends React.PureComponent { static getLabel() { @@ -751,7 +751,7 @@ class VerificationExplorer extends React.PureComponent { private onNewRequest = () => { this.forceUpdate(); - } + }; componentDidMount() { const cli = this.context; @@ -806,17 +806,17 @@ class WidgetExplorer extends React.Component { - this.setState({query}); + this.setState({ query }); }; private onEditWidget = (widget: IApp) => { - this.setState({editWidget: widget}); + this.setState({ editWidget: widget }); }; private onBack = () => { const widgets = WidgetStore.instance.getApps(this.props.room.roomId); if (this.state.editWidget && widgets.includes(this.state.editWidget)) { - this.setState({editWidget: null}); + this.setState({ editWidget: null }); } else { this.props.onBack(); } @@ -908,22 +908,22 @@ class SettingsExplorer extends React.PureComponent) => { - this.setState({query: ev.target.value}); + this.setState({ query: ev.target.value }); }; private onExplValuesEdit = (ev: ChangeEvent) => { - this.setState({explicitValues: ev.target.value}); + this.setState({ explicitValues: ev.target.value }); }; private onExplRoomValuesEdit = (ev: ChangeEvent) => { - this.setState({explicitRoomValues: ev.target.value}); + this.setState({ explicitRoomValues: ev.target.value }); }; private onBack = () => { if (this.state.editSetting) { - this.setState({editSetting: null}); + this.setState({ editSetting: null }); } else if (this.state.viewSetting) { - this.setState({viewSetting: null}); + this.setState({ viewSetting: null }); } else { this.props.onBack(); } @@ -931,7 +931,7 @@ class SettingsExplorer extends React.PureComponent { ev.preventDefault(); - this.setState({viewSetting: settingId}); + this.setState({ viewSetting: settingId }); }; private onEditClick = (ev: MouseEvent, settingId: string) => { @@ -1221,11 +1221,11 @@ export default class DevtoolsDialog extends React.PureComponent private onBack = () => { this.setState({ mode: null }); - } + }; private onCancel = () => { this.props.onFinished(false); - } + }; render() { let body; diff --git a/src/components/views/dialogs/EditCommunityPrototypeDialog.tsx b/src/components/views/dialogs/EditCommunityPrototypeDialog.tsx index ee3696b427..217e4f2d37 100644 --- a/src/components/views/dialogs/EditCommunityPrototypeDialog.tsx +++ b/src/components/views/dialogs/EditCommunityPrototypeDialog.tsx @@ -23,8 +23,8 @@ import AccessibleButton from "../elements/AccessibleButton"; import { MatrixClientPeg } from "../../../MatrixClientPeg"; import { CommunityPrototypeStore } from "../../../stores/CommunityPrototypeStore"; import FlairStore from "../../../stores/FlairStore"; -import {replaceableComponent} from "../../../utils/replaceableComponent"; -import {mediaFromMxc} from "../../../customisations/Media"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; +import { mediaFromMxc } from "../../../customisations/Media"; interface IProps extends IDialogProps { communityId: string; @@ -60,7 +60,7 @@ export default class EditCommunityPrototypeDialog extends React.PureComponent) => { - this.setState({name: ev.target.value}); + this.setState({ name: ev.target.value }); }; private onSubmit = async (ev) => { @@ -71,7 +71,7 @@ export default class EditCommunityPrototypeDialog extends React.PureComponent) => { if (!e.target.files || !e.target.files.length) { - this.setState({avatarFile: null}); + this.setState({ avatarFile: null }); } else { - this.setState({busy: true}); + this.setState({ busy: true }); const file = e.target.files[0]; const reader = new FileReader(); reader.onload = (ev: ProgressEvent) => { - this.setState({avatarFile: file, busy: false, avatarPreview: ev.target.result as string}); + this.setState({ avatarFile: file, busy: false, avatarPreview: ev.target.result as string }); }; reader.readAsDataURL(file); } @@ -122,7 +122,7 @@ export default class EditCommunityPrototypeDialog extends React.PureComponent; } else { - preview =
    + preview =
    ; } } @@ -144,7 +144,7 @@ export default class EditCommunityPrototypeDialog extends React.PureComponent
    diff --git a/src/components/views/dialogs/ErrorDialog.tsx b/src/components/views/dialogs/ErrorDialog.tsx index d50ec7bf36..0f675f0df7 100644 --- a/src/components/views/dialogs/ErrorDialog.tsx +++ b/src/components/views/dialogs/ErrorDialog.tsx @@ -28,7 +28,7 @@ limitations under the License. import React from 'react'; import * as sdk from '../../../index'; import { _t } from '../../../languageHandler'; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; interface IProps { onFinished: (success: boolean) => void; diff --git a/src/components/views/dialogs/FeedbackDialog.js b/src/components/views/dialogs/FeedbackDialog.js index d80a935573..88a57cf8cb 100644 --- a/src/components/views/dialogs/FeedbackDialog.js +++ b/src/components/views/dialogs/FeedbackDialog.js @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import React, {useState} from 'react'; +import React, { useState } from 'react'; import QuestionDialog from './QuestionDialog'; import { _t } from '../../../languageHandler'; import Field from "../elements/Field"; @@ -30,7 +30,6 @@ const existingIssuesUrl = "https://github.com/vector-im/element-web/issues" + "?q=is%3Aopen+is%3Aissue+sort%3Areactions-%2B1-desc"; const newIssueUrl = "https://github.com/vector-im/element-web/issues/new"; - export default (props) => { const [rating, setRating] = useState(""); const [comment, setComment] = useState(""); diff --git a/src/components/views/dialogs/HostSignupDialog.tsx b/src/components/views/dialogs/HostSignupDialog.tsx index c8bc907136..64c080bf01 100644 --- a/src/components/views/dialogs/HostSignupDialog.tsx +++ b/src/components/views/dialogs/HostSignupDialog.tsx @@ -31,7 +31,7 @@ import { IPostmessageResponseData, PostmessageAction, } from "./HostSignupDialogTypes"; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; const HOST_SIGNUP_KEY = "host_signup"; @@ -86,7 +86,7 @@ export default class HostSignupDialog extends React.PureComponent { this.setState({ @@ -96,7 +96,7 @@ export default class HostSignupDialog extends React.PureComponent { this.setState({ @@ -106,7 +106,7 @@ export default class HostSignupDialog extends React.PureComponent { window.removeEventListener("message", this.messageHandler); @@ -114,7 +114,7 @@ export default class HostSignupDialog extends React.PureComponent { if (this.state.completed) { @@ -137,16 +137,16 @@ export default class HostSignupDialog extends React.PureComponent { this.iframeRef.current.contentWindow.postMessage(message, this.config.url); - } + }; private async sendAccountDetails() { const openIdToken = await MatrixClientPeg.get().getOpenIdToken(); if (!openIdToken || !openIdToken.access_token) { - console.warn("Failed to connect to homeserver for OpenID token.") + console.warn("Failed to connect to homeserver for OpenID token."); this.setState({ completed: true, error: _t("Failed to connect to your homeserver. Please close this dialog and try again."), @@ -171,7 +171,7 @@ export default class HostSignupDialog extends React.PureComponent { const textComponent = ( @@ -215,7 +215,7 @@ export default class HostSignupDialog extends React.PureComponent { - this.setState({phase: PHASE_WAIT_FOR_PARTNER_TO_CONFIRM}); + this.setState({ phase: PHASE_WAIT_FOR_PARTNER_TO_CONFIRM }); this.props.verifier.verify().then(() => { - this.setState({phase: PHASE_VERIFIED}); + this.setState({ phase: PHASE_VERIFIED }); }).catch((e) => { console.log("Verification failed", e); }); diff --git a/src/components/views/dialogs/IntegrationsDisabledDialog.js b/src/components/views/dialogs/IntegrationsDisabledDialog.js index dd7a51420e..1e2ff09196 100644 --- a/src/components/views/dialogs/IntegrationsDisabledDialog.js +++ b/src/components/views/dialogs/IntegrationsDisabledDialog.js @@ -16,11 +16,11 @@ limitations under the License. import React from 'react'; import PropTypes from 'prop-types'; -import {_t} from "../../../languageHandler"; +import { _t } from "../../../languageHandler"; import * as sdk from "../../../index"; import dis from '../../../dispatcher/dispatcher'; -import {Action} from "../../../dispatcher/actions"; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { Action } from "../../../dispatcher/actions"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; @replaceableComponent("views.dialogs.IntegrationsDisabledDialog") export default class IntegrationsDisabledDialog extends React.Component { diff --git a/src/components/views/dialogs/IntegrationsImpossibleDialog.js b/src/components/views/dialogs/IntegrationsImpossibleDialog.js index e14d40aaef..2cf9daa7ea 100644 --- a/src/components/views/dialogs/IntegrationsImpossibleDialog.js +++ b/src/components/views/dialogs/IntegrationsImpossibleDialog.js @@ -16,10 +16,10 @@ limitations under the License. import React from 'react'; import PropTypes from 'prop-types'; -import {_t} from "../../../languageHandler"; +import { _t } from "../../../languageHandler"; import SdkConfig from "../../../SdkConfig"; import * as sdk from "../../../index"; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; @replaceableComponent("views.dialogs.IntegrationsImpossibleDialog") export default class IntegrationsImpossibleDialog extends React.Component { diff --git a/src/components/views/dialogs/InteractiveAuthDialog.js b/src/components/views/dialogs/InteractiveAuthDialog.js index 28a9bf673a..09da72cab0 100644 --- a/src/components/views/dialogs/InteractiveAuthDialog.js +++ b/src/components/views/dialogs/InteractiveAuthDialog.js @@ -23,9 +23,9 @@ import * as sdk from '../../../index'; import { _t } from '../../../languageHandler'; import AccessibleButton from '../elements/AccessibleButton'; -import {ERROR_USER_CANCELLED} from "../../structures/InteractiveAuth"; -import {SSOAuthEntry} from "../auth/InteractiveAuthEntryComponents"; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { ERROR_USER_CANCELLED } from "../../structures/InteractiveAuth"; +import { SSOAuthEntry } from "../auth/InteractiveAuthEntryComponents"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; @replaceableComponent("views.dialogs.InteractiveAuthDialog") export default class InteractiveAuthDialog extends React.Component { @@ -117,7 +117,7 @@ export default class InteractiveAuthDialog extends React.Component { _onUpdateStagePhase = (newStage, newPhase) => { // We copy the stage and stage phase params into state for title selection in render() - this.setState({uiaStage: newStage, uiaStagePhase: newPhase}); + this.setState({ uiaStage: newStage, uiaStagePhase: newPhase }); }; _onDismissClick = () => { diff --git a/src/components/views/dialogs/InviteDialog.tsx b/src/components/views/dialogs/InviteDialog.tsx index 553c1c544e..d9dcb8fe00 100644 --- a/src/components/views/dialogs/InviteDialog.tsx +++ b/src/components/views/dialogs/InviteDialog.tsx @@ -426,8 +426,8 @@ export default class InviteDialog extends React.PureComponent { - this.setState({consultFirst: ev.target.checked}); - } + this.setState({ consultFirst: ev.target.checked }); + }; public static buildRecents(excludedTargetIds: Set): IRecentUser[] { const rooms = DMRoomMap.shared().getUniqueRoomsWithIndividuals(); // map of userId => js-sdk Room @@ -482,7 +482,7 @@ export default class InviteDialog extends React.PureComponent ({userId: m.member.userId, user: m.member})); + return members.map(m => ({ userId: m.member.userId, user: m.member })); } private shouldAbortAfterInviteError(result: IInviteResult, room: Room): boolean { @@ -623,18 +623,18 @@ export default class InviteDialog extends React.PureComponent { - this.setState({busy: true}); + this.setState({ busy: true }); const client = MatrixClientPeg.get(); const targets = this.convertFilter(); const targetIds = targets.map(t => t.userId); @@ -657,7 +657,7 @@ export default class InviteDialog extends React.PureComponent { const startTime = CountlyAnalytics.getTimestamp(); - this.setState({busy: true}); + this.setState({ busy: true }); this.convertFilter(); const targets = this.convertFilter(); const targetIds = targets.map(t => t.userId); @@ -729,7 +729,7 @@ export default class InviteDialog extends React.PureComponent { - MatrixClientPeg.get().searchUserDirectory({term}).then(async r => { + MatrixClientPeg.get().searchUserDirectory({ term }).then(async r => { if (term !== this.state.filterText) { // Discard the results - we were probably too slow on the server-side to make // these results useful. This is a race we want to avoid because we could overwrite @@ -874,14 +874,14 @@ export default class InviteDialog extends React.PureComponent { console.error("Error searching user directory:"); console.error(e); - this.setState({serverResultsMixin: []}); // clear results because it's moderately fatal + this.setState({ serverResultsMixin: [] }); // clear results because it's moderately fatal }); // Whenever we search the directory, also try to search the identity server. It's // all debounced the same anyways. if (!this.state.canUseIdentityServer) { // The user doesn't have an identity server set - warn them of that. - this.setState({tryingIdentityServer: true}); + this.setState({ tryingIdentityServer: true }); return; } if (term.indexOf('@') > 0 && Email.looksValid(term) && SettingsStore.getValue(UIFeature.IdentityServer)) { @@ -889,7 +889,7 @@ export default class InviteDialog extends React.PureComponent { const term = e.target.value; - this.setState({filterText: term}); + this.setState({ filterText: term }); // Debounce server lookups to reduce spam. We don't clear the existing server // results because they might still be vaguely accurate, likewise for races which @@ -950,11 +950,11 @@ export default class InviteDialog extends React.PureComponent { - this.setState({numRecentsShown: this.state.numRecentsShown + INCREMENT_ROOMS_SHOWN}); + this.setState({ numRecentsShown: this.state.numRecentsShown + INCREMENT_ROOMS_SHOWN }); }; private showMoreSuggestions = () => { - this.setState({numSuggestionsShown: this.state.numSuggestionsShown + INCREMENT_ROOMS_SHOWN}); + this.setState({ numSuggestionsShown: this.state.numSuggestionsShown + INCREMENT_ROOMS_SHOWN }); }; private toggleMember = (member: Member) => { @@ -968,7 +968,7 @@ export default class InviteDialog extends React.PureComponent= 0) { targets.splice(idx, 1); - this.setState({targets}); + this.setState({ targets }); } if (this.editorRef && this.editorRef.current) { @@ -1051,13 +1051,13 @@ export default class InviteDialog extends React.PureComponent { @@ -1076,7 +1076,7 @@ export default class InviteDialog extends React.PureComponent { @@ -1100,7 +1100,7 @@ export default class InviteDialog extends React.PureComponent).", {}, - {userId: () => { + { userId: () => { return ( {userId} ); - }}, + } }, ); } else { helpText = _t( "Start a conversation with someone using their name or username (like ).", {}, - {userId: () => { + { userId: () => { return ( {userId} ); - }}, + } }, ); } @@ -1320,7 +1320,7 @@ export default class InviteDialog extends React.PureComponenthere", - {communityName}, { + { communityName }, { userId: () => { return (
    -
    +
    ; } else if (this.props.kind === KIND_INVITE) { const room = MatrixClientPeg.get()?.getRoom(this.props.roomId); const isSpace = SettingsStore.getValue("feature_spaces") && room?.isSpaceRoom(); diff --git a/src/components/views/dialogs/KeySignatureUploadFailedDialog.js b/src/components/views/dialogs/KeySignatureUploadFailedDialog.js index bcb4d4f9b9..22487af17c 100644 --- a/src/components/views/dialogs/KeySignatureUploadFailedDialog.js +++ b/src/components/views/dialogs/KeySignatureUploadFailedDialog.js @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import React, {useState, useCallback, useRef} from 'react'; +import React, { useState, useCallback, useRef } from 'react'; import * as sdk from '../../../index'; import { _t } from '../../../languageHandler'; import SdkConfig from '../../../SdkConfig'; diff --git a/src/components/views/dialogs/LogoutDialog.js b/src/components/views/dialogs/LogoutDialog.js index 7bced46d43..bd9411358b 100644 --- a/src/components/views/dialogs/LogoutDialog.js +++ b/src/components/views/dialogs/LogoutDialog.js @@ -22,7 +22,7 @@ import dis from '../../../dispatcher/dispatcher'; import { _t } from '../../../languageHandler'; import { MatrixClientPeg } from '../../../MatrixClientPeg'; import RestoreKeyBackupDialog from './security/RestoreKeyBackupDialog'; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; @replaceableComponent("views.dialogs.LogoutDialog") export default class LogoutDialog extends React.Component { @@ -85,7 +85,7 @@ export default class LogoutDialog extends React.Component { _onFinished(confirmed) { if (confirmed) { - dis.dispatch({action: 'logout'}); + dis.dispatch({ action: 'logout' }); } // close dialog this.props.onFinished(); @@ -112,7 +112,7 @@ export default class LogoutDialog extends React.Component { } _onLogoutConfirm() { - dis.dispatch({action: 'logout'}); + dis.dispatch({ action: 'logout' }); // close dialog this.props.onFinished(); diff --git a/src/components/views/dialogs/ManualDeviceKeyVerificationDialog.js b/src/components/views/dialogs/ManualDeviceKeyVerificationDialog.js index 3151edd796..4387108fac 100644 --- a/src/components/views/dialogs/ManualDeviceKeyVerificationDialog.js +++ b/src/components/views/dialogs/ManualDeviceKeyVerificationDialog.js @@ -20,11 +20,11 @@ limitations under the License. import React from 'react'; import PropTypes from 'prop-types'; -import {MatrixClientPeg} from '../../../MatrixClientPeg'; +import { MatrixClientPeg } from '../../../MatrixClientPeg'; import * as sdk from '../../../index'; import * as FormattingUtils from '../../../utils/FormattingUtils'; import { _t } from '../../../languageHandler'; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; @replaceableComponent("views.dialogs.ManualDeviceKeyVerificationDialog") export default class ManualDeviceKeyVerificationDialog extends React.Component { diff --git a/src/components/views/dialogs/MessageEditHistoryDialog.js b/src/components/views/dialogs/MessageEditHistoryDialog.js index 64d66fe833..b9225f5932 100644 --- a/src/components/views/dialogs/MessageEditHistoryDialog.js +++ b/src/components/views/dialogs/MessageEditHistoryDialog.js @@ -16,12 +16,12 @@ limitations under the License. import React from 'react'; import PropTypes from 'prop-types'; -import {MatrixClientPeg} from "../../../MatrixClientPeg"; +import { MatrixClientPeg } from "../../../MatrixClientPeg"; import { _t } from '../../../languageHandler'; import * as sdk from "../../../index"; -import {wantsDateSeparator} from '../../../DateUtils'; +import { wantsDateSeparator } from '../../../DateUtils'; import SettingsStore from '../../../settings/SettingsStore'; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; @replaceableComponent("views.dialogs.MessageEditHistoryDialog") export default class MessageEditHistoryDialog extends React.PureComponent { @@ -46,7 +46,7 @@ export default class MessageEditHistoryDialog extends React.PureComponent { // bail out on backwards as we only paginate in one direction return false; } - const opts = {from: this.state.nextBatch}; + const opts = { from: this.state.nextBatch }; const roomId = this.props.mxEvent.getRoomId(); const eventId = this.props.mxEvent.getId(); const client = MatrixClientPeg.get(); @@ -62,7 +62,7 @@ export default class MessageEditHistoryDialog extends React.PureComponent { if (error.errcode) { console.error("fetching /relations failed with error", error); } - this.setState({error}, () => reject(error)); + this.setState({ error }, () => reject(error)); return promise; } @@ -131,7 +131,7 @@ export default class MessageEditHistoryDialog extends React.PureComponent { render() { let content; if (this.state.error) { - const {error} = this.state; + const { error } = this.state; if (error.errcode === "M_UNRECOGNIZED") { content = (

    {_t("Your homeserver doesn't seem to support this feature.")} diff --git a/src/components/views/dialogs/ModalWidgetDialog.tsx b/src/components/views/dialogs/ModalWidgetDialog.tsx index df2ed6b335..6bc84b66b4 100644 --- a/src/components/views/dialogs/ModalWidgetDialog.tsx +++ b/src/components/views/dialogs/ModalWidgetDialog.tsx @@ -33,13 +33,13 @@ import { WidgetApiFromWidgetAction, WidgetKind, } from "matrix-widget-api"; -import {StopGapWidgetDriver} from "../../../stores/widgets/StopGapWidgetDriver"; -import {MatrixClientPeg} from "../../../MatrixClientPeg"; -import {OwnProfileStore} from "../../../stores/OwnProfileStore"; +import { StopGapWidgetDriver } from "../../../stores/widgets/StopGapWidgetDriver"; +import { MatrixClientPeg } from "../../../MatrixClientPeg"; +import { OwnProfileStore } from "../../../stores/OwnProfileStore"; import { arrayFastClone } from "../../../utils/arrays"; import { ElementWidget } from "../../../stores/widgets/StopGapWidget"; -import {replaceableComponent} from "../../../utils/replaceableComponent"; -import {ELEMENT_CLIENT_ID} from "../../../identifiers"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; +import { ELEMENT_CLIENT_ID } from "../../../identifiers"; import SettingsStore from "../../../settings/SettingsStore"; interface IProps { @@ -81,7 +81,7 @@ export default class ModalWidgetDialog extends React.PureComponent) => { this.props.onFinished(true, ev.detail.data); - } + }; private onButtonEnableToggle = (ev: CustomEvent) => { ev.preventDefault(); const isClose = ev.detail.data.button === BuiltInModalButtonID.Close; if (isClose || !this.possibleButtons.includes(ev.detail.data.button)) { return this.state.messaging.transport.reply(ev.detail, { - error: {message: "Invalid button"}, + error: { message: "Invalid button" }, } as IWidgetApiErrorResponseData); } @@ -122,7 +122,7 @@ export default class ModalWidgetDialog extends React.PureComponent = ({onFinished}) => { +const RegistrationEmailPromptDialog: React.FC = ({ onFinished }) => { const [email, setEmail] = useState(""); const fieldRef = useRef(); diff --git a/src/components/views/dialogs/ReportEventDialog.tsx b/src/components/views/dialogs/ReportEventDialog.tsx index 8271239f7f..81a7d569fe 100644 --- a/src/components/views/dialogs/ReportEventDialog.tsx +++ b/src/components/views/dialogs/ReportEventDialog.tsx @@ -19,11 +19,11 @@ import * as sdk from '../../../index'; import { _t } from '../../../languageHandler'; import { ensureDMExists } from "../../../createRoom"; import { IDialogProps } from "./IDialogProps"; -import {MatrixEvent} from "matrix-js-sdk/src/models/event"; -import {MatrixClientPeg} from "../../../MatrixClientPeg"; +import { MatrixEvent } from "matrix-js-sdk/src/models/event"; +import { MatrixClientPeg } from "../../../MatrixClientPeg"; import SdkConfig from '../../../SdkConfig'; import Markdown from '../../../Markdown'; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; import SettingsStore from "../../../settings/SettingsStore"; import StyledRadioButton from "../elements/StyledRadioButton"; @@ -40,7 +40,6 @@ interface IState { nature?: EXTENDED_NATURE; } - const MODERATED_BY_STATE_EVENT_TYPE = [ "org.matrix.msc3215.room.moderation.moderated_by", /** @@ -75,7 +74,7 @@ type Moderation = { moderationRoomId: string; // The id of the bot in charge of forwarding abuse reports to the moderation room. moderationBotUserId: string; -} +}; /* * A dialog for reporting an event. * @@ -162,13 +161,13 @@ export default class ReportEventDialog extends React.Component { } // The user has written down a freeform description of the abuse. - private onReasonChange = ({target: {value: reason}}): void => { + private onReasonChange = ({ target: { value: reason } }): void => { this.setState({ reason }); }; // The user has clicked on a nature. private onNatureChosen = (e: React.FormEvent): void => { - this.setState({ nature: e.currentTarget.value as EXTENDED_NATURE}); + this.setState({ nature: e.currentTarget.value as EXTENDED_NATURE }); }; // The user has clicked "cancel". diff --git a/src/components/views/dialogs/RoomSettingsDialog.tsx b/src/components/views/dialogs/RoomSettingsDialog.tsx index 303f17c342..005222a94e 100644 --- a/src/components/views/dialogs/RoomSettingsDialog.tsx +++ b/src/components/views/dialogs/RoomSettingsDialog.tsx @@ -16,8 +16,8 @@ limitations under the License. */ import React from 'react'; -import TabbedView, {Tab} from "../../structures/TabbedView"; -import {_t, _td} from "../../../languageHandler"; +import TabbedView, { Tab } from "../../structures/TabbedView"; +import { _t, _td } from "../../../languageHandler"; import AdvancedRoomSettingsTab from "../settings/tabs/room/AdvancedRoomSettingsTab"; import RolesRoomSettingsTab from "../settings/tabs/room/RolesRoomSettingsTab"; import GeneralRoomSettingsTab from "../settings/tabs/room/GeneralRoomSettingsTab"; @@ -25,11 +25,11 @@ import SecurityRoomSettingsTab from "../settings/tabs/room/SecurityRoomSettingsT import NotificationSettingsTab from "../settings/tabs/room/NotificationSettingsTab"; import BridgeSettingsTab from "../settings/tabs/room/BridgeSettingsTab"; import * as sdk from "../../../index"; -import {MatrixClientPeg} from "../../../MatrixClientPeg"; +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 { UIFeature } from "../../../settings/UIFeature"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; export const ROOM_GENERAL_TAB = "ROOM_GENERAL_TAB"; export const ROOM_SECURITY_TAB = "ROOM_SECURITY_TAB"; @@ -127,7 +127,7 @@ export default class RoomSettingsDialog extends React.Component { className='mx_RoomSettingsDialog' hasCancel={true} onFinished={this.props.onFinished} - title={_t("Room Settings - %(roomName)s", {roomName})} + title={_t("Room Settings - %(roomName)s", { roomName })} >

    { @@ -44,7 +44,7 @@ export default class RoomUpgradeDialog extends React.Component { }; _onUpgradeClick = () => { - this.setState({busy: true}); + this.setState({ busy: true }); MatrixClientPeg.get().upgradeRoom(this.props.room.roomId, this._targetVersion).then(() => { this.props.onFinished(true); }).catch((err) => { @@ -54,7 +54,7 @@ export default class RoomUpgradeDialog extends React.Component { description: ((err && err.message) ? err.message : _t("The room upgrade could not be completed")), }); }).finally(() => { - this.setState({busy: false}); + this.setState({ busy: false }); }); }; @@ -70,7 +70,7 @@ export default class RoomUpgradeDialog extends React.Component { buttons = { - this.props.onFinished({continue: true, invite: this.state.isPrivate && this.state.inviteUsersToNewRoom}); + this.props.onFinished({ continue: true, invite: this.state.isPrivate && this.state.inviteUsersToNewRoom }); }; _onCancel = () => { - this.props.onFinished({continue: false, invite: false}); + this.props.onFinished({ continue: false, invite: false }); }; _onInviteUsersToggle = (newVal) => { - this.setState({inviteUsersToNewRoom: newVal}); + this.setState({ inviteUsersToNewRoom: newVal }); }; _openBugReportDialog = (e) => { @@ -86,7 +86,7 @@ export default class RoomUpgradeWarningDialog extends React.Component {

    {_t( "This usually only affects how the room is processed on the server. If you're " + - "having problems with your %(brand)s, please report a bug.", {brand}, + "having problems with your %(brand)s, please report a bug.", { brand }, )}

    ); diff --git a/src/components/views/dialogs/ServerOfflineDialog.tsx b/src/components/views/dialogs/ServerOfflineDialog.tsx index 52ff056907..ebf32e9131 100644 --- a/src/components/views/dialogs/ServerOfflineDialog.tsx +++ b/src/components/views/dialogs/ServerOfflineDialog.tsx @@ -28,7 +28,7 @@ import AccessibleButton from "../elements/AccessibleButton"; import { UPDATE_EVENT } from "../../../stores/AsyncStore"; import { MatrixClientPeg } from "../../../MatrixClientPeg"; import { IDialogProps } from "./IDialogProps"; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; interface IProps extends IDialogProps { } @@ -85,7 +85,7 @@ export default class ServerOfflineDialog extends React.PureComponent { {entries}
    - ) + ); }); } @@ -108,7 +108,7 @@ export default class ServerOfflineDialog extends React.PureComponent { "Below are some of the most likely reasons.", )}

      -
    • {_t("The server (%(serverName)s) took too long to respond.", {serverName})}
    • +
    • {_t("The server (%(serverName)s) took too long to respond.", { serverName })}
    • {_t("Your firewall or anti-virus is blocking the request.")}
    • {_t("A browser extension is preventing the request.")}
    • {_t("The server is offline.")}
    • diff --git a/src/components/views/dialogs/ServerPickerDialog.tsx b/src/components/views/dialogs/ServerPickerDialog.tsx index 11fef9e75d..8dafd8a2bc 100644 --- a/src/components/views/dialogs/ServerPickerDialog.tsx +++ b/src/components/views/dialogs/ServerPickerDialog.tsx @@ -14,10 +14,10 @@ See the License for the specific language governing permissions and limitations under the License. */ -import React, {createRef} from "react"; -import {AutoDiscovery} from "matrix-js-sdk/src/autodiscovery"; +import React, { createRef } from "react"; +import { AutoDiscovery } from "matrix-js-sdk/src/autodiscovery"; -import AutoDiscoveryUtils, {ValidatedServerConfig} from "../../../utils/AutoDiscoveryUtils"; +import AutoDiscoveryUtils, { ValidatedServerConfig } from "../../../utils/AutoDiscoveryUtils"; import BaseDialog from './BaseDialog'; import { _t } from '../../../languageHandler'; import AccessibleButton from "../elements/AccessibleButton"; @@ -25,8 +25,8 @@ import SdkConfig from "../../../SdkConfig"; import Field from "../elements/Field"; import StyledRadioButton from "../elements/StyledRadioButton"; import TextWithTooltip from "../elements/TextWithTooltip"; -import withValidation, {IFieldState} from "../elements/Validation"; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import withValidation, { IFieldState } from "../elements/Validation"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; interface IProps { title?: string; diff --git a/src/components/views/dialogs/SeshatResetDialog.tsx b/src/components/views/dialogs/SeshatResetDialog.tsx index 63654ca949..863157ec08 100644 --- a/src/components/views/dialogs/SeshatResetDialog.tsx +++ b/src/components/views/dialogs/SeshatResetDialog.tsx @@ -15,13 +15,13 @@ limitations under the License. */ import React from 'react'; -import {_t} from "../../../languageHandler"; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { _t } from "../../../languageHandler"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; import BaseDialog from "./BaseDialog"; import DialogButtons from "../elements/DialogButtons"; -import {IDialogProps} from "./IDialogProps"; +import { IDialogProps } from "./IDialogProps"; @replaceableComponent("views.dialogs.SeshatResetDialog") export default class SeshatResetDialog extends React.PureComponent { diff --git a/src/components/views/dialogs/SessionRestoreErrorDialog.js b/src/components/views/dialogs/SessionRestoreErrorDialog.js index 43e73a2f83..b7037d1f4f 100644 --- a/src/components/views/dialogs/SessionRestoreErrorDialog.js +++ b/src/components/views/dialogs/SessionRestoreErrorDialog.js @@ -22,7 +22,7 @@ import * as sdk from '../../../index'; import SdkConfig from '../../../SdkConfig'; import Modal from '../../../Modal'; import { _t } from '../../../languageHandler'; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; @replaceableComponent("views.dialogs.SessionRestoreErrorDialog") export default class SessionRestoreErrorDialog extends React.Component { diff --git a/src/components/views/dialogs/SetEmailDialog.js b/src/components/views/dialogs/SetEmailDialog.js index 0f8f410a6a..3dad3821fb 100644 --- a/src/components/views/dialogs/SetEmailDialog.js +++ b/src/components/views/dialogs/SetEmailDialog.js @@ -22,8 +22,7 @@ import * as Email from '../../../email'; import AddThreepid from '../../../AddThreepid'; import { _t } from '../../../languageHandler'; import Modal from '../../../Modal'; -import {replaceableComponent} from "../../../utils/replaceableComponent"; - +import { replaceableComponent } from "../../../utils/replaceableComponent"; /* * Prompt the user to set an email address. @@ -71,14 +70,14 @@ export default class SetEmailDialog extends React.Component { onFinished: this.onEmailDialogFinished, }); }, (err) => { - this.setState({emailBusy: false}); + this.setState({ emailBusy: false }); console.error("Unable to add email address " + emailAddress + " " + err); Modal.createTrackedDialog('Unable to add email address', '', ErrorDialog, { title: _t("Unable to add email address"), description: ((err && err.message) ? err.message : _t("Operation failed")), }); }); - this.setState({emailBusy: true}); + this.setState({ emailBusy: true }); }; onCancelled = () => { @@ -89,7 +88,7 @@ export default class SetEmailDialog extends React.Component { if (ok) { this.verifyEmailAddress(); } else { - this.setState({emailBusy: false}); + this.setState({ emailBusy: false }); } }; @@ -97,7 +96,7 @@ export default class SetEmailDialog extends React.Component { this._addThreepid.checkEmailLinkClicked().then(() => { this.props.onFinished(true); }, (err) => { - this.setState({emailBusy: false}); + this.setState({ emailBusy: false }); if (err.errcode == 'M_THREEPID_AUTH_FAILED') { const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog"); const message = _t("Unable to verify email address.") + " " + diff --git a/src/components/views/dialogs/ShareDialog.tsx b/src/components/views/dialogs/ShareDialog.tsx index df1206a4f0..fb43db1a25 100644 --- a/src/components/views/dialogs/ShareDialog.tsx +++ b/src/components/views/dialogs/ShareDialog.tsx @@ -17,24 +17,24 @@ limitations under the License. import * as React from 'react'; import * as PropTypes from 'prop-types'; -import {Room} from "matrix-js-sdk/src/models/room"; -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 { Room } from "matrix-js-sdk/src/models/room"; +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"; +import { RoomPermalinkCreator, makeGroupPermalink, makeUserPermalink } from "../../../utils/permalinks/Permalinks"; import * as ContextMenu from "../../structures/ContextMenu"; -import {toRightOf} from "../../structures/ContextMenu"; -import {copyPlaintext, selectText} from "../../../utils/strings"; +import { toRightOf } from "../../structures/ContextMenu"; +import { copyPlaintext, selectText } from "../../../utils/strings"; import StyledCheckbox from '../elements/StyledCheckbox'; import AccessibleTooltipButton from '../elements/AccessibleTooltipButton'; import { IDialogProps } from "./IDialogProps"; import SettingsStore from "../../../settings/SettingsStore"; -import {UIFeature} from "../../../settings/UIFeature"; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { UIFeature } from "../../../settings/UIFeature"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; const socials = [ { @@ -120,7 +120,7 @@ export default class ShareDialog extends React.PureComponent { const successful = await copyPlaintext(this.getUrl()); const buttonRect = target.getBoundingClientRect(); const GenericTextContextMenu = sdk.getComponent('context_menus.GenericTextContextMenu'); - const {close} = ContextMenu.createMenu(GenericTextContextMenu, { + const { close } = ContextMenu.createMenu(GenericTextContextMenu, { ...toRightOf(buttonRect, 2), message: successful ? _t('Copied!') : _t('Failed to copy'), }); diff --git a/src/components/views/dialogs/SlashCommandHelpDialog.js b/src/components/views/dialogs/SlashCommandHelpDialog.js index 5b4148e939..608f81a612 100644 --- a/src/components/views/dialogs/SlashCommandHelpDialog.js +++ b/src/components/views/dialogs/SlashCommandHelpDialog.js @@ -15,11 +15,11 @@ limitations under the License. */ import React from 'react'; -import {_t} from "../../../languageHandler"; -import {CommandCategories, Commands} from "../../../SlashCommands"; +import { _t } from "../../../languageHandler"; +import { CommandCategories, Commands } from "../../../SlashCommands"; import * as sdk from "../../../index"; -export default ({onFinished}) => { +export default ({ onFinished }) => { const InfoDialog = sdk.getComponent('dialogs.InfoDialog'); const categories = {}; diff --git a/src/components/views/dialogs/SpaceSettingsDialog.tsx b/src/components/views/dialogs/SpaceSettingsDialog.tsx index 5e0cd96740..fe836ebc5c 100644 --- a/src/components/views/dialogs/SpaceSettingsDialog.tsx +++ b/src/components/views/dialogs/SpaceSettingsDialog.tsx @@ -42,7 +42,7 @@ interface IProps extends IDialogProps { } const SpaceSettingsDialog: React.FC = ({ matrixClient: cli, space, onFinished }) => { - useDispatcher(defaultDispatcher, ({action, ...params}) => { + useDispatcher(defaultDispatcher, ({ action, ...params }) => { if (action === "after_leave_room" && params.room_id === space.roomId) { onFinished(false); } diff --git a/src/components/views/dialogs/StorageEvictedDialog.js b/src/components/views/dialogs/StorageEvictedDialog.js index 1e17ab1738..c25866b64d 100644 --- a/src/components/views/dialogs/StorageEvictedDialog.js +++ b/src/components/views/dialogs/StorageEvictedDialog.js @@ -20,7 +20,7 @@ import * as sdk from '../../../index'; import SdkConfig from '../../../SdkConfig'; import Modal from '../../../Modal'; import { _t } from '../../../languageHandler'; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; @replaceableComponent("views.dialogs.StorageEvictedDialog") export default class StorageEvictedDialog extends React.Component { diff --git a/src/components/views/dialogs/TabbedIntegrationManagerDialog.js b/src/components/views/dialogs/TabbedIntegrationManagerDialog.js index 618b0b4347..3a3cc31cf8 100644 --- a/src/components/views/dialogs/TabbedIntegrationManagerDialog.js +++ b/src/components/views/dialogs/TabbedIntegrationManagerDialog.js @@ -16,13 +16,13 @@ limitations under the License. import React from 'react'; import PropTypes from 'prop-types'; -import {IntegrationManagers} from "../../../integrations/IntegrationManagers"; -import {Room} from "matrix-js-sdk/src/models/room"; +import { IntegrationManagers } from "../../../integrations/IntegrationManagers"; +import { Room } from "matrix-js-sdk/src/models/room"; import * as sdk from '../../../index'; -import {dialogTermsInteractionCallback, TermsNotSignedError} from "../../../Terms"; +import { dialogTermsInteractionCallback, TermsNotSignedError } from "../../../Terms"; import classNames from 'classnames'; import * as ScalarMessaging from "../../../ScalarMessaging"; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; @replaceableComponent("views.dialogs.TabbedIntegrationManagerDialog") export default class TabbedIntegrationManagerDialog extends React.Component { @@ -63,11 +63,11 @@ export default class TabbedIntegrationManagerDialog extends React.Component { }; } - componentDidMount(): void { + componentDidMount() { this.openManager(0, true); } - openManager = async (i: number, force = false) => { + openManager = async (i, force = false) => { if (i === this.state.currentIndex && !force) return; const manager = this.state.managers[i]; diff --git a/src/components/views/dialogs/TermsDialog.tsx b/src/components/views/dialogs/TermsDialog.tsx index ace5316323..818ac4b9e4 100644 --- a/src/components/views/dialogs/TermsDialog.tsx +++ b/src/components/views/dialogs/TermsDialog.tsx @@ -19,7 +19,7 @@ import React from 'react'; import * as sdk from '../../../index'; import { _t, pickBestLanguage } from '../../../languageHandler'; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; import { SERVICE_TYPES } from "matrix-js-sdk/src/service-types"; interface ITermsCheckboxProps { @@ -31,7 +31,7 @@ interface ITermsCheckboxProps { class TermsCheckbox extends React.PureComponent { private onChange = (ev: React.FormEvent): void => { this.props.onChange(this.props.url, ev.currentTarget.checked); - } + }; render() { return { this.props.onFinished(false); - } + }; private onNextClick = (): void => { this.props.onFinished(true, Object.keys(this.state.agreedUrls).filter((url) => this.state.agreedUrls[url])); - } + }; private nameForServiceType(serviceType: SERVICE_TYPES, host: string): JSX.Element { switch (serviceType) { @@ -114,7 +114,7 @@ export default class TermsDialog extends React.PureComponent = ({device, user, onFinished}) => { +const UntrustedDeviceDialog: React.FC = ({ device, user, onFinished }) => { let askToVerifyText; let newSessionText; @@ -39,7 +39,7 @@ const UntrustedDeviceDialog: React.FC = ({device, user, onFinished}) => askToVerifyText = _t("Verify your other session using one of the options below."); } else { newSessionText = _t("%(name)s (%(userId)s) signed in to a new session without verifying it:", - {name: user.displayName, userId: user.userId}); + { name: user.displayName, userId: user.userId }); askToVerifyText = _t("Ask this user to verify their session, or manually verify it below."); } diff --git a/src/components/views/dialogs/UploadConfirmDialog.tsx b/src/components/views/dialogs/UploadConfirmDialog.tsx index 7f6bcd27d1..5024880c1c 100644 --- a/src/components/views/dialogs/UploadConfirmDialog.tsx +++ b/src/components/views/dialogs/UploadConfirmDialog.tsx @@ -36,7 +36,7 @@ export default class UploadConfirmDialog extends React.Component { static defaultProps = { totalFiles: 1, - } + }; constructor(props) { super(props); @@ -56,15 +56,15 @@ export default class UploadConfirmDialog extends React.Component { private onCancelClick = () => { this.props.onFinished(false); - } + }; private onUploadClick = () => { this.props.onFinished(true); - } + }; private onUploadAllClick = () => { this.props.onFinished(true, true); - } + }; render() { const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog'); diff --git a/src/components/views/dialogs/UploadFailureDialog.js b/src/components/views/dialogs/UploadFailureDialog.js index d220d6c684..d26b83d0d6 100644 --- a/src/components/views/dialogs/UploadFailureDialog.js +++ b/src/components/views/dialogs/UploadFailureDialog.js @@ -21,7 +21,7 @@ import PropTypes from 'prop-types'; import * as sdk from '../../../index'; import { _t } from '../../../languageHandler'; import ContentMessages from '../../../ContentMessages'; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; /* * Tells the user about files we know cannot be uploaded before we even try uploading diff --git a/src/components/views/dialogs/UserSettingsDialog.tsx b/src/components/views/dialogs/UserSettingsDialog.tsx index 1a62a4ff22..2878a07d35 100644 --- a/src/components/views/dialogs/UserSettingsDialog.tsx +++ b/src/components/views/dialogs/UserSettingsDialog.tsx @@ -16,8 +16,8 @@ limitations under the License. */ import React from 'react'; -import TabbedView, {Tab} from "../../structures/TabbedView"; -import {_t, _td} from "../../../languageHandler"; +import TabbedView, { Tab } from "../../structures/TabbedView"; +import { _t, _td } from "../../../languageHandler"; import GeneralUserSettingsTab from "../settings/tabs/user/GeneralUserSettingsTab"; import SettingsStore, { CallbackFn } from "../../../settings/SettingsStore"; import LabsUserSettingsTab from "../settings/tabs/user/LabsUserSettingsTab"; @@ -31,8 +31,8 @@ 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 { UIFeature } from "../../../settings/UIFeature"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; export enum UserTab { General = "USER_GENERAL_TAB", @@ -78,8 +78,8 @@ export default class UserSettingsDialog extends React.Component private mjolnirChanged: CallbackFn = (settingName, roomId, atLevel, newValue) => { // We can cheat because we know what levels a feature is tracked at, and how it is tracked - this.setState({mjolnirEnabled: newValue}); - } + this.setState({ mjolnirEnabled: newValue }); + }; _getTabs() { const tabs = []; diff --git a/src/components/views/dialogs/VerificationRequestDialog.js b/src/components/views/dialogs/VerificationRequestDialog.js index 9281275e6a..bf5d63b895 100644 --- a/src/components/views/dialogs/VerificationRequestDialog.js +++ b/src/components/views/dialogs/VerificationRequestDialog.js @@ -16,10 +16,10 @@ limitations under the License. import React from 'react'; import PropTypes from 'prop-types'; -import {MatrixClientPeg} from '../../../MatrixClientPeg'; +import { MatrixClientPeg } from '../../../MatrixClientPeg'; import * as sdk from '../../../index'; import { _t } from '../../../languageHandler'; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; @replaceableComponent("views.dialogs.VerificationRequestDialog") export default class VerificationRequestDialog extends React.Component { @@ -37,7 +37,7 @@ export default class VerificationRequestDialog extends React.Component { this.state.verificationRequest = this.props.verificationRequest; } else if (this.props.verificationRequestPromise) { this.props.verificationRequestPromise.then(r => { - this.setState({verificationRequest: r}); + this.setState({ verificationRequest: r }); }); } } diff --git a/src/components/views/dialogs/WidgetCapabilitiesPromptDialog.tsx b/src/components/views/dialogs/WidgetCapabilitiesPromptDialog.tsx index 70fe7fe5e3..638d5cde93 100644 --- a/src/components/views/dialogs/WidgetCapabilitiesPromptDialog.tsx +++ b/src/components/views/dialogs/WidgetCapabilitiesPromptDialog.tsx @@ -29,7 +29,7 @@ import StyledCheckbox from "../elements/StyledCheckbox"; import DialogButtons from "../elements/DialogButtons"; import LabelledToggleSwitch from "../elements/LabelledToggleSwitch"; import { CapabilityText } from "../../../widgets/CapabilityText"; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; export function getRememberedCapabilitiesForWidget(widget: Widget): Capability[] { return JSON.parse(localStorage.getItem(`widget_${widget.id}_approved_caps`) || "[]"); @@ -77,11 +77,11 @@ export default class WidgetCapabilitiesPromptDialog extends React.PureComponent< private onToggle = (capability: Capability) => { const newStates = objectShallowClone(this.state.booleanStates); newStates[capability] = !newStates[capability]; - this.setState({booleanStates: newStates}); + this.setState({ booleanStates: newStates }); }; private onRememberSelectionChange = (newVal: boolean) => { - this.setState({rememberSelection: newVal}); + this.setState({ rememberSelection: newVal }); }; private onSubmit = async (ev) => { @@ -98,7 +98,7 @@ export default class WidgetCapabilitiesPromptDialog extends React.PureComponent< if (this.state.rememberSelection) { setRememberedCapabilitiesForWidget(this.props.widget, approved); } - this.props.onFinished({approved}); + this.props.onFinished({ approved }); } public render() { diff --git a/src/components/views/dialogs/WidgetOpenIDPermissionsDialog.js b/src/components/views/dialogs/WidgetOpenIDPermissionsDialog.js index f77661c54e..2130d0e4ef 100644 --- a/src/components/views/dialogs/WidgetOpenIDPermissionsDialog.js +++ b/src/components/views/dialogs/WidgetOpenIDPermissionsDialog.js @@ -16,12 +16,12 @@ limitations under the License. import React from 'react'; import PropTypes from 'prop-types'; -import {_t} from "../../../languageHandler"; +import { _t } from "../../../languageHandler"; import * as sdk from "../../../index"; import LabelledToggleSwitch from "../elements/LabelledToggleSwitch"; -import {Widget} from "matrix-widget-api"; -import {OIDCState, WidgetPermissionStore} from "../../../stores/widgets/WidgetPermissionStore"; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { Widget } from "matrix-widget-api"; +import { OIDCState, WidgetPermissionStore } from "../../../stores/widgets/WidgetPermissionStore"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; @replaceableComponent("views.dialogs.WidgetOpenIDPermissionsDialog") export default class WidgetOpenIDPermissionsDialog extends React.Component { @@ -62,7 +62,7 @@ export default class WidgetOpenIDPermissionsDialog extends React.Component { } _onRememberSelectionChange = (newVal) => { - this.setState({rememberSelection: newVal}); + this.setState({ rememberSelection: newVal }); }; render() { diff --git a/src/components/views/dialogs/security/AccessSecretStorageDialog.tsx b/src/components/views/dialogs/security/AccessSecretStorageDialog.tsx index e09b39f4c7..d614cc0956 100644 --- a/src/components/views/dialogs/security/AccessSecretStorageDialog.tsx +++ b/src/components/views/dialogs/security/AccessSecretStorageDialog.tsx @@ -14,18 +14,18 @@ See the License for the specific language governing permissions and limitations under the License. */ -import {debounce} from "lodash"; +import { debounce } from "lodash"; import classNames from 'classnames'; -import React, {ChangeEvent, FormEvent} from 'react'; -import {ISecretStorageKeyInfo} from "matrix-js-sdk/src"; +import React, { ChangeEvent, FormEvent } from 'react'; +import { ISecretStorageKeyInfo } from "matrix-js-sdk/src"; import * as sdk from '../../../../index'; -import {MatrixClientPeg} from '../../../../MatrixClientPeg'; +import { MatrixClientPeg } from '../../../../MatrixClientPeg'; import Field from '../../elements/Field'; import AccessibleButton from '../../elements/AccessibleButton'; -import {_t} from '../../../../languageHandler'; -import {IDialogProps} from "../IDialogProps"; -import {accessSecretStorage} from "../../../../SecurityManager"; +import { _t } from '../../../../languageHandler'; +import { IDialogProps } from "../IDialogProps"; +import { accessSecretStorage } from "../../../../SecurityManager"; import Modal from "../../../../Modal"; // Maximum acceptable size of a key file. It's 59 characters including the spaces we encode, @@ -75,7 +75,7 @@ export default class AccessSecretStorageDialog extends React.PureComponent { if (this.state.resetting) { - this.setState({resetting: false}); + this.setState({ resetting: false }); } this.props.onFinished(false); }; @@ -169,7 +169,7 @@ export default class AccessSecretStorageDialog extends React.PureComponent { this.fileUpload.current.click(); - } + }; private onPassPhraseNext = async (ev: FormEvent) => { ev.preventDefault(); @@ -210,7 +210,7 @@ export default class AccessSecretStorageDialog extends React.PureComponent) => { ev.preventDefault(); - this.setState({resetting: true}); + this.setState({ resetting: true }); }; private onConfirmResetAllClick = async () => { @@ -231,7 +231,7 @@ export default class AccessSecretStorageDialog extends React.PureComponent { // XXX: Making this an import breaks the app. const InteractiveAuthDialog = sdk.getComponent("views.dialogs.InteractiveAuthDialog"); - const {finished} = Modal.createTrackedDialog( + const { finished } = Modal.createTrackedDialog( 'Cross-signing keys dialog', '', InteractiveAuthDialog, { title: _t("Setting up keys"), diff --git a/src/components/views/dialogs/security/CreateCrossSigningDialog.tsx b/src/components/views/dialogs/security/CreateCrossSigningDialog.tsx index 840390f6fb..84dcfede4a 100644 --- a/src/components/views/dialogs/security/CreateCrossSigningDialog.tsx +++ b/src/components/views/dialogs/security/CreateCrossSigningDialog.tsx @@ -16,6 +16,8 @@ limitations under the License. */ import React from 'react'; +import { CrossSigningKeys } from 'matrix-js-sdk/src/client'; + import { MatrixClientPeg } from '../../../../MatrixClientPeg'; import { _t } from '../../../../languageHandler'; import Modal from '../../../../Modal'; @@ -71,7 +73,7 @@ export default class CreateCrossSigningDialog extends React.PureComponent { try { - await MatrixClientPeg.get().uploadDeviceSigningKeys(null, {}); + await MatrixClientPeg.get().uploadDeviceSigningKeys(null, {} as CrossSigningKeys); // We should never get here: the server should always require // UI auth to upload device signing keys. If we do, we upload // no keys which would be a no-op. @@ -139,7 +141,7 @@ export default class CreateCrossSigningDialog extends React.PureComponent => { this.setState({ @@ -163,11 +165,11 @@ export default class CreateCrossSigningDialog extends React.PureComponent { this.props.onFinished(false); - } + }; render() { let content; diff --git a/src/components/views/dialogs/security/RestoreKeyBackupDialog.js b/src/components/views/dialogs/security/RestoreKeyBackupDialog.js index 4ac15ab5a3..5f21033d29 100644 --- a/src/components/views/dialogs/security/RestoreKeyBackupDialog.js +++ b/src/components/views/dialogs/security/RestoreKeyBackupDialog.js @@ -18,7 +18,7 @@ limitations under the License. import React from 'react'; import PropTypes from 'prop-types'; import * as sdk from '../../../../index'; -import {MatrixClientPeg} from '../../../../MatrixClientPeg'; +import { MatrixClientPeg } from '../../../../MatrixClientPeg'; import { MatrixClient } from 'matrix-js-sdk/src/client'; import { _t } from '../../../../languageHandler'; import { accessSecretStorage } from '../../../../SecurityManager'; @@ -327,11 +327,11 @@ export default class RestoreKeyBackupDialog extends React.PureComponent { if (this.state.recoverInfo.total > this.state.recoverInfo.imported) { failedToDecrypt =

      {_t( "Failed to decrypt %(failedCount)s sessions!", - {failedCount: this.state.recoverInfo.total - this.state.recoverInfo.imported}, + { failedCount: this.state.recoverInfo.total - this.state.recoverInfo.imported }, )}

      ; } content =
      -

      {_t("Successfully restored %(sessionCount)s keys", {sessionCount: this.state.recoverInfo.imported})}

      +

      {_t("Successfully restored %(sessionCount)s keys", { sessionCount: this.state.recoverInfo.imported })}

      {failedToDecrypt} { - this.setState({icon: iconFromPhase(this.store.phase)}); + this.setState({ icon: iconFromPhase(this.store.phase) }); }; public render() { diff --git a/src/components/views/directory/NetworkDropdown.tsx b/src/components/views/directory/NetworkDropdown.tsx index c805ee42e7..c57aa7bccc 100644 --- a/src/components/views/directory/NetworkDropdown.tsx +++ b/src/components/views/directory/NetworkDropdown.tsx @@ -186,10 +186,10 @@ const NetworkDropdown = ({ onOptionChange, protocols = {}, selectedServerName, s }); } - protocolsList.forEach(({instances=[]}) => { + protocolsList.forEach(({ instances=[] }) => { [...instances].sort((b, a) => { return compare(a.desc, b.desc); - }).forEach(({desc, instance_id: instanceId}) => { + }).forEach(({ desc, instance_id: instanceId }) => { entries.push( { closeMenu(); - const {finished} = Modal.createTrackedDialog("Network Dropdown", "Remove server", QuestionDialog, { - title: _t("Are you sure?"), - description: _t("Are you sure you want to remove %(serverName)s", { - serverName: server, - }, { - b: serverName => { serverName }, - }), - button: _t("Remove"), - fixedWidth: false, - }, "mx_NetworkDropdown_dialog"); + const { finished } = Modal.createTrackedDialog( + "Network Dropdown", "Remove server", QuestionDialog, + { + title: _t("Are you sure?"), + description: _t("Are you sure you want to remove %(serverName)s", { + serverName: server, + }, { + b: serverName => { serverName }, + }), + button: _t("Remove"), + fixedWidth: false, + }, + "mx_NetworkDropdown_dialog", + ); const [ok] = await finished; if (!ok) return; diff --git a/src/components/views/elements/AccessibleButton.tsx b/src/components/views/elements/AccessibleButton.tsx index 05bcca24b2..997bbcb9c2 100644 --- a/src/components/views/elements/AccessibleButton.tsx +++ b/src/components/views/elements/AccessibleButton.tsx @@ -16,7 +16,7 @@ import React from 'react'; -import {Key} from '../../../Keyboard'; +import { Key } from '../../../Keyboard'; import classnames from 'classnames'; export type ButtonEvent = React.MouseEvent | React.KeyboardEvent; diff --git a/src/components/views/elements/AccessibleTooltipButton.tsx b/src/components/views/elements/AccessibleTooltipButton.tsx index a1743da475..8ac41ad1a2 100644 --- a/src/components/views/elements/AccessibleTooltipButton.tsx +++ b/src/components/views/elements/AccessibleTooltipButton.tsx @@ -19,8 +19,8 @@ import React from 'react'; import classNames from 'classnames'; import AccessibleButton from "./AccessibleButton"; -import Tooltip, {Alignment} from './Tooltip'; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import Tooltip, { Alignment } from './Tooltip'; +import { replaceableComponent } from "../../../utils/replaceableComponent"; interface ITooltipProps extends React.ComponentProps { title: string; @@ -67,7 +67,7 @@ export default class AccessibleTooltipButton extends React.PureComponent { ev.stopPropagation(); Analytics.trackEvent('Action Button', 'click', this.props.action); - dis.dispatch({action: this.props.action}); + dis.dispatch({ action: this.props.action }); }; _onMouseEnter = () => { - if (this.props.tooltip) this.setState({showTooltip: true}); + if (this.props.tooltip) this.setState({ showTooltip: true }); if (this.props.mouseOverAction) { - dis.dispatch({action: this.props.mouseOverAction}); + dis.dispatch({ action: this.props.mouseOverAction }); } }; _onMouseLeave = () => { - this.setState({showTooltip: false}); + this.setState({ showTooltip: false }); }; render() { - const TintableSvg = sdk.getComponent("elements.TintableSvg"); - let tooltip; if (this.state.showTooltip) { const Tooltip = sdk.getComponent("elements.Tooltip"); @@ -71,7 +69,7 @@ export default class ActionButton extends React.Component { } const icon = this.props.iconPath ? - () : + () : undefined; const classNames = ["mx_RoleButton"]; diff --git a/src/components/views/elements/AddressSelector.js b/src/components/views/elements/AddressSelector.js index 33b2906870..b7c9124438 100644 --- a/src/components/views/elements/AddressSelector.js +++ b/src/components/views/elements/AddressSelector.js @@ -20,7 +20,7 @@ import PropTypes from 'prop-types'; import * as sdk from '../../../index'; import classNames from 'classnames'; import { UserAddressType } from '../../../UserAddress'; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; @replaceableComponent("views.elements.AddressSelector") export default class AddressSelector extends React.Component { diff --git a/src/components/views/elements/AddressTile.js b/src/components/views/elements/AddressTile.js index f8fa294b71..ca85d73a11 100644 --- a/src/components/views/elements/AddressTile.js +++ b/src/components/views/elements/AddressTile.js @@ -53,7 +53,6 @@ export default class AddressTile extends React.Component { } const BaseAvatar = sdk.getComponent('avatars.BaseAvatar'); - const TintableSvg = sdk.getComponent("elements.TintableSvg"); const nameClasses = classNames({ "mx_AddressTile_name": true, @@ -124,7 +123,7 @@ export default class AddressTile extends React.Component { if (this.props.canDismiss) { dismiss = (
      - +
      ); } diff --git a/src/components/views/elements/AppPermission.js b/src/components/views/elements/AppPermission.js index 65e40ef19a..152d3c6b95 100644 --- a/src/components/views/elements/AppPermission.js +++ b/src/components/views/elements/AppPermission.js @@ -23,8 +23,8 @@ import * as sdk from '../../../index'; import { _t } from '../../../languageHandler'; import SdkConfig from '../../../SdkConfig'; import WidgetUtils from "../../../utils/WidgetUtils"; -import {MatrixClientPeg} from "../../../MatrixClientPeg"; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { MatrixClientPeg } from "../../../MatrixClientPeg"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; @replaceableComponent("views.elements.AppPermission") export default class AppPermission extends React.Component { @@ -115,9 +115,9 @@ export default class AppPermission extends React.Component { // Due to i18n limitations, we can't dedupe the code for variables in these two messages. const warning = this.state.isWrapped ? _t("Using this widget may share data with %(widgetDomain)s & your Integration Manager.", - {widgetDomain: this.state.widgetDomain}, {helpIcon: () => warningTooltip}) + { widgetDomain: this.state.widgetDomain }, { helpIcon: () => warningTooltip }) : _t("Using this widget may share data with %(widgetDomain)s.", - {widgetDomain: this.state.widgetDomain}, {helpIcon: () => warningTooltip}); + { widgetDomain: this.state.widgetDomain }, { helpIcon: () => warningTooltip }); const encryptionWarning = this.props.isRoomEncrypted ? _t("Widgets do not use message encryption.") : null; diff --git a/src/components/views/elements/AppTile.js b/src/components/views/elements/AppTile.js index 3fa43ee9c2..f5d3aaf9eb 100644 --- a/src/components/views/elements/AppTile.js +++ b/src/components/views/elements/AppTile.js @@ -18,9 +18,9 @@ limitations under the License. */ import url from 'url'; -import React, {createRef} from 'react'; +import React, { createRef } from 'react'; import PropTypes from 'prop-types'; -import {MatrixClientPeg} from '../../../MatrixClientPeg'; +import { MatrixClientPeg } from '../../../MatrixClientPeg'; import AccessibleButton from './AccessibleButton'; import { _t } from '../../../languageHandler'; import AppPermission from './AppPermission'; @@ -30,15 +30,15 @@ import dis from '../../../dispatcher/dispatcher'; import ActiveWidgetStore from '../../../stores/ActiveWidgetStore'; import classNames from 'classnames'; import SettingsStore from "../../../settings/SettingsStore"; -import {aboveLeftOf, ContextMenuButton} from "../../structures/ContextMenu"; -import PersistedElement, {getPersistKey} from "./PersistedElement"; -import {WidgetType} from "../../../widgets/WidgetType"; -import {StopGapWidget} from "../../../stores/widgets/StopGapWidget"; -import {ElementWidgetActions} from "../../../stores/widgets/ElementWidgetActions"; -import {MatrixCapabilities} from "matrix-widget-api"; +import { aboveLeftOf, ContextMenuButton } from "../../structures/ContextMenu"; +import PersistedElement, { getPersistKey } from "./PersistedElement"; +import { WidgetType } from "../../../widgets/WidgetType"; +import { StopGapWidget } from "../../../stores/widgets/StopGapWidget"; +import { ElementWidgetActions } from "../../../stores/widgets/ElementWidgetActions"; +import { MatrixCapabilities } from "matrix-widget-api"; import RoomWidgetContextMenu from "../context_menus/WidgetContextMenu"; import WidgetAvatar from "../avatars/WidgetAvatar"; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; @replaceableComponent("views.elements.AppTile") export default class AppTile extends React.Component { @@ -164,7 +164,7 @@ export default class AppTile extends React.Component { _startWidget() { this._sgWidget.prepare().then(() => { - this.setState({initialising: false}); + this.setState({ initialising: false }); }); } @@ -213,17 +213,17 @@ export default class AppTile extends React.Component { } if (WidgetType.JITSI.matches(this.props.app.type)) { - dis.dispatch({action: 'hangup_conference'}); + dis.dispatch({ action: 'hangup_conference' }); } // Delete the widget from the persisted store for good measure. PersistedElement.destroyElement(this._persistKey); - if (this._sgWidget) this._sgWidget.stop({forceDestroy: true}); + if (this._sgWidget) this._sgWidget.stop({ forceDestroy: true }); } _onWidgetPrepared = () => { - this.setState({loading: false}); + this.setState({ loading: false }); }; _onWidgetReady = () => { @@ -237,7 +237,7 @@ export default class AppTile extends React.Component { switch (payload.action) { case 'm.sticker': if (this._sgWidget.widgetApi.hasCapability(MatrixCapabilities.StickerSending)) { - dis.dispatch({action: 'post_sticker_message', data: payload.data}); + dis.dispatch({ action: 'post_sticker_message', data: payload.data }); } else { console.warn('Ignoring sticker message. Invalid capability'); } @@ -253,7 +253,7 @@ export default class AppTile extends React.Component { current[this.props.app.eventId] = true; const level = SettingsStore.firstSupportedLevel("allowedWidgets"); SettingsStore.setValue("allowedWidgets", roomId, level, current).then(() => { - this.setState({hasPermissionToLoad: true}); + this.setState({ hasPermissionToLoad: true }); // Fetch a token for the integration manager, now that we're allowed to this._startWidget(); @@ -313,7 +313,7 @@ export default class AppTile extends React.Component { // Using Object.assign workaround as the following opens in a new window instead of a new tab. // window.open(this._getPopoutUrl(), '_blank', 'noopener=yes'); Object.assign(document.createElement('a'), - { target: '_blank', href: this._sgWidget.popoutUrl, rel: 'noreferrer noopener'}).click(); + { target: '_blank', href: this._sgWidget.popoutUrl, rel: 'noreferrer noopener' }).click(); }; _onContextMenuClick = () => { @@ -416,11 +416,11 @@ export default class AppTile extends React.Component { let appTileClasses; if (this.props.miniMode) { - appTileClasses = {mx_AppTile_mini: true}; + appTileClasses = { mx_AppTile_mini: true }; } else if (this.props.fullWidth) { - appTileClasses = {mx_AppTileFullWidth: true}; + appTileClasses = { mx_AppTileFullWidth: true }; } else { - appTileClasses = {mx_AppTile: true}; + appTileClasses = { mx_AppTile: true }; } appTileClasses = classNames(appTileClasses); @@ -443,7 +443,7 @@ export default class AppTile extends React.Component {
      { this.props.showMenubar &&
      - + { this.props.showTitle && this._getTileTitle() } diff --git a/src/components/views/elements/DesktopBuildsNotice.tsx b/src/components/views/elements/DesktopBuildsNotice.tsx index 426554f31e..c97a9b6cef 100644 --- a/src/components/views/elements/DesktopBuildsNotice.tsx +++ b/src/components/views/elements/DesktopBuildsNotice.tsx @@ -22,7 +22,6 @@ import dis from "../../../dispatcher/dispatcher"; import { Action } from "../../../dispatcher/actions"; import { UserTab } from "../dialogs/UserSettingsDialog"; - export enum WarningKind { Files, Search, @@ -33,7 +32,7 @@ interface IProps { kind: WarningKind; } -export default function DesktopBuildsNotice({isRoomEncrypted, kind}: IProps) { +export default function DesktopBuildsNotice({ isRoomEncrypted, kind }: IProps) { if (!isRoomEncrypted) return null; if (EventIndexPeg.get()) return null; @@ -53,7 +52,7 @@ export default function DesktopBuildsNotice({isRoomEncrypted, kind}: IProps) { ; } - const {desktopBuilds, brand} = SdkConfig.get(); + const { desktopBuilds, brand } = SdkConfig.get(); let text = null; let logo = null; @@ -74,10 +73,10 @@ export default function DesktopBuildsNotice({isRoomEncrypted, kind}: IProps) { } else { switch (kind) { case WarningKind.Files: - text = _t("This version of %(brand)s does not support viewing some encrypted files", {brand}); + text = _t("This version of %(brand)s does not support viewing some encrypted files", { brand }); break; case WarningKind.Search: - text = _t("This version of %(brand)s does not support searching encrypted messages", {brand}); + text = _t("This version of %(brand)s does not support searching encrypted messages", { brand }); break; } } diff --git a/src/components/views/elements/DesktopCapturerSourcePicker.tsx b/src/components/views/elements/DesktopCapturerSourcePicker.tsx index 2d066a7ed7..8f9b847f4f 100644 --- a/src/components/views/elements/DesktopCapturerSourcePicker.tsx +++ b/src/components/views/elements/DesktopCapturerSourcePicker.tsx @@ -16,10 +16,10 @@ limitations under the License. import React from 'react'; import { _t } from '../../../languageHandler'; -import BaseDialog from "..//dialogs/BaseDialog" +import BaseDialog from "..//dialogs/BaseDialog"; import AccessibleButton from './AccessibleButton'; -import {getDesktopCapturerSources} from "matrix-js-sdk/src/webrtc/call"; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { getDesktopCapturerSources } from "matrix-js-sdk/src/webrtc/call"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; export interface DesktopCapturerSource { id: string; @@ -44,7 +44,7 @@ export class ExistingSource extends React.Component onClick = (ev) => { this.props.onSelect(this.props.source); - } + }; render() { return ( @@ -108,19 +108,19 @@ export default class DesktopCapturerSourcePicker extends React.Component< onSelect = (source) => { this.props.onFinished(source); - } + }; onScreensClick = (ev) => { - this.setState({selectedTab: Tabs.Screens}); - } + this.setState({ selectedTab: Tabs.Screens }); + }; onWindowsClick = (ev) => { - this.setState({selectedTab: Tabs.Windows}); - } + this.setState({ selectedTab: Tabs.Windows }); + }; onCloseClick = (ev) => { this.props.onFinished(null); - } + }; render() { let sources; diff --git a/src/components/views/elements/DialogButtons.js b/src/components/views/elements/DialogButtons.js index dcb1cee077..af68260563 100644 --- a/src/components/views/elements/DialogButtons.js +++ b/src/components/views/elements/DialogButtons.js @@ -19,7 +19,7 @@ limitations under the License. import React from "react"; import PropTypes from "prop-types"; import { _t } from '../../../languageHandler'; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; /** * Basic container for buttons in modal dialogs. diff --git a/src/components/views/elements/DirectorySearchBox.js b/src/components/views/elements/DirectorySearchBox.js index 6447bb3cd8..45270ada64 100644 --- a/src/components/views/elements/DirectorySearchBox.js +++ b/src/components/views/elements/DirectorySearchBox.js @@ -18,7 +18,7 @@ import React from 'react'; import PropTypes from 'prop-types'; import * as sdk from '../../../index'; import { _t } from '../../../languageHandler'; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; @replaceableComponent("views.elements.DirectorySearchBox") export default class DirectorySearchBox extends React.Component { @@ -42,7 +42,7 @@ export default class DirectorySearchBox extends React.Component { } _onClearClick() { - this.setState({value: ''}); + this.setState({ value: '' }); if (this.input) { this.input.focus(); @@ -55,7 +55,7 @@ export default class DirectorySearchBox extends React.Component { _onChange(ev) { if (!this.input) return; - this.setState({value: ev.target.value}); + this.setState({ value: ev.target.value }); if (this.props.onChange) { this.props.onChange(ev.target.value); diff --git a/src/components/views/elements/Draggable.tsx b/src/components/views/elements/Draggable.tsx index 6032721a48..03dccadcb9 100644 --- a/src/components/views/elements/Draggable.tsx +++ b/src/components/views/elements/Draggable.tsx @@ -15,7 +15,7 @@ limitations under the License. */ import React from 'react'; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; interface IProps { className: string; diff --git a/src/components/views/elements/Dropdown.js b/src/components/views/elements/Dropdown.js index 981c0becc0..f95247e9ae 100644 --- a/src/components/views/elements/Dropdown.js +++ b/src/components/views/elements/Dropdown.js @@ -16,13 +16,13 @@ See the License for the specific language governing permissions and limitations under the License. */ -import React, {createRef} from 'react'; +import React, { createRef } from 'react'; import PropTypes from 'prop-types'; import classnames from 'classnames'; import AccessibleButton from './AccessibleButton'; import { _t } from '../../../languageHandler'; -import {Key} from "../../../Keyboard"; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { Key } from "../../../Keyboard"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; class MenuOption extends React.Component { constructor(props) { diff --git a/src/components/views/elements/EditableText.js b/src/components/views/elements/EditableText.js index 7c38ac1777..6dbc8b8771 100644 --- a/src/components/views/elements/EditableText.js +++ b/src/components/views/elements/EditableText.js @@ -15,10 +15,10 @@ See the License for the specific language governing permissions and limitations under the License. */ -import React, {createRef} from 'react'; +import React, { createRef } from 'react'; import PropTypes from 'prop-types'; -import {Key} from "../../../Keyboard"; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { Key } from "../../../Keyboard"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; @replaceableComponent("views.elements.EditableText") export default class EditableText extends React.Component { @@ -209,7 +209,7 @@ export default class EditableText extends React.Component { }; render() { - const {className, editable, initialValue, label, labelClassName} = this.props; + const { className, editable, initialValue, label, labelClassName } = this.props; let editableEl; if (!editable || (this.state.phase === EditableText.Phases.Display && diff --git a/src/components/views/elements/EditableTextContainer.js b/src/components/views/elements/EditableTextContainer.js index e925220089..5778446355 100644 --- a/src/components/views/elements/EditableTextContainer.js +++ b/src/components/views/elements/EditableTextContainer.js @@ -17,7 +17,7 @@ limitations under the License. import React from 'react'; import PropTypes from 'prop-types'; import * as sdk from '../../../index'; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; /** * A component which wraps an EditableText, with a spinner while updates take @@ -50,7 +50,7 @@ export default class EditableTextContainer extends React.Component { return; } - this.setState({busy: true}); + this.setState({ busy: true }); this.props.getInitialValue().then( (result) => { @@ -144,7 +144,6 @@ EditableTextContainer.propTypes = { blurToSubmit: PropTypes.bool, }; - EditableTextContainer.defaultProps = { initialValue: "", placeholder: "", diff --git a/src/components/views/elements/EffectsOverlay.tsx b/src/components/views/elements/EffectsOverlay.tsx index 00d9d147f1..9e6833696f 100644 --- a/src/components/views/elements/EffectsOverlay.tsx +++ b/src/components/views/elements/EffectsOverlay.tsx @@ -17,7 +17,7 @@ import React, { FunctionComponent, useEffect, useRef } from 'react'; import dis from '../../../dispatcher/dispatcher'; import ICanvasEffect from '../../../effects/ICanvasEffect'; -import { CHAT_EFFECTS } from '../../../effects' +import { CHAT_EFFECTS } from '../../../effects'; import UIStore, { UI_EVENTS } from "../../../stores/UIStore"; interface IProps { @@ -32,7 +32,7 @@ const EffectsOverlay: FunctionComponent = ({ roomWidth }) => { if (!name) return null; let effect: ICanvasEffect | null = effectsRef.current[name] || null; if (effect === null) { - const options = CHAT_EFFECTS.find((e) => e.command === name)?.options + const options = CHAT_EFFECTS.find((e) => e.command === name)?.options; try { const { default: Effect } = await import(`../../../effects/${name}`); effect = new Effect(options); @@ -56,7 +56,7 @@ const EffectsOverlay: FunctionComponent = ({ roomWidth }) => { const effect = payload.action.substr(actionPrefix.length); lazyLoadEffectModule(effect).then((module) => module?.start(canvasRef.current)); } - } + }; const dispatcherRef = dis.register(onAction); const canvas = canvasRef.current; canvas.height = UIStore.instance.windowHeight; @@ -89,7 +89,7 @@ const EffectsOverlay: FunctionComponent = ({ roomWidth }) => { right: 0, }} /> - ) -} + ); +}; export default EffectsOverlay; diff --git a/src/components/views/elements/ErrorBoundary.js b/src/components/views/elements/ErrorBoundary.tsx similarity index 80% rename from src/components/views/elements/ErrorBoundary.js rename to src/components/views/elements/ErrorBoundary.tsx index 9037287f49..f967b8c594 100644 --- a/src/components/views/elements/ErrorBoundary.js +++ b/src/components/views/elements/ErrorBoundary.tsx @@ -1,5 +1,5 @@ /* -Copyright 2019 The Matrix.org Foundation C.I.C. +Copyright 2019 - 2021 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. @@ -14,21 +14,27 @@ See the License for the specific language governing permissions and limitations under the License. */ -import React from 'react'; -import * as sdk from '../../../index'; +import React, { ErrorInfo } from 'react'; + import { _t } from '../../../languageHandler'; -import {MatrixClientPeg} from '../../../MatrixClientPeg'; +import { MatrixClientPeg } from '../../../MatrixClientPeg'; import PlatformPeg from '../../../PlatformPeg'; import Modal from '../../../Modal'; import SdkConfig from "../../../SdkConfig"; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; +import BugReportDialog from '../dialogs/BugReportDialog'; +import AccessibleButton from './AccessibleButton'; + +interface IState { + error: Error; +} /** * This error boundary component can be used to wrap large content areas and * catch exceptions during rendering in the component tree below them. */ @replaceableComponent("views.elements.ErrorBoundary") -export default class ErrorBoundary extends React.PureComponent { +export default class ErrorBoundary extends React.PureComponent<{}, IState> { constructor(props) { super(props); @@ -37,13 +43,13 @@ export default class ErrorBoundary extends React.PureComponent { }; } - static getDerivedStateFromError(error) { + static getDerivedStateFromError(error: Error): Partial { // Side effects are not permitted here, so we only update the state so // that the next render shows an error message. return { error }; } - componentDidCatch(error, { componentStack }) { + componentDidCatch(error: Error, { componentStack }: ErrorInfo): void { // Browser consoles are better at formatting output when native errors are passed // in their own `console.error` invocation. console.error(error); @@ -53,7 +59,7 @@ export default class ErrorBoundary extends React.PureComponent { ); } - _onClearCacheAndReload = () => { + private onClearCacheAndReload = (): void => { if (!PlatformPeg.get()) return; MatrixClientPeg.get().stopClient(); @@ -62,11 +68,7 @@ export default class ErrorBoundary extends React.PureComponent { }); }; - _onBugReport = () => { - const BugReportDialog = sdk.getComponent("dialogs.BugReportDialog"); - if (!BugReportDialog) { - return; - } + private onBugReport = (): void => { Modal.createTrackedDialog('Bug Report Dialog', '', BugReportDialog, { label: 'react-soft-crash', }); @@ -74,7 +76,6 @@ export default class ErrorBoundary extends React.PureComponent { render() { if (this.state.error) { - const AccessibleButton = sdk.getComponent('elements.AccessibleButton'); const newIssueUrl = "https://github.com/vector-im/element-web/issues/new"; let bugReportSection; @@ -95,7 +96,7 @@ export default class ErrorBoundary extends React.PureComponent { "the rooms or groups you have visited and the usernames of " + "other users. They do not contain messages.", )}

      - + {_t("Submit debug logs")} ; @@ -105,7 +106,7 @@ export default class ErrorBoundary extends React.PureComponent {

      {_t("Something went wrong!")}

      { bugReportSection } - + {_t("Clear cache and reload")}
      diff --git a/src/components/views/elements/EventListSummary.tsx b/src/components/views/elements/EventListSummary.tsx index 665263d19c..1dee38f205 100644 --- a/src/components/views/elements/EventListSummary.tsx +++ b/src/components/views/elements/EventListSummary.tsx @@ -14,13 +14,13 @@ See the License for the specific language governing permissions and limitations under the License. */ -import React, {ReactChildren, useEffect} from 'react'; -import {MatrixEvent} from "matrix-js-sdk/src/models/event"; -import {RoomMember} from "matrix-js-sdk/src/models/room-member"; +import React, { ReactNode, useEffect } from 'react'; +import { MatrixEvent } from "matrix-js-sdk/src/models/event"; +import { RoomMember } from "matrix-js-sdk/src/models/room-member"; import MemberAvatar from '../avatars/MemberAvatar'; import { _t } from '../../../languageHandler'; -import {useStateToggle} from "../../../hooks/useStateToggle"; +import { useStateToggle } from "../../../hooks/useStateToggle"; import AccessibleButton from "./AccessibleButton"; interface IProps { @@ -31,11 +31,11 @@ interface IProps { // Whether or not to begin with state.expanded=true startExpanded?: boolean, // The list of room members for which to show avatars next to the summary - summaryMembers?: RoomMember[], + summaryMembers?: RoomMember[]; // The text to show as the summary of this event list - summaryText?: string, + summaryText?: string; // An array of EventTiles to render when expanded - children: ReactChildren, + children: ReactNode[]; // Called when the event list expansion is toggled onToggle?(): void; } diff --git a/src/components/views/elements/EventTilePreview.tsx b/src/components/views/elements/EventTilePreview.tsx index 332f3ac333..68a70133e6 100644 --- a/src/components/views/elements/EventTilePreview.tsx +++ b/src/components/views/elements/EventTilePreview.tsx @@ -73,7 +73,7 @@ export default class EventTilePreview extends React.Component { }; } - private fakeEvent({message}: IState) { + private fakeEvent({ message }: IState) { // Fake it till we make it /* eslint-disable quote-props */ const rawEvent = { diff --git a/src/components/views/elements/Field.tsx b/src/components/views/elements/Field.tsx index 1373c2df0e..297044e422 100644 --- a/src/components/views/elements/Field.tsx +++ b/src/components/views/elements/Field.tsx @@ -14,11 +14,11 @@ See the License for the specific language governing permissions and limitations under the License. */ -import React, {InputHTMLAttributes, SelectHTMLAttributes, TextareaHTMLAttributes} from 'react'; +import React, { InputHTMLAttributes, SelectHTMLAttributes, TextareaHTMLAttributes } from 'react'; import classNames from 'classnames'; import * as sdk from '../../../index'; -import {debounce} from "lodash"; -import {IFieldState, IValidationResult} from "./Validation"; +import { debounce } from "lodash"; +import { IFieldState, IValidationResult } from "./Validation"; // Invoke validation from user input (when typing, etc.) at most once every N ms. const VALIDATION_THROTTLE_MS = 200; @@ -222,7 +222,7 @@ export default class Field extends React.PureComponent { /* eslint @typescript-eslint/no-unused-vars: ["error", { "ignoreRestSiblings": true }] */ const { element, prefixComponent, postfixComponent, className, onValidate, children, tooltipContent, forceValidity, tooltipClassName, list, validateOnBlur, validateOnChange, validateOnFocus, - ...inputProps} = this.props; + ...inputProps } = this.props; // Set some defaults for the element const ref = input => this.input = input; @@ -234,7 +234,7 @@ export default class Field extends React.PureComponent { inputProps.onBlur = this.onBlur; // Appease typescript's inference - const inputProps_ = {...inputProps, ref, list}; + const inputProps_ = { ...inputProps, ref, list }; const fieldInput = React.createElement(this.props.element, inputProps_, children); diff --git a/src/components/views/elements/Flair.js b/src/components/views/elements/Flair.js index 23858b860d..873d65d5bd 100644 --- a/src/components/views/elements/Flair.js +++ b/src/components/views/elements/Flair.js @@ -19,9 +19,8 @@ import PropTypes from 'prop-types'; import FlairStore from '../../../stores/FlairStore'; import dis from '../../../dispatcher/dispatcher'; import MatrixClientContext from "../../../contexts/MatrixClientContext"; -import {replaceableComponent} from "../../../utils/replaceableComponent"; -import {mediaFromMxc} from "../../../customisations/Media"; - +import { replaceableComponent } from "../../../utils/replaceableComponent"; +import { mediaFromMxc } from "../../../customisations/Media"; class FlairAvatar extends React.Component { constructor() { diff --git a/src/components/views/elements/IRCTimelineProfileResizer.tsx b/src/components/views/elements/IRCTimelineProfileResizer.tsx index cd1ccf2fc4..13e8ae2ae2 100644 --- a/src/components/views/elements/IRCTimelineProfileResizer.tsx +++ b/src/components/views/elements/IRCTimelineProfileResizer.tsx @@ -16,9 +16,9 @@ limitations under the License. import React from 'react'; import SettingsStore from "../../../settings/SettingsStore"; -import Draggable, {ILocationState} from './Draggable'; +import Draggable, { ILocationState } from './Draggable'; import { SettingLevel } from "../../../settings/SettingLevel"; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; interface IProps { // Current room diff --git a/src/components/views/elements/ImageView.tsx b/src/components/views/elements/ImageView.tsx index 4812817359..74538d2fa9 100644 --- a/src/components/views/elements/ImageView.tsx +++ b/src/components/views/elements/ImageView.tsx @@ -30,7 +30,7 @@ import SettingsStore from "../../../settings/SettingsStore"; import { formatFullDate } from "../../../DateUtils"; import dis from '../../../dispatcher/dispatcher'; import { replaceableComponent } from "../../../utils/replaceableComponent"; -import { RoomPermalinkCreator } from "../../../utils/permalinks/Permalinks" +import { RoomPermalinkCreator } from "../../../utils/permalinks/Permalinks"; import { MatrixEvent } from "matrix-js-sdk/src/models/event"; import { normalizeWheelEvent } from "../../../utils/Mouse"; @@ -116,7 +116,7 @@ export default class ImageView extends React.Component { private recalculateZoom = () => { this.setZoomAndRotation(); - } + }; private setZoomAndRotation = (inputRotation?: number) => { const image = this.image.current; @@ -158,7 +158,7 @@ export default class ImageView extends React.Component { rotation: rotation, zoom: zoom, }); - } + }; private zoom(delta: number) { const newZoom = this.state.zoom + delta; diff --git a/src/components/views/elements/InfoTooltip.tsx b/src/components/views/elements/InfoTooltip.tsx index d49090dbae..de82c5daeb 100644 --- a/src/components/views/elements/InfoTooltip.tsx +++ b/src/components/views/elements/InfoTooltip.tsx @@ -18,9 +18,9 @@ limitations under the License. import React from 'react'; import classNames from 'classnames'; -import Tooltip, {Alignment} from './Tooltip'; -import {_t} from "../../../languageHandler"; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import Tooltip, { Alignment } from './Tooltip'; +import { _t } from "../../../languageHandler"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; interface ITooltipProps { tooltip?: React.ReactNode; @@ -53,7 +53,7 @@ export default class InfoTooltip extends React.PureComponent { static defaultProps = { w: 16, h: 16, - } + }; render() { return (
      {this.props.children} diff --git a/src/components/views/elements/InviteReason.tsx b/src/components/views/elements/InviteReason.tsx index ddce7552ed..d684f61859 100644 --- a/src/components/views/elements/InviteReason.tsx +++ b/src/components/views/elements/InviteReason.tsx @@ -42,7 +42,7 @@ export default class InviteReason extends React.PureComponent { this.setState({ hidden: false, }); - } + }; render() { const classes = classNames({ diff --git a/src/components/views/elements/LabelledToggleSwitch.tsx b/src/components/views/elements/LabelledToggleSwitch.tsx index d97b698fd8..14853ea117 100644 --- a/src/components/views/elements/LabelledToggleSwitch.tsx +++ b/src/components/views/elements/LabelledToggleSwitch.tsx @@ -17,7 +17,7 @@ limitations under the License. import React from "react"; import ToggleSwitch from "./ToggleSwitch"; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; interface IProps { // The value for the toggle switch diff --git a/src/components/views/elements/LanguageDropdown.js b/src/components/views/elements/LanguageDropdown.js index 9420061a74..3f17a78629 100644 --- a/src/components/views/elements/LanguageDropdown.js +++ b/src/components/views/elements/LanguageDropdown.js @@ -22,7 +22,7 @@ import * as sdk from '../../../index'; import * as languageHandler from '../../../languageHandler'; import SettingsStore from "../../../settings/SettingsStore"; import { _t } from "../../../languageHandler"; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; function languageMatchesSearchQuery(query, language) { if (language.label.toUpperCase().includes(query.toUpperCase())) return true; @@ -49,9 +49,9 @@ export default class LanguageDropdown extends React.Component { if (a.label > b.label) return 1; return 0; }); - this.setState({langs}); + this.setState({ langs }); }).catch(() => { - this.setState({langs: ['en']}); + this.setState({ langs: ['en'] }); }); if (!this.props.value) { diff --git a/src/components/views/elements/LazyRenderList.js b/src/components/views/elements/LazyRenderList.js index f2c8148cd2..070d9bcc8d 100644 --- a/src/components/views/elements/LazyRenderList.js +++ b/src/components/views/elements/LazyRenderList.js @@ -16,7 +16,7 @@ limitations under the License. import React from "react"; import PropTypes from 'prop-types'; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; class ItemRange { constructor(topCount, renderCount, bottomCount) { @@ -72,13 +72,13 @@ export default class LazyRenderList extends React.Component { // only update render Range if the list has shrunk/grown and we need to adjust padding OR // if the new range + overflowMargin isn't contained by the old anymore if (listHasChangedSize || !state.renderRange || !state.renderRange.contains(intersectRange)) { - return {renderRange}; + return { renderRange }; } return null; } static getVisibleRangeFromProps(props) { - const {items, itemHeight, scrollTop, height} = props; + const { items, itemHeight, scrollTop, height } = props; const length = items ? items.length : 0; const topCount = Math.min(Math.max(0, Math.floor(scrollTop / itemHeight)), length); const itemsAfterTop = length - topCount; @@ -89,9 +89,9 @@ export default class LazyRenderList extends React.Component { } render() { - const {itemHeight, items, renderItem} = this.props; - const {renderRange} = this.state; - const {topCount, renderCount, bottomCount} = renderRange; + const { itemHeight, items, renderItem } = this.props; + const { renderRange } = this.state; + const { topCount, renderCount, bottomCount } = renderRange; const paddingTop = topCount * itemHeight; const paddingBottom = bottomCount * itemHeight; @@ -102,7 +102,7 @@ export default class LazyRenderList extends React.Component { const element = this.props.element || "div"; const elementProps = { - "style": {paddingTop: `${paddingTop}px`, paddingBottom: `${paddingBottom}px`}, + "style": { paddingTop: `${paddingTop}px`, paddingBottom: `${paddingBottom}px` }, "className": this.props.className, }; return React.createElement(element, elementProps, renderedItems.map(renderItem)); diff --git a/src/components/views/elements/MemberEventListSummary.tsx b/src/components/views/elements/MemberEventListSummary.tsx index f10884ce9d..d52462f629 100644 --- a/src/components/views/elements/MemberEventListSummary.tsx +++ b/src/components/views/elements/MemberEventListSummary.tsx @@ -16,7 +16,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import React, { ReactChildren } from 'react'; +import React, { ComponentProps } from 'react'; import { MatrixEvent } from "matrix-js-sdk/src/models/event"; import { RoomMember } from "matrix-js-sdk/src/models/room-member"; @@ -26,21 +26,11 @@ import { isValid3pidInvite } from "../../../RoomInvite"; import EventListSummary from "./EventListSummary"; import { replaceableComponent } from "../../../utils/replaceableComponent"; -interface IProps { - // An array of member events to summarise - events: MatrixEvent[]; +interface IProps extends Omit, "summaryText" | "summaryMembers"> { // The maximum number of names to show in either each summary e.g. 2 would result "A, B and 234 others left" summaryLength?: number; // The maximum number of avatars to display in the summary avatarsMaxLength?: number; - // The minimum number of events needed to trigger summarisation - threshold?: number, - // Whether or not to begin with state.expanded=true - startExpanded?: boolean, - // An array of EventTiles to render when expanded - children: ReactChildren; - // Called when the MELS expansion is toggled - onToggle?(): void, } interface IUserEvents { @@ -66,6 +56,7 @@ enum TransitionType { ChangedName = "changed_name", ChangedAvatar = "changed_avatar", NoChange = "no_change", + ServerAcl = "server_acl", } const SEP = ","; @@ -298,6 +289,12 @@ export default class MemberEventListSummary extends React.Component { ? _t("%(severalUsers)smade no changes %(count)s times", { severalUsers: "", count: repeats }) : _t("%(oneUser)smade no changes %(count)s times", { oneUser: "", count: repeats }); break; + case "server_acl": + res = (userCount > 1) + ? _t("%(severalUsers)schanged the server ACLs %(count)s times", + { severalUsers: "", count: repeats }) + : _t("%(oneUser)schanged the server ACLs %(count)s times", { oneUser: "", count: repeats }); + break; } return res; @@ -324,6 +321,10 @@ export default class MemberEventListSummary extends React.Component { return TransitionType.Invited; } + if (e.mxEvent.getType() === 'm.room.server_acl') { + return TransitionType.ServerAcl; + } + switch (e.mxEvent.getContent().membership) { case 'invite': return TransitionType.Invited; case 'ban': return TransitionType.Banned; @@ -410,19 +411,23 @@ export default class MemberEventListSummary extends React.Component { // Object mapping user IDs to an array of IUserEvents const userEvents: Record = {}; eventsToRender.forEach((e, index) => { - const userId = e.getStateKey(); + const userId = e.getType() === 'm.room.server_acl' ? e.getSender() : e.getStateKey(); // Initialise a user's events if (!userEvents[userId]) { userEvents[userId] = []; } - if (e.target) { + if (e.getType() === 'm.room.server_acl') { + latestUserAvatarMember.set(userId, e.sender); + } else if (e.target) { latestUserAvatarMember.set(userId, e.target); } let displayName = userId; if (e.getType() === 'm.room.third_party_invite') { displayName = e.getContent().display_name; + } else if (e.getType() === 'm.room.server_acl') { + displayName = e.sender.name; } else if (e.target) { displayName = e.target.name; } diff --git a/src/components/views/elements/MiniAvatarUploader.tsx b/src/components/views/elements/MiniAvatarUploader.tsx index 32ef0d4da2..83fc1ebefd 100644 --- a/src/components/views/elements/MiniAvatarUploader.tsx +++ b/src/components/views/elements/MiniAvatarUploader.tsx @@ -14,14 +14,14 @@ See the License for the specific language governing permissions and limitations under the License. */ -import React, {useContext, useRef, useState} from 'react'; -import {EventType} from 'matrix-js-sdk/src/@types/event'; +import React, { useContext, useRef, useState } from 'react'; +import { EventType } from 'matrix-js-sdk/src/@types/event'; import classNames from 'classnames'; import AccessibleButton from "./AccessibleButton"; import Spinner from "./Spinner"; import MatrixClientContext from "../../../contexts/MatrixClientContext"; -import {useTimeout} from "../../../hooks/useTimeout"; +import { useTimeout } from "../../../hooks/useTimeout"; import Analytics from "../../../Analytics"; import CountlyAnalytics from '../../../CountlyAnalytics'; import RoomContext from "../../../contexts/RoomContext"; @@ -52,7 +52,7 @@ const MiniAvatarUploader: React.FC = ({ hasAvatar, hasAvatarLabel, noAva const label = (hasAvatar || busy) ? hasAvatarLabel : noAvatarLabel; - const {room} = useContext(RoomContext); + const { room } = useContext(RoomContext); const canSetAvatar = room?.currentState.maySendStateEvent(EventType.RoomAvatar, cli.getUserId()); if (!canSetAvatar) return { children }; diff --git a/src/components/views/elements/PersistedElement.js b/src/components/views/elements/PersistedElement.js index 701c140a19..22d4bfdd68 100644 --- a/src/components/views/elements/PersistedElement.js +++ b/src/components/views/elements/PersistedElement.js @@ -17,14 +17,14 @@ limitations under the License. import React from 'react'; import ReactDOM from 'react-dom'; import PropTypes from 'prop-types'; -import {throttle} from "lodash"; +import { throttle } from "lodash"; import ResizeObserver from 'resize-observer-polyfill'; import dis from '../../../dispatcher/dispatcher'; import MatrixClientContext from "../../../contexts/MatrixClientContext"; -import {MatrixClientPeg} from "../../../MatrixClientPeg"; -import {isNullOrUndefined} from "matrix-js-sdk/src/utils"; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { MatrixClientPeg } from "../../../MatrixClientPeg"; +import { isNullOrUndefined } from "matrix-js-sdk/src/utils"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; // Shamelessly ripped off Modal.js. There's probably a better way // of doing reusable widgets like dialog boxes & menus where we go and @@ -180,11 +180,11 @@ export default class PersistedElement extends React.Component { width: parentRect.width + 'px', height: parentRect.height + 'px', }); - }, 100, {trailing: true, leading: true}); + }, 100, { trailing: true, leading: true }); render() { return
      ; } } -export const getPersistKey = (appId: string) => 'widget_' + appId; +export const getPersistKey = (appId) => 'widget_' + appId; diff --git a/src/components/views/elements/PersistentApp.js b/src/components/views/elements/PersistentApp.js index 5df373e4fe..763ab63487 100644 --- a/src/components/views/elements/PersistentApp.js +++ b/src/components/views/elements/PersistentApp.js @@ -20,8 +20,8 @@ import RoomViewStore from '../../../stores/RoomViewStore'; import ActiveWidgetStore from '../../../stores/ActiveWidgetStore'; import WidgetUtils from '../../../utils/WidgetUtils'; import * as sdk from '../../../index'; -import {MatrixClientPeg} from '../../../MatrixClientPeg'; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { MatrixClientPeg } from '../../../MatrixClientPeg'; +import { replaceableComponent } from "../../../utils/replaceableComponent"; @replaceableComponent("views.elements.PersistentApp") export default class PersistentApp extends React.Component { diff --git a/src/components/views/elements/Pill.js b/src/components/views/elements/Pill.js index ace41db39d..ba166ccfc6 100644 --- a/src/components/views/elements/Pill.js +++ b/src/components/views/elements/Pill.js @@ -20,14 +20,14 @@ import classNames from 'classnames'; import { Room } from 'matrix-js-sdk/src/models/room'; import { RoomMember } from 'matrix-js-sdk/src/models/room-member'; import PropTypes from 'prop-types'; -import {MatrixClientPeg} from '../../../MatrixClientPeg'; +import { MatrixClientPeg } from '../../../MatrixClientPeg'; import FlairStore from "../../../stores/FlairStore"; -import {getPrimaryPermalinkEntity, parseAppLocalLink} from "../../../utils/permalinks/Permalinks"; +import { getPrimaryPermalinkEntity, parseAppLocalLink } from "../../../utils/permalinks/Permalinks"; import MatrixClientContext from "../../../contexts/MatrixClientContext"; -import {Action} from "../../../dispatcher/actions"; -import {mediaFromMxc} from "../../../customisations/Media"; +import { Action } from "../../../dispatcher/actions"; +import { mediaFromMxc } from "../../../customisations/Media"; import Tooltip from './Tooltip'; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; @replaceableComponent("views.elements.Pill") class Pill extends React.Component { @@ -144,7 +144,7 @@ class Pill extends React.Component { } } } - this.setState({resourceId, pillType, member, group, room}); + this.setState({ resourceId, pillType, member, group, room }); } componentDidMount() { @@ -180,13 +180,13 @@ class Pill extends React.Component { member.rawDisplayName = resp.displayname; member.events.member = { getContent: () => { - return {avatar_url: resp.avatar_url}; + return { avatar_url: resp.avatar_url }; }, getDirectionalContent: function() { return this.getContent(); }, }; - this.setState({member}); + this.setState({ member }); }).catch((err) => { console.error('Could not retrieve profile data for ' + userId + ':', err); }); @@ -253,7 +253,7 @@ class Pill extends React.Component { break; case Pill.TYPE_GROUP_MENTION: { if (this.state.group) { - const {avatarUrl, groupId, name} = this.state.group; + const { avatarUrl, groupId, name } = this.state.group; linkText = groupId; if (this.props.shouldShowPillAvatar) { @@ -273,7 +273,7 @@ class Pill extends React.Component { }); if (this.state.pillType) { - const {yOffset} = this.props; + const { yOffset } = this.props; let tip; if (this.state.hover && resource) { diff --git a/src/components/views/elements/PowerSelector.js b/src/components/views/elements/PowerSelector.js index a7a65425a3..ef449df295 100644 --- a/src/components/views/elements/PowerSelector.js +++ b/src/components/views/elements/PowerSelector.js @@ -19,8 +19,8 @@ import PropTypes from 'prop-types'; import * as Roles from '../../../Roles'; import { _t } from '../../../languageHandler'; import Field from "./Field"; -import {Key} from "../../../Keyboard"; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { Key } from "../../../Keyboard"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; @replaceableComponent("views.elements.PowerSelector") export default class PowerSelector extends React.Component { @@ -97,15 +97,15 @@ export default class PowerSelector extends React.Component { onSelectChange = event => { const isCustom = event.target.value === "SELECT_VALUE_CUSTOM"; if (isCustom) { - this.setState({custom: true}); + this.setState({ custom: true }); } else { this.props.onChange(event.target.value, this.props.powerLevelKey); - this.setState({selectValue: event.target.value}); + this.setState({ selectValue: event.target.value }); } }; onCustomChange = event => { - this.setState({customValue: event.target.value}); + this.setState({ customValue: event.target.value }); }; onCustomBlur = event => { diff --git a/src/components/views/elements/ProgressBar.tsx b/src/components/views/elements/ProgressBar.tsx index 90832e5006..c4ff06e04e 100644 --- a/src/components/views/elements/ProgressBar.tsx +++ b/src/components/views/elements/ProgressBar.tsx @@ -21,7 +21,7 @@ interface IProps { max: number; } -const ProgressBar: React.FC = ({value, max}) => { +const ProgressBar: React.FC = ({ value, max }) => { return ; }; diff --git a/src/components/views/elements/QRCode.tsx b/src/components/views/elements/QRCode.tsx index 9ce3dc7202..50b12ae23d 100644 --- a/src/components/views/elements/QRCode.tsx +++ b/src/components/views/elements/QRCode.tsx @@ -15,10 +15,10 @@ limitations under the License. */ import * as React from "react"; -import {toDataURL, QRCodeSegment, QRCodeToDataURLOptions} from "qrcode"; +import { toDataURL, QRCodeSegment, QRCodeToDataURLOptions } from "qrcode"; import classNames from "classnames"; -import {_t} from "../../../languageHandler"; +import { _t } from "../../../languageHandler"; import Spinner from "./Spinner"; interface IProps extends QRCodeToDataURLOptions { @@ -30,11 +30,11 @@ const defaultOptions: QRCodeToDataURLOptions = { errorCorrectionLevel: 'L', // we want it as trivial-looking as possible }; -const QRCode: React.FC = ({data, className, ...options}) => { +const QRCode: React.FC = ({ data, className, ...options }) => { const [dataUri, setUri] = React.useState(null); React.useEffect(() => { let cancelled = false; - toDataURL(data, {...defaultOptions, ...options}).then(uri => { + toDataURL(data, { ...defaultOptions, ...options }).then(uri => { if (cancelled) return; setUri(uri); }); diff --git a/src/components/views/elements/ReplyThread.js b/src/components/views/elements/ReplyThread.js index 1ca68f18a8..8a5fd3ed4a 100644 --- a/src/components/views/elements/ReplyThread.js +++ b/src/components/views/elements/ReplyThread.js @@ -17,21 +17,21 @@ limitations under the License. */ import React from 'react'; import * as sdk from '../../../index'; -import {_t} from '../../../languageHandler'; +import { _t } from '../../../languageHandler'; import PropTypes from 'prop-types'; import dis from '../../../dispatcher/dispatcher'; -import {wantsDateSeparator} from '../../../DateUtils'; -import {MatrixEvent} from 'matrix-js-sdk/src/models/event'; -import {makeUserPermalink, RoomPermalinkCreator} from "../../../utils/permalinks/Permalinks"; +import { wantsDateSeparator } from '../../../DateUtils'; +import { MatrixEvent } from 'matrix-js-sdk/src/models/event'; +import { makeUserPermalink, RoomPermalinkCreator } from "../../../utils/permalinks/Permalinks"; import SettingsStore from "../../../settings/SettingsStore"; -import {LayoutPropType} from "../../../settings/Layout"; +import { LayoutPropType } from "../../../settings/Layout"; import escapeHtml from "escape-html"; import MatrixClientContext from "../../../contexts/MatrixClientContext"; -import {Action} from "../../../dispatcher/actions"; +import { Action } from "../../../dispatcher/actions"; import sanitizeHtml from "sanitize-html"; -import {UIFeature} from "../../../settings/UIFeature"; -import {PERMITTED_URL_SCHEMES} from "../../../HtmlUtils"; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { UIFeature } from "../../../settings/UIFeature"; +import { PERMITTED_URL_SCHEMES } from "../../../HtmlUtils"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; // This component does no cycle detection, simply because the only way to make such a cycle would be to // craft event_id's, using a homeserver that generates predictable event IDs; even then the impact would @@ -136,7 +136,7 @@ export default class ReplyThread extends React.Component { static getNestedReplyText(ev, permalinkCreator) { if (!ev) return null; - let {body, formatted_body: html} = ev.getContent(); + let { body, formatted_body: html } = ev.getContent(); if (this.getParentEventId(ev)) { if (body) body = this.stripPlainReply(body); } @@ -206,7 +206,7 @@ export default class ReplyThread extends React.Component { return null; } - return {body, html}; + return { body, html }; } static makeReplyMixIn(ev) { @@ -276,7 +276,7 @@ export default class ReplyThread extends React.Component { }; async initialize() { - const {parentEv} = this.props; + const { parentEv } = this.props; // at time of making this component we checked that props.parentEv has a parentEventId const ev = await this.getEvent(ReplyThread.getParentEventId(parentEv)); @@ -290,7 +290,7 @@ export default class ReplyThread extends React.Component { loading: false, }); } else { - this.setState({err: true}); + this.setState({ err: true }); } } diff --git a/src/components/views/elements/RoomAliasField.tsx b/src/components/views/elements/RoomAliasField.tsx index 74af311b47..d9e081341b 100644 --- a/src/components/views/elements/RoomAliasField.tsx +++ b/src/components/views/elements/RoomAliasField.tsx @@ -80,7 +80,7 @@ export default class RoomAliasField extends React.PureComponent private onValidate = async (fieldState) => { const result = await this.validationRules(fieldState); - this.setState({isValid: result.valid}); + this.setState({ isValid: result.valid }); return result; }; @@ -105,7 +105,7 @@ export default class RoomAliasField extends React.PureComponent }, { key: "taken", final: true, - test: async ({value}) => { + test: async ({ value }) => { if (!value) { return true; } diff --git a/src/components/views/elements/RoomTopic.tsx b/src/components/views/elements/RoomTopic.tsx index fe8aa5a83d..0526c2676c 100644 --- a/src/components/views/elements/RoomTopic.tsx +++ b/src/components/views/elements/RoomTopic.tsx @@ -14,12 +14,12 @@ See the License for the specific language governing permissions and limitations under the License. */ -import React, {useEffect, useState} from "react"; -import {EventType} from "matrix-js-sdk/src/@types/event"; -import {Room} from "matrix-js-sdk/src/models/room"; +import React, { useEffect, useState } from "react"; +import { EventType } from "matrix-js-sdk/src/@types/event"; +import { Room } from "matrix-js-sdk/src/models/room"; -import {useEventEmitter} from "../../../hooks/useEventEmitter"; -import {linkifyElement} from "../../../HtmlUtils"; +import { useEventEmitter } from "../../../hooks/useEventEmitter"; +import { linkifyElement } from "../../../HtmlUtils"; interface IProps { room?: Room; diff --git a/src/components/views/elements/SSOButtons.tsx b/src/components/views/elements/SSOButtons.tsx index a531abdf83..68c58a3e56 100644 --- a/src/components/views/elements/SSOButtons.tsx +++ b/src/components/views/elements/SSOButtons.tsx @@ -17,14 +17,14 @@ limitations under the License. import React from "react"; import { chunk } from "lodash"; import classNames from "classnames"; -import {MatrixClient} from "matrix-js-sdk/src/client"; +import { MatrixClient } from "matrix-js-sdk/src/client"; import PlatformPeg from "../../../PlatformPeg"; import AccessibleButton from "./AccessibleButton"; -import {_t} from "../../../languageHandler"; -import {IdentityProviderBrand, IIdentityProvider, ISSOFlow} from "../../../Login"; +import { _t } from "../../../languageHandler"; +import { IdentityProviderBrand, IIdentityProvider, ISSOFlow } from "../../../Login"; import AccessibleTooltipButton from "./AccessibleTooltipButton"; -import {mediaFromMxc} from "../../../customisations/Media"; +import { mediaFromMxc } from "../../../customisations/Media"; interface ISSOButtonProps extends Omit { idp: IIdentityProvider; @@ -48,7 +48,7 @@ const getIcon = (brand: IdentityProviderBrand | string) => { default: return null; } -} +}; const SSOButton: React.FC = ({ matrixClient, @@ -111,7 +111,7 @@ interface IProps { const MAX_PER_ROW = 6; -const SSOButtons: React.FC = ({matrixClient, flow, loginType, fragmentAfterLogin, primary}) => { +const SSOButtons: React.FC = ({ matrixClient, flow, loginType, fragmentAfterLogin, primary }) => { const providers = flow.identity_providers || []; if (providers.length < 2) { return
      diff --git a/src/components/views/elements/ServerPicker.tsx b/src/components/views/elements/ServerPicker.tsx index 9f06e2618c..c2d1fcb275 100644 --- a/src/components/views/elements/ServerPicker.tsx +++ b/src/components/views/elements/ServerPicker.tsx @@ -17,8 +17,8 @@ limitations under the License. import React from 'react'; import AccessibleButton from "./AccessibleButton"; -import {ValidatedServerConfig} from "../../../utils/AutoDiscoveryUtils"; -import {_t} from "../../../languageHandler"; +import { ValidatedServerConfig } from "../../../utils/AutoDiscoveryUtils"; +import { _t } from "../../../languageHandler"; import TextWithTooltip from "./TextWithTooltip"; import SdkConfig from "../../../SdkConfig"; import Modal from "../../../Modal"; @@ -87,7 +87,7 @@ const ServerPicker = ({ title, dialogTitle, serverConfig, onServerConfigChange } {serverName} { editBtn } { desc } -
      -} +
      ; +}; export default ServerPicker; diff --git a/src/components/views/elements/SettingsFlag.tsx b/src/components/views/elements/SettingsFlag.tsx index 24a21e1a33..ccde80ff00 100644 --- a/src/components/views/elements/SettingsFlag.tsx +++ b/src/components/views/elements/SettingsFlag.tsx @@ -21,7 +21,7 @@ import { _t } from '../../../languageHandler'; import ToggleSwitch from "./ToggleSwitch"; import StyledCheckbox from "./StyledCheckbox"; import { SettingLevel } from "../../../settings/SettingLevel"; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; interface IProps { // The setting must be a boolean diff --git a/src/components/views/elements/Slider.tsx b/src/components/views/elements/Slider.tsx index b513f90460..b9234d0550 100644 --- a/src/components/views/elements/Slider.tsx +++ b/src/components/views/elements/Slider.tsx @@ -15,7 +15,7 @@ limitations under the License. */ import * as React from 'react'; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; interface IProps { // A callback for the selected value @@ -86,8 +86,8 @@ export default class Slider extends React.Component { if (!this.props.disabled) { const offset = this.offset(this.props.values, this.props.value); selection =
      -
      -
      +
      +
      ; } diff --git a/src/components/views/elements/SpellCheckLanguagesDropdown.tsx b/src/components/views/elements/SpellCheckLanguagesDropdown.tsx index 06e1efe415..d10a599d95 100644 --- a/src/components/views/elements/SpellCheckLanguagesDropdown.tsx +++ b/src/components/views/elements/SpellCheckLanguagesDropdown.tsx @@ -16,12 +16,12 @@ limitations under the License. import React from 'react'; -import Dropdown from "../../views/elements/Dropdown" +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 { replaceableComponent } from "../../../utils/replaceableComponent"; function languageMatchesSearchQuery(query, language) { if (language.label.toUpperCase().includes(query.toUpperCase())) return true; @@ -67,11 +67,11 @@ export default class SpellCheckLanguagesDropdown extends React.Component { - this.setState({languages: ['en']}); + this.setState({ languages: ['en'] }); }); } } diff --git a/src/components/views/elements/Spinner.js b/src/components/views/elements/Spinner.js index 3ad8444bd6..75f85d0441 100644 --- a/src/components/views/elements/Spinner.js +++ b/src/components/views/elements/Spinner.js @@ -17,14 +17,14 @@ limitations under the License. import React from "react"; import PropTypes from "prop-types"; -import {_t} from "../../../languageHandler"; +import { _t } from "../../../languageHandler"; -const Spinner = ({w = 32, h = 32, message}) => ( +const Spinner = ({ w = 32, h = 32, message }) => (
      { message &&
      { message }
       
      }
      diff --git a/src/components/views/elements/Spoiler.js b/src/components/views/elements/Spoiler.js index 33b4382a2c..56c18c6e33 100644 --- a/src/components/views/elements/Spoiler.js +++ b/src/components/views/elements/Spoiler.js @@ -15,7 +15,7 @@ */ import React from 'react'; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; @replaceableComponent("views.elements.Spoiler") export default class Spoiler extends React.Component { diff --git a/src/components/views/elements/StyledCheckbox.tsx b/src/components/views/elements/StyledCheckbox.tsx index 2454d1336b..366cc2f1f7 100644 --- a/src/components/views/elements/StyledCheckbox.tsx +++ b/src/components/views/elements/StyledCheckbox.tsx @@ -16,7 +16,7 @@ limitations under the License. import React from "react"; import { randomString } from "matrix-js-sdk/src/randomstring"; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; interface IProps extends React.InputHTMLAttributes { } diff --git a/src/components/views/elements/StyledRadioButton.tsx b/src/components/views/elements/StyledRadioButton.tsx index 835394e055..7ec472b639 100644 --- a/src/components/views/elements/StyledRadioButton.tsx +++ b/src/components/views/elements/StyledRadioButton.tsx @@ -16,7 +16,7 @@ limitations under the License. import React from 'react'; import classnames from 'classnames'; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; interface IProps extends React.InputHTMLAttributes { outlined?: boolean; diff --git a/src/components/views/elements/SyntaxHighlight.js b/src/components/views/elements/SyntaxHighlight.js index f9874c5367..2c29f7c989 100644 --- a/src/components/views/elements/SyntaxHighlight.js +++ b/src/components/views/elements/SyntaxHighlight.js @@ -16,8 +16,8 @@ limitations under the License. import React from 'react'; import PropTypes from 'prop-types'; -import {highlightBlock} from 'highlight.js'; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { highlightBlock } from 'highlight.js'; +import { replaceableComponent } from "../../../utils/replaceableComponent"; @replaceableComponent("views.elements.SyntaxHighlight") export default class SyntaxHighlight extends React.Component { diff --git a/src/components/views/elements/TagTile.js b/src/components/views/elements/TagTile.js index 03d853babc..12c3718274 100644 --- a/src/components/views/elements/TagTile.js +++ b/src/components/views/elements/TagTile.js @@ -30,8 +30,8 @@ import GroupFilterOrderStore from '../../../stores/GroupFilterOrderStore'; import MatrixClientContext from "../../../contexts/MatrixClientContext"; import AccessibleButton from "./AccessibleButton"; import SettingsStore from "../../../settings/SettingsStore"; -import {mediaFromMxc} from "../../../customisations/Media"; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { mediaFromMxc } from "../../../customisations/Media"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; // A class for a child of GroupFilterPanel (possibly wrapped in a DNDTagTile) that represents // a thing to click on for the user to filter the visible rooms in the RoomList to: diff --git a/src/components/views/elements/TextWithTooltip.js b/src/components/views/elements/TextWithTooltip.js index a6fc00fc2e..633d182fcf 100644 --- a/src/components/views/elements/TextWithTooltip.js +++ b/src/components/views/elements/TextWithTooltip.js @@ -17,7 +17,7 @@ import React from 'react'; import PropTypes from 'prop-types'; import * as sdk from '../../../index'; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; @replaceableComponent("views.elements.TextWithTooltip") export default class TextWithTooltip extends React.Component { @@ -37,17 +37,17 @@ export default class TextWithTooltip extends React.Component { } onMouseOver = () => { - this.setState({hover: true}); + this.setState({ hover: true }); }; onMouseLeave = () => { - this.setState({hover: false}); + this.setState({ hover: false }); }; render() { const Tooltip = sdk.getComponent("elements.Tooltip"); - const {class: className, children, tooltip, tooltipClass, tooltipProps, ...props} = this.props; + const { class: className, children, tooltip, tooltipClass, tooltipProps, ...props } = this.props; return ( diff --git a/src/components/views/elements/TintableSvg.js b/src/components/views/elements/TintableSvg.js deleted file mode 100644 index 670f3e9bb9..0000000000 --- a/src/components/views/elements/TintableSvg.js +++ /dev/null @@ -1,82 +0,0 @@ -/* -Copyright 2015 OpenMarket Ltd -Copyright 2019 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 PropTypes from 'prop-types'; -import Tinter from "../../../Tinter"; -import {replaceableComponent} from "../../../utils/replaceableComponent"; - -@replaceableComponent("views.elements.TintableSvg") -class TintableSvg extends React.Component { - static propTypes = { - src: PropTypes.string.isRequired, - width: PropTypes.string.isRequired, - height: PropTypes.string.isRequired, - className: PropTypes.string, - }; - - // list of currently mounted TintableSvgs - static mounts = {}; - static idSequence = 0; - - componentDidMount() { - this.fixups = []; - - this.id = TintableSvg.idSequence++; - TintableSvg.mounts[this.id] = this; - } - - componentWillUnmount() { - delete TintableSvg.mounts[this.id]; - } - - tint = () => { - // TODO: only bother running this if the global tint settings have changed - // since we loaded! - Tinter.applySvgFixups(this.fixups); - }; - - onLoad = event => { - // console.log("TintableSvg.onLoad for " + this.props.src); - this.fixups = Tinter.calcSvgFixups([event.target]); - Tinter.applySvgFixups(this.fixups); - }; - - render() { - return ( - - ); - } -} - -// Register with the Tinter so that we will be told if the tint changes -Tinter.registerTintable(function() { - if (TintableSvg.mounts) { - Object.keys(TintableSvg.mounts).forEach((id) => { - TintableSvg.mounts[id].tint(); - }); - } -}); - -export default TintableSvg; diff --git a/src/components/views/elements/ToggleSwitch.tsx b/src/components/views/elements/ToggleSwitch.tsx index f05c45b3db..7315cc6383 100644 --- a/src/components/views/elements/ToggleSwitch.tsx +++ b/src/components/views/elements/ToggleSwitch.tsx @@ -31,7 +31,7 @@ interface IProps { } // Controlled Toggle Switch element, written with Accessibility in mind -export default ({checked, disabled = false, onChange, ...props}: IProps) => { +export default ({ checked, disabled = false, onChange, ...props }: IProps) => { const _onClick = () => { if (disabled) return; onChange(!checked); diff --git a/src/components/views/elements/Tooltip.tsx b/src/components/views/elements/Tooltip.tsx index 0202c6b02f..e64819f441 100644 --- a/src/components/views/elements/Tooltip.tsx +++ b/src/components/views/elements/Tooltip.tsx @@ -17,11 +17,10 @@ See the License for the specific language governing permissions and limitations under the License. */ - -import React, {Component, CSSProperties} from 'react'; +import React, { Component, CSSProperties } from 'react'; import ReactDOM from 'react-dom'; import classNames from 'classnames'; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; import UIStore from "../../../stores/UIStore"; const MIN_TOOLTIP_HEIGHT = 25; diff --git a/src/components/views/elements/TooltipButton.tsx b/src/components/views/elements/TooltipButton.tsx index 191018cc19..87bf04c2ea 100644 --- a/src/components/views/elements/TooltipButton.tsx +++ b/src/components/views/elements/TooltipButton.tsx @@ -17,7 +17,7 @@ limitations under the License. import React from 'react'; import * as sdk from '../../../index'; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; interface IProps { helpText: string; diff --git a/src/components/views/elements/TruncatedList.tsx b/src/components/views/elements/TruncatedList.tsx index 395caa9222..403df4111e 100644 --- a/src/components/views/elements/TruncatedList.tsx +++ b/src/components/views/elements/TruncatedList.tsx @@ -17,7 +17,7 @@ limitations under the License. import React from 'react'; import { _t } from '../../../languageHandler'; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; interface IProps { // The number of elements to show before truncating. If negative, no truncation is done. @@ -43,7 +43,7 @@ export default class TruncatedList extends React.Component { truncateAt: 2, createOverflowElement(overflowCount, totalCount) { return ( -
      { _t("And %(count)s more...", {count: overflowCount}) }
      +
      { _t("And %(count)s more...", { count: overflowCount }) }
      ); }, }; diff --git a/src/components/views/elements/UserTagTile.tsx b/src/components/views/elements/UserTagTile.tsx index d3e07a0a34..4414ff31fd 100644 --- a/src/components/views/elements/UserTagTile.tsx +++ b/src/components/views/elements/UserTagTile.tsx @@ -21,7 +21,7 @@ import GroupFilterOrderStore from "../../../stores/GroupFilterOrderStore"; import AccessibleTooltipButton from "./AccessibleTooltipButton"; import classNames from "classnames"; import { _t } from "../../../languageHandler"; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; interface IProps { } @@ -52,7 +52,7 @@ export default class UserTagTile extends React.PureComponent { private onTagStoreUpdate = () => { const selected = GroupFilterOrderStore.getSelectedTags().length === 0; - this.setState({selected}); + this.setState({ selected }); }; private onTileClick = (ev) => { @@ -60,7 +60,7 @@ export default class UserTagTile extends React.PureComponent { ev.stopPropagation(); // Deselect all tags - defaultDispatcher.dispatch({action: "deselect_tags"}); + defaultDispatcher.dispatch({ action: "deselect_tags" }); }; public render() { diff --git a/src/components/views/elements/Validation.tsx b/src/components/views/elements/Validation.tsx index 1b0659ab9b..ad3571513c 100644 --- a/src/components/views/elements/Validation.tsx +++ b/src/components/views/elements/Validation.tsx @@ -15,7 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -/* eslint-disable babel/no-invalid-this */ +/* eslint-disable @typescript-eslint/no-invalid-this */ import React from "react"; import classNames from "classnames"; diff --git a/src/components/views/elements/crypto/VerificationQRCode.js b/src/components/views/elements/crypto/VerificationQRCode.js index 3bbfb004c6..76cfb82d35 100644 --- a/src/components/views/elements/crypto/VerificationQRCode.js +++ b/src/components/views/elements/crypto/VerificationQRCode.js @@ -16,7 +16,7 @@ limitations under the License. import React from "react"; import PropTypes from "prop-types"; -import {replaceableComponent} from "../../../../utils/replaceableComponent"; +import { replaceableComponent } from "../../../../utils/replaceableComponent"; import QRCode from "../QRCode"; @replaceableComponent("views.elements.crypto.VerificationQRCode") @@ -28,7 +28,7 @@ export default class VerificationQRCode extends React.PureComponent { render() { return ( ); diff --git a/src/components/views/emojipicker/Category.tsx b/src/components/views/emojipicker/Category.tsx index 4c7852def3..24b4fbe3ed 100644 --- a/src/components/views/emojipicker/Category.tsx +++ b/src/components/views/emojipicker/Category.tsx @@ -15,13 +15,13 @@ See the License for the specific language governing permissions and limitations under the License. */ -import React, {RefObject} from 'react'; +import React, { RefObject } from 'react'; import { CATEGORY_HEADER_HEIGHT, EMOJI_HEIGHT, EMOJIS_PER_ROW } from "./EmojiPicker"; import LazyRenderList from "../elements/LazyRenderList"; -import {DATA_BY_CATEGORY, IEmoji} from "../../../emoji"; +import { DATA_BY_CATEGORY, IEmoji } from "../../../emoji"; import Emoji from './Emoji'; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; const OVERFLOW_ROWS = 3; diff --git a/src/components/views/emojipicker/Emoji.tsx b/src/components/views/emojipicker/Emoji.tsx index 5d7665ce98..73e24f46fb 100644 --- a/src/components/views/emojipicker/Emoji.tsx +++ b/src/components/views/emojipicker/Emoji.tsx @@ -17,9 +17,9 @@ limitations under the License. import React from 'react'; -import {MenuItem} from "../../structures/ContextMenu"; -import {IEmoji} from "../../../emoji"; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { MenuItem } from "../../structures/ContextMenu"; +import { IEmoji } from "../../../emoji"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; interface IProps { emoji: IEmoji; diff --git a/src/components/views/emojipicker/EmojiPicker.tsx b/src/components/views/emojipicker/EmojiPicker.tsx index 6d7b90c8a6..47e3823116 100644 --- a/src/components/views/emojipicker/EmojiPicker.tsx +++ b/src/components/views/emojipicker/EmojiPicker.tsx @@ -19,14 +19,14 @@ import React from 'react'; import { _t } from '../../../languageHandler'; import * as recent from '../../../emojipicker/recent'; -import {DATA_BY_CATEGORY, getEmojiFromUnicode, IEmoji} from "../../../emoji"; +import { DATA_BY_CATEGORY, getEmojiFromUnicode, IEmoji } from "../../../emoji"; import AutoHideScrollbar from "../../structures/AutoHideScrollbar"; import Header from "./Header"; import Search from "./Search"; import Preview from "./Preview"; import QuickReactions from "./QuickReactions"; -import Category, {ICategory, CategoryKey} from "./Category"; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import Category, { ICategory, CategoryKey } from "./Category"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; export const CATEGORY_HEADER_HEIGHT = 22; export const EMOJI_HEIGHT = 37; @@ -234,7 +234,7 @@ class EmojiPicker extends React.Component { className="mx_EmojiPicker_body" wrappedRef={ref => { // @ts-ignore - AutoHideScrollbar should accept a RefObject or fall back to its own instead - this.bodyRef.current = ref + this.bodyRef.current = ref; }} onScroll={this.onScroll} > diff --git a/src/components/views/emojipicker/Header.tsx b/src/components/views/emojipicker/Header.tsx index 693f86ad73..010801141a 100644 --- a/src/components/views/emojipicker/Header.tsx +++ b/src/components/views/emojipicker/Header.tsx @@ -18,10 +18,10 @@ limitations under the License. import React from 'react'; import classNames from "classnames"; -import {_t} from "../../../languageHandler"; -import {Key} from "../../../Keyboard"; -import {CategoryKey, ICategory} from "./Category"; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { _t } from "../../../languageHandler"; +import { Key } from "../../../Keyboard"; +import { CategoryKey, ICategory } from "./Category"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; interface IProps { categories: ICategory[]; diff --git a/src/components/views/emojipicker/Preview.tsx b/src/components/views/emojipicker/Preview.tsx index e0952ec73e..9c2dbb9cbd 100644 --- a/src/components/views/emojipicker/Preview.tsx +++ b/src/components/views/emojipicker/Preview.tsx @@ -17,8 +17,8 @@ limitations under the License. import React from 'react'; -import {IEmoji} from "../../../emoji"; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { IEmoji } from "../../../emoji"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; interface IProps { emoji: IEmoji; diff --git a/src/components/views/emojipicker/QuickReactions.tsx b/src/components/views/emojipicker/QuickReactions.tsx index a250aca458..ffd3ce9760 100644 --- a/src/components/views/emojipicker/QuickReactions.tsx +++ b/src/components/views/emojipicker/QuickReactions.tsx @@ -18,9 +18,9 @@ limitations under the License. import React from 'react'; import { _t } from '../../../languageHandler'; -import {getEmojiFromUnicode, IEmoji} from "../../../emoji"; +import { getEmojiFromUnicode, IEmoji } from "../../../emoji"; import Emoji from "./Emoji"; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; // We use the variation-selector Heart in Quick Reactions for some reason const QUICK_REACTIONS = ["👍", "👎", "😄", "🎉", "😕", "❤️", "🚀", "👀"].map(emoji => { diff --git a/src/components/views/emojipicker/ReactionPicker.tsx b/src/components/views/emojipicker/ReactionPicker.tsx index e86d183aba..d8f8b7f2ff 100644 --- a/src/components/views/emojipicker/ReactionPicker.tsx +++ b/src/components/views/emojipicker/ReactionPicker.tsx @@ -16,12 +16,12 @@ limitations under the License. */ import React from 'react'; -import {MatrixEvent} from "matrix-js-sdk/src/models/event"; +import { MatrixEvent } from "matrix-js-sdk/src/models/event"; import EmojiPicker from "./EmojiPicker"; -import {MatrixClientPeg} from "../../../MatrixClientPeg"; +import { MatrixClientPeg } from "../../../MatrixClientPeg"; import dis from "../../../dispatcher/dispatcher"; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; interface IProps { mxEvent: MatrixEvent; @@ -103,7 +103,7 @@ class ReactionPicker extends React.Component { "key": reaction, }, }); - dis.dispatch({action: "message_sent"}); + dis.dispatch({ action: "message_sent" }); return true; } }; diff --git a/src/components/views/emojipicker/Search.tsx b/src/components/views/emojipicker/Search.tsx index abe3e026be..c88bf8d84d 100644 --- a/src/components/views/emojipicker/Search.tsx +++ b/src/components/views/emojipicker/Search.tsx @@ -18,8 +18,8 @@ limitations under the License. import React from 'react'; import { _t } from '../../../languageHandler'; -import {Key} from "../../../Keyboard"; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { Key } from "../../../Keyboard"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; interface IProps { query: string; diff --git a/src/components/views/groups/GroupInviteTile.js b/src/components/views/groups/GroupInviteTile.js index bc0bf966f9..c12e14e024 100644 --- a/src/components/views/groups/GroupInviteTile.js +++ b/src/components/views/groups/GroupInviteTile.js @@ -20,19 +20,19 @@ import React from 'react'; import PropTypes from 'prop-types'; import * as sdk from '../../../index'; import dis from '../../../dispatcher/dispatcher'; -import {_t} from '../../../languageHandler'; +import { _t } from '../../../languageHandler'; import classNames from 'classnames'; -import {MatrixClientPeg} from "../../../MatrixClientPeg"; -import {ContextMenu, ContextMenuButton, toRightOf} from "../../structures/ContextMenu"; +import { MatrixClientPeg } from "../../../MatrixClientPeg"; +import { ContextMenu, ContextMenuButton, toRightOf } from "../../structures/ContextMenu"; import MatrixClientContext from "../../../contexts/MatrixClientContext"; -import {RovingTabIndexWrapper} from "../../../accessibility/RovingTabIndex"; -import {replaceableComponent} from "../../../utils/replaceableComponent"; -import {mediaFromMxc} from "../../../customisations/Media"; +import { RovingTabIndexWrapper } from "../../../accessibility/RovingTabIndex"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; +import { mediaFromMxc } from "../../../customisations/Media"; // XXX this class copies a lot from RoomTile.js @replaceableComponent("views.groups.GroupInviteTile") export default class GroupInviteTile extends React.Component { - static propTypes: { + static propTypes = { group: PropTypes.object.isRequired, }; @@ -57,7 +57,7 @@ export default class GroupInviteTile extends React.Component { }; onMouseEnter = () => { - const state = {hover: true}; + const state = { hover: true }; // Only allow non-guests to access the context menu if (!this.context.isGuest()) { state.badgeHover = true; @@ -165,7 +165,7 @@ export default class GroupInviteTile extends React.Component { return - {({onFocus, isActive, ref}) => + {({ onFocus, isActive, ref }) => { if (!proceed) return; - this.setState({groupRoomRemoveLoading: true}); + this.setState({ groupRoomRemoveLoading: true }); const groupId = this.props.groupId; const roomId = this.props.groupRoomId; GroupStore.removeRoomFromGroup(this.props.groupId, roomId).then(() => { @@ -108,11 +108,11 @@ export default class GroupRoomInfo extends React.Component { Modal.createTrackedDialog('Failed to remove room from group', '', ErrorDialog, { title: _t("Failed to remove room from community"), description: _t( - "Failed to remove '%(roomName)s' from %(groupId)s", {groupId, roomName}, + "Failed to remove '%(roomName)s' from %(groupId)s", { groupId, roomName }, ), }); }).finally(() => { - this.setState({groupRoomRemoveLoading: false}); + this.setState({ groupRoomRemoveLoading: false }); }); }, }); @@ -139,7 +139,7 @@ export default class GroupRoomInfo extends React.Component { title: _t("Something went wrong!"), description: _t( "The visibility of '%(roomName)s' in %(groupId)s could not be updated.", - {roomName, groupId}, + { roomName, groupId }, ), }); }).finally(() => { diff --git a/src/components/views/groups/GroupRoomList.js b/src/components/views/groups/GroupRoomList.js index 2921ac79ee..00220441e7 100644 --- a/src/components/views/groups/GroupRoomList.js +++ b/src/components/views/groups/GroupRoomList.js @@ -21,7 +21,7 @@ import PropTypes from 'prop-types'; import { showGroupAddRoomDialog } from '../../../GroupAddressPicker'; import AccessibleButton from '../elements/AccessibleButton'; import AutoHideScrollbar from "../../structures/AutoHideScrollbar"; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; const INITIAL_LOAD_NUM_ROOMS = 30; diff --git a/src/components/views/groups/GroupRoomTile.js b/src/components/views/groups/GroupRoomTile.js index 7edfc1a376..662359669d 100644 --- a/src/components/views/groups/GroupRoomTile.js +++ b/src/components/views/groups/GroupRoomTile.js @@ -20,8 +20,8 @@ import * as sdk from '../../../index'; import dis from '../../../dispatcher/dispatcher'; import { GroupRoomType } from '../../../groups'; import MatrixClientContext from "../../../contexts/MatrixClientContext"; -import {replaceableComponent} from "../../../utils/replaceableComponent"; -import {mediaFromMxc} from "../../../customisations/Media"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; +import { mediaFromMxc } from "../../../customisations/Media"; @replaceableComponent("views.groups.GroupRoomTile") class GroupRoomTile extends React.Component { diff --git a/src/components/views/groups/GroupTile.js b/src/components/views/groups/GroupTile.js index dd8366bbe0..21308ac056 100644 --- a/src/components/views/groups/GroupTile.js +++ b/src/components/views/groups/GroupTile.js @@ -20,8 +20,8 @@ import * as sdk from '../../../index'; import dis from '../../../dispatcher/dispatcher'; import FlairStore from '../../../stores/FlairStore'; import MatrixClientContext from "../../../contexts/MatrixClientContext"; -import {replaceableComponent} from "../../../utils/replaceableComponent"; -import {mediaFromMxc} from "../../../customisations/Media"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; +import { mediaFromMxc } from "../../../customisations/Media"; import { _t } from "../../../languageHandler"; import TagOrderActions from "../../../actions/TagOrderActions"; import GroupFilterOrderStore from "../../../stores/GroupFilterOrderStore"; @@ -49,7 +49,7 @@ class GroupTile extends React.Component { componentDidMount() { FlairStore.getGroupProfileCached(this.context, this.props.groupId).then((profile) => { - this.setState({profile}); + this.setState({ profile }); }).catch((err) => { console.error('Error whilst getting cached profile for GroupTile', err); }); diff --git a/src/components/views/groups/GroupUserSettings.js b/src/components/views/groups/GroupUserSettings.js index 5b537d7377..efb392c54f 100644 --- a/src/components/views/groups/GroupUserSettings.js +++ b/src/components/views/groups/GroupUserSettings.js @@ -18,7 +18,7 @@ import React from 'react'; import * as sdk from '../../../index'; import { _t } from '../../../languageHandler'; import MatrixClientContext from "../../../contexts/MatrixClientContext"; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; @replaceableComponent("views.groups.GroupUserSettings") export default class GroupUserSettings extends React.Component { @@ -31,10 +31,10 @@ export default class GroupUserSettings extends React.Component { componentDidMount() { this.context.getJoinedGroups().then((result) => { - this.setState({groups: result.groups || [], error: null}); + this.setState({ groups: result.groups || [], error: null }); }, (err) => { console.error(err); - this.setState({groups: null, error: err}); + this.setState({ groups: null, error: err }); }); } diff --git a/src/components/views/host_signup/HostSignupContainer.tsx b/src/components/views/host_signup/HostSignupContainer.tsx index 6445454994..fc1506bf61 100644 --- a/src/components/views/host_signup/HostSignupContainer.tsx +++ b/src/components/views/host_signup/HostSignupContainer.tsx @@ -33,4 +33,4 @@ const HostSignupContainer = () => { ; }; -export default HostSignupContainer +export default HostSignupContainer; diff --git a/src/components/views/messages/DateSeparator.js b/src/components/views/messages/DateSeparator.tsx similarity index 82% rename from src/components/views/messages/DateSeparator.js rename to src/components/views/messages/DateSeparator.tsx index 5e15b584c5..fa363c7c4c 100644 --- a/src/components/views/messages/DateSeparator.js +++ b/src/components/views/messages/DateSeparator.tsx @@ -1,6 +1,6 @@ /* -Copyright 2015, 2016 OpenMarket Ltd Copyright 2018 Michael Telatynski <7t3chguy@gmail.com> +Copyright 2015 - 2021 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. @@ -16,12 +16,12 @@ limitations under the License. */ import React from 'react'; -import PropTypes from 'prop-types'; -import { _t } from '../../../languageHandler'; -import {formatFullDateNoTime} from '../../../DateUtils'; -import {replaceableComponent} from "../../../utils/replaceableComponent"; -function getdaysArray() { +import { _t } from '../../../languageHandler'; +import { formatFullDateNoTime } from '../../../DateUtils'; +import { replaceableComponent } from "../../../utils/replaceableComponent"; + +function getDaysArray(): string[] { return [ _t('Sunday'), _t('Monday'), @@ -33,14 +33,14 @@ function getdaysArray() { ]; } -@replaceableComponent("views.messages.DateSeparator") -export default class DateSeparator extends React.Component { - static propTypes = { - ts: PropTypes.number.isRequired, - forExport: PropTypes.bool, - }; +interface IProps { + ts: number; + forExport?: boolean +} - getLabel() { +@replaceableComponent("views.messages.DateSeparator") +export default class DateSeparator extends React.Component { + private getLabel() { const date = new Date(this.props.ts); // During the time the archive is being viewed, a specific day might not make sense, so we return the full date @@ -48,7 +48,7 @@ export default class DateSeparator extends React.Component { const today = new Date(); const yesterday = new Date(); - const days = getdaysArray(); + const days = getDaysArray(); yesterday.setDate(today.getDate() - 1); if (date.toDateString() === today.toDateString()) { diff --git a/src/components/views/messages/EditHistoryMessage.js b/src/components/views/messages/EditHistoryMessage.js index dc4e0187d3..1416cfff53 100644 --- a/src/components/views/messages/EditHistoryMessage.js +++ b/src/components/views/messages/EditHistoryMessage.js @@ -14,20 +14,20 @@ See the License for the specific language governing permissions and limitations under the License. */ -import React, {createRef} from 'react'; +import React, { createRef } from 'react'; import PropTypes from 'prop-types'; import * as HtmlUtils from '../../../HtmlUtils'; import { editBodyDiffToHtml } from '../../../utils/MessageDiffUtils'; -import {formatTime} from '../../../DateUtils'; -import {MatrixEvent} from 'matrix-js-sdk/src/models/event'; -import {pillifyLinks, unmountPills} from '../../../utils/pillify'; +import { formatTime } from '../../../DateUtils'; +import { MatrixEvent } from 'matrix-js-sdk/src/models/event'; +import { pillifyLinks, unmountPills } from '../../../utils/pillify'; import { _t } from '../../../languageHandler'; import * as sdk from '../../../index'; -import {MatrixClientPeg} from '../../../MatrixClientPeg'; +import { MatrixClientPeg } from '../../../MatrixClientPeg'; import Modal from '../../../Modal'; import classNames from 'classnames'; import RedactedBody from "./RedactedBody"; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; function getReplacedContent(event) { const originalContent = event.getOriginalContent(); @@ -46,21 +46,21 @@ export default class EditHistoryMessage extends React.PureComponent { constructor(props) { super(props); const cli = MatrixClientPeg.get(); - const {userId} = cli.credentials; + const { userId } = cli.credentials; const event = this.props.mxEvent; const room = cli.getRoom(event.getRoomId()); if (event.localRedactionEvent()) { event.localRedactionEvent().on("status", this._onAssociatedStatusChanged); } const canRedact = room.currentState.maySendRedactionForEvent(event, userId); - this.state = {canRedact, sendStatus: event.getAssociatedStatus()}; + this.state = { canRedact, sendStatus: event.getAssociatedStatus() }; this._content = createRef(); this._pills = []; } _onAssociatedStatusChanged = () => { - this.setState({sendStatus: this.props.mxEvent.getAssociatedStatus()}); + this.setState({ sendStatus: this.props.mxEvent.getAssociatedStatus() }); }; _onRedactClick = async () => { @@ -129,7 +129,7 @@ export default class EditHistoryMessage extends React.PureComponent { } render() { - const {mxEvent} = this.props; + const { mxEvent } = this.props; const content = getReplacedContent(mxEvent); let contentContainer; if (mxEvent.isRedacted()) { @@ -139,7 +139,7 @@ export default class EditHistoryMessage extends React.PureComponent { if (this.props.previousEdit) { contentElements = editBodyDiffToHtml(getReplacedContent(this.props.previousEdit), content); } else { - contentElements = HtmlUtils.bodyToHtml(content, null, {stripReplyFallback: true}); + contentElements = HtmlUtils.bodyToHtml(content, null, { stripReplyFallback: true }); } if (mxEvent.getContent().msgtype === "m.emote") { const name = mxEvent.sender ? mxEvent.sender.name : mxEvent.getSender(); diff --git a/src/components/views/messages/EncryptionEvent.tsx b/src/components/views/messages/EncryptionEvent.tsx index 3af9c463c9..0f716ed010 100644 --- a/src/components/views/messages/EncryptionEvent.tsx +++ b/src/components/views/messages/EncryptionEvent.tsx @@ -14,8 +14,8 @@ See the License for the specific language governing permissions and limitations under the License. */ -import React, {forwardRef, useContext} from 'react'; -import {MatrixEvent} from "matrix-js-sdk/src/models/event"; +import React, { forwardRef, useContext } from 'react'; +import { MatrixEvent } from "matrix-js-sdk/src/models/event"; import { _t } from '../../../languageHandler'; import { MatrixClientPeg } from '../../../MatrixClientPeg'; @@ -27,7 +27,7 @@ interface IProps { mxEvent: MatrixEvent; } -const EncryptionEvent = forwardRef(({mxEvent}, ref) => { +const EncryptionEvent = forwardRef(({ mxEvent }, ref) => { const cli = useContext(MatrixClientContext); const roomId = mxEvent.getRoomId(); const isRoomEncrypted = MatrixClientPeg.get().isRoomEncrypted(roomId); diff --git a/src/components/views/messages/EventTileBubble.tsx b/src/components/views/messages/EventTileBubble.tsx index 88913ac2d4..9fa3586ea5 100644 --- a/src/components/views/messages/EventTileBubble.tsx +++ b/src/components/views/messages/EventTileBubble.tsx @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import React, {forwardRef, ReactNode, ReactChildren} from "react"; +import React, { forwardRef, ReactNode, ReactChildren } from "react"; import classNames from "classnames"; interface IProps { diff --git a/src/components/views/messages/MAudioBody.js b/src/components/views/messages/MAudioBody.js index 2258aa1713..3f03fc3054 100644 --- a/src/components/views/messages/MAudioBody.js +++ b/src/components/views/messages/MAudioBody.js @@ -20,8 +20,8 @@ import MFileBody from './MFileBody'; import { decryptFile } from '../../../utils/DecryptFile'; import { _t } from '../../../languageHandler'; import InlineSpinner from '../elements/InlineSpinner'; -import {replaceableComponent} from "../../../utils/replaceableComponent"; -import {mediaFromContent} from "../../../customisations/Media"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; +import { mediaFromContent } from "../../../customisations/Media"; @replaceableComponent("views.messages.MAudioBody") export default class MAudioBody extends React.Component { diff --git a/src/components/views/messages/MFileBody.js b/src/components/views/messages/MFileBody.js index c33ad5f21b..ea14a0db40 100644 --- a/src/components/views/messages/MFileBody.js +++ b/src/components/views/messages/MFileBody.js @@ -14,15 +14,15 @@ See the License for the specific language governing permissions and limitations under the License. */ -import React, {createRef} from 'react'; +import React, { createRef } from 'react'; import PropTypes from 'prop-types'; import filesize from 'filesize'; import { _t } from '../../../languageHandler'; -import {decryptFile} from '../../../utils/DecryptFile'; +import { decryptFile } from '../../../utils/DecryptFile'; import Modal from '../../../Modal'; import AccessibleButton from "../elements/AccessibleButton"; -import {replaceableComponent} from "../../../utils/replaceableComponent"; -import {mediaFromContent} from "../../../customisations/Media"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; +import { mediaFromContent } from "../../../customisations/Media"; import ErrorDialog from "../dialogs/ErrorDialog"; let downloadIconUrl; // cached copy of the download.svg asset for the sandboxed iframe later on diff --git a/src/components/views/messages/MImageBody.js b/src/components/views/messages/MImageBody.js index 9229755d29..0abdd8424a 100644 --- a/src/components/views/messages/MImageBody.js +++ b/src/components/views/messages/MImageBody.js @@ -16,7 +16,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import React, {createRef} from 'react'; +import React, { createRef } from 'react'; import PropTypes from 'prop-types'; import MFileBody from './MFileBody'; @@ -27,8 +27,8 @@ import { _t } from '../../../languageHandler'; import SettingsStore from "../../../settings/SettingsStore"; import MatrixClientContext from "../../../contexts/MatrixClientContext"; import InlineSpinner from '../elements/InlineSpinner'; -import {replaceableComponent} from "../../../utils/replaceableComponent"; -import {mediaFromContent} from "../../../customisations/Media"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; +import { mediaFromContent } from "../../../customisations/Media"; @replaceableComponent("views.messages.MImageBody") export default class MImageBody extends React.Component { @@ -419,7 +419,7 @@ export default class MImageBody extends React.Component { } -
      +
      { img } { gifLabel }
      diff --git a/src/components/views/messages/MJitsiWidgetEvent.tsx b/src/components/views/messages/MJitsiWidgetEvent.tsx index 626efe1f36..aaf659d6d9 100644 --- a/src/components/views/messages/MJitsiWidgetEvent.tsx +++ b/src/components/views/messages/MJitsiWidgetEvent.tsx @@ -21,7 +21,7 @@ import WidgetStore from "../../../stores/WidgetStore"; import EventTileBubble from "./EventTileBubble"; import { MatrixClientPeg } from "../../../MatrixClientPeg"; import { Container, WidgetLayoutStore } from "../../../stores/widgets/WidgetLayoutStore"; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; interface IProps { mxEvent: MatrixEvent; @@ -52,20 +52,20 @@ export default class MJitsiWidgetEvent extends React.PureComponent { // removed return ; } else if (prevUrl) { // modified return ; } else { // assume added return ; } diff --git a/src/components/views/messages/MKeyVerificationConclusion.js b/src/components/views/messages/MKeyVerificationConclusion.js index c9489711aa..a5f12df47d 100644 --- a/src/components/views/messages/MKeyVerificationConclusion.js +++ b/src/components/views/messages/MKeyVerificationConclusion.js @@ -17,12 +17,12 @@ limitations under the License. import React from 'react'; import classNames from 'classnames'; import PropTypes from 'prop-types'; -import {MatrixClientPeg} from '../../../MatrixClientPeg'; +import { MatrixClientPeg } from '../../../MatrixClientPeg'; import { _t } from '../../../languageHandler'; -import {getNameForEventRoom, userLabelForEventRoom} +import { getNameForEventRoom, userLabelForEventRoom } from '../../../utils/KeyVerificationStateObserver'; import EventTileBubble from "./EventTileBubble"; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; @replaceableComponent("views.messages.MKeyVerificationConclusion") export default class MKeyVerificationConclusion extends React.Component { @@ -90,7 +90,7 @@ export default class MKeyVerificationConclusion extends React.Component { } render() { - const {mxEvent} = this.props; + const { mxEvent } = this.props; const request = mxEvent.verificationRequest; if (!this._shouldRender(mxEvent, request)) { @@ -103,15 +103,15 @@ export default class MKeyVerificationConclusion extends React.Component { let title; if (request.done) { - title = _t("You verified %(name)s", {name: getNameForEventRoom(request.otherUserId, mxEvent)}); + title = _t("You verified %(name)s", { name: getNameForEventRoom(request.otherUserId, mxEvent) }); } else if (request.cancelled) { const userId = request.cancellingUserId; if (userId === myUserId) { title = _t("You cancelled verifying %(name)s", - {name: getNameForEventRoom(request.otherUserId, mxEvent)}); + { name: getNameForEventRoom(request.otherUserId, mxEvent) }); } else { title = _t("%(name)s cancelled verifying", - {name: getNameForEventRoom(userId, mxEvent)}); + { name: getNameForEventRoom(userId, mxEvent) }); } } diff --git a/src/components/views/messages/MKeyVerificationRequest.tsx b/src/components/views/messages/MKeyVerificationRequest.tsx index 69467cfa50..d690513d55 100644 --- a/src/components/views/messages/MKeyVerificationRequest.tsx +++ b/src/components/views/messages/MKeyVerificationRequest.tsx @@ -53,7 +53,7 @@ export default class MKeyVerificationRequest extends React.Component { dis.dispatch({ action: Action.SetRightPanelPhase, phase: RightPanelPhases.EncryptionPanel, - refireParams: {verificationRequest, member}, + refireParams: { verificationRequest, member }, }); }; @@ -90,14 +90,14 @@ export default class MKeyVerificationRequest extends React.Component { if (userId === myUserId) { return _t("You accepted"); } else { - return _t("%(name)s accepted", {name: getNameForEventRoom(userId, this.props.mxEvent.getRoomId())}); + return _t("%(name)s accepted", { name: getNameForEventRoom(userId, this.props.mxEvent.getRoomId()) }); } } private cancelledLabel(userId: string) { const client = MatrixClientPeg.get(); const myUserId = client.getUserId(); - const {cancellationCode} = this.props.mxEvent.verificationRequest; + const { cancellationCode } = this.props.mxEvent.verificationRequest; const declined = cancellationCode === "m.user"; if (userId === myUserId) { if (declined) { @@ -107,9 +107,9 @@ export default class MKeyVerificationRequest extends React.Component { } } else { if (declined) { - return _t("%(name)s declined", {name: getNameForEventRoom(userId, this.props.mxEvent.getRoomId())}); + return _t("%(name)s declined", { name: getNameForEventRoom(userId, this.props.mxEvent.getRoomId()) }); } else { - return _t("%(name)s cancelled", {name: getNameForEventRoom(userId, this.props.mxEvent.getRoomId())}); + return _t("%(name)s cancelled", { name: getNameForEventRoom(userId, this.props.mxEvent.getRoomId()) }); } } } @@ -117,7 +117,7 @@ export default class MKeyVerificationRequest extends React.Component { public render() { const AccessibleButton = sdk.getComponent("elements.AccessibleButton"); - const {mxEvent} = this.props; + const { mxEvent } = this.props; const request = mxEvent.verificationRequest; if (!request || request.invalid) { @@ -147,7 +147,7 @@ export default class MKeyVerificationRequest extends React.Component { if (!request.initiatedByMe) { const name = getNameForEventRoom(request.requestingUserId, mxEvent.getRoomId()); - title = _t("%(name)s wants to verify", {name}); + title = _t("%(name)s wants to verify", { name }); subtitle = userLabelForEventRoom(request.requestingUserId, mxEvent.getRoomId()); if (request.canAccept) { stateNode = (
      diff --git a/src/components/views/messages/MStickerBody.js b/src/components/views/messages/MStickerBody.js index 54eb7649b4..aca3dba37c 100644 --- a/src/components/views/messages/MStickerBody.js +++ b/src/components/views/messages/MStickerBody.js @@ -17,7 +17,7 @@ limitations under the License. import React from 'react'; import MImageBody from './MImageBody'; import * as sdk from '../../../index'; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; @replaceableComponent("views.messages.MStickerBody") export default class MStickerBody extends MImageBody { @@ -53,7 +53,7 @@ export default class MStickerBody extends MImageBody { if (!content || !content.body || !content.info || !content.info.w) return null; const Tooltip = sdk.getComponent('elements.Tooltip'); - return
      + return
      ; } diff --git a/src/components/views/messages/MVideoBody.tsx b/src/components/views/messages/MVideoBody.tsx index ec9cbcf7b5..67394875f6 100644 --- a/src/components/views/messages/MVideoBody.tsx +++ b/src/components/views/messages/MVideoBody.tsx @@ -21,8 +21,8 @@ import { decryptFile } from '../../../utils/DecryptFile'; import { _t } from '../../../languageHandler'; import SettingsStore from "../../../settings/SettingsStore"; import InlineSpinner from '../elements/InlineSpinner'; -import {replaceableComponent} from "../../../utils/replaceableComponent"; -import {mediaFromContent} from "../../../customisations/Media"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; +import { mediaFromContent } from "../../../customisations/Media"; interface IProps { /* the MatrixEvent to show */ @@ -53,7 +53,7 @@ export default class MVideoBody extends React.PureComponent { decryptedThumbnailUrl: null, decryptedBlob: null, error: null, - } + }; } thumbScale(fullWidth: number, fullHeight: number, thumbWidth: number, thumbHeight: number) { @@ -189,7 +189,7 @@ export default class MVideoBody extends React.PureComponent { this.videoRef.current.play(); }); this.props.onHeightChanged(); - } + }; private getFileBody = () => { if (this.props.forExport) return null; diff --git a/src/components/views/messages/MVoiceMessageBody.tsx b/src/components/views/messages/MVoiceMessageBody.tsx index a7e3b1cd86..edb791f7ee 100644 --- a/src/components/views/messages/MVoiceMessageBody.tsx +++ b/src/components/views/messages/MVoiceMessageBody.tsx @@ -15,16 +15,16 @@ limitations under the License. */ import React from "react"; -import {MatrixEvent} from "matrix-js-sdk/src/models/event"; -import {replaceableComponent} from "../../../utils/replaceableComponent"; -import {Playback} from "../../../voice/Playback"; +import { MatrixEvent } from "matrix-js-sdk/src/models/event"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; +import { Playback } from "../../../voice/Playback"; import MFileBody from "./MFileBody"; import InlineSpinner from '../elements/InlineSpinner'; -import {_t} from "../../../languageHandler"; -import {mediaFromContent} from "../../../customisations/Media"; -import {decryptFile} from "../../../utils/DecryptFile"; +import { _t } from "../../../languageHandler"; +import { mediaFromContent } from "../../../customisations/Media"; +import { decryptFile } from "../../../utils/DecryptFile"; import RecordingPlayback from "../voice_messages/RecordingPlayback"; -import {IMediaEventContent} from "../../../customisations/models/IMediaEventContent"; +import { IMediaEventContent } from "../../../customisations/models/IMediaEventContent"; interface IProps { mxEvent: MatrixEvent; @@ -52,9 +52,9 @@ export default class MVoiceMessageBody extends React.PureComponent r.blob()).then(r => r.arrayBuffer()); } catch (e) { - this.setState({error: e}); + this.setState({ error: e }); console.warn("Unable to download voice message", e); return; // stop processing the audio file } @@ -106,6 +106,6 @@ export default class MVoiceMessageBody extends React.PureComponent - ) + ); } } diff --git a/src/components/views/messages/MVoiceOrAudioBody.tsx b/src/components/views/messages/MVoiceOrAudioBody.tsx index 3b60471f95..7564fa00ec 100644 --- a/src/components/views/messages/MVoiceOrAudioBody.tsx +++ b/src/components/views/messages/MVoiceOrAudioBody.tsx @@ -15,9 +15,9 @@ limitations under the License. */ import React from "react"; -import {MatrixEvent} from "matrix-js-sdk/src/models/event"; +import { MatrixEvent } from "matrix-js-sdk/src/models/event"; import MAudioBody from "./MAudioBody"; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; import SettingsStore from "../../../settings/SettingsStore"; import MVoiceMessageBody from "./MVoiceMessageBody"; diff --git a/src/components/views/messages/MessageActionBar.js b/src/components/views/messages/MessageActionBar.js index 37737519ce..7532554666 100644 --- a/src/components/views/messages/MessageActionBar.js +++ b/src/components/views/messages/MessageActionBar.js @@ -16,24 +16,24 @@ See the License for the specific language governing permissions and limitations under the License. */ -import React, {useEffect} from 'react'; +import React, { useEffect } from 'react'; import PropTypes from 'prop-types'; import { EventStatus } from 'matrix-js-sdk/src/models/event'; import { _t } from '../../../languageHandler'; import * as sdk from '../../../index'; import dis from '../../../dispatcher/dispatcher'; -import {aboveLeftOf, ContextMenu, ContextMenuTooltipButton, useContextMenu} from '../../structures/ContextMenu'; +import { aboveLeftOf, ContextMenu, ContextMenuTooltipButton, useContextMenu } from '../../structures/ContextMenu'; import { isContentActionable, canEditContent } from '../../../utils/EventUtils'; import RoomContext from "../../../contexts/RoomContext"; import Toolbar from "../../../accessibility/Toolbar"; -import {RovingAccessibleTooltipButton, useRovingTabIndex} from "../../../accessibility/RovingTabIndex"; -import {replaceableComponent} from "../../../utils/replaceableComponent"; -import {canCancel} from "../context_menus/MessageContextMenu"; +import { RovingAccessibleTooltipButton, useRovingTabIndex } from "../../../accessibility/RovingTabIndex"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; +import { canCancel } from "../context_menus/MessageContextMenu"; import Resend from "../../../Resend"; import { MatrixClientPeg } from "../../../MatrixClientPeg"; -const OptionsButton = ({mxEvent, getTile, getReplyThread, permalinkCreator, onFocusChange}) => { +const OptionsButton = ({ mxEvent, getTile, getReplyThread, permalinkCreator, onFocusChange }) => { const [menuDisplayed, button, openMenu, closeMenu] = useContextMenu(); const [onFocus, isActive, ref] = useRovingTabIndex(button); useEffect(() => { @@ -48,15 +48,14 @@ const OptionsButton = ({mxEvent, getTile, getReplyThread, permalinkCreator, onFo const replyThread = getReplyThread && getReplyThread(); const buttonRect = button.current.getBoundingClientRect(); - contextMenu = - - ; + contextMenu = ; } return @@ -74,7 +73,7 @@ const OptionsButton = ({mxEvent, getTile, getReplyThread, permalinkCreator, onFo ; }; -const ReactButton = ({mxEvent, reactions, onFocusChange}) => { +const ReactButton = ({ mxEvent, reactions, onFocusChange }) => { const [menuDisplayed, button, openMenu, closeMenu] = useContextMenu(); const [onFocus, isActive, ref] = useRovingTabIndex(button); useEffect(() => { diff --git a/src/components/views/messages/MessageEvent.js b/src/components/views/messages/MessageEvent.js index e53a796f70..92a2bc70c2 100644 --- a/src/components/views/messages/MessageEvent.js +++ b/src/components/views/messages/MessageEvent.js @@ -14,14 +14,14 @@ See the License for the specific language governing permissions and limitations under the License. */ -import React, {createRef} from 'react'; +import React, { createRef } from 'react'; import PropTypes from 'prop-types'; import * as sdk from '../../../index'; import SettingsStore from "../../../settings/SettingsStore"; -import {Mjolnir} from "../../../mjolnir/Mjolnir"; +import { Mjolnir } from "../../../mjolnir/Mjolnir"; import RedactedBody from "./RedactedBody"; import UnknownBody from "./UnknownBody"; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; @replaceableComponent("views.messages.MessageEvent") export default class MessageEvent extends React.Component { diff --git a/src/components/views/messages/MjolnirBody.js b/src/components/views/messages/MjolnirBody.js index 4368fd936c..67484a6d9c 100644 --- a/src/components/views/messages/MjolnirBody.js +++ b/src/components/views/messages/MjolnirBody.js @@ -16,8 +16,8 @@ limitations under the License. import React from 'react'; import PropTypes from 'prop-types'; -import {_t} from '../../../languageHandler'; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { _t } from '../../../languageHandler'; +import { replaceableComponent } from "../../../utils/replaceableComponent"; @replaceableComponent("views.messages.MjolnirBody") export default class MjolnirBody extends React.Component { @@ -43,7 +43,7 @@ export default class MjolnirBody extends React.Component { return (
      {_t( "You have ignored this user, so their message is hidden. Show anyways.", - {}, {a: (sub) => {sub}}, + {}, { a: (sub) => {sub} }, )}
      ); } diff --git a/src/components/views/messages/ReactionsRow.tsx b/src/components/views/messages/ReactionsRow.tsx index 0180baa466..55ffb8deac 100644 --- a/src/components/views/messages/ReactionsRow.tsx +++ b/src/components/views/messages/ReactionsRow.tsx @@ -125,7 +125,7 @@ export default class ReactionsRow extends React.PureComponent { private onDecrypted = () => { // Decryption changes whether the event is actionable this.forceUpdate(); - } + }; private onReactionsChange = () => { // TODO: Call `onHeightChanged` as needed @@ -136,7 +136,7 @@ export default class ReactionsRow extends React.PureComponent { // has changed (this is triggered by events for that purpose only) and // `PureComponent`s shallow state / props compare would otherwise filter this out. this.forceUpdate(); - } + }; private getMyReactions() { const reactions = this.props.reactions; @@ -155,7 +155,7 @@ export default class ReactionsRow extends React.PureComponent { this.setState({ showAll: true, }); - } + }; render() { const { mxEvent, reactions } = this.props; diff --git a/src/components/views/messages/ReactionsRowButton.tsx b/src/components/views/messages/ReactionsRowButton.tsx index d163f1ad30..53e27b882e 100644 --- a/src/components/views/messages/ReactionsRowButton.tsx +++ b/src/components/views/messages/ReactionsRowButton.tsx @@ -68,7 +68,7 @@ export default class ReactionsRowButton extends React.PureComponent { this.setState({ tooltipVisible: false, }); - } + }; render() { const { mxEvent, content, count, reactionEvents, myReactionEvent } = this.props; diff --git a/src/components/views/messages/RedactedBody.tsx b/src/components/views/messages/RedactedBody.tsx index 7fa6a3b093..bfcac384d3 100644 --- a/src/components/views/messages/RedactedBody.tsx +++ b/src/components/views/messages/RedactedBody.tsx @@ -27,7 +27,7 @@ interface IProps { forExport: boolean; } -const RedactedBody = React.forwardRef(({mxEvent, forExport}, ref) => { +const RedactedBody = React.forwardRef(({ mxEvent, forExport }, ref) => { const cli: MatrixClient = useContext(MatrixClientContext); let text = _t("Message deleted"); const unsigned = mxEvent.getUnsigned(); diff --git a/src/components/views/messages/RoomAvatarEvent.js b/src/components/views/messages/RoomAvatarEvent.js index 41eada3193..d68d794ee6 100644 --- a/src/components/views/messages/RoomAvatarEvent.js +++ b/src/components/views/messages/RoomAvatarEvent.js @@ -18,13 +18,13 @@ limitations under the License. import React from 'react'; import PropTypes from 'prop-types'; -import {MatrixClientPeg} from '../../../MatrixClientPeg'; +import { MatrixClientPeg } from '../../../MatrixClientPeg'; import { _t } from '../../../languageHandler'; import * as sdk from '../../../index'; import Modal from '../../../Modal'; import AccessibleButton from '../elements/AccessibleButton'; -import {replaceableComponent} from "../../../utils/replaceableComponent"; -import {mediaFromMxc} from "../../../customisations/Media"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; +import { mediaFromMxc } from "../../../customisations/Media"; @replaceableComponent("views.messages.RoomAvatarEvent") export default class RoomAvatarEvent extends React.Component { @@ -60,7 +60,7 @@ export default class RoomAvatarEvent extends React.Component { if (!ev.getContent().url || ev.getContent().url.trim().length === 0) { return (
      - { _t('%(senderDisplayName)s removed the room avatar.', {senderDisplayName}) } + { _t('%(senderDisplayName)s removed the room avatar.', { senderDisplayName }) }
      ); } diff --git a/src/components/views/messages/RoomCreate.js b/src/components/views/messages/RoomCreate.js index 3e02884c02..56bd25cbac 100644 --- a/src/components/views/messages/RoomCreate.js +++ b/src/components/views/messages/RoomCreate.js @@ -21,9 +21,9 @@ import PropTypes from 'prop-types'; import dis from '../../../dispatcher/dispatcher'; import { RoomPermalinkCreator } from '../../../utils/permalinks/Permalinks'; import { _t } from '../../../languageHandler'; -import {MatrixClientPeg} from '../../../MatrixClientPeg'; +import { MatrixClientPeg } from '../../../MatrixClientPeg'; import EventTileBubble from "./EventTileBubble"; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; @replaceableComponent("views.messages.RoomCreate") export default class RoomCreate extends React.Component { diff --git a/src/components/views/messages/SenderProfile.tsx b/src/components/views/messages/SenderProfile.tsx index d6b802beff..11c3ca4e3c 100644 --- a/src/components/views/messages/SenderProfile.tsx +++ b/src/components/views/messages/SenderProfile.tsx @@ -39,7 +39,7 @@ export default class SenderProfile extends React.Component { private unmounted: boolean; constructor(props: IProps) { - super(props) + super(props); const senderId = this.props.mxEvent.getSender(); this.state = { @@ -56,7 +56,6 @@ export default class SenderProfile extends React.Component { this.getPublicisedGroups(); } - this.context.on('RoomState.events', this.onRoomStateEvents); } @@ -70,7 +69,7 @@ export default class SenderProfile extends React.Component { const userGroups = await FlairStore.getPublicisedGroupsCached( this.context, this.props.mxEvent.getSender(), ); - this.setState({userGroups}); + this.setState({ userGroups }); } } @@ -106,9 +105,9 @@ export default class SenderProfile extends React.Component { } render() { - const {mxEvent} = this.props; + const { mxEvent } = this.props; const colorClass = getUserNameColorClass(mxEvent.getSender()); - const {msgtype} = mxEvent.getContent(); + const { msgtype } = mxEvent.getContent(); const disambiguate = mxEvent.sender?.disambiguate; const displayName = mxEvent.sender?.rawDisplayName || mxEvent.getSender() || ""; diff --git a/src/components/views/messages/TextualBody.js b/src/components/views/messages/TextualBody.js index ebc4ce7ce8..ffaaaada4d 100644 --- a/src/components/views/messages/TextualBody.js +++ b/src/components/views/messages/TextualBody.js @@ -190,7 +190,7 @@ export default class TextualBody extends React.Component { const buttonRect = button.getBoundingClientRect(); const GenericTextContextMenu = sdk.getComponent('context_menus.GenericTextContextMenu'); - const {close} = ContextMenu.createMenu(GenericTextContextMenu, { + const { close } = ContextMenu.createMenu(GenericTextContextMenu, { ...toRightOf(buttonRect, 2), message: successful ? _t('Copied!') : _t('Failed to copy'), }); @@ -404,7 +404,7 @@ export default class TextualBody extends React.Component { }, unhideWidget: () => { - this.setState({widgetHidden: false}); + this.setState({ widgetHidden: false }); if (global.localStorage) { global.localStorage.removeItem("hide_preview_" + this.props.mxEvent.getId()); } @@ -460,7 +460,7 @@ export default class TextualBody extends React.Component { _openHistoryDialog = async () => { const MessageEditHistoryDialog = sdk.getComponent("views.dialogs.MessageEditHistoryDialog"); - Modal.createDialog(MessageEditHistoryDialog, {mxEvent: this.props.mxEvent}); + Modal.createDialog(MessageEditHistoryDialog, { mxEvent: this.props.mxEvent }); }; _renderEditedMarker() { @@ -469,7 +469,7 @@ export default class TextualBody extends React.Component { const tooltip =
      - {_t("Edited at %(date)s", {date: dateString})} + {_t("Edited at %(date)s", { date: dateString })}
      {_t("Click to view edits")} @@ -480,7 +480,7 @@ export default class TextualBody extends React.Component { {`(${_t("edited")})`} diff --git a/src/components/views/messages/TextualEvent.js b/src/components/views/messages/TextualEvent.js index 25da18da0d..663f47dd2a 100644 --- a/src/components/views/messages/TextualEvent.js +++ b/src/components/views/messages/TextualEvent.js @@ -18,7 +18,7 @@ limitations under the License. import React from 'react'; import PropTypes from 'prop-types'; import * as TextForEvent from "../../../TextForEvent"; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; @replaceableComponent("views.messages.TextualEvent") export default class TextualEvent extends React.Component { diff --git a/src/components/views/messages/TileErrorBoundary.js b/src/components/views/messages/TileErrorBoundary.tsx similarity index 77% rename from src/components/views/messages/TileErrorBoundary.js rename to src/components/views/messages/TileErrorBoundary.tsx index 0e9a7b6128..967127d275 100644 --- a/src/components/views/messages/TileErrorBoundary.js +++ b/src/components/views/messages/TileErrorBoundary.tsx @@ -1,5 +1,5 @@ /* -Copyright 2020 The Matrix.org Foundation C.I.C. +Copyright 2020 - 2021 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. @@ -16,14 +16,24 @@ limitations under the License. import React from 'react'; import classNames from 'classnames'; +import { MatrixEvent } from "matrix-js-sdk/src/models/event"; + import { _t } from '../../../languageHandler'; -import * as sdk from '../../../index'; import Modal from '../../../Modal'; import SdkConfig from "../../../SdkConfig"; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; +import BugReportDialog from '../dialogs/BugReportDialog'; + +interface IProps { + mxEvent: MatrixEvent; +} + +interface IState { + error: Error; +} @replaceableComponent("views.messages.TileErrorBoundary") -export default class TileErrorBoundary extends React.Component { +export default class TileErrorBoundary extends React.Component { constructor(props) { super(props); @@ -32,17 +42,13 @@ export default class TileErrorBoundary extends React.Component { }; } - static getDerivedStateFromError(error) { + static getDerivedStateFromError(error: Error): Partial { // Side effects are not permitted here, so we only update the state so // that the next render shows an error message. return { error }; } - _onBugReport = () => { - const BugReportDialog = sdk.getComponent("dialogs.BugReportDialog"); - if (!BugReportDialog) { - return; - } + private onBugReport = (): void => { Modal.createTrackedDialog('Bug Report Dialog', '', BugReportDialog, { label: 'react-soft-crash-tile', }); @@ -60,7 +66,7 @@ export default class TileErrorBoundary extends React.Component { let submitLogsButton; if (SdkConfig.get().bug_report_endpoint_url) { - submitLogsButton = + submitLogsButton = {_t("Submit logs")} ; } diff --git a/src/components/views/messages/UnknownBody.js b/src/components/views/messages/UnknownBody.js index 786facc340..0f866216fc 100644 --- a/src/components/views/messages/UnknownBody.js +++ b/src/components/views/messages/UnknownBody.js @@ -15,9 +15,9 @@ See the License for the specific language governing permissions and limitations under the License. */ -import React, {forwardRef} from "react"; +import React, { forwardRef } from "react"; -export default forwardRef(({mxEvent}, ref) => { +export default forwardRef(({ mxEvent }, ref) => { const text = mxEvent.getContent().body; return ( diff --git a/src/components/views/messages/ViewSourceEvent.js b/src/components/views/messages/ViewSourceEvent.js index 2ec567c5ad..62454fef1a 100644 --- a/src/components/views/messages/ViewSourceEvent.js +++ b/src/components/views/messages/ViewSourceEvent.js @@ -17,7 +17,7 @@ limitations under the License. import React from 'react'; import PropTypes from 'prop-types'; import classNames from 'classnames'; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; import { MatrixClientPeg } from "../../../MatrixClientPeg"; @replaceableComponent("views.messages.ViewSourceEvent") @@ -36,7 +36,7 @@ export default class ViewSourceEvent extends React.PureComponent { } componentDidMount() { - const {mxEvent} = this.props; + const { mxEvent } = this.props; const client = MatrixClientPeg.get(); client.decryptEventIfNeeded(mxEvent); diff --git a/src/components/views/right_panel/BaseCard.tsx b/src/components/views/right_panel/BaseCard.tsx index 09973809de..2528139a2b 100644 --- a/src/components/views/right_panel/BaseCard.tsx +++ b/src/components/views/right_panel/BaseCard.tsx @@ -14,16 +14,16 @@ See the License for the specific language governing permissions and limitations under the License. */ -import React, {ReactNode} from 'react'; +import React, { ReactNode } from 'react'; import classNames from 'classnames'; import AutoHideScrollbar from "../../structures/AutoHideScrollbar"; -import {_t} from "../../../languageHandler"; +import { _t } from "../../../languageHandler"; import AccessibleButton from "../elements/AccessibleButton"; import defaultDispatcher from "../../../dispatcher/dispatcher"; -import {SetRightPanelPhasePayload} from "../../../dispatcher/payloads/SetRightPanelPhasePayload"; -import {Action} from "../../../dispatcher/actions"; -import {RightPanelPhases} from "../../../stores/RightPanelStorePhases"; +import { SetRightPanelPhasePayload } from "../../../dispatcher/payloads/SetRightPanelPhasePayload"; +import { Action } from "../../../dispatcher/actions"; +import { RightPanelPhases } from "../../../stores/RightPanelStorePhases"; interface IProps { header?: ReactNode; diff --git a/src/components/views/right_panel/EncryptionInfo.tsx b/src/components/views/right_panel/EncryptionInfo.tsx index db59a88967..c34cf18710 100644 --- a/src/components/views/right_panel/EncryptionInfo.tsx +++ b/src/components/views/right_panel/EncryptionInfo.tsx @@ -21,7 +21,7 @@ import { _t } from "../../../languageHandler"; import { RoomMember } from "matrix-js-sdk/src/models/room-member"; import { User } from "matrix-js-sdk/src/models/user"; -export const PendingActionSpinner = ({text}) => { +export const PendingActionSpinner = ({ text }) => { const Spinner = sdk.getComponent('elements.Spinner'); return
      diff --git a/src/components/views/right_panel/GroupHeaderButtons.tsx b/src/components/views/right_panel/GroupHeaderButtons.tsx index 3c93cf6470..132a76e891 100644 --- a/src/components/views/right_panel/GroupHeaderButtons.tsx +++ b/src/components/views/right_panel/GroupHeaderButtons.tsx @@ -48,7 +48,7 @@ export default class GroupHeaderButtons extends HeaderButtons { protected onAction(payload: ActionPayload) { if (payload.action === Action.ViewUser) { if ((payload as ViewUserPayload).member) { - this.setPhase(RightPanelPhases.RoomMemberInfo, {member: payload.member}); + this.setPhase(RightPanelPhases.RoomMemberInfo, { member: payload.member }); } else { this.setPhase(RightPanelPhases.GroupMemberList); } @@ -57,14 +57,14 @@ export default class GroupHeaderButtons extends HeaderButtons { } else if (payload.action === "view_group_room") { this.setPhase( RightPanelPhases.GroupRoomInfo, - {groupRoomId: payload.groupRoomId, groupId: payload.groupId}, + { groupRoomId: payload.groupRoomId, groupId: payload.groupId }, ); } else if (payload.action === "view_group_room_list") { this.setPhase(RightPanelPhases.GroupRoomList); } else if (payload.action === "view_group_member_list") { this.setPhase(RightPanelPhases.GroupMemberList); } else if (payload.action === "view_group_user") { - this.setPhase(RightPanelPhases.GroupMemberInfo, {member: payload.member}); + this.setPhase(RightPanelPhases.GroupMemberInfo, { member: payload.member }); } } diff --git a/src/components/views/right_panel/HeaderButton.tsx b/src/components/views/right_panel/HeaderButton.tsx index cdf4f44e06..1625db3f55 100644 --- a/src/components/views/right_panel/HeaderButton.tsx +++ b/src/components/views/right_panel/HeaderButton.tsx @@ -48,7 +48,7 @@ export default class HeaderButton extends React.Component { public render() { // eslint-disable-next-line @typescript-eslint/no-unused-vars - const {isHighlighted, onClick, analytics, name, title, ...props} = this.props; + const { isHighlighted, onClick, analytics, name, title, ...props } = this.props; const classes = classNames({ mx_RightPanel_headerButton: true, diff --git a/src/components/views/right_panel/HeaderButtons.tsx b/src/components/views/right_panel/HeaderButtons.tsx index 6d44a081d9..c30ad60771 100644 --- a/src/components/views/right_panel/HeaderButtons.tsx +++ b/src/components/views/right_panel/HeaderButtons.tsx @@ -88,9 +88,9 @@ export default abstract class HeaderButtons

      extends React.Component { protected onAction(payload: ActionPayload) { if (payload.action === Action.ViewUser) { if (payload.member) { - this.setPhase(RightPanelPhases.RoomMemberInfo, {member: payload.member}); + this.setPhase(RightPanelPhases.RoomMemberInfo, { member: payload.member }); } else { this.setPhase(RightPanelPhases.RoomMemberList); } } else if (payload.action === "view_3pid_invite") { if (payload.event) { - this.setPhase(RightPanelPhases.Room3pidMemberInfo, {event: payload.event}); + this.setPhase(RightPanelPhases.Room3pidMemberInfo, { event: payload.event }); } else { this.setPhase(RightPanelPhases.RoomMemberList); } diff --git a/src/components/views/right_panel/RoomSummaryCard.tsx b/src/components/views/right_panel/RoomSummaryCard.tsx index 5dd5790bfb..75049811e1 100644 --- a/src/components/views/right_panel/RoomSummaryCard.tsx +++ b/src/components/views/right_panel/RoomSummaryCard.tsx @@ -14,9 +14,9 @@ See the License for the specific language governing permissions and limitations under the License. */ -import React, {useCallback, useState, useEffect, useContext} from "react"; +import React, { useCallback, useState, useEffect, useContext } from "react"; import classNames from "classnames"; -import {Room} from "matrix-js-sdk/src/models/room"; +import { Room } from "matrix-js-sdk/src/models/room"; import MatrixClientContext from "../../../contexts/MatrixClientContext"; import { useIsEncrypted } from '../../../hooks/useIsEncrypted'; @@ -25,25 +25,25 @@ import { _t } from '../../../languageHandler'; import RoomAvatar from "../avatars/RoomAvatar"; import AccessibleButton from "../elements/AccessibleButton"; import defaultDispatcher from "../../../dispatcher/dispatcher"; -import {Action} from "../../../dispatcher/actions"; -import {RightPanelPhases} from "../../../stores/RightPanelStorePhases"; -import {SetRightPanelPhasePayload} from "../../../dispatcher/payloads/SetRightPanelPhasePayload"; +import { Action } from "../../../dispatcher/actions"; +import { RightPanelPhases } from "../../../stores/RightPanelStorePhases"; +import { SetRightPanelPhasePayload } from "../../../dispatcher/payloads/SetRightPanelPhasePayload"; import Modal from "../../../Modal"; import ShareDialog from '../dialogs/ShareDialog'; -import {useEventEmitter} from "../../../hooks/useEventEmitter"; +import { useEventEmitter } from "../../../hooks/useEventEmitter"; import WidgetUtils from "../../../utils/WidgetUtils"; -import {IntegrationManagers} from "../../../integrations/IntegrationManagers"; +import { IntegrationManagers } from "../../../integrations/IntegrationManagers"; import SettingsStore from "../../../settings/SettingsStore"; import TextWithTooltip from "../elements/TextWithTooltip"; import WidgetAvatar from "../avatars/WidgetAvatar"; import AccessibleTooltipButton from "../elements/AccessibleTooltipButton"; -import WidgetStore, {IApp} from "../../../stores/WidgetStore"; +import WidgetStore, { IApp } from "../../../stores/WidgetStore"; import { E2EStatus } from "../../../utils/ShieldUtils"; import RoomContext from "../../../contexts/RoomContext"; -import {UIFeature} from "../../../settings/UIFeature"; -import {ChevronFace, ContextMenuTooltipButton, useContextMenu} from "../../structures/ContextMenu"; +import { UIFeature } from "../../../settings/UIFeature"; +import { ChevronFace, ContextMenuTooltipButton, useContextMenu } from "../../structures/ContextMenu"; import WidgetContextMenu from "../context_menus/WidgetContextMenu"; -import {useRoomMemberCount} from "../../../hooks/useRoomMembers"; +import { useRoomMemberCount } from "../../../hooks/useRoomMembers"; import { Container, MAX_PINNED, WidgetLayoutStore } from "../../../stores/widgets/WidgetLayoutStore"; import RoomName from "../elements/RoomName"; import UIStore from "../../../stores/UIStore"; diff --git a/src/components/views/right_panel/UserInfo.tsx b/src/components/views/right_panel/UserInfo.tsx index 111e9dbf38..e9d80d49c5 100644 --- a/src/components/views/right_panel/UserInfo.tsx +++ b/src/components/views/right_panel/UserInfo.tsx @@ -164,7 +164,7 @@ function useHasCrossSigningKeys(cli: MatrixClient, member: User, canVerify: bool }, [cli, member, canVerify], undefined); } -function DeviceItem({userId, device}: {userId: string, device: IDevice}) { +function DeviceItem({ userId, device }: {userId: string, device: IDevice}) { const cli = useContext(MatrixClientContext); const isMe = userId === cli.getUserId(); const deviceTrust = cli.checkDeviceTrust(userId, device.deviceId); @@ -202,7 +202,6 @@ function DeviceItem({userId, device}: {userId: string, device: IDevice}) { let trustedLabel = null; if (userTrust.isVerified()) trustedLabel = isVerified ? _t("Trusted") : _t("Not trusted"); - if (isVerified) { return (

      @@ -226,7 +225,7 @@ function DeviceItem({userId, device}: {userId: string, device: IDevice}) { } } -function DevicesSection({devices, userId, loading}: {devices: IDevice[], userId: string, loading: boolean}) { +function DevicesSection({ devices, userId, loading }: {devices: IDevice[], userId: string, loading: boolean}) { const cli = useContext(MatrixClientContext); const userTrust = cli.checkUserTrust(userId); @@ -266,12 +265,12 @@ function DevicesSection({devices, userId, loading}: {devices: IDevice[], userId: unverifiedDevices.push(device); } } - expandCountCaption = _t("%(count)s verified sessions", {count: expandSectionDevices.length}); + expandCountCaption = _t("%(count)s verified sessions", { count: expandSectionDevices.length }); expandHideCaption = _t("Hide verified sessions"); expandIconClasses += " mx_E2EIcon_verified"; } else { expandSectionDevices = devices; - expandCountCaption = _t("%(count)s sessions", {count: devices.length}); + expandCountCaption = _t("%(count)s sessions", { count: devices.length }); expandHideCaption = _t("Hide sessions"); expandIconClasses += " mx_E2EIcon_normal"; } @@ -317,7 +316,7 @@ const UserOptionsSection: React.FC<{ isIgnored: boolean; canInvite: boolean; isSpace?: boolean; -}> = ({member, isIgnored, canInvite, isSpace}) => { +}> = ({ member, isIgnored, canInvite, isSpace }) => { const cli = useContext(MatrixClientContext); let ignoreButton = null; @@ -351,7 +350,7 @@ const UserOptionsSection: React.FC<{ ignoreButton = ( { isIgnored ? _t("Unignore") : _t("Ignore") } @@ -450,7 +449,7 @@ const UserOptionsSection: React.FC<{ }; const warnSelfDemote = async (isSpace: boolean) => { - const {finished} = Modal.createTrackedDialog('Demoting Self', '', QuestionDialog, { + const { finished } = Modal.createTrackedDialog('Demoting Self', '', QuestionDialog, { title: _t("Demote yourself?"), description:
      @@ -469,7 +468,7 @@ const warnSelfDemote = async (isSpace: boolean) => { return confirmed; }; -const GenericAdminToolsContainer: React.FC<{}> = ({children}) => { +const GenericAdminToolsContainer: React.FC<{}> = ({ children }) => { return (

      { _t("Admin Tools") }

      @@ -530,14 +529,14 @@ interface IBaseProps { stopUpdating(): void; } -const RoomKickButton: React.FC = ({member, startUpdating, stopUpdating}) => { +const RoomKickButton: React.FC = ({ member, startUpdating, stopUpdating }) => { const cli = useContext(MatrixClientContext); // check if user can be kicked/disinvited if (member.membership !== "invite" && member.membership !== "join") return null; const onKick = async () => { - const {finished} = Modal.createTrackedDialog( + const { finished } = Modal.createTrackedDialog( 'Confirm User Action Dialog', 'onKick', ConfirmUserActionDialog, @@ -575,11 +574,11 @@ const RoomKickButton: React.FC = ({member, startUpdating, stopUpdati ; }; -const RedactMessagesButton: React.FC = ({member}) => { +const RedactMessagesButton: React.FC = ({ member }) => { const cli = useContext(MatrixClientContext); const onRedactAllMessages = async () => { - const {roomId, userId} = member; + const { roomId, userId } = member; const room = cli.getRoom(roomId); if (!room) { return; @@ -607,23 +606,23 @@ const RedactMessagesButton: React.FC = ({member}) => { if (count === 0) { Modal.createTrackedDialog('No user messages found to remove', '', InfoDialog, { - title: _t("No recent messages by %(user)s found", {user}), + title: _t("No recent messages by %(user)s found", { user }), description:

      { _t("Try scrolling up in the timeline to see if there are any earlier ones.") }

      , }); } else { - const {finished} = Modal.createTrackedDialog('Remove recent messages by user', '', QuestionDialog, { - title: _t("Remove recent messages by %(user)s", {user}), + const { finished } = Modal.createTrackedDialog('Remove recent messages by user', '', QuestionDialog, { + title: _t("Remove recent messages by %(user)s", { user }), description:

      { _t("You are about to remove %(count)s messages by %(user)s. " + - "This cannot be undone. Do you wish to continue?", {count, user}) }

      + "This cannot be undone. Do you wish to continue?", { count, user }) }

      { _t("For a large amount of messages, this might take some time. " + "Please don't refresh your client in the meantime.") }

      , - button: _t("Remove %(count)s messages", {count}), + button: _t("Remove %(count)s messages", { count }), }); const [confirmed] = await finished; @@ -654,11 +653,11 @@ const RedactMessagesButton: React.FC = ({member}) => { ; }; -const BanToggleButton: React.FC = ({member, startUpdating, stopUpdating}) => { +const BanToggleButton: React.FC = ({ member, startUpdating, stopUpdating }) => { const cli = useContext(MatrixClientContext); const onBanOrUnban = async () => { - const {finished} = Modal.createTrackedDialog( + const { finished } = Modal.createTrackedDialog( 'Confirm User Action Dialog', 'onBanOrUnban', ConfirmUserActionDialog, @@ -715,7 +714,7 @@ interface IBaseRoomProps extends IBaseProps { powerLevels: IPowerLevelsContent; } -const MuteToggleButton: React.FC = ({member, room, powerLevels, startUpdating, stopUpdating}) => { +const MuteToggleButton: React.FC = ({ member, room, powerLevels, startUpdating, stopUpdating }) => { const cli = useContext(MatrixClientContext); // Don't show the mute/unmute option if the user is not in the room @@ -862,7 +861,7 @@ const GroupAdminToolsSection: React.FC<{ groupMember: GroupMember; startUpdating(): void; stopUpdating(): void; -}> = ({children, groupId, groupMember, startUpdating, stopUpdating}) => { +}> = ({ children, groupId, groupMember, startUpdating, stopUpdating }) => { const cli = useContext(MatrixClientContext); const [isPrivileged, setIsPrivileged] = useState(false); @@ -891,7 +890,7 @@ const GroupAdminToolsSection: React.FC<{ if (isPrivileged) { const onKick = async () => { - const {finished} = Modal.createDialog(ConfirmUserActionDialog, { + const { finished } = Modal.createDialog(ConfirmUserActionDialog, { matrixClient: cli, groupMember, action: isInvited ? _t('Disinvite') : _t('Remove from community'), @@ -1029,7 +1028,7 @@ const PowerLevelSection: React.FC<{ room: Room; roomPermissions: IRoomPermissions; powerLevels: IPowerLevelsContent; -}> = ({user, room, roomPermissions, powerLevels}) => { +}> = ({ user, room, roomPermissions, powerLevels }) => { if (roomPermissions.canEdit) { return (); } else { @@ -1048,7 +1047,7 @@ const PowerLevelEditor: React.FC<{ user: RoomMember; room: Room; roomPermissions: IRoomPermissions; -}> = ({user, room, roomPermissions}) => { +}> = ({ user, room, roomPermissions }) => { const cli = useContext(MatrixClientContext); const [selectedPowerLevel, setSelectedPowerLevel] = useState(user.powerLevel); @@ -1081,7 +1080,7 @@ const PowerLevelEditor: React.FC<{ const myUserId = cli.getUserId(); const myPower = powerLevelEvent.getContent().users[myUserId]; if (myPower && parseInt(myPower) === powerLevel) { - const {finished} = Modal.createTrackedDialog('Promote to PL100 Warning', '', QuestionDialog, { + const { finished } = Modal.createTrackedDialog('Promote to PL100 Warning', '', QuestionDialog, { title: _t("Warning!"), description:
      @@ -1198,7 +1197,7 @@ const BasicUserInfo: React.FC<{ groupId: string; devices: IDevice[]; isRoomEncrypted: boolean; -}> = ({room, member, groupId, devices, isRoomEncrypted}) => { +}> = ({ room, member, groupId, devices, isRoomEncrypted }) => { const cli = useContext(MatrixClientContext); const powerLevels = useRoomPowerLevels(cli, room); @@ -1231,7 +1230,7 @@ const BasicUserInfo: React.FC<{ const roomPermissions = useRoomPermissions(cli, room, member as RoomMember); const onSynapseDeactivate = useCallback(async () => { - const {finished} = Modal.createTrackedDialog('Synapse User Deactivation', '', QuestionDialog, { + const { finished } = Modal.createTrackedDialog('Synapse User Deactivation', '', QuestionDialog, { title: _t("Deactivate user?"), description:
      { _t( @@ -1382,7 +1381,7 @@ const BasicUserInfo: React.FC<{ }}> { _t("Edit devices") } -

      ) +

      ); } const securitySection = ( @@ -1420,7 +1419,7 @@ type Member = User | RoomMember | GroupMember; const UserInfoHeader: React.FC<{ member: Member; e2eStatus: E2EStatus; -}> = ({member, e2eStatus}) => { +}> = ({ member, e2eStatus }) => { const cli = useContext(MatrixClientContext); const onMemberAvatarClick = useCallback(() => { @@ -1567,7 +1566,7 @@ const UserInfo: React.FC = ({ // We have no previousPhase for when viewing a UserInfo from a Group or without a Room at this time if (room && phase === RightPanelPhases.EncryptionPanel) { previousPhase = RightPanelPhases.RoomMemberInfo; - refireParams = {member: member}; + refireParams = { member: member }; } else if (room) { previousPhase = previousPhase = SettingsStore.getValue("feature_spaces") && room.isSpaceRoom() ? RightPanelPhases.SpaceMemberList @@ -1580,7 +1579,7 @@ const UserInfo: React.FC = ({ phase: previousPhase, refireParams: refireParams, }); - } + }; let content; switch (phase) { diff --git a/src/components/views/right_panel/VerificationPanel.tsx b/src/components/views/right_panel/VerificationPanel.tsx index d3f2ba8cbf..6087923057 100644 --- a/src/components/views/right_panel/VerificationPanel.tsx +++ b/src/components/views/right_panel/VerificationPanel.tsx @@ -16,18 +16,18 @@ limitations under the License. import React from "react"; -import {MatrixClientPeg} from "../../../MatrixClientPeg"; +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"; -import {RoomMember} from "matrix-js-sdk/src/models/room-member"; +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"; +import { RoomMember } from "matrix-js-sdk/src/models/room-member"; import { User } from "matrix-js-sdk/src/models/user"; -import {ReciprocateQRCode} from "matrix-js-sdk/src/crypto/verification/QRCode"; -import {SAS} from "matrix-js-sdk/src/crypto/verification/SAS"; +import { ReciprocateQRCode } from "matrix-js-sdk/src/crypto/verification/QRCode"; +import { SAS } from "matrix-js-sdk/src/crypto/verification/SAS"; import VerificationQRCode from "../elements/crypto/VerificationQRCode"; -import {_t} from "../../../languageHandler"; +import { _t } from "../../../languageHandler"; import SdkConfig from "../../../SdkConfig"; import E2EIcon from "../rooms/E2EIcon"; import { @@ -37,7 +37,7 @@ import { PHASE_CANCELLED, } from "matrix-js-sdk/src/crypto/verification/request/VerificationRequest"; import Spinner from "../elements/Spinner"; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; // XXX: Should be defined in matrix-js-sdk enum VerificationPhase { @@ -78,7 +78,7 @@ export default class VerificationPanel extends React.PureComponent { - this.setState({reciprocateButtonClicked: true}); + this.setState({ reciprocateButtonClicked: true }); this.state.reciprocateQREvent.confirm(); }; private onReciprocateNoClick = () => { - this.setState({reciprocateButtonClicked: true}); + this.setState({ reciprocateButtonClicked: true }); this.state.reciprocateQREvent.cancel(); }; @@ -194,7 +194,7 @@ export default class VerificationPanel extends React.PureComponent { - this.setState({emojiButtonClicked: true}); + this.setState({ emojiButtonClicked: true }); const verifier = this.props.request.beginKeyVerification(verificationMethods.SAS); try { await verifier.verify(); @@ -379,15 +379,15 @@ export default class VerificationPanel extends React.PureComponent { - const {request} = this.props; - const {sasEvent, reciprocateQREvent} = request.verifier; + const { request } = this.props; + const { sasEvent, reciprocateQREvent } = request.verifier; request.verifier.off('show_sas', this.updateVerifierState); request.verifier.off('show_reciprocate_qr', this.updateVerifierState); - this.setState({sasEvent, reciprocateQREvent}); + this.setState({ sasEvent, reciprocateQREvent }); }; private onRequestChange = async () => { - const {request} = this.props; + const { request } = this.props; const hadVerifier = this.hasVerifier; this.hasVerifier = !!request.verifier; if (!hadVerifier && this.hasVerifier) { @@ -404,17 +404,17 @@ export default class VerificationPanel extends React.PureComponent { if (!this.props.domain) { return super.renderNewItemField(); } - const onChange = (alias) => this.onNewItemChanged({target: {value: alias}}); + const onChange = (alias) => this.onNewItemChanged({ target: { value: alias } }); return ( { "or a temporary failure occurred.", ), }); - this.setState({canonicalAlias: oldAlias}); + this.setState({ canonicalAlias: oldAlias }); }).finally(() => { - this.setState({updatingCanonicalAlias: false}); + this.setState({ updatingCanonicalAlias: false }); }); } @@ -213,7 +213,7 @@ export default class AliasSettings extends React.Component { ), }); }).finally(() => { - this.setState({updatingCanonicalAlias: false}); + this.setState({ updatingCanonicalAlias: false }); }); } @@ -253,7 +253,7 @@ export default class AliasSettings extends React.Component { // to this room. See https://github.com/vector-im/element-web/issues/7353 MatrixClientPeg.get().deleteAlias(alias).then(() => { const localAliases = this.state.localAliases.filter(a => a !== alias); - this.setState({localAliases}); + this.setState({ localAliases }); if (this.state.canonicalAlias === alias) { this.changeCanonicalAlias(null); @@ -293,7 +293,7 @@ export default class AliasSettings extends React.Component { private onNewAltAliasChanged = (value: string) => { this.setState({ newAltAlias: value }); - } + }; private onAltAliasAdded = (alias: string) => { const altAliases = this.state.altAliases.slice(); @@ -302,20 +302,20 @@ export default class AliasSettings extends React.Component { this.changeAltAliases(altAliases); this.setState({ newAltAlias: "" }); } - } + }; private onAltAliasDeleted = (index: number) => { const altAliases = this.state.altAliases.slice(); altAliases.splice(index, 1); this.changeAltAliases(altAliases); - } + }; private getAliases() { return this.state.altAliases.concat(this.getLocalNonAltAliases()); } private getLocalNonAltAliases() { - const {altAliases} = this.state; + const { altAliases } = this.state; return this.state.localAliases.filter(alias => !altAliases.includes(alias)); } diff --git a/src/components/views/room_settings/RelatedGroupSettings.js b/src/components/views/room_settings/RelatedGroupSettings.js index 272ecd1228..f2533bc11e 100644 --- a/src/components/views/room_settings/RelatedGroupSettings.js +++ b/src/components/views/room_settings/RelatedGroupSettings.js @@ -16,13 +16,13 @@ limitations under the License. import React from 'react'; import PropTypes from 'prop-types'; -import {MatrixEvent} from 'matrix-js-sdk/src/models/event'; +import { MatrixEvent } from 'matrix-js-sdk/src/models/event'; import * as sdk from '../../../index'; import { _t } from '../../../languageHandler'; import Modal from '../../../Modal'; import ErrorDialog from "../dialogs/ErrorDialog"; import MatrixClientContext from "../../../contexts/MatrixClientContext"; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; const GROUP_ID_REGEX = /\+\S+:\S+/; @@ -116,7 +116,7 @@ export default class RelatedGroupSettings extends React.Component { itemsLabel={_t('Showing flair for these communities:')} noItemsLabel={_t('This room is not showing flair for any communities')} placeholder={_t( - 'New community ID (e.g. +foo:%(localDomain)s)', {localDomain}, + 'New community ID (e.g. +foo:%(localDomain)s)', { localDomain }, )} />
      ; diff --git a/src/components/views/room_settings/RoomProfileSettings.js b/src/components/views/room_settings/RoomProfileSettings.js index b6885887b1..ded186af9c 100644 --- a/src/components/views/room_settings/RoomProfileSettings.js +++ b/src/components/views/room_settings/RoomProfileSettings.js @@ -14,14 +14,14 @@ See the License for the specific language governing permissions and limitations under the License. */ -import React, {createRef} from 'react'; +import React, { createRef } from 'react'; import PropTypes from 'prop-types'; -import {_t} from "../../../languageHandler"; -import {MatrixClientPeg} from "../../../MatrixClientPeg"; +import { _t } from "../../../languageHandler"; +import { MatrixClientPeg } from "../../../MatrixClientPeg"; import Field from "../elements/Field"; import * as sdk from "../../../index"; -import {replaceableComponent} from "../../../utils/replaceableComponent"; -import {mediaFromMxc} from "../../../customisations/Media"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; +import { mediaFromMxc } from "../../../customisations/Media"; // TODO: Merge with ProfileSettings? @replaceableComponent("views.room_settings.RoomProfileSettings") @@ -97,7 +97,7 @@ export default class RoomProfileSettings extends React.Component { e.preventDefault(); if (!this.state.enableProfileSave) return; - this.setState({enableProfileSave: false}); + this.setState({ enableProfileSave: false }); const client = MatrixClientPeg.get(); const newState = {}; @@ -112,7 +112,7 @@ export default class RoomProfileSettings extends React.Component { if (this.state.avatarFile) { const uri = await client.uploadContent(this.state.avatarFile); - await client.sendStateEvent(this.props.roomId, 'm.room.avatar', {url: uri}, ''); + await client.sendStateEvent(this.props.roomId, 'm.room.avatar', { url: uri }, ''); newState.avatarUrl = mediaFromMxc(uri).getSquareThumbnailHttp(96); newState.originalAvatarUrl = newState.avatarUrl; newState.avatarFile = null; @@ -129,20 +129,20 @@ export default class RoomProfileSettings extends React.Component { }; _onDisplayNameChanged = (e) => { - this.setState({displayName: e.target.value}); + this.setState({ displayName: e.target.value }); if (this.state.originalDisplayName === e.target.value) { - this.setState({enableProfileSave: false}); + this.setState({ enableProfileSave: false }); } else { - this.setState({enableProfileSave: true}); + this.setState({ enableProfileSave: true }); } }; _onTopicChanged = (e) => { - this.setState({topic: e.target.value}); + this.setState({ topic: e.target.value }); if (this.state.originalTopic === e.target.value) { - this.setState({enableProfileSave: false}); + this.setState({ enableProfileSave: false }); } else { - this.setState({enableProfileSave: true}); + this.setState({ enableProfileSave: true }); } }; diff --git a/src/components/views/room_settings/RoomPublishSetting.tsx b/src/components/views/room_settings/RoomPublishSetting.tsx index 95b0ac100d..bc1d6f9e2c 100644 --- a/src/components/views/room_settings/RoomPublishSetting.tsx +++ b/src/components/views/room_settings/RoomPublishSetting.tsx @@ -44,7 +44,7 @@ export default class RoomPublishSetting extends React.PureComponent { const valueBefore = this.state.isRoomPublished; const newValue = !valueBefore; - this.setState({isRoomPublished: newValue}); + this.setState({ isRoomPublished: newValue }); const client = MatrixClientPeg.get(); client.setRoomDirectoryVisibility( @@ -52,14 +52,14 @@ export default class RoomPublishSetting extends React.PureComponent { // Roll back the local echo on the change - this.setState({isRoomPublished: valueBefore}); + this.setState({ isRoomPublished: valueBefore }); }); }; componentDidMount() { const client = MatrixClientPeg.get(); client.getRoomDirectoryVisibility(this.props.roomId).then((result => { - this.setState({isRoomPublished: result.visibility === 'public'}); + this.setState({ isRoomPublished: result.visibility === 'public' }); })); } diff --git a/src/components/views/room_settings/UrlPreviewSettings.js b/src/components/views/room_settings/UrlPreviewSettings.js index f797ffeb96..0ff3b051d6 100644 --- a/src/components/views/room_settings/UrlPreviewSettings.js +++ b/src/components/views/room_settings/UrlPreviewSettings.js @@ -23,10 +23,10 @@ import * as sdk from "../../../index"; import { _t, _td } from '../../../languageHandler'; import SettingsStore from "../../../settings/SettingsStore"; import dis from "../../../dispatcher/dispatcher"; -import {MatrixClientPeg} from "../../../MatrixClientPeg"; -import {Action} from "../../../dispatcher/actions"; -import {SettingLevel} from "../../../settings/SettingLevel"; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { MatrixClientPeg } from "../../../MatrixClientPeg"; +import { Action } from "../../../dispatcher/actions"; +import { SettingLevel } from "../../../settings/SettingLevel"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; @replaceableComponent("views.room_settings.UrlPreviewSettings") export default class UrlPreviewSettings extends React.Component { diff --git a/src/components/views/rooms/AppsDrawer.js b/src/components/views/rooms/AppsDrawer.js index 0b32d5d1bb..2866780255 100644 --- a/src/components/views/rooms/AppsDrawer.js +++ b/src/components/views/rooms/AppsDrawer.js @@ -18,7 +18,7 @@ limitations under the License. import React from 'react'; import PropTypes from 'prop-types'; import classNames from 'classnames'; -import {Resizable} from "re-resizable"; +import { Resizable } from "re-resizable"; import AppTile from '../elements/AppTile'; import dis from '../../../dispatcher/dispatcher'; @@ -26,16 +26,16 @@ import * as sdk from '../../../index'; import * as ScalarMessaging from '../../../ScalarMessaging'; import WidgetUtils from '../../../utils/WidgetUtils'; import WidgetEchoStore from "../../../stores/WidgetEchoStore"; -import {IntegrationManagers} from "../../../integrations/IntegrationManagers"; +import { IntegrationManagers } from "../../../integrations/IntegrationManagers"; import SettingsStore from "../../../settings/SettingsStore"; import ResizeNotifier from "../../../utils/ResizeNotifier"; import ResizeHandle from "../elements/ResizeHandle"; import Resizer from "../../../resizer/resizer"; import PercentageDistributor from "../../../resizer/distributors/percentage"; -import {Container, WidgetLayoutStore} from "../../../stores/widgets/WidgetLayoutStore"; -import {clamp, percentageOf, percentageWithin} from "../../../utils/numbers"; -import {useStateCallback} from "../../../hooks/useStateCallback"; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { Container, WidgetLayoutStore } from "../../../stores/widgets/WidgetLayoutStore"; +import { clamp, percentageOf, percentageWithin } from "../../../utils/numbers"; +import { useStateCallback } from "../../../hooks/useStateCallback"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; import UIStore from "../../../stores/UIStore"; @replaceableComponent("views.rooms.AppsDrawer") @@ -303,7 +303,7 @@ const PersistentVResizer = ({ }); return { @@ -317,9 +317,9 @@ const PersistentVResizer = ({ resizeNotifier.stopResizing(); }} handleWrapperClass={handleWrapperClass} - handleClasses={{bottom: handleClass}} + handleClasses={{ bottom: handleClass }} className={className} - enable={{bottom: true}} + enable={{ bottom: true }} > { children } ; diff --git a/src/components/views/rooms/Autocomplete.tsx b/src/components/views/rooms/Autocomplete.tsx index 7054741da4..8fbecbe722 100644 --- a/src/components/views/rooms/Autocomplete.tsx +++ b/src/components/views/rooms/Autocomplete.tsx @@ -15,15 +15,15 @@ See the License for the specific language governing permissions and limitations under the License. */ -import React, {createRef, KeyboardEvent} from 'react'; +import React, { createRef, KeyboardEvent } from 'react'; import classNames from 'classnames'; -import {flatMap} from "lodash"; -import {ICompletion, ISelectionRange, IProviderCompletions} from '../../../autocomplete/Autocompleter'; -import {Room} from 'matrix-js-sdk/src/models/room'; +import { flatMap } from "lodash"; +import { ICompletion, ISelectionRange, IProviderCompletions } from '../../../autocomplete/Autocompleter'; +import { Room } from 'matrix-js-sdk/src/models/room'; import SettingsStore from "../../../settings/SettingsStore"; import Autocompleter from '../../../autocomplete/Autocompleter'; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; const COMPOSER_SELECTED = 0; const MAX_PROVIDER_MATCHES = 20; @@ -247,7 +247,7 @@ export default class Autocomplete extends React.PureComponent { }; setSelection(selectionOffset: number) { - this.setState({selectionOffset, hide: false}); + this.setState({ selectionOffset, hide: false }); if (this.props.onSelectionChange) { this.props.onSelectionChange(this.state.completionList[selectionOffset - 1], selectionOffset - 1); } @@ -273,7 +273,7 @@ export default class Autocomplete extends React.PureComponent { const renderedCompletions = this.state.completions.map((completionResult, i) => { const completions = completionResult.completions.map((completion, j) => { const selected = position === this.state.selectionOffset; - const className = classNames('mx_Autocomplete_Completion', {selected}); + const className = classNames('mx_Autocomplete_Completion', { selected }); const componentPosition = position; position++; @@ -291,7 +291,6 @@ export default class Autocomplete extends React.PureComponent { }); }); - return completions.length > 0 ? (
      { completionResult.provider.getName() }
      diff --git a/src/components/views/rooms/AuxPanel.tsx b/src/components/views/rooms/AuxPanel.tsx index 04c7a57048..1c817140fa 100644 --- a/src/components/views/rooms/AuxPanel.tsx +++ b/src/components/views/rooms/AuxPanel.tsx @@ -17,7 +17,7 @@ limitations under the License. import React from 'react'; import classNames from 'classnames'; import { lexicographicCompare } from 'matrix-js-sdk/src/utils'; -import { Room } from 'matrix-js-sdk/src/models/room' +import { Room } from 'matrix-js-sdk/src/models/room'; import { MatrixClientPeg } from "../../../MatrixClientPeg"; import AppsDrawer from './AppsDrawer'; @@ -126,7 +126,7 @@ export default class AuxPanel extends React.Component { link, severity, stateKey, - }) + }); } } } diff --git a/src/components/views/rooms/BasicMessageComposer.tsx b/src/components/views/rooms/BasicMessageComposer.tsx index 981ff1b4ae..94a292afe7 100644 --- a/src/components/views/rooms/BasicMessageComposer.tsx +++ b/src/components/views/rooms/BasicMessageComposer.tsx @@ -147,7 +147,7 @@ export default class BasicMessageEditor extends React.Component const enabledChange = this.props.disabled !== prevProps.disabled; const placeholderChanged = this.props.placeholder !== prevProps.placeholder; if (this.props.placeholder && (placeholderChanged || enabledChange)) { - const {isEmpty} = this.props.model; + const { isEmpty } = this.props.model; if (isEmpty) { this.showPlaceholder(); } else { @@ -157,7 +157,7 @@ export default class BasicMessageEditor extends React.Component } private replaceEmoticon = (caretPosition: DocumentPosition) => { - const {model} = this.props; + const { model } = this.props; const range = model.startRange(caretPosition); // expand range max 8 characters backwards from caretPosition, // as a space to look for an emoticon @@ -174,7 +174,7 @@ export default class BasicMessageEditor extends React.Component const data = EMOTICON_TO_EMOJI.get(query) || EMOTICON_TO_EMOJI.get(query.toLowerCase()); if (data) { - const {partCreator} = model; + const { partCreator } = model; const hasPrecedingSpace = emoticonMatch[0][0] === " "; // we need the range to only comprise of the emoticon // because we'll replace the whole range with an emoji, @@ -200,7 +200,7 @@ export default class BasicMessageEditor extends React.Component const position = selection instanceof Range ? selection.end : selection; this.setLastCaretFromPosition(position); } - const {isEmpty} = this.props.model; + const { isEmpty } = this.props.model; if (this.props.placeholder) { if (isEmpty) { this.showPlaceholder(); @@ -211,13 +211,13 @@ export default class BasicMessageEditor extends React.Component if (isEmpty) { this.formatBarRef.current.hide(); } - this.setState({autoComplete: this.props.model.autoComplete}); + this.setState({ autoComplete: this.props.model.autoComplete }); this.historyManager.tryPush(this.props.model, selection, inputType, diff); let isTyping = !this.props.model.isEmpty; // If the user is entering a command, only consider them typing if it is one which sends a message into the room if (isTyping && this.props.model.parts[0].type === "command") { - const {cmd} = parseCommandString(this.props.model.parts[0].text); + const { cmd } = parseCommandString(this.props.model.parts[0].text); const command = CommandMap.get(cmd); if (!command || !command.isEnabled() || command.category !== CommandCategories.messages) { isTyping = false; @@ -263,10 +263,10 @@ export default class BasicMessageEditor extends React.Component const isSafari = ua.includes('safari/') && !ua.includes('chrome/'); if (isSafari) { - this.onInput({inputType: "insertCompositionText"}); + this.onInput({ inputType: "insertCompositionText" }); } else { Promise.resolve().then(() => { - this.onInput({inputType: "insertCompositionText"}); + this.onInput({ inputType: "insertCompositionText" }); }); } }; @@ -282,7 +282,7 @@ export default class BasicMessageEditor extends React.Component const selection = document.getSelection(); const text = selection.toString(); if (text) { - const {model} = this.props; + const { model } = this.props; const range = getRangeForSelection(this.editorRef.current, model, selection); const selectedParts = range.parts.map(p => p.serialize()); event.clipboardData.setData("application/x-element-composer", JSON.stringify(selectedParts)); @@ -311,8 +311,8 @@ export default class BasicMessageEditor extends React.Component return true; } - const {model} = this.props; - const {partCreator} = model; + const { model } = this.props; + const { partCreator } = model; const partsText = event.clipboardData.getData("application/x-element-composer"); let parts; if (partsText) { @@ -335,13 +335,13 @@ export default class BasicMessageEditor extends React.Component } this.modifiedFlag = true; const sel = document.getSelection(); - const {caret, text} = getCaretOffsetAndText(this.editorRef.current, sel); + const { caret, text } = getCaretOffsetAndText(this.editorRef.current, sel); this.props.model.update(text, event.inputType, caret); }; private insertText(textToInsert: string, inputType = "insertText") { const sel = document.getSelection(); - const {caret, text} = getCaretOffsetAndText(this.editorRef.current, sel); + const { caret, text } = getCaretOffsetAndText(this.editorRef.current, sel); const newText = text.substr(0, caret.offset) + textToInsert + text.substr(caret.offset); caret.offset += textToInsert.length; this.modifiedFlag = true; @@ -354,7 +354,7 @@ export default class BasicMessageEditor extends React.Component // we need to recalculate it, to be able to know where to insert content after // losing focus private setLastCaretFromPosition(position: DocumentPosition) { - const {model} = this.props; + const { model } = this.props; this._isCaretAtEnd = position.isAtEnd(model); this.lastCaret = position.asOffset(model); this.lastSelection = cloneSelection(document.getSelection()); @@ -370,7 +370,7 @@ export default class BasicMessageEditor extends React.Component const selection = document.getSelection(); if (!this.lastSelection || !selectionEquals(this.lastSelection, selection)) { this.lastSelection = cloneSelection(selection); - const {caret, text} = getCaretOffsetAndText(this.editorRef.current, selection); + const { caret, text } = getCaretOffsetAndText(this.editorRef.current, selection); this.lastCaret = caret; this._isCaretAtEnd = caret.offset === text.length; } @@ -409,7 +409,7 @@ export default class BasicMessageEditor extends React.Component }; private onSelectionChange = () => { - const {isEmpty} = this.props.model; + const { isEmpty } = this.props.model; this.refreshLastCaretIfNeeded(); const selection = document.getSelection(); @@ -446,7 +446,7 @@ export default class BasicMessageEditor extends React.Component break; case MessageComposerAction.EditRedo: if (this.historyManager.canRedo()) { - const {parts, caret} = this.historyManager.redo(); + const { parts, caret } = this.historyManager.redo(); // pass matching inputType so historyManager doesn't push echo // when invoked from rerender callback. model.reset(parts, caret, "historyRedo"); @@ -455,7 +455,7 @@ export default class BasicMessageEditor extends React.Component break; case MessageComposerAction.EditUndo: if (this.historyManager.canUndo()) { - const {parts, caret} = this.historyManager.undo(this.props.model); + const { parts, caret } = this.historyManager.undo(this.props.model); // pass matching inputType so historyManager doesn't push echo // when invoked from rerender callback. model.reset(parts, caret, "historyUndo"); @@ -525,8 +525,8 @@ export default class BasicMessageEditor extends React.Component private async tabCompleteName() { try { - await new Promise(resolve => this.setState({showVisualBell: false}, resolve)); - const {model} = this.props; + await new Promise(resolve => this.setState({ showVisualBell: false }, resolve)); + const { model } = this.props; const caret = this.getCaret(); const position = model.positionForOffset(caret.offset, caret.atNodeEnd); const range = model.startRange(position); @@ -537,7 +537,7 @@ export default class BasicMessageEditor extends React.Component part.type === "command" ); }); - const {partCreator} = model; + const { partCreator } = model; // await for auto-complete to be open await model.transform(() => { const addedLen = range.replace([partCreator.pillCandidate(range.text)]); @@ -548,7 +548,7 @@ export default class BasicMessageEditor extends React.Component if (model.autoComplete) { await model.autoComplete.startSelection(); if (!model.autoComplete.hasSelection()) { - this.setState({showVisualBell: true}); + this.setState({ showVisualBell: true }); model.autoComplete.close(); } } @@ -569,7 +569,7 @@ export default class BasicMessageEditor extends React.Component private onAutoCompleteSelectionChange = (completion: ICompletion, completionIndex: number) => { this.modifiedFlag = true; this.props.model.autoComplete.onComponentSelectionChange(completion); - this.setState({completionIndex}); + this.setState({ completionIndex }); }; private configureEmoticonAutoReplace = () => { @@ -599,7 +599,7 @@ export default class BasicMessageEditor extends React.Component // not really, but we could not serialize the parts, and just change the autoCompleter partCreator.setAutoCompleteCreator(getAutoCompleteCreator( () => this.autocompleteRef.current, - query => new Promise(resolve => this.setState({query}, resolve)), + query => new Promise(resolve => this.setState({ query }, resolve)), )); // initial render of model this.updateEditorState(this.getInitialCaretPosition()); @@ -666,7 +666,7 @@ export default class BasicMessageEditor extends React.Component query={query} onConfirm={this.onAutoCompleteConfirm} onSelectionChange={this.onAutoCompleteSelectionChange} - selection={{beginning: true, end: queryLen, start: queryLen}} + selection={{ beginning: true, end: queryLen, start: queryLen }} room={this.props.room} />
      ); @@ -685,7 +685,7 @@ export default class BasicMessageEditor extends React.Component quote: ctrlShortcutLabel(">"), }; - const {completionIndex} = this.state; + const { completionIndex } = this.state; return (
      { autoComplete } @@ -719,8 +719,8 @@ export default class BasicMessageEditor extends React.Component } public insertMention(userId: string) { - const {model} = this.props; - const {partCreator} = model; + const { model } = this.props; + const { partCreator } = model; const member = this.props.room.getMember(userId); const displayName = member ? member.rawDisplayName : userId; @@ -737,9 +737,9 @@ export default class BasicMessageEditor extends React.Component } public insertQuotedMessage(event: MatrixEvent) { - const {model} = this.props; - const {partCreator} = model; - const quoteParts = parseEvent(event, partCreator, {isQuotedMessage: true}); + const { model } = this.props; + const { partCreator } = model; + const quoteParts = parseEvent(event, partCreator, { isQuotedMessage: true }); // add two newlines quoteParts.push(partCreator.newline()); quoteParts.push(partCreator.newline()); @@ -752,8 +752,8 @@ export default class BasicMessageEditor extends React.Component } public insertPlaintext(text: string) { - const {model} = this.props; - const {partCreator} = model; + const { model } = this.props; + const { partCreator } = model; const caret = this.getCaret(); const position = model.positionForOffset(caret.offset, caret.atNodeEnd); model.transform(() => { diff --git a/src/components/views/rooms/E2EIcon.js b/src/components/views/rooms/E2EIcon.js index d7316f198d..7425af6060 100644 --- a/src/components/views/rooms/E2EIcon.js +++ b/src/components/views/rooms/E2EIcon.js @@ -15,11 +15,11 @@ See the License for the specific language governing permissions and limitations under the License. */ -import React, {useState} from "react"; +import React, { useState } from "react"; import PropTypes from "prop-types"; import classNames from 'classnames'; -import {_t, _td} from '../../../languageHandler'; +import { _t, _td } from '../../../languageHandler'; import AccessibleButton from "../elements/AccessibleButton"; import Tooltip from "../elements/Tooltip"; @@ -42,7 +42,7 @@ const crossSigningRoomTitles = { [E2E_STATE.VERIFIED]: _td("Everyone in this room is verified"), }; -const E2EIcon = ({isUser, status, className, size, onClick, hideTooltip, bordered}) => { +const E2EIcon = ({ isUser, status, className, size, onClick, hideTooltip, bordered }) => { const [hover, setHover] = useState(false); const classes = classNames({ @@ -62,7 +62,7 @@ const E2EIcon = ({isUser, status, className, size, onClick, hideTooltip, bordere let style; if (size) { - style = {width: `${size}px`, height: `${size}px`}; + style = { width: `${size}px`, height: `${size}px` }; } const onMouseOver = () => setHover(true); diff --git a/src/components/views/rooms/EditMessageComposer.js b/src/components/views/rooms/EditMessageComposer.js index 914f08eac7..0ab972b5f1 100644 --- a/src/components/views/rooms/EditMessageComposer.js +++ b/src/components/views/rooms/EditMessageComposer.js @@ -88,7 +88,7 @@ function createEditContent(model, editedEvent) { body: `${plainPrefix} * ${body}`, }; - const formattedBody = htmlSerializeIfNeeded(model, {forceHTML: isReply}); + const formattedBody = htmlSerializeIfNeeded(model, { forceHTML: isReply }); if (formattedBody) { newContent.format = "org.matrix.custom.html"; newContent.formatted_body = formattedBody; @@ -156,7 +156,7 @@ export default class EditMessageComposer extends React.Component { const previousEvent = findEditableEvent(this._getRoom(), false, this.props.editState.getEvent().getId()); if (previousEvent) { - dis.dispatch({action: 'edit_event', event: previousEvent}); + dis.dispatch({ action: 'edit_event', event: previousEvent }); event.preventDefault(); } break; @@ -167,10 +167,10 @@ export default class EditMessageComposer extends React.Component { } const nextEvent = findEditableEvent(this._getRoom(), true, this.props.editState.getEvent().getId()); if (nextEvent) { - dis.dispatch({action: 'edit_event', event: nextEvent}); + dis.dispatch({ action: 'edit_event', event: nextEvent }); } else { this._clearStoredEditorState(); - dis.dispatch({action: 'edit_event', event: null}); + dis.dispatch({ action: 'edit_event', event: null }); dis.fire(Action.FocusComposer); } event.preventDefault(); @@ -189,7 +189,7 @@ export default class EditMessageComposer extends React.Component { _cancelEdit = () => { this._clearStoredEditorState(); - dis.dispatch({action: "edit_event", event: null}); + dis.dispatch({ action: "edit_event", event: null }); dis.fire(Action.FocusComposer); } @@ -201,7 +201,7 @@ export default class EditMessageComposer extends React.Component { const json = localStorage.getItem(this._editorStateKey); if (json) { try { - const {parts: serializedParts} = JSON.parse(json); + const { parts: serializedParts } = JSON.parse(json); const parts = serializedParts.map(p => partCreator.deserializePart(p)); return parts; } catch (e) { @@ -264,7 +264,7 @@ export default class EditMessageComposer extends React.Component { } return text + part.text; }, ""); - const {cmd, args} = getCommand(commandText); + const { cmd, args } = getCommand(commandText); return [cmd, args, commandText]; } @@ -332,11 +332,11 @@ export default class EditMessageComposer extends React.Component { } else { // ask the user if their unknown command should be sent as a message const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog"); - const {finished} = Modal.createTrackedDialog("Unknown command", "", QuestionDialog, { + const { finished } = Modal.createTrackedDialog("Unknown command", "", QuestionDialog, { title: _t("Unknown Command"), description:

      - { _t("Unrecognised command: %(commandText)s", {commandText}) } + { _t("Unrecognised command: %(commandText)s", { commandText }) }

      { _t("You can use /help to list available commands. " + @@ -361,13 +361,13 @@ export default class EditMessageComposer extends React.Component { this._cancelPreviousPendingEdit(); const prom = this.context.sendMessage(roomId, editContent); this._clearStoredEditorState(); - dis.dispatch({action: "message_sent"}); + dis.dispatch({ action: "message_sent" }); CountlyAnalytics.instance.trackSendMessage(startTime, prom, roomId, true, false, editContent); } } // close the event editing and focus composer - dis.dispatch({action: "edit_event", event: null}); + dis.dispatch({ action: "edit_event", event: null }); dis.fire(Action.FocusComposer); }; @@ -404,7 +404,7 @@ export default class EditMessageComposer extends React.Component { } _createEditorModel() { - const {editState} = this.props; + const { editState } = this.props; const room = this._getRoom(); const partCreator = new CommandPartCreator(room, this.context); let parts; @@ -421,7 +421,7 @@ export default class EditMessageComposer extends React.Component { } _getInitialCaretPosition() { - const {editState} = this.props; + const { editState } = this.props; let caretPosition; if (editState.hasEditorState() && editState.getCaret()) { // if restoring state from a previous editor, diff --git a/src/components/views/rooms/EntityTile.tsx b/src/components/views/rooms/EntityTile.tsx index 2032856500..74738c3683 100644 --- a/src/components/views/rooms/EntityTile.tsx +++ b/src/components/views/rooms/EntityTile.tsx @@ -33,7 +33,7 @@ export enum PowerStatus { const PowerLabel: Record = { [PowerStatus.Admin]: _td("Admin"), [PowerStatus.Moderator]: _td("Mod"), -} +}; const PRESENCE_CLASS = { "offline": "mx_EntityTile_offline", @@ -116,7 +116,7 @@ export default class EntityTile extends React.PureComponent { mainClassNames[presenceClass] = true; let nameEl; - const {name} = this.props; + const { name } = this.props; if (!this.props.suppressOnHover) { const activeAgo = this.props.presenceLastActiveAgo ? diff --git a/src/components/views/rooms/EventTile.tsx b/src/components/views/rooms/EventTile.tsx index 78293fcd02..b5b30e2fae 100644 --- a/src/components/views/rooms/EventTile.tsx +++ b/src/components/views/rooms/EventTile.tsx @@ -15,7 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import React from 'react'; +import React, { createRef } from 'react'; import classNames from "classnames"; import { EventType } from "matrix-js-sdk/src/@types/event"; import { EventStatus, MatrixEvent } from "matrix-js-sdk/src/models/event"; @@ -176,12 +176,19 @@ const MAX_READ_AVATARS = 5; // | '--------------------------------------' | // '----------------------------------------------------------' -interface IReadReceiptProps { +export interface IReadReceiptProps { userId: string; roomMember: RoomMember; ts: number; } +export enum TileShape { + Notif = "notif", + FileGrid = "file_grid", + Reply = "reply", + ReplyPreview = "reply_preview", +} + interface IProps { // the MatrixEvent to show mxEvent: MatrixEvent; @@ -248,7 +255,7 @@ interface IProps { // It could also be done by subclassing EventTile, but that'd be quite // boiilerplatey. So just make the necessary render decisions conditional // for now. - tileShape?: 'notif' | 'file_grid' | 'reply' | 'reply_preview'; + tileShape?: TileShape; forExport?: boolean; @@ -308,10 +315,11 @@ interface IState { export default class EventTile extends React.Component { private suppressReadReceiptAnimation: boolean; private isListeningForReceipts: boolean; - private ref: React.RefObject; private tile = React.createRef(); private replyThread = React.createRef(); + public readonly ref = createRef(); + static defaultProps = { // no-op function because onHeightChanged is optional yet some sub-components assume its existence onHeightChanged: function() {}, @@ -348,8 +356,6 @@ export default class EventTile extends React.Component { // to determine if we've already subscribed and use a combination of other flags to find // out if we should even be subscribed at all. this.isListeningForReceipts = false; - - this.ref = React.createRef(); } /** @@ -727,7 +733,7 @@ export default class EventTile extends React.Component { { avatars }

      - ) + ); } onSenderProfileClick = event => { @@ -874,7 +880,7 @@ export default class EventTile extends React.Component { // This shouldn't happen: the caller should check we support this type // before trying to instantiate us if (!tileHandler) { - const {mxEvent} = this.props; + const { mxEvent } = this.props; console.warn(`Event type not supported: type:${mxEvent.getType()} isState:${mxEvent.isState()}`); return
      @@ -1025,7 +1031,7 @@ export default class EventTile extends React.Component { _t( 'Re-request encryption keys from your other sessions.', {}, - {'requestLink': (sub) => { sub }}, + { 'requestLink': (sub) => { sub } }, ); const TooltipButton = sdk.getComponent('elements.TooltipButton'); @@ -1217,7 +1223,7 @@ export default class EventTile extends React.Component { avatar, ]) - ) + ); } } } diff --git a/src/components/views/rooms/ExtraTile.tsx b/src/components/views/rooms/ExtraTile.tsx index 20d12955d5..18c5d50ae8 100644 --- a/src/components/views/rooms/ExtraTile.tsx +++ b/src/components/views/rooms/ExtraTile.tsx @@ -46,11 +46,11 @@ export default class ExtraTile extends React.Component { } private onTileMouseEnter = () => { - this.setState({hover: true}); + this.setState({ hover: true }); }; private onTileMouseLeave = () => { - this.setState({hover: false}); + this.setState({ hover: false }); }; public render(): React.ReactElement { diff --git a/src/components/views/rooms/LinkPreviewWidget.js b/src/components/views/rooms/LinkPreviewWidget.js index 904040a067..360ca41d55 100644 --- a/src/components/views/rooms/LinkPreviewWidget.js +++ b/src/components/views/rooms/LinkPreviewWidget.js @@ -15,18 +15,18 @@ See the License for the specific language governing permissions and limitations under the License. */ -import React, {createRef} from 'react'; +import React, { createRef } from 'react'; import PropTypes from 'prop-types'; import { AllHtmlEntities } from 'html-entities'; -import {linkifyElement} from '../../../HtmlUtils'; +import { linkifyElement } from '../../../HtmlUtils'; import SettingsStore from "../../../settings/SettingsStore"; -import {MatrixClientPeg} from "../../../MatrixClientPeg"; +import { MatrixClientPeg } from "../../../MatrixClientPeg"; import * as sdk from "../../../index"; import Modal from "../../../Modal"; import * as ImageUtils from "../../../ImageUtils"; import { _t } from "../../../languageHandler"; -import {replaceableComponent} from "../../../utils/replaceableComponent"; -import {mediaFromMxc} from "../../../customisations/Media"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; +import { mediaFromMxc } from "../../../customisations/Media"; @replaceableComponent("views.rooms.LinkPreviewWidget") export default class LinkPreviewWidget extends React.Component { diff --git a/src/components/views/rooms/MemberList.tsx b/src/components/views/rooms/MemberList.tsx index 5ebe5bea59..68f87580df 100644 --- a/src/components/views/rooms/MemberList.tsx +++ b/src/components/views/rooms/MemberList.tsx @@ -148,7 +148,7 @@ export default class MemberList extends React.Component { const room = cli.getRoom(this.props.roomId); const membership = room && room.getMyMembership(); if (membership === "join") { - this.setState({loading: true}); + this.setState({ loading: true }); try { await room.loadMembersIfNeeded(); } catch (ex) {/* already logged in RoomView */} @@ -242,7 +242,7 @@ export default class MemberList extends React.Component { }, 500); private updateListNow(): void { - const members = this.roomMembers() + const members = this.roomMembers(); this.setState({ loading: false, @@ -471,7 +471,7 @@ export default class MemberList extends React.Component { } private getChildrenJoined = (start: number, end: number): Array => { - return this.makeMemberTiles(this.state.filteredJoinedMembers.slice(start, end)) + return this.makeMemberTiles(this.state.filteredJoinedMembers.slice(start, end)); }; private getChildCountJoined = (): number => this.state.filteredJoinedMembers.length; @@ -487,7 +487,7 @@ export default class MemberList extends React.Component { private getChildCountInvited = (): number => { return this.state.filteredInvitedMembers.length + (this.getPending3PidInvites() || []).length; - } + }; render() { if (this.state.loading) { @@ -582,7 +582,7 @@ export default class MemberList extends React.Component { onInviteButtonClick = (): void => { if (MatrixClientPeg.get().isGuest()) { - dis.dispatch({action: 'require_registration'}); + dis.dispatch({ action: 'require_registration' }); return; } diff --git a/src/components/views/rooms/MemberTile.tsx b/src/components/views/rooms/MemberTile.tsx index 2f9927a756..ce571f78ad 100644 --- a/src/components/views/rooms/MemberTile.tsx +++ b/src/components/views/rooms/MemberTile.tsx @@ -20,7 +20,7 @@ import React from 'react'; import dis from "../../../dispatcher/dispatcher"; import { _t } from '../../../languageHandler'; import { MatrixClientPeg } from "../../../MatrixClientPeg"; -import {Action} from "../../../dispatcher/actions"; +import { Action } from "../../../dispatcher/actions"; import { replaceableComponent } from "../../../utils/replaceableComponent"; import { RoomMember } from "matrix-js-sdk/src/models/room-member"; import { MatrixEvent } from "matrix-js-sdk/src/models/event"; diff --git a/src/components/views/rooms/MessageComposer.tsx b/src/components/views/rooms/MessageComposer.tsx index f7d562fca0..db57f98025 100644 --- a/src/components/views/rooms/MessageComposer.tsx +++ b/src/components/views/rooms/MessageComposer.tsx @@ -69,7 +69,7 @@ function SendButton(props: ISendButtonProps) { ); } -const EmojiButton = ({addEmoji}) => { +const EmojiButton = ({ addEmoji }) => { const [menuDisplayed, button, openMenu, closeMenu] = useContextMenu(); let contextMenu; @@ -132,11 +132,11 @@ class UploadButton extends React.Component { private onUploadClick = () => { if (MatrixClientPeg.get().isGuest()) { - dis.dispatch({action: 'require_registration'}); + dis.dispatch({ action: 'require_registration' }); return; } this.uploadInput.current.click(); - } + }; private onUploadFileInputChange = (ev: React.ChangeEvent) => { if (ev.target.files.length === 0) return; @@ -157,10 +157,10 @@ class UploadButton extends React.Component { // to empty. // NB. we need to set 'value': the 'files' property is immutable. ev.target.value = ''; - } + }; render() { - const uploadInputStyle = {display: 'none'}; + const uploadInputStyle = { display: 'none' }; return ( { // if we have the member already, do that const me = this.props.room.getMember(MatrixClientPeg.get().getUserId()); if (me) { - this.setState({me}); + this.setState({ me }); return; } // Otherwise, wait for member loading to finish and then update the member for the avatar. @@ -245,7 +245,7 @@ export default class MessageComposer extends React.Component { // will return the promise for the existing operation this.props.room.loadMembersIfNeeded().then(() => { const me = this.props.room.getMember(MatrixClientPeg.get().getUserId()); - this.setState({me}); + this.setState({ me }); }); } @@ -261,12 +261,12 @@ export default class MessageComposer extends React.Component { if (ev.getRoomId() !== this.props.room.roomId) return; if (ev.getType() === 'm.room.tombstone') { - this.setState({tombstone: this.getRoomTombstone()}); + this.setState({ tombstone: this.getRoomTombstone() }); } if (ev.getType() === 'm.room.power_levels') { - this.setState({canSendMessages: this.props.room.maySendMessage()}); + this.setState({ canSendMessages: this.props.room.maySendMessage() }); } - } + }; private getRoomTombstone() { return this.props.room.currentState.getStateEvents('m.room.tombstone', ''); @@ -300,7 +300,7 @@ export default class MessageComposer extends React.Component { viaServers: viaServers, }, }); - } + }; private renderPlaceholderText = () => { if (this.props.replyToEvent) { @@ -316,7 +316,7 @@ export default class MessageComposer extends React.Component { return _t('Send a message…'); } } - } + }; addEmoji(emoji: string) { dis.dispatch({ @@ -335,24 +335,24 @@ export default class MessageComposer extends React.Component { // XXX: Private function access this.messageComposerInput._sendMessage(); - } + }; onChange = (model) => { this.setState({ isComposerEmpty: model.isEmpty, }); - } + }; private onVoiceStoreUpdate = () => { const recording = VoiceRecordingStore.instance.activeRecording; - this.setState({haveRecording: !!recording}); + this.setState({ haveRecording: !!recording }); if (recording) { // We show a little heads up that the recording is about to automatically end soon. The 3s // display time is completely arbitrary. Note that we don't need to deregister the listener // because the recording instance will clean that up for us. - recording.on(RecordingState.EndingSoon, ({secondsLeft}) => { - this.setState({recordingTimeLeftSeconds: secondsLeft}); - setTimeout(() => this.setState({recordingTimeLeftSeconds: null}), 3000); + recording.on(RecordingState.EndingSoon, ({ secondsLeft }) => { + this.setState({ recordingTimeLeftSeconds: secondsLeft }); + setTimeout(() => this.setState({ recordingTimeLeftSeconds: null }), 3000); }); } }; @@ -442,7 +442,7 @@ export default class MessageComposer extends React.Component { const secondsLeft = Math.round(this.state.recordingTimeLeftSeconds); if (secondsLeft) { recordingTooltip = ; } diff --git a/src/components/views/rooms/MessageComposerFormatBar.js b/src/components/views/rooms/MessageComposerFormatBar.js index fc0f785b08..c31538c6cd 100644 --- a/src/components/views/rooms/MessageComposerFormatBar.js +++ b/src/components/views/rooms/MessageComposerFormatBar.js @@ -19,7 +19,7 @@ import PropTypes from 'prop-types'; import { _t } from '../../../languageHandler'; import classNames from 'classnames'; import AccessibleTooltipButton from "../elements/AccessibleTooltipButton"; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; @replaceableComponent("views.rooms.MessageComposerFormatBar") export default class MessageComposerFormatBar extends React.PureComponent { @@ -30,7 +30,7 @@ export default class MessageComposerFormatBar extends React.PureComponent { constructor(props) { super(props); - this.state = {visible: false}; + this.state = { visible: false }; } render() { @@ -47,7 +47,7 @@ export default class MessageComposerFormatBar extends React.PureComponent { } showAt(selectionRect) { - this.setState({visible: true}); + this.setState({ visible: true }); const parentRect = this._formatBarRef.parentElement.getBoundingClientRect(); this._formatBarRef.style.left = `${selectionRect.left - parentRect.left}px`; // 12 is half the height of the bar (e.g. to center it) and 16 is an offset that felt ok. @@ -55,7 +55,7 @@ export default class MessageComposerFormatBar extends React.PureComponent { } hide() { - this.setState({visible: false}); + this.setState({ visible: false }); } } diff --git a/src/components/views/rooms/NewRoomIntro.tsx b/src/components/views/rooms/NewRoomIntro.tsx index cae86846d9..8961bcc253 100644 --- a/src/components/views/rooms/NewRoomIntro.tsx +++ b/src/components/views/rooms/NewRoomIntro.tsx @@ -45,7 +45,7 @@ function hasExpectedEncryptionSettings(matrixClient: MatrixClient, room: Room): const NewRoomIntro = () => { const cli = useContext(MatrixClientContext); - const {room, roomId} = useContext(RoomContext); + const { room, roomId } = useContext(RoomContext); const dmPartner = DMRoomMap.shared().getUserIdForRoomId(roomId); let body; diff --git a/src/components/views/rooms/NotificationBadge.tsx b/src/components/views/rooms/NotificationBadge.tsx index 4b843bfc29..778a8a7215 100644 --- a/src/components/views/rooms/NotificationBadge.tsx +++ b/src/components/views/rooms/NotificationBadge.tsx @@ -21,7 +21,7 @@ import SettingsStore from "../../../settings/SettingsStore"; import AccessibleButton from "../elements/AccessibleButton"; import { XOR } from "../../../@types/common"; import { NOTIFICATION_STATE_UPDATE, NotificationState } from "../../../stores/notifications/NotificationState"; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; interface IProps { notification: NotificationState; @@ -86,7 +86,7 @@ export default class NotificationBadge extends React.PureComponent { - this.setState({showCounts: SettingsStore.getValue("Notifications.alwaysShowBadgeCounts", this.roomId)}); + this.setState({ showCounts: SettingsStore.getValue("Notifications.alwaysShowBadgeCounts", this.roomId) }); }; private onNotificationUpdate = () => { @@ -95,7 +95,7 @@ export default class NotificationBadge extends React.PureComponent // The second update, on the next available tick, causes the "enter" animation to start // again and this time we want to show the newest breadcrumb because it'll be hidden // off screen for the animation. - this.setState({doAnimation: false, skipFirst: true}); - setTimeout(() => this.setState({doAnimation: true, skipFirst: false}), 0); + this.setState({ doAnimation: false, skipFirst: true }); + setTimeout(() => this.setState({ doAnimation: true, skipFirst: false }), 0); }; private viewRoom = (room: Room, index: number) => { Analytics.trackEvent("Breadcrumbs", "click_node", String(index)); - defaultDispatcher.dispatch({action: "view_room", room_id: room.roomId}); + defaultDispatcher.dispatch({ action: "view_room", room_id: room.roomId }); }; public render(): React.ReactElement { @@ -87,7 +87,7 @@ export default class RoomBreadcrumbs extends React.PureComponent className="mx_RoomBreadcrumbs_crumb" key={r.roomId} onClick={() => this.viewRoom(r, i)} - aria-label={_t("Room %(name)s", {name: r.name})} + aria-label={_t("Room %(name)s", { name: r.name })} title={r.name} tooltipClassName="mx_RoomBreadcrumbs_Tooltip" > diff --git a/src/components/views/rooms/RoomDetailList.js b/src/components/views/rooms/RoomDetailList.js index be22cda199..bf2f5418c9 100644 --- a/src/components/views/rooms/RoomDetailList.js +++ b/src/components/views/rooms/RoomDetailList.js @@ -21,8 +21,8 @@ import { _t } from '../../../languageHandler'; import PropTypes from 'prop-types'; import classNames from 'classnames'; -import {roomShape} from './RoomDetailRow'; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { roomShape } from './RoomDetailRow'; +import { replaceableComponent } from "../../../utils/replaceableComponent"; @replaceableComponent("views.rooms.RoomDetailList") export default class RoomDetailList extends React.Component { diff --git a/src/components/views/rooms/RoomDetailRow.js b/src/components/views/rooms/RoomDetailRow.js index ad073f3278..6cee691dfa 100644 --- a/src/components/views/rooms/RoomDetailRow.js +++ b/src/components/views/rooms/RoomDetailRow.js @@ -15,12 +15,12 @@ limitations under the License. */ import * as sdk from '../../../index'; -import React, {createRef} from 'react'; +import React, { createRef } from 'react'; import { _t } from '../../../languageHandler'; import { linkifyElement } from '../../../HtmlUtils'; import PropTypes from 'prop-types'; -import {replaceableComponent} from "../../../utils/replaceableComponent"; -import {mediaFromMxc} from "../../../customisations/Media"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; +import { mediaFromMxc } from "../../../customisations/Media"; export function getDisplayAliasForRoom(room) { return room.canonicalAlias || (room.aliases ? room.aliases[0] : ""); diff --git a/src/components/views/rooms/RoomHeader.js b/src/components/views/rooms/RoomHeader.js index 0e1a7bc60b..ed90760e48 100644 --- a/src/components/views/rooms/RoomHeader.js +++ b/src/components/views/rooms/RoomHeader.js @@ -75,7 +75,7 @@ export default class RoomHeader extends React.Component { }; _rateLimitedUpdate = new RateLimitedFunc(function() { - /* eslint-disable babel/no-invalid-this */ + /* eslint-disable @babel/no-invalid-this */ this.forceUpdate(); }, 500); diff --git a/src/components/views/rooms/RoomList.tsx b/src/components/views/rooms/RoomList.tsx index eb50224a60..c94256800d 100644 --- a/src/components/views/rooms/RoomList.tsx +++ b/src/components/views/rooms/RoomList.tsx @@ -45,9 +45,9 @@ import { objectShallowClone, objectWithOnly } from "../../../utils/objects"; import { IconizedContextMenuOption, IconizedContextMenuOptionList } from "../context_menus/IconizedContextMenu"; import AccessibleButton from "../elements/AccessibleButton"; import { CommunityPrototypeStore } from "../../../stores/CommunityPrototypeStore"; -import SpaceStore, {ISuggestedRoom, SUGGESTED_ROOMS} from "../../../stores/SpaceStore"; -import {showAddExistingRooms, showCreateNewRoom, showSpaceInvite} from "../../../utils/space"; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import SpaceStore, { ISuggestedRoom, SUGGESTED_ROOMS } from "../../../stores/SpaceStore"; +import { showAddExistingRooms, showCreateNewRoom, showSpaceInvite } from "../../../utils/space"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; import RoomAvatar from "../avatars/RoomAvatar"; interface IProps { @@ -119,7 +119,7 @@ const TAG_AESTHETICS: ITagAestheticsMap = { defaultHidden: false, addRoomLabel: _td("Start chat"), onAddRoom: (dispatcher?: Dispatcher) => { - (dispatcher || defaultDispatcher).dispatch({action: 'view_create_chat'}); + (dispatcher || defaultDispatcher).dispatch({ action: 'view_create_chat' }); }, }, [DefaultTagID.Untagged]: { @@ -180,7 +180,7 @@ const TAG_AESTHETICS: ITagAestheticsMap = { e.preventDefault(); e.stopPropagation(); onFinished(); - defaultDispatcher.dispatch({action: "view_create_room"}); + defaultDispatcher.dispatch({ action: "view_create_room" }); }} /> { const newSublists = objectWithOnly(newLists, newListIds); const sublists = objectShallowClone(newSublists, (k, v) => arrayFastClone(v)); - this.setState({sublists, isNameFiltering}, () => { + this.setState({ sublists, isNameFiltering }, () => { this.props.onResize(); }); } @@ -495,7 +495,7 @@ export default class RoomList extends React.PureComponent { resizeNotifier={this.props.resizeNotifier} alwaysVisible={ALWAYS_VISIBLE_TAGS.includes(orderedTagId)} onListCollapse={this.props.onListCollapse} - /> + />; }); } @@ -542,7 +542,7 @@ export default class RoomList extends React.PureComponent { }
      ; } else if (Object.values(this.state.sublists).some(list => list.length > 0)) { - const unfilteredLists = RoomListStore.instance.unfilteredLists + const unfilteredLists = RoomListStore.instance.unfilteredLists; const unfilteredRooms = unfilteredLists[DefaultTagID.Untagged] || []; const unfilteredHistorical = unfilteredLists[DefaultTagID.Archived] || []; const unfilteredFavourite = unfilteredLists[DefaultTagID.Favourite] || []; @@ -572,7 +572,7 @@ export default class RoomList extends React.PureComponent { const sublists = this.renderSublists(); return ( - {({onKeyDownHandler}) => ( + {({ onKeyDownHandler }) => (
      wants to chat", {}, {userName: () => inviterElement}), + _t(" wants to chat", {}, { userName: () => inviterElement }), ]; primaryActionLabel = _t("Start chatting"); } else { @@ -486,7 +486,7 @@ export default class RoomPreviewBar extends React.Component { { roomName: this._roomName() }); subTitle = [ avatar, - _t(" invited you", {}, {userName: () => inviterElement}), + _t(" invited you", {}, { userName: () => inviterElement }), ]; primaryActionLabel = _t("Accept"); } @@ -513,22 +513,22 @@ export default class RoomPreviewBar extends React.Component { case MessageCase.ViewingRoom: { if (this.props.canPreview) { title = _t("You're previewing %(roomName)s. Want to join it?", - {roomName: this._roomName()}); + { roomName: this._roomName() }); } else { title = _t("%(roomName)s can't be previewed. Do you want to join it?", - {roomName: this._roomName(true)}); + { roomName: this._roomName(true) }); } primaryActionLabel = _t("Join the discussion"); primaryActionHandler = this.props.onJoinClick; break; } case MessageCase.RoomNotFound: { - title = _t("%(roomName)s does not exist.", {roomName: this._roomName(true)}); + title = _t("%(roomName)s does not exist.", { roomName: this._roomName(true) }); subTitle = _t("This room doesn't exist. Are you sure you're at the right place?"); break; } case MessageCase.OtherError: { - title = _t("%(roomName)s is not accessible at this time.", {roomName: this._roomName(true)}); + title = _t("%(roomName)s is not accessible at this time.", { roomName: this._roomName(true) }); subTitle = [ _t("Try again later, or ask a room admin to check if you have access."), _t( diff --git a/src/components/views/rooms/RoomSublist.tsx b/src/components/views/rooms/RoomSublist.tsx index 61166b4230..fce9e297a1 100644 --- a/src/components/views/rooms/RoomSublist.tsx +++ b/src/components/views/rooms/RoomSublist.tsx @@ -54,7 +54,7 @@ import ExtraTile from "./ExtraTile"; import { ListNotificationState } from "../../../stores/notifications/ListNotificationState"; import IconizedContextMenu from "../context_menus/IconizedContextMenu"; import { getKeyBindingsManager, RoomListAction } from "../../../KeyBindingsManager"; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; const SHOW_N_BUTTON_HEIGHT = 28; // As defined by CSS const RESIZE_HANDLE_HEIGHT = 4; // As defined by CSS @@ -128,7 +128,7 @@ export default class RoomSublist extends React.Component { rooms: arrayFastClone(RoomListStore.instance.orderedLists[this.props.tagId] || []), }; // Why Object.assign() and not this.state.height? Because TypeScript says no. - this.state = Object.assign(this.state, {height: this.calculateInitialHeight()}); + this.state = Object.assign(this.state, { height: this.calculateInitialHeight() }); } private calculateInitialHeight() { @@ -184,7 +184,7 @@ export default class RoomSublist extends React.Component { // as the rooms can come in one by one we need to reevaluate // the amount of available rooms to cap the amount of requested visible rooms by the layout if (RoomSublist.calcNumTiles(prevState.rooms, prevExtraTiles) !== this.numTiles) { - this.setState({height: this.calculateInitialHeight()}); + this.setState({ height: this.calculateInitialHeight() }); } } @@ -329,12 +329,12 @@ export default class RoomSublist extends React.Component { ) => { const newHeight = this.heightAtStart + delta.height; this.applyHeightChange(newHeight); - this.setState({height: newHeight}); + this.setState({ height: newHeight }); }; private onResizeStart = () => { this.heightAtStart = this.state.height; - this.setState({isResizing: true}); + this.setState({ isResizing: true }); }; private onResizeStop = ( @@ -345,7 +345,7 @@ export default class RoomSublist extends React.Component { ) => { const newHeight = this.heightAtStart + delta.height; this.applyHeightChange(newHeight); - this.setState({isResizing: false, height: newHeight}); + this.setState({ isResizing: false, height: newHeight }); }; private onShowAllClick = () => { @@ -353,7 +353,7 @@ export default class RoomSublist extends React.Component { const numVisibleTiles = this.numVisibleTiles; const newHeight = this.layout.tilesToPixelsWithPadding(this.numTiles, this.padding); this.applyHeightChange(newHeight); - this.setState({height: newHeight}, () => { + this.setState({ height: newHeight }, () => { // focus the top-most new room this.focusRoomTile(numVisibleTiles); }); @@ -362,7 +362,7 @@ export default class RoomSublist extends React.Component { private onShowLessClick = () => { const newHeight = this.layout.tilesToPixelsWithPadding(this.layout.defaultVisibleTiles, this.padding); this.applyHeightChange(newHeight); - this.setState({height: newHeight}); + this.setState({ height: newHeight }); }; private focusRoomTile = (index: number) => { @@ -378,7 +378,7 @@ export default class RoomSublist extends React.Component { ev.preventDefault(); ev.stopPropagation(); const target = ev.target as HTMLButtonElement; - this.setState({contextMenuPosition: target.getBoundingClientRect()}); + this.setState({ contextMenuPosition: target.getBoundingClientRect() }); }; private onContextMenu = (ev: React.MouseEvent) => { @@ -397,15 +397,15 @@ export default class RoomSublist extends React.Component { ev.preventDefault(); ev.stopPropagation(); const target = ev.target as HTMLButtonElement; - this.setState({addRoomContextMenuPosition: target.getBoundingClientRect()}); + this.setState({ addRoomContextMenuPosition: target.getBoundingClientRect() }); }; private onCloseMenu = () => { - this.setState({contextMenuPosition: null}); + this.setState({ contextMenuPosition: null }); }; private onCloseAddRoomMenu = () => { - this.setState({addRoomContextMenuPosition: null}); + this.setState({ addRoomContextMenuPosition: null }); }; private onUnreadFirstChanged = async () => { @@ -462,7 +462,7 @@ export default class RoomSublist extends React.Component { if ((isStickyBottom && !isAtBottom) || (isStickyTop && !isAtTop)) { // is sticky - jump to list - sublist.scrollIntoView({behavior: 'smooth'}); + sublist.scrollIntoView({ behavior: 'smooth' }); } else { // on screen - toggle collapse const isExpanded = this.state.isExpanded; @@ -470,7 +470,7 @@ export default class RoomSublist extends React.Component { // if the bottom list is collapsed then scroll it in so it doesn't expand off screen if (!isExpanded && isStickyBottom) { setImmediate(() => { - sublist.scrollIntoView({behavior: 'smooth'}); + sublist.scrollIntoView({ behavior: 'smooth' }); }); } } @@ -478,9 +478,9 @@ export default class RoomSublist extends React.Component { private toggleCollapsed = () => { this.layout.isCollapsed = this.state.isExpanded; - this.setState({isExpanded: !this.layout.isCollapsed}); + this.setState({ isExpanded: !this.layout.isCollapsed }); if (this.props.onListCollapse) { - this.props.onListCollapse(!this.layout.isCollapsed) + this.props.onListCollapse(!this.layout.isCollapsed); } }; @@ -655,7 +655,7 @@ export default class RoomSublist extends React.Component { private renderHeader(): React.ReactElement { return ( - {({onFocus, isActive, ref}) => { + {({ onFocus, isActive, ref }) => { const tabIndex = isActive ? 0 : -1; let ariaLabel = _t("Jump to first unread room."); @@ -801,7 +801,7 @@ export default class RoomSublist extends React.Component { const nonPaddedHeight = this.state.height - RESIZE_HANDLE_HEIGHT - SHOW_N_BUTTON_HEIGHT; const amountFullyShown = Math.floor(nonPaddedHeight / this.layout.tileHeight); const numMissing = this.numTiles - amountFullyShown; - const label = _t("Show %(count)s more", {count: numMissing}); + const label = _t("Show %(count)s more", { count: numMissing }); let showMoreText = ( {label} @@ -879,14 +879,14 @@ export default class RoomSublist extends React.Component { content = ( diff --git a/src/components/views/rooms/RoomTile.tsx b/src/components/views/rooms/RoomTile.tsx index 310ff29010..9be0274dd5 100644 --- a/src/components/views/rooms/RoomTile.tsx +++ b/src/components/views/rooms/RoomTile.tsx @@ -78,7 +78,7 @@ const contextMenuBelow = (elementRect: PartialDOMRect) => { const left = elementRect.left + window.pageXOffset - 9; const top = elementRect.bottom + window.pageYOffset + 17; const chevronFace = ChevronFace.None; - return {left, top, chevronFace}; + return { left, top, chevronFace }; }; @replaceableComponent("views.rooms.RoomTile") @@ -112,7 +112,7 @@ export default class RoomTile extends React.PureComponent { private onRoomNameUpdate = (room) => { this.forceUpdate(); - } + }; private onNotificationUpdate = () => { this.forceUpdate(); // notification state changed - update @@ -120,7 +120,7 @@ export default class RoomTile extends React.PureComponent { private onLocalEchoUpdated = (ev: MatrixEvent, room: Room) => { if (room?.roomId !== this.props.room.roomId) return; - this.setState({hasUnsentEvents: this.countUnsentEvents() > 0}); + this.setState({ hasUnsentEvents: this.countUnsentEvents() > 0 }); }; private onRoomPropertyUpdate = (property: CachedRoomKey) => { @@ -259,25 +259,25 @@ export default class RoomTile extends React.PureComponent { }; private onActiveRoomUpdate = (isActive: boolean) => { - this.setState({selected: isActive}); + this.setState({ selected: isActive }); }; private onNotificationsMenuOpenClick = (ev: React.MouseEvent) => { ev.preventDefault(); ev.stopPropagation(); const target = ev.target as HTMLButtonElement; - this.setState({notificationsMenuPosition: target.getBoundingClientRect()}); + this.setState({ notificationsMenuPosition: target.getBoundingClientRect() }); }; private onCloseNotificationsMenu = () => { - this.setState({notificationsMenuPosition: null}); + this.setState({ notificationsMenuPosition: null }); }; private onGeneralMenuOpenClick = (ev: React.MouseEvent) => { ev.preventDefault(); ev.stopPropagation(); const target = ev.target as HTMLButtonElement; - this.setState({generalMenuPosition: target.getBoundingClientRect()}); + this.setState({ generalMenuPosition: target.getBoundingClientRect() }); }; private onContextMenu = (ev: React.MouseEvent) => { @@ -295,7 +295,7 @@ export default class RoomTile extends React.PureComponent { }; private onCloseGeneralMenu = () => { - this.setState({generalMenuPosition: null}); + this.setState({ generalMenuPosition: null }); }; private onTagRoom = (ev: ButtonEvent, tagId: TagID) => { @@ -321,7 +321,7 @@ export default class RoomTile extends React.PureComponent { if ((ev as React.KeyboardEvent).key === Key.ENTER) { // Implements https://www.w3.org/TR/wai-aria-practices/#keyboard-interaction-12 - this.setState({generalMenuPosition: null}); // hide the menu + this.setState({ generalMenuPosition: null }); // hide the menu } }; @@ -333,7 +333,7 @@ export default class RoomTile extends React.PureComponent { action: 'leave_room', room_id: this.props.room.roomId, }); - this.setState({generalMenuPosition: null}); // hide the menu + this.setState({ generalMenuPosition: null }); // hide the menu }; private onForgetRoomClick = (ev: ButtonEvent) => { @@ -344,7 +344,7 @@ export default class RoomTile extends React.PureComponent { action: 'forget_room', room_id: this.props.room.roomId, }); - this.setState({generalMenuPosition: null}); // hide the menu + this.setState({ generalMenuPosition: null }); // hide the menu }; private onOpenRoomSettings = (ev: ButtonEvent) => { @@ -355,7 +355,7 @@ export default class RoomTile extends React.PureComponent { action: 'open_room_settings', room_id: this.props.room.roomId, }); - this.setState({generalMenuPosition: null}); // hide the menu + this.setState({ generalMenuPosition: null }); // hide the menu }; private onInviteClick = (ev: ButtonEvent) => { @@ -366,7 +366,7 @@ export default class RoomTile extends React.PureComponent { action: 'view_invite', roomId: this.props.room.roomId, }); - this.setState({generalMenuPosition: null}); // hide the menu + this.setState({ generalMenuPosition: null }); // hide the menu }; private async saveNotifState(ev: ButtonEvent, newState: Volume) { @@ -379,7 +379,7 @@ export default class RoomTile extends React.PureComponent { const key = (ev as React.KeyboardEvent).key; if (key === Key.ENTER) { // Implements https://www.w3.org/TR/wai-aria-practices/#keyboard-interaction-12 - this.setState({notificationsMenuPosition: null}); // hide the menu + this.setState({ notificationsMenuPosition: null }); // hide the menu } } @@ -554,7 +554,7 @@ export default class RoomTile extends React.PureComponent { 'mx_RoomTile_minimized': this.props.isMinimized, }); - let roomProfile: IRoomProfile = {displayName: null, avatarMxc: null}; + let roomProfile: IRoomProfile = { displayName: null, avatarMxc: null }; if (this.props.tag === DefaultTagID.Invite) { roomProfile = CommunityPrototypeStore.instance.getInviteProfile(this.props.room.roomId); } @@ -567,7 +567,7 @@ export default class RoomTile extends React.PureComponent { room={this.props.room} avatarSize={32} displayBadge={this.props.isMinimized} - oobData={({avatarUrl: roomProfile.avatarMxc})} + oobData={({ avatarUrl: roomProfile.avatarMxc })} />; let badge: React.ReactNode; @@ -659,7 +659,7 @@ export default class RoomTile extends React.PureComponent { return ( - {({onFocus, isActive, ref}) => + {({ onFocus, isActive, ref }) => } @@ -119,4 +119,3 @@ describe("RovingTabIndex", () => { }); }); - diff --git a/test/autocomplete/QueryMatcher-test.js b/test/autocomplete/QueryMatcher-test.js index cae71841d4..72f894c678 100644 --- a/test/autocomplete/QueryMatcher-test.js +++ b/test/autocomplete/QueryMatcher-test.js @@ -31,7 +31,7 @@ const NONWORDOBJECTS = [ describe('QueryMatcher', function() { it('Returns results by key', function() { - const qm = new QueryMatcher(OBJECTS, {keys: ["name"]}); + const qm = new QueryMatcher(OBJECTS, { keys: ["name"] }); const results = qm.match('Geri'); expect(results.length).toBe(1); @@ -39,7 +39,7 @@ describe('QueryMatcher', function() { }); it('Returns results by prefix', function() { - const qm = new QueryMatcher(OBJECTS, {keys: ["name"]}); + const qm = new QueryMatcher(OBJECTS, { keys: ["name"] }); const results = qm.match('Ge'); expect(results.length).toBe(1); @@ -47,7 +47,7 @@ describe('QueryMatcher', function() { }); it('Matches case-insensitive', function() { - const qm = new QueryMatcher(OBJECTS, {keys: ["name"]}); + const qm = new QueryMatcher(OBJECTS, { keys: ["name"] }); const results = qm.match('geri'); expect(results.length).toBe(1); @@ -55,7 +55,7 @@ describe('QueryMatcher', function() { }); it('Matches ignoring accents', function() { - const qm = new QueryMatcher([{name: "Gëri", foo: 46}], {keys: ["name"]}); + const qm = new QueryMatcher([{ name: "Gëri", foo: 46 }], { keys: ["name"] }); const results = qm.match('geri'); expect(results.length).toBe(1); @@ -63,14 +63,13 @@ describe('QueryMatcher', function() { }); it('Returns multiple results in order of search string appearance', function() { - const qm = new QueryMatcher(OBJECTS, {keys: ["name", "nick"]}); + const qm = new QueryMatcher(OBJECTS, { keys: ["name", "nick"] }); const results = qm.match('or'); expect(results.length).toBe(2); expect(results[0].name).toBe('Mel C'); expect(results[1].name).toBe('Victoria'); - qm.setObjects(OBJECTS.slice().reverse()); const reverseResults = qm.match('or'); @@ -87,7 +86,7 @@ describe('QueryMatcher', function() { { name: "b", first: "miss", second: "hit", third: "miss" }, { name: "c", first: "miss", second: "miss", third: "hit" }, ]; - const qm = new QueryMatcher(objects, {keys: ["second", "first", "third"]}); + const qm = new QueryMatcher(objects, { keys: ["second", "first", "third"] }); const results = qm.match('hit'); expect(results.length).toBe(3); @@ -95,7 +94,6 @@ describe('QueryMatcher', function() { expect(results[1].name).toBe('a'); expect(results[2].name).toBe('c'); - qm.setObjects(objects.slice().reverse()); const reverseResults = qm.match('hit'); @@ -109,14 +107,13 @@ describe('QueryMatcher', function() { }); it('Returns results with search string in same place and key in same place in insertion order', function() { - const qm = new QueryMatcher(OBJECTS, {keys: ["name"]}); + const qm = new QueryMatcher(OBJECTS, { keys: ["name"] }); const results = qm.match('Mel'); expect(results.length).toBe(2); expect(results[0].name).toBe('Mel B'); expect(results[1].name).toBe('Mel C'); - qm.setObjects(OBJECTS.slice().reverse()); const reverseResults = qm.match('Mel'); @@ -129,9 +126,9 @@ describe('QueryMatcher', function() { it('Returns numeric results in correct order (input pos)', function() { // regression test for depending on object iteration order const qm = new QueryMatcher([ - {name: "123456badger"}, - {name: "123456"}, - ], {keys: ["name"]}); + { name: "123456badger" }, + { name: "123456" }, + ], { keys: ["name"] }); const results = qm.match('123456'); expect(results.length).toBe(2); @@ -141,9 +138,9 @@ describe('QueryMatcher', function() { it('Returns numeric results in correct order (query pos)', function() { const qm = new QueryMatcher([ - {name: "999999123456"}, - {name: "123456badger"}, - ], {keys: ["name"]}); + { name: "999999123456" }, + { name: "123456badger" }, + ], { keys: ["name"] }); const results = qm.match('123456'); expect(results.length).toBe(2); diff --git a/test/components/structures/GroupView-test.js b/test/components/structures/GroupView-test.js index ee5d1b6912..2ff1257d32 100644 --- a/test/components/structures/GroupView-test.js +++ b/test/components/structures/GroupView-test.js @@ -19,7 +19,7 @@ import ReactDOM from 'react-dom'; import ReactTestUtils from 'react-dom/test-utils'; import MockHttpBackend from 'matrix-mock-request'; -import {MatrixClientPeg} from '../../../src/MatrixClientPeg'; +import { MatrixClientPeg } from '../../../src/MatrixClientPeg'; import sdk from '../../skinned-sdk'; import Matrix from 'matrix-js-sdk'; diff --git a/test/components/structures/auth/Login-test.js b/test/components/structures/auth/Login-test.js index f39802464f..9def0c8d95 100644 --- a/test/components/structures/auth/Login-test.js +++ b/test/components/structures/auth/Login-test.js @@ -19,7 +19,7 @@ import ReactDOM from 'react-dom'; import ReactTestUtils from 'react-dom/test-utils'; import sdk from '../../../skinned-sdk'; import SdkConfig from '../../../../src/SdkConfig'; -import {mkServerConfig} from "../../../test-utils"; +import { mkServerConfig } from "../../../test-utils"; const Login = sdk.getComponent( 'structures.auth.Login', diff --git a/test/components/structures/auth/Registration-test.js b/test/components/structures/auth/Registration-test.js index 3e8e887329..e09304962f 100644 --- a/test/components/structures/auth/Registration-test.js +++ b/test/components/structures/auth/Registration-test.js @@ -19,7 +19,7 @@ import ReactDOM from 'react-dom'; import ReactTestUtils from 'react-dom/test-utils'; import sdk from '../../../skinned-sdk'; import SdkConfig from '../../../../src/SdkConfig'; -import {mkServerConfig} from "../../../test-utils"; +import { mkServerConfig } from "../../../test-utils"; const Registration = sdk.getComponent( 'structures.auth.Registration', diff --git a/test/components/stub-component.js b/test/components/stub-component.js index e242c06707..f98959a573 100644 --- a/test/components/stub-component.js +++ b/test/components/stub-component.js @@ -3,7 +3,7 @@ import React from 'react'; -export default function({displayName = "StubComponent", render} = {}) { +export default function({ displayName = "StubComponent", render } = {}) { if (!render) { render = function() { return
      { displayName }
      ; diff --git a/test/components/views/dialogs/AccessSecretStorageDialog-test.js b/test/components/views/dialogs/AccessSecretStorageDialog-test.js index d9e07a2d74..8c16e7f104 100644 --- a/test/components/views/dialogs/AccessSecretStorageDialog-test.js +++ b/test/components/views/dialogs/AccessSecretStorageDialog-test.js @@ -17,7 +17,7 @@ limitations under the License. import React from 'react'; import TestRenderer from 'react-test-renderer'; import sdk from '../../../skinned-sdk'; -import {MatrixClientPeg} from '../../../../src/MatrixClientPeg'; +import { MatrixClientPeg } from '../../../../src/MatrixClientPeg'; import { stubClient } from '../../../test-utils'; const AccessSecretStorageDialog = sdk.getComponent("dialogs.security.AccessSecretStorageDialog"); diff --git a/test/components/views/dialogs/ForwardDialog-test.js b/test/components/views/dialogs/ForwardDialog-test.js index dbd50612bb..c5ce330fec 100644 --- a/test/components/views/dialogs/ForwardDialog-test.js +++ b/test/components/views/dialogs/ForwardDialog-test.js @@ -17,14 +17,14 @@ limitations under the License. import "../../../skinned-sdk"; import React from "react"; -import {configure, mount} from "enzyme"; +import { configure, mount } from "enzyme"; import Adapter from "@wojtekmaj/enzyme-adapter-react-17"; -import {act} from "react-dom/test-utils"; +import { act } from "react-dom/test-utils"; import * as TestUtils from "../../../test-utils"; -import {MatrixClientPeg} from "../../../../src/MatrixClientPeg"; +import { MatrixClientPeg } from "../../../../src/MatrixClientPeg"; import DMRoomMap from "../../../../src/utils/DMRoomMap"; -import {RoomPermalinkCreator} from "../../../../src/utils/permalinks/Permalinks"; +import { RoomPermalinkCreator } from "../../../../src/utils/permalinks/Permalinks"; import ForwardDialog from "../../../../src/components/views/dialogs/ForwardDialog"; configure({ adapter: new Adapter() }); diff --git a/test/components/views/elements/MemberEventListSummary-test.js b/test/components/views/elements/MemberEventListSummary-test.js index 95bf206d02..e2d51f13a4 100644 --- a/test/components/views/elements/MemberEventListSummary-test.js +++ b/test/components/views/elements/MemberEventListSummary-test.js @@ -90,7 +90,7 @@ describe('MemberEventListSummary', function() { it('renders expanded events if there are less than props.threshold', function() { const events = generateEvents([ - {userId: "@user_1:some.domain", prevMembership: "leave", membership: "join"}, + { userId: "@user_1:some.domain", prevMembership: "leave", membership: "join" }, ]); const props = { events: events, @@ -112,8 +112,8 @@ describe('MemberEventListSummary', function() { it('renders expanded events if there are less than props.threshold', function() { const events = generateEvents([ - {userId: "@user_1:some.domain", prevMembership: "leave", membership: "join"}, - {userId: "@user_1:some.domain", prevMembership: "join", membership: "leave"}, + { userId: "@user_1:some.domain", prevMembership: "leave", membership: "join" }, + { userId: "@user_1:some.domain", prevMembership: "join", membership: "leave" }, ]); const props = { events: events, @@ -136,9 +136,9 @@ describe('MemberEventListSummary', function() { it('renders collapsed events if events.length = props.threshold', function() { const events = generateEvents([ - {userId: "@user_1:some.domain", prevMembership: "leave", membership: "join"}, - {userId: "@user_1:some.domain", prevMembership: "join", membership: "leave"}, - {userId: "@user_1:some.domain", prevMembership: "leave", membership: "join"}, + { userId: "@user_1:some.domain", prevMembership: "leave", membership: "join" }, + { userId: "@user_1:some.domain", prevMembership: "join", membership: "leave" }, + { userId: "@user_1:some.domain", prevMembership: "leave", membership: "join" }, ]); const props = { events: events, @@ -161,20 +161,20 @@ describe('MemberEventListSummary', function() { it('truncates long join,leave repetitions', function() { const events = generateEvents([ - {userId: "@user_1:some.domain", prevMembership: "leave", membership: "join"}, - {userId: "@user_1:some.domain", prevMembership: "join", membership: "leave"}, - {userId: "@user_1:some.domain", prevMembership: "leave", membership: "join"}, - {userId: "@user_1:some.domain", prevMembership: "join", membership: "leave"}, - {userId: "@user_1:some.domain", prevMembership: "leave", membership: "join"}, - {userId: "@user_1:some.domain", prevMembership: "join", membership: "leave"}, - {userId: "@user_1:some.domain", prevMembership: "leave", membership: "join"}, - {userId: "@user_1:some.domain", prevMembership: "join", membership: "leave"}, - {userId: "@user_1:some.domain", prevMembership: "leave", membership: "join"}, - {userId: "@user_1:some.domain", prevMembership: "join", membership: "leave"}, - {userId: "@user_1:some.domain", prevMembership: "leave", membership: "join"}, - {userId: "@user_1:some.domain", prevMembership: "join", membership: "leave"}, - {userId: "@user_1:some.domain", prevMembership: "leave", membership: "join"}, - {userId: "@user_1:some.domain", prevMembership: "join", membership: "leave"}, + { userId: "@user_1:some.domain", prevMembership: "leave", membership: "join" }, + { userId: "@user_1:some.domain", prevMembership: "join", membership: "leave" }, + { userId: "@user_1:some.domain", prevMembership: "leave", membership: "join" }, + { userId: "@user_1:some.domain", prevMembership: "join", membership: "leave" }, + { userId: "@user_1:some.domain", prevMembership: "leave", membership: "join" }, + { userId: "@user_1:some.domain", prevMembership: "join", membership: "leave" }, + { userId: "@user_1:some.domain", prevMembership: "leave", membership: "join" }, + { userId: "@user_1:some.domain", prevMembership: "join", membership: "leave" }, + { userId: "@user_1:some.domain", prevMembership: "leave", membership: "join" }, + { userId: "@user_1:some.domain", prevMembership: "join", membership: "leave" }, + { userId: "@user_1:some.domain", prevMembership: "leave", membership: "join" }, + { userId: "@user_1:some.domain", prevMembership: "join", membership: "leave" }, + { userId: "@user_1:some.domain", prevMembership: "leave", membership: "join" }, + { userId: "@user_1:some.domain", prevMembership: "join", membership: "leave" }, ]); const props = { events: events, @@ -203,20 +203,20 @@ describe('MemberEventListSummary', function() { membership: "leave", senderId: "@some_other_user:some.domain", }, - {userId: "@user_1:some.domain", prevMembership: "leave", membership: "join"}, - {userId: "@user_1:some.domain", prevMembership: "join", membership: "leave"}, - {userId: "@user_1:some.domain", prevMembership: "leave", membership: "join"}, - {userId: "@user_1:some.domain", prevMembership: "join", membership: "leave"}, - {userId: "@user_1:some.domain", prevMembership: "leave", membership: "join"}, - {userId: "@user_1:some.domain", prevMembership: "join", membership: "leave"}, - {userId: "@user_1:some.domain", prevMembership: "leave", membership: "join"}, - {userId: "@user_1:some.domain", prevMembership: "join", membership: "leave"}, - {userId: "@user_1:some.domain", prevMembership: "leave", membership: "join"}, - {userId: "@user_1:some.domain", prevMembership: "join", membership: "leave"}, - {userId: "@user_1:some.domain", prevMembership: "leave", membership: "join"}, - {userId: "@user_1:some.domain", prevMembership: "join", membership: "leave"}, - {userId: "@user_1:some.domain", prevMembership: "leave", membership: "join"}, - {userId: "@user_1:some.domain", prevMembership: "join", membership: "leave"}, + { userId: "@user_1:some.domain", prevMembership: "leave", membership: "join" }, + { userId: "@user_1:some.domain", prevMembership: "join", membership: "leave" }, + { userId: "@user_1:some.domain", prevMembership: "leave", membership: "join" }, + { userId: "@user_1:some.domain", prevMembership: "join", membership: "leave" }, + { userId: "@user_1:some.domain", prevMembership: "leave", membership: "join" }, + { userId: "@user_1:some.domain", prevMembership: "join", membership: "leave" }, + { userId: "@user_1:some.domain", prevMembership: "leave", membership: "join" }, + { userId: "@user_1:some.domain", prevMembership: "join", membership: "leave" }, + { userId: "@user_1:some.domain", prevMembership: "leave", membership: "join" }, + { userId: "@user_1:some.domain", prevMembership: "join", membership: "leave" }, + { userId: "@user_1:some.domain", prevMembership: "leave", membership: "join" }, + { userId: "@user_1:some.domain", prevMembership: "join", membership: "leave" }, + { userId: "@user_1:some.domain", prevMembership: "leave", membership: "join" }, + { userId: "@user_1:some.domain", prevMembership: "join", membership: "leave" }, { userId: "@user_1:some.domain", prevMembership: "leave", @@ -253,22 +253,22 @@ describe('MemberEventListSummary', function() { membership: "leave", senderId: "@some_other_user:some.domain", }, - {userId: "@user_1:some.domain", prevMembership: "leave", membership: "join"}, - {userId: "@user_1:some.domain", prevMembership: "join", membership: "leave"}, - {userId: "@user_1:some.domain", prevMembership: "leave", membership: "join"}, - {userId: "@user_1:some.domain", prevMembership: "join", membership: "leave"}, + { userId: "@user_1:some.domain", prevMembership: "leave", membership: "join" }, + { userId: "@user_1:some.domain", prevMembership: "join", membership: "leave" }, + { userId: "@user_1:some.domain", prevMembership: "leave", membership: "join" }, + { userId: "@user_1:some.domain", prevMembership: "join", membership: "leave" }, { userId: "@user_1:some.domain", prevMembership: "leave", membership: "ban", senderId: "@some_other_user:some.domain", }, - {userId: "@user_1:some.domain", prevMembership: "ban", membership: "join"}, - {userId: "@user_1:some.domain", prevMembership: "join", membership: "leave"}, - {userId: "@user_1:some.domain", prevMembership: "leave", membership: "join"}, - {userId: "@user_1:some.domain", prevMembership: "join", membership: "leave"}, - {userId: "@user_1:some.domain", prevMembership: "leave", membership: "join"}, - {userId: "@user_1:some.domain", prevMembership: "join", membership: "leave"}, + { userId: "@user_1:some.domain", prevMembership: "ban", membership: "join" }, + { userId: "@user_1:some.domain", prevMembership: "join", membership: "leave" }, + { userId: "@user_1:some.domain", prevMembership: "leave", membership: "join" }, + { userId: "@user_1:some.domain", prevMembership: "join", membership: "leave" }, + { userId: "@user_1:some.domain", prevMembership: "leave", membership: "join" }, + { userId: "@user_1:some.domain", prevMembership: "join", membership: "leave" }, { userId: "@user_1:some.domain", prevMembership: "leave", @@ -307,10 +307,10 @@ describe('MemberEventListSummary', function() { membership: "leave", senderId: "@some_other_user:some.domain", }, - {userId: "@user_1:some.domain", prevMembership: "leave", membership: "join"}, - {userId: "@user_1:some.domain", prevMembership: "join", membership: "leave"}, - {userId: "@user_1:some.domain", prevMembership: "leave", membership: "join"}, - {userId: "@user_1:some.domain", prevMembership: "join", membership: "leave"}, + { userId: "@user_1:some.domain", prevMembership: "leave", membership: "join" }, + { userId: "@user_1:some.domain", prevMembership: "join", membership: "leave" }, + { userId: "@user_1:some.domain", prevMembership: "leave", membership: "join" }, + { userId: "@user_1:some.domain", prevMembership: "join", membership: "leave" }, { userId: "@user_1:some.domain", prevMembership: "leave", @@ -324,10 +324,10 @@ describe('MemberEventListSummary', function() { membership: "leave", senderId: "@some_other_user:some.domain", }, - {userId: "@user_2:some.domain", prevMembership: "leave", membership: "join"}, - {userId: "@user_2:some.domain", prevMembership: "join", membership: "leave"}, - {userId: "@user_2:some.domain", prevMembership: "leave", membership: "join"}, - {userId: "@user_2:some.domain", prevMembership: "join", membership: "leave"}, + { userId: "@user_2:some.domain", prevMembership: "leave", membership: "join" }, + { userId: "@user_2:some.domain", prevMembership: "join", membership: "leave" }, + { userId: "@user_2:some.domain", prevMembership: "leave", membership: "join" }, + { userId: "@user_2:some.domain", prevMembership: "join", membership: "leave" }, { userId: "@user_2:some.domain", prevMembership: "leave", @@ -363,10 +363,10 @@ describe('MemberEventListSummary', function() { membership: "leave", senderId: "@some_other_user:some.domain", }, - {prevMembership: "leave", membership: "join"}, - {prevMembership: "join", membership: "leave"}, - {prevMembership: "leave", membership: "join"}, - {prevMembership: "join", membership: "leave"}, + { prevMembership: "leave", membership: "join" }, + { prevMembership: "join", membership: "leave" }, + { prevMembership: "leave", membership: "join" }, + { prevMembership: "join", membership: "leave" }, { prevMembership: "leave", membership: "ban", @@ -408,20 +408,20 @@ describe('MemberEventListSummary', function() { membership: "leave", senderId: "@some_other_user:some.domain", }, - {userId: "@user_1:some.domain", prevMembership: "leave", membership: "join"}, - {userId: "@user_1:some.domain", prevMembership: "join", membership: "leave"}, - {userId: "@user_1:some.domain", prevMembership: "leave", membership: "join"}, - {userId: "@user_1:some.domain", prevMembership: "join", membership: "leave"}, + { userId: "@user_1:some.domain", prevMembership: "leave", membership: "join" }, + { userId: "@user_1:some.domain", prevMembership: "join", membership: "leave" }, + { userId: "@user_1:some.domain", prevMembership: "leave", membership: "join" }, + { userId: "@user_1:some.domain", prevMembership: "join", membership: "leave" }, { userId: "@user_1:some.domain", prevMembership: "leave", membership: "ban", senderId: "@some_other_user:some.domain", }, - {userId: "@user_2:some.domain", prevMembership: "leave", membership: "join"}, - {userId: "@user_2:some.domain", prevMembership: "join", membership: "leave"}, - {userId: "@user_2:some.domain", prevMembership: "leave", membership: "join"}, - {userId: "@user_2:some.domain", prevMembership: "join", membership: "leave"}, + { userId: "@user_2:some.domain", prevMembership: "leave", membership: "join" }, + { userId: "@user_2:some.domain", prevMembership: "join", membership: "leave" }, + { userId: "@user_2:some.domain", prevMembership: "leave", membership: "join" }, + { userId: "@user_2:some.domain", prevMembership: "join", membership: "leave" }, ]); const props = { events: events, @@ -448,11 +448,11 @@ describe('MemberEventListSummary', function() { it('correctly identifies transitions', function() { const events = generateEvents([ // invited - {userId: "@user_1:some.domain", membership: "invite"}, + { userId: "@user_1:some.domain", membership: "invite" }, // banned - {userId: "@user_1:some.domain", membership: "ban"}, + { userId: "@user_1:some.domain", membership: "ban" }, // joined - {userId: "@user_1:some.domain", membership: "join"}, + { userId: "@user_1:some.domain", membership: "join" }, // invite_reject { userId: "@user_1:some.domain", @@ -460,7 +460,7 @@ describe('MemberEventListSummary', function() { membership: "leave", }, // left - {userId: "@user_1:some.domain", prevMembership: "join", membership: "leave"}, + { userId: "@user_1:some.domain", prevMembership: "join", membership: "leave" }, // invite_withdrawal { userId: "@user_1:some.domain", @@ -602,10 +602,10 @@ describe('MemberEventListSummary', function() { it('handles a summary length = 2, with no "others"', function() { const events = generateEvents([ - {userId: "@user_1:some.domain", membership: "join"}, - {userId: "@user_1:some.domain", membership: "join"}, - {userId: "@user_2:some.domain", membership: "join"}, - {userId: "@user_2:some.domain", membership: "join"}, + { userId: "@user_1:some.domain", membership: "join" }, + { userId: "@user_1:some.domain", membership: "join" }, + { userId: "@user_2:some.domain", membership: "join" }, + { userId: "@user_2:some.domain", membership: "join" }, ]); const props = { events: events, @@ -630,9 +630,9 @@ describe('MemberEventListSummary', function() { it('handles a summary length = 2, with 1 "other"', function() { const events = generateEvents([ - {userId: "@user_1:some.domain", membership: "join"}, - {userId: "@user_2:some.domain", membership: "join"}, - {userId: "@user_3:some.domain", membership: "join"}, + { userId: "@user_1:some.domain", membership: "join" }, + { userId: "@user_2:some.domain", membership: "join" }, + { userId: "@user_3:some.domain", membership: "join" }, ]); const props = { events: events, @@ -657,7 +657,7 @@ describe('MemberEventListSummary', function() { it('handles a summary length = 2, with many "others"', function() { const events = generateEventsForUsers("@user_$:some.domain", 20, [ - {membership: "join"}, + { membership: "join" }, ]); const props = { events: events, diff --git a/test/components/views/groups/GroupMemberList-test.js b/test/components/views/groups/GroupMemberList-test.js index 39720177cc..7e01540d38 100644 --- a/test/components/views/groups/GroupMemberList-test.js +++ b/test/components/views/groups/GroupMemberList-test.js @@ -19,7 +19,7 @@ import ReactDOM from "react-dom"; import ReactTestUtils from "react-dom/test-utils"; import MockHttpBackend from "matrix-mock-request"; -import {MatrixClientPeg} from "../../../../src/MatrixClientPeg"; +import { MatrixClientPeg } from "../../../../src/MatrixClientPeg"; import sdk from "../../../skinned-sdk"; import Matrix from "matrix-js-sdk"; diff --git a/test/components/views/messages/TextualBody-test.js b/test/components/views/messages/TextualBody-test.js index b81486b293..c9418fc557 100644 --- a/test/components/views/messages/TextualBody-test.js +++ b/test/components/views/messages/TextualBody-test.js @@ -19,8 +19,8 @@ import Adapter from "@wojtekmaj/enzyme-adapter-react-17"; import { configure, mount } from "enzyme"; import sdk from "../../../skinned-sdk"; -import {mkEvent, mkStubRoom} from "../../../test-utils"; -import {MatrixClientPeg} from "../../../../src/MatrixClientPeg"; +import { mkEvent, mkStubRoom } from "../../../test-utils"; +import { MatrixClientPeg } from "../../../../src/MatrixClientPeg"; import * as languageHandler from "../../../../src/languageHandler"; const TextualBody = sdk.getComponent("views.messages.TextualBody"); @@ -343,4 +343,3 @@ describe("", () => { }); }); - diff --git a/test/components/views/rooms/MemberList-test.tsx b/test/components/views/rooms/MemberList-test.tsx index 8012c43c4b..a169cd08e6 100644 --- a/test/components/views/rooms/MemberList-test.tsx +++ b/test/components/views/rooms/MemberList-test.tsx @@ -312,4 +312,3 @@ describe('MemberList', () => { }); }); - diff --git a/test/components/views/rooms/RoomList-test.js b/test/components/views/rooms/RoomList-test.js index 6aad6a90fd..cee0fe5a47 100644 --- a/test/components/views/rooms/RoomList-test.js +++ b/test/components/views/rooms/RoomList-test.js @@ -4,7 +4,7 @@ import ReactDOM from 'react-dom'; import * as TestUtils from '../../../test-utils'; -import {MatrixClientPeg} from '../../../../src/MatrixClientPeg'; +import { MatrixClientPeg } from '../../../../src/MatrixClientPeg'; import sdk from '../../../skinned-sdk'; import dis from '../../../../src/dispatcher/dispatcher'; @@ -12,7 +12,7 @@ import DMRoomMap from '../../../../src/utils/DMRoomMap'; import GroupStore from '../../../../src/stores/GroupStore'; import { MatrixClient, Room, RoomMember } from 'matrix-js-sdk'; -import {DefaultTagID} from "../../../../src/stores/room-list/models"; +import { DefaultTagID } from "../../../../src/stores/room-list/models"; import RoomListStore, { LISTS_UPDATE_EVENT, RoomListStoreClass } from "../../../../src/stores/room-list/RoomListStore"; import RoomListLayoutStore from "../../../../src/stores/room-list/RoomListLayoutStore"; @@ -55,7 +55,7 @@ describe('RoomList', () => { TestUtils.stubClient(); client = MatrixClientPeg.get(); - client.credentials = {userId: myUserId}; + client.credentials = { userId: myUserId }; //revert this to prototype method as the test-utils monkey-patches this to return a hardcoded value client.getUserId = MatrixClient.prototype.getUserId; @@ -72,7 +72,7 @@ describe('RoomList', () => { ); ReactTestUtils.findRenderedComponentWithType(root, RoomList); - movingRoom = createRoom({name: 'Moving room'}); + movingRoom = createRoom({ name: 'Moving room' }); expect(movingRoom.roomId).not.toBe(null); // Mock joined member @@ -83,7 +83,7 @@ describe('RoomList', () => { [client.credentials.userId]: myMember, }[userId]); - otherRoom = createRoom({name: 'Other room'}); + otherRoom = createRoom({ name: 'Other room' }); myOtherMember = new RoomMember(otherRoom.roomId, myUserId); myOtherMember.membership = 'join'; otherRoom.updateMyMembership('join'); @@ -95,10 +95,10 @@ describe('RoomList', () => { client.getRooms = () => [ movingRoom, otherRoom, - createRoom({tags: {'m.favourite': {order: 0.1}}, name: 'Some other room'}), - createRoom({tags: {'m.favourite': {order: 0.2}}, name: 'Some other room 2'}), - createRoom({tags: {'m.lowpriority': {}}, name: 'Some unimportant room'}), - createRoom({tags: {'custom.tag': {}}, name: 'Some room customly tagged'}), + createRoom({ tags: { 'm.favourite': { order: 0.1 } }, name: 'Some other room' }), + createRoom({ tags: { 'm.favourite': { order: 0.2 } }, name: 'Some other room 2' }), + createRoom({ tags: { 'm.lowpriority': {} }, name: 'Some unimportant room' }), + createRoom({ tags: { 'custom.tag': {} }, name: 'Some room customly tagged' }), ]; client.getVisibleRooms = client.getRooms; @@ -138,7 +138,7 @@ describe('RoomList', () => { let expectedRoomTile; try { const roomTiles = ReactTestUtils.scryRenderedComponentsWithType(containingSubList, RoomTile); - console.info({roomTiles: roomTiles.length}); + console.info({ roomTiles: roomTiles.length }); expectedRoomTile = roomTiles.find((tile) => tile.props.room === room); } catch (err) { // truncate the error message because it's spammy @@ -164,7 +164,7 @@ describe('RoomList', () => { // Set up the room that will be moved such that it has the correct state for a room in // the section for oldTagId if (oldTagId === DefaultTagID.Favourite || oldTagId === DefaultTagID.LowPriority) { - movingRoom.tags = {[oldTagId]: {}}; + movingRoom.tags = { [oldTagId]: {} }; } else if (oldTagId === DefaultTagID.DM) { // Mock inverse m.direct DMRoomMap.shared().roomToUser = { @@ -172,13 +172,13 @@ describe('RoomList', () => { }; } - dis.dispatch({action: 'MatrixActions.sync', prevState: null, state: 'PREPARED', matrixClient: client}); + dis.dispatch({ action: 'MatrixActions.sync', prevState: null, state: 'PREPARED', matrixClient: client }); expectRoomInSubList(movingRoom, srcSubListTest); - dis.dispatch({action: 'RoomListActions.tagRoom.pending', request: { + dis.dispatch({ action: 'RoomListActions.tagRoom.pending', request: { oldTagId, newTagId, room: movingRoom, - }}); + } }); expectRoomInSubList(movingRoom, destSubListTest); } @@ -279,11 +279,11 @@ describe('RoomList', () => { // We also have to mock the client's getGroup function for the room list to filter it. // It's not smart enough to tell the difference between a real group and a template though. client.getGroup = (groupId) => { - return {groupId}; + return { groupId }; }; // Select tag - dis.dispatch({action: 'select_tag', tag: '+group:domain'}, true); + dis.dispatch({ action: 'select_tag', tag: '+group:domain' }, true); } beforeEach(() => { @@ -309,4 +309,3 @@ describe('RoomList', () => { }); }); - diff --git a/test/components/views/rooms/RoomSettings-test.js b/test/components/views/rooms/RoomSettings-test.js index 3b4989ccab..cd70b81cd7 100644 --- a/test/components/views/rooms/RoomSettings-test.js +++ b/test/components/views/rooms/RoomSettings-test.js @@ -3,10 +3,9 @@ import React from 'react'; import ReactDOM from 'react-dom'; import * as testUtils from '../../../test-utils'; import sdk from '../../../skinned-sdk'; -import {MatrixClientPeg} from '../../../../src/MatrixClientPeg'; +import { MatrixClientPeg } from '../../../../src/MatrixClientPeg'; import SettingsStore from '../../../../src/settings/SettingsStore'; - describe.skip('RoomSettings', () => { const WrappedRoomSettings = testUtils.wrapInMatrixClientContext(sdk.getComponent('views.rooms.RoomSettings')); @@ -36,7 +35,7 @@ describe.skip('RoomSettings', () => { beforeEach(function(done) { testUtils.stubClient(); client = MatrixClientPeg.get(); - client.credentials = {userId: '@me:domain.com'}; + client.credentials = { userId: '@me:domain.com' }; client.setRoomName = jest.fn().mockReturnValue(Promise.resolve()); client.setRoomTopic = jest.fn().mockReturnValue(Promise.resolve()); @@ -128,7 +127,7 @@ describe.skip('RoomSettings', () => { roomSettings.save().then(() => { expectSentStateEvent( "!DdJkzRliezrwpNebLk:matrix.org", - "m.room.history_visibility", {history_visibility: historyVisibility}, + "m.room.history_visibility", { history_visibility: historyVisibility }, ); done(); }); diff --git a/test/components/views/rooms/SendMessageComposer-test.js b/test/components/views/rooms/SendMessageComposer-test.js index eb7b2ffeff..2fddf8b691 100644 --- a/test/components/views/rooms/SendMessageComposer-test.js +++ b/test/components/views/rooms/SendMessageComposer-test.js @@ -18,18 +18,18 @@ import '../../../skinned-sdk'; // Must be first for skinning to work import Adapter from "@wojtekmaj/enzyme-adapter-react-17"; import { configure, mount } from "enzyme"; import React from "react"; -import {act} from "react-dom/test-utils"; +import { act } from "react-dom/test-utils"; import SendMessageComposer, { createMessageContent, isQuickReaction, } from "../../../../src/components/views/rooms/SendMessageComposer"; import MatrixClientContext from "../../../../src/contexts/MatrixClientContext"; import EditorModel from "../../../../src/editor/model"; -import {createPartCreator, createRenderer} from "../../../editor/mock"; -import {createTestClient, mkEvent, mkStubRoom} from "../../../test-utils"; +import { createPartCreator, createRenderer } from "../../../editor/mock"; +import { createTestClient, mkEvent, mkStubRoom } from "../../../test-utils"; import BasicMessageComposer from "../../../../src/components/views/rooms/BasicMessageComposer"; -import {MatrixClientPeg} from "../../../../src/MatrixClientPeg"; -import {sleep} from "../../../../src/utils/promise"; +import { MatrixClientPeg } from "../../../../src/MatrixClientPeg"; +import { sleep } from "../../../../src/utils/promise"; import SpecPermalinkConstructor from "../../../../src/utils/permalinks/SpecPermalinkConstructor"; import defaultDispatcher from "../../../../src/dispatcher/dispatcher"; @@ -43,7 +43,7 @@ describe('', () => { it("sends plaintext messages correctly", () => { const model = new EditorModel([], createPartCreator(), createRenderer()); - model.update("hello world", "insertText", {offset: 11, atNodeEnd: true}); + model.update("hello world", "insertText", { offset: 11, atNodeEnd: true }); const content = createMessageContent(model, permalinkCreator); @@ -55,7 +55,7 @@ describe('', () => { it("sends markdown messages correctly", () => { const model = new EditorModel([], createPartCreator(), createRenderer()); - model.update("hello *world*", "insertText", {offset: 13, atNodeEnd: true}); + model.update("hello *world*", "insertText", { offset: 13, atNodeEnd: true }); const content = createMessageContent(model, permalinkCreator); @@ -69,7 +69,7 @@ describe('', () => { it("strips /me from messages and marks them as m.emote accordingly", () => { const model = new EditorModel([], createPartCreator(), createRenderer()); - model.update("/me blinks __quickly__", "insertText", {offset: 22, atNodeEnd: true}); + model.update("/me blinks __quickly__", "insertText", { offset: 22, atNodeEnd: true }); const content = createMessageContent(model, permalinkCreator); @@ -83,7 +83,7 @@ describe('', () => { it("allows sending double-slash escaped slash commands correctly", () => { const model = new EditorModel([], createPartCreator(), createRenderer()); - model.update("//dev/null is my favourite place", "insertText", {offset: 32, atNodeEnd: true}); + model.update("//dev/null is my favourite place", "insertText", { offset: 32, atNodeEnd: true }); const content = createMessageContent(model, permalinkCreator); @@ -155,7 +155,7 @@ describe('', () => { // ensure the right state was persisted to localStorage wrapper.unmount(); expect(JSON.parse(localStorage.getItem(key))).toStrictEqual({ - parts: [{"type": "plain", "text": "Test Text"}], + parts: [{ "type": "plain", "text": "Test Text" }], replyEventId: mockEvent.getId(), }); @@ -196,7 +196,7 @@ describe('', () => { // ensure the right state was persisted to localStorage window.dispatchEvent(new Event('beforeunload')); expect(JSON.parse(localStorage.getItem(key))).toStrictEqual({ - parts: [{"type": "plain", "text": "Hello World"}], + parts: [{ "type": "plain", "text": "Hello World" }], }); }); @@ -225,7 +225,7 @@ describe('', () => { expect(wrapper.text()).toBe(""); const str = sessionStorage.getItem(`mx_cider_history_${mockRoom.roomId}[0]`); expect(JSON.parse(str)).toStrictEqual({ - parts: [{"type": "plain", "text": "This is a message"}], + parts: [{ "type": "plain", "text": "This is a message" }], replyEventId: mockEvent.getId(), }); }); @@ -234,7 +234,7 @@ describe('', () => { describe("isQuickReaction", () => { it("correctly detects quick reaction", () => { const model = new EditorModel([], createPartCreator(), createRenderer()); - model.update("+😊", "insertText", {offset: 3, atNodeEnd: true}); + model.update("+😊", "insertText", { offset: 3, atNodeEnd: true }); const isReaction = isQuickReaction(model); @@ -243,7 +243,7 @@ describe('', () => { it("correctly detects quick reaction with space", () => { const model = new EditorModel([], createPartCreator(), createRenderer()); - model.update("+ 😊", "insertText", {offset: 4, atNodeEnd: true}); + model.update("+ 😊", "insertText", { offset: 4, atNodeEnd: true }); const isReaction = isQuickReaction(model); @@ -255,10 +255,10 @@ describe('', () => { const model2 = new EditorModel([], createPartCreator(), createRenderer()); const model3 = new EditorModel([], createPartCreator(), createRenderer()); const model4 = new EditorModel([], createPartCreator(), createRenderer()); - model.update("+😊hello", "insertText", {offset: 8, atNodeEnd: true}); - model2.update(" +😊", "insertText", {offset: 4, atNodeEnd: true}); - model3.update("+ 😊😊", "insertText", {offset: 6, atNodeEnd: true}); - model4.update("+smiley", "insertText", {offset: 7, atNodeEnd: true}); + model.update("+😊hello", "insertText", { offset: 8, atNodeEnd: true }); + model2.update(" +😊", "insertText", { offset: 4, atNodeEnd: true }); + model3.update("+ 😊😊", "insertText", { offset: 6, atNodeEnd: true }); + model4.update("+smiley", "insertText", { offset: 7, atNodeEnd: true }); expect(isQuickReaction(model)).toBeFalsy(); expect(isQuickReaction(model2)).toBeFalsy(); @@ -268,4 +268,3 @@ describe('', () => { }); }); - diff --git a/test/createRoom-test.js b/test/createRoom-test.js index ed8f9779f7..b9b7e7df01 100644 --- a/test/createRoom-test.js +++ b/test/createRoom-test.js @@ -1,6 +1,6 @@ import './skinned-sdk'; // Must be first for skinning to work -import {_waitForMember, canEncryptToAllUsers} from '../src/createRoom'; -import {EventEmitter} from 'events'; +import { _waitForMember, canEncryptToAllUsers } from '../src/createRoom'; +import { EventEmitter } from 'events'; /* Shorter timeout, we've got tests to run */ const timeout = 30; @@ -61,10 +61,9 @@ describe("canEncryptToAllUsers", () => { done(); }); - it("returns false if not all users have crypto", async (done) => { const client = { - downloadKeys: async function(userIds) { return {...trueUser, ...falseUser}; }, + downloadKeys: async function(userIds) { return { ...trueUser, ...falseUser }; }, }; const response = await canEncryptToAllUsers(client, ["@goodUser:localhost", "@badUser:localhost"]); expect(response).toBe(false); diff --git a/test/editor/caret-test.js b/test/editor/caret-test.js index f0c171c7c9..e1a66a4431 100644 --- a/test/editor/caret-test.js +++ b/test/editor/caret-test.js @@ -14,9 +14,9 @@ See the License for the specific language governing permissions and limitations under the License. */ -import {getLineAndNodePosition} from "../../src/editor/caret"; +import { getLineAndNodePosition } from "../../src/editor/caret"; import EditorModel from "../../src/editor/model"; -import {createPartCreator} from "./mock"; +import { createPartCreator } from "./mock"; describe('editor/caret: DOM position for caret', function() { describe('basic text handling', function() { @@ -25,8 +25,8 @@ describe('editor/caret: DOM position for caret', function() { const model = new EditorModel([ pc.plain("hello"), ]); - const {offset, lineIndex, nodeIndex} = - getLineAndNodePosition(model, {index: 0, offset: 5}); + const { offset, lineIndex, nodeIndex } = + getLineAndNodePosition(model, { index: 0, offset: 5 }); expect(lineIndex).toBe(0); expect(nodeIndex).toBe(0); expect(offset).toBe(5); @@ -36,8 +36,8 @@ describe('editor/caret: DOM position for caret', function() { const model = new EditorModel([ pc.plain("hello"), ]); - const {offset, lineIndex, nodeIndex} = - getLineAndNodePosition(model, {index: 0, offset: 0}); + const { offset, lineIndex, nodeIndex } = + getLineAndNodePosition(model, { index: 0, offset: 0 }); expect(lineIndex).toBe(0); expect(nodeIndex).toBe(0); expect(offset).toBe(0); @@ -47,8 +47,8 @@ describe('editor/caret: DOM position for caret', function() { const model = new EditorModel([ pc.plain("hello"), ]); - const {offset, lineIndex, nodeIndex} = - getLineAndNodePosition(model, {index: 0, offset: 2}); + const { offset, lineIndex, nodeIndex } = + getLineAndNodePosition(model, { index: 0, offset: 2 }); expect(lineIndex).toBe(0); expect(nodeIndex).toBe(0); expect(offset).toBe(2); @@ -62,8 +62,8 @@ describe('editor/caret: DOM position for caret', function() { pc.newline(), pc.plain("world"), ]); - const {offset, lineIndex, nodeIndex} = - getLineAndNodePosition(model, {index: 2, offset: 5}); + const { offset, lineIndex, nodeIndex } = + getLineAndNodePosition(model, { index: 2, offset: 5 }); expect(lineIndex).toBe(1); expect(nodeIndex).toBe(0); expect(offset).toBe(5); @@ -75,8 +75,8 @@ describe('editor/caret: DOM position for caret', function() { pc.newline(), pc.plain("world"), ]); - const {offset, lineIndex, nodeIndex} = - getLineAndNodePosition(model, {index: 2, offset: 0}); + const { offset, lineIndex, nodeIndex } = + getLineAndNodePosition(model, { index: 2, offset: 0 }); expect(lineIndex).toBe(1); expect(nodeIndex).toBe(0); expect(offset).toBe(0); @@ -89,8 +89,8 @@ describe('editor/caret: DOM position for caret', function() { pc.newline(), pc.plain("world"), ]); - const {offset, lineIndex, nodeIndex} = - getLineAndNodePosition(model, {index: 1, offset: 1}); + const { offset, lineIndex, nodeIndex } = + getLineAndNodePosition(model, { index: 1, offset: 1 }); expect(lineIndex).toBe(1); expect(nodeIndex).toBe(-1); expect(offset).toBe(0); @@ -103,8 +103,8 @@ describe('editor/caret: DOM position for caret', function() { pc.newline(), pc.plain("world"), ]); - const {offset, lineIndex, nodeIndex} = - getLineAndNodePosition(model, {index: 3, offset: 0}); + const { offset, lineIndex, nodeIndex } = + getLineAndNodePosition(model, { index: 3, offset: 0 }); expect(lineIndex).toBe(2); expect(nodeIndex).toBe(0); expect(offset).toBe(0); @@ -118,8 +118,8 @@ describe('editor/caret: DOM position for caret', function() { pc.userPill("Alice", "@alice:hs.tld"), pc.plain("!"), ]); - const {offset, lineIndex, nodeIndex} = - getLineAndNodePosition(model, {index: 1, offset: 0}); + const { offset, lineIndex, nodeIndex } = + getLineAndNodePosition(model, { index: 1, offset: 0 }); expect(lineIndex).toBe(0); expect(nodeIndex).toBe(0); expect(offset).toBe(5); @@ -131,8 +131,8 @@ describe('editor/caret: DOM position for caret', function() { pc.userPill("Alice", "@alice:hs.tld"), pc.plain("!"), ]); - const {offset, lineIndex, nodeIndex} = - getLineAndNodePosition(model, {index: 1, offset: 2}); + const { offset, lineIndex, nodeIndex } = + getLineAndNodePosition(model, { index: 1, offset: 2 }); expect(lineIndex).toBe(0); expect(nodeIndex).toBe(2); expect(offset).toBe(0); @@ -142,8 +142,8 @@ describe('editor/caret: DOM position for caret', function() { const model = new EditorModel([ pc.userPill("Alice", "@alice:hs.tld"), ]); - const {offset, lineIndex, nodeIndex} = - getLineAndNodePosition(model, {index: 0, offset: 0}); + const { offset, lineIndex, nodeIndex } = + getLineAndNodePosition(model, { index: 0, offset: 0 }); expect(lineIndex).toBe(0); //presumed nodes on line are (caret, pill, caret) expect(nodeIndex).toBe(0); @@ -154,8 +154,8 @@ describe('editor/caret: DOM position for caret', function() { const model = new EditorModel([ pc.userPill("Alice", "@alice:hs.tld"), ]); - const {offset, lineIndex, nodeIndex} = - getLineAndNodePosition(model, {index: 0, offset: 1}); + const { offset, lineIndex, nodeIndex } = + getLineAndNodePosition(model, { index: 0, offset: 1 }); expect(lineIndex).toBe(0); //presumed nodes on line are (caret, pill, caret) expect(nodeIndex).toBe(2); @@ -167,8 +167,8 @@ describe('editor/caret: DOM position for caret', function() { pc.userPill("Alice", "@alice:hs.tld"), pc.userPill("Bob", "@bob:hs.tld"), ]); - const {offset, lineIndex, nodeIndex} = - getLineAndNodePosition(model, {index: 0, offset: 1}); + const { offset, lineIndex, nodeIndex } = + getLineAndNodePosition(model, { index: 0, offset: 1 }); expect(lineIndex).toBe(0); //presumed nodes on line are (caret, pill, caret, pill, caret) expect(nodeIndex).toBe(2); @@ -180,8 +180,8 @@ describe('editor/caret: DOM position for caret', function() { pc.userPill("Alice", "@alice:hs.tld"), pc.userPill("Bob", "@bob:hs.tld"), ]); - const {offset, lineIndex, nodeIndex} = - getLineAndNodePosition(model, {index: 1, offset: 0}); + const { offset, lineIndex, nodeIndex } = + getLineAndNodePosition(model, { index: 1, offset: 0 }); expect(lineIndex).toBe(0); //presumed nodes on line are (caret, pill, caret, pill, caret) expect(nodeIndex).toBe(2); @@ -193,8 +193,8 @@ describe('editor/caret: DOM position for caret', function() { pc.userPill("Alice", "@alice:hs.tld"), pc.userPill("Bob", "@bob:hs.tld"), ]); - const {offset, lineIndex, nodeIndex} = - getLineAndNodePosition(model, {index: 1, offset: 1}); + const { offset, lineIndex, nodeIndex } = + getLineAndNodePosition(model, { index: 1, offset: 1 }); expect(lineIndex).toBe(0); //presumed nodes on line are (caret, pill, caret, pill, caret) expect(nodeIndex).toBe(4); diff --git a/test/editor/deserialize-test.js b/test/editor/deserialize-test.js index 7c7a2f84fb..17e8a31780 100644 --- a/test/editor/deserialize-test.js +++ b/test/editor/deserialize-test.js @@ -15,8 +15,8 @@ limitations under the License. */ import '../skinned-sdk'; // Must be first for skinning to work -import {parseEvent} from "../../src/editor/deserialize"; -import {createPartCreator} from "./mock"; +import { parseEvent } from "../../src/editor/deserialize"; +import { createPartCreator } from "./mock"; function htmlMessage(formattedBody, msgtype = "m.text") { return { @@ -71,22 +71,22 @@ describe('editor/deserialize', function() { describe('text messages', function() { it('test with newlines', function() { const parts = normalize(parseEvent(textMessage("hello\nworld"), createPartCreator())); - expect(parts[0]).toStrictEqual({type: "plain", text: "hello"}); - expect(parts[1]).toStrictEqual({type: "newline", text: "\n"}); - expect(parts[2]).toStrictEqual({type: "plain", text: "world"}); + expect(parts[0]).toStrictEqual({ type: "plain", text: "hello" }); + expect(parts[1]).toStrictEqual({ type: "newline", text: "\n" }); + expect(parts[2]).toStrictEqual({ type: "plain", text: "world" }); expect(parts.length).toBe(3); }); it('@room pill', function() { const parts = normalize(parseEvent(textMessage("text message for @room"), createPartCreator())); expect(parts.length).toBe(2); - expect(parts[0]).toStrictEqual({type: "plain", text: "text message for "}); - expect(parts[1]).toStrictEqual({type: "at-room-pill", text: "@room"}); + expect(parts[0]).toStrictEqual({ type: "plain", text: "text message for " }); + expect(parts[1]).toStrictEqual({ type: "at-room-pill", text: "@room" }); }); it('emote', function() { const text = "says DON'T SHOUT!"; const parts = normalize(parseEvent(textMessage(text, "m.emote"), createPartCreator())); expect(parts.length).toBe(1); - expect(parts[0]).toStrictEqual({type: "plain", text: "/me says DON'T SHOUT!"}); + expect(parts[0]).toStrictEqual({ type: "plain", text: "/me says DON'T SHOUT!" }); }); }); describe('html messages', function() { @@ -94,159 +94,159 @@ describe('editor/deserialize', function() { const html = "bold and emphasized text"; const parts = normalize(parseEvent(htmlMessage(html), createPartCreator())); expect(parts.length).toBe(1); - expect(parts[0]).toStrictEqual({type: "plain", text: "**bold** and _emphasized_ text"}); + expect(parts[0]).toStrictEqual({ type: "plain", text: "**bold** and _emphasized_ text" }); }); it('hyperlink', function() { const html = 'click this!'; const parts = normalize(parseEvent(htmlMessage(html), createPartCreator())); expect(parts.length).toBe(1); - expect(parts[0]).toStrictEqual({type: "plain", text: "click [this](http://example.com/)!"}); + expect(parts[0]).toStrictEqual({ type: "plain", text: "click [this](http://example.com/)!" }); }); it('multiple lines with paragraphs', function() { const html = '

      hello

      world

      '; const parts = normalize(parseEvent(htmlMessage(html), createPartCreator())); expect(parts.length).toBe(4); - expect(parts[0]).toStrictEqual({type: "plain", text: "hello"}); - expect(parts[1]).toStrictEqual({type: "newline", text: "\n"}); - expect(parts[2]).toStrictEqual({type: "newline", text: "\n"}); - expect(parts[3]).toStrictEqual({type: "plain", text: "world"}); + expect(parts[0]).toStrictEqual({ type: "plain", text: "hello" }); + expect(parts[1]).toStrictEqual({ type: "newline", text: "\n" }); + expect(parts[2]).toStrictEqual({ type: "newline", text: "\n" }); + expect(parts[3]).toStrictEqual({ type: "plain", text: "world" }); }); it('multiple lines with line breaks', function() { const html = 'hello
      world'; const parts = normalize(parseEvent(htmlMessage(html), createPartCreator())); expect(parts.length).toBe(3); - expect(parts[0]).toStrictEqual({type: "plain", text: "hello"}); - expect(parts[1]).toStrictEqual({type: "newline", text: "\n"}); - expect(parts[2]).toStrictEqual({type: "plain", text: "world"}); + expect(parts[0]).toStrictEqual({ type: "plain", text: "hello" }); + expect(parts[1]).toStrictEqual({ type: "newline", text: "\n" }); + expect(parts[2]).toStrictEqual({ type: "plain", text: "world" }); }); it('multiple lines mixing paragraphs and line breaks', function() { const html = '

      hello
      warm

      world

      '; const parts = normalize(parseEvent(htmlMessage(html), createPartCreator())); expect(parts.length).toBe(6); - expect(parts[0]).toStrictEqual({type: "plain", text: "hello"}); - expect(parts[1]).toStrictEqual({type: "newline", text: "\n"}); - expect(parts[2]).toStrictEqual({type: "plain", text: "warm"}); - expect(parts[3]).toStrictEqual({type: "newline", text: "\n"}); - expect(parts[4]).toStrictEqual({type: "newline", text: "\n"}); - expect(parts[5]).toStrictEqual({type: "plain", text: "world"}); + expect(parts[0]).toStrictEqual({ type: "plain", text: "hello" }); + expect(parts[1]).toStrictEqual({ type: "newline", text: "\n" }); + expect(parts[2]).toStrictEqual({ type: "plain", text: "warm" }); + expect(parts[3]).toStrictEqual({ type: "newline", text: "\n" }); + expect(parts[4]).toStrictEqual({ type: "newline", text: "\n" }); + expect(parts[5]).toStrictEqual({ type: "plain", text: "world" }); }); it('quote', function() { const html = '

      wise
      words

      indeed

      '; const parts = normalize(parseEvent(htmlMessage(html), createPartCreator())); expect(parts.length).toBe(6); - expect(parts[0]).toStrictEqual({type: "plain", text: "> _wise_"}); - expect(parts[1]).toStrictEqual({type: "newline", text: "\n"}); - expect(parts[2]).toStrictEqual({type: "plain", text: "> **words**"}); - expect(parts[3]).toStrictEqual({type: "newline", text: "\n"}); - expect(parts[4]).toStrictEqual({type: "newline", text: "\n"}); - expect(parts[5]).toStrictEqual({type: "plain", text: "indeed"}); + expect(parts[0]).toStrictEqual({ type: "plain", text: "> _wise_" }); + expect(parts[1]).toStrictEqual({ type: "newline", text: "\n" }); + expect(parts[2]).toStrictEqual({ type: "plain", text: "> **words**" }); + expect(parts[3]).toStrictEqual({ type: "newline", text: "\n" }); + expect(parts[4]).toStrictEqual({ type: "newline", text: "\n" }); + expect(parts[5]).toStrictEqual({ type: "plain", text: "indeed" }); }); it('user pill', function() { const html = "Hi Alice!"; const parts = normalize(parseEvent(htmlMessage(html), createPartCreator())); expect(parts.length).toBe(3); - expect(parts[0]).toStrictEqual({type: "plain", text: "Hi "}); - expect(parts[1]).toStrictEqual({type: "user-pill", text: "Alice", resourceId: "@alice:hs.tld"}); - expect(parts[2]).toStrictEqual({type: "plain", text: "!"}); + expect(parts[0]).toStrictEqual({ type: "plain", text: "Hi " }); + expect(parts[1]).toStrictEqual({ type: "user-pill", text: "Alice", resourceId: "@alice:hs.tld" }); + expect(parts[2]).toStrictEqual({ type: "plain", text: "!" }); }); it('user pill with displayname containing backslash', function() { const html = "Hi Alice\\!"; const parts = normalize(parseEvent(htmlMessage(html), createPartCreator())); expect(parts.length).toBe(3); - expect(parts[0]).toStrictEqual({type: "plain", text: "Hi "}); - expect(parts[1]).toStrictEqual({type: "user-pill", text: "Alice\\", resourceId: "@alice:hs.tld"}); - expect(parts[2]).toStrictEqual({type: "plain", text: "!"}); + expect(parts[0]).toStrictEqual({ type: "plain", text: "Hi " }); + expect(parts[1]).toStrictEqual({ type: "user-pill", text: "Alice\\", resourceId: "@alice:hs.tld" }); + expect(parts[2]).toStrictEqual({ type: "plain", text: "!" }); }); it('user pill with displayname containing opening square bracket', function() { const html = "Hi Alice[[!"; const parts = normalize(parseEvent(htmlMessage(html), createPartCreator())); expect(parts.length).toBe(3); - expect(parts[0]).toStrictEqual({type: "plain", text: "Hi "}); - expect(parts[1]).toStrictEqual({type: "user-pill", text: "Alice[[", resourceId: "@alice:hs.tld"}); - expect(parts[2]).toStrictEqual({type: "plain", text: "!"}); + expect(parts[0]).toStrictEqual({ type: "plain", text: "Hi " }); + expect(parts[1]).toStrictEqual({ type: "user-pill", text: "Alice[[", resourceId: "@alice:hs.tld" }); + expect(parts[2]).toStrictEqual({ type: "plain", text: "!" }); }); it('user pill with displayname containing closing square bracket', function() { const html = "Hi Alice]!"; const parts = normalize(parseEvent(htmlMessage(html), createPartCreator())); expect(parts.length).toBe(3); - expect(parts[0]).toStrictEqual({type: "plain", text: "Hi "}); - expect(parts[1]).toStrictEqual({type: "user-pill", text: "Alice]", resourceId: "@alice:hs.tld"}); - expect(parts[2]).toStrictEqual({type: "plain", text: "!"}); + expect(parts[0]).toStrictEqual({ type: "plain", text: "Hi " }); + expect(parts[1]).toStrictEqual({ type: "user-pill", text: "Alice]", resourceId: "@alice:hs.tld" }); + expect(parts[2]).toStrictEqual({ type: "plain", text: "!" }); }); it('room pill', function() { const html = "Try #room:hs.tld?"; const parts = normalize(parseEvent(htmlMessage(html), createPartCreator())); expect(parts.length).toBe(3); - expect(parts[0]).toStrictEqual({type: "plain", text: "Try "}); - expect(parts[1]).toStrictEqual({type: "room-pill", text: "#room:hs.tld", resourceId: "#room:hs.tld"}); - expect(parts[2]).toStrictEqual({type: "plain", text: "?"}); + expect(parts[0]).toStrictEqual({ type: "plain", text: "Try " }); + expect(parts[1]).toStrictEqual({ type: "room-pill", text: "#room:hs.tld", resourceId: "#room:hs.tld" }); + expect(parts[2]).toStrictEqual({ type: "plain", text: "?" }); }); it('@room pill', function() { const html = "formatted message for @room"; const parts = normalize(parseEvent(htmlMessage(html), createPartCreator())); expect(parts.length).toBe(2); - expect(parts[0]).toStrictEqual({type: "plain", text: "_formatted_ message for "}); - expect(parts[1]).toStrictEqual({type: "at-room-pill", text: "@room"}); + expect(parts[0]).toStrictEqual({ type: "plain", text: "_formatted_ message for " }); + expect(parts[1]).toStrictEqual({ type: "at-room-pill", text: "@room" }); }); it('inline code', function() { const html = "there is no place like 127.0.0.1!"; const parts = normalize(parseEvent(htmlMessage(html), createPartCreator())); expect(parts.length).toBe(1); - expect(parts[0]).toStrictEqual({type: "plain", text: "there is no place like `127.0.0.1`!"}); + expect(parts[0]).toStrictEqual({ type: "plain", text: "there is no place like `127.0.0.1`!" }); }); it('code block with no trailing text', function() { const html = "
      0xDEADBEEF\n
      \n"; const parts = normalize(parseEvent(htmlMessage(html), createPartCreator())); console.log(parts); expect(parts.length).toBe(5); - expect(parts[0]).toStrictEqual({type: "plain", text: "```"}); - expect(parts[1]).toStrictEqual({type: "newline", text: "\n"}); - expect(parts[2]).toStrictEqual({type: "plain", text: "0xDEADBEEF"}); - expect(parts[3]).toStrictEqual({type: "newline", text: "\n"}); - expect(parts[4]).toStrictEqual({type: "plain", text: "```"}); + expect(parts[0]).toStrictEqual({ type: "plain", text: "```" }); + expect(parts[1]).toStrictEqual({ type: "newline", text: "\n" }); + expect(parts[2]).toStrictEqual({ type: "plain", text: "0xDEADBEEF" }); + expect(parts[3]).toStrictEqual({ type: "newline", text: "\n" }); + expect(parts[4]).toStrictEqual({ type: "plain", text: "```" }); }); // failing likely because of https://github.com/vector-im/element-web/issues/10316 xit('code block with no trailing text and no newlines', function() { const html = "
      0xDEADBEEF
      "; const parts = normalize(parseEvent(htmlMessage(html), createPartCreator())); expect(parts.length).toBe(5); - expect(parts[0]).toStrictEqual({type: "plain", text: "```"}); - expect(parts[1]).toStrictEqual({type: "newline", text: "\n"}); - expect(parts[2]).toStrictEqual({type: "plain", text: "0xDEADBEEF"}); - expect(parts[3]).toStrictEqual({type: "newline", text: "\n"}); - expect(parts[4]).toStrictEqual({type: "plain", text: "```"}); + expect(parts[0]).toStrictEqual({ type: "plain", text: "```" }); + expect(parts[1]).toStrictEqual({ type: "newline", text: "\n" }); + expect(parts[2]).toStrictEqual({ type: "plain", text: "0xDEADBEEF" }); + expect(parts[3]).toStrictEqual({ type: "newline", text: "\n" }); + expect(parts[4]).toStrictEqual({ type: "plain", text: "```" }); }); it('unordered lists', function() { const html = "
      • Oak
      • Spruce
      • Birch
      "; const parts = normalize(parseEvent(htmlMessage(html), createPartCreator())); expect(parts.length).toBe(5); - expect(parts[0]).toStrictEqual({type: "plain", text: "- Oak"}); - expect(parts[1]).toStrictEqual({type: "newline", text: "\n"}); - expect(parts[2]).toStrictEqual({type: "plain", text: "- Spruce"}); - expect(parts[3]).toStrictEqual({type: "newline", text: "\n"}); - expect(parts[4]).toStrictEqual({type: "plain", text: "- Birch"}); + expect(parts[0]).toStrictEqual({ type: "plain", text: "- Oak" }); + expect(parts[1]).toStrictEqual({ type: "newline", text: "\n" }); + expect(parts[2]).toStrictEqual({ type: "plain", text: "- Spruce" }); + expect(parts[3]).toStrictEqual({ type: "newline", text: "\n" }); + expect(parts[4]).toStrictEqual({ type: "plain", text: "- Birch" }); }); it('ordered lists', function() { const html = "
      1. Start
      2. Continue
      3. Finish
      "; const parts = normalize(parseEvent(htmlMessage(html), createPartCreator())); expect(parts.length).toBe(5); - expect(parts[0]).toStrictEqual({type: "plain", text: "1. Start"}); - expect(parts[1]).toStrictEqual({type: "newline", text: "\n"}); - expect(parts[2]).toStrictEqual({type: "plain", text: "2. Continue"}); - expect(parts[3]).toStrictEqual({type: "newline", text: "\n"}); - expect(parts[4]).toStrictEqual({type: "plain", text: "3. Finish"}); + expect(parts[0]).toStrictEqual({ type: "plain", text: "1. Start" }); + expect(parts[1]).toStrictEqual({ type: "newline", text: "\n" }); + expect(parts[2]).toStrictEqual({ type: "plain", text: "2. Continue" }); + expect(parts[3]).toStrictEqual({ type: "newline", text: "\n" }); + expect(parts[4]).toStrictEqual({ type: "plain", text: "3. Finish" }); }); it('mx-reply is stripped', function() { const html = "foobar"; const parts = normalize(parseEvent(htmlMessage(html), createPartCreator())); expect(parts.length).toBe(1); - expect(parts[0]).toStrictEqual({type: "plain", text: "bar"}); + expect(parts[0]).toStrictEqual({ type: "plain", text: "bar" }); }); it('emote', function() { const html = "says DON'T SHOUT!"; const parts = normalize(parseEvent(htmlMessage(html, "m.emote"), createPartCreator())); expect(parts.length).toBe(1); - expect(parts[0]).toStrictEqual({type: "plain", text: "/me says _DON'T SHOUT_!"}); + expect(parts[0]).toStrictEqual({ type: "plain", text: "/me says _DON'T SHOUT_!" }); }); }); }); diff --git a/test/editor/diff-test.js b/test/editor/diff-test.js index 4637206b27..e525731340 100644 --- a/test/editor/diff-test.js +++ b/test/editor/diff-test.js @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import {diffDeletion, diffAtCaret} from "../../src/editor/diff"; +import { diffDeletion, diffAtCaret } from "../../src/editor/diff"; describe('editor/diff', function() { describe('diffDeletion', function() { diff --git a/test/editor/history-test.js b/test/editor/history-test.js index e54c1e7ea9..e3ae3e16f6 100644 --- a/test/editor/history-test.js +++ b/test/editor/history-test.js @@ -14,13 +14,13 @@ See the License for the specific language governing permissions and limitations under the License. */ -import HistoryManager, {MAX_STEP_LENGTH} from "../../src/editor/history"; +import HistoryManager, { MAX_STEP_LENGTH } from "../../src/editor/history"; describe('editor/history', function() { it('push, then undo', function() { const history = new HistoryManager(); const parts = ["hello"]; - const model = {serializeParts: () => parts.slice()}; + const model = { serializeParts: () => parts.slice() }; const caret1 = {}; const result1 = history.tryPush(model, caret1); expect(result1).toEqual(true); @@ -35,7 +35,7 @@ describe('editor/history', function() { it('push, undo, then redo', function() { const history = new HistoryManager(); const parts = ["hello"]; - const model = {serializeParts: () => parts.slice()}; + const model = { serializeParts: () => parts.slice() }; history.tryPush(model, {}); parts[0] = "hello world"; const caret2 = {}; @@ -51,7 +51,7 @@ describe('editor/history', function() { it('push, undo, push, ensure you can`t redo', function() { const history = new HistoryManager(); const parts = ["hello"]; - const model = {serializeParts: () => parts.slice()}; + const model = { serializeParts: () => parts.slice() }; history.tryPush(model, {}); parts[0] = "hello world"; history.tryPush(model, {}); @@ -63,10 +63,10 @@ describe('editor/history', function() { it('not every keystroke stores a history step', function() { const history = new HistoryManager(); const parts = ["hello"]; - const model = {serializeParts: () => parts.slice()}; + const model = { serializeParts: () => parts.slice() }; const firstCaret = {}; history.tryPush(model, firstCaret); - const diff = {added: "o"}; + const diff = { added: "o" }; let keystrokeCount = 0; do { parts[0] = parts[0] + diff.added; @@ -80,24 +80,24 @@ describe('editor/history', function() { }); it('history step is added at word boundary', function() { const history = new HistoryManager(); - const model = {serializeParts: () => parts.slice()}; + const model = { serializeParts: () => parts.slice() }; const parts = ["h"]; - let diff = {added: "h"}; + let diff = { added: "h" }; expect(history.tryPush(model, {}, "insertText", diff)).toEqual(false); - diff = {added: "i"}; + diff = { added: "i" }; parts[0] = "hi"; expect(history.tryPush(model, {}, "insertText", diff)).toEqual(false); - diff = {added: " "}; + diff = { added: " " }; parts[0] = "hi "; const spaceCaret = {}; expect(history.tryPush(model, spaceCaret, "insertText", diff)).toEqual(true); - diff = {added: "y"}; + diff = { added: "y" }; parts[0] = "hi y"; expect(history.tryPush(model, {}, "insertText", diff)).toEqual(false); - diff = {added: "o"}; + diff = { added: "o" }; parts[0] = "hi yo"; expect(history.tryPush(model, {}, "insertText", diff)).toEqual(false); - diff = {added: "u"}; + diff = { added: "u" }; parts[0] = "hi you"; expect(history.canUndo()).toEqual(true); @@ -108,11 +108,11 @@ describe('editor/history', function() { it('keystroke that didn\'t add a step can undo', function() { const history = new HistoryManager(); const parts = ["hello"]; - const model = {serializeParts: () => parts.slice()}; + const model = { serializeParts: () => parts.slice() }; const firstCaret = {}; history.tryPush(model, {}); parts[0] = "helloo"; - const result = history.tryPush(model, {}, "insertText", {added: "o"}); + const result = history.tryPush(model, {}, "insertText", { added: "o" }); expect(result).toEqual(false); expect(history.canUndo()).toEqual(true); const undoState = history.undo(model); @@ -122,11 +122,11 @@ describe('editor/history', function() { it('undo after keystroke that didn\'t add a step is able to redo', function() { const history = new HistoryManager(); const parts = ["hello"]; - const model = {serializeParts: () => parts.slice()}; + const model = { serializeParts: () => parts.slice() }; history.tryPush(model, {}); parts[0] = "helloo"; - const caret = {last: true}; - history.tryPush(model, caret, "insertText", {added: "o"}); + const caret = { last: true }; + history.tryPush(model, caret, "insertText", { added: "o" }); history.undo(model); expect(history.canRedo()).toEqual(true); const redoState = history.redo(); @@ -136,10 +136,10 @@ describe('editor/history', function() { it('overwriting text always stores a step', function() { const history = new HistoryManager(); const parts = ["hello"]; - const model = {serializeParts: () => parts.slice()}; + const model = { serializeParts: () => parts.slice() }; const firstCaret = {}; history.tryPush(model, firstCaret); - const diff = {at: 1, added: "a", removed: "e"}; + const diff = { at: 1, added: "a", removed: "e" }; const result = history.tryPush(model, {}, "insertText", diff); expect(result).toEqual(true); }); diff --git a/test/editor/mock.js b/test/editor/mock.js index 6de65cf23d..2d82d22033 100644 --- a/test/editor/mock.js +++ b/test/editor/mock.js @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import {PartCreator} from "../../src/editor/parts"; +import { PartCreator } from "../../src/editor/parts"; class MockAutoComplete { constructor(updateCallback, partCreator, completions) { @@ -25,7 +25,7 @@ class MockAutoComplete { } close() { - this._updateCallback({close: true}); + this._updateCallback({ close: true }); } tryComplete(close = true) { @@ -40,7 +40,7 @@ class MockAutoComplete { } else { pill = this._partCreator.roomPill(match.resourceId); } - this._updateCallback({replaceParts: [pill], close}); + this._updateCallback({ replaceParts: [pill], close }); } } diff --git a/test/editor/model-test.js b/test/editor/model-test.js index 2df9fdd573..35bd4143a7 100644 --- a/test/editor/model-test.js +++ b/test/editor/model-test.js @@ -15,14 +15,14 @@ limitations under the License. */ import EditorModel from "../../src/editor/model"; -import {createPartCreator, createRenderer} from "./mock"; +import { createPartCreator, createRenderer } from "./mock"; describe('editor/model', function() { describe('plain text manipulation', function() { it('insert text into empty document', function() { const renderer = createRenderer(); const model = new EditorModel([], createPartCreator(), renderer); - model.update("hello", "insertText", {offset: 5, atNodeEnd: true}); + model.update("hello", "insertText", { offset: 5, atNodeEnd: true }); expect(renderer.count).toBe(1); expect(renderer.caret.index).toBe(0); expect(renderer.caret.offset).toBe(5); @@ -34,7 +34,7 @@ describe('editor/model', function() { const renderer = createRenderer(); const pc = createPartCreator(); const model = new EditorModel([pc.plain("hello")], pc, renderer); - model.update("hello world", "insertText", {offset: 11, atNodeEnd: true}); + model.update("hello world", "insertText", { offset: 11, atNodeEnd: true }); expect(renderer.count).toBe(1); expect(renderer.caret.index).toBe(0); expect(renderer.caret.offset).toBe(11); @@ -46,7 +46,7 @@ describe('editor/model', function() { const renderer = createRenderer(); const pc = createPartCreator(); const model = new EditorModel([pc.plain("world")], pc, renderer); - model.update("hello world", "insertText", {offset: 6, atNodeEnd: false}); + model.update("hello world", "insertText", { offset: 6, atNodeEnd: false }); expect(renderer.count).toBe(1); expect(renderer.caret.index).toBe(0); expect(renderer.caret.offset).toBe(6); @@ -60,7 +60,7 @@ describe('editor/model', function() { const renderer = createRenderer(); const pc = createPartCreator(); const model = new EditorModel([pc.plain("hello")], pc, renderer); - model.update("hello\n", "insertText", {offset: 6, atNodeEnd: true}); + model.update("hello\n", "insertText", { offset: 6, atNodeEnd: true }); expect(renderer.count).toBe(1); expect(renderer.caret.index).toBe(1); expect(renderer.caret.offset).toBe(1); @@ -74,7 +74,7 @@ describe('editor/model', function() { const renderer = createRenderer(); const pc = createPartCreator(); const model = new EditorModel([pc.plain("hello")], pc, renderer); - model.update("hello\n\n\nworld!", "insertText", {offset: 14, atNodeEnd: true}); + model.update("hello\n\n\nworld!", "insertText", { offset: 14, atNodeEnd: true }); expect(renderer.count).toBe(1); expect(renderer.caret.index).toBe(4); expect(renderer.caret.offset).toBe(6); @@ -99,7 +99,7 @@ describe('editor/model', function() { pc.newline(), pc.plain("world"), ], pc, renderer); - model.update("hello\nwarm\nworld", "insertText", {offset: 10, atNodeEnd: true}); + model.update("hello\nwarm\nworld", "insertText", { offset: 10, atNodeEnd: true }); console.log(model.serializeParts()); expect(renderer.count).toBe(1); expect(renderer.caret.index).toBe(2); @@ -125,7 +125,7 @@ describe('editor/model', function() { pc.plain("try "), pc.roomPill("#someroom"), ], pc, renderer); - model.update("try foo#someroom", "insertText", {offset: 7, atNodeEnd: false}); + model.update("try foo#someroom", "insertText", { offset: 7, atNodeEnd: false }); expect(renderer.caret.index).toBe(0); expect(renderer.caret.offset).toBe(7); expect(model.parts.length).toBe(2); @@ -142,7 +142,7 @@ describe('editor/model', function() { pc.roomPill("#someroom"), pc.plain("?"), ], pc, renderer); - model.update("try #some perhapsroom?", "insertText", {offset: 17, atNodeEnd: false}); + model.update("try #some perhapsroom?", "insertText", { offset: 17, atNodeEnd: false }); expect(renderer.caret.index).toBe(2); expect(renderer.caret.offset).toBe(8); expect(model.parts.length).toBe(3); @@ -157,7 +157,7 @@ describe('editor/model', function() { const renderer = createRenderer(); const pc = createPartCreator(); const model = new EditorModel([pc.roomPill("#someroom")], pc, renderer); - model.update("#someroo", "deleteContentBackward", {offset: 8, atNodeEnd: true}); + model.update("#someroo", "deleteContentBackward", { offset: 8, atNodeEnd: true }); expect(renderer.count).toBe(1); expect(renderer.caret.index).toBe(-1); expect(renderer.caret.offset).toBe(0); @@ -167,7 +167,7 @@ describe('editor/model', function() { const renderer = createRenderer(); const pc = createPartCreator(); const model = new EditorModel([pc.roomPill("#someroom")], pc, renderer); - model.update("someroom", "deleteContentForward", {offset: 0, atNodeEnd: false}); + model.update("someroom", "deleteContentForward", { offset: 0, atNodeEnd: false }); expect(renderer.count).toBe(1); expect(renderer.caret.index).toBe(-1); expect(renderer.caret.offset).toBe(0); @@ -177,10 +177,10 @@ describe('editor/model', function() { describe('auto-complete', function() { it('insert user pill', function() { const renderer = createRenderer(); - const pc = createPartCreator([{resourceId: "@alice", label: "Alice"}]); + const pc = createPartCreator([{ resourceId: "@alice", label: "Alice" }]); const model = new EditorModel([pc.plain("hello ")], pc, renderer); - model.update("hello @a", "insertText", {offset: 8, atNodeEnd: true}); + model.update("hello @a", "insertText", { offset: 8, atNodeEnd: true }); expect(renderer.count).toBe(1); expect(renderer.caret.index).toBe(1); @@ -205,10 +205,10 @@ describe('editor/model', function() { it('insert room pill', function() { const renderer = createRenderer(); - const pc = createPartCreator([{resourceId: "#riot-dev"}]); + const pc = createPartCreator([{ resourceId: "#riot-dev" }]); const model = new EditorModel([pc.plain("hello ")], pc, renderer); - model.update("hello #r", "insertText", {offset: 8, atNodeEnd: true}); + model.update("hello #r", "insertText", { offset: 8, atNodeEnd: true }); expect(renderer.count).toBe(1); expect(renderer.caret.index).toBe(1); @@ -233,12 +233,12 @@ describe('editor/model', function() { it('type after inserting pill', function() { const renderer = createRenderer(); - const pc = createPartCreator([{resourceId: "#riot-dev"}]); + const pc = createPartCreator([{ resourceId: "#riot-dev" }]); const model = new EditorModel([pc.plain("hello ")], pc, renderer); - model.update("hello #r", "insertText", {offset: 8, atNodeEnd: true}); + model.update("hello #r", "insertText", { offset: 8, atNodeEnd: true }); model.autoComplete.tryComplete(); // see MockAutoComplete - model.update("hello #riot-dev!!", "insertText", {offset: 17, atNodeEnd: true}); + model.update("hello #riot-dev!!", "insertText", { offset: 17, atNodeEnd: true }); expect(renderer.count).toBe(3); expect(renderer.caret.index).toBe(2); @@ -254,10 +254,10 @@ describe('editor/model', function() { it('pasting text does not trigger auto-complete', function() { const renderer = createRenderer(); - const pc = createPartCreator([{resourceId: "#define-room"}]); + const pc = createPartCreator([{ resourceId: "#define-room" }]); const model = new EditorModel([pc.plain("try ")], pc, renderer); - model.update("try #define", "insertFromPaste", {offset: 11, atNodeEnd: true}); + model.update("try #define", "insertFromPaste", { offset: 11, atNodeEnd: true }); expect(model.autoComplete).toBeFalsy(); expect(renderer.caret.index).toBe(0); @@ -269,10 +269,10 @@ describe('editor/model', function() { it('dropping text does not trigger auto-complete', function() { const renderer = createRenderer(); - const pc = createPartCreator([{resourceId: "#define-room"}]); + const pc = createPartCreator([{ resourceId: "#define-room" }]); const model = new EditorModel([pc.plain("try ")], pc, renderer); - model.update("try #define", "insertFromDrop", {offset: 11, atNodeEnd: true}); + model.update("try #define", "insertFromDrop", { offset: 11, atNodeEnd: true }); expect(model.autoComplete).toBeFalsy(); expect(renderer.caret.index).toBe(0); @@ -284,17 +284,17 @@ describe('editor/model', function() { it('insert room pill without splitting at the colon', () => { const renderer = createRenderer(); - const pc = createPartCreator([{resourceId: "#room:server"}]); + const pc = createPartCreator([{ resourceId: "#room:server" }]); const model = new EditorModel([], pc, renderer); - model.update("#roo", "insertText", {offset: 4, atNodeEnd: true}); + model.update("#roo", "insertText", { offset: 4, atNodeEnd: true }); expect(renderer.count).toBe(1); expect(model.parts.length).toBe(1); expect(model.parts[0].type).toBe("pill-candidate"); expect(model.parts[0].text).toBe("#roo"); - model.update("#room:s", "insertText", {offset: 7, atNodeEnd: true}); + model.update("#room:s", "insertText", { offset: 7, atNodeEnd: true }); expect(renderer.count).toBe(2); expect(model.parts.length).toBe(1); @@ -304,10 +304,10 @@ describe('editor/model', function() { it('allow typing e-mail addresses without splitting at the @', () => { const renderer = createRenderer(); - const pc = createPartCreator([{resourceId: "@alice", label: "Alice"}]); + const pc = createPartCreator([{ resourceId: "@alice", label: "Alice" }]); const model = new EditorModel([], pc, renderer); - model.update("foo@a", "insertText", {offset: 5, atNodeEnd: true}); + model.update("foo@a", "insertText", { offset: 5, atNodeEnd: true }); expect(renderer.count).toBe(1); expect(model.parts.length).toBe(1); diff --git a/test/editor/operations-test.js b/test/editor/operations-test.js index 90a9812306..32ccaa5440 100644 --- a/test/editor/operations-test.js +++ b/test/editor/operations-test.js @@ -15,10 +15,10 @@ limitations under the License. */ import EditorModel from "../../src/editor/model"; -import {createPartCreator, createRenderer} from "./mock"; -import {toggleInlineFormat} from "../../src/editor/operations"; +import { createPartCreator, createRenderer } from "./mock"; +import { toggleInlineFormat } from "../../src/editor/operations"; -const SERIALIZED_NEWLINE = {"text": "\n", "type": "newline"}; +const SERIALIZED_NEWLINE = { "text": "\n", "type": "newline" }; describe('editor/operations: formatting operations', () => { describe('toggleInlineFormat', () => { @@ -33,9 +33,9 @@ describe('editor/operations: formatting operations', () => { model.positionForOffset(11, false)); // around "world" expect(range.parts[0].text).toBe("world"); - expect(model.serializeParts()).toEqual([{"text": "hello world!", "type": "plain"}]); + expect(model.serializeParts()).toEqual([{ "text": "hello world!", "type": "plain" }]); toggleInlineFormat(range, "_"); - expect(model.serializeParts()).toEqual([{"text": "hello _world_!", "type": "plain"}]); + expect(model.serializeParts()).toEqual([{ "text": "hello _world_!", "type": "plain" }]); }); it('works for parts of words', () => { @@ -49,9 +49,9 @@ describe('editor/operations: formatting operations', () => { model.positionForOffset(10, false)); // around "orl" expect(range.parts[0].text).toBe("orl"); - expect(model.serializeParts()).toEqual([{"text": "hello world!", "type": "plain"}]); + expect(model.serializeParts()).toEqual([{ "text": "hello world!", "type": "plain" }]); toggleInlineFormat(range, "*"); - expect(model.serializeParts()).toEqual([{"text": "hello w*orl*d!", "type": "plain"}]); + expect(model.serializeParts()).toEqual([{ "text": "hello w*orl*d!", "type": "plain" }]); }); it('works for around pills', () => { @@ -68,15 +68,15 @@ describe('editor/operations: formatting operations', () => { expect(range.parts.map(p => p.text).join("")).toBe("there @room, how are you"); expect(model.serializeParts()).toEqual([ - {"text": "hello there ", "type": "plain"}, - {"text": "@room", "type": "at-room-pill"}, - {"text": ", how are you doing?", "type": "plain"}, + { "text": "hello there ", "type": "plain" }, + { "text": "@room", "type": "at-room-pill" }, + { "text": ", how are you doing?", "type": "plain" }, ]); toggleInlineFormat(range, "_"); expect(model.serializeParts()).toEqual([ - {"text": "hello _there ", "type": "plain"}, - {"text": "@room", "type": "at-room-pill"}, - {"text": ", how are you_ doing?", "type": "plain"}, + { "text": "hello _there ", "type": "plain" }, + { "text": "@room", "type": "at-room-pill" }, + { "text": ", how are you_ doing?", "type": "plain" }, ]); }); @@ -94,15 +94,15 @@ describe('editor/operations: formatting operations', () => { expect(range.parts.map(p => p.text).join("")).toBe("world,\nhow"); expect(model.serializeParts()).toEqual([ - {"text": "hello world,", "type": "plain"}, + { "text": "hello world,", "type": "plain" }, SERIALIZED_NEWLINE, - {"text": "how are you doing?", "type": "plain"}, + { "text": "how are you doing?", "type": "plain" }, ]); toggleInlineFormat(range, "**"); expect(model.serializeParts()).toEqual([ - {"text": "hello **world,", "type": "plain"}, + { "text": "hello **world,", "type": "plain" }, SERIALIZED_NEWLINE, - {"text": "how** are you doing?", "type": "plain"}, + { "text": "how** are you doing?", "type": "plain" }, ]); }); @@ -125,9 +125,9 @@ describe('editor/operations: formatting operations', () => { expect(model.serializeParts()).toEqual([ SERIALIZED_NEWLINE, SERIALIZED_NEWLINE, - {"text": "hello world,", "type": "plain"}, + { "text": "hello world,", "type": "plain" }, SERIALIZED_NEWLINE, - {"text": "how are you doing?", "type": "plain"}, + { "text": "how are you doing?", "type": "plain" }, SERIALIZED_NEWLINE, SERIALIZED_NEWLINE, ]); @@ -135,9 +135,9 @@ describe('editor/operations: formatting operations', () => { expect(model.serializeParts()).toEqual([ SERIALIZED_NEWLINE, SERIALIZED_NEWLINE, - {"text": "**hello world,", "type": "plain"}, + { "text": "**hello world,", "type": "plain" }, SERIALIZED_NEWLINE, - {"text": "how are you doing?**", "type": "plain"}, + { "text": "how are you doing?**", "type": "plain" }, SERIALIZED_NEWLINE, SERIALIZED_NEWLINE, ]); @@ -158,32 +158,32 @@ describe('editor/operations: formatting operations', () => { let range = model.startRange(model.positionForOffset(0, true), model.getPositionAtEnd()); // select-all expect(model.serializeParts()).toEqual([ - {"text": "hello world,", "type": "plain"}, + { "text": "hello world,", "type": "plain" }, SERIALIZED_NEWLINE, - {"text": "how are you doing?", "type": "plain"}, + { "text": "how are you doing?", "type": "plain" }, SERIALIZED_NEWLINE, SERIALIZED_NEWLINE, - {"text": "new paragraph", "type": "plain"}, + { "text": "new paragraph", "type": "plain" }, ]); toggleInlineFormat(range, "__"); expect(model.serializeParts()).toEqual([ - {"text": "__hello world,", "type": "plain"}, + { "text": "__hello world,", "type": "plain" }, SERIALIZED_NEWLINE, - {"text": "how are you doing?__", "type": "plain"}, + { "text": "how are you doing?__", "type": "plain" }, SERIALIZED_NEWLINE, SERIALIZED_NEWLINE, - {"text": "__new paragraph__", "type": "plain"}, + { "text": "__new paragraph__", "type": "plain" }, ]); range = model.startRange(model.positionForOffset(0, true), model.getPositionAtEnd()); // select-all console.log("RANGE", range.parts); toggleInlineFormat(range, "__"); expect(model.serializeParts()).toEqual([ - {"text": "hello world,", "type": "plain"}, + { "text": "hello world,", "type": "plain" }, SERIALIZED_NEWLINE, - {"text": "how are you doing?", "type": "plain"}, + { "text": "how are you doing?", "type": "plain" }, SERIALIZED_NEWLINE, SERIALIZED_NEWLINE, - {"text": "new paragraph", "type": "plain"}, + { "text": "new paragraph", "type": "plain" }, ]); }); }); diff --git a/test/editor/position-test.js b/test/editor/position-test.js index 90f40c21a7..813a8e9f7f 100644 --- a/test/editor/position-test.js +++ b/test/editor/position-test.js @@ -15,7 +15,7 @@ limitations under the License. */ import EditorModel from "../../src/editor/model"; -import {createPartCreator} from "./mock"; +import { createPartCreator } from "./mock"; function createRenderer() { const render = (c) => { diff --git a/test/editor/range-test.js b/test/editor/range-test.js index 60055af824..d411a0d911 100644 --- a/test/editor/range-test.js +++ b/test/editor/range-test.js @@ -15,7 +15,7 @@ limitations under the License. */ import EditorModel from "../../src/editor/model"; -import {createPartCreator, createRenderer} from "./mock"; +import { createPartCreator, createRenderer } from "./mock"; const pillChannel = "#riot-dev:matrix.org"; diff --git a/test/editor/serialize-test.js b/test/editor/serialize-test.js index f0d577ea21..691130bd34 100644 --- a/test/editor/serialize-test.js +++ b/test/editor/serialize-test.js @@ -15,8 +15,8 @@ limitations under the License. */ import EditorModel from "../../src/editor/model"; -import {htmlSerializeIfNeeded} from "../../src/editor/serialize"; -import {createPartCreator} from "./mock"; +import { htmlSerializeIfNeeded } from "../../src/editor/serialize"; +import { createPartCreator } from "./mock"; describe('editor/serialize', function() { it('user pill turns message into html', function() { diff --git a/test/end-to-end-tests/src/rest/consent.js b/test/end-to-end-tests/src/rest/consent.js index 956441571b..8be27258d0 100644 --- a/test/end-to-end-tests/src/rest/consent.js +++ b/test/end-to-end-tests/src/rest/consent.js @@ -27,5 +27,5 @@ module.exports.approveConsent = async function(consentUrl) { const h = doc("input[name=h]").val(); const formAction = doc("form").attr("action"); const absAction = url.resolve(consentUrl, formAction); - await request.post(absAction).form({v, u, h}); + await request.post(absAction).form({ v, u, h }); }; diff --git a/test/end-to-end-tests/src/rest/creator.js b/test/end-to-end-tests/src/rest/creator.js index 03b2e099bc..f01a325a71 100644 --- a/test/end-to-end-tests/src/rest/creator.js +++ b/test/end-to-end-tests/src/rest/creator.js @@ -15,7 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -const {exec} = require('child_process'); +const { exec } = require('child_process'); const request = require('request-promise-native'); const RestSession = require('./session'); const RestMultiSession = require('./multi'); @@ -26,7 +26,7 @@ function execAsync(command, options) { if (error) { reject(error); } else { - resolve({stdout, stderr}); + resolve({ stdout, stderr }); } }); }); @@ -67,7 +67,7 @@ module.exports = class RestSessionCreator { registerCmd, ].join(' && '); - await execAsync(allCmds, {cwd: this.cwd, encoding: 'utf-8'}); + await execAsync(allCmds, { cwd: this.cwd, encoding: 'utf-8' }); } async _authenticate(username, password) { @@ -80,7 +80,7 @@ module.exports = class RestSessionCreator { "password": password, }; const url = `${this.hsUrl}/_matrix/client/r0/login`; - const responseBody = await request.post({url, json: true, body: requestBody}); + const responseBody = await request.post({ url, json: true, body: requestBody }); return { accessToken: responseBody.access_token, homeServer: responseBody.home_server, diff --git a/test/end-to-end-tests/src/rest/session.js b/test/end-to-end-tests/src/rest/session.js index 5b97824f5c..3c04592d02 100644 --- a/test/end-to-end-tests/src/rest/session.js +++ b/test/end-to-end-tests/src/rest/session.js @@ -17,7 +17,7 @@ limitations under the License. const request = require('request-promise-native'); const Logger = require('../logger'); const RestRoom = require('./room'); -const {approveConsent} = require('./consent'); +const { approveConsent } = require('./consent'); module.exports = class RestSession { constructor(credentials) { diff --git a/test/end-to-end-tests/src/scenario.js b/test/end-to-end-tests/src/scenario.js index 2191d630ac..c44f209bf3 100644 --- a/test/end-to-end-tests/src/scenario.js +++ b/test/end-to-end-tests/src/scenario.js @@ -14,8 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ - -const {range} = require('./util'); +const { range } = require('./util'); const signup = require('./usecases/signup'); const toastScenarios = require('./scenarios/toast'); const roomDirectoryScenarios = require('./scenarios/directory'); diff --git a/test/end-to-end-tests/src/scenarios/directory.js b/test/end-to-end-tests/src/scenarios/directory.js index b5be9ed4f4..53b790c174 100644 --- a/test/end-to-end-tests/src/scenarios/directory.js +++ b/test/end-to-end-tests/src/scenarios/directory.js @@ -15,23 +15,22 @@ See the License for the specific language governing permissions and limitations under the License. */ - const join = require('../usecases/join'); const sendMessage = require('../usecases/send-message'); -const {receiveMessage} = require('../usecases/timeline'); -const {createRoom} = require('../usecases/create-room'); -const {changeRoomSettings} = require('../usecases/room-settings'); +const { receiveMessage } = require('../usecases/timeline'); +const { createRoom } = require('../usecases/create-room'); +const { changeRoomSettings } = require('../usecases/room-settings'); module.exports = async function roomDirectoryScenarios(alice, bob) { console.log(" creating a public room and join through directory:"); const room = 'test'; await createRoom(alice, room); - await changeRoomSettings(alice, {directory: true, visibility: "public_no_guests", alias: "#test"}); + await changeRoomSettings(alice, { directory: true, visibility: "public_no_guests", alias: "#test" }); await join(bob, room); //looks up room in directory const bobMessage = "hi Alice!"; await sendMessage(bob, bobMessage); - await receiveMessage(alice, {sender: "bob", body: bobMessage}); + await receiveMessage(alice, { sender: "bob", body: bobMessage }); const aliceMessage = "hi Bob, welcome!"; await sendMessage(alice, aliceMessage); - await receiveMessage(bob, {sender: "alice", body: aliceMessage}); + await receiveMessage(bob, { sender: "alice", body: aliceMessage }); }; diff --git a/test/end-to-end-tests/src/scenarios/e2e-encryption.js b/test/end-to-end-tests/src/scenarios/e2e-encryption.js index b20874fdaf..23234b85ce 100644 --- a/test/end-to-end-tests/src/scenarios/e2e-encryption.js +++ b/test/end-to-end-tests/src/scenarios/e2e-encryption.js @@ -17,19 +17,18 @@ limitations under the License. const sendMessage = require('../usecases/send-message'); const acceptInvite = require('../usecases/accept-invite'); -const {receiveMessage} = require('../usecases/timeline'); -const {createDm} = require('../usecases/create-room'); -const {checkRoomSettings} = require('../usecases/room-settings'); -const {startSasVerification, acceptSasVerification} = require('../usecases/verify'); +const { receiveMessage } = require('../usecases/timeline'); +const { createDm } = require('../usecases/create-room'); +const { checkRoomSettings } = require('../usecases/room-settings'); +const { startSasVerification, acceptSasVerification } = require('../usecases/verify'); const { setupSecureBackup } = require('../usecases/security'); const assert = require('assert'); const { measureStart, measureStop } = require('../util'); - module.exports = async function e2eEncryptionScenarios(alice, bob) { console.log(" creating an e2e encrypted DM and join through invite:"); await createDm(bob, ['@alice:localhost']); - await checkRoomSettings(bob, {encryption: true}); // for sanity, should be e2e-by-default + await checkRoomSettings(bob, { encryption: true }); // for sanity, should be e2e-by-default await acceptInvite(alice, 'bob'); // do sas verifcation bob.log.step(`starts SAS verification with ${alice.username}`); @@ -44,9 +43,9 @@ module.exports = async function e2eEncryptionScenarios(alice, bob) { bob.log.done(`done (match for ${bobSas.join(", ")})`); const aliceMessage = "Guess what I just heard?!"; await sendMessage(alice, aliceMessage); - await receiveMessage(bob, {sender: "alice", body: aliceMessage, encrypted: true}); + await receiveMessage(bob, { sender: "alice", body: aliceMessage, encrypted: true }); const bobMessage = "You've got to tell me!"; await sendMessage(bob, bobMessage); - await receiveMessage(alice, {sender: "bob", body: bobMessage, encrypted: true}); + await receiveMessage(alice, { sender: "bob", body: bobMessage, encrypted: true }); await setupSecureBackup(alice); }; diff --git a/test/end-to-end-tests/src/scenarios/lazy-loading.js b/test/end-to-end-tests/src/scenarios/lazy-loading.js index 6d321dc737..1b5d449af9 100644 --- a/test/end-to-end-tests/src/scenarios/lazy-loading.js +++ b/test/end-to-end-tests/src/scenarios/lazy-loading.js @@ -15,17 +15,16 @@ See the License for the specific language governing permissions and limitations under the License. */ - -const {delay} = require('../util'); +const { delay } = require('../util'); const join = require('../usecases/join'); const sendMessage = require('../usecases/send-message'); const { checkTimelineContains, scrollToTimelineTop, } = require('../usecases/timeline'); -const {createRoom} = require('../usecases/create-room'); -const {getMembersInMemberlist} = require('../usecases/memberlist'); -const {changeRoomSettings} = require('../usecases/room-settings'); +const { createRoom } = require('../usecases/create-room'); +const { getMembersInMemberlist } = require('../usecases/memberlist'); +const { changeRoomSettings } = require('../usecases/room-settings'); const assert = require('assert'); module.exports = async function lazyLoadingScenarios(alice, bob, charlies) { @@ -52,7 +51,7 @@ const charlyMsg2 = "how's it going??"; async function setupRoomWithBobAliceAndCharlies(alice, bob, charlies) { await createRoom(bob, room); - await changeRoomSettings(bob, {directory: true, visibility: "public_no_guests", alias}); + await changeRoomSettings(bob, { directory: true, visibility: "public_no_guests", alias }); // wait for alias to be set by server after clicking "save" // so the charlies can join it. await bob.delay(500); diff --git a/test/end-to-end-tests/src/scenarios/toast.js b/test/end-to-end-tests/src/scenarios/toast.js index 8b23dbcabc..40b480c3fa 100644 --- a/test/end-to-end-tests/src/scenarios/toast.js +++ b/test/end-to-end-tests/src/scenarios/toast.js @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -const {assertNoToasts, acceptToast, rejectToast} = require("../usecases/toasts"); +const { assertNoToasts, acceptToast, rejectToast } = require("../usecases/toasts"); module.exports = async function toastScenarios(alice, bob) { console.log(" checking and clearing toasts:"); diff --git a/test/end-to-end-tests/src/session.js b/test/end-to-end-tests/src/session.js index 6c68929a0b..f5d20fde28 100644 --- a/test/end-to-end-tests/src/session.js +++ b/test/end-to-end-tests/src/session.js @@ -18,7 +18,7 @@ limitations under the License. const puppeteer = require('puppeteer'); const Logger = require('./logger'); const LogBuffer = require('./logbuffer'); -const {delay} = require('./util'); +const { delay } = require('./util'); const DEFAULT_TIMEOUT = 20000; @@ -112,7 +112,7 @@ module.exports = class ElementSession { async replaceInputText(input, text) { // click 3 times to select all text - await input.click({clickCount: 3}); + await input.click({ clickCount: 3 }); // waiting here solves not having selected all the text by the 3x click above, // presumably because of the Field label animation. await this.delay(300); @@ -123,7 +123,7 @@ module.exports = class ElementSession { } query(selector, timeout = DEFAULT_TIMEOUT, hidden = false) { - return this.page.waitForSelector(selector, {visible: true, timeout, hidden}); + return this.page.waitForSelector(selector, { visible: true, timeout, hidden }); } async queryAll(selector) { diff --git a/test/end-to-end-tests/src/usecases/accept-invite.js b/test/end-to-end-tests/src/usecases/accept-invite.js index d7c024ac4b..50d685dc74 100644 --- a/test/end-to-end-tests/src/usecases/accept-invite.js +++ b/test/end-to-end-tests/src/usecases/accept-invite.js @@ -15,7 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -const {findSublist} = require("./create-room"); +const { findSublist } = require("./create-room"); module.exports = async function acceptInvite(session, name) { session.log.step(`accepts "${name}" invite`); @@ -23,9 +23,9 @@ module.exports = async function acceptInvite(session, name) { const invitesHandles = await inviteSublist.$$(".mx_RoomTile_name"); const invitesWithText = await Promise.all(invitesHandles.map(async (inviteHandle) => { const text = await session.innerText(inviteHandle); - return {inviteHandle, text}; + return { inviteHandle, text }; })); - const inviteHandle = invitesWithText.find(({inviteHandle, text}) => { + const inviteHandle = invitesWithText.find(({ inviteHandle, text }) => { return text.trim() === name; }).inviteHandle; diff --git a/test/end-to-end-tests/src/usecases/create-room.js b/test/end-to-end-tests/src/usecases/create-room.js index 36b9ed21ec..b644ad0309 100644 --- a/test/end-to-end-tests/src/usecases/create-room.js +++ b/test/end-to-end-tests/src/usecases/create-room.js @@ -84,4 +84,4 @@ async function createDm(session, invitees) { await measureStop(session, "mx_CreateDM"); } -module.exports = {openRoomDirectory, findSublist, createRoom, createDm}; +module.exports = { openRoomDirectory, findSublist, createRoom, createDm }; diff --git a/test/end-to-end-tests/src/usecases/join.js b/test/end-to-end-tests/src/usecases/join.js index cf0f67be44..1dff5fc45b 100644 --- a/test/end-to-end-tests/src/usecases/join.js +++ b/test/end-to-end-tests/src/usecases/join.js @@ -15,10 +15,9 @@ See the License for the specific language governing permissions and limitations under the License. */ -const {openRoomDirectory} = require('./create-room'); +const { openRoomDirectory } = require('./create-room'); const { measureStart, measureStop } = require('../util'); - module.exports = async function join(session, roomName) { session.log.step(`joins room "${roomName}"`); await measureStart(session, "mx_JoinRoom"); diff --git a/test/end-to-end-tests/src/usecases/memberlist.js b/test/end-to-end-tests/src/usecases/memberlist.js index ed7f0e389b..26c0c39755 100644 --- a/test/end-to-end-tests/src/usecases/memberlist.js +++ b/test/end-to-end-tests/src/usecases/memberlist.js @@ -16,7 +16,7 @@ limitations under the License. */ const assert = require('assert'); -const {openRoomSummaryCard} = require("./rightpanel"); +const { openRoomSummaryCard } = require("./rightpanel"); async function openMemberInfo(session, name) { const membersAndNames = await getMembersInMemberlist(session); @@ -49,7 +49,6 @@ module.exports.verifyDeviceForUser = async function(session, name, expectedDevic const sasLabels = await Promise.all(sasLabelElements.map(e => session.innerText(e))); console.log("my sas labels", sasLabels); - const dialogCodeFields = await session.queryAll(".mx_QuestionDialog code"); assert.equal(dialogCodeFields.length, 2); const deviceId = await session.innerText(dialogCodeFields[0]); @@ -71,7 +70,7 @@ async function getMembersInMemberlist(session) { const memberNameElements = await session.queryAll(".mx_MemberList .mx_EntityTile_name"); return Promise.all(memberNameElements.map(async (el) => { - return {label: el, displayName: await session.innerText(el)}; + return { label: el, displayName: await session.innerText(el) }; })); } diff --git a/test/end-to-end-tests/src/usecases/rightpanel.js b/test/end-to-end-tests/src/usecases/rightpanel.js index ae6bb2c771..00a8cde5a6 100644 --- a/test/end-to-end-tests/src/usecases/rightpanel.js +++ b/test/end-to-end-tests/src/usecases/rightpanel.js @@ -32,7 +32,11 @@ module.exports.goBackToRoomSummaryCard = async function(session) { // Sometimes our tests have this opened to MemberInfo await backButton.click(); } catch (e) { - break; // stop trying to go further back + // explicitly check for TimeoutError as this sometimes returned + // `Error: Node is detached from document` due to a re-render race or similar + if (e.name === "TimeoutError") { + break; // stop trying to go further back + } } } }; diff --git a/test/end-to-end-tests/src/usecases/room-settings.js b/test/end-to-end-tests/src/usecases/room-settings.js index 654c461296..b40afe76bf 100644 --- a/test/end-to-end-tests/src/usecases/room-settings.js +++ b/test/end-to-end-tests/src/usecases/room-settings.js @@ -16,8 +16,8 @@ limitations under the License. */ const assert = require('assert'); -const {openRoomSummaryCard} = require("./rightpanel"); -const {acceptDialog} = require('./dialog'); +const { openRoomSummaryCard } = require("./rightpanel"); +const { acceptDialog } = require('./dialog'); async function setSettingsToggle(session, toggle, enabled) { const className = await session.getElementProperty(toggle, "className"); @@ -57,13 +57,13 @@ async function findTabs(session) { const tabLabels = await Promise.all(tabButtons.map(t => session.innerText(t))); const securityTabButton = tabButtons[tabLabels.findIndex(l => l.toLowerCase().includes("security"))]; - return {securityTabButton}; + return { securityTabButton }; } async function checkRoomSettings(session, expectedSettings) { session.log.startGroup(`checks the room settings`); - const {securityTabButton} = await findTabs(session); + const { securityTabButton } = await findTabs(session); const generalSwitches = await session.queryAll(".mx_RoomSettingsDialog .mx_ToggleSwitch"); const isDirectory = generalSwitches[0]; @@ -129,7 +129,7 @@ async function checkRoomSettings(session, expectedSettings) { async function changeRoomSettings(session, settings) { session.log.startGroup(`changes the room settings`); - const {securityTabButton} = await findTabs(session); + const { securityTabButton } = await findTabs(session); const generalSwitches = await session.queryAll(".mx_RoomSettingsDialog .mx_ToggleSwitch"); const isDirectory = generalSwitches[0]; @@ -188,4 +188,4 @@ async function changeRoomSettings(session, settings) { session.log.endGroup(); } -module.exports = {checkRoomSettings, changeRoomSettings}; +module.exports = { checkRoomSettings, changeRoomSettings }; diff --git a/test/end-to-end-tests/src/usecases/settings.js b/test/end-to-end-tests/src/usecases/settings.js index 52e4bb7e0a..509e0b4a07 100644 --- a/test/end-to-end-tests/src/usecases/settings.js +++ b/test/end-to-end-tests/src/usecases/settings.js @@ -51,5 +51,5 @@ module.exports.getE2EDeviceFromSettings = async function(session) { const closeButton = await session.query(".mx_UserSettingsDialog .mx_Dialog_cancelButton"); await closeButton.click(); session.log.done(); - return {id, key}; + return { id, key }; }; diff --git a/test/end-to-end-tests/src/usecases/timeline.js b/test/end-to-end-tests/src/usecases/timeline.js index 01dc618571..f9d7300ff1 100644 --- a/test/end-to-end-tests/src/usecases/timeline.js +++ b/test/end-to-end-tests/src/usecases/timeline.js @@ -69,7 +69,6 @@ module.exports.receiveMessage = async function(session, expectedMessage) { session.log.done(); }; - module.exports.checkTimelineContains = async function(session, expectedMessages, sendersDescription) { session.log.step(`checks timeline contains ${expectedMessages.length} ` + `given messages${sendersDescription ? ` from ${sendersDescription}`:""}`); diff --git a/test/end-to-end-tests/src/usecases/toasts.js b/test/end-to-end-tests/src/usecases/toasts.js index d739f3b4ea..8650ff1400 100644 --- a/test/end-to-end-tests/src/usecases/toasts.js +++ b/test/end-to-end-tests/src/usecases/toasts.js @@ -44,4 +44,4 @@ async function rejectToast(session, expectedTitle) { await btn.click(); } -module.exports = {assertNoToasts, assertToast, acceptToast, rejectToast}; +module.exports = { assertNoToasts, assertToast, acceptToast, rejectToast }; diff --git a/test/end-to-end-tests/src/usecases/verify.js b/test/end-to-end-tests/src/usecases/verify.js index a66c8c1b1c..a1f600833d 100644 --- a/test/end-to-end-tests/src/usecases/verify.js +++ b/test/end-to-end-tests/src/usecases/verify.js @@ -16,7 +16,7 @@ limitations under the License. */ const assert = require('assert'); -const {openMemberInfo} = require("./memberlist"); +const { openMemberInfo } = require("./memberlist"); async function startVerification(session, name) { session.log.step("opens their opponent's profile and starts verification"); diff --git a/test/end-to-end-tests/start.js b/test/end-to-end-tests/start.js index 04df0c51c0..f65d6137f4 100644 --- a/test/end-to-end-tests/start.js +++ b/test/end-to-end-tests/start.js @@ -133,7 +133,7 @@ async function writeLogs(sessions, dir) { fs.writeFileSync(appHtmlName, documentHtml); fs.writeFileSync(networkLogName, session.networkLogs()); fs.writeFileSync(consoleLogName, session.consoleLogs()); - await session.page.screenshot({path: `${userLogDir}/screenshot.png`}); + await session.page.screenshot({ path: `${userLogDir}/screenshot.png` }); } return logs; } diff --git a/test/notifications/ContentRules-test.js b/test/notifications/ContentRules-test.js index ca25edf5b1..9c21c05da7 100644 --- a/test/notifications/ContentRules-test.js +++ b/test/notifications/ContentRules-test.js @@ -52,13 +52,12 @@ const USERNAME_RULE = { rule_id: ".m.rule.contains_user_name", }; - describe("ContentRules", function() { describe("parseContentRules", function() { it("should handle there being no keyword rules", function() { const rules = { 'global': { 'content': [ USERNAME_RULE, - ]}}; + ] } }; const parsed = ContentRules.parseContentRules(rules); expect(parsed.rules).toEqual([]); expect(parsed.vectorState).toEqual(PushRuleVectorState.ON); @@ -69,7 +68,7 @@ describe("ContentRules", function() { const rules = { 'global': { 'content': [ NORMAL_RULE, USERNAME_RULE, - ]}}; + ] } }; const parsed = ContentRules.parseContentRules(rules); expect(parsed.rules.length).toEqual(1); @@ -82,7 +81,7 @@ describe("ContentRules", function() { const rules = { 'global': { 'content': [ LOUD_RULE, USERNAME_RULE, - ]}}; + ] } }; const parsed = ContentRules.parseContentRules(rules); expect(parsed.rules.length).toEqual(1); @@ -96,7 +95,7 @@ describe("ContentRules", function() { LOUD_RULE, NORMAL_RULE, USERNAME_RULE, - ]}}; + ] } }; const parsed = ContentRules.parseContentRules(rules); expect(parsed.rules.length).toEqual(1); diff --git a/test/skinned-sdk.js b/test/skinned-sdk.js index 876a188cc0..9de13d20a1 100644 --- a/test/skinned-sdk.js +++ b/test/skinned-sdk.js @@ -18,12 +18,12 @@ components['structures.RightPanel'] = stubComponent(); components['structures.RoomDirectory'] = stubComponent(); components['views.globals.GuestWarningBar'] = stubComponent(); components['views.globals.NewVersionBar'] = stubComponent(); -components['views.elements.Spinner'] = stubComponent({displayName: 'Spinner'}); -components['views.messages.DateSeparator'] = stubComponent({displayName: 'DateSeparator'}); -components['views.messages.MessageTimestamp'] = stubComponent({displayName: 'MessageTimestamp'}); -components['views.messages.SenderProfile'] = stubComponent({displayName: 'SenderProfile'}); +components['views.elements.Spinner'] = stubComponent({ displayName: 'Spinner' }); +components['views.messages.DateSeparator'] = stubComponent({ displayName: 'DateSeparator' }); +components['views.messages.MessageTimestamp'] = stubComponent({ displayName: 'MessageTimestamp' }); +components['views.messages.SenderProfile'] = stubComponent({ displayName: 'SenderProfile' }); components['views.rooms.SearchBar'] = stubComponent(); -sdk.loadSkin({components}); +sdk.loadSkin({ components }); export default sdk; diff --git a/test/stores/RoomViewStore-test.js b/test/stores/RoomViewStore-test.js index 41252103e7..cb5d7d21f0 100644 --- a/test/stores/RoomViewStore-test.js +++ b/test/stores/RoomViewStore-test.js @@ -1,6 +1,6 @@ import RoomViewStore from '../../src/stores/RoomViewStore'; -import {MatrixClientPeg as peg} from '../../src/MatrixClientPeg'; +import { MatrixClientPeg as peg } from '../../src/MatrixClientPeg'; import * as testUtils from '../test-utils'; @@ -36,7 +36,7 @@ describe('RoomViewStore', function() { } }); - peg.get().getRoomIdForAlias.mockResolvedValue({room_id: "!randomcharacters:aser.ver"}); + peg.get().getRoomIdForAlias.mockResolvedValue({ room_id: "!randomcharacters:aser.ver" }); peg.get().joinRoom = async (roomAddress) => { token.remove(); // stop RVS listener expect(roomAddress).toBe("#somealias2:aser.ver"); diff --git a/test/test-utils.js b/test/test-utils.js index e4c051cce2..ad56522965 100644 --- a/test/test-utils.js +++ b/test/test-utils.js @@ -1,11 +1,11 @@ import React from 'react'; -import {MatrixClientPeg as peg} from '../src/MatrixClientPeg'; +import { MatrixClientPeg as peg } from '../src/MatrixClientPeg'; import dis from '../src/dispatcher/dispatcher'; -import {makeType} from "../src/utils/TypeUtils"; -import {ValidatedServerConfig} from "../src/utils/AutoDiscoveryUtils"; +import { makeType } from "../src/utils/TypeUtils"; +import { ValidatedServerConfig } from "../src/utils/AutoDiscoveryUtils"; import ShallowRenderer from 'react-test-renderer/shallow'; import MatrixClientContext from "../src/contexts/MatrixClientContext"; -import {MatrixEvent} from "matrix-js-sdk/src/models/event"; +import { MatrixEvent } from "matrix-js-sdk/src/models/event"; export function getRenderer() { // Old: ReactTestUtils.createRenderer(); diff --git a/test/utils/MegolmExportEncryption-test.js b/test/utils/MegolmExportEncryption-test.js index 07ec03860b..39ffed25f1 100644 --- a/test/utils/MegolmExportEncryption-test.js +++ b/test/utils/MegolmExportEncryption-test.js @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import {TextEncoder} from "util"; +import { TextEncoder } from "util"; import nodeCrypto from "crypto"; import { Crypto } from "@peculiar/webcrypto"; @@ -144,7 +144,7 @@ cissyYBxjsfsAn const password = 'my super secret passphrase'; return MegolmExportEncryption.encryptMegolmKeyFile( - input, password, {kdf_rounds: 1000}, + input, password, { kdf_rounds: 1000 }, ).then((ciphertext) => { return MegolmExportEncryption.decryptMegolmKeyFile( ciphertext, password, diff --git a/test/utils/ShieldUtils-test.js b/test/utils/ShieldUtils-test.js index fdf4f527ee..b70031dc21 100644 --- a/test/utils/ShieldUtils-test.js +++ b/test/utils/ShieldUtils-test.js @@ -54,7 +54,7 @@ describe("shieldStatusForMembership self-trust behaviour", function() { const client = mkClient(trusted); const room = { roomId: dm ? "DM" : "other", - getEncryptionTargetMembers: () => ["@self:localhost", "@FF1:h", "@FF2:h"].map((userId) => ({userId})), + getEncryptionTargetMembers: () => ["@self:localhost", "@FF1:h", "@FF2:h"].map((userId) => ({ userId })), }; const status = await shieldStatusForRoom(client, room); expect(status).toEqual("normal"); @@ -67,7 +67,7 @@ describe("shieldStatusForMembership self-trust behaviour", function() { const client = mkClient(trusted); const room = { roomId: dm ? "DM" : "other", - getEncryptionTargetMembers: () => ["@self:localhost", "@TT1:h", "@TT2:h"].map((userId) => ({userId})), + getEncryptionTargetMembers: () => ["@self:localhost", "@TT1:h", "@TT2:h"].map((userId) => ({ userId })), }; const status = await shieldStatusForRoom(client, room); expect(status).toEqual(result); @@ -80,7 +80,7 @@ describe("shieldStatusForMembership self-trust behaviour", function() { const client = mkClient(trusted); const room = { roomId: dm ? "DM" : "other", - getEncryptionTargetMembers: () => ["@self:localhost", "@TT1:h", "@FF2:h"].map((userId) => ({userId})), + getEncryptionTargetMembers: () => ["@self:localhost", "@TT1:h", "@FF2:h"].map((userId) => ({ userId })), }; const status = await shieldStatusForRoom(client, room); expect(status).toEqual(result); @@ -93,7 +93,7 @@ describe("shieldStatusForMembership self-trust behaviour", function() { const client = mkClient(trusted); const room = { roomId: dm ? "DM" : "other", - getEncryptionTargetMembers: () => ["@self:localhost"].map((userId) => ({userId})), + getEncryptionTargetMembers: () => ["@self:localhost"].map((userId) => ({ userId })), }; const status = await shieldStatusForRoom(client, room); expect(status).toEqual(result); @@ -106,7 +106,7 @@ describe("shieldStatusForMembership self-trust behaviour", function() { const client = mkClient(trusted); const room = { roomId: dm ? "DM" : "other", - getEncryptionTargetMembers: () => ["@self:localhost", "@TT:h"].map((userId) => ({userId})), + getEncryptionTargetMembers: () => ["@self:localhost", "@TT:h"].map((userId) => ({ userId })), }; const status = await shieldStatusForRoom(client, room); expect(status).toEqual(result); @@ -119,7 +119,7 @@ describe("shieldStatusForMembership self-trust behaviour", function() { const client = mkClient(trusted); const room = { roomId: dm ? "DM" : "other", - getEncryptionTargetMembers: () => ["@self:localhost", "@FF:h"].map((userId) => ({userId})), + getEncryptionTargetMembers: () => ["@self:localhost", "@FF:h"].map((userId) => ({ userId })), }; const status = await shieldStatusForRoom(client, room); expect(status).toEqual(result); @@ -139,7 +139,7 @@ describe("shieldStatusForMembership other-trust behaviour", function() { const client = mkClient(true); const room = { roomId: dm ? "DM" : "other", - getEncryptionTargetMembers: () => ["@self:localhost", "@TF:h"].map((userId) => ({userId})), + getEncryptionTargetMembers: () => ["@self:localhost", "@TF:h"].map((userId) => ({ userId })), }; const status = await shieldStatusForRoom(client, room); expect(status).toEqual(result); @@ -151,7 +151,7 @@ describe("shieldStatusForMembership other-trust behaviour", function() { const client = mkClient(true); const room = { roomId: dm ? "DM" : "other", - getEncryptionTargetMembers: () => ["@self:localhost", "@TF:h", "@TT:h"].map((userId) => ({userId})), + getEncryptionTargetMembers: () => ["@self:localhost", "@TF:h", "@TT:h"].map((userId) => ({ userId })), }; const status = await shieldStatusForRoom(client, room); expect(status).toEqual(result); @@ -163,7 +163,7 @@ describe("shieldStatusForMembership other-trust behaviour", function() { const client = mkClient(true); const room = { roomId: dm ? "DM" : "other", - getEncryptionTargetMembers: () => ["@self:localhost", "@FF:h", "@FT:h"].map((userId) => ({userId})), + getEncryptionTargetMembers: () => ["@self:localhost", "@FF:h", "@FT:h"].map((userId) => ({ userId })), }; const status = await shieldStatusForRoom(client, room); expect(status).toEqual(result); @@ -175,7 +175,7 @@ describe("shieldStatusForMembership other-trust behaviour", function() { const client = mkClient(true); const room = { roomId: dm ? "DM" : "other", - getEncryptionTargetMembers: () => ["@self:localhost", "@WF:h", "@FT:h"].map((userId) => ({userId})), + getEncryptionTargetMembers: () => ["@self:localhost", "@WF:h", "@FT:h"].map((userId) => ({ userId })), }; const status = await shieldStatusForRoom(client, room); expect(status).toEqual(result); diff --git a/test/utils/Singleflight-test.ts b/test/utils/Singleflight-test.ts index 80258701bb..148388dc71 100644 --- a/test/utils/Singleflight-test.ts +++ b/test/utils/Singleflight-test.ts @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import {Singleflight} from "../../src/utils/Singleflight"; +import { Singleflight } from "../../src/utils/Singleflight"; describe('Singleflight', () => { afterEach(() => { diff --git a/test/utils/arrays-test.ts b/test/utils/arrays-test.ts index 5974915965..cf9a5f0089 100644 --- a/test/utils/arrays-test.ts +++ b/test/utils/arrays-test.ts @@ -29,7 +29,7 @@ import { ArrayUtil, GroupedArray, } from "../../src/utils/arrays"; -import {objectFromEntries} from "../../src/utils/objects"; +import { objectFromEntries } from "../../src/utils/objects"; function expectSample(i: number, input: number[], expected: number[], smooth = false) { console.log(`Resample case index: ${i}`); // for debugging test failures @@ -43,26 +43,26 @@ describe('arrays', () => { describe('arrayFastResample', () => { it('should downsample', () => { [ - {input: [1, 2, 3, 4, 5], output: [1, 4]}, // Odd -> Even - {input: [1, 2, 3, 4, 5], output: [1, 3, 5]}, // Odd -> Odd - {input: [1, 2, 3, 4], output: [1, 2, 3]}, // Even -> Odd - {input: [1, 2, 3, 4], output: [1, 3]}, // Even -> Even + { input: [1, 2, 3, 4, 5], output: [1, 4] }, // Odd -> Even + { input: [1, 2, 3, 4, 5], output: [1, 3, 5] }, // Odd -> Odd + { input: [1, 2, 3, 4], output: [1, 2, 3] }, // Even -> Odd + { input: [1, 2, 3, 4], output: [1, 3] }, // Even -> Even ].forEach((c, i) => expectSample(i, c.input, c.output)); }); it('should upsample', () => { [ - {input: [1, 2, 3], output: [1, 1, 2, 2, 3, 3]}, // Odd -> Even - {input: [1, 2, 3], output: [1, 1, 2, 2, 3]}, // Odd -> Odd - {input: [1, 2], output: [1, 1, 1, 2, 2]}, // Even -> Odd - {input: [1, 2], output: [1, 1, 1, 2, 2, 2]}, // Even -> Even + { input: [1, 2, 3], output: [1, 1, 2, 2, 3, 3] }, // Odd -> Even + { input: [1, 2, 3], output: [1, 1, 2, 2, 3] }, // Odd -> Odd + { input: [1, 2], output: [1, 1, 1, 2, 2] }, // Even -> Odd + { input: [1, 2], output: [1, 1, 1, 2, 2, 2] }, // Even -> Even ].forEach((c, i) => expectSample(i, c.input, c.output)); }); it('should maintain sample', () => { [ - {input: [1, 2, 3], output: [1, 2, 3]}, // Odd - {input: [1, 2], output: [1, 2]}, // Even + { input: [1, 2, 3], output: [1, 2, 3] }, // Odd + { input: [1, 2], output: [1, 2] }, // Even ].forEach((c, i) => expectSample(i, c.input, c.output)); }); }); @@ -73,26 +73,26 @@ describe('arrays', () => { // we'd be feeding a thousand values in and seeing what a curve of 250 values looks like, // but that's not really feasible to manually verify accuracy. [ - {input: [4, 4, 1, 4, 4, 1, 4, 4, 1], output: [3, 3, 3, 3]}, // Odd -> Even - {input: [4, 4, 1, 4, 4, 1, 4, 4, 1], output: [3, 3, 3]}, // Odd -> Odd - {input: [4, 4, 1, 4, 4, 1, 4, 4], output: [3, 3, 3]}, // Even -> Odd - {input: [4, 4, 1, 4, 4, 1, 4, 4], output: [3, 3]}, // Even -> Even + { input: [4, 4, 1, 4, 4, 1, 4, 4, 1], output: [3, 3, 3, 3] }, // Odd -> Even + { input: [4, 4, 1, 4, 4, 1, 4, 4, 1], output: [3, 3, 3] }, // Odd -> Odd + { input: [4, 4, 1, 4, 4, 1, 4, 4], output: [3, 3, 3] }, // Even -> Odd + { input: [4, 4, 1, 4, 4, 1, 4, 4], output: [3, 3] }, // Even -> Even ].forEach((c, i) => expectSample(i, c.input, c.output, true)); }); it('should upsample', () => { [ - {input: [2, 0, 2], output: [2, 2, 0, 0, 2, 2]}, // Odd -> Even - {input: [2, 0, 2], output: [2, 2, 0, 0, 2]}, // Odd -> Odd - {input: [2, 0], output: [2, 2, 2, 0, 0]}, // Even -> Odd - {input: [2, 0], output: [2, 2, 2, 0, 0, 0]}, // Even -> Even + { input: [2, 0, 2], output: [2, 2, 0, 0, 2, 2] }, // Odd -> Even + { input: [2, 0, 2], output: [2, 2, 0, 0, 2] }, // Odd -> Odd + { input: [2, 0], output: [2, 2, 2, 0, 0] }, // Even -> Odd + { input: [2, 0], output: [2, 2, 2, 0, 0, 0] }, // Even -> Even ].forEach((c, i) => expectSample(i, c.input, c.output, true)); }); it('should maintain sample', () => { [ - {input: [2, 0, 2], output: [2, 0, 2]}, // Odd - {input: [2, 0], output: [2, 0]}, // Even + { input: [2, 0, 2], output: [2, 0, 2] }, // Odd + { input: [2, 0], output: [2, 0] }, // Even ].forEach((c, i) => expectSample(i, c.input, c.output, true)); }); }); diff --git a/test/utils/enums-test.ts b/test/utils/enums-test.ts index 423b135f77..e1d34ee688 100644 --- a/test/utils/enums-test.ts +++ b/test/utils/enums-test.ts @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import {getEnumValues, isEnumValue} from "../../src/utils/enums"; +import { getEnumValues, isEnumValue } from "../../src/utils/enums"; enum TestStringEnum { First = "__first__", diff --git a/test/utils/iterables-test.ts b/test/utils/iterables-test.ts index 9b30b6241c..5c1e2241f4 100644 --- a/test/utils/iterables-test.ts +++ b/test/utils/iterables-test.ts @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import {iterableDiff, iterableUnion} from "../../src/utils/iterables"; +import { iterableDiff, iterableUnion } from "../../src/utils/iterables"; describe('iterables', () => { describe('iterableUnion', () => { diff --git a/test/utils/maps-test.ts b/test/utils/maps-test.ts index 8764a8f2cf..097f3ef9c9 100644 --- a/test/utils/maps-test.ts +++ b/test/utils/maps-test.ts @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import {EnhancedMap, mapDiff, mapKeyChanges} from "../../src/utils/maps"; +import { EnhancedMap, mapDiff, mapKeyChanges } from "../../src/utils/maps"; describe('maps', () => { describe('mapDiff', () => { @@ -187,7 +187,7 @@ describe('maps', () => { }); it('should use the provided entries', () => { - const obj = {a: 1, b: 2}; + const obj = { a: 1, b: 2 }; const result = new EnhancedMap(Object.entries(obj)); expect(result.size).toBe(2); expect(result.get('a')).toBe(1); diff --git a/test/utils/numbers-test.ts b/test/utils/numbers-test.ts index 36e7d4f7e7..340ffe3302 100644 --- a/test/utils/numbers-test.ts +++ b/test/utils/numbers-test.ts @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import {clamp, defaultNumber, percentageOf, percentageWithin, sum} from "../../src/utils/numbers"; +import { clamp, defaultNumber, percentageOf, percentageWithin, sum } from "../../src/utils/numbers"; describe('numbers', () => { describe('defaultNumber', () => { diff --git a/test/utils/objects-test.ts b/test/utils/objects-test.ts index b7a80e6761..154fa3604f 100644 --- a/test/utils/objects-test.ts +++ b/test/utils/objects-test.ts @@ -28,8 +28,8 @@ import { describe('objects', () => { describe('objectExcluding', () => { it('should exclude the given properties', () => { - const input = {hello: "world", test: true}; - const output = {hello: "world"}; + const input = { hello: "world", test: true }; + const output = { hello: "world" }; const props = ["test", "doesnotexist"]; // we also make sure it doesn't explode on missing props const result = objectExcluding(input, props); // any is to test the missing prop expect(result).toBeDefined(); @@ -39,8 +39,8 @@ describe('objects', () => { describe('objectWithOnly', () => { it('should exclusively use the given properties', () => { - const input = {hello: "world", test: true}; - const output = {hello: "world"}; + const input = { hello: "world", test: true }; + const output = { hello: "world" }; const props = ["hello", "doesnotexist"]; // we also make sure it doesn't explode on missing props const result = objectWithOnly(input, props); // any is to test the missing prop expect(result).toBeDefined(); @@ -50,7 +50,7 @@ describe('objects', () => { describe('objectShallowClone', () => { it('should create a new object', () => { - const input = {test: 1}; + const input = { test: 1 }; const result = objectShallowClone(input); expect(result).toBeDefined(); expect(result).not.toBe(input); @@ -58,7 +58,7 @@ describe('objects', () => { }); it('should only clone the top level properties', () => { - const input = {a: 1, b: {c: 2}}; + const input = { a: 1, b: { c: 2 } }; const result = objectShallowClone(input); expect(result).toBeDefined(); expect(result).toMatchObject(input); @@ -66,8 +66,8 @@ describe('objects', () => { }); it('should support custom clone functions', () => { - const input = {a: 1, b: 2}; - const output = {a: 4, b: 8}; + const input = { a: 1, b: 2 }; + const output = { a: 4, b: 8 }; const result = objectShallowClone(input, (k, v) => { // XXX: inverted expectation for ease of assertion expect(Object.keys(input)).toContain(k); @@ -87,29 +87,29 @@ describe('objects', () => { }); it('should return true if keys for A > keys for B', () => { - const a = {a: 1, b: 2}; - const b = {a: 1}; + const a = { a: 1, b: 2 }; + const b = { a: 1 }; const result = objectHasDiff(a, b); expect(result).toBe(true); }); it('should return true if keys for A < keys for B', () => { - const a = {a: 1}; - const b = {a: 1, b: 2}; + const a = { a: 1 }; + const b = { a: 1, b: 2 }; const result = objectHasDiff(a, b); expect(result).toBe(true); }); it('should return false if the objects are the same but different pointers', () => { - const a = {a: 1, b: 2}; - const b = {a: 1, b: 2}; + const a = { a: 1, b: 2 }; + const b = { a: 1, b: 2 }; const result = objectHasDiff(a, b); expect(result).toBe(false); }); it('should consider pointers when testing values', () => { - const a = {a: {}, b: 2}; // `{}` is shorthand for `new Object()` - const b = {a: {}, b: 2}; + const a = { a: {}, b: 2 }; // `{}` is shorthand for `new Object()` + const b = { a: {}, b: 2 }; const result = objectHasDiff(a, b); expect(result).toBe(true); // even though the keys are the same, the value pointers vary }); @@ -117,8 +117,8 @@ describe('objects', () => { describe('objectDiff', () => { it('should return empty sets for the same object', () => { - const a = {a: 1, b: 2}; - const b = {a: 1, b: 2}; + const a = { a: 1, b: 2 }; + const b = { a: 1, b: 2 }; const result = objectDiff(a, b); expect(result).toBeDefined(); expect(result.changed).toBeDefined(); @@ -130,7 +130,7 @@ describe('objects', () => { }); it('should return empty sets for the same object pointer', () => { - const a = {a: 1, b: 2}; + const a = { a: 1, b: 2 }; const result = objectDiff(a, a); expect(result).toBeDefined(); expect(result.changed).toBeDefined(); @@ -142,8 +142,8 @@ describe('objects', () => { }); it('should indicate when property changes are made', () => { - const a = {a: 1, b: 2}; - const b = {a: 11, b: 2}; + const a = { a: 1, b: 2 }; + const b = { a: 11, b: 2 }; const result = objectDiff(a, b); expect(result.changed).toBeDefined(); expect(result.added).toBeDefined(); @@ -155,8 +155,8 @@ describe('objects', () => { }); it('should indicate when properties are added', () => { - const a = {a: 1, b: 2}; - const b = {a: 1, b: 2, c: 3}; + const a = { a: 1, b: 2 }; + const b = { a: 1, b: 2, c: 3 }; const result = objectDiff(a, b); expect(result.changed).toBeDefined(); expect(result.added).toBeDefined(); @@ -168,8 +168,8 @@ describe('objects', () => { }); it('should indicate when properties are removed', () => { - const a = {a: 1, b: 2}; - const b = {a: 1}; + const a = { a: 1, b: 2 }; + const b = { a: 1 }; const result = objectDiff(a, b); expect(result.changed).toBeDefined(); expect(result.added).toBeDefined(); @@ -181,8 +181,8 @@ describe('objects', () => { }); it('should indicate when multiple aspects change', () => { - const a = {a: 1, b: 2, c: 3}; - const b: (typeof a | {d: number}) = {a: 1, b: 22, d: 4}; + const a = { a: 1, b: 2, c: 3 }; + const b: (typeof a | {d: number}) = { a: 1, b: 22, d: 4 }; const result = objectDiff(a, b); expect(result.changed).toBeDefined(); expect(result.added).toBeDefined(); @@ -198,23 +198,23 @@ describe('objects', () => { describe('objectKeyChanges', () => { it('should return an empty set if no properties changed', () => { - const a = {a: 1, b: 2}; - const b = {a: 1, b: 2}; + const a = { a: 1, b: 2 }; + const b = { a: 1, b: 2 }; const result = objectKeyChanges(a, b); expect(result).toBeDefined(); expect(result).toHaveLength(0); }); it('should return an empty set if no properties changed for the same pointer', () => { - const a = {a: 1, b: 2}; + const a = { a: 1, b: 2 }; const result = objectKeyChanges(a, a); expect(result).toBeDefined(); expect(result).toHaveLength(0); }); it('should return properties which were changed, added, or removed', () => { - const a = {a: 1, b: 2, c: 3}; - const b: (typeof a | {d: number}) = {a: 1, b: 22, d: 4}; + const a = { a: 1, b: 2, c: 3 }; + const b: (typeof a | {d: number}) = { a: 1, b: 22, d: 4 }; const result = objectKeyChanges(a, b); expect(result).toBeDefined(); expect(result).toHaveLength(3); @@ -245,14 +245,14 @@ describe('objects', () => { describe('objectFromEntries', () => { it('should create an object from an array of entries', () => { - const output = {a: 1, b: 2, c: 3}; + const output = { a: 1, b: 2, c: 3 }; const result = objectFromEntries(Object.entries(output)); expect(result).toBeDefined(); expect(result).toMatchObject(output); }); it('should maintain pointers in values', () => { - const output = {a: {}, b: 2, c: 3}; + const output = { a: {}, b: 2, c: 3 }; const result = objectFromEntries(Object.entries(output)); expect(result).toBeDefined(); expect(result).toMatchObject(output); diff --git a/test/utils/permalinks/Permalinks-test.js b/test/utils/permalinks/Permalinks-test.js index 3c4982b465..41cce7f98d 100644 --- a/test/utils/permalinks/Permalinks-test.js +++ b/test/utils/permalinks/Permalinks-test.js @@ -13,7 +13,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import {MatrixClientPeg as peg} from '../../../src/MatrixClientPeg'; +import { MatrixClientPeg as peg } from '../../../src/MatrixClientPeg'; import { makeGroupPermalink, makeRoomPermalink, @@ -48,7 +48,7 @@ function mockRoom(roomId, members, serverACL) { content = serverACL; break; case "m.room.power_levels": - content = {users: powerLevelsUsers, users_default: 0}; + content = { users: powerLevelsUsers, users_default: 0 }; break; } if (content) { diff --git a/test/utils/sets-test.ts b/test/utils/sets-test.ts index 98dc218309..fec6cab0f3 100644 --- a/test/utils/sets-test.ts +++ b/test/utils/sets-test.ts @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import {setHasDiff} from "../../src/utils/sets"; +import { setHasDiff } from "../../src/utils/sets"; describe('sets', () => { describe('setHasDiff', () => { diff --git a/yarn.lock b/yarn.lock index 62f353f656..7343a3c419 100644 --- a/yarn.lock +++ b/yarn.lock @@ -26,12 +26,12 @@ dependencies: "@babel/highlight" "^7.10.4" -"@babel/code-frame@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.12.13.tgz#dcfc826beef65e75c50e21d3837d7d95798dd658" - integrity sha512-HV1Cm0Q3ZrpCR93tkWOYiuYIgLxZXZFVG2VgK+MBWjUqZTundupbfx2aXarXuw5Ko5aMcjtJgbSs4vUGBS5v6g== +"@babel/code-frame@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.14.5.tgz#23b08d740e83f49c5e59945fbf1b43e80bbf4edb" + integrity sha512-9pzDqyc6OLDaqe+zbACgFkb6fKMNG6CObKpnYXChRsvYGyEdc7CA2BaqeOM+vOtCS5ndmJicPJhKAwYRI6UfFw== dependencies: - "@babel/highlight" "^7.12.13" + "@babel/highlight" "^7.14.5" "@babel/compat-data@^7.12.5", "@babel/compat-data@^7.12.7": version "7.12.7" @@ -59,7 +59,23 @@ semver "^5.4.1" source-map "^0.5.0" -"@babel/generator@^7.12.1", "@babel/generator@^7.12.10", "@babel/generator@^7.12.11": +"@babel/eslint-parser@^7.12.10": + version "7.13.14" + resolved "https://registry.yarnpkg.com/@babel/eslint-parser/-/eslint-parser-7.13.14.tgz#f80fd23bdd839537221914cb5d17720a5ea6ba3a" + integrity sha512-I0HweR36D73Ibn/FfrRDMKlMqJHFwidIUgYdMpH+aXYuQC+waq59YaJ6t9e9N36axJ82v1jR041wwqDrDXEwRA== + dependencies: + eslint-scope "^5.1.0" + eslint-visitor-keys "^1.3.0" + semver "^6.3.0" + +"@babel/eslint-plugin@^7.12.10": + version "7.13.10" + resolved "https://registry.yarnpkg.com/@babel/eslint-plugin/-/eslint-plugin-7.13.10.tgz#6720c32d52a4fef817796c7bb55a87b80320bbe7" + integrity sha512-xsNxo099fKnJ2rArkuuMOTPxxTLZSXwbFXdH4GjqQRKTOr6S1odQlE+R3Leid56VFQ3KVAR295vVNG9fqNQVvQ== + dependencies: + eslint-rule-composer "^0.3.0" + +"@babel/generator@^7.12.10", "@babel/generator@^7.12.11": version "7.12.11" resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.12.11.tgz#98a7df7b8c358c9a37ab07a24056853016aba3af" integrity sha512-Ggg6WPOJtSi8yYQvLVjG8F/TlpWDlKx0OpS4Kt+xMQPs5OaGYWy+v1A+1TvxI6sAMGZpKWWoAQ1DaeQbImlItA== @@ -68,12 +84,12 @@ jsesc "^2.5.1" source-map "^0.5.0" -"@babel/generator@^7.13.16": - version "7.13.16" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.13.16.tgz#0befc287031a201d84cdfc173b46b320ae472d14" - integrity sha512-grBBR75UnKOcUWMp8WoDxNsWCFl//XCK6HWTrBQKTr5SV9f5g0pNOjdyzi/DTBv12S9GnYPInIXQBTky7OXEMg== +"@babel/generator@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.14.5.tgz#848d7b9f031caca9d0cd0af01b063f226f52d785" + integrity sha512-y3rlP+/G25OIX3mYKKIOlQRcqj7YgrvHxOLbVmyLJ9bPmi5ttvUmpydVjcFjZphOktWuA7ovbx91ECloWTfjIA== dependencies: - "@babel/types" "^7.13.16" + "@babel/types" "^7.14.5" jsesc "^2.5.1" source-map "^0.5.0" @@ -146,14 +162,14 @@ "@babel/template" "^7.12.7" "@babel/types" "^7.12.11" -"@babel/helper-function-name@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.12.13.tgz#93ad656db3c3c2232559fd7b2c3dbdcbe0eb377a" - integrity sha512-TZvmPn0UOqmvi5G4vvw0qZTpVptGkB1GL61R6lKvrSdIxGm5Pky7Q3fpKiIkQCAtRCBUwB0PaThlx9vebCDSwA== +"@babel/helper-function-name@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.14.5.tgz#89e2c474972f15d8e233b52ee8c480e2cfcd50c4" + integrity sha512-Gjna0AsXWfFvrAuX+VKcN/aNNWonizBj39yGwUzVDVTlMYJMK2Wp6xdpy72mfArFq5uK+NOuexfzZlzI1z9+AQ== dependencies: - "@babel/helper-get-function-arity" "^7.12.13" - "@babel/template" "^7.12.13" - "@babel/types" "^7.12.13" + "@babel/helper-get-function-arity" "^7.14.5" + "@babel/template" "^7.14.5" + "@babel/types" "^7.14.5" "@babel/helper-get-function-arity@^7.12.10": version "7.12.10" @@ -162,12 +178,12 @@ dependencies: "@babel/types" "^7.12.10" -"@babel/helper-get-function-arity@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.12.13.tgz#bc63451d403a3b3082b97e1d8b3fe5bd4091e583" - integrity sha512-DjEVzQNz5LICkzN0REdpD5prGoidvbdYk1BVgRUOINaWJP2t6avB27X1guXK1kXNrX0WMfsrm1A/ZBthYuIMQg== +"@babel/helper-get-function-arity@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.14.5.tgz#25fbfa579b0937eee1f3b805ece4ce398c431815" + integrity sha512-I1Db4Shst5lewOM4V+ZKJzQ0JGGaZ6VY1jYvMghRjqs6DWgxLCIyFt30GlnKkfUeFLpJt2vzbMVEXVSXlIFYUg== dependencies: - "@babel/types" "^7.12.13" + "@babel/types" "^7.14.5" "@babel/helper-hoist-variables@^7.10.4": version "7.10.4" @@ -176,6 +192,13 @@ dependencies: "@babel/types" "^7.10.4" +"@babel/helper-hoist-variables@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.14.5.tgz#e0dd27c33a78e577d7c8884916a3e7ef1f7c7f8d" + integrity sha512-R1PXiz31Uc0Vxy4OEOm07x0oSjKAdPPCh3tPivn/Eo8cvz6gveAeuyUUPB21Hoiif0uoPQSSdhIPS3352nvdyQ== + dependencies: + "@babel/types" "^7.14.5" + "@babel/helper-member-expression-to-functions@^7.12.1", "@babel/helper-member-expression-to-functions@^7.12.7": version "7.12.7" resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.12.7.tgz#aa77bd0396ec8114e5e30787efa78599d874a855" @@ -257,18 +280,23 @@ dependencies: "@babel/types" "^7.12.11" -"@babel/helper-split-export-declaration@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.12.13.tgz#e9430be00baf3e88b0e13e6f9d4eaf2136372b05" - integrity sha512-tCJDltF83htUtXx5NLcaDqRmknv652ZWCHyoTETf1CXYJdPC7nohZohjUgieXhv0hTJdRf2FjDueFehdNucpzg== +"@babel/helper-split-export-declaration@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.14.5.tgz#22b23a54ef51c2b7605d851930c1976dd0bc693a" + integrity sha512-hprxVPu6e5Kdp2puZUmvOGjaLv9TCe58E/Fl6hRq4YiVQxIcNvuq6uTM2r1mT/oPskuS9CgR+I94sqAYv0NGKA== dependencies: - "@babel/types" "^7.12.13" + "@babel/types" "^7.14.5" "@babel/helper-validator-identifier@^7.10.4", "@babel/helper-validator-identifier@^7.12.11": version "7.12.11" resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz#c9a1f021917dcb5ccf0d4e453e399022981fc9ed" integrity sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw== +"@babel/helper-validator-identifier@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.5.tgz#d0f0e277c512e0c938277faa85a3968c9a44c0e8" + integrity sha512-5lsetuxCLilmVGyiLEfoHBRX8UCFD+1m2x3Rj97WrW3V7H3u4RWRXA4evMjImCsin2J2YT0QaVDGf+z8ondbAg== + "@babel/helper-validator-option@^7.12.1", "@babel/helper-validator-option@^7.12.11": version "7.12.11" resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.12.11.tgz#d66cb8b7a3e7fe4c6962b32020a131ecf0847f4f" @@ -302,24 +330,24 @@ chalk "^2.0.0" js-tokens "^4.0.0" -"@babel/highlight@^7.12.13": - version "7.13.10" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.13.10.tgz#a8b2a66148f5b27d666b15d81774347a731d52d1" - integrity sha512-5aPpe5XQPzflQrFwL1/QoeHkP2MsA4JCntcXHRhEsdsfPVkvPi2w7Qix4iV7t5S/oC9OodGrggd8aco1g3SZFg== +"@babel/highlight@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.14.5.tgz#6861a52f03966405001f6aa534a01a24d99e8cd9" + integrity sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg== dependencies: - "@babel/helper-validator-identifier" "^7.12.11" + "@babel/helper-validator-identifier" "^7.14.5" chalk "^2.0.0" js-tokens "^4.0.0" -"@babel/parser@^7.1.0", "@babel/parser@^7.12.10", "@babel/parser@^7.12.11", "@babel/parser@^7.12.7", "@babel/parser@^7.7.0": +"@babel/parser@^7.1.0", "@babel/parser@^7.12.10", "@babel/parser@^7.12.11", "@babel/parser@^7.12.7": version "7.12.11" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.12.11.tgz#9ce3595bcd74bc5c466905e86c535b8b25011e79" integrity sha512-N3UxG+uuF4CMYoNj8AhnbAcJF0PiuJ9KHuy1lQmkYsxTer/MAH9UBNHsBoAX/4s6NvlDD047No8mYVGGzLL4hg== -"@babel/parser@^7.12.13", "@babel/parser@^7.13.16": - version "7.13.16" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.13.16.tgz#0f18179b0448e6939b1f3f5c4c355a3a9bcdfd37" - integrity sha512-6bAg36mCwuqLO0hbR+z7PHuqWiCeP7Dzg73OpQwsAB1Eb8HnGEz5xYBzCfbu+YjoaJsJs+qheDxVAuqbt3ILEw== +"@babel/parser@^7.13.16", "@babel/parser@^7.14.5", "@babel/parser@^7.14.7": + version "7.14.7" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.14.7.tgz#6099720c8839ca865a2637e6c85852ead0bdb595" + integrity sha512-X67Z5y+VBJuHB/RjwECp8kSl5uYi0BvRbNeWqkaJCVh+LiTPl19WBUfG627psSgp9rSf6ojuXghQM3ha6qHHdA== "@babel/plugin-proposal-async-generator-functions@^7.12.1": version "7.12.12" @@ -494,13 +522,6 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-syntax-flow@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.12.1.tgz#a77670d9abe6d63e8acadf4c31bb1eb5a506bbdd" - integrity sha512-1lBLLmtxrwpm4VKmtVFselI/P3pX+G63fAtUUt6b2Nzgao77KNDwyuRt90Mj2/9pKobtt68FdvjfqohZjg/FCA== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/plugin-syntax-import-meta@^7.8.3": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz#ee601348c370fa334d2207be158777496521fd51" @@ -659,23 +680,6 @@ "@babel/helper-builder-binary-assignment-operator-visitor" "^7.10.4" "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-flow-comments@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-flow-comments/-/plugin-transform-flow-comments-7.12.1.tgz#92fe5a27e635bd6d2e46f616094d60edff895a0b" - integrity sha512-jQd0UQUg98j95JJVQL74mOrzES7dYyd8hy+ZDiMj1wjHw1Nj0Pzkk7tKZdqqAoSZV/yTYLp0lJ0/PTozy2cNDg== - dependencies: - "@babel/generator" "^7.12.1" - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/plugin-syntax-flow" "^7.12.1" - -"@babel/plugin-transform-flow-strip-types@^7.12.1": - version "7.12.10" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.12.10.tgz#d85e30ecfa68093825773b7b857e5085bbd32c95" - integrity sha512-0ti12wLTLeUIzu9U7kjqIn4MyOL7+Wibc7avsHhj4o1l5C0ATs8p2IMHrVYjm9t9wzhfEO6S3kxax0Rpdo8LTg== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/plugin-syntax-flow" "^7.12.1" - "@babel/plugin-transform-for-of@^7.12.1": version "7.12.1" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.12.1.tgz#07640f28867ed16f9511c99c888291f560921cfa" @@ -967,14 +971,6 @@ core-js-compat "^3.8.0" semver "^5.5.0" -"@babel/preset-flow@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/preset-flow/-/preset-flow-7.12.1.tgz#1a81d376c5a9549e75352a3888f8c273455ae940" - integrity sha512-UAoyMdioAhM6H99qPoKvpHMzxmNVXno8GYU/7vZmGaHk6/KqfDYL1W0NxszVbJ2EP271b7e6Ox+Vk2A9QsB3Sw== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/plugin-transform-flow-strip-types" "^7.12.1" - "@babel/preset-modules@^0.1.3": version "0.1.4" resolved "https://registry.yarnpkg.com/@babel/preset-modules/-/preset-modules-0.1.4.tgz#362f2b68c662842970fdb5e254ffc8fc1c2e415e" @@ -1040,16 +1036,16 @@ "@babel/parser" "^7.12.7" "@babel/types" "^7.12.7" -"@babel/template@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.12.13.tgz#530265be8a2589dbb37523844c5bcb55947fb327" - integrity sha512-/7xxiGA57xMo/P2GVvdEumr8ONhFOhfgq2ihK3h1e6THqzTAkHbkXgB0xI9yeTfIUoH3+oAeHhqm/I43OTbbjA== +"@babel/template@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.14.5.tgz#a9bc9d8b33354ff6e55a9c60d1109200a68974f4" + integrity sha512-6Z3Po85sfxRGachLULUhOmvAaOo7xCvqGQtxINai2mEGPFm6pQ4z5QInFnUrRpfoSV60BnjyF5F3c+15fxFV1g== dependencies: - "@babel/code-frame" "^7.12.13" - "@babel/parser" "^7.12.13" - "@babel/types" "^7.12.13" + "@babel/code-frame" "^7.14.5" + "@babel/parser" "^7.14.5" + "@babel/types" "^7.14.5" -"@babel/traverse@^7.1.0", "@babel/traverse@^7.10.4", "@babel/traverse@^7.12.1", "@babel/traverse@^7.12.10", "@babel/traverse@^7.12.12", "@babel/traverse@^7.12.5", "@babel/traverse@^7.7.0", "@babel/traverse@^7.7.4": +"@babel/traverse@^7.1.0", "@babel/traverse@^7.10.4", "@babel/traverse@^7.12.1", "@babel/traverse@^7.12.10", "@babel/traverse@^7.12.12", "@babel/traverse@^7.12.5": version "7.12.12" resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.12.12.tgz#d0cd87892704edd8da002d674bc811ce64743376" integrity sha512-s88i0X0lPy45RrLM8b9mz8RPH5FqO9G9p7ti59cToE44xFm1Q+Pjh5Gq4SXBbtb88X7Uy7pexeqRIQDDMNkL0w== @@ -1065,20 +1061,21 @@ lodash "^4.17.19" "@babel/traverse@^7.13.17": - version "7.13.17" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.13.17.tgz#c85415e0c7d50ac053d758baec98b28b2ecfeea3" - integrity sha512-BMnZn0R+X6ayqm3C3To7o1j7Q020gWdqdyP50KEoVqaCO2c/Im7sYZSmVgvefp8TTMQ+9CtwuBp0Z1CZ8V3Pvg== + version "7.14.7" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.14.7.tgz#64007c9774cfdc3abd23b0780bc18a3ce3631753" + integrity sha512-9vDr5NzHu27wgwejuKL7kIOm4bwEtaPQ4Z6cpCmjSuaRqpH/7xc4qcGEscwMqlkwgcXl6MvqoAjZkQ24uSdIZQ== dependencies: - "@babel/code-frame" "^7.12.13" - "@babel/generator" "^7.13.16" - "@babel/helper-function-name" "^7.12.13" - "@babel/helper-split-export-declaration" "^7.12.13" - "@babel/parser" "^7.13.16" - "@babel/types" "^7.13.17" + "@babel/code-frame" "^7.14.5" + "@babel/generator" "^7.14.5" + "@babel/helper-function-name" "^7.14.5" + "@babel/helper-hoist-variables" "^7.14.5" + "@babel/helper-split-export-declaration" "^7.14.5" + "@babel/parser" "^7.14.7" + "@babel/types" "^7.14.5" debug "^4.1.0" globals "^11.1.0" -"@babel/types@^7.0.0", "@babel/types@^7.10.4", "@babel/types@^7.10.5", "@babel/types@^7.12.1", "@babel/types@^7.12.10", "@babel/types@^7.12.11", "@babel/types@^7.12.12", "@babel/types@^7.12.5", "@babel/types@^7.12.7", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.4.4", "@babel/types@^7.7.0": +"@babel/types@^7.0.0", "@babel/types@^7.10.4", "@babel/types@^7.10.5", "@babel/types@^7.12.1", "@babel/types@^7.12.10", "@babel/types@^7.12.11", "@babel/types@^7.12.12", "@babel/types@^7.12.5", "@babel/types@^7.12.7", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.4.4": version "7.12.12" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.12.12.tgz#4608a6ec313abbd87afa55004d373ad04a96c299" integrity sha512-lnIX7piTxOH22xE7fDXDbSHg9MM1/6ORnafpJmov5rs0kX5g4BZxeXNJLXsMRiO0U5Rb8/FvMS6xlTnTHvxonQ== @@ -1087,12 +1084,12 @@ lodash "^4.17.19" to-fast-properties "^2.0.0" -"@babel/types@^7.12.13", "@babel/types@^7.13.16", "@babel/types@^7.13.17": - version "7.13.17" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.13.17.tgz#48010a115c9fba7588b4437dd68c9469012b38b4" - integrity sha512-RawydLgxbOPDlTLJNtoIypwdmAy//uQIzlKt2+iBiJaRlVuI6QLUxVAyWGNfOzp8Yu4L4lLIacoCyTNtpb4wiA== +"@babel/types@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.14.5.tgz#3bb997ba829a2104cedb20689c4a5b8121d383ff" + integrity sha512-M/NzBpEL95I5Hh4dwhin5JlE7EzO5PHMAuzjxss3tiOBD46KfQvVedN/3jEPZvdRvtsK2222XfdHogNIttFgcg== dependencies: - "@babel/helper-validator-identifier" "^7.12.11" + "@babel/helper-validator-identifier" "^7.14.5" to-fast-properties "^2.0.0" "@bcoe/v8-coverage@^0.2.3": @@ -1564,11 +1561,6 @@ resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.7.tgz#98a993516c859eb0d5c4c8f098317a9ea68db9ad" integrity sha512-cxWFQVseBm6O9Gbw1IWb8r6OS4OhSt3hPZLkFApLjM8TEXROBuQGLAH2i2gZpcXdLBIrpXuTDhH7Vbm1iXmNGA== -"@types/json5@^0.0.29": - version "0.0.29" - resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" - integrity sha1-7ihweulOEdK4J7y+UnC86n8+ce4= - "@types/linkifyjs@^2.1.3": version "2.1.3" resolved "https://registry.yarnpkg.com/@types/linkifyjs/-/linkifyjs-2.1.3.tgz#80195c3c88c5e75d9f660e3046ce4a42be2c2fa4" @@ -1729,13 +1721,13 @@ resolved "https://registry.yarnpkg.com/@types/zxcvbn/-/zxcvbn-4.4.0.tgz#fbc1d941cc6d9d37d18405c513ba6b294f89b609" integrity sha512-GQLOT+SN20a+AI51y3fAimhyTF4Y0RG+YP3gf91OibIZ7CJmPFgoZi+ZR5a+vRbS01LbQosITWum4ATmJ1Z6Pg== -"@typescript-eslint/eslint-plugin@^4.14.0": - version "4.14.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.14.0.tgz#92db8e7c357ed7d69632d6843ca70b71be3a721d" - integrity sha512-IJ5e2W7uFNfg4qh9eHkHRUCbgZ8VKtGwD07kannJvM5t/GU8P8+24NX8gi3Hf5jST5oWPY8kyV1s/WtfiZ4+Ww== +"@typescript-eslint/eslint-plugin@^4.17.0": + version "4.20.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.20.0.tgz#9d8794bd99aad9153092ad13c96164e3082e9a92" + integrity sha512-sw+3HO5aehYqn5w177z2D82ZQlqHCwcKSMboueo7oE4KU9QiC0SAgfS/D4z9xXvpTc8Bt41Raa9fBR8T2tIhoQ== dependencies: - "@typescript-eslint/experimental-utils" "4.14.0" - "@typescript-eslint/scope-manager" "4.14.0" + "@typescript-eslint/experimental-utils" "4.20.0" + "@typescript-eslint/scope-manager" "4.20.0" debug "^4.1.1" functional-red-black-tree "^1.0.1" lodash "^4.17.15" @@ -1743,61 +1735,60 @@ semver "^7.3.2" tsutils "^3.17.1" -"@typescript-eslint/experimental-utils@4.14.0": - version "4.14.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-4.14.0.tgz#5aa7b006736634f588a69ee343ca959cd09988df" - integrity sha512-6i6eAoiPlXMKRbXzvoQD5Yn9L7k9ezzGRvzC/x1V3650rUk3c3AOjQyGYyF9BDxQQDK2ElmKOZRD0CbtdkMzQQ== +"@typescript-eslint/experimental-utils@4.20.0": + version "4.20.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-4.20.0.tgz#a8ab2d7b61924f99042b7d77372996d5f41dc44b" + integrity sha512-sQNlf6rjLq2yB5lELl3gOE7OuoA/6IVXJUJ+Vs7emrQMva14CkOwyQwD7CW+TkmOJ4Q/YGmoDLmbfFrpGmbKng== dependencies: "@types/json-schema" "^7.0.3" - "@typescript-eslint/scope-manager" "4.14.0" - "@typescript-eslint/types" "4.14.0" - "@typescript-eslint/typescript-estree" "4.14.0" + "@typescript-eslint/scope-manager" "4.20.0" + "@typescript-eslint/types" "4.20.0" + "@typescript-eslint/typescript-estree" "4.20.0" eslint-scope "^5.0.0" eslint-utils "^2.0.0" -"@typescript-eslint/parser@^4.14.0": - version "4.14.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-4.14.0.tgz#62d4cd2079d5c06683e9bfb200c758f292c4dee7" - integrity sha512-sUDeuCjBU+ZF3Lzw0hphTyScmDDJ5QVkyE21pRoBo8iDl7WBtVFS+WDN3blY1CH3SBt7EmYCw6wfmJjF0l/uYg== +"@typescript-eslint/parser@^4.17.0": + version "4.20.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-4.20.0.tgz#8dd403c8b4258b99194972d9799e201b8d083bdd" + integrity sha512-m6vDtgL9EABdjMtKVw5rr6DdeMCH3OA1vFb0dAyuZSa3e5yw1YRzlwFnm9knma9Lz6b2GPvoNSa8vOXrqsaglA== dependencies: - "@typescript-eslint/scope-manager" "4.14.0" - "@typescript-eslint/types" "4.14.0" - "@typescript-eslint/typescript-estree" "4.14.0" + "@typescript-eslint/scope-manager" "4.20.0" + "@typescript-eslint/types" "4.20.0" + "@typescript-eslint/typescript-estree" "4.20.0" debug "^4.1.1" -"@typescript-eslint/scope-manager@4.14.0": - version "4.14.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.14.0.tgz#55a4743095d684e1f7b7180c4bac2a0a3727f517" - integrity sha512-/J+LlRMdbPh4RdL4hfP1eCwHN5bAhFAGOTsvE6SxsrM/47XQiPSgF5MDgLyp/i9kbZV9Lx80DW0OpPkzL+uf8Q== +"@typescript-eslint/scope-manager@4.20.0": + version "4.20.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.20.0.tgz#953ecbf3b00845ece7be66246608be9d126d05ca" + integrity sha512-/zm6WR6iclD5HhGpcwl/GOYDTzrTHmvf8LLLkwKqqPKG6+KZt/CfSgPCiybshmck66M2L5fWSF/MKNuCwtKQSQ== dependencies: - "@typescript-eslint/types" "4.14.0" - "@typescript-eslint/visitor-keys" "4.14.0" + "@typescript-eslint/types" "4.20.0" + "@typescript-eslint/visitor-keys" "4.20.0" -"@typescript-eslint/types@4.14.0": - version "4.14.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.14.0.tgz#d8a8202d9b58831d6fd9cee2ba12f8a5a5dd44b6" - integrity sha512-VsQE4VvpldHrTFuVPY1ZnHn/Txw6cZGjL48e+iBxTi2ksa9DmebKjAeFmTVAYoSkTk7gjA7UqJ7pIsyifTsI4A== +"@typescript-eslint/types@4.20.0": + version "4.20.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.20.0.tgz#c6cf5ef3c9b1c8f699a9bbdafb7a1da1ca781225" + integrity sha512-cYY+1PIjei1nk49JAPnH1VEnu7OYdWRdJhYI5wiKOUMhLTG1qsx5cQxCUTuwWCmQoyriadz3Ni8HZmGSofeC+w== -"@typescript-eslint/typescript-estree@4.14.0": - version "4.14.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.14.0.tgz#4bcd67486e9acafc3d0c982b23a9ab8ac8911ed7" - integrity sha512-wRjZ5qLao+bvS2F7pX4qi2oLcOONIB+ru8RGBieDptq/SudYwshveORwCVU4/yMAd4GK7Fsf8Uq1tjV838erag== +"@typescript-eslint/typescript-estree@4.20.0": + version "4.20.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.20.0.tgz#8b3b08f85f18a8da5d88f65cb400f013e88ab7be" + integrity sha512-Knpp0reOd4ZsyoEJdW8i/sK3mtZ47Ls7ZHvD8WVABNx5Xnn7KhenMTRGegoyMTx6TiXlOVgMz9r0pDgXTEEIHA== dependencies: - "@typescript-eslint/types" "4.14.0" - "@typescript-eslint/visitor-keys" "4.14.0" + "@typescript-eslint/types" "4.20.0" + "@typescript-eslint/visitor-keys" "4.20.0" debug "^4.1.1" globby "^11.0.1" is-glob "^4.0.1" - lodash "^4.17.15" semver "^7.3.2" tsutils "^3.17.1" -"@typescript-eslint/visitor-keys@4.14.0": - version "4.14.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.14.0.tgz#b1090d9d2955b044b2ea2904a22496849acbdf54" - integrity sha512-MeHHzUyRI50DuiPgV9+LxcM52FCJFYjJiWHtXlbyC27b80mfOwKeiKI+MHOTEpcpfmoPFm/vvQS88bYIx6PZTA== +"@typescript-eslint/visitor-keys@4.20.0": + version "4.20.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.20.0.tgz#1e84db034da13f208325e6bfc995c3b75f7dbd62" + integrity sha512-NXKRM3oOVQL8yNFDNCZuieRIwZ5UtjNLYtmMx2PacEAGmbaEYtGgVHUHVyZvU/0rYZcizdrWjDo+WBtRPSgq+A== dependencies: - "@typescript-eslint/types" "4.14.0" + "@typescript-eslint/types" "4.20.0" eslint-visitor-keys "^2.0.0" "@wojtekmaj/enzyme-adapter-react-17@^0.6.1": @@ -1838,7 +1829,7 @@ acorn-globals@^6.0.0: acorn "^7.1.1" acorn-walk "^7.1.1" -acorn-jsx@^5.2.0, acorn-jsx@^5.3.1: +acorn-jsx@^5.3.1: version "5.3.1" resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.1.tgz#fc8661e11b7ac1539c47dbfea2e72b3af34d267b" integrity sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng== @@ -1853,7 +1844,7 @@ acorn@^7.1.1, acorn@^7.4.0: resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa" integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== -ajv@^6.10.0, ajv@^6.10.2, ajv@^6.12.3, ajv@^6.12.4: +ajv@^6.10.0, ajv@^6.12.3, ajv@^6.12.4: version "6.12.6" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== @@ -2031,11 +2022,6 @@ assign-symbols@^1.0.0: resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c= -astral-regex@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9" - integrity sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg== - astral-regex@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31" @@ -2084,18 +2070,6 @@ aws4@^1.8.0: resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.11.0.tgz#d61f46d83b2519250e2784daf5b09479a8b41c59" integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA== -babel-eslint@^10.0.1, babel-eslint@^10.1.0: - version "10.1.0" - resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-10.1.0.tgz#6968e568a910b78fb3779cdd8b6ac2f479943232" - integrity sha512-ifWaTHQ0ce+448CYop8AdrQiBsGrnC+bMgfyKFdi6EsPLTAWG+QfyDeM6OH+FmWnKvEq5NnBMLvlBUPKQZoDSg== - dependencies: - "@babel/code-frame" "^7.0.0" - "@babel/parser" "^7.7.0" - "@babel/traverse" "^7.7.0" - "@babel/types" "^7.7.0" - eslint-visitor-keys "^1.0.0" - resolve "^1.12.0" - babel-jest@^26.6.3: version "26.6.3" resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-26.6.3.tgz#d87d25cb0037577a0c89f82e5755c5d293c01056" @@ -2392,7 +2366,7 @@ caseless@~0.12.0: resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= -chalk@^2.0.0, chalk@^2.1.0, chalk@^2.4.2: +chalk@^2.0.0, chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== @@ -2437,11 +2411,6 @@ character-reference-invalid@^1.0.0: resolved "https://registry.yarnpkg.com/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz#083329cda0eae272ab3dbbf37e9a382c13af1560" integrity sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg== -chardet@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" - integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== - cheerio-select@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/cheerio-select/-/cheerio-select-1.4.0.tgz#3a16f21e37a2ef0f211d6d1aa4eff054bb22cdc9" @@ -2506,18 +2475,6 @@ classnames@^2.2.6: resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.6.tgz#43935bffdd291f326dad0a205309b38d00f650ce" integrity sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q== -cli-cursor@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307" - integrity sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw== - dependencies: - restore-cursor "^3.1.0" - -cli-width@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-3.0.0.tgz#a2f48437a2caa9a22436e794bf071ec9e61cedf6" - integrity sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw== - cliui@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/cliui/-/cliui-5.0.0.tgz#deefcfdb2e800784aa34f46fa08e06851c7bbbc5" @@ -2647,11 +2604,6 @@ concurrently@^5.3.0: tree-kill "^1.2.2" yargs "^13.3.0" -contains-path@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/contains-path/-/contains-path-0.1.0.tgz#fe8cf184ff6670b6baef01a9d4861a5cbec4120a" - integrity sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo= - content-type@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" @@ -2721,7 +2673,7 @@ cross-fetch@^3.0.4: dependencies: node-fetch "2.6.1" -cross-spawn@^6.0.0, cross-spawn@^6.0.5: +cross-spawn@^6.0.0: version "6.0.5" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== @@ -2822,7 +2774,7 @@ date-names@^0.1.11: resolved "https://registry.yarnpkg.com/date-names/-/date-names-0.1.13.tgz#c4358f6f77c8056e2f5ea68fdbb05f0bf1e53bd0" integrity sha512-IxxoeD9tdx8pXVcmqaRlPvrXIsSrSrIZzfzlOkm9u+hyzKp5Wk/odt9O/gd7Ockzy8n/WHeEpTVJ2bF3mMV4LA== -debug@^2.2.0, debug@^2.3.3, debug@^2.6.9: +debug@^2.2.0, debug@^2.3.3: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== @@ -2945,14 +2897,6 @@ discontinuous-range@1.0.0: resolved "https://registry.yarnpkg.com/discontinuous-range/-/discontinuous-range-1.0.0.tgz#e38331f0844bba49b9a9cb71c771585aab1bc65a" integrity sha1-44Mx8IRLukm5qctxx3FYWqsbxlo= -doctrine@1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-1.5.0.tgz#379dce730f6166f76cefa4e6707a159b02c5a6fa" - integrity sha1-N53Ocw9hZvds76TmcHoVmwLFpvo= - dependencies: - esutils "^2.0.2" - isarray "^1.0.0" - doctrine@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" @@ -3150,7 +3094,7 @@ enzyme@^3.11.0: rst-selector-parser "^2.2.3" string.prototype.trim "^1.2.1" -error-ex@^1.2.0, error-ex@^1.3.1: +error-ex@^1.3.1: version "1.3.2" resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== @@ -3276,131 +3220,21 @@ escodegen@^1.14.1: optionalDependencies: source-map "~0.6.1" -eslint-config-esnext@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/eslint-config-esnext/-/eslint-config-esnext-4.1.0.tgz#8695b858fcf40d28c1aedca181f700528c7b60c6" - integrity sha512-GhfVEXdqYKEIIj7j+Fw2SQdL9qyZMekgXfq6PyXM66cQw0B435ddjz3P3kxOBVihMRJ0xGYjosaveQz5Y6z0uA== - dependencies: - babel-eslint "^10.0.1" - eslint "^6.8.0" - eslint-plugin-babel "^5.2.1" - eslint-plugin-import "^2.14.0" - eslint-config-google@^0.14.0: version "0.14.0" resolved "https://registry.yarnpkg.com/eslint-config-google/-/eslint-config-google-0.14.0.tgz#4f5f8759ba6e11b424294a219dbfa18c508bcc1a" integrity sha512-WsbX4WbjuMvTdeVL6+J3rK1RGhCTqjsFjX7UMSMgZiyxxaNLkoJENbrGExzERFeoTpGw3F3FypTiWAP9ZXzkEw== -eslint-config-matrix-org@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/eslint-config-matrix-org/-/eslint-config-matrix-org-0.2.0.tgz#27571c7c3a9ab6cc1e9d0f3d53a3739d1b004a7f" - integrity sha512-Hwgm1Qk0atjWgj5SWxpFPvxy6k6bDlPb9Pqjvb1i59nx8Zm6jDPy1C5vKQpkFpc0ntr+gJHa+ejYhuhaofu6Mw== - dependencies: - "@typescript-eslint/eslint-plugin" "^4.14.0" - "@typescript-eslint/parser" "^4.14.0" - babel-eslint "^10.1.0" - eslint-config-google "^0.14.0" - eslint-config-recommended "^4.1.0" - eslint-plugin-babel "^5.3.1" - typescript "^4.1.3" - -eslint-config-node@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/eslint-config-node/-/eslint-config-node-4.1.0.tgz#fc1f13946d83766d6b83b0e67699e2071a56f417" - integrity sha512-Wz17xV5O2WFG8fGdMYEBdbiL6TL7YNJSJvSX9V4sXQownewfYmoqlly7wxqLkOUv/57pq6LnnotMiQQrrPjCqQ== - dependencies: - eslint "^6.8.0" - eslint-config-esnext "^4.1.0" - -eslint-config-react-native@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/eslint-config-react-native/-/eslint-config-react-native-4.1.0.tgz#63e9401c7fac146804785f609e7df8f15b3e04eb" - integrity sha512-kNND+cs+ztawH7wgajf/K6FfNshjlDsFDAkkFZF9HAXDgH1w1sNMIfTfwzufg0hOcSK7rbiL4qbG/gg/oR507Q== - dependencies: - eslint "^6.8.0" - eslint-config-esnext "^4.1.0" - eslint-plugin-react "^7.19.0" - eslint-plugin-react-native "^3.8.1" - -eslint-config-recommended@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/eslint-config-recommended/-/eslint-config-recommended-4.1.0.tgz#1adff90e0716d439be471d192977f233de171a46" - integrity sha512-2evA0SX1VqtyFiExmBI2WAO4XQCKlr7wmNELE8rcT5PyZY2ixsY881ofVZWKuI/dywpgLiES1gR/XUQcnVLRzQ== - dependencies: - eslint "^6.8.0" - eslint-config-esnext "^4.1.0" - eslint-config-node "^4.1.0" - eslint-config-react-native "^4.1.0" - -eslint-import-resolver-node@^0.3.4: - version "0.3.4" - resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.4.tgz#85ffa81942c25012d8231096ddf679c03042c717" - integrity sha512-ogtf+5AB/O+nM6DIeBUNr2fuT7ot9Qg/1harBfBtaP13ekEWFQEEMP94BCB7zaNW3gyY+8SHYF00rnqYwXKWOA== - dependencies: - debug "^2.6.9" - resolve "^1.13.1" - -eslint-module-utils@^2.6.0: - version "2.6.0" - resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.6.0.tgz#579ebd094f56af7797d19c9866c9c9486629bfa6" - integrity sha512-6j9xxegbqe8/kZY8cYpcp0xhbK0EgJlg3g9mib3/miLaExuuwc3n5UEfSnU6hWMbT0FAYVvDbL9RrRgpUeQIvA== - dependencies: - debug "^2.6.9" - pkg-dir "^2.0.0" - -eslint-plugin-babel@^5.2.1, eslint-plugin-babel@^5.3.1: - version "5.3.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-babel/-/eslint-plugin-babel-5.3.1.tgz#75a2413ffbf17e7be57458301c60291f2cfbf560" - integrity sha512-VsQEr6NH3dj664+EyxJwO4FCYm/00JhYb3Sk3ft8o+fpKuIfQ9TaW6uVUfvwMXHcf/lsnRIoyFPsLMyiWCSL/g== - dependencies: - eslint-rule-composer "^0.3.0" - -eslint-plugin-flowtype@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-flowtype/-/eslint-plugin-flowtype-5.2.0.tgz#a4bef5dc18f9b2bdb41569a4ab05d73805a3d261" - integrity sha512-z7ULdTxuhlRJcEe1MVljePXricuPOrsWfScRXFhNzVD5dmTHWjIF57AxD0e7AbEoLSbjSsaA5S+hCg43WvpXJQ== - dependencies: - lodash "^4.17.15" - string-natural-compare "^3.0.1" - -eslint-plugin-import@^2.14.0: - version "2.22.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.22.1.tgz#0896c7e6a0cf44109a2d97b95903c2bb689d7702" - integrity sha512-8K7JjINHOpH64ozkAhpT3sd+FswIZTfMZTjdx052pnWrgRCVfp8op9tbjpAk3DdUeI/Ba4C8OjdC0r90erHEOw== - dependencies: - array-includes "^3.1.1" - array.prototype.flat "^1.2.3" - contains-path "^0.1.0" - debug "^2.6.9" - doctrine "1.5.0" - eslint-import-resolver-node "^0.3.4" - eslint-module-utils "^2.6.0" - has "^1.0.3" - minimatch "^3.0.4" - object.values "^1.1.1" - read-pkg-up "^2.0.0" - resolve "^1.17.0" - tsconfig-paths "^3.9.0" +"eslint-plugin-matrix-org@github:matrix-org/eslint-plugin-matrix-org#main": + version "0.3.2" + resolved "https://codeload.github.com/matrix-org/eslint-plugin-matrix-org/tar.gz/28d392822533a7468be0dd806d0a4ba573a45d74" eslint-plugin-react-hooks@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.2.0.tgz#8c229c268d468956334c943bb45fc860280f5556" integrity sha512-623WEiZJqxR7VdxFCKLI6d6LLpwJkGPYKODnkH3D7WpOG5KM8yWueBd8TLsNAetEJNF5iJmolaAKO3F8yzyVBQ== -eslint-plugin-react-native-globals@^0.1.1: - version "0.1.2" - resolved "https://registry.yarnpkg.com/eslint-plugin-react-native-globals/-/eslint-plugin-react-native-globals-0.1.2.tgz#ee1348bc2ceb912303ce6bdbd22e2f045ea86ea2" - integrity sha512-9aEPf1JEpiTjcFAmmyw8eiIXmcNZOqaZyHO77wgm0/dWfT/oxC1SrIq8ET38pMxHYrcB6Uew+TzUVsBeczF88g== - -eslint-plugin-react-native@^3.8.1: - version "3.10.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-react-native/-/eslint-plugin-react-native-3.10.0.tgz#240f7e6979a908af3dfd9ba9652434c33f4d64cd" - integrity sha512-4f5+hHYYq5wFhB5eptkPEAR7FfvqbS7AzScUOANfAMZtYw5qgnCxRq45bpfBaQF+iyPMim5Q8pubcpvLv75NAg== - dependencies: - "@babel/traverse" "^7.7.4" - eslint-plugin-react-native-globals "^0.1.1" - -eslint-plugin-react@^7.19.0, eslint-plugin-react@^7.22.0: +eslint-plugin-react@^7.22.0: version "7.22.0" resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.22.0.tgz#3d1c542d1d3169c45421c1215d9470e341707269" integrity sha512-p30tuX3VS+NWv9nQot9xIGAHBXR0+xJVaZriEsHoJrASGCJZDJ8JLNM0YqKqI0AKm6Uxaa1VUHoNEibxRCMQHA== @@ -3422,7 +3256,7 @@ eslint-rule-composer@^0.3.0: resolved "https://registry.yarnpkg.com/eslint-rule-composer/-/eslint-rule-composer-0.3.0.tgz#79320c927b0c5c0d3d3d2b76c8b4a488f25bbaf9" integrity sha512-bt+Sh8CtDmn2OajxvNO+BX7Wn4CIWMpTRm3MaiKPCQcnnlm0CS2mhui6QaoeQugs+3Kj2ESKEEGJUdVafwhiCg== -eslint-scope@^5.0.0, eslint-scope@^5.1.1: +eslint-scope@^5.0.0, eslint-scope@^5.1.0, eslint-scope@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== @@ -3430,13 +3264,6 @@ eslint-scope@^5.0.0, eslint-scope@^5.1.1: esrecurse "^4.3.0" estraverse "^4.1.1" -eslint-utils@^1.4.3: - version "1.4.3" - resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-1.4.3.tgz#74fec7c54d0776b6f67e0251040b5806564e981f" - integrity sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q== - dependencies: - eslint-visitor-keys "^1.1.0" - eslint-utils@^2.0.0, eslint-utils@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-2.1.0.tgz#d2de5e03424e707dc10c74068ddedae708741b27" @@ -3444,7 +3271,7 @@ eslint-utils@^2.0.0, eslint-utils@^2.1.0: dependencies: eslint-visitor-keys "^1.1.0" -eslint-visitor-keys@^1.0.0, eslint-visitor-keys@^1.1.0, eslint-visitor-keys@^1.3.0: +eslint-visitor-keys@^1.1.0, eslint-visitor-keys@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e" integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ== @@ -3497,58 +3324,6 @@ eslint@7.18.0: text-table "^0.2.0" v8-compile-cache "^2.0.3" -eslint@^6.8.0: - version "6.8.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-6.8.0.tgz#62262d6729739f9275723824302fb227c8c93ffb" - integrity sha512-K+Iayyo2LtyYhDSYwz5D5QdWw0hCacNzyq1Y821Xna2xSJj7cijoLLYmLxTQgcgZ9mC61nryMy9S7GRbYpI5Ig== - dependencies: - "@babel/code-frame" "^7.0.0" - ajv "^6.10.0" - chalk "^2.1.0" - cross-spawn "^6.0.5" - debug "^4.0.1" - doctrine "^3.0.0" - eslint-scope "^5.0.0" - eslint-utils "^1.4.3" - eslint-visitor-keys "^1.1.0" - espree "^6.1.2" - esquery "^1.0.1" - esutils "^2.0.2" - file-entry-cache "^5.0.1" - functional-red-black-tree "^1.0.1" - glob-parent "^5.0.0" - globals "^12.1.0" - ignore "^4.0.6" - import-fresh "^3.0.0" - imurmurhash "^0.1.4" - inquirer "^7.0.0" - is-glob "^4.0.0" - js-yaml "^3.13.1" - json-stable-stringify-without-jsonify "^1.0.1" - levn "^0.3.0" - lodash "^4.17.14" - minimatch "^3.0.4" - mkdirp "^0.5.1" - natural-compare "^1.4.0" - optionator "^0.8.3" - progress "^2.0.0" - regexpp "^2.0.1" - semver "^6.1.2" - strip-ansi "^5.2.0" - strip-json-comments "^3.0.1" - table "^5.2.3" - text-table "^0.2.0" - v8-compile-cache "^2.0.3" - -espree@^6.1.2: - version "6.2.1" - resolved "https://registry.yarnpkg.com/espree/-/espree-6.2.1.tgz#77fc72e1fd744a2052c20f38a5b575832e82734a" - integrity sha512-ysCxRQY3WaXJz9tdbWOwuWr5Y/XrPTGX9Kiz3yoUXwW0VZ4w30HTkQLaGx/+ttFjF8i+ACbArnB4ce68a9m5hw== - dependencies: - acorn "^7.1.1" - acorn-jsx "^5.2.0" - eslint-visitor-keys "^1.1.0" - espree@^7.3.0, espree@^7.3.1: version "7.3.1" resolved "https://registry.yarnpkg.com/espree/-/espree-7.3.1.tgz#f2df330b752c6f55019f8bd89b7660039c1bbbb6" @@ -3563,7 +3338,7 @@ esprima@^4.0.0, esprima@^4.0.1: resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== -esquery@^1.0.1, esquery@^1.2.0: +esquery@^1.2.0: version "1.3.1" resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.3.1.tgz#b78b5828aa8e214e29fb74c4d5b752e1c033da57" integrity sha512-olpvt9QG0vniUBZspVRN6lwB7hOZoTRtT+jzR+tS4ffYx2mzbw+z0XCOk44aaLYKApNX5nMm+E+P6o25ip/DHQ== @@ -3707,15 +3482,6 @@ extend@^3.0.0, extend@~3.0.2: resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== -external-editor@^3.0.3: - version "3.1.0" - resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.1.0.tgz#cb03f740befae03ea4d283caed2741a83f335495" - integrity sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew== - dependencies: - chardet "^0.7.0" - iconv-lite "^0.4.24" - tmp "^0.0.33" - extglob@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" @@ -3820,20 +3586,6 @@ fbjs@^0.8.4: setimmediate "^1.0.5" ua-parser-js "^0.7.18" -figures@^3.0.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/figures/-/figures-3.2.0.tgz#625c18bd293c604dc4a8ddb2febf0c88341746af" - integrity sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg== - dependencies: - escape-string-regexp "^1.0.5" - -file-entry-cache@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-5.0.1.tgz#ca0f6efa6dd3d561333fb14515065c2fafdf439c" - integrity sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g== - dependencies: - flat-cache "^2.0.1" - file-entry-cache@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.0.tgz#7921a89c391c6d93efec2169ac6bf300c527ea0a" @@ -3877,13 +3629,6 @@ find-cache-dir@^2.0.0: make-dir "^2.0.0" pkg-dir "^3.0.0" -find-up@^2.0.0, find-up@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" - integrity sha1-RdG35QbHF93UgndaK3eSCjwMV6c= - dependencies: - locate-path "^2.0.0" - find-up@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" @@ -3899,15 +3644,6 @@ find-up@^4.0.0, find-up@^4.1.0: locate-path "^5.0.0" path-exists "^4.0.0" -flat-cache@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-2.0.1.tgz#5d296d6f04bda44a4630a301413bdbc2ec085ec0" - integrity sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA== - dependencies: - flatted "^2.0.0" - rimraf "2.6.3" - write "1.0.3" - flat-cache@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11" @@ -3916,11 +3652,6 @@ flat-cache@^3.0.4: flatted "^3.1.0" rimraf "^3.0.2" -flatted@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.2.tgz#4575b21e2bcee7434aa9be662f4b7b5f9c2b5138" - integrity sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA== - flatted@^3.1.0: version "3.1.1" resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.1.1.tgz#c4b489e80096d9df1dfc97c79871aea7c617c469" @@ -4157,7 +3888,19 @@ globals@^12.1.0: dependencies: type-fest "^0.8.1" -globby@^11.0.1, globby@^11.0.2: +globby@^11.0.1: + version "11.0.3" + resolved "https://registry.yarnpkg.com/globby/-/globby-11.0.3.tgz#9b1f0cb523e171dd1ad8c7b2a9fb4b644b9593cb" + integrity sha512-ffdmosjA807y7+lA1NM0jELARVmYul/715xiILEjo3hBLPTcirgQNnXECn5g3mtR8TOLCVbkfua1Hpen25/Xcg== + dependencies: + array-union "^2.1.0" + dir-glob "^3.0.1" + fast-glob "^3.1.1" + ignore "^5.1.4" + merge2 "^1.3.0" + slash "^3.0.0" + +globby@^11.0.2: version "11.0.2" resolved "https://registry.yarnpkg.com/globby/-/globby-11.0.2.tgz#1af538b766a3b540ebfb58a32b2e2d5897321d83" integrity sha512-2ZThXDvvV8fYFRVIxnrMQBipZQDr7MxKAmQK1vujaj9/7eF0efG7BPUKJ7jP7G5SLF37xKDXvO4S/KKLj/Z0og== @@ -4181,7 +3924,7 @@ gonzales-pe@^4.3.0: dependencies: minimist "^1.2.5" -graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.2.4: +graceful-fs@^4.1.11, graceful-fs@^4.2.4: version "4.2.4" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb" integrity sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw== @@ -4371,7 +4114,7 @@ human-signals@^1.1.1: resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-1.1.1.tgz#c5b1cd14f50aeae09ab6c59fe63ba3395fe4dfa3" integrity sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw== -iconv-lite@0.4.24, iconv-lite@^0.4.24: +iconv-lite@0.4.24: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== @@ -4464,25 +4207,6 @@ ini@^1.3.5: resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== -inquirer@^7.0.0: - version "7.3.3" - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-7.3.3.tgz#04d176b2af04afc157a83fd7c100e98ee0aad003" - integrity sha512-JG3eIAj5V9CwcGvuOmoo6LB9kbAYT8HXffUl6memuszlwDC/qvFAJw49XJ5NROSFNPxp3iQg1GqkFhaY/CR0IA== - dependencies: - ansi-escapes "^4.2.1" - chalk "^4.1.0" - cli-cursor "^3.1.0" - cli-width "^3.0.0" - external-editor "^3.0.3" - figures "^3.0.0" - lodash "^4.17.19" - mute-stream "0.0.8" - run-async "^2.4.0" - rxjs "^6.6.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - through "^2.3.6" - internal-slot@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.2.tgz#9c2e9fb3cd8e5e4256c6f45fe310067fcfa378a3" @@ -4880,7 +4604,7 @@ is-wsl@^2.2.0: dependencies: is-docker "^2.0.0" -isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: +isarray@1.0.0, isarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= @@ -5487,13 +5211,6 @@ json-stringify-safe@~5.0.1: resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= -json5@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe" - integrity sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow== - dependencies: - minimist "^1.2.0" - json5@^2.1.2: version "2.1.3" resolved "https://registry.yarnpkg.com/json5/-/json5-2.1.3.tgz#c9b0f7fa9233bfe5807fe66fcf3a5617ed597d43" @@ -5570,14 +5287,6 @@ leven@^3.1.0: resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== -levn@^0.3.0, levn@~0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" - integrity sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4= - dependencies: - prelude-ls "~1.1.2" - type-check "~0.3.2" - levn@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" @@ -5586,6 +5295,14 @@ levn@^0.4.1: prelude-ls "^1.2.1" type-check "~0.4.0" +levn@~0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" + integrity sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4= + dependencies: + prelude-ls "~1.1.2" + type-check "~0.3.2" + lines-and-columns@^1.1.6: version "1.1.6" resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.1.6.tgz#1c00c743b433cd0a4e80758f7b64a57440d9ff00" @@ -5596,24 +5313,6 @@ linkifyjs@^2.1.9: resolved "https://registry.yarnpkg.com/linkifyjs/-/linkifyjs-2.1.9.tgz#af06e45a2866ff06c4766582590d098a4d584702" integrity sha512-74ivurkK6WHvHFozVaGtQWV38FzBwSTGNmJolEgFp7QgR2bl6ArUWlvT4GcHKbPe1z3nWYi+VUdDZk16zDOVug== -load-json-file@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-2.0.0.tgz#7947e42149af80d696cbf797bcaabcfe1fe29ca8" - integrity sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg= - dependencies: - graceful-fs "^4.1.2" - parse-json "^2.2.0" - pify "^2.0.0" - strip-bom "^3.0.0" - -locate-path@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" - integrity sha1-K1aLJl7slExtnA3pw9u7ygNUzY4= - dependencies: - p-locate "^2.0.0" - path-exists "^3.0.0" - locate-path@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" @@ -5649,7 +5348,7 @@ lodash.sortby@^4.7.0: resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438" integrity sha1-7dFMgk4sycHgsKG0K7UhBRakJDg= -lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20: +lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== @@ -5937,13 +5636,6 @@ mixin-deep@^1.2.0: for-in "^1.0.2" is-extendable "^1.0.1" -mkdirp@^0.5.1: - version "0.5.5" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" - integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== - dependencies: - minimist "^1.2.5" - moo-color@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/moo-color/-/moo-color-1.0.2.tgz#837c40758d2d58763825d1359a84e330531eca64" @@ -5966,11 +5658,6 @@ ms@2.1.2: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== -mute-stream@0.0.8: - version "0.0.8" - resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" - integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA== - nanoid@^3.1.20: version "3.1.20" resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.20.tgz#badc263c6b1dcf14b71efaa85f6ab4c1d6cfc788" @@ -6255,7 +5942,7 @@ onetime@^5.1.0: dependencies: mimic-fn "^2.1.0" -optionator@^0.8.1, optionator@^0.8.3: +optionator@^0.8.1: version "0.8.3" resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA== @@ -6284,11 +5971,6 @@ opus-recorder@^8.0.3: resolved "https://registry.yarnpkg.com/opus-recorder/-/opus-recorder-8.0.3.tgz#f7b44f8f68500c9b96a15042a69f915fd9c1716d" integrity sha512-8vXGiRwlJAavT9D3yYzukNVXQ8vEcKHcsQL/zXO24DQtJ0PLXvoPHNQPJrbMCdB4ypJgWDExvHF4JitQDL7dng== -os-tmpdir@~1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" - integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= - p-each-series@^2.1.0: version "2.2.0" resolved "https://registry.yarnpkg.com/p-each-series/-/p-each-series-2.2.0.tgz#105ab0357ce72b202a8a8b94933672657b5e2a9a" @@ -6299,13 +5981,6 @@ p-finally@^1.0.0: resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4= -p-limit@^1.1.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" - integrity sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q== - dependencies: - p-try "^1.0.0" - p-limit@^2.0.0, p-limit@^2.2.0: version "2.3.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" @@ -6313,13 +5988,6 @@ p-limit@^2.0.0, p-limit@^2.2.0: dependencies: p-try "^2.0.0" -p-locate@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" - integrity sha1-IKAQOyIqcMj9OcwuWAaA893l7EM= - dependencies: - p-limit "^1.1.0" - p-locate@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" @@ -6334,11 +6002,6 @@ p-locate@^4.1.0: dependencies: p-limit "^2.2.0" -p-try@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" - integrity sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M= - p-try@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" @@ -6368,13 +6031,6 @@ parse-entities@^2.0.0: is-decimal "^1.0.0" is-hexadecimal "^1.0.0" -parse-json@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" - integrity sha1-9ID0BDTvgHQfhGkJn43qGPVaTck= - dependencies: - error-ex "^1.2.0" - parse-json@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0" @@ -6455,13 +6111,6 @@ path-parse@^1.0.6: resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw== -path-type@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/path-type/-/path-type-2.0.0.tgz#f012ccb8415b7096fc2daa1054c3d72389594c73" - integrity sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM= - dependencies: - pify "^2.0.0" - path-type@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" @@ -6477,11 +6126,6 @@ picomatch@^2.0.4, picomatch@^2.0.5, picomatch@^2.2.1: resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad" integrity sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg== -pify@^2.0.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" - integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw= - pify@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" @@ -6499,13 +6143,6 @@ pirates@^4.0.0, pirates@^4.0.1: dependencies: node-modules-regexp "^1.0.0" -pkg-dir@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-2.0.0.tgz#f6d5d1109e19d63edf428e0bd57e12777615334b" - integrity sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s= - dependencies: - find-up "^2.1.0" - pkg-dir@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-3.0.0.tgz#2749020f239ed990881b1f71210d51eb6523bea3" @@ -6889,14 +6526,6 @@ react@^17.0.2: loose-envify "^1.1.0" object-assign "^4.1.1" -read-pkg-up@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-2.0.0.tgz#6b72a8048984e0c41e79510fd5e9fa99b3b549be" - integrity sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4= - dependencies: - find-up "^2.0.0" - read-pkg "^2.0.0" - read-pkg-up@^7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-7.0.1.tgz#f3a6135758459733ae2b95638056e1854e7ef507" @@ -6906,15 +6535,6 @@ read-pkg-up@^7.0.1: read-pkg "^5.2.0" type-fest "^0.8.1" -read-pkg@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-2.0.0.tgz#8ef1c0623c6a6db0dc6713c4bfac46332b2368f8" - integrity sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg= - dependencies: - load-json-file "^2.0.0" - normalize-package-data "^2.3.2" - path-type "^2.0.0" - read-pkg@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-4.0.1.tgz#963625378f3e1c4d48c85872b5a6ec7d5d093237" @@ -7027,11 +6647,6 @@ regexp.prototype.flags@^1.3.0: call-bind "^1.0.2" define-properties "^1.1.3" -regexpp@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-2.0.1.tgz#8d19d31cf632482b589049f8281f93dbcba4d07f" - integrity sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw== - regexpp@^3.0.0, regexpp@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.1.0.tgz#206d0ad0a5648cffbdb8ae46438f3dc51c9f78e2" @@ -7183,7 +6798,7 @@ resolve-url@^0.2.1: resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= -resolve@^1.10.0, resolve@^1.12.0, resolve@^1.13.1, resolve@^1.17.0, resolve@^1.18.1: +resolve@^1.10.0, resolve@^1.17.0, resolve@^1.18.1: version "1.19.0" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.19.0.tgz#1af5bf630409734a067cae29318aac7fa29a267c" integrity sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg== @@ -7191,14 +6806,6 @@ resolve@^1.10.0, resolve@^1.12.0, resolve@^1.13.1, resolve@^1.17.0, resolve@^1.1 is-core-module "^2.1.0" path-parse "^1.0.6" -restore-cursor@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e" - integrity sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA== - dependencies: - onetime "^5.1.0" - signal-exit "^3.0.2" - ret@~0.1.10: version "0.1.15" resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" @@ -7214,13 +6821,6 @@ rfc4648@^1.4.0: resolved "https://registry.yarnpkg.com/rfc4648/-/rfc4648-1.4.0.tgz#c75b2856ad2e2d588b6ddb985d556f1f7f2a2abd" integrity sha512-3qIzGhHlMHA6PoT6+cdPKZ+ZqtxkIvg8DZGKA5z6PQ33/uuhoJ+Ws/D/J9rXW6gXodgH8QYlz2UCl+sdUDmNIg== -rimraf@2.6.3: - version "2.6.3" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" - integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== - dependencies: - glob "^7.1.3" - rimraf@^3.0.0, rimraf@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" @@ -7241,17 +6841,12 @@ rsvp@^4.8.4: resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-4.8.5.tgz#c8f155311d167f68f21e168df71ec5b083113734" integrity sha512-nfMOlASu9OnRJo1mbEk2cz0D56a1MBNrJ7orjRZQG10XDyuvwksKbuXNp6qa+kbn839HwjwhBzhFmdsaEAfauA== -run-async@^2.4.0: - version "2.4.1" - resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455" - integrity sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ== - run-parallel@^1.1.9: version "1.1.10" resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.1.10.tgz#60a51b2ae836636c81377df16cb107351bcd13ef" integrity sha512-zb/1OuZ6flOlH6tQyMPUrE3x3Ulxjlo9WIVXR4yVYi4H9UXQaeIsPbLn2R3O3vQCnDKkAl2qHiuocKKX4Tz/Sw== -rxjs@^6.5.2, rxjs@^6.6.0: +rxjs@^6.5.2: version "6.6.3" resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.3.tgz#8ca84635c4daa900c0d3967a6ee7ac60271ee552" integrity sha512-trsQc+xYYXZ3urjOiJOuCOa5N3jAZ3eiSpQB5hIT8zGlL2QfnHLJ2r7GMkBGuIausdJN1OneaI6gQlsqNHHmZQ== @@ -7333,7 +6928,7 @@ semver@7.0.0: resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e" integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A== -semver@^6.0.0, semver@^6.1.2, semver@^6.3.0: +semver@^6.0.0, semver@^6.3.0: version "6.3.0" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== @@ -7423,15 +7018,6 @@ slash@^3.0.0: resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== -slice-ansi@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-2.1.0.tgz#cacd7693461a637a5788d92a7dd4fba068e81636" - integrity sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ== - dependencies: - ansi-styles "^3.2.0" - astral-regex "^1.0.0" - is-fullwidth-code-point "^2.0.0" - slice-ansi@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-4.0.0.tgz#500e8dd0fd55b05815086255b3195adf2a45fe6b" @@ -7618,11 +7204,6 @@ string-length@^4.0.1: char-regex "^1.0.2" strip-ansi "^6.0.0" -string-natural-compare@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/string-natural-compare/-/string-natural-compare-3.0.1.tgz#7a42d58474454963759e8e8b7ae63d71c1e7fdf4" - integrity sha512-n3sPwynL1nwKi3WJ6AIsClwBMa0zTi54fn2oLU6ndfTSIO05xaznjSf15PcBZU6FNWbmN5Q6cxT4V5hGvB4taw== - string-width@^3.0.0, string-width@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" @@ -7728,11 +7309,6 @@ strip-ansi@^6.0.0: dependencies: ansi-regex "^5.0.0" -strip-bom@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" - integrity sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM= - strip-bom@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-4.0.0.tgz#9c3505c1db45bcedca3d9cf7a16f5c5aa3901878" @@ -7755,7 +7331,7 @@ strip-indent@^3.0.0: dependencies: min-indent "^1.0.0" -strip-json-comments@^3.0.1, strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: +strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== @@ -7888,16 +7464,6 @@ symbol-tree@^3.2.4: resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2" integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw== -table@^5.2.3: - version "5.4.6" - resolved "https://registry.yarnpkg.com/table/-/table-5.4.6.tgz#1292d19500ce3f86053b05f0e8e7e4a3bb21079e" - integrity sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug== - dependencies: - ajv "^6.10.2" - lodash "^4.17.14" - slice-ansi "^2.1.0" - string-width "^3.0.0" - table@^6.0.4, table@^6.0.7: version "6.0.7" resolved "https://registry.yarnpkg.com/table/-/table-6.0.7.tgz#e45897ffbcc1bcf9e8a87bf420f2c9e5a7a52a34" @@ -7940,11 +7506,6 @@ throat@^5.0.0: resolved "https://registry.yarnpkg.com/throat/-/throat-5.0.0.tgz#c5199235803aad18754a667d659b5e72ce16764b" integrity sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA== -through@^2.3.6: - version "2.3.8" - resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" - integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= - tiny-invariant@^1.0.6: version "1.1.0" resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.1.0.tgz#634c5f8efdc27714b7f386c35e6760991d230875" @@ -7955,13 +7516,6 @@ tmatch@^2.0.1: resolved "https://registry.yarnpkg.com/tmatch/-/tmatch-2.0.1.tgz#0c56246f33f30da1b8d3d72895abaf16660f38cf" integrity sha1-DFYkbzPzDaG409colauvFmYPOM8= -tmp@^0.0.33: - version "0.0.33" - resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" - integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== - dependencies: - os-tmpdir "~1.0.2" - tmpl@1.0.x: version "1.0.4" resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.4.tgz#23640dd7b42d00433911140820e5cf440e521dd1" @@ -8043,16 +7597,6 @@ trough@^1.0.0: resolved "https://registry.yarnpkg.com/trough/-/trough-1.0.5.tgz#b8b639cefad7d0bb2abd37d433ff8293efa5f406" integrity sha512-rvuRbTarPXmMb79SmzEp8aqXNKcK+y0XaB298IXueQ8I2PsrATcPBCSPyK/dDNa2iWOhKlfNnOjdAOTBU/nkFA== -tsconfig-paths@^3.9.0: - version "3.9.0" - resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.9.0.tgz#098547a6c4448807e8fcb8eae081064ee9a3c90b" - integrity sha512-dRcuzokWhajtZWkQsDVKbWyY+jgcLC5sqJhg2PSgf4ZkH2aHPvaOY8YWGhmjb68b5qqTfasSsDO9k7RUiEmZAw== - dependencies: - "@types/json5" "^0.0.29" - json5 "^1.0.1" - minimist "^1.2.0" - strip-bom "^3.0.0" - tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3: version "1.14.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" @@ -8069,9 +7613,9 @@ tslib@^2.2.0: integrity sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w== tsutils@^3.17.1: - version "3.19.1" - resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.19.1.tgz#d8566e0c51c82f32f9c25a4d367cd62409a547a9" - integrity sha512-GEdoBf5XI324lu7ycad7s6laADfnAqCw6wLGI+knxvw9vsIYBaJfYdmeCEG3FMMUiSm3OGgNb+m6utsWf5h9Vw== + version "3.21.0" + resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623" + integrity sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA== dependencies: tslib "^1.8.1" @@ -8515,13 +8059,6 @@ write-file-atomic@^3.0.0, write-file-atomic@^3.0.3: signal-exit "^3.0.2" typedarray-to-buffer "^3.1.5" -write@1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/write/-/write-1.0.3.tgz#0800e14523b923a387e415123c865616aae0f5c3" - integrity sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig== - dependencies: - mkdirp "^0.5.1" - ws@^7.2.3: version "7.4.6" resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.6.tgz#5654ca8ecdeee47c33a9a4bf6d28e2be2980377c"