Enable strictFunctionTypes (#11201)

This commit is contained in:
Michael Telatynski 2023-07-07 13:37:26 +01:00 committed by GitHub
parent 40de66424d
commit 4207d182cd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
30 changed files with 245 additions and 258 deletions

View file

@ -62,7 +62,7 @@
"@babel/runtime": "^7.12.5", "@babel/runtime": "^7.12.5",
"@matrix-org/analytics-events": "^0.5.0", "@matrix-org/analytics-events": "^0.5.0",
"@matrix-org/matrix-wysiwyg": "^2.3.0", "@matrix-org/matrix-wysiwyg": "^2.3.0",
"@matrix-org/react-sdk-module-api": "^0.0.5", "@matrix-org/react-sdk-module-api": "^0.0.6",
"@sentry/browser": "^7.0.0", "@sentry/browser": "^7.0.0",
"@sentry/tracing": "^7.0.0", "@sentry/tracing": "^7.0.0",
"@testing-library/react-hooks": "^8.0.1", "@testing-library/react-hooks": "^8.0.1",

View file

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import React, { JSXElementConstructor } from "react"; import { JSXElementConstructor } from "react";
// Based on https://stackoverflow.com/a/53229857/3532235 // Based on https://stackoverflow.com/a/53229857/3532235
export type Without<T, U> = { [P in Exclude<keyof T, keyof U>]?: never }; export type Without<T, U> = { [P in Exclude<keyof T, keyof U>]?: never };
@ -22,7 +22,6 @@ export type XOR<T, U> = T | U extends object ? (Without<T, U> & U) | (Without<U,
export type Writeable<T> = { -readonly [P in keyof T]: T[P] }; export type Writeable<T> = { -readonly [P in keyof T]: T[P] };
export type ComponentClass = keyof JSX.IntrinsicElements | JSXElementConstructor<any>; export type ComponentClass = keyof JSX.IntrinsicElements | JSXElementConstructor<any>;
export type ReactAnyComponent = React.Component | React.ExoticComponent;
// Utility type for string dot notation for accessing nested object properties // Utility type for string dot notation for accessing nested object properties
// Based on https://stackoverflow.com/a/58436959 // Based on https://stackoverflow.com/a/58436959

View file

@ -46,7 +46,7 @@ import RoomListStore from "../../stores/room-list/RoomListStore";
import NonUrgentToastContainer from "./NonUrgentToastContainer"; import NonUrgentToastContainer from "./NonUrgentToastContainer";
import { IOOBData, IThreepidInvite } from "../../stores/ThreepidInviteStore"; import { IOOBData, IThreepidInvite } from "../../stores/ThreepidInviteStore";
import Modal from "../../Modal"; import Modal from "../../Modal";
import { ICollapseConfig } from "../../resizer/distributors/collapse"; import { CollapseItem, ICollapseConfig } from "../../resizer/distributors/collapse";
import { getKeyBindingsManager } from "../../KeyBindingsManager"; import { getKeyBindingsManager } from "../../KeyBindingsManager";
import { IOpts } from "../../createRoom"; import { IOpts } from "../../createRoom";
import SpacePanel from "../views/spaces/SpacePanel"; import SpacePanel from "../views/spaces/SpacePanel";
@ -134,7 +134,7 @@ class LoggedInView extends React.Component<IProps, IState> {
protected layoutWatcherRef?: string; protected layoutWatcherRef?: string;
protected compactLayoutWatcherRef?: string; protected compactLayoutWatcherRef?: string;
protected backgroundImageWatcherRef?: string; protected backgroundImageWatcherRef?: string;
protected resizer?: Resizer; protected resizer?: Resizer<ICollapseConfig, CollapseItem>;
public constructor(props: IProps) { public constructor(props: IProps) {
super(props); super(props);
@ -230,7 +230,7 @@ class LoggedInView extends React.Component<IProps, IState> {
return this._roomView.current.canResetTimeline(); return this._roomView.current.canResetTimeline();
}; };
private createResizer(): Resizer { private createResizer(): Resizer<ICollapseConfig, CollapseItem> {
let panelSize: number | null; let panelSize: number | null;
let panelCollapsed: boolean; let panelCollapsed: boolean;
const collapseConfig: ICollapseConfig = { const collapseConfig: ICollapseConfig = {

View file

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import React, { forwardRef, RefObject, useCallback, useContext, useEffect, useRef, useState } from "react"; import React, { forwardRef, useCallback, useContext, useEffect, useRef, useState } from "react";
import { ISearchResults } from "matrix-js-sdk/src/@types/search"; import { ISearchResults } from "matrix-js-sdk/src/@types/search";
import { IThreadBundledRelationship } from "matrix-js-sdk/src/models/event"; import { IThreadBundledRelationship } from "matrix-js-sdk/src/models/event";
import { THREAD_RELATION_TYPE } from "matrix-js-sdk/src/models/thread"; import { THREAD_RELATION_TYPE } from "matrix-js-sdk/src/models/thread";
@ -57,10 +57,7 @@ interface Props {
// XXX: todo: merge overlapping results somehow? // XXX: todo: merge overlapping results somehow?
// XXX: why doesn't searching on name work? // XXX: why doesn't searching on name work?
export const RoomSearchView = forwardRef<ScrollPanel, Props>( export const RoomSearchView = forwardRef<ScrollPanel, Props>(
( ({ term, scope, promise, abortController, resizeNotifier, className, onUpdate }: Props, ref) => {
{ term, scope, promise, abortController, resizeNotifier, className, onUpdate }: Props,
ref: RefObject<ScrollPanel>,
) => {
const client = useContext(MatrixClientContext); const client = useContext(MatrixClientContext);
const roomContext = useContext(RoomContext); const roomContext = useContext(RoomContext);
const [inProgress, setInProgress] = useState(true); const [inProgress, setInProgress] = useState(true);
@ -69,6 +66,7 @@ export const RoomSearchView = forwardRef<ScrollPanel, Props>(
const aborted = useRef(false); const aborted = useRef(false);
// A map from room ID to permalink creator // A map from room ID to permalink creator
const permalinkCreators = useRef(new Map<string, RoomPermalinkCreator>()).current; const permalinkCreators = useRef(new Map<string, RoomPermalinkCreator>()).current;
const innerRef = useRef<ScrollPanel | null>();
useEffect(() => { useEffect(() => {
return () => { return () => {
@ -214,8 +212,16 @@ export const RoomSearchView = forwardRef<ScrollPanel, Props>(
// once dynamic content in the search results load, make the scrollPanel check // once dynamic content in the search results load, make the scrollPanel check
// the scroll offsets. // the scroll offsets.
const onHeightChanged = (): void => { const onHeightChanged = (): void => {
const scrollPanel = ref.current; innerRef.current?.checkScroll();
scrollPanel?.checkScroll(); };
const onRef = (e: ScrollPanel | null): void => {
if (typeof ref === "function") {
ref(e);
} else if (!!ref) {
ref.current = e;
}
innerRef.current = e;
}; };
let lastRoomId: string | undefined; let lastRoomId: string | undefined;
@ -317,7 +323,7 @@ export const RoomSearchView = forwardRef<ScrollPanel, Props>(
return ( return (
<ScrollPanel <ScrollPanel
ref={ref} ref={onRef}
className={"mx_RoomView_searchResultsPanel " + className} className={"mx_RoomView_searchResultsPanel " + className}
onFillRequest={onSearchResultsFillRequest} onFillRequest={onSearchResultsFillRequest}
resizeNotifier={resizeNotifier} resizeNotifier={resizeNotifier}

View file

@ -854,7 +854,7 @@ export default class ScrollPanel extends React.Component<IProps> {
return this.divScroll; return this.divScroll;
} }
private collectScroll = (divScroll: HTMLDivElement): void => { private collectScroll = (divScroll: HTMLDivElement | null): void => {
this.divScroll = divScroll; this.divScroll = divScroll;
}; };

View file

@ -91,6 +91,9 @@ interface IAuthEntryProps {
onPhaseChange: (phase: number) => void; onPhaseChange: (phase: number) => void;
submitAuthDict: (auth: IAuthDict) => void; submitAuthDict: (auth: IAuthDict) => void;
requestEmailToken?: () => Promise<void>; requestEmailToken?: () => Promise<void>;
fail: (error: Error) => void;
clientSecret: string;
showContinue: boolean;
} }
interface IPasswordAuthEntryState { interface IPasswordAuthEntryState {
@ -248,7 +251,6 @@ interface ITermsAuthEntryProps extends IAuthEntryProps {
stageParams?: { stageParams?: {
policies?: Policies; policies?: Policies;
}; };
showContinue: boolean;
} }
interface LocalisedPolicyWithId extends LocalisedPolicy { interface LocalisedPolicyWithId extends LocalisedPolicy {
@ -416,7 +418,7 @@ interface IEmailIdentityAuthEntryProps extends IAuthEntryProps {
emailAddress?: string; emailAddress?: string;
}; };
stageState?: { stageState?: {
emailSid: string; emailSid?: string;
}; };
} }
@ -540,12 +542,10 @@ export class EmailIdentityAuthEntry extends React.Component<
} }
interface IMsisdnAuthEntryProps extends IAuthEntryProps { interface IMsisdnAuthEntryProps extends IAuthEntryProps {
inputs: { inputs?: {
phoneCountry: string; phoneCountry?: string;
phoneNumber: string; phoneNumber?: string;
}; };
clientSecret: string;
fail: (error: Error) => void;
} }
interface IMsisdnAuthEntryState { interface IMsisdnAuthEntryState {
@ -590,8 +590,8 @@ export class MsisdnAuthEntry extends React.Component<IMsisdnAuthEntryProps, IMsi
private requestMsisdnToken(): Promise<void> { private requestMsisdnToken(): Promise<void> {
return this.props.matrixClient return this.props.matrixClient
.requestRegisterMsisdnToken( .requestRegisterMsisdnToken(
this.props.inputs.phoneCountry, this.props.inputs?.phoneCountry ?? "",
this.props.inputs.phoneNumber, this.props.inputs?.phoneNumber ?? "",
this.props.clientSecret, this.props.clientSecret,
1, // TODO: Multiple send attempts? 1, // TODO: Multiple send attempts?
) )
@ -982,14 +982,11 @@ export class FallbackAuthEntry extends React.Component<IAuthEntryProps> {
} }
export interface IStageComponentProps extends IAuthEntryProps { export interface IStageComponentProps extends IAuthEntryProps {
clientSecret?: string;
stageParams?: Record<string, any>; stageParams?: Record<string, any>;
inputs?: IInputs; inputs?: IInputs;
stageState?: IStageStatus; stageState?: IStageStatus;
showContinue?: boolean;
continueText?: string; continueText?: string;
continueKind?: string; continueKind?: string;
fail?(e: Error): void;
setEmailSid?(sid: string): void; setEmailSid?(sid: string): void;
onCancel?(): void; onCancel?(): void;
requestEmailToken?(): Promise<void>; requestEmailToken?(): Promise<void>;

View file

@ -21,21 +21,24 @@ import { logger } from "matrix-js-sdk/src/logger";
import ScrollableBaseModal, { IScrollableBaseState } from "./ScrollableBaseModal"; import ScrollableBaseModal, { IScrollableBaseState } from "./ScrollableBaseModal";
import { _t } from "../../../languageHandler"; import { _t } from "../../../languageHandler";
interface IProps<C extends React.Component = React.Component> { interface IProps<P extends DialogProps, C extends DialogContent<P>> {
contentFactory: (props: DialogProps, ref: React.Ref<C>) => React.ReactNode; contentFactory: (props: P, ref: React.RefObject<C>) => React.ReactNode;
contentProps: DialogProps; contentProps: P;
title: string; title: string;
onFinished(ok?: boolean, model?: Awaited<ReturnType<DialogContent["trySubmit"]>>): void; onFinished(ok?: boolean, model?: Awaited<ReturnType<DialogContent<P>["trySubmit"]>>): void;
} }
interface IState extends IScrollableBaseState { interface IState extends IScrollableBaseState {
// nothing special // nothing special
} }
export class ModuleUiDialog extends ScrollableBaseModal<IProps, IState> { export class ModuleUiDialog<P extends DialogProps, C extends DialogContent<P>> extends ScrollableBaseModal<
private contentRef = createRef<DialogContent>(); IProps<P, C>,
IState
> {
private contentRef = createRef<C>();
public constructor(props: IProps) { public constructor(props: IProps<P, C>) {
super(props); super(props);
this.state = { this.state = {

View file

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import React, { forwardRef } from "react"; import React, { forwardRef, ForwardRefExoticComponent } from "react";
import { MatrixEvent } from "matrix-js-sdk/src/matrix"; import { MatrixEvent } from "matrix-js-sdk/src/matrix";
import { _t } from "../../../languageHandler"; import { _t } from "../../../languageHandler";
@ -27,12 +27,10 @@ function getErrorMessage(mxEvent?: MatrixEvent): string {
} }
// A placeholder element for messages that could not be decrypted // A placeholder element for messages that could not be decrypted
export const DecryptionFailureBody = forwardRef<HTMLDivElement, Partial<IBodyProps>>( export const DecryptionFailureBody = forwardRef<HTMLDivElement, IBodyProps>(({ mxEvent }, ref): JSX.Element => {
({ mxEvent }, ref): JSX.Element => {
return ( return (
<div className="mx_DecryptionFailureBody mx_EventTile_content" ref={ref}> <div className="mx_DecryptionFailureBody mx_EventTile_content" ref={ref}>
{getErrorMessage(mxEvent)} {getErrorMessage(mxEvent)}
</div> </div>
); );
}, }) as ForwardRefExoticComponent<IBodyProps>;
);

View file

@ -39,9 +39,9 @@ export interface IBodyProps {
maxImageHeight?: number; maxImageHeight?: number;
replacingEventId?: string; replacingEventId?: string;
editState?: EditorStateTransfer; editState?: EditorStateTransfer;
onMessageAllowed: () => void; // TODO: Docs onMessageAllowed?: () => void; // TODO: Docs
permalinkCreator?: RoomPermalinkCreator; permalinkCreator?: RoomPermalinkCreator;
mediaEventHelper: MediaEventHelper; mediaEventHelper?: MediaEventHelper;
/* /*
If present and `true`, the message has been marked as hidden pending moderation If present and `true`, the message has been marked as hidden pending moderation

View file

@ -51,7 +51,7 @@ export default class MAudioBody extends React.PureComponent<IBodyProps, IState>
try { try {
try { try {
const blob = await this.props.mediaEventHelper.sourceBlob.value; const blob = await this.props.mediaEventHelper!.sourceBlob.value;
buffer = await blob.arrayBuffer(); buffer = await blob.arrayBuffer();
} catch (e) { } catch (e) {
this.setState({ error: e }); this.setState({ error: e });

View file

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import React, { useCallback, useContext, useEffect, useState } from "react"; import React, { ForwardRefExoticComponent, useCallback, useContext, useEffect, useState } from "react";
import { import {
Beacon, Beacon,
BeaconEvent, BeaconEvent,
@ -234,6 +234,6 @@ const MBeaconBody = React.forwardRef<HTMLDivElement, IBodyProps>(({ mxEvent, get
)} )}
</div> </div>
); );
}); }) as ForwardRefExoticComponent<IBodyProps>;
export default MBeaconBody; export default MBeaconBody;

View file

@ -168,7 +168,7 @@ export default class MFileBody extends React.Component<IProps, IState> {
try { try {
this.userDidClick = true; this.userDidClick = true;
this.setState({ this.setState({
decryptedBlob: await this.props.mediaEventHelper.sourceBlob.value, decryptedBlob: await this.props.mediaEventHelper!.sourceBlob.value,
}); });
} catch (err) { } catch (err) {
logger.warn("Unable to decrypt attachment: ", err); logger.warn("Unable to decrypt attachment: ", err);
@ -188,7 +188,7 @@ export default class MFileBody extends React.Component<IProps, IState> {
// As a button we're missing the `download` attribute for styling reasons, so // As a button we're missing the `download` attribute for styling reasons, so
// download with the file downloader. // download with the file downloader.
this.fileDownloader.download({ this.fileDownloader.download({
blob: await mediaHelper.sourceBlob.value, blob: await mediaHelper!.sourceBlob.value,
name: this.fileName, name: this.fileName,
}); });
} }
@ -322,7 +322,7 @@ export default class MFileBody extends React.Component<IProps, IState> {
// Start a fetch for the download // Start a fetch for the download
// Based upon https://stackoverflow.com/a/49500465 // Based upon https://stackoverflow.com/a/49500465
this.props.mediaEventHelper.sourceBlob.value.then((blob) => { this.props.mediaEventHelper?.sourceBlob.value.then((blob) => {
const blobUrl = URL.createObjectURL(blob); const blobUrl = URL.createObjectURL(blob);
// We have to create an anchor to download the file // We have to create an anchor to download the file

View file

@ -261,7 +261,7 @@ export default class MImageBody extends React.Component<IBodyProps, IState> {
let thumbUrl: string | null; let thumbUrl: string | null;
let contentUrl: string | null; let contentUrl: string | null;
if (this.props.mediaEventHelper.media.isEncrypted) { if (this.props.mediaEventHelper?.media.isEncrypted) {
try { try {
[contentUrl, thumbUrl] = await Promise.all([ [contentUrl, thumbUrl] = await Promise.all([
this.props.mediaEventHelper.sourceUrl.value, this.props.mediaEventHelper.sourceUrl.value,
@ -311,7 +311,7 @@ export default class MImageBody extends React.Component<IBodyProps, IState> {
} }
try { try {
const blob = await this.props.mediaEventHelper.sourceBlob.value; const blob = await this.props.mediaEventHelper!.sourceBlob.value;
if (!(await blobIsAnimated(content.info?.mimetype, blob))) { if (!(await blobIsAnimated(content.info?.mimetype, blob))) {
isAnimated = false; isAnimated = false;
} }

View file

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import React, { useEffect, useState, useContext } from "react"; import React, { useEffect, useState, useContext, ForwardRefExoticComponent } from "react";
import { MatrixEvent } from "matrix-js-sdk/src/matrix"; import { MatrixEvent } from "matrix-js-sdk/src/matrix";
import { M_TEXT } from "matrix-js-sdk/src/@types/extensible_events"; import { M_TEXT } from "matrix-js-sdk/src/@types/extensible_events";
import { logger } from "matrix-js-sdk/src/logger"; import { logger } from "matrix-js-sdk/src/logger";
@ -109,9 +109,9 @@ export const MPollEndBody = React.forwardRef<any, IBodyProps>(({ mxEvent, ...pro
} }
return ( return (
<div> <div ref={ref}>
<Caption>{_t("Ended a poll")}</Caption> <Caption>{_t("Ended a poll")}</Caption>
<MPollBody mxEvent={pollStartEvent} {...props} /> <MPollBody mxEvent={pollStartEvent} {...props} />
</div> </div>
); );
}); }) as ForwardRefExoticComponent<IBodyProps>;

View file

@ -143,7 +143,7 @@ export default class MVideoBody extends React.PureComponent<IBodyProps, IState>
logger.error("Failed to load blurhash", e); logger.error("Failed to load blurhash", e);
} }
if (this.props.mediaEventHelper.media.isEncrypted && this.state.decryptedUrl === null) { if (this.props.mediaEventHelper?.media.isEncrypted && this.state.decryptedUrl === null) {
try { try {
const autoplay = SettingsStore.getValue("autoplayVideo") as boolean; const autoplay = SettingsStore.getValue("autoplayVideo") as boolean;
const thumbnailUrl = await this.props.mediaEventHelper.thumbnailUrl.value; const thumbnailUrl = await this.props.mediaEventHelper.thumbnailUrl.value;
@ -199,7 +199,7 @@ export default class MVideoBody extends React.PureComponent<IBodyProps, IState>
// To stop subsequent download attempts // To stop subsequent download attempts
fetchingData: true, fetchingData: true,
}); });
if (!this.props.mediaEventHelper.media.isEncrypted) { if (!this.props.mediaEventHelper!.media.isEncrypted) {
this.setState({ this.setState({
error: "No file given in content", error: "No file given in content",
}); });
@ -207,8 +207,8 @@ export default class MVideoBody extends React.PureComponent<IBodyProps, IState>
} }
this.setState( this.setState(
{ {
decryptedUrl: await this.props.mediaEventHelper.sourceUrl.value, decryptedUrl: await this.props.mediaEventHelper!.sourceUrl.value,
decryptedBlob: await this.props.mediaEventHelper.sourceBlob.value, decryptedBlob: await this.props.mediaEventHelper!.sourceBlob.value,
fetchingData: false, fetchingData: false,
}, },
() => { () => {

View file

@ -27,7 +27,6 @@ import RedactedBody from "./RedactedBody";
import UnknownBody from "./UnknownBody"; import UnknownBody from "./UnknownBody";
import { IMediaBody } from "./IMediaBody"; import { IMediaBody } from "./IMediaBody";
import { MediaEventHelper } from "../../../utils/MediaEventHelper"; import { MediaEventHelper } from "../../../utils/MediaEventHelper";
import { ReactAnyComponent } from "../../../@types/common";
import { IBodyProps } from "./IBodyProps"; import { IBodyProps } from "./IBodyProps";
import MatrixClientContext from "../../../contexts/MatrixClientContext"; import MatrixClientContext from "../../../contexts/MatrixClientContext";
import TextualBody from "./TextualBody"; import TextualBody from "./TextualBody";
@ -70,7 +69,7 @@ const baseBodyTypes = new Map<string, typeof React.Component>([
[MsgType.Audio, MVoiceOrAudioBody], [MsgType.Audio, MVoiceOrAudioBody],
[MsgType.Video, MVideoBody], [MsgType.Video, MVideoBody],
]); ]);
const baseEvTypes = new Map<string, React.ComponentType<Partial<IBodyProps>>>([ const baseEvTypes = new Map<string, React.ComponentType<IBodyProps>>([
[EventType.Sticker, MStickerBody], [EventType.Sticker, MStickerBody],
[M_POLL_START.name, MPollBody], [M_POLL_START.name, MPollBody],
[M_POLL_START.altName, MPollBody], [M_POLL_START.altName, MPollBody],
@ -84,7 +83,7 @@ export default class MessageEvent extends React.Component<IProps> implements IMe
private body: React.RefObject<React.Component | IOperableEventTile> = createRef(); private body: React.RefObject<React.Component | IOperableEventTile> = createRef();
private mediaHelper?: MediaEventHelper; private mediaHelper?: MediaEventHelper;
private bodyTypes = new Map<string, typeof React.Component>(baseBodyTypes.entries()); private bodyTypes = new Map<string, typeof React.Component>(baseBodyTypes.entries());
private evTypes = new Map<string, React.ComponentType<Partial<IBodyProps>>>(baseEvTypes.entries()); private evTypes = new Map<string, React.ComponentType<IBodyProps>>(baseEvTypes.entries());
public static contextType = MatrixClientContext; public static contextType = MatrixClientContext;
public context!: React.ContextType<typeof MatrixClientContext>; public context!: React.ContextType<typeof MatrixClientContext>;
@ -123,7 +122,7 @@ export default class MessageEvent extends React.Component<IProps> implements IMe
this.bodyTypes.set(bodyType, bodyComponent); this.bodyTypes.set(bodyType, bodyComponent);
} }
this.evTypes = new Map<string, React.ComponentType<Partial<IBodyProps>>>(baseEvTypes.entries()); this.evTypes = new Map<string, React.ComponentType<IBodyProps>>(baseEvTypes.entries());
for (const [evType, evComponent] of Object.entries(this.props.overrideEventTypes ?? {})) { for (const [evType, evComponent] of Object.entries(this.props.overrideEventTypes ?? {})) {
this.evTypes.set(evType, evComponent); this.evTypes.set(evType, evComponent);
} }
@ -153,7 +152,7 @@ export default class MessageEvent extends React.Component<IProps> implements IMe
const content = this.props.mxEvent.getContent(); const content = this.props.mxEvent.getContent();
const type = this.props.mxEvent.getType(); const type = this.props.mxEvent.getType();
const msgtype = content.msgtype; const msgtype = content.msgtype;
let BodyType: React.ComponentType<Partial<IBodyProps>> | ReactAnyComponent = RedactedBody; let BodyType: React.ComponentType<IBodyProps> = RedactedBody;
if (!this.props.mxEvent.isRedacted()) { if (!this.props.mxEvent.isRedacted()) {
// only resolve BodyType if event is not redacted // only resolve BodyType if event is not redacted
if (this.props.mxEvent.isDecryptionFailure()) { if (this.props.mxEvent.isDecryptionFailure()) {
@ -195,7 +194,6 @@ export default class MessageEvent extends React.Component<IProps> implements IMe
} }
} }
// @ts-ignore - this is a dynamic react component
return BodyType ? ( return BodyType ? (
<BodyType <BodyType
ref={this.body} ref={this.body}

View file

@ -15,24 +15,19 @@ limitations under the License.
*/ */
import React from "react"; import React from "react";
import { MatrixEvent } from "matrix-js-sdk/src/models/event";
import { _t } from "../../../languageHandler"; import { _t } from "../../../languageHandler";
import AccessibleButton, { ButtonEvent } from "../elements/AccessibleButton"; import AccessibleButton, { ButtonEvent } from "../elements/AccessibleButton";
import { IBodyProps } from "./IBodyProps";
interface IProps { export default class MjolnirBody extends React.Component<IBodyProps> {
mxEvent: MatrixEvent;
onMessageAllowed: () => void;
}
export default class MjolnirBody extends React.Component<IProps> {
private onAllowClick = (e: ButtonEvent): void => { private onAllowClick = (e: ButtonEvent): void => {
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
const key = `mx_mjolnir_render_${this.props.mxEvent.getRoomId()}__${this.props.mxEvent.getId()}`; const key = `mx_mjolnir_render_${this.props.mxEvent.getRoomId()}__${this.props.mxEvent.getId()}`;
localStorage.setItem(key, "true"); localStorage.setItem(key, "true");
this.props.onMessageAllowed(); this.props.onMessageAllowed?.();
}; };
public render(): React.ReactNode { public render(): React.ReactNode {

View file

@ -14,20 +14,16 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import React, { useContext } from "react"; import React, { ForwardRefExoticComponent, useContext } from "react";
import { MatrixClient } from "matrix-js-sdk/src/client"; import { MatrixClient } from "matrix-js-sdk/src/client";
import { MatrixEvent } from "matrix-js-sdk/src/models/event";
import { _t } from "../../../languageHandler"; import { _t } from "../../../languageHandler";
import MatrixClientContext from "../../../contexts/MatrixClientContext"; import MatrixClientContext from "../../../contexts/MatrixClientContext";
import { formatFullDate } from "../../../DateUtils"; import { formatFullDate } from "../../../DateUtils";
import SettingsStore from "../../../settings/SettingsStore"; import SettingsStore from "../../../settings/SettingsStore";
import { IBodyProps } from "./IBodyProps"; import { IBodyProps } from "./IBodyProps";
interface IProps {
mxEvent: MatrixEvent;
}
const RedactedBody = React.forwardRef<any, IProps | IBodyProps>(({ mxEvent }, ref) => { const RedactedBody = React.forwardRef<any, IBodyProps>(({ mxEvent }, ref) => {
const cli: MatrixClient = useContext(MatrixClientContext); const cli: MatrixClient = useContext(MatrixClientContext);
let text = _t("Message deleted"); let text = _t("Message deleted");
const unsigned = mxEvent.getUnsigned(); const unsigned = mxEvent.getUnsigned();
@ -49,6 +45,6 @@ const RedactedBody = React.forwardRef<any, IProps | IBodyProps>(({ mxEvent }, re
{text} {text}
</span> </span>
); );
}); }) as ForwardRefExoticComponent<IBodyProps>;
export default RedactedBody; export default RedactedBody;

View file

@ -15,15 +15,11 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import React, { forwardRef } from "react"; import React, { forwardRef, ForwardRefExoticComponent } from "react";
import { MatrixEvent } from "matrix-js-sdk/src/matrix";
interface IProps { import { IBodyProps } from "./IBodyProps";
mxEvent: MatrixEvent;
children?: React.ReactNode;
}
export default forwardRef<HTMLDivElement, IProps>(({ mxEvent, children }, ref) => { export default forwardRef<HTMLDivElement, IBodyProps>(({ mxEvent, children }, ref) => {
const text = mxEvent.getContent().body; const text = mxEvent.getContent().body;
return ( return (
<div className="mx_UnknownBody" ref={ref}> <div className="mx_UnknownBody" ref={ref}>
@ -31,4 +27,4 @@ export default forwardRef<HTMLDivElement, IProps>(({ mxEvent, children }, ref) =
{children} {children}
</div> </div>
); );
}); }) as ForwardRefExoticComponent<IBodyProps>;

View file

@ -28,7 +28,7 @@ import WidgetUtils from "../../../utils/WidgetUtils";
import WidgetEchoStore from "../../../stores/WidgetEchoStore"; import WidgetEchoStore from "../../../stores/WidgetEchoStore";
import ResizeNotifier from "../../../utils/ResizeNotifier"; import ResizeNotifier from "../../../utils/ResizeNotifier";
import ResizeHandle from "../elements/ResizeHandle"; import ResizeHandle from "../elements/ResizeHandle";
import Resizer from "../../../resizer/resizer"; import Resizer, { IConfig } from "../../../resizer/resizer";
import PercentageDistributor from "../../../resizer/distributors/percentage"; import PercentageDistributor from "../../../resizer/distributors/percentage";
import { Container, WidgetLayoutStore } from "../../../stores/widgets/WidgetLayoutStore"; import { Container, WidgetLayoutStore } from "../../../stores/widgets/WidgetLayoutStore";
import { clamp, percentageOf, percentageWithin } from "../../../utils/numbers"; import { clamp, percentageOf, percentageWithin } from "../../../utils/numbers";
@ -58,7 +58,7 @@ interface IState {
export default class AppsDrawer extends React.Component<IProps, IState> { export default class AppsDrawer extends React.Component<IProps, IState> {
private unmounted = false; private unmounted = false;
private resizeContainer?: HTMLDivElement; private resizeContainer?: HTMLDivElement;
private resizer: Resizer; private resizer: Resizer<IConfig>;
private dispatcherRef?: string; private dispatcherRef?: string;
public static defaultProps: Partial<IProps> = { public static defaultProps: Partial<IProps> = {
showApps: true, showApps: true,
@ -104,7 +104,7 @@ export default class AppsDrawer extends React.Component<IProps, IState> {
} }
}; };
private createResizer(): Resizer { private createResizer(): Resizer<IConfig> {
// This is the horizontal one, changing the distribution of the width between the app tiles // This is the horizontal one, changing the distribution of the width between the app tiles
// (ie. a vertical resize handle because, the handle itself is vertical...) // (ie. a vertical resize handle because, the handle itself is vertical...)
const classNames = { const classNames = {

View file

@ -243,7 +243,7 @@ const CreateSpaceButton: React.FC<Pick<IInnerSpacePanelProps, "isPanelCollapsed"
label={menuDisplayed ? _t("Cancel") : _t("Create a space")} label={menuDisplayed ? _t("Cancel") : _t("Create a space")}
onClick={onNewClick} onClick={onNewClick}
isNarrow={isPanelCollapsed} isNarrow={isPanelCollapsed}
ref={handle} innerRef={handle}
/> />
{contextMenu} {contextMenu}

View file

@ -21,7 +21,6 @@ import React, {
createRef, createRef,
InputHTMLAttributes, InputHTMLAttributes,
LegacyRef, LegacyRef,
forwardRef,
RefObject, RefObject,
} from "react"; } from "react";
import classNames from "classnames"; import classNames from "classnames";
@ -59,13 +58,12 @@ interface IButtonProps extends Omit<ComponentProps<typeof AccessibleTooltipButto
notificationState?: NotificationState; notificationState?: NotificationState;
isNarrow?: boolean; isNarrow?: boolean;
avatarSize?: number; avatarSize?: number;
innerRef?: RefObject<HTMLElement>;
ContextMenuComponent?: ComponentType<ComponentProps<typeof SpaceContextMenu>>; ContextMenuComponent?: ComponentType<ComponentProps<typeof SpaceContextMenu>>;
onClick?(ev?: ButtonEvent): void; onClick?(ev?: ButtonEvent): void;
} }
export const SpaceButton = forwardRef<HTMLElement, IButtonProps>( export const SpaceButton: React.FC<IButtonProps> = ({
(
{
space, space,
spaceKey, spaceKey,
className, className,
@ -76,12 +74,11 @@ export const SpaceButton = forwardRef<HTMLElement, IButtonProps>(
avatarSize, avatarSize,
isNarrow, isNarrow,
children, children,
innerRef,
ContextMenuComponent, ContextMenuComponent,
...props ...props
}, }) => {
ref: RefObject<HTMLElement>, const [menuDisplayed, handle, openMenu, closeMenu] = useContextMenu<HTMLElement>(innerRef);
) => {
const [menuDisplayed, handle, openMenu, closeMenu] = useContextMenu<HTMLElement>(ref);
const [onFocus, isActive] = useRovingTabIndex(handle); const [onFocus, isActive] = useRovingTabIndex(handle);
const tabIndex = isActive ? 0 : -1; const tabIndex = isActive ? 0 : -1;
@ -175,8 +172,7 @@ export const SpaceButton = forwardRef<HTMLElement, IButtonProps>(
</div> </div>
</AccessibleTooltipButton> </AccessibleTooltipButton>
); );
}, };
);
interface IItemProps extends InputHTMLAttributes<HTMLLIElement> { interface IItemProps extends InputHTMLAttributes<HTMLLIElement> {
space: Room; space: Room;

View file

@ -105,7 +105,7 @@ const EVENT_TILE_TYPES = new Map<string, Factory>([
[M_POLL_END.altName, MessageEventFactory], [M_POLL_END.altName, MessageEventFactory],
[EventType.KeyVerificationCancel, KeyVerificationConclFactory], [EventType.KeyVerificationCancel, KeyVerificationConclFactory],
[EventType.KeyVerificationDone, KeyVerificationConclFactory], [EventType.KeyVerificationDone, KeyVerificationConclFactory],
[EventType.CallInvite, LegacyCallEventFactory], // note that this requires a special factory type [EventType.CallInvite, LegacyCallEventFactory as Factory], // note that this requires a special factory type
]); ]);
const STATE_EVENT_TILE_TYPES = new Map<string, Factory>([ const STATE_EVENT_TILE_TYPES = new Map<string, Factory>([

View file

@ -17,7 +17,7 @@ limitations under the License.
import { ModuleApi } from "@matrix-org/react-sdk-module-api/lib/ModuleApi"; import { ModuleApi } from "@matrix-org/react-sdk-module-api/lib/ModuleApi";
import { TranslationStringsObject } from "@matrix-org/react-sdk-module-api/lib/types/translations"; import { TranslationStringsObject } from "@matrix-org/react-sdk-module-api/lib/types/translations";
import { Optional } from "matrix-events-sdk"; import { Optional } from "matrix-events-sdk";
import { DialogProps } from "@matrix-org/react-sdk-module-api/lib/components/DialogContent"; import { DialogContent, DialogProps } from "@matrix-org/react-sdk-module-api/lib/components/DialogContent";
import React from "react"; import React from "react";
import { AccountAuthInfo } from "@matrix-org/react-sdk-module-api/lib/types/AccountAuthInfo"; import { AccountAuthInfo } from "@matrix-org/react-sdk-module-api/lib/types/AccountAuthInfo";
import { PlainSubstitution } from "@matrix-org/react-sdk-module-api/lib/types/translations"; import { PlainSubstitution } from "@matrix-org/react-sdk-module-api/lib/types/translations";
@ -81,23 +81,22 @@ export class ProxiedModuleApi implements ModuleApi {
/** /**
* @override * @override
*/ */
public openDialog< public openDialog<M extends object, P extends DialogProps, C extends DialogContent<P>>(
M extends object,
P extends DialogProps = DialogProps,
C extends React.Component = React.Component,
>(
title: string, title: string,
body: (props: P, ref: React.RefObject<C>) => React.ReactNode, body: (props: P, ref: React.RefObject<C>) => React.ReactNode,
props?: Omit<P, keyof DialogProps>,
): Promise<{ didOkOrSubmit: boolean; model: M }> { ): Promise<{ didOkOrSubmit: boolean; model: M }> {
return new Promise<{ didOkOrSubmit: boolean; model: M }>((resolve) => { return new Promise<{ didOkOrSubmit: boolean; model: M }>((resolve) => {
Modal.createDialog( Modal.createDialog(
ModuleUiDialog, ModuleUiDialog<P, C>,
{ {
title: title, title: title,
contentFactory: body, contentFactory: body,
contentProps: <DialogProps>{ // Typescript isn't very happy understanding that `props` satisfies `Omit<P, keyof DialogProps>`
contentProps: {
...props,
moduleApi: this, moduleApi: this,
}, } as unknown as P,
}, },
"mx_CompoundDialog", "mx_CompoundDialog",
).finished.then(([didOkOrSubmit, model]) => { ).finished.then(([didOkOrSubmit, model]) => {

View file

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import FixedDistributor from "./fixed"; import { BaseDistributor } from "./fixed";
import ResizeItem from "../item"; import ResizeItem from "../item";
import Resizer, { IConfig } from "../resizer"; import Resizer, { IConfig } from "../resizer";
import Sizer from "../sizer"; import Sizer from "../sizer";
@ -25,7 +25,7 @@ export interface ICollapseConfig extends IConfig {
isItemCollapsed(element: HTMLElement): boolean; isItemCollapsed(element: HTMLElement): boolean;
} }
class CollapseItem extends ResizeItem<ICollapseConfig> { export class CollapseItem extends ResizeItem<ICollapseConfig> {
public notifyCollapsed(collapsed: boolean): void { public notifyCollapsed(collapsed: boolean): void {
this.resizer.config?.onCollapsed?.(collapsed, this.id, this.domNode); this.resizer.config?.onCollapsed?.(collapsed, this.id, this.domNode);
} }
@ -35,10 +35,10 @@ class CollapseItem extends ResizeItem<ICollapseConfig> {
} }
} }
export default class CollapseDistributor extends FixedDistributor<ICollapseConfig, CollapseItem> { export default class CollapseDistributor extends BaseDistributor<ICollapseConfig, CollapseItem> {
public static createItem( public static createItem(
resizeHandle: HTMLDivElement, resizeHandle: HTMLDivElement,
resizer: Resizer<ICollapseConfig>, resizer: Resizer<ICollapseConfig, CollapseItem>,
sizer: Sizer, sizer: Sizer,
container?: HTMLElement, container?: HTMLElement,
): CollapseItem { ): CollapseItem {

View file

@ -18,21 +18,7 @@ import ResizeItem from "../item";
import Sizer from "../sizer"; import Sizer from "../sizer";
import Resizer, { IConfig } from "../resizer"; import Resizer, { IConfig } from "../resizer";
/** export abstract class BaseDistributor<C extends IConfig, I extends ResizeItem<C> = ResizeItem<C>> {
distributors translate a moving cursor into
CSS/DOM changes by calling the sizer
they have two methods:
`resize` receives then new item size
`resizeFromContainerOffset` receives resize handle location
within the container bounding box. For internal use.
This method usually ends up calling `resize` once the start offset is subtracted.
*/
export default class FixedDistributor<C extends IConfig, I extends ResizeItem<any> = ResizeItem<C>> {
public static createItem(resizeHandle: HTMLDivElement, resizer: Resizer, sizer: Sizer): ResizeItem {
return new ResizeItem(resizeHandle, resizer, sizer);
}
public static createSizer(containerElement: HTMLElement, vertical: boolean, reverse: boolean): Sizer { public static createSizer(containerElement: HTMLElement, vertical: boolean, reverse: boolean): Sizer {
return new Sizer(containerElement, vertical, reverse); return new Sizer(containerElement, vertical, reverse);
} }
@ -67,3 +53,22 @@ export default class FixedDistributor<C extends IConfig, I extends ResizeItem<an
this.item.finish(); this.item.finish();
} }
} }
/**
distributors translate a moving cursor into
CSS/DOM changes by calling the sizer
they have two methods:
`resize` receives then new item size
`resizeFromContainerOffset` receives resize handle location
within the container bounding box. For internal use.
This method usually ends up calling `resize` once the start offset is subtracted.
*/
export default class FixedDistributor<
C extends IConfig,
I extends ResizeItem<C> = ResizeItem<C>,
> extends BaseDistributor<C, I> {
public static createItem(resizeHandle: HTMLDivElement, resizer: Resizer<any>, sizer: Sizer): ResizeItem<any> {
return new ResizeItem(resizeHandle, resizer, sizer);
}
}

View file

@ -17,14 +17,14 @@ limitations under the License.
import Resizer, { IConfig } from "./resizer"; import Resizer, { IConfig } from "./resizer";
import Sizer from "./sizer"; import Sizer from "./sizer";
export default class ResizeItem<C extends IConfig = IConfig> { export default class ResizeItem<C extends IConfig> {
public readonly domNode: HTMLElement; public readonly domNode: HTMLElement;
protected readonly id: string | null; protected readonly id: string | null;
protected reverse: boolean; protected reverse: boolean;
public constructor( public constructor(
handle: HTMLElement, handle: HTMLElement,
public readonly resizer: Resizer<C>, public readonly resizer: Resizer<C, any>,
public readonly sizer: Sizer, public readonly sizer: Sizer,
public readonly container?: HTMLElement, public readonly container?: HTMLElement,
) { ) {
@ -37,12 +37,17 @@ export default class ResizeItem<C extends IConfig = IConfig> {
this.id = handle.getAttribute("data-id"); this.id = handle.getAttribute("data-id");
} }
private copyWith(handle: HTMLElement, resizer: Resizer, sizer: Sizer, container?: HTMLElement): ResizeItem { private copyWith(
handle: HTMLElement,
resizer: Resizer<C, any>,
sizer: Sizer,
container?: HTMLElement,
): ResizeItem<C> {
const Ctor = this.constructor as typeof ResizeItem; const Ctor = this.constructor as typeof ResizeItem;
return new Ctor(handle, resizer, sizer, container); return new Ctor(handle, resizer, sizer, container);
} }
private advance(forwards: boolean): ResizeItem | undefined { private advance(forwards: boolean): ResizeItem<C> | undefined {
// opposite direction from fromResizeHandle to get back to handle // opposite direction from fromResizeHandle to get back to handle
let handle: Element | null | undefined = this.reverse let handle: Element | null | undefined = this.reverse
? this.domNode.previousElementSibling ? this.domNode.previousElementSibling
@ -64,11 +69,11 @@ export default class ResizeItem<C extends IConfig = IConfig> {
} }
} }
public next(): ResizeItem | undefined { public next(): ResizeItem<C> | undefined {
return this.advance(true); return this.advance(true);
} }
public previous(): ResizeItem | undefined { public previous(): ResizeItem<C> | undefined {
return this.advance(false); return this.advance(false);
} }
@ -106,7 +111,7 @@ export default class ResizeItem<C extends IConfig = IConfig> {
this.resizer.config?.onResized?.(null, this.id, this.domNode); this.resizer.config?.onResized?.(null, this.id, this.domNode);
} }
public first(): ResizeItem | undefined { public first(): ResizeItem<C> | undefined {
if (!this.domNode.parentElement?.children) { if (!this.domNode.parentElement?.children) {
return; return;
} }
@ -118,7 +123,7 @@ export default class ResizeItem<C extends IConfig = IConfig> {
} }
} }
public last(): ResizeItem | undefined { public last(): ResizeItem<C> | undefined {
if (!this.domNode.parentElement?.children) { if (!this.domNode.parentElement?.children) {
return; return;
} }

View file

@ -38,7 +38,7 @@ export interface IConfig {
handler?: HTMLDivElement; handler?: HTMLDivElement;
} }
export default class Resizer<C extends IConfig = IConfig> { export default class Resizer<C extends IConfig, I extends ResizeItem<C> = ResizeItem<C>> {
private classNames: IClassNames; private classNames: IClassNames;
// TODO move vertical/horizontal to config option/container class // TODO move vertical/horizontal to config option/container class
@ -46,13 +46,8 @@ export default class Resizer<C extends IConfig = IConfig> {
public constructor( public constructor(
public container: HTMLElement | null, public container: HTMLElement | null,
private readonly distributorCtor: { private readonly distributorCtor: {
new (item: ResizeItem): FixedDistributor<C, any>; new (item: I): FixedDistributor<C, I>;
createItem( createItem(resizeHandle: HTMLDivElement, resizer: Resizer<C, I>, sizer: Sizer, container?: HTMLElement): I;
resizeHandle: HTMLDivElement,
resizer: Resizer,
sizer: Sizer,
container?: HTMLElement,
): ResizeItem;
createSizer(containerElement: HTMLElement | null, vertical: boolean, reverse: boolean): Sizer; createSizer(containerElement: HTMLElement | null, vertical: boolean, reverse: boolean): Sizer;
}, },
public readonly config?: C, public readonly config?: C,
@ -87,7 +82,7 @@ export default class Resizer<C extends IConfig = IConfig> {
@param {number} handleIndex the index of the resize handle in the container @param {number} handleIndex the index of the resize handle in the container
@return {FixedDistributor} a new distributor for the given handle @return {FixedDistributor} a new distributor for the given handle
*/ */
public forHandleAt(handleIndex: number): FixedDistributor<C> | undefined { public forHandleAt(handleIndex: number): FixedDistributor<C, I> | undefined {
const handles = this.getResizeHandles(); const handles = this.getResizeHandles();
const handle = handles[handleIndex]; const handle = handles[handleIndex];
if (handle) { if (handle) {
@ -96,7 +91,7 @@ export default class Resizer<C extends IConfig = IConfig> {
} }
} }
public forHandleWithId(id: string): FixedDistributor<C> | undefined { public forHandleWithId(id: string): FixedDistributor<C, I> | undefined {
const handles = this.getResizeHandles(); const handles = this.getResizeHandles();
const handle = handles.find((h) => h.getAttribute("data-id") === id); const handle = handles.find((h) => h.getAttribute("data-id") === id);
if (handle) { if (handle) {
@ -178,7 +173,7 @@ export default class Resizer<C extends IConfig = IConfig> {
{ trailing: true, leading: true }, { trailing: true, leading: true },
); );
public getDistributors = (): FixedDistributor<any, ResizeItem<any>>[] => { public getDistributors = (): FixedDistributor<C, I>[] => {
return this.getResizeHandles().map((handle) => { return this.getResizeHandles().map((handle) => {
const { distributor } = this.createSizerAndDistributor(<HTMLDivElement>handle); const { distributor } = this.createSizerAndDistributor(<HTMLDivElement>handle);
return distributor; return distributor;
@ -187,7 +182,7 @@ export default class Resizer<C extends IConfig = IConfig> {
private createSizerAndDistributor(resizeHandle: HTMLDivElement): { private createSizerAndDistributor(resizeHandle: HTMLDivElement): {
sizer: Sizer; sizer: Sizer;
distributor: FixedDistributor<any>; distributor: FixedDistributor<C, I>;
} { } {
const vertical = resizeHandle.classList.contains(this.classNames.vertical!); const vertical = resizeHandle.classList.contains(this.classNames.vertical!);
const reverse = this.isReverseResizeHandle(resizeHandle); const reverse = this.isReverseResizeHandle(resizeHandle);

View file

@ -14,7 +14,6 @@
"jsx": "react", "jsx": "react",
"lib": ["es2020", "dom", "dom.iterable"], "lib": ["es2020", "dom", "dom.iterable"],
"strict": true, "strict": true,
"strictFunctionTypes": false,
"useUnknownInCatchVariables": false "useUnknownInCatchVariables": false
}, },
"include": [ "include": [

View file

@ -1619,10 +1619,10 @@
version "3.2.14" version "3.2.14"
resolved "https://gitlab.matrix.org/api/v4/projects/27/packages/npm/@matrix-org/olm/-/@matrix-org/olm-3.2.14.tgz#acd96c00a881d0f462e1f97a56c73742c8dbc984" resolved "https://gitlab.matrix.org/api/v4/projects/27/packages/npm/@matrix-org/olm/-/@matrix-org/olm-3.2.14.tgz#acd96c00a881d0f462e1f97a56c73742c8dbc984"
"@matrix-org/react-sdk-module-api@^0.0.5": "@matrix-org/react-sdk-module-api@^0.0.6":
version "0.0.5" version "0.0.6"
resolved "https://registry.yarnpkg.com/@matrix-org/react-sdk-module-api/-/react-sdk-module-api-0.0.5.tgz#78bd80f42b918394978965ef3e08496e97948c7a" resolved "https://registry.yarnpkg.com/@matrix-org/react-sdk-module-api/-/react-sdk-module-api-0.0.6.tgz#941872ed081acdca9d247ccd6e146265aa24010b"
integrity sha512-QhH1T1E6Q6csCUitQzm32SRnX49Ox73TF5BZ4p5TOGFpPD3QuYc5/dDC1Yh3xUljgqOS2C6H24qaskw6olCtfQ== integrity sha512-FydbJYSMecpDIGk4fVQ9djjckQdbJPV9bH3px78TQ+MX/WHmzPmjEpMPTeP3uDSeg0EWmfoIFdNypJglMqAHpw==
dependencies: dependencies:
"@babel/runtime" "^7.17.9" "@babel/runtime" "^7.17.9"