diff --git a/src/autocomplete/UserProvider.tsx b/src/autocomplete/UserProvider.tsx index 22bd307b47..3d4c542c48 100644 --- a/src/autocomplete/UserProvider.tsx +++ b/src/autocomplete/UserProvider.tsx @@ -74,7 +74,7 @@ export default class UserProvider extends AutocompleteProvider { private onRoomTimeline = ( ev: MatrixEvent, room: Room | undefined, - toStartOfTimeline: boolean, + toStartOfTimeline: boolean | undefined, removed: boolean, data: IRoomTimelineData, ): void => { diff --git a/src/components/structures/FilePanel.tsx b/src/components/structures/FilePanel.tsx index ab7dd8ba5d..49c7dfebae 100644 --- a/src/components/structures/FilePanel.tsx +++ b/src/components/structures/FilePanel.tsx @@ -67,7 +67,7 @@ class FilePanel extends React.Component { private onRoomTimeline = ( ev: MatrixEvent, room: Room | undefined, - toStartOfTimeline: boolean, + toStartOfTimeline: boolean | undefined, removed: boolean, data: IRoomTimelineData, ): void => { diff --git a/src/components/structures/MatrixChat.tsx b/src/components/structures/MatrixChat.tsx index 9932a102ef..4aea34870c 100644 --- a/src/components/structures/MatrixChat.tsx +++ b/src/components/structures/MatrixChat.tsx @@ -113,7 +113,7 @@ import { PosthogAnalytics } from "../../PosthogAnalytics"; import { initSentry } from "../../sentry"; import LegacyCallHandler from "../../LegacyCallHandler"; import { showSpaceInvite } from "../../utils/space"; -import AccessibleButton from "../views/elements/AccessibleButton"; +import AccessibleButton, { ButtonEvent } from "../views/elements/AccessibleButton"; import { ActionPayload } from "../../dispatcher/payloads"; import { SummarizedNotificationState } from "../../stores/notifications/SummarizedNotificationState"; import Views from "../../Views"; @@ -1874,7 +1874,7 @@ export default class MatrixChat extends React.PureComponent { this.setPageSubtitle(); } - private onLogoutClick(event: React.MouseEvent): void { + private onLogoutClick(event: ButtonEvent): void { dis.dispatch({ action: "logout", }); diff --git a/src/components/structures/RoomView.tsx b/src/components/structures/RoomView.tsx index c11892d22c..b4a38ee2eb 100644 --- a/src/components/structures/RoomView.tsx +++ b/src/components/structures/RoomView.tsx @@ -1461,7 +1461,7 @@ export class RoomView extends React.Component { this.updateRoomMembers(); }; - private onMyMembership = (room: Room, membership: string, oldMembership: string): void => { + private onMyMembership = (room: Room): void => { if (room.roomId === this.state.roomId) { this.forceUpdate(); this.loadMembersIfJoined(room); diff --git a/src/components/structures/TimelinePanel.tsx b/src/components/structures/TimelinePanel.tsx index 874d0b7a34..75f8fe0d4f 100644 --- a/src/components/structures/TimelinePanel.tsx +++ b/src/components/structures/TimelinePanel.tsx @@ -666,7 +666,7 @@ class TimelinePanel extends React.Component { private onRoomTimeline = ( ev: MatrixEvent, room: Room | undefined, - toStartOfTimeline: boolean, + toStartOfTimeline: boolean | undefined, removed: boolean, data: IRoomTimelineData, ): void => { @@ -769,7 +769,7 @@ class TimelinePanel extends React.Component { }); }; - private onRoomTimelineReset = (room: Room, timelineSet: EventTimelineSet): void => { + private onRoomTimelineReset = (room: Room | undefined, timelineSet: EventTimelineSet): void => { if (timelineSet !== this.props.timelineSet) return; if (this.canResetTimeline()) { @@ -873,7 +873,7 @@ class TimelinePanel extends React.Component { this.forceUpdate(); }; - private onLocalEchoUpdated = (ev: MatrixEvent, room: Room, oldEventId: string): void => { + private onLocalEchoUpdated = (ev: MatrixEvent, room: Room, oldEventId?: string): void => { if (this.unmounted) return; // ignore events for other rooms @@ -921,7 +921,7 @@ class TimelinePanel extends React.Component { this.forceUpdate(); }; - private onSync = (clientSyncState: SyncState, prevState: SyncState, data: object): void => { + private onSync = (clientSyncState: SyncState, prevState: SyncState | null, data?: object): void => { if (this.unmounted) return; this.setState({ clientSyncState }); }; diff --git a/src/components/structures/UserMenu.tsx b/src/components/structures/UserMenu.tsx index 609bcdf3e4..8a2d08f6cc 100644 --- a/src/components/structures/UserMenu.tsx +++ b/src/components/structures/UserMenu.tsx @@ -113,7 +113,7 @@ export default class UserMenu extends React.Component { return !!getHomePageUrl(SdkConfig.get()); } - private onCurrentVoiceBroadcastRecordingChanged = (recording: VoiceBroadcastRecording): void => { + private onCurrentVoiceBroadcastRecordingChanged = (recording: VoiceBroadcastRecording | null): void => { this.setState({ showLiveAvatarAddon: recording !== null, }); @@ -195,7 +195,7 @@ export default class UserMenu extends React.Component { } }; - private onOpenMenuClick = (ev: React.MouseEvent): void => { + private onOpenMenuClick = (ev: ButtonEvent): void => { ev.preventDefault(); ev.stopPropagation(); this.setState({ contextMenuPosition: ev.currentTarget.getBoundingClientRect() }); @@ -218,7 +218,7 @@ export default class UserMenu extends React.Component { this.setState({ contextMenuPosition: null }); }; - private onSwitchThemeClick = (ev: React.MouseEvent): void => { + private onSwitchThemeClick = (ev: ButtonEvent): void => { ev.preventDefault(); ev.stopPropagation(); diff --git a/src/components/structures/auth/SetupEncryptionBody.tsx b/src/components/structures/auth/SetupEncryptionBody.tsx index 2cbfbf8367..d94718ab60 100644 --- a/src/components/structures/auth/SetupEncryptionBody.tsx +++ b/src/components/structures/auth/SetupEncryptionBody.tsx @@ -26,7 +26,7 @@ import Modal from "../../../Modal"; import VerificationRequestDialog from "../../views/dialogs/VerificationRequestDialog"; import { SetupEncryptionStore, Phase } from "../../../stores/SetupEncryptionStore"; import EncryptionPanel from "../../views/right_panel/EncryptionPanel"; -import AccessibleButton from "../../views/elements/AccessibleButton"; +import AccessibleButton, { ButtonEvent } from "../../views/elements/AccessibleButton"; import Spinner from "../../views/elements/Spinner"; function keyHasPassphrase(keyInfo: ISecretStorageKeyInfo): boolean { @@ -115,7 +115,7 @@ export default class SetupEncryptionBody extends React.Component store.returnAfterSkip(); }; - private onResetClick = (ev: React.MouseEvent): void => { + private onResetClick = (ev: ButtonEvent): void => { ev.preventDefault(); const store = SetupEncryptionStore.sharedInstance(); store.reset(); diff --git a/src/components/views/auth/InteractiveAuthEntryComponents.tsx b/src/components/views/auth/InteractiveAuthEntryComponents.tsx index 8431bfc01c..cefdecab5e 100644 --- a/src/components/views/auth/InteractiveAuthEntryComponents.tsx +++ b/src/components/views/auth/InteractiveAuthEntryComponents.tsx @@ -18,14 +18,14 @@ import classNames from "classnames"; import { MatrixClient } from "matrix-js-sdk/src/client"; import { AuthType, IAuthDict, IInputs, IStageStatus } from "matrix-js-sdk/src/interactive-auth"; import { logger } from "matrix-js-sdk/src/logger"; -import React, { ChangeEvent, createRef, FormEvent, Fragment, MouseEvent } from "react"; +import React, { ChangeEvent, createRef, FormEvent, Fragment } from "react"; import EmailPromptIcon from "../../../../res/img/element-icons/email-prompt.svg"; import { _t } from "../../../languageHandler"; import SettingsStore from "../../../settings/SettingsStore"; import { LocalisedPolicy, Policies } from "../../../Terms"; import { AuthHeaderModifier } from "../../structures/auth/header/AuthHeaderModifier"; -import AccessibleButton from "../elements/AccessibleButton"; +import AccessibleButton, { ButtonEvent } from "../elements/AccessibleButton"; import AccessibleTooltipButton from "../elements/AccessibleTooltipButton"; import Field from "../elements/Field"; import Spinner from "../elements/Spinner"; @@ -943,7 +943,7 @@ export class FallbackAuthEntry extends React.Component { this.fallbackButton.current?.focus(); }; - private onShowFallbackClick = (e: MouseEvent): void => { + private onShowFallbackClick = (e: ButtonEvent): void => { if (!this.props.authSessionId) return; e.preventDefault(); diff --git a/src/components/views/avatars/BaseAvatar.tsx b/src/components/views/avatars/BaseAvatar.tsx index 5e9356d09e..277eb673e8 100644 --- a/src/components/views/avatars/BaseAvatar.tsx +++ b/src/components/views/avatars/BaseAvatar.tsx @@ -24,7 +24,7 @@ import { ClientEvent } from "matrix-js-sdk/src/client"; import * as AvatarLogic from "../../../Avatar"; import SettingsStore from "../../../settings/SettingsStore"; -import AccessibleButton from "../elements/AccessibleButton"; +import AccessibleButton, { ButtonEvent } from "../elements/AccessibleButton"; import RoomContext from "../../../contexts/RoomContext"; import MatrixClientContext from "../../../contexts/MatrixClientContext"; import { useTypedEventEmitter } from "../../../hooks/useEventEmitter"; @@ -42,7 +42,7 @@ interface IProps { // XXX: resizeMethod not actually used. resizeMethod?: ResizeMethod; defaultToInitialLetter?: boolean; // true to add default url - onClick?: React.MouseEventHandler; + onClick?: (ev: ButtonEvent) => void; inputRef?: React.RefObject; className?: string; tabIndex?: number; diff --git a/src/components/views/avatars/MemberAvatar.tsx b/src/components/views/avatars/MemberAvatar.tsx index a17f18926c..c1a19261e2 100644 --- a/src/components/views/avatars/MemberAvatar.tsx +++ b/src/components/views/avatars/MemberAvatar.tsx @@ -33,8 +33,6 @@ interface IProps extends Omit, "name" | width: number; height: number; resizeMethod?: ResizeMethod; - // The onClick to give the avatar - onClick?: React.MouseEventHandler; // Whether the onClick of the avatar should be overridden to dispatch `Action.ViewUser` viewUserOnClick?: boolean; pushUserOnClick?: boolean; diff --git a/src/components/views/dialogs/StorageEvictedDialog.tsx b/src/components/views/dialogs/StorageEvictedDialog.tsx index df27c4a31d..9c81b0192c 100644 --- a/src/components/views/dialogs/StorageEvictedDialog.tsx +++ b/src/components/views/dialogs/StorageEvictedDialog.tsx @@ -22,14 +22,14 @@ import { _t } from "../../../languageHandler"; import BaseDialog from "./BaseDialog"; import DialogButtons from "../elements/DialogButtons"; import BugReportDialog from "./BugReportDialog"; -import AccessibleButton from "../elements/AccessibleButton"; +import AccessibleButton, { ButtonEvent } from "../elements/AccessibleButton"; interface IProps { onFinished(signOut?: boolean): void; } export default class StorageEvictedDialog extends React.Component { - private sendBugReport = (ev: React.MouseEvent): void => { + private sendBugReport = (ev: ButtonEvent): void => { ev.preventDefault(); Modal.createDialog(BugReportDialog, {}); }; diff --git a/src/components/views/dialogs/security/AccessSecretStorageDialog.tsx b/src/components/views/dialogs/security/AccessSecretStorageDialog.tsx index 9cffc20241..682445833e 100644 --- a/src/components/views/dialogs/security/AccessSecretStorageDialog.tsx +++ b/src/components/views/dialogs/security/AccessSecretStorageDialog.tsx @@ -22,7 +22,7 @@ import { logger } from "matrix-js-sdk/src/logger"; import { MatrixClientPeg } from "../../../../MatrixClientPeg"; import Field from "../../elements/Field"; -import AccessibleButton from "../../elements/AccessibleButton"; +import AccessibleButton, { ButtonEvent } from "../../elements/AccessibleButton"; import { _t } from "../../../../languageHandler"; import { accessSecretStorage } from "../../../../SecurityManager"; import Modal from "../../../../Modal"; @@ -217,7 +217,7 @@ export default class AccessSecretStorageDialog extends React.PureComponent): void => { + private onResetAllClick = (ev: ButtonEvent): void => { ev.preventDefault(); this.setState({ resetting: true }); }; diff --git a/src/components/views/elements/AppTile.tsx b/src/components/views/elements/AppTile.tsx index 1fa1fba752..a90e01f317 100644 --- a/src/components/views/elements/AppTile.tsx +++ b/src/components/views/elements/AppTile.tsx @@ -106,7 +106,7 @@ interface IState { export default class AppTile extends React.Component { public static contextType = MatrixClientContext; - public context: ContextType; + public context!: ContextType; public static defaultProps: Partial = { waitForIframeLoad: true, diff --git a/src/components/views/elements/PersistentApp.tsx b/src/components/views/elements/PersistentApp.tsx index a13588b96b..d6ed5d6bf8 100644 --- a/src/components/views/elements/PersistentApp.tsx +++ b/src/components/views/elements/PersistentApp.tsx @@ -32,7 +32,7 @@ interface IProps { export default class PersistentApp extends React.Component { public static contextType = MatrixClientContext; - public context: ContextType; + public context!: ContextType; private room: Room; public constructor(props: IProps, context: ContextType) { diff --git a/src/components/views/messages/MBeaconBody.tsx b/src/components/views/messages/MBeaconBody.tsx index 25327df74e..20cfaf1411 100644 --- a/src/components/views/messages/MBeaconBody.tsx +++ b/src/components/views/messages/MBeaconBody.tsx @@ -131,7 +131,7 @@ const useHandleBeaconRedaction = ( }, [event, onBeforeBeaconInfoRedaction]); }; -const MBeaconBody: React.FC = React.forwardRef(({ mxEvent, getRelationsForEvent }, ref) => { +const MBeaconBody = React.forwardRef(({ mxEvent, getRelationsForEvent }, ref) => { const { beacon, isLive, latestLocationState, waitingToStart } = useBeaconState(mxEvent); const mapId = useUniqueId(mxEvent.getId()!); diff --git a/src/components/views/messages/MessageActionBar.tsx b/src/components/views/messages/MessageActionBar.tsx index 78d001ae95..f94bdf5f16 100644 --- a/src/components/views/messages/MessageActionBar.tsx +++ b/src/components/views/messages/MessageActionBar.tsx @@ -58,6 +58,7 @@ import { ShowThreadPayload } from "../../../dispatcher/payloads/ShowThreadPayloa import useFavouriteMessages from "../../../hooks/useFavouriteMessages"; import { GetRelationsForEvent } from "../rooms/EventTile"; import { VoiceBroadcastInfoEventType } from "../../../voice-broadcast/types"; +import { ButtonEvent } from "../elements/AccessibleButton"; interface IOptionsButtonProps { mxEvent: MatrixEvent; @@ -84,7 +85,7 @@ const OptionsButton: React.FC = ({ }, [onFocusChange, menuDisplayed]); const onOptionsClick = useCallback( - (e: React.MouseEvent): void => { + (e: ButtonEvent): void => { // Don't open the regular browser or our context menu on right-click e.preventDefault(); e.stopPropagation(); @@ -159,7 +160,7 @@ const ReactButton: React.FC = ({ mxEvent, reactions, onFocusC } const onClick = useCallback( - (e: React.MouseEvent) => { + (e: ButtonEvent) => { // Don't open the regular browser or our context menu on right-click e.preventDefault(); e.stopPropagation(); @@ -203,7 +204,7 @@ const ReplyInThreadButton: React.FC = ({ mxEvent }) => { const relationType = mxEvent?.getRelation()?.rel_type; const hasARelation = !!relationType && relationType !== RelationType.Thread; - const onClick = (e: React.MouseEvent): void => { + const onClick = (e: ButtonEvent): void => { // Don't open the regular browser or our context menu on right-click e.preventDefault(); e.stopPropagation(); @@ -266,7 +267,7 @@ const FavouriteButton: React.FC = ({ mxEvent }) => { }); const onClick = useCallback( - (e: React.MouseEvent) => { + (e: ButtonEvent) => { // Don't open the regular browser or our context menu on right-click e.preventDefault(); e.stopPropagation(); @@ -345,7 +346,7 @@ export default class MessageActionBar extends React.PureComponent { + private onReplyClick = (e: ButtonEvent): void => { // Don't open the regular browser or our context menu on right-click e.preventDefault(); e.stopPropagation(); @@ -357,7 +358,7 @@ export default class MessageActionBar extends React.PureComponent { + private onEditClick = (e: ButtonEvent): void => { // Don't open the regular browser or our context menu on right-click e.preventDefault(); e.stopPropagation(); @@ -406,7 +407,7 @@ export default class MessageActionBar extends React.PureComponent { + private onResendClick = (ev: ButtonEvent): void => { // Don't open the regular browser or our context menu on right-click ev.preventDefault(); ev.stopPropagation(); @@ -414,7 +415,7 @@ export default class MessageActionBar extends React.PureComponent Resend.resend(tarEv)); }; - private onCancelClick = (ev: React.MouseEvent): void => { + private onCancelClick = (ev: ButtonEvent): void => { this.runActionOnFailedEv( (tarEv) => Resend.removeFromQueue(tarEv), (testEv) => canCancel(testEv.status), diff --git a/src/components/views/messages/UnknownBody.tsx b/src/components/views/messages/UnknownBody.tsx index 419ec5971e..ec32449e92 100644 --- a/src/components/views/messages/UnknownBody.tsx +++ b/src/components/views/messages/UnknownBody.tsx @@ -23,7 +23,7 @@ interface IProps { children?: React.ReactNode; } -export default forwardRef(({ mxEvent, children }: IProps, ref: React.RefObject) => { +export default forwardRef(({ mxEvent, children }, ref) => { const text = mxEvent.getContent().body; return (
diff --git a/src/components/views/messages/ViewSourceEvent.tsx b/src/components/views/messages/ViewSourceEvent.tsx index 344ddd344e..1d33074a7a 100644 --- a/src/components/views/messages/ViewSourceEvent.tsx +++ b/src/components/views/messages/ViewSourceEvent.tsx @@ -20,7 +20,7 @@ import classNames from "classnames"; import { MatrixClientPeg } from "../../../MatrixClientPeg"; import { _t } from "../../../languageHandler"; -import AccessibleButton from "../elements/AccessibleButton"; +import AccessibleButton, { ButtonEvent } from "../elements/AccessibleButton"; interface IProps { mxEvent: MatrixEvent; @@ -50,7 +50,7 @@ export default class ViewSourceEvent extends React.PureComponent } } - private onToggle = (ev: React.MouseEvent): void => { + private onToggle = (ev: ButtonEvent): void => { ev.preventDefault(); const { expanded } = this.state; this.setState({ diff --git a/src/components/views/room_settings/AliasSettings.tsx b/src/components/views/room_settings/AliasSettings.tsx index f6a6f32e4f..ab92feca76 100644 --- a/src/components/views/room_settings/AliasSettings.tsx +++ b/src/components/views/room_settings/AliasSettings.tsx @@ -102,7 +102,7 @@ interface IState { export default class AliasSettings extends React.Component { public static contextType = MatrixClientContext; - public context: ContextType; + public context!: ContextType; public static defaultProps = { canSetAliases: false, diff --git a/src/components/views/room_settings/RoomProfileSettings.tsx b/src/components/views/room_settings/RoomProfileSettings.tsx index 573a1f6933..7117608f39 100644 --- a/src/components/views/room_settings/RoomProfileSettings.tsx +++ b/src/components/views/room_settings/RoomProfileSettings.tsx @@ -22,7 +22,7 @@ import { _t } from "../../../languageHandler"; import { MatrixClientPeg } from "../../../MatrixClientPeg"; import Field from "../elements/Field"; import { mediaFromMxc } from "../../../customisations/Media"; -import AccessibleButton from "../elements/AccessibleButton"; +import AccessibleButton, { ButtonEvent } from "../elements/AccessibleButton"; import AvatarSetting from "../settings/AvatarSetting"; import { htmlSerializeFromMdIfNeeded } from "../../../editor/serialize"; import { chromeFileInputFix } from "../../../utils/BrowserWorkarounds"; @@ -103,7 +103,7 @@ export default class RoomProfileSettings extends React.Component return Boolean(Object.values(this.state.profileFieldsTouched).length); }; - private cancelProfileChanges = async (e: React.MouseEvent): Promise => { + private cancelProfileChanges = async (e: ButtonEvent): Promise => { e.stopPropagation(); e.preventDefault(); diff --git a/src/components/views/rooms/EventTile.tsx b/src/components/views/rooms/EventTile.tsx index 13a8e6b006..07015fee72 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, { createRef, forwardRef, MouseEvent, ReactNode, RefObject, useRef } from "react"; +import React, { createRef, forwardRef, MouseEvent, ReactNode, useRef } from "react"; import classNames from "classnames"; import { EventType, MsgType, RelationType } from "matrix-js-sdk/src/@types/event"; import { EventStatus, MatrixEvent, MatrixEventEvent } from "matrix-js-sdk/src/models/event"; @@ -1437,7 +1437,7 @@ export class UnwrappedEventTile extends React.Component } // Wrap all event tiles with the tile error boundary so that any throws even during construction are captured -const SafeEventTile = forwardRef((props: EventTileProps, ref: RefObject) => { +const SafeEventTile = forwardRef((props, ref) => { return ( <> diff --git a/src/components/views/rooms/JumpToBottomButton.tsx b/src/components/views/rooms/JumpToBottomButton.tsx index a732d2cc32..bbff1d9605 100644 --- a/src/components/views/rooms/JumpToBottomButton.tsx +++ b/src/components/views/rooms/JumpToBottomButton.tsx @@ -18,12 +18,12 @@ import React from "react"; import classNames from "classnames"; import { _t } from "../../../languageHandler"; -import AccessibleButton from "../elements/AccessibleButton"; +import AccessibleButton, { ButtonEvent } from "../elements/AccessibleButton"; interface IProps { numUnreadMessages?: number; highlight: boolean; - onScrollToBottomClick: (e: React.MouseEvent) => void; + onScrollToBottomClick: (e: ButtonEvent) => void; } const JumpToBottomButton: React.FC = (props) => { diff --git a/src/components/views/rooms/MemberList.tsx b/src/components/views/rooms/MemberList.tsx index 44dba2e32b..bcc4c4fb97 100644 --- a/src/components/views/rooms/MemberList.tsx +++ b/src/components/views/rooms/MemberList.tsx @@ -142,7 +142,7 @@ export default class MemberList extends React.Component { }; } - private onUserPresenceChange = (event: MatrixEvent, user: User): void => { + private onUserPresenceChange = (event: MatrixEvent | undefined, user: User): void => { // Attach a SINGLE listener for global presence changes then locate the // member tile and re-render it. This is more efficient than every tile // ever attaching their own listener. @@ -162,7 +162,7 @@ export default class MemberList extends React.Component { this.updateListNow(true); }; - private onMyMembership = (room: Room, membership: string, oldMembership: string): void => { + private onMyMembership = (room: Room, membership: string, oldMembership?: string): void => { if (room.roomId === this.props.roomId && membership === "join" && oldMembership !== "join") { // we just joined the room, load the member list this.updateListNow(true); diff --git a/src/components/views/rooms/MessageComposerButtons.tsx b/src/components/views/rooms/MessageComposerButtons.tsx index 81491d35c2..bfd9906e7e 100644 --- a/src/components/views/rooms/MessageComposerButtons.tsx +++ b/src/components/views/rooms/MessageComposerButtons.tsx @@ -17,7 +17,7 @@ limitations under the License. import classNames from "classnames"; import { IEventRelation } from "matrix-js-sdk/src/models/event"; import { M_POLL_START } from "matrix-js-sdk/src/@types/polls"; -import React, { createContext, MouseEventHandler, ReactElement, ReactNode, useContext, useRef } from "react"; +import React, { createContext, ReactElement, ReactNode, useContext, useRef } from "react"; import { Room } from "matrix-js-sdk/src/models/room"; import { MatrixClient } from "matrix-js-sdk/src/client"; import { THREAD_RELATION_TYPE } from "matrix-js-sdk/src/models/thread"; @@ -40,6 +40,7 @@ import { chromeFileInputFix } from "../../../utils/BrowserWorkarounds"; import IconizedContextMenu, { IconizedContextMenuOptionList } from "../context_menus/IconizedContextMenu"; import { EmojiButton } from "./EmojiButton"; import { useSettingValue } from "../../../hooks/useSettings"; +import { ButtonEvent } from "../elements/AccessibleButton"; interface IProps { addEmoji: (emoji: string) => boolean; @@ -362,7 +363,7 @@ function showLocationButton(props: IProps, room: Room, matrixClient: MatrixClien interface WysiwygToggleButtonProps { isRichTextEnabled: boolean; - onClick: MouseEventHandler; + onClick: (ev: ButtonEvent) => void; } function ComposerModeButton({ isRichTextEnabled, onClick }: WysiwygToggleButtonProps): JSX.Element { diff --git a/src/components/views/rooms/NotificationBadge/StatelessNotificationBadge.tsx b/src/components/views/rooms/NotificationBadge/StatelessNotificationBadge.tsx index d6083507f0..1055ee07b2 100644 --- a/src/components/views/rooms/NotificationBadge/StatelessNotificationBadge.tsx +++ b/src/components/views/rooms/NotificationBadge/StatelessNotificationBadge.tsx @@ -18,7 +18,7 @@ import React, { MouseEvent, ReactNode } from "react"; import classNames from "classnames"; import { formatCount } from "../../../../utils/FormattingUtils"; -import AccessibleButton from "../../elements/AccessibleButton"; +import AccessibleButton, { ButtonEvent } from "../../elements/AccessibleButton"; import { NotificationColor } from "../../../../stores/notifications/NotificationColor"; import { useSettingValue } from "../../../../hooks/useSettings"; import { XOR } from "../../../../@types/common"; @@ -37,7 +37,7 @@ interface ClickableProps extends Props { /** * If specified will return an AccessibleButton instead of a div. */ - onClick(ev: React.MouseEvent): void; + onClick(ev: ButtonEvent): void; tabIndex?: number; } diff --git a/src/components/views/rooms/RoomSublist.tsx b/src/components/views/rooms/RoomSublist.tsx index c4b3efa3e6..ccb3c77f8e 100644 --- a/src/components/views/rooms/RoomSublist.tsx +++ b/src/components/views/rooms/RoomSublist.tsx @@ -48,7 +48,7 @@ import ContextMenu, { StyledMenuItemCheckbox, StyledMenuItemRadio, } from "../../structures/ContextMenu"; -import AccessibleButton from "../../views/elements/AccessibleButton"; +import AccessibleButton, { ButtonEvent } from "../../views/elements/AccessibleButton"; import AccessibleTooltipButton from "../elements/AccessibleTooltipButton"; import ExtraTile from "./ExtraTile"; import SettingsStore from "../../../settings/SettingsStore"; @@ -369,7 +369,7 @@ export default class RoomSublist extends React.Component { } }; - private onOpenMenuClick = (ev: React.MouseEvent): void => { + private onOpenMenuClick = (ev: ButtonEvent): void => { ev.preventDefault(); ev.stopPropagation(); const target = ev.target as HTMLButtonElement; diff --git a/src/components/views/rooms/RoomTile.tsx b/src/components/views/rooms/RoomTile.tsx index 58664951df..a5abb16a8f 100644 --- a/src/components/views/rooms/RoomTile.tsx +++ b/src/components/views/rooms/RoomTile.tsx @@ -220,11 +220,11 @@ export class RoomTile extends React.PureComponent { }); }; - private onTileClick = async (ev: React.KeyboardEvent): Promise => { + private onTileClick = async (ev: ButtonEvent): Promise => { ev.preventDefault(); ev.stopPropagation(); - const action = getKeyBindingsManager().getAccessibilityAction(ev); + const action = getKeyBindingsManager().getAccessibilityAction(ev as React.KeyboardEvent); const clearSearch = ([KeyBindingAction.Enter, KeyBindingAction.Space] as Array).includes( action, ); diff --git a/src/components/views/rooms/TopUnreadMessagesBar.tsx b/src/components/views/rooms/TopUnreadMessagesBar.tsx index 51e67e611b..ffead7d53a 100644 --- a/src/components/views/rooms/TopUnreadMessagesBar.tsx +++ b/src/components/views/rooms/TopUnreadMessagesBar.tsx @@ -17,11 +17,11 @@ limitations under the License. import React from "react"; import { _t } from "../../../languageHandler"; -import AccessibleButton from "../elements/AccessibleButton"; +import AccessibleButton, { ButtonEvent } from "../elements/AccessibleButton"; interface IProps { - onScrollUpClick: (e: React.MouseEvent) => void; - onCloseClick: (e: React.MouseEvent) => void; + onScrollUpClick: (e: ButtonEvent) => void; + onCloseClick: (e: ButtonEvent) => void; } export default class TopUnreadMessagesBar extends React.PureComponent { diff --git a/src/components/views/settings/ProfileSettings.tsx b/src/components/views/settings/ProfileSettings.tsx index d8ef992835..8f962ba38e 100644 --- a/src/components/views/settings/ProfileSettings.tsx +++ b/src/components/views/settings/ProfileSettings.tsx @@ -24,7 +24,7 @@ import { OwnProfileStore } from "../../../stores/OwnProfileStore"; import Modal from "../../../Modal"; import ErrorDialog from "../dialogs/ErrorDialog"; import { mediaFromMxc } from "../../../customisations/Media"; -import AccessibleButton from "../elements/AccessibleButton"; +import AccessibleButton, { ButtonEvent } from "../elements/AccessibleButton"; import AvatarSetting from "./AvatarSetting"; import UserIdentifierCustomisations from "../../../customisations/UserIdentifier"; import { chromeFileInputFix } from "../../../utils/BrowserWorkarounds"; @@ -75,7 +75,7 @@ export default class ProfileSettings extends React.Component<{}, IState> { }); }; - private cancelProfileChanges = async (e: React.MouseEvent): Promise => { + private cancelProfileChanges = async (e: ButtonEvent): Promise => { e.stopPropagation(); e.preventDefault(); @@ -88,7 +88,7 @@ export default class ProfileSettings extends React.Component<{}, IState> { }); }; - private saveProfile = async (e: React.FormEvent): Promise => { + private saveProfile = async (e: ButtonEvent): Promise => { e.stopPropagation(); e.preventDefault(); diff --git a/src/components/views/settings/account/EmailAddresses.tsx b/src/components/views/settings/account/EmailAddresses.tsx index 08e014c65b..3d72becf33 100644 --- a/src/components/views/settings/account/EmailAddresses.tsx +++ b/src/components/views/settings/account/EmailAddresses.tsx @@ -23,7 +23,7 @@ import { MatrixError } from "matrix-js-sdk/src/matrix"; import { _t, UserFriendlyError } from "../../../../languageHandler"; import { MatrixClientPeg } from "../../../../MatrixClientPeg"; import Field from "../../elements/Field"; -import AccessibleButton from "../../elements/AccessibleButton"; +import AccessibleButton, { ButtonEvent } from "../../elements/AccessibleButton"; import * as Email from "../../../../email"; import AddThreepid from "../../../../AddThreepid"; import Modal from "../../../../Modal"; @@ -59,21 +59,21 @@ export class ExistingEmailAddress extends React.Component { + private onRemove = (e: ButtonEvent): void => { e.stopPropagation(); e.preventDefault(); this.setState({ verifyRemove: true }); }; - private onDontRemove = (e: React.MouseEvent): void => { + private onDontRemove = (e: ButtonEvent): void => { e.stopPropagation(); e.preventDefault(); this.setState({ verifyRemove: false }); }; - private onActuallyRemove = (e: React.MouseEvent): void => { + private onActuallyRemove = (e: ButtonEvent): void => { e.stopPropagation(); e.preventDefault(); @@ -196,7 +196,7 @@ export default class EmailAddresses extends React.Component { }); }; - private onContinueClick = (e: React.MouseEvent): void => { + private onContinueClick = (e: ButtonEvent): void => { e.stopPropagation(); e.preventDefault(); diff --git a/src/components/views/settings/account/PhoneNumbers.tsx b/src/components/views/settings/account/PhoneNumbers.tsx index ede650642d..212148be6e 100644 --- a/src/components/views/settings/account/PhoneNumbers.tsx +++ b/src/components/views/settings/account/PhoneNumbers.tsx @@ -22,7 +22,7 @@ import { logger } from "matrix-js-sdk/src/logger"; import { _t, UserFriendlyError } from "../../../../languageHandler"; import { MatrixClientPeg } from "../../../../MatrixClientPeg"; import Field from "../../elements/Field"; -import AccessibleButton from "../../elements/AccessibleButton"; +import AccessibleButton, { ButtonEvent } from "../../elements/AccessibleButton"; import AddThreepid from "../../../../AddThreepid"; import CountryDropdown from "../../auth/CountryDropdown"; import Modal from "../../../../Modal"; @@ -54,21 +54,21 @@ export class ExistingPhoneNumber extends React.Component { + private onRemove = (e: ButtonEvent): void => { e.stopPropagation(); e.preventDefault(); this.setState({ verifyRemove: true }); }; - private onDontRemove = (e: React.MouseEvent): void => { + private onDontRemove = (e: ButtonEvent): void => { e.stopPropagation(); e.preventDefault(); this.setState({ verifyRemove: false }); }; - private onActuallyRemove = (e: React.MouseEvent): void => { + private onActuallyRemove = (e: ButtonEvent): void => { e.stopPropagation(); e.preventDefault(); @@ -173,7 +173,7 @@ export default class PhoneNumbers extends React.Component { }); }; - private onAddClick = (e: React.MouseEvent | React.FormEvent): void => { + private onAddClick = (e: ButtonEvent | React.FormEvent): void => { e.stopPropagation(); e.preventDefault(); @@ -199,7 +199,7 @@ export default class PhoneNumbers extends React.Component { }); }; - private onContinueClick = (e: React.MouseEvent | React.FormEvent): void => { + private onContinueClick = (e: ButtonEvent | React.FormEvent): void => { e.stopPropagation(); e.preventDefault(); diff --git a/src/components/views/settings/devices/DeviceDetailHeading.tsx b/src/components/views/settings/devices/DeviceDetailHeading.tsx index 8a0e054a63..a956316f8c 100644 --- a/src/components/views/settings/devices/DeviceDetailHeading.tsx +++ b/src/components/views/settings/devices/DeviceDetailHeading.tsx @@ -14,10 +14,10 @@ See the License for the specific language governing permissions and limitations under the License. */ -import React, { FormEvent, useEffect, useState } from "react"; +import React, { useEffect, useState } from "react"; import { _t } from "../../../../languageHandler"; -import AccessibleButton from "../../elements/AccessibleButton"; +import AccessibleButton, { ButtonEvent } from "../../elements/AccessibleButton"; import Field from "../../elements/Field"; import LearnMore from "../../elements/LearnMore"; import Spinner from "../../elements/Spinner"; @@ -41,7 +41,7 @@ const DeviceNameEditor: React.FC void }> = ({ devic const onInputChange = (event: React.ChangeEvent): void => setDeviceName(event.target.value); - const onSubmit = async (event: FormEvent): Promise => { + const onSubmit = async (event: ButtonEvent): Promise => { setIsLoading(true); setError(null); event.preventDefault(); diff --git a/src/components/views/settings/discovery/EmailAddresses.tsx b/src/components/views/settings/discovery/EmailAddresses.tsx index f11222af48..8bc13bf187 100644 --- a/src/components/views/settings/discovery/EmailAddresses.tsx +++ b/src/components/views/settings/discovery/EmailAddresses.tsx @@ -25,7 +25,7 @@ import { MatrixClientPeg } from "../../../../MatrixClientPeg"; import Modal from "../../../../Modal"; import AddThreepid, { Binding } from "../../../../AddThreepid"; import ErrorDialog, { extractErrorMessageFromError } from "../../dialogs/ErrorDialog"; -import AccessibleButton from "../../elements/AccessibleButton"; +import AccessibleButton, { ButtonEvent } from "../../elements/AccessibleButton"; /* TODO: Improve the UX for everything in here. @@ -147,7 +147,7 @@ export class EmailAddress extends React.Component { + private onRevokeClick = (e: ButtonEvent): void => { e.stopPropagation(); e.preventDefault(); this.changeBinding({ @@ -157,7 +157,7 @@ export class EmailAddress extends React.Component { + private onShareClick = (e: ButtonEvent): void => { e.stopPropagation(); e.preventDefault(); this.changeBinding({ @@ -167,7 +167,7 @@ export class EmailAddress extends React.Component => { + private onContinueClick = async (e: ButtonEvent): Promise => { e.stopPropagation(); e.preventDefault(); diff --git a/src/components/views/settings/discovery/PhoneNumbers.tsx b/src/components/views/settings/discovery/PhoneNumbers.tsx index 9ae1719259..7c61db8cd3 100644 --- a/src/components/views/settings/discovery/PhoneNumbers.tsx +++ b/src/components/views/settings/discovery/PhoneNumbers.tsx @@ -26,7 +26,7 @@ import Modal from "../../../../Modal"; import AddThreepid, { Binding } from "../../../../AddThreepid"; import ErrorDialog, { extractErrorMessageFromError } from "../../dialogs/ErrorDialog"; import Field from "../../elements/Field"; -import AccessibleButton from "../../elements/AccessibleButton"; +import AccessibleButton, { ButtonEvent } from "../../elements/AccessibleButton"; /* TODO: Improve the UX for everything in here. @@ -154,7 +154,7 @@ export class PhoneNumber extends React.Component { + private onRevokeClick = (e: ButtonEvent): void => { e.stopPropagation(); e.preventDefault(); this.changeBinding({ @@ -164,7 +164,7 @@ export class PhoneNumber extends React.Component { + private onShareClick = (e: ButtonEvent): void => { e.stopPropagation(); e.preventDefault(); this.changeBinding({ @@ -180,7 +180,7 @@ export class PhoneNumber extends React.Component => { + private onContinueClick = async (e: ButtonEvent | React.FormEvent): Promise => { e.stopPropagation(); e.preventDefault(); diff --git a/src/components/views/settings/tabs/room/GeneralRoomSettingsTab.tsx b/src/components/views/settings/tabs/room/GeneralRoomSettingsTab.tsx index 631af29fa2..fa5c65ab89 100644 --- a/src/components/views/settings/tabs/room/GeneralRoomSettingsTab.tsx +++ b/src/components/views/settings/tabs/room/GeneralRoomSettingsTab.tsx @@ -41,7 +41,7 @@ interface IState { export default class GeneralRoomSettingsTab extends React.Component { public static contextType = MatrixClientContext; - public context: ContextType; + public context!: ContextType; public constructor(props: IProps, context: ContextType) { super(props, context); diff --git a/src/components/views/settings/tabs/room/NotificationSettingsTab.tsx b/src/components/views/settings/tabs/room/NotificationSettingsTab.tsx index f1304d44ed..627971eaf3 100644 --- a/src/components/views/settings/tabs/room/NotificationSettingsTab.tsx +++ b/src/components/views/settings/tabs/room/NotificationSettingsTab.tsx @@ -70,7 +70,7 @@ export default class NotificationsSettingsTab extends React.Component => { + private triggerUploader = async (e: ButtonEvent): Promise => { e.stopPropagation(); e.preventDefault(); @@ -91,7 +91,7 @@ export default class NotificationsSettingsTab extends React.Component => { + private onClickSaveSound = async (e: ButtonEvent): Promise => { e.stopPropagation(); e.preventDefault(); @@ -133,7 +133,7 @@ export default class NotificationsSettingsTab extends React.Component { + private clearSound = (e: ButtonEvent): void => { e.stopPropagation(); e.preventDefault(); SettingsStore.setValue("notificationSound", this.props.roomId, SettingLevel.ROOM_ACCOUNT, null); diff --git a/src/indexing/EventIndex.ts b/src/indexing/EventIndex.ts index 84c0a3ec20..c2acab5b00 100644 --- a/src/indexing/EventIndex.ts +++ b/src/indexing/EventIndex.ts @@ -193,7 +193,7 @@ export default class EventIndex extends EventEmitter { private onRoomTimeline = async ( ev: MatrixEvent, room: Room | undefined, - toStartOfTimeline: boolean, + toStartOfTimeline: boolean | undefined, removed: boolean, data: IRoomTimelineData, ): Promise => { diff --git a/src/settings/handlers/AccountSettingsHandler.ts b/src/settings/handlers/AccountSettingsHandler.ts index 8e35b2554f..30424c3a16 100644 --- a/src/settings/handlers/AccountSettingsHandler.ts +++ b/src/settings/handlers/AccountSettingsHandler.ts @@ -50,7 +50,7 @@ export default class AccountSettingsHandler extends MatrixClientBackedSettingsHa newClient.on(ClientEvent.AccountData, this.onAccountData); } - private onAccountData = (event: MatrixEvent, prevEvent: MatrixEvent): void => { + private onAccountData = (event: MatrixEvent, prevEvent?: MatrixEvent): void => { if (event.getType() === "org.matrix.preview_urls") { let val = event.getContent()["disable"]; if (typeof val !== "boolean") { diff --git a/src/settings/handlers/RoomAccountSettingsHandler.ts b/src/settings/handlers/RoomAccountSettingsHandler.ts index 5e29330329..700bc7d397 100644 --- a/src/settings/handlers/RoomAccountSettingsHandler.ts +++ b/src/settings/handlers/RoomAccountSettingsHandler.ts @@ -44,7 +44,7 @@ export default class RoomAccountSettingsHandler extends MatrixClientBackedSettin newClient.on(RoomEvent.AccountData, this.onAccountData); } - private onAccountData = (event: MatrixEvent, room: Room, prevEvent: MatrixEvent): void => { + private onAccountData = (event: MatrixEvent, room: Room, prevEvent?: MatrixEvent): void => { const roomId = room.roomId; if (event.getType() === "org.matrix.room.preview_urls") { @@ -58,7 +58,7 @@ export default class RoomAccountSettingsHandler extends MatrixClientBackedSettin this.watchers.notifyUpdate("urlPreviewsEnabled", roomId, SettingLevel.ROOM_ACCOUNT, val); } else if (event.getType() === DEFAULT_SETTINGS_EVENT_TYPE) { // Figure out what changed and fire those updates - const prevContent = prevEvent ? prevEvent.getContent() : {}; + const prevContent = prevEvent?.getContent() ?? {}; const changedSettings = objectKeyChanges>(prevContent, event.getContent()); for (const settingName of changedSettings) { const val = event.getContent()[settingName]; diff --git a/src/settings/handlers/RoomSettingsHandler.ts b/src/settings/handlers/RoomSettingsHandler.ts index a7c6408ce9..48370df36c 100644 --- a/src/settings/handlers/RoomSettingsHandler.ts +++ b/src/settings/handlers/RoomSettingsHandler.ts @@ -43,7 +43,7 @@ export default class RoomSettingsHandler extends MatrixClientBackedSettingsHandl newClient.on(RoomStateEvent.Events, this.onEvent); } - private onEvent = (event: MatrixEvent, state: RoomState, prevEvent: MatrixEvent): void => { + private onEvent = (event: MatrixEvent, state: RoomState, prevEvent: MatrixEvent | null): void => { const roomId = event.getRoomId()!; const room = this.client.getRoom(roomId); @@ -67,7 +67,7 @@ export default class RoomSettingsHandler extends MatrixClientBackedSettingsHandl this.watchers.notifyUpdate("urlPreviewsEnabled", roomId, SettingLevel.ROOM, val); } else if (event.getType() === DEFAULT_SETTINGS_EVENT_TYPE) { // Figure out what changed and fire those updates - const prevContent = prevEvent ? prevEvent.getContent() : {}; + const prevContent = prevEvent?.getContent() ?? {}; const changedSettings = objectKeyChanges>(prevContent, event.getContent()); for (const settingName of changedSettings) { this.watchers.notifyUpdate(settingName, roomId, SettingLevel.ROOM, event.getContent()[settingName]); diff --git a/src/stores/AutoRageshakeStore.ts b/src/stores/AutoRageshakeStore.ts index 2d20b95da4..a5d6b0068b 100644 --- a/src/stores/AutoRageshakeStore.ts +++ b/src/stores/AutoRageshakeStore.ts @@ -142,7 +142,11 @@ export default class AutoRageshakeStore extends AsyncStoreWithClient { } } - private async onSyncStateChange(_state: SyncState, _prevState: SyncState, data?: ISyncStateData): Promise { + private async onSyncStateChange( + _state: SyncState, + _prevState: SyncState | null, + data?: ISyncStateData, + ): Promise { if (!this.state.initialSyncCompleted) { await this.updateState({ initialSyncCompleted: !!data?.nextSyncToken }); } diff --git a/src/toasts/IncomingLegacyCallToast.tsx b/src/toasts/IncomingLegacyCallToast.tsx index 26ea393332..33a904afe7 100644 --- a/src/toasts/IncomingLegacyCallToast.tsx +++ b/src/toasts/IncomingLegacyCallToast.tsx @@ -26,7 +26,7 @@ import { MatrixClientPeg } from "../MatrixClientPeg"; import { _t } from "../languageHandler"; import RoomAvatar from "../components/views/avatars/RoomAvatar"; import AccessibleTooltipButton from "../components/views/elements/AccessibleTooltipButton"; -import AccessibleButton from "../components/views/elements/AccessibleButton"; +import AccessibleButton, { ButtonEvent } from "../components/views/elements/AccessibleButton"; export const getIncomingLegacyCallToastKey = (callId: string): string => `call_${callId}`; @@ -73,17 +73,17 @@ export default class IncomingLegacyCallToast extends React.Component { + private onAnswerClick = (e: ButtonEvent): void => { e.stopPropagation(); LegacyCallHandler.instance.answerCall(this.roomId); }; - private onRejectClick = (e: React.MouseEvent): void => { + private onRejectClick = (e: ButtonEvent): void => { e.stopPropagation(); LegacyCallHandler.instance.hangupOrReject(this.roomId, true); }; - private onSilenceClick = (e: React.MouseEvent): void => { + private onSilenceClick = (e: ButtonEvent): void => { e.stopPropagation(); const callId = this.props.call.callId; this.state.silenced diff --git a/src/utils/connection.ts b/src/utils/connection.ts index 55eed17d47..0a0569fc98 100644 --- a/src/utils/connection.ts +++ b/src/utils/connection.ts @@ -22,7 +22,7 @@ import { SyncState } from "matrix-js-sdk/src/sync"; * @param callback The callback to be called on reconnect */ export const createReconnectedListener = (callback: () => void): ClientEventHandlerMap[ClientEvent.Sync] => { - return (syncState: SyncState, prevState: SyncState) => { + return (syncState: SyncState, prevState: SyncState | null) => { if (syncState !== SyncState.Error && prevState !== syncState) { // Consider the client reconnected if there is no error with syncing. // This means the state could be RECONNECTING, SYNCING, PREPARED or CATCHUP. diff --git a/test/components/views/rooms/MessageComposer-test.tsx b/test/components/views/rooms/MessageComposer-test.tsx index e076b8ae4a..b4f5b696db 100644 --- a/test/components/views/rooms/MessageComposer-test.tsx +++ b/test/components/views/rooms/MessageComposer-test.tsx @@ -268,9 +268,11 @@ describe("MessageComposer", () => { let resizeCallback: Function; beforeEach(() => { - jest.spyOn(UIStore.instance, "on").mockImplementation((_event: string, listener: Function): any => { - resizeCallback = listener; - }); + jest.spyOn(UIStore.instance, "on").mockImplementation( + (_event: string | symbol, listener: Function): any => { + resizeCallback = listener; + }, + ); }); describe("when a non-resize event occurred in UIStore", () => { diff --git a/test/voice-broadcast/stores/VoiceBroadcastPlaybacksStore-test.ts b/test/voice-broadcast/stores/VoiceBroadcastPlaybacksStore-test.ts index 889e94a093..375851ee8b 100644 --- a/test/voice-broadcast/stores/VoiceBroadcastPlaybacksStore-test.ts +++ b/test/voice-broadcast/stores/VoiceBroadcastPlaybacksStore-test.ts @@ -40,7 +40,7 @@ describe("VoiceBroadcastPlaybacksStore", () => { let playback1: VoiceBroadcastPlayback; let playback2: VoiceBroadcastPlayback; let playbacks: VoiceBroadcastPlaybacksStore; - let onCurrentChanged: (playback: VoiceBroadcastPlayback) => void; + let onCurrentChanged: (playback: VoiceBroadcastPlayback | null) => void; beforeEach(() => { client = stubClient(); diff --git a/test/voice-broadcast/stores/VoiceBroadcastRecordingsStore-test.ts b/test/voice-broadcast/stores/VoiceBroadcastRecordingsStore-test.ts index f8a9cc9448..ae255405a5 100644 --- a/test/voice-broadcast/stores/VoiceBroadcastRecordingsStore-test.ts +++ b/test/voice-broadcast/stores/VoiceBroadcastRecordingsStore-test.ts @@ -35,7 +35,7 @@ describe("VoiceBroadcastRecordingsStore", () => { let recording: VoiceBroadcastRecording; let otherRecording: VoiceBroadcastRecording; let recordings: VoiceBroadcastRecordingsStore; - let onCurrentChanged: (recording: VoiceBroadcastRecording) => void; + let onCurrentChanged: (recording: VoiceBroadcastRecording | null) => void; beforeEach(() => { client = stubClient();