From f1534fda79bc255389db097597a8ce9b0577abb1 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 12 Jul 2023 15:56:51 +0100 Subject: [PATCH] Improve types (#11239) --- src/AddThreepid.ts | 4 ++-- src/PosthogAnalytics.ts | 20 +++++-------------- .../structures/auth/ForgotPassword.tsx | 7 +++++-- .../auth/forgot-password/EnterEmail.tsx | 2 +- .../views/dialogs/DeactivateAccountDialog.tsx | 4 ++-- .../views/dialogs/devtools/RoomState.tsx | 2 +- .../views/messages/DownloadActionButton.tsx | 11 +++++----- .../views/messages/MessageActionBar.tsx | 12 +++++------ src/components/views/rooms/EventTile.tsx | 1 + .../views/settings/JoinRuleSettings.tsx | 2 +- src/hooks/useLocalEcho.ts | 8 ++++---- src/utils/dm/startDm.ts | 4 ++-- 12 files changed, 35 insertions(+), 42 deletions(-) diff --git a/src/AddThreepid.ts b/src/AddThreepid.ts index e115441f5c..a1567d2256 100644 --- a/src/AddThreepid.ts +++ b/src/AddThreepid.ts @@ -256,7 +256,7 @@ export default class AddThreepid { } else { await this.matrixClient.addThreePid( { - sid: this.sessionId, + sid: this.sessionId!, client_secret: this.clientSecret, id_server: getIdServerDomain(this.matrixClient), }, @@ -377,7 +377,7 @@ export default class AddThreepid { } else { await this.matrixClient.addThreePid( { - sid: this.sessionId, + sid: this.sessionId!, client_secret: this.clientSecret, id_server: getIdServerDomain(this.matrixClient), }, diff --git a/src/PosthogAnalytics.ts b/src/PosthogAnalytics.ts index dc4e483781..5924c0a768 100644 --- a/src/PosthogAnalytics.ts +++ b/src/PosthogAnalytics.ts @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import posthog, { PostHog, Properties } from "posthog-js"; +import posthog, { CaptureOptions, PostHog, Properties } from "posthog-js"; import { MatrixClient } from "matrix-js-sdk/src/client"; import { logger } from "matrix-js-sdk/src/logger"; import { UserProperties } from "@matrix-org/analytics-events/types/typescript/UserProperties"; @@ -56,10 +56,6 @@ export interface IPosthogEvent { $set_once?: void; } -export interface IPostHogEventOptions { - timestamp?: Date; -} - export enum Anonymity { Disabled, Anonymous, @@ -256,19 +252,13 @@ export class PosthogAnalytics { } // eslint-disable-nextline no-unused-vars - private capture(eventName: string, properties: Properties, options?: IPostHogEventOptions): void { + private capture(eventName: string, properties: Properties, options?: CaptureOptions): void { if (!this.enabled) { return; } const { origin, hash, pathname } = window.location; properties["redactedCurrentUrl"] = getRedactedCurrentLocation(origin, hash, pathname); - this.posthog.capture( - eventName, - { ...this.propertiesForNextEvent, ...properties }, - // TODO: Uncomment below once https://github.com/PostHog/posthog-js/pull/391 - // gets merged - /* options as any, */ // No proper type definition in the posthog library - ); + this.posthog.capture(eventName, { ...this.propertiesForNextEvent, ...properties }, options); this.propertiesForNextEvent = {}; } @@ -342,7 +332,7 @@ export class PosthogAnalytics { this.setAnonymity(Anonymity.Disabled); } - public trackEvent({ eventName, ...properties }: E, options?: IPostHogEventOptions): void { + public trackEvent({ eventName, ...properties }: E, options?: CaptureOptions): void { if (this.anonymity == Anonymity.Disabled || this.anonymity == Anonymity.Anonymous) return; this.capture(eventName, properties, options); } @@ -420,7 +410,7 @@ export class PosthogAnalytics { // that we want to accumulate before the user has given consent // All other scenarios should not track a user before they have given // explicit consent that they are ok with their analytics data being collected - const options: IPostHogEventOptions = {}; + const options: CaptureOptions = {}; const registrationTime = parseInt(window.localStorage.getItem("mx_registration_time")!, 10); if (!isNaN(registrationTime)) { options.timestamp = new Date(registrationTime); diff --git a/src/components/structures/auth/ForgotPassword.tsx b/src/components/structures/auth/ForgotPassword.tsx index c4c0834987..311fb373db 100644 --- a/src/components/structures/auth/ForgotPassword.tsx +++ b/src/components/structures/auth/ForgotPassword.tsx @@ -345,12 +345,15 @@ export default class ForgotPassword extends React.Component { } }; - private onInputChanged = (stateKey: string, ev: React.FormEvent): void => { + private onInputChanged = ( + stateKey: "email" | "password" | "password2", + ev: React.FormEvent, + ): void => { let value = ev.currentTarget.value; if (stateKey === "email") value = value.trim(); this.setState({ [stateKey]: value, - } as any); + } as Pick); }; public renderEnterEmail(): JSX.Element { diff --git a/src/components/structures/auth/forgot-password/EnterEmail.tsx b/src/components/structures/auth/forgot-password/EnterEmail.tsx index 653aaef233..7b82121216 100644 --- a/src/components/structures/auth/forgot-password/EnterEmail.tsx +++ b/src/components/structures/auth/forgot-password/EnterEmail.tsx @@ -29,7 +29,7 @@ interface EnterEmailProps { errorText: string | ReactNode | null; homeserver: string; loading: boolean; - onInputChanged: (stateKey: string, ev: React.FormEvent) => void; + onInputChanged: (stateKey: "email", ev: React.FormEvent) => void; onLoginClick: () => void; onSubmitForm: (ev: React.FormEvent) => void; } diff --git a/src/components/views/dialogs/DeactivateAccountDialog.tsx b/src/components/views/dialogs/DeactivateAccountDialog.tsx index d59f42109d..c53ff765f0 100644 --- a/src/components/views/dialogs/DeactivateAccountDialog.tsx +++ b/src/components/views/dialogs/DeactivateAccountDialog.tsx @@ -130,7 +130,7 @@ export default class DeactivateAccountDialog extends React.Component { // Deactivation worked - logout & close this dialog defaultDispatcher.fire(Action.TriggerLogout); @@ -163,7 +163,7 @@ export default class DeactivateAccountDialog extends React.Component { // If we got here, oops. The server didn't require any auth. // Our application lifecycle will catch the error and do the logout bits. diff --git a/src/components/views/dialogs/devtools/RoomState.tsx b/src/components/views/dialogs/devtools/RoomState.tsx index 3c6ac3a935..b83d977248 100644 --- a/src/components/views/dialogs/devtools/RoomState.tsx +++ b/src/components/views/dialogs/devtools/RoomState.tsx @@ -37,7 +37,7 @@ export const StateEventEditor: React.FC = ({ mxEvent, onBack }) => [mxEvent], ); - const onSend = async ([eventType, stateKey]: string[], content?: IContent): Promise => { + const onSend = async ([eventType, stateKey]: string[], content: IContent): Promise => { await cli.sendStateEvent(context.room.roomId, eventType, content, stateKey); }; diff --git a/src/components/views/messages/DownloadActionButton.tsx b/src/components/views/messages/DownloadActionButton.tsx index d1d416d7e3..8e974c1e15 100644 --- a/src/components/views/messages/DownloadActionButton.tsx +++ b/src/components/views/messages/DownloadActionButton.tsx @@ -31,7 +31,7 @@ interface IProps { // XXX: It can take a cycle or two for the MessageActionBar to have all the props/setup // required to get us a MediaEventHelper, so we use a getter function instead to prod for // one. - mediaEventHelperGet: () => MediaEventHelper; + mediaEventHelperGet: () => MediaEventHelper | undefined; } interface IState { @@ -53,9 +53,10 @@ export default class DownloadActionButton extends React.PureComponent => { - if (this.state.loading) return; + const mediaEventHelper = this.props.mediaEventHelperGet(); + if (this.state.loading || !mediaEventHelper) return; - if (this.props.mediaEventHelperGet().media.isEncrypted) { + if (mediaEventHelper.media.isEncrypted) { this.setState({ tooltip: _td("Decrypting") }); } @@ -66,7 +67,7 @@ export default class DownloadActionButton extends React.PureComponent { await this.downloader.download({ blob, - name: this.props.mediaEventHelperGet().fileName, + name: this.props.mediaEventHelperGet()!.fileName, }); this.setState({ loading: false }); } diff --git a/src/components/views/messages/MessageActionBar.tsx b/src/components/views/messages/MessageActionBar.tsx index e792a47221..5bf600c02e 100644 --- a/src/components/views/messages/MessageActionBar.tsx +++ b/src/components/views/messages/MessageActionBar.tsx @@ -53,14 +53,13 @@ import { Key } from "../../../Keyboard"; import { ALTERNATE_KEY_NAME } from "../../../accessibility/KeyboardShortcuts"; import { Action } from "../../../dispatcher/actions"; import { ShowThreadPayload } from "../../../dispatcher/payloads/ShowThreadPayload"; -import { GetRelationsForEvent } from "../rooms/EventTile"; +import { GetRelationsForEvent, IEventTileType } from "../rooms/EventTile"; import { VoiceBroadcastInfoEventType } from "../../../voice-broadcast/types"; import { ButtonEvent } from "../elements/AccessibleButton"; interface IOptionsButtonProps { mxEvent: MatrixEvent; - // TODO: Types - getTile: () => any | null; + getTile: () => IEventTileType | null; getReplyChain: () => ReplyChain | null; permalinkCreator?: RoomPermalinkCreator; onFocusChange: (menuDisplayed: boolean) => void; @@ -97,7 +96,7 @@ const OptionsButton: React.FC = ({ let contextMenu: ReactElement | undefined; if (menuDisplayed && button.current) { - const tile = getTile && getTile(); + const tile = getTile?.(); const replyChain = getReplyChain(); const buttonRect = button.current.getBoundingClientRect(); @@ -254,8 +253,7 @@ const ReplyInThreadButton: React.FC = ({ mxEvent }) => { interface IMessageActionBarProps { mxEvent: MatrixEvent; reactions?: Relations | null | undefined; - // TODO: Types - getTile: () => any | null; + getTile: () => IEventTileType | null; getReplyChain: () => ReplyChain | null; permalinkCreator?: RoomPermalinkCreator; onFocusChange?: (menuDisplayed: boolean) => void; @@ -487,7 +485,7 @@ export default class MessageActionBar extends React.PureComponent this.props.getTile?.().getMediaHelper?.()} + mediaEventHelperGet={() => this.props.getTile()?.getMediaHelper?.()} key="download" />, ); diff --git a/src/components/views/rooms/EventTile.tsx b/src/components/views/rooms/EventTile.tsx index 17aa6f92a8..f750cd5510 100644 --- a/src/components/views/rooms/EventTile.tsx +++ b/src/components/views/rooms/EventTile.tsx @@ -107,6 +107,7 @@ export interface IEventTileOps { export interface IEventTileType extends React.Component { getEventTileOps?(): IEventTileOps; + getMediaHelper(): MediaEventHelper | undefined; } export interface EventTileProps { diff --git a/src/components/views/settings/JoinRuleSettings.tsx b/src/components/views/settings/JoinRuleSettings.tsx index 864529e6b2..4cdefc8e5c 100644 --- a/src/components/views/settings/JoinRuleSettings.tsx +++ b/src/components/views/settings/JoinRuleSettings.tsx @@ -61,7 +61,7 @@ const JoinRuleSettings: React.FC = ({ const disabled = !room.currentState.mayClientSendStateEvent(EventType.RoomJoinRules, cli); - const [content, setContent] = useLocalEcho( + const [content, setContent] = useLocalEcho( () => room.currentState.getStateEvents(EventType.RoomJoinRules, "")?.getContent(), (content) => cli.sendStateEvent(room.roomId, EventType.RoomJoinRules, content, ""), onError, diff --git a/src/hooks/useLocalEcho.ts b/src/hooks/useLocalEcho.ts index e1374c82c5..6305d56088 100644 --- a/src/hooks/useLocalEcho.ts +++ b/src/hooks/useLocalEcho.ts @@ -16,13 +16,13 @@ limitations under the License. import { useState } from "react"; -export const useLocalEcho = ( +export const useLocalEcho = ( currentFactory: () => T, - setterFn: (value: T) => Promise, + setterFn: (value: V) => Promise, errorFn: (error: unknown) => void, -): [value: T, handler: (value: T) => void] => { +): [value: T, handler: (value: V) => void] => { const [value, setValue] = useState(currentFactory); - const handler = async (value: T): Promise => { + const handler = async (value: V): Promise => { setValue(value); try { await setterFn(value); diff --git a/src/utils/dm/startDm.ts b/src/utils/dm/startDm.ts index f3731e117d..b69f449ef6 100644 --- a/src/utils/dm/startDm.ts +++ b/src/utils/dm/startDm.ts @@ -25,7 +25,7 @@ import { isLocalRoom } from "../localRoom/isLocalRoom"; import { findDMForUser } from "./findDMForUser"; import dis from "../../dispatcher/dispatcher"; import { getAddressType } from "../../UserAddress"; -import createRoom from "../../createRoom"; +import createRoom, { IOpts } from "../../createRoom"; /** * Start a DM. @@ -53,7 +53,7 @@ export async function startDm(client: MatrixClient, targets: Member[], showSpinn return Promise.resolve(existingRoom.roomId); } - const createRoomOptions = { inlineErrors: true } as any; // XXX: Type out `createRoomOptions` + const createRoomOptions: IOpts = { inlineErrors: true }; if (await determineCreateRoomEncryptionOption(client, targets)) { createRoomOptions.encryption = true;