From 95283d21bb7bfd125cef7c4ad60dcc256e3ad16f Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Thu, 29 Jun 2023 12:17:05 +0100 Subject: [PATCH] Conform more of the codebase to strict types (#11162) --- src/AddThreepid.ts | 12 ++++++------ src/Modal.tsx | 8 +++++--- src/NodeAnimator.tsx | 9 +++++++-- src/SecurityManager.ts | 5 ++--- src/SlashCommands.tsx | 4 ++-- src/autocomplete/EmojiProvider.tsx | 4 ++-- src/emoji.ts | 16 +++++----------- src/mjolnir/Mjolnir.ts | 7 ++++++- src/stores/right-panel/RightPanelStore.ts | 2 +- 9 files changed, 36 insertions(+), 31 deletions(-) diff --git a/src/AddThreepid.ts b/src/AddThreepid.ts index b6335059cf..9be733824c 100644 --- a/src/AddThreepid.ts +++ b/src/AddThreepid.ts @@ -58,7 +58,7 @@ export type Binding = { * https://gist.github.com/jryans/839a09bf0c5a70e2f36ed990d50ed928 */ export default class AddThreepid { - private sessionId: string; + private sessionId?: string; private submitUrl?: string; private bind = false; private readonly clientSecret: string; @@ -202,7 +202,7 @@ export default class AddThreepid { throw new UserFriendlyError("No identity access token found"); } await this.matrixClient.bindThreePid({ - sid: this.sessionId, + sid: this.sessionId!, client_secret: this.clientSecret, id_server: getIdServerDomain(this.matrixClient), id_access_token: identityAccessToken, @@ -278,7 +278,7 @@ export default class AddThreepid { */ private makeAddThreepidOnlyRequest = (auth?: IAddThreePidOnlyBody["auth"] | null): Promise<{}> => { return this.matrixClient.addThreePidOnly({ - sid: this.sessionId, + sid: this.sessionId!, client_secret: this.clientSecret, auth: auth ?? undefined, }); @@ -302,13 +302,13 @@ export default class AddThreepid { if (this.submitUrl) { result = await this.matrixClient.submitMsisdnTokenOtherUrl( this.submitUrl, - this.sessionId, + this.sessionId!, this.clientSecret, msisdnToken, ); } else if (this.bind || !supportsSeparateAddAndBind) { result = await this.matrixClient.submitMsisdnToken( - this.sessionId, + this.sessionId!, this.clientSecret, msisdnToken, await authClient.getAccessToken(), @@ -323,7 +323,7 @@ export default class AddThreepid { if (supportsSeparateAddAndBind) { if (this.bind) { await this.matrixClient.bindThreePid({ - sid: this.sessionId, + sid: this.sessionId!, client_secret: this.clientSecret, id_server: getIdServerDomain(this.matrixClient), id_access_token: await authClient.getAccessToken(), diff --git a/src/Modal.tsx b/src/Modal.tsx index d78758685b..bf9564b5f0 100644 --- a/src/Modal.tsx +++ b/src/Modal.tsx @@ -29,9 +29,11 @@ const DIALOG_CONTAINER_ID = "mx_Dialog_Container"; const STATIC_DIALOG_CONTAINER_ID = "mx_Dialog_StaticContainer"; // Type which accepts a React Component which looks like a Modal (accepts an onFinished prop) -export type ComponentType = React.ComponentType<{ - onFinished(...args: any): void; -}>; +export type ComponentType = + | React.ComponentType<{ + onFinished(...args: any): void; + }> + | React.ComponentType; // Generic type which returns the props of the Modal component with the onFinished being optional. export type ComponentProps = Defaultize< diff --git a/src/NodeAnimator.tsx b/src/NodeAnimator.tsx index 2a496fa4b2..ec0602b3b5 100644 --- a/src/NodeAnimator.tsx +++ b/src/NodeAnimator.tsx @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import React, { Key, ReactElement, ReactInstance } from "react"; +import React, { Key, ReactElement, ReactFragment, ReactInstance, ReactPortal } from "react"; import ReactDom from "react-dom"; interface IChildProps { @@ -33,6 +33,10 @@ interface IProps { startStyles: React.CSSProperties[]; } +function isReactElement(c: ReactElement | ReactFragment | ReactPortal): c is ReactElement { + return typeof c === "object" && "type" in c; +} + /** * The NodeAnimator contains components and animates transitions. * It will only pick up direct changes to properties ('left', currently), and so @@ -72,7 +76,8 @@ export default class NodeAnimator extends React.Component { private updateChildren(newChildren: React.ReactNode): void { const oldChildren = this.children || {}; this.children = {}; - React.Children.toArray(newChildren).forEach((c: ReactElement) => { + React.Children.toArray(newChildren).forEach((c) => { + if (!isReactElement(c)) return; if (oldChildren[c.key!]) { const old = oldChildren[c.key!]; const oldNode = ReactDom.findDOMNode(this.nodes[old.key!]); diff --git a/src/SecurityManager.ts b/src/SecurityManager.ts index 52c5a8f852..0e71076991 100644 --- a/src/SecurityManager.ts +++ b/src/SecurityManager.ts @@ -14,13 +14,12 @@ See the License for the specific language governing permissions and limitations under the License. */ -import { ICryptoCallbacks } from "matrix-js-sdk/src/matrix"; +import { DeviceVerificationStatus, ICryptoCallbacks } from "matrix-js-sdk/src/matrix"; import { ISecretStorageKeyInfo } from "matrix-js-sdk/src/crypto/api"; import { MatrixClient } from "matrix-js-sdk/src/client"; import { deriveKey } from "matrix-js-sdk/src/crypto/key_passphrase"; import { decodeRecoveryKey } from "matrix-js-sdk/src/crypto/recoverykey"; import { encodeBase64 } from "matrix-js-sdk/src/crypto/olmlib"; -import { DeviceTrustLevel } from "matrix-js-sdk/src/crypto/CrossSigning"; import { logger } from "matrix-js-sdk/src/logger"; import type CreateSecretStorageDialog from "./async-components/views/dialogs/security/CreateSecretStorageDialog"; @@ -241,7 +240,7 @@ async function onSecretRequested( deviceId: string, requestId: string, name: string, - deviceTrust: DeviceTrustLevel, + deviceTrust: DeviceVerificationStatus, ): Promise { logger.log("onSecretRequested", userId, deviceId, requestId, name, deviceTrust); const client = MatrixClientPeg.safeGet(); diff --git a/src/SlashCommands.tsx b/src/SlashCommands.tsx index 71e39d1326..ce9d6cd187 100644 --- a/src/SlashCommands.tsx +++ b/src/SlashCommands.tsx @@ -81,8 +81,8 @@ const singleMxcUpload = async (cli: MatrixClient): Promise => { return new Promise((resolve) => { const fileSelector = document.createElement("input"); fileSelector.setAttribute("type", "file"); - fileSelector.onchange = (ev: HTMLInputEvent) => { - const file = ev.target.files?.[0]; + fileSelector.onchange = (ev: Event) => { + const file = (ev as HTMLInputEvent).target.files?.[0]; if (!file) return; Modal.createDialog(UploadConfirmDialog, { diff --git a/src/autocomplete/EmojiProvider.tsx b/src/autocomplete/EmojiProvider.tsx index bad4477768..b93973a2d4 100644 --- a/src/autocomplete/EmojiProvider.tsx +++ b/src/autocomplete/EmojiProvider.tsx @@ -47,9 +47,9 @@ interface ISortedEmoji { const SORTED_EMOJI: ISortedEmoji[] = EMOJI.sort((a, b) => { if (a.group === b.group) { - return a.order - b.order; + return a.order! - b.order!; } - return a.group - b.group; + return a.group! - b.group!; }).map((emoji, index) => ({ emoji, // Include the index so that we can preserve the original order diff --git a/src/emoji.ts b/src/emoji.ts index 12f136fbcf..faebd299e5 100644 --- a/src/emoji.ts +++ b/src/emoji.ts @@ -16,17 +16,11 @@ limitations under the License. import EMOJIBASE from "emojibase-data/en/compact.json"; import SHORTCODES from "emojibase-data/en/shortcodes/iamcal.json"; +import { CompactEmoji } from "emojibase"; -export interface IEmoji { - label: string; - group: number; - hexcode: string; - order: number; +export interface IEmoji extends Omit { + // We generate a shortcode based on the label if none exist in the dataset shortcodes: string[]; - tags?: string[]; - unicode: string; - skins?: Omit[]; // Currently unused - emoticon?: string | string[]; } // The unicode is stored without the variant selector @@ -74,7 +68,7 @@ export const DATA_BY_CATEGORY: Record = { }; // Store various mappings from unicode/emoticon/shortcode to the Emoji objects -export const EMOJI: IEmoji[] = EMOJIBASE.map((emojiData: Omit) => { +export const EMOJI: IEmoji[] = EMOJIBASE.map((emojiData) => { // If there's ever a gap in shortcode coverage, we fudge it by // filling it in with the emoji's CLDR annotation const shortcodeData = SHORTCODES[emojiData.hexcode] ?? [emojiData.label.toLowerCase().replace(/\W+/g, "_")]; @@ -88,7 +82,7 @@ export const EMOJI: IEmoji[] = EMOJIBASE.map((emojiData: Omit; private constructor() {