Properly type Modal props to ensure useful typescript checking (#10238

* Properly type Modal props to ensure useful typescript checking

* delint

* Iterate

* Iterate

* Fix modal.close loop

* Iterate

* Fix tests

* Add comment

* Fix test
This commit is contained in:
Michael Telatyński 2023-02-28 10:31:48 +00:00 committed by GitHub
parent ae5725b24c
commit 629e5cb01f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
124 changed files with 600 additions and 560 deletions

View file

@ -184,7 +184,7 @@ export default class AddThreepid {
* with a "message" property which contains a human-readable message detailing why
* the request failed.
*/
public async checkEmailLinkClicked(): Promise<[boolean, IAuthData | Error | null] | undefined> {
public async checkEmailLinkClicked(): Promise<[success?: boolean, result?: IAuthData | Error | null]> {
try {
if (await MatrixClientPeg.get().doesServerSupportSeparateAddAndBind()) {
if (this.bind) {
@ -202,7 +202,7 @@ export default class AddThreepid {
// The spec has always required this to use UI auth but synapse briefly
// implemented it without, so this may just succeed and that's OK.
return;
return [true];
} catch (e) {
if (e.httpStatus !== 401 || !e.data || !e.data.flows) {
// doesn't look like an interactive-auth failure
@ -225,9 +225,7 @@ export default class AddThreepid {
continueKind: "primary",
},
};
const { finished } = Modal.createDialog<[boolean, IAuthData | Error | null]>(
InteractiveAuthDialog,
{
const { finished } = Modal.createDialog(InteractiveAuthDialog, {
title: _t("Add Email Address"),
matrixClient: MatrixClientPeg.get(),
authData: e.data,
@ -236,8 +234,7 @@ export default class AddThreepid {
[SSOAuthEntry.LOGIN_TYPE]: dialogAesthetics,
[SSOAuthEntry.UNSTABLE_LOGIN_TYPE]: dialogAesthetics,
},
},
);
});
return finished;
}
}
@ -259,6 +256,7 @@ export default class AddThreepid {
}
throw err;
}
return [];
}
/**

View file

@ -18,16 +18,16 @@ import React, { ComponentType } from "react";
import { logger } from "matrix-js-sdk/src/logger";
import { _t } from "./languageHandler";
import { IDialogProps } from "./components/views/dialogs/IDialogProps";
import BaseDialog from "./components/views/dialogs/BaseDialog";
import DialogButtons from "./components/views/elements/DialogButtons";
import Spinner from "./components/views/elements/Spinner";
type AsyncImport<T> = { default: T };
interface IProps extends IDialogProps {
interface IProps {
// A promise which resolves with the real component
prom: Promise<ComponentType | AsyncImport<ComponentType>>;
prom: Promise<ComponentType<any> | AsyncImport<ComponentType<any>>>;
onFinished(): void;
}
interface IState {
@ -71,7 +71,7 @@ export default class AsyncWrapper extends React.Component<IProps, IState> {
}
private onWrapperCancelClick = (): void => {
this.props.onFinished(false);
this.props.onFinished();
};
public render(): React.ReactNode {

View file

@ -389,7 +389,7 @@ export default class ContentMessages {
}
if (tooBigFiles.length > 0) {
const { finished } = Modal.createDialog<[boolean]>(UploadFailureDialog, {
const { finished } = Modal.createDialog(UploadFailureDialog, {
badFiles: tooBigFiles,
totalFiles: files.length,
contentMessages: this,
@ -407,7 +407,7 @@ export default class ContentMessages {
const loopPromiseBefore = promBefore;
if (!uploadAll) {
const { finished } = Modal.createDialog<[boolean, boolean]>(UploadConfirmDialog, {
const { finished } = Modal.createDialog(UploadConfirmDialog, {
file,
currentIndex: i,
totalFiles: okFiles.length,

View file

@ -58,7 +58,7 @@ import IncomingLegacyCallToast, { getIncomingLegacyCallToastKey } from "./toasts
import ToastStore from "./stores/ToastStore";
import Resend from "./Resend";
import { ViewRoomPayload } from "./dispatcher/payloads/ViewRoomPayload";
import { KIND_CALL_TRANSFER } from "./components/views/dialogs/InviteDialogTypes";
import { InviteKind } from "./components/views/dialogs/InviteDialogTypes";
import { OpenInviteDialogPayload } from "./dispatcher/payloads/OpenInviteDialogPayload";
import { findDMForUser } from "./utils/dm/findDMForUser";
import { getJoinedNonFunctionalMembers } from "./utils/room/getJoinedNonFunctionalMembers";
@ -1214,7 +1214,7 @@ export default class LegacyCallHandler extends EventEmitter {
call.setRemoteOnHold(true);
dis.dispatch<OpenInviteDialogPayload>({
action: Action.OpenInviteDialog,
kind: KIND_CALL_TRANSFER,
kind: InviteKind.CallTransfer,
call,
analyticsName: "Transfer Call",
className: "mx_InviteDialog_transferWrapper",

View file

@ -265,7 +265,7 @@ export function handleInvalidStoreError(e: InvalidStoreError): Promise<void> {
.then(() => {
const lazyLoadEnabled = e.value;
if (lazyLoadEnabled) {
return new Promise((resolve) => {
return new Promise<void>((resolve) => {
Modal.createDialog(LazyLoadingResyncDialog, {
onFinished: resolve,
});
@ -275,7 +275,7 @@ export function handleInvalidStoreError(e: InvalidStoreError): Promise<void> {
// between LL/non-LL version on same host.
// as disabling LL when previously enabled
// is a strong indicator of this (/develop & /app)
return new Promise((resolve) => {
return new Promise<void>((resolve) => {
Modal.createDialog(LazyLoadingDisabledDialog, {
onFinished: resolve,
host: window.location.host,

View file

@ -27,34 +27,35 @@ import AsyncWrapper from "./AsyncWrapper";
const DIALOG_CONTAINER_ID = "mx_Dialog_Container";
const STATIC_DIALOG_CONTAINER_ID = "mx_Dialog_StaticContainer";
export interface IModal<T extends any[]> {
// Type which accepts a React Component which looks like a Modal (accepts an onFinished prop)
export type ComponentType = React.ComponentType<{
onFinished?(...args: any): void;
}>;
// Generic type which returns the props of the Modal component with the onFinished being optional.
export type ComponentProps<C extends ComponentType> = Omit<React.ComponentProps<C>, "onFinished"> &
Partial<Pick<React.ComponentProps<C>, "onFinished">>;
export interface IModal<C extends ComponentType> {
elem: React.ReactNode;
className?: string;
beforeClosePromise?: Promise<boolean>;
closeReason?: string;
onBeforeClose?(reason?: string): Promise<boolean>;
onFinished?(...args: T): void;
close(...args: T): void;
onFinished: ComponentProps<C>["onFinished"];
close(...args: Parameters<ComponentProps<C>["onFinished"]>): void;
hidden?: boolean;
}
export interface IHandle<T extends any[]> {
finished: Promise<T>;
close(...args: T): void;
export interface IHandle<C extends ComponentType> {
finished: Promise<Parameters<ComponentProps<C>["onFinished"]>>;
close(...args: Parameters<ComponentProps<C>["onFinished"]>): void;
}
interface IProps<T extends any[]> {
onFinished?(...args: T): void;
// TODO improve typing here once all Modals are TS and we can exhaustively check the props
[key: string]: any;
interface IOptions<C extends ComponentType> {
onBeforeClose?: IModal<C>["onBeforeClose"];
}
interface IOptions<T extends any[]> {
onBeforeClose?: IModal<T>["onBeforeClose"];
}
type ParametersWithoutFirst<T extends (...args: any) => any> = T extends (a: any, ...args: infer P) => any ? P : never;
export enum ModalManagerEvent {
Opened = "opened",
}
@ -111,18 +112,30 @@ export class ModalManager extends TypedEventEmitter<ModalManagerEvent, HandlerMa
return !!this.priorityModal || !!this.staticModal || this.modals.length > 0;
}
public createDialog<T extends any[]>(
Element: React.ComponentType<any>,
...rest: ParametersWithoutFirst<ModalManager["createDialogAsync"]>
): IHandle<T> {
return this.createDialogAsync<T>(Promise.resolve(Element), ...rest);
public createDialog<C extends ComponentType>(
Element: C,
props?: ComponentProps<C>,
className?: string,
isPriorityModal = false,
isStaticModal = false,
options: IOptions<C> = {},
): IHandle<C> {
return this.createDialogAsync<C>(
Promise.resolve(Element),
props,
className,
isPriorityModal,
isStaticModal,
options,
);
}
public appendDialog<T extends any[]>(
public appendDialog<C extends ComponentType>(
Element: React.ComponentType,
...rest: ParametersWithoutFirst<ModalManager["appendDialogAsync"]>
): IHandle<T> {
return this.appendDialogAsync<T>(Promise.resolve(Element), ...rest);
props?: ComponentProps<C>,
className?: string,
): IHandle<C> {
return this.appendDialogAsync<C>(Promise.resolve(Element), props, className);
}
public closeCurrentModal(reason: string): void {
@ -134,15 +147,15 @@ export class ModalManager extends TypedEventEmitter<ModalManagerEvent, HandlerMa
modal.close();
}
private buildModal<T extends any[]>(
private buildModal<C extends ComponentType>(
prom: Promise<React.ComponentType>,
props?: IProps<T>,
props?: ComponentProps<C>,
className?: string,
options?: IOptions<T>,
options?: IOptions<C>,
): {
modal: IModal<T>;
closeDialog: IHandle<T>["close"];
onFinishedProm: IHandle<T>["finished"];
modal: IModal<C>;
closeDialog: IHandle<C>["close"];
onFinishedProm: IHandle<C>["finished"];
} {
const modal = {
onFinished: props?.onFinished,
@ -151,10 +164,10 @@ export class ModalManager extends TypedEventEmitter<ModalManagerEvent, HandlerMa
// these will be set below but we need an object reference to pass to getCloseFn before we can do that
elem: null,
} as IModal<T>;
} as IModal<C>;
// never call this from onFinished() otherwise it will loop
const [closeDialog, onFinishedProm] = this.getCloseFn<T>(modal, props);
const [closeDialog, onFinishedProm] = this.getCloseFn<C>(modal, props);
// don't attempt to reuse the same AsyncWrapper for different dialogs,
// otherwise we'll get confused.
@ -168,13 +181,13 @@ export class ModalManager extends TypedEventEmitter<ModalManagerEvent, HandlerMa
return { modal, closeDialog, onFinishedProm };
}
private getCloseFn<T extends any[]>(
modal: IModal<T>,
props?: IProps<T>,
): [IHandle<T>["close"], IHandle<T>["finished"]] {
const deferred = defer<T>();
private getCloseFn<C extends ComponentType>(
modal: IModal<C>,
props?: ComponentProps<C>,
): [IHandle<C>["close"], IHandle<C>["finished"]] {
const deferred = defer<Parameters<ComponentProps<C>["onFinished"]>>();
return [
async (...args: T): Promise<void> => {
async (...args: Parameters<ComponentProps<C>["onFinished"]>): Promise<void> => {
if (modal.beforeClosePromise) {
await modal.beforeClosePromise;
} else if (modal.onBeforeClose) {
@ -249,16 +262,16 @@ export class ModalManager extends TypedEventEmitter<ModalManagerEvent, HandlerMa
* @param {onBeforeClose} options.onBeforeClose a callback to decide whether to close the dialog
* @returns {object} Object with 'close' parameter being a function that will close the dialog
*/
public createDialogAsync<T extends any[]>(
prom: Promise<React.ComponentType>,
props?: IProps<T>,
public createDialogAsync<C extends ComponentType>(
prom: Promise<C>,
props?: ComponentProps<C>,
className?: string,
isPriorityModal = false,
isStaticModal = false,
options: IOptions<T> = {},
): IHandle<T> {
options: IOptions<C> = {},
): IHandle<C> {
const beforeModal = this.getCurrentModal();
const { modal, closeDialog, onFinishedProm } = this.buildModal<T>(prom, props, className, options);
const { modal, closeDialog, onFinishedProm } = this.buildModal<C>(prom, props, className, options);
if (isPriorityModal) {
// XXX: This is destructive
this.priorityModal = modal;
@ -278,13 +291,13 @@ export class ModalManager extends TypedEventEmitter<ModalManagerEvent, HandlerMa
};
}
private appendDialogAsync<T extends any[]>(
private appendDialogAsync<C extends ComponentType>(
prom: Promise<React.ComponentType>,
props?: IProps<T>,
props?: ComponentProps<C>,
className?: string,
): IHandle<T> {
): IHandle<C> {
const beforeModal = this.getCurrentModal();
const { modal, closeDialog, onFinishedProm } = this.buildModal<T>(prom, props, className, {});
const { modal, closeDialog, onFinishedProm } = this.buildModal<C>(prom, props, className, {});
this.modals.push(modal);

View file

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import React from "react";
import React, { ComponentProps } from "react";
import { Room } from "matrix-js-sdk/src/models/room";
import { MatrixEvent } from "matrix-js-sdk/src/models/event";
import { User } from "matrix-js-sdk/src/models/user";
@ -29,7 +29,7 @@ import InviteDialog from "./components/views/dialogs/InviteDialog";
import BaseAvatar from "./components/views/avatars/BaseAvatar";
import { mediaFromMxc } from "./customisations/Media";
import ErrorDialog from "./components/views/dialogs/ErrorDialog";
import { KIND_DM, KIND_INVITE } from "./components/views/dialogs/InviteDialogTypes";
import { InviteKind } from "./components/views/dialogs/InviteDialogTypes";
import { Member } from "./utils/direct-messages";
export interface IInviteResult {
@ -64,7 +64,7 @@ export function showStartChatInviteDialog(initialText = ""): void {
// This dialog handles the room creation internally - we don't need to worry about it.
Modal.createDialog(
InviteDialog,
{ kind: KIND_DM, initialText },
{ kind: InviteKind.Dm, initialText },
/*className=*/ "mx_InviteDialog_flexWrapper",
/*isPriority=*/ false,
/*isStatic=*/ true,
@ -76,10 +76,10 @@ export function showRoomInviteDialog(roomId: string, initialText = ""): void {
Modal.createDialog(
InviteDialog,
{
kind: KIND_INVITE,
kind: InviteKind.Invite,
initialText,
roomId,
},
} as Omit<ComponentProps<typeof InviteDialog>, "onFinished">,
/*className=*/ "mx_InviteDialog_flexWrapper",
/*isPriority=*/ false,
/*isStatic=*/ true,

View file

@ -22,13 +22,13 @@ import { decodeRecoveryKey } from "matrix-js-sdk/src/crypto/recoverykey";
import { encodeBase64 } from "matrix-js-sdk/src/crypto/olmlib";
import { DeviceTrustLevel } from "matrix-js-sdk/src/crypto/CrossSigning";
import { logger } from "matrix-js-sdk/src/logger";
import { ComponentType } from "react";
import type CreateSecretStorageDialog from "./async-components/views/dialogs/security/CreateSecretStorageDialog";
import Modal from "./Modal";
import { MatrixClientPeg } from "./MatrixClientPeg";
import { _t } from "./languageHandler";
import { isSecureBackupRequired } from "./utils/WellKnownUtils";
import AccessSecretStorageDialog from "./components/views/dialogs/security/AccessSecretStorageDialog";
import AccessSecretStorageDialog, { KeyParams } from "./components/views/dialogs/security/AccessSecretStorageDialog";
import RestoreKeyBackupDialog from "./components/views/dialogs/security/RestoreKeyBackupDialog";
import SettingsStore from "./settings/SettingsStore";
import SecurityCustomisations from "./customisations/Security";
@ -83,8 +83,6 @@ async function confirmToDismiss(): Promise<boolean> {
return !sure;
}
type KeyParams = { passphrase: string; recoveryKey: string };
function makeInputToKey(keyInfo: ISecretStorageKeyInfo): (keyParams: KeyParams) => Promise<Uint8Array> {
return async ({ passphrase, recoveryKey }): Promise<Uint8Array> => {
if (passphrase) {
@ -333,7 +331,7 @@ export async function accessSecretStorage(func = async (): Promise<void> => {},
// passphrase creation.
const { finished } = Modal.createDialogAsync(
import("./async-components/views/dialogs/security/CreateSecretStorageDialog") as unknown as Promise<
ComponentType<{}>
typeof CreateSecretStorageDialog
>,
{
forceReset,

View file

@ -551,7 +551,7 @@ export const Commands = [
) {
const defaultIdentityServerUrl = getDefaultIdentityServerUrl();
if (defaultIdentityServerUrl) {
const { finished } = Modal.createDialog<[boolean]>(QuestionDialog, {
const { finished } = Modal.createDialog(QuestionDialog, {
title: _t("Use an identity server"),
description: (
<p>

View file

@ -191,7 +191,7 @@ export async function dialogTermsInteractionCallback(
): Promise<string[]> {
logger.log("Terms that need agreement", policiesAndServicePairs);
const { finished } = Modal.createDialog<[boolean, string[]]>(
const { finished } = Modal.createDialog(
TermsDialog,
{
policiesAndServicePairs,

View file

@ -27,7 +27,7 @@ import { Action } from "../../../../dispatcher/actions";
import { SettingLevel } from "../../../../settings/SettingLevel";
interface IProps {
onFinished: (success: boolean) => void;
onFinished: (success?: boolean) => void;
}
interface IState {

View file

@ -27,10 +27,11 @@ import { SettingLevel } from "../../../../settings/SettingLevel";
import Field from "../../../../components/views/elements/Field";
import BaseDialog from "../../../../components/views/dialogs/BaseDialog";
import DialogButtons from "../../../../components/views/elements/DialogButtons";
import { IDialogProps } from "../../../../components/views/dialogs/IDialogProps";
import { IIndexStats } from "../../../../indexing/BaseEventIndexManager";
interface IProps extends IDialogProps {}
interface IProps {
onFinished(): void;
}
interface IState {
eventIndexSize: number;

View file

@ -26,7 +26,6 @@ import { accessSecretStorage } from "../../../../SecurityManager";
import AccessibleButton from "../../../../components/views/elements/AccessibleButton";
import { copyNode } from "../../../../utils/strings";
import PassphraseField from "../../../../components/views/auth/PassphraseField";
import { IDialogProps } from "../../../../components/views/dialogs/IDialogProps";
import Field from "../../../../components/views/elements/Field";
import Spinner from "../../../../components/views/elements/Spinner";
import BaseDialog from "../../../../components/views/dialogs/BaseDialog";
@ -45,7 +44,9 @@ enum Phase {
const PASSWORD_MIN_SCORE = 4; // So secure, many characters, much complex, wow, etc, etc.
interface IProps extends IDialogProps {}
interface IProps {
onFinished(done?: boolean): void;
}
interface IState {
secureSecretStorage: boolean;

View file

@ -43,7 +43,6 @@ import {
SecureBackupSetupMethod,
} from "../../../../utils/WellKnownUtils";
import SecurityCustomisations from "../../../../customisations/Security";
import { IDialogProps } from "../../../../components/views/dialogs/IDialogProps";
import Field from "../../../../components/views/elements/Field";
import BaseDialog from "../../../../components/views/dialogs/BaseDialog";
import Spinner from "../../../../components/views/elements/Spinner";
@ -67,10 +66,11 @@ enum Phase {
const PASSWORD_MIN_SCORE = 4; // So secure, many characters, much complex, wow, etc, etc.
interface IProps extends IDialogProps {
hasCancel: boolean;
accountPassword: string;
forceReset: boolean;
interface IProps {
hasCancel?: boolean;
accountPassword?: string;
forceReset?: boolean;
onFinished(ok?: boolean): void;
}
interface IState {

View file

@ -22,7 +22,6 @@ import { logger } from "matrix-js-sdk/src/logger";
import { _t } from "../../../../languageHandler";
import * as MegolmExportEncryption from "../../../../utils/MegolmExportEncryption";
import { IDialogProps } from "../../../../components/views/dialogs/IDialogProps";
import BaseDialog from "../../../../components/views/dialogs/BaseDialog";
import Field from "../../../../components/views/elements/Field";
import { KeysStartingWith } from "../../../../@types/common";
@ -32,8 +31,9 @@ enum Phase {
Exporting = "exporting",
}
interface IProps extends IDialogProps {
interface IProps {
matrixClient: MatrixClient;
onFinished(doExport?: boolean): void;
}
interface IState {

View file

@ -21,7 +21,6 @@ import { logger } from "matrix-js-sdk/src/logger";
import * as MegolmExportEncryption from "../../../../utils/MegolmExportEncryption";
import { _t } from "../../../../languageHandler";
import { IDialogProps } from "../../../../components/views/dialogs/IDialogProps";
import BaseDialog from "../../../../components/views/dialogs/BaseDialog";
import Field from "../../../../components/views/elements/Field";
@ -42,8 +41,9 @@ enum Phase {
Importing = "importing",
}
interface IProps extends IDialogProps {
interface IProps {
matrixClient: MatrixClient;
onFinished(imported?: boolean): void;
}
interface IState {

View file

@ -24,12 +24,12 @@ import { _t } from "../../../../languageHandler";
import Modal from "../../../../Modal";
import RestoreKeyBackupDialog from "../../../../components/views/dialogs/security/RestoreKeyBackupDialog";
import { Action } from "../../../../dispatcher/actions";
import { IDialogProps } from "../../../../components/views/dialogs/IDialogProps";
import DialogButtons from "../../../../components/views/elements/DialogButtons";
import BaseDialog from "../../../../components/views/dialogs/BaseDialog";
interface IProps extends IDialogProps {
interface IProps {
newVersionInfo: IKeyBackupInfo;
onFinished(): void;
}
export default class NewRecoveryMethodDialog extends React.PureComponent<IProps> {

View file

@ -21,11 +21,12 @@ import dis from "../../../../dispatcher/dispatcher";
import { _t } from "../../../../languageHandler";
import Modal from "../../../../Modal";
import { Action } from "../../../../dispatcher/actions";
import { IDialogProps } from "../../../../components/views/dialogs/IDialogProps";
import BaseDialog from "../../../../components/views/dialogs/BaseDialog";
import DialogButtons from "../../../../components/views/elements/DialogButtons";
interface IProps extends IDialogProps {}
interface IProps {
onFinished(): void;
}
export default class RecoveryMethodRemovedDialog extends React.PureComponent<IProps> {
private onGoToSettingsClick = (): void => {

View file

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import React, { ComponentType, createRef } from "react";
import React, { createRef } from "react";
import {
ClientEvent,
createClient,
@ -38,6 +38,8 @@ import "focus-visible";
// what-input helps improve keyboard accessibility
import "what-input";
import type NewRecoveryMethodDialog from "../../async-components/views/dialogs/security/NewRecoveryMethodDialog";
import type RecoveryMethodRemovedDialog from "../../async-components/views/dialogs/security/RecoveryMethodRemovedDialog";
import PosthogTrackers from "../../PosthogTrackers";
import { DecryptionFailureTracker } from "../../DecryptionFailureTracker";
import { IMatrixClientCreds, MatrixClientPeg } from "../../MatrixClientPeg";
@ -140,6 +142,7 @@ import RovingSpotlightDialog, { Filter } from "../views/dialogs/spotlight/Spotli
import { findDMForUser } from "../../utils/dm/findDMForUser";
import { Linkify } from "../../HtmlUtils";
import { NotificationColor } from "../../stores/notifications/NotificationColor";
import { UserTab } from "../views/dialogs/UserTab";
// legacy export
export { default as Views } from "../../Views";
@ -705,7 +708,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
const tabPayload = payload as OpenToTabPayload;
Modal.createDialog(
UserSettingsDialog,
{ initialTabId: tabPayload.initialTabId },
{ initialTabId: tabPayload.initialTabId as UserTab },
/*className=*/ null,
/*isPriority=*/ false,
/*isStatic=*/ true,
@ -1629,14 +1632,14 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
Modal.createDialogAsync(
import(
"../../async-components/views/dialogs/security/NewRecoveryMethodDialog"
) as unknown as Promise<ComponentType<{}>>,
) as unknown as Promise<typeof NewRecoveryMethodDialog>,
{ newVersionInfo },
);
} else {
Modal.createDialogAsync(
import(
"../../async-components/views/dialogs/security/RecoveryMethodRemovedDialog"
) as unknown as Promise<ComponentType<{}>>,
) as unknown as Promise<typeof RecoveryMethodRemovedDialog>,
);
}
});

View file

@ -23,15 +23,15 @@ import { _t } from "../../languageHandler";
import MatrixClientContext from "../../contexts/MatrixClientContext";
import { canEditContent } from "../../utils/EventUtils";
import { MatrixClientPeg } from "../../MatrixClientPeg";
import { IDialogProps } from "../views/dialogs/IDialogProps";
import BaseDialog from "../views/dialogs/BaseDialog";
import { DevtoolsContext } from "../views/dialogs/devtools/BaseTool";
import { StateEventEditor } from "../views/dialogs/devtools/RoomState";
import { stringify, TimelineEventEditor } from "../views/dialogs/devtools/Event";
import CopyableText from "../views/elements/CopyableText";
interface IProps extends IDialogProps {
interface IProps {
mxEvent: MatrixEvent; // the MatrixEvent associated with the context menu
onFinished(): void;
}
interface IState {

View file

@ -368,7 +368,7 @@ export default class ForgotPassword extends React.Component<Props, State> {
}
public async renderConfirmLogoutDevicesDialog(): Promise<boolean> {
const { finished } = Modal.createDialog<[boolean]>(QuestionDialog, {
const { finished } = Modal.createDialog(QuestionDialog, {
title: _t("Warning!"),
description: (
<div>

View file

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import React from "react";
import React, { ReactNode } from "react";
import { _t } from "../../../../languageHandler";
import AccessibleButton from "../../../views/elements/AccessibleButton";
@ -26,7 +26,8 @@ import { ErrorMessage } from "../../ErrorMessage";
interface Props {
email: string;
errorText: string | null;
errorText: ReactNode | null;
onFinished(): void; // This modal is weird in that the way you close it signals intent
onCloseClick: () => void;
onReEnterEmailClick: () => void;
onResendClick: () => Promise<boolean>;

View file

@ -23,7 +23,6 @@ import { Icon as LiveLocationIcon } from "../../../../res/img/location/live-loca
import { useLiveBeacons } from "../../../utils/beacon/useLiveBeacons";
import MatrixClientContext from "../../../contexts/MatrixClientContext";
import BaseDialog from "../dialogs/BaseDialog";
import { IDialogProps } from "../dialogs/IDialogProps";
import Map from "../location/Map";
import ZoomButtons from "../location/ZoomButtons";
import BeaconMarker from "./BeaconMarker";
@ -38,11 +37,12 @@ import MapFallback from "../location/MapFallback";
import { MapError } from "../location/MapError";
import { LocationShareError } from "../../../utils/location";
interface IProps extends IDialogProps {
interface IProps {
roomId: Room["roomId"];
matrixClient: MatrixClient;
// open the map centered on this beacon's location
initialFocusedBeacon?: Beacon;
onFinished(): void;
}
// track the 'focused time' as ts

View file

@ -25,13 +25,16 @@ import AccessibleButton from "../elements/AccessibleButton";
import QRCode from "../elements/QRCode";
import Heading from "../typography/Heading";
import BaseDialog from "./BaseDialog";
import { IDialogProps } from "./IDialogProps";
const fallbackAppStore = "https://apps.apple.com/app/vector/id1083446067";
const fallbackGooglePlay = "https://play.google.com/store/apps/details?id=im.vector.app";
const fallbackFDroid = "https://f-droid.org/repository/browse/?fdid=im.vector.app";
export const AppDownloadDialog: FC<IDialogProps> = ({ onFinished }: IDialogProps) => {
interface Props {
onFinished(): void;
}
export const AppDownloadDialog: FC<Props> = ({ onFinished }) => {
const brand = SdkConfig.get("brand");
const desktopBuilds = SdkConfig.getObject("desktop_builds");
const mobileBuilds = SdkConfig.getObject("mobile_builds");

View file

@ -21,17 +21,16 @@ import FocusLock from "react-focus-lock";
import classNames from "classnames";
import { MatrixClient } from "matrix-js-sdk/src/client";
import AccessibleButton, { ButtonEvent } from "../elements/AccessibleButton";
import AccessibleButton from "../elements/AccessibleButton";
import { MatrixClientPeg } from "../../../MatrixClientPeg";
import { _t } from "../../../languageHandler";
import MatrixClientContext from "../../../contexts/MatrixClientContext";
import Heading from "../typography/Heading";
import { IDialogProps } from "./IDialogProps";
import { PosthogScreenTracker, ScreenName } from "../../../PosthogTrackers";
import { getKeyBindingsManager } from "../../../KeyBindingsManager";
import { KeyBindingAction } from "../../../accessibility/KeyboardShortcuts";
interface IProps extends IDialogProps {
interface IProps {
// Whether the dialog should have a 'close' button that will
// cause the dialog to be cancelled. This should only be set
// to false if there is nothing the app can sensibly do if the
@ -75,6 +74,7 @@ interface IProps extends IDialogProps {
// optional Posthog ScreenName to supply during the lifetime of this dialog
"screenName"?: ScreenName;
onFinished(): void;
}
/*
@ -86,7 +86,7 @@ interface IProps extends IDialogProps {
export default class BaseDialog extends React.Component<IProps> {
private matrixClient: MatrixClient;
public static defaultProps = {
public static defaultProps: Partial<IProps> = {
hasCancel: true,
fixedWidth: true,
};
@ -98,9 +98,7 @@ export default class BaseDialog extends React.Component<IProps> {
}
private onKeyDown = (e: KeyboardEvent | React.KeyboardEvent): void => {
if (this.props.onKeyDown) {
this.props.onKeyDown(e);
}
this.props.onKeyDown?.(e);
const action = getKeyBindingsManager().getAccessibilityAction(e);
switch (action) {
@ -109,13 +107,13 @@ export default class BaseDialog extends React.Component<IProps> {
e.stopPropagation();
e.preventDefault();
this.props.onFinished(false);
this.props.onFinished();
break;
}
};
private onCancelClick = (e: ButtonEvent): void => {
this.props.onFinished(false);
private onCancelClick = (): void => {
this.props.onFinished();
};
public render(): React.ReactNode {

View file

@ -17,7 +17,6 @@ limitations under the License.
import React from "react";
import { _t } from "../../../languageHandler";
import { IDialogProps } from "./IDialogProps";
import SettingsStore from "../../../settings/SettingsStore";
import AccessibleButton from "../elements/AccessibleButton";
import defaultDispatcher from "../../../dispatcher/dispatcher";
@ -27,8 +26,9 @@ import GenericFeatureFeedbackDialog from "./GenericFeatureFeedbackDialog";
// XXX: Keep this around for re-use in future Betas
interface IProps extends IDialogProps {
interface IProps {
featureId: string;
onFinished(sendFeedback?: boolean): void;
}
const BetaFeedbackDialog: React.FC<IProps> = ({ featureId, onFinished }) => {
@ -49,7 +49,7 @@ const BetaFeedbackDialog: React.FC<IProps> = ({ featureId, onFinished }) => {
<AccessibleButton
kind="link_inline"
onClick={() => {
onFinished(false);
onFinished();
defaultDispatcher.dispatch({
action: Action.ViewUserSettings,
initialTabId: UserTab.Labs,

View file

@ -26,19 +26,19 @@ import { MatrixEvent } from "matrix-js-sdk/src/models/event";
import { _t } from "../../../languageHandler";
import dis from "../../../dispatcher/dispatcher";
import { Action } from "../../../dispatcher/actions";
import { IDialogProps } from "./IDialogProps";
import BaseDialog from "../dialogs/BaseDialog";
import InfoDialog from "../dialogs/InfoDialog";
import DialogButtons from "../elements/DialogButtons";
import StyledCheckbox from "../elements/StyledCheckbox";
interface IBulkRedactDialogProps extends IDialogProps {
interface Props {
matrixClient: MatrixClient;
room: Room;
member: RoomMember;
onFinished(redact?: boolean): void;
}
const BulkRedactDialog: React.FC<IBulkRedactDialogProps> = (props) => {
const BulkRedactDialog: React.FC<Props> = (props) => {
const { matrixClient: cli, room, member, onFinished } = props;
const [keepStateEvents, setKeepStateEvents] = useState(true);

View file

@ -24,7 +24,7 @@ import Spinner from "../elements/Spinner";
interface IProps {
redact: () => Promise<void>;
onFinished: (success: boolean) => void;
onFinished: (success?: boolean) => void;
}
interface IState {

View file

@ -39,7 +39,7 @@ interface IProps {
children?: ReactNode;
className?: string;
roomId?: string;
onFinished: (success: boolean, reason?: string) => void;
onFinished: (success?: boolean, reason?: string) => void;
}
interface IState {
@ -55,7 +55,7 @@ interface IState {
* Also tweaks the style for 'dangerous' actions (albeit only with colour)
*/
export default class ConfirmUserActionDialog extends React.Component<IProps, IState> {
public static defaultProps = {
public static defaultProps: Partial<IProps> = {
danger: false,
askReason: false,
};

View file

@ -21,7 +21,7 @@ import BaseDialog from "./BaseDialog";
import DialogButtons from "../elements/DialogButtons";
interface IProps {
onFinished: (success: boolean) => void;
onFinished: (success?: boolean) => void;
}
export default class ConfirmWipeDeviceDialog extends React.Component<IProps> {

View file

@ -41,7 +41,7 @@ interface IProps {
defaultName?: string;
parentSpace?: Room;
defaultEncrypted?: boolean;
onFinished(proceed: boolean, opts?: IOpts): void;
onFinished(proceed?: boolean, opts?: IOpts): void;
}
interface IState {

View file

@ -24,9 +24,10 @@ import Modal from "../../../Modal";
import BaseDialog from "./BaseDialog";
import DialogButtons from "../elements/DialogButtons";
import QuestionDialog from "./QuestionDialog";
import { IDialogProps } from "./IDialogProps";
interface IProps extends IDialogProps {}
interface IProps {
onFinished(logout?: boolean): void;
}
const CryptoStoreTooNewDialog: React.FC<IProps> = (props: IProps) => {
const brand = SdkConfig.get().brand;
@ -72,7 +73,7 @@ const CryptoStoreTooNewDialog: React.FC<IProps> = (props: IProps) => {
<DialogButtons
primaryButton={_t("Continue With Encryption Disabled")}
hasCancel={false}
onPrimaryButtonClick={props.onFinished}
onPrimaryButtonClick={() => props.onFinished(false)}
>
<button onClick={_onLogoutClicked}>{_t("Sign out")}</button>
</DialogButtons>

View file

@ -39,7 +39,7 @@ type DialogAesthetics = Partial<{
}>;
interface IProps {
onFinished: (success: boolean) => void;
onFinished: (success?: boolean) => void;
}
interface IState {

View file

@ -65,7 +65,7 @@ const Tools: Record<Category, [label: string, tool: Tool][]> = {
interface IProps {
roomId: string;
onFinished(finished: boolean): void;
onFinished(finished?: boolean): void;
}
type ToolInfo = [label: string, tool: Tool];

View file

@ -20,17 +20,16 @@ import { MatrixClient } from "matrix-js-sdk/src/client";
import { PollEndEvent } from "matrix-js-sdk/src/extensible_events_v1/PollEndEvent";
import { _t } from "../../../languageHandler";
import { IDialogProps } from "./IDialogProps";
import QuestionDialog from "./QuestionDialog";
import { findTopAnswer } from "../messages/MPollBody";
import Modal from "../../../Modal";
import ErrorDialog from "./ErrorDialog";
import { GetRelationsForEvent } from "../rooms/EventTile";
interface IProps extends IDialogProps {
interface IProps {
matrixClient: MatrixClient;
event: MatrixEvent;
onFinished: (success: boolean) => void;
onFinished: (success?: boolean) => void;
getRelationsForEvent?: GetRelationsForEvent;
}

View file

@ -31,7 +31,7 @@ import { _t } from "../../../languageHandler";
import BaseDialog from "./BaseDialog";
interface IProps {
onFinished: (success: boolean) => void;
onFinished: (success?: boolean) => void;
title?: string;
description?: React.ReactNode;
button?: string;
@ -44,7 +44,7 @@ interface IState {
}
export default class ErrorDialog extends React.Component<IProps, IState> {
public static defaultProps = {
public static defaultProps: Partial<IProps> = {
focus: true,
};

View file

@ -19,7 +19,6 @@ import { Room } from "matrix-js-sdk/src/matrix";
import { logger } from "matrix-js-sdk/src/logger";
import { _t } from "../../../languageHandler";
import { IDialogProps } from "./IDialogProps";
import BaseDialog from "./BaseDialog";
import DialogButtons from "../elements/DialogButtons";
import Field from "../elements/Field";
@ -44,8 +43,9 @@ import InfoDialog from "./InfoDialog";
import ChatExport from "../../../customisations/ChatExport";
import { validateNumberInRange } from "../../../utils/validate";
interface IProps extends IDialogProps {
interface IProps {
room: Room;
onFinished(doExport?: boolean): void;
}
interface ExportConfig {

View file

@ -24,7 +24,6 @@ import SdkConfig from "../../../SdkConfig";
import Modal from "../../../Modal";
import BugReportDialog from "./BugReportDialog";
import InfoDialog from "./InfoDialog";
import { IDialogProps } from "./IDialogProps";
import { submitFeedback } from "../../../rageshake/submit-rageshake";
import { useStateToggle } from "../../../hooks/useStateToggle";
import StyledCheckbox from "../elements/StyledCheckbox";
@ -33,8 +32,9 @@ const existingIssuesUrl =
"https://github.com/vector-im/element-web/issues" + "?q=is%3Aopen+is%3Aissue+sort%3Areactions-%2B1-desc";
const newIssueUrl = "https://github.com/vector-im/element-web/issues/new/choose";
interface IProps extends IDialogProps {
interface IProps {
feature?: string;
onFinished(): void;
}
const FeedbackDialog: React.FC<IProps> = (props: IProps) => {

View file

@ -29,7 +29,6 @@ import { _t } from "../../../languageHandler";
import dis from "../../../dispatcher/dispatcher";
import { useSettingValue } from "../../../hooks/useSettings";
import { Layout } from "../../../settings/enums/Layout";
import { IDialogProps } from "./IDialogProps";
import BaseDialog from "./BaseDialog";
import { avatarUrlForUser } from "../../../Avatar";
import EventTile from "../rooms/EventTile";
@ -55,13 +54,14 @@ import { RoomContextDetails } from "../rooms/RoomContextDetails";
const AVATAR_SIZE = 30;
interface IProps extends IDialogProps {
interface IProps {
matrixClient: MatrixClient;
// The event to forward
event: MatrixEvent;
// We need a permalink creator for the source room to pass through to EventTile
// in case the event is a reply (even though the user can't get at the link)
permalinkCreator: RoomPermalinkCreator;
onFinished(): void;
}
interface IEntryProps {

View file

@ -20,17 +20,17 @@ import QuestionDialog from "./QuestionDialog";
import { _t } from "../../../languageHandler";
import Field from "../elements/Field";
import SdkConfig from "../../../SdkConfig";
import { IDialogProps } from "./IDialogProps";
import { submitFeedback } from "../../../rageshake/submit-rageshake";
import StyledCheckbox from "../elements/StyledCheckbox";
import Modal from "../../../Modal";
import InfoDialog from "./InfoDialog";
interface IProps extends IDialogProps {
interface IProps {
title: string;
subheading: string;
rageshakeLabel: string;
rageshakeData?: Record<string, string>;
onFinished(sendFeedback?: boolean): void;
}
const GenericFeatureFeedbackDialog: React.FC<IProps> = ({

View file

@ -1,19 +0,0 @@
/*
Copyright 2020 The Matrix.org Foundation C.I.C.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
export interface IDialogProps {
onFinished(...args: any): void;
}

View file

@ -29,7 +29,6 @@ import Spinner from "../elements/Spinner";
import VerificationShowSas from "../verification/VerificationShowSas";
import BaseDialog from "./BaseDialog";
import DialogButtons from "../elements/DialogButtons";
import { IDialogProps } from "./IDialogProps";
const PHASE_START = 0;
const PHASE_SHOW_SAS = 1;
@ -37,8 +36,9 @@ const PHASE_WAIT_FOR_PARTNER_TO_CONFIRM = 2;
const PHASE_VERIFIED = 3;
const PHASE_CANCELLED = 4;
interface IProps extends IDialogProps {
interface IProps {
verifier: VerificationBase<SasEvent, any>;
onFinished(verified?: boolean): void;
}
interface IState {

View file

@ -19,11 +19,10 @@ import React, { ReactNode, KeyboardEvent } from "react";
import classNames from "classnames";
import { _t } from "../../../languageHandler";
import { IDialogProps } from "./IDialogProps";
import BaseDialog from "./BaseDialog";
import DialogButtons from "../elements/DialogButtons";
interface IProps extends IDialogProps {
interface IProps {
top?: ReactNode;
title?: string;
description?: ReactNode;
@ -32,10 +31,11 @@ interface IProps extends IDialogProps {
hasCloseButton?: boolean;
fixedWidth?: boolean;
onKeyDown?(event: KeyboardEvent): void;
onFinished(): void;
}
export default class InfoDialog extends React.Component<IProps> {
public static defaultProps = {
public static defaultProps: Partial<IProps> = {
title: "",
description: "",
hasCloseButton: false,

View file

@ -21,9 +21,10 @@ import dis from "../../../dispatcher/dispatcher";
import { Action } from "../../../dispatcher/actions";
import BaseDialog from "./BaseDialog";
import DialogButtons from "../elements/DialogButtons";
import { IDialogProps } from "./IDialogProps";
interface IProps extends IDialogProps {}
interface IProps {
onFinished(): void;
}
export default class IntegrationsDisabledDialog extends React.Component<IProps> {
private onAcknowledgeClick = (): void => {

View file

@ -18,11 +18,12 @@ import React from "react";
import { _t } from "../../../languageHandler";
import SdkConfig from "../../../SdkConfig";
import { IDialogProps } from "./IDialogProps";
import BaseDialog from "./BaseDialog";
import DialogButtons from "../elements/DialogButtons";
interface IProps extends IDialogProps {}
interface IProps {
onFinished(): void;
}
export default class IntegrationsImpossibleDialog extends React.Component<IProps> {
private onAcknowledgeClick = (): void => {

View file

@ -25,7 +25,6 @@ import AccessibleButton from "../elements/AccessibleButton";
import InteractiveAuth, { ERROR_USER_CANCELLED, InteractiveAuthCallback } from "../../structures/InteractiveAuth";
import { SSOAuthEntry } from "../auth/InteractiveAuthEntryComponents";
import BaseDialog from "./BaseDialog";
import { IDialogProps } from "./IDialogProps";
type DialogAesthetics = Partial<{
[x in AuthType]: {
@ -38,7 +37,7 @@ type DialogAesthetics = Partial<{
};
}>;
export interface InteractiveAuthDialogProps extends IDialogProps {
export interface InteractiveAuthDialogProps {
// matrix client to use for UI auth requests
matrixClient: MatrixClient;
@ -72,6 +71,8 @@ export interface InteractiveAuthDialogProps extends IDialogProps {
//
// Default is defined in _getDefaultDialogAesthetics()
aestheticsForStagePhases?: DialogAesthetics;
onFinished(success?: boolean, result?: IAuthData | Error | null): void;
}
interface IState {
@ -152,14 +153,14 @@ export default class InteractiveAuthDialog extends React.Component<InteractiveAu
if (!this.state.authError && dialogAesthetics) {
if (dialogAesthetics[this.state.uiaStage]) {
const aesthetics = dialogAesthetics[this.state.uiaStage][this.state.uiaStagePhase];
if (aesthetics && aesthetics.title) title = aesthetics.title;
if (aesthetics && aesthetics.body) body = aesthetics.body;
if (aesthetics && aesthetics.continueText) continueText = aesthetics.continueText;
if (aesthetics && aesthetics.continueKind) continueKind = aesthetics.continueKind;
if (aesthetics?.title) title = aesthetics.title;
if (aesthetics?.body) body = aesthetics.body;
if (aesthetics?.continueText) continueText = aesthetics.continueText;
if (aesthetics?.continueKind) continueKind = aesthetics.continueKind;
}
}
let content;
let content: JSX.Element;
if (this.state.authError) {
content = (
<div id="mx_Dialog_content">

View file

@ -70,7 +70,7 @@ import {
startDmOnFirstMessage,
ThreepidMember,
} from "../../../utils/direct-messages";
import { KIND_CALL_TRANSFER, KIND_DM, KIND_INVITE } from "./InviteDialogTypes";
import { InviteKind } from "./InviteDialogTypes";
import Modal from "../../../Modal";
import dis from "../../../dispatcher/dispatcher";
@ -253,32 +253,32 @@ interface BaseProps {
// Takes a boolean which is true if a user / users were invited /
// a call transfer was initiated or false if the dialog was cancelled
// with no action taken.
onFinished: (success: boolean) => void;
onFinished: (success?: boolean) => void;
// Initial value to populate the filter with
initialText?: string;
}
interface InviteDMProps extends BaseProps {
// The kind of invite being performed. Assumed to be KIND_DM if not provided.
kind?: typeof KIND_DM;
// The kind of invite being performed. Assumed to be InviteKind.Dm if not provided.
kind?: InviteKind.Dm;
}
interface InviteRoomProps extends BaseProps {
kind: typeof KIND_INVITE;
kind: InviteKind.Invite;
// The room ID this dialog is for. Only required for KIND_INVITE.
// The room ID this dialog is for. Only required for InviteKind.Invite.
roomId: string;
}
function isRoomInvite(props: Props): props is InviteRoomProps {
return props.kind === KIND_INVITE;
return props.kind === InviteKind.Invite;
}
interface InviteCallProps extends BaseProps {
kind: typeof KIND_CALL_TRANSFER;
kind: InviteKind.CallTransfer;
// The call to transfer. Only required for KIND_CALL_TRANSFER.
// The call to transfer. Only required for InviteKind.CallTransfer.
call: MatrixCall;
}
@ -305,8 +305,8 @@ interface IInviteDialogState {
}
export default class InviteDialog extends React.PureComponent<Props, IInviteDialogState> {
public static defaultProps = {
kind: KIND_DM,
public static defaultProps: Partial<Props> = {
kind: InviteKind.Dm,
initialText: "",
};
@ -318,10 +318,10 @@ export default class InviteDialog extends React.PureComponent<Props, IInviteDial
public constructor(props: Props) {
super(props);
if (props.kind === KIND_INVITE && !props.roomId) {
throw new Error("When using KIND_INVITE a roomId is required for an InviteDialog");
} else if (props.kind === KIND_CALL_TRANSFER && !props.call) {
throw new Error("When using KIND_CALL_TRANSFER a call is required for an InviteDialog");
if (props.kind === InviteKind.Invite && !props.roomId) {
throw new Error("When using InviteKind.Invite a roomId is required for an InviteDialog");
} else if (props.kind === InviteKind.CallTransfer && !props.call) {
throw new Error("When using InviteKind.CallTransfer a call is required for an InviteDialog");
}
const alreadyInvited = new Set([MatrixClientPeg.get().getUserId()!, SdkConfig.get("welcome_user_id")]);
@ -493,7 +493,7 @@ export default class InviteDialog extends React.PureComponent<Props, IInviteDial
};
private inviteUsers = async (): Promise<void> => {
if (this.props.kind !== KIND_INVITE) return;
if (this.props.kind !== InviteKind.Invite) return;
this.setState({ busy: true });
this.convertFilter();
const targets = this.convertFilter();
@ -528,7 +528,7 @@ export default class InviteDialog extends React.PureComponent<Props, IInviteDial
};
private transferCall = async (): Promise<void> => {
if (this.props.kind !== KIND_CALL_TRANSFER) return;
if (this.props.kind !== InviteKind.CallTransfer) return;
if (this.state.currentTabId == TabId.UserDirectory) {
this.convertFilter();
const targets = this.convertFilter();
@ -737,7 +737,7 @@ export default class InviteDialog extends React.PureComponent<Props, IInviteDial
if (idx >= 0) {
targets.splice(idx, 1);
} else {
if (this.props.kind === KIND_CALL_TRANSFER && targets.length > 0) {
if (this.props.kind === InviteKind.CallTransfer && targets.length > 0) {
targets = [];
}
targets.push(member);
@ -869,7 +869,7 @@ export default class InviteDialog extends React.PureComponent<Props, IInviteDial
const lastActive = (m: Result): number | undefined => (kind === "recents" ? m.lastActive : undefined);
let sectionName = kind === "recents" ? _t("Recent Conversations") : _t("Suggestions");
if (this.props.kind === KIND_INVITE) {
if (this.props.kind === InviteKind.Invite) {
sectionName = kind === "recents" ? _t("Recently Direct Messaged") : _t("Suggestions");
}
@ -959,7 +959,7 @@ export default class InviteDialog extends React.PureComponent<Props, IInviteDial
private renderEditor(): JSX.Element {
const hasPlaceholder =
this.props.kind == KIND_CALL_TRANSFER &&
this.props.kind == InviteKind.CallTransfer &&
this.state.targets.length === 0 &&
this.state.filterText.length === 0;
const targets = this.state.targets.map((t) => (
@ -974,7 +974,9 @@ export default class InviteDialog extends React.PureComponent<Props, IInviteDial
ref={this.editorRef}
onPaste={this.onPaste}
autoFocus={true}
disabled={this.state.busy || (this.props.kind == KIND_CALL_TRANSFER && this.state.targets.length > 0)}
disabled={
this.state.busy || (this.props.kind == InviteKind.CallTransfer && this.state.targets.length > 0)
}
autoComplete="off"
placeholder={hasPlaceholder ? _t("Search") : undefined}
data-testid="invite-dialog-input"
@ -1085,7 +1087,7 @@ export default class InviteDialog extends React.PureComponent<Props, IInviteDial
private get screenName(): ScreenName | undefined {
switch (this.props.kind) {
case KIND_DM:
case InviteKind.Dm:
return "StartChat";
}
}
@ -1112,7 +1114,7 @@ export default class InviteDialog extends React.PureComponent<Props, IInviteDial
const cli = MatrixClientPeg.get();
const userId = cli.getUserId()!;
if (this.props.kind === KIND_DM) {
if (this.props.kind === InviteKind.Dm) {
title = _t("Direct Messages");
if (identityServersEnabled) {
@ -1164,7 +1166,7 @@ export default class InviteDialog extends React.PureComponent<Props, IInviteDial
</CopyableText>
</div>
);
} else if (this.props.kind === KIND_INVITE) {
} else if (this.props.kind === InviteKind.Invite) {
const roomId = this.props.roomId;
const room = MatrixClientPeg.get()?.getRoom(roomId);
const isSpace = room?.isSpaceRoom();
@ -1235,7 +1237,7 @@ export default class InviteDialog extends React.PureComponent<Props, IInviteDial
);
}
}
} else if (this.props.kind === KIND_CALL_TRANSFER) {
} else if (this.props.kind === InviteKind.CallTransfer) {
title = _t("Transfer");
consultConnectSection = (
@ -1264,7 +1266,7 @@ export default class InviteDialog extends React.PureComponent<Props, IInviteDial
}
const goButton =
this.props.kind == KIND_CALL_TRANSFER ? null : (
this.props.kind == InviteKind.CallTransfer ? null : (
<AccessibleButton
kind="primary"
onClick={goButtonFn}
@ -1298,7 +1300,7 @@ export default class InviteDialog extends React.PureComponent<Props, IInviteDial
);
let dialogContent;
if (this.props.kind === KIND_CALL_TRANSFER) {
if (this.props.kind === InviteKind.CallTransfer) {
const tabs: Tab[] = [];
tabs.push(
new Tab(TabId.UserDirectory, _td("User Directory"), "mx_InviteDialog_userDirectoryIcon", usersSection),
@ -1363,8 +1365,8 @@ export default class InviteDialog extends React.PureComponent<Props, IInviteDial
return (
<BaseDialog
className={classNames({
mx_InviteDialog_transfer: this.props.kind === KIND_CALL_TRANSFER,
mx_InviteDialog_other: this.props.kind !== KIND_CALL_TRANSFER,
mx_InviteDialog_transfer: this.props.kind === InviteKind.CallTransfer,
mx_InviteDialog_other: this.props.kind !== InviteKind.CallTransfer,
mx_InviteDialog_hasFooter: !!footer,
})}
hasCancel={true}

View file

@ -14,11 +14,11 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
export const KIND_DM = "dm";
export const KIND_INVITE = "invite";
// NB. This dialog needs the 'mx_InviteDialog_transferWrapper' wrapper class to have the correct
// padding on the bottom (because all modals have 24px padding on all sides), so this needs to
// be passed when creating the modal
export const KIND_CALL_TRANSFER = "call_transfer";
export type AnyInviteKind = typeof KIND_INVITE | typeof KIND_DM | typeof KIND_CALL_TRANSFER;
export enum InviteKind {
Dm = "dm",
Invite = "invite",
// NB. This dialog needs the 'mx_InviteDialog_transferWrapper' wrapper class to have the correct
// padding on the bottom (because all modals have 24px padding on all sides), so this needs to
// be passed when creating the modal
CallTransfer = "call_transfer",
}

View file

@ -21,9 +21,8 @@ import SdkConfig from "../../../SdkConfig";
import BaseDialog from "./BaseDialog";
import DialogButtons from "../elements/DialogButtons";
import Spinner from "../elements/Spinner";
import { IDialogProps } from "./IDialogProps";
interface IProps extends IDialogProps {
interface IProps {
failures: Record<
string,
Record<
@ -35,7 +34,8 @@ interface IProps extends IDialogProps {
>
>;
source: string;
continuation: () => Promise<void>;
continuation: (opts: { shouldEmit: boolean }) => Promise<void>;
onFinished(): void;
}
const KeySignatureUploadFailedDialog: React.FC<IProps> = ({ failures, source, continuation, onFinished }) => {
@ -61,7 +61,7 @@ const KeySignatureUploadFailedDialog: React.FC<IProps> = ({ failures, source, co
}).finally(() => {
setCancelled(true);
});
await Promise.race([continuation(), cancel]);
await Promise.race([continuation({ shouldEmit: false }), cancel]);
setSuccess(true);
} catch (e) {
setRetry((r) => r - 1);

View file

@ -20,10 +20,10 @@ import React from "react";
import QuestionDialog from "./QuestionDialog";
import { _t } from "../../../languageHandler";
import SdkConfig from "../../../SdkConfig";
import { IDialogProps } from "./IDialogProps";
interface IProps extends IDialogProps {
interface IProps {
host: string;
onFinished(): void;
}
const LazyLoadingDisabledDialog: React.FC<IProps> = (props) => {

View file

@ -20,9 +20,10 @@ import React from "react";
import QuestionDialog from "./QuestionDialog";
import { _t } from "../../../languageHandler";
import SdkConfig from "../../../SdkConfig";
import { IDialogProps } from "./IDialogProps";
interface IProps extends IDialogProps {}
interface IProps {
onFinished(): void;
}
const LazyLoadingResyncDialog: React.FC<IProps> = (props) => {
const brand = SdkConfig.get().brand;

View file

@ -15,10 +15,12 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import React, { ComponentType } from "react";
import React from "react";
import { IKeyBackupInfo } from "matrix-js-sdk/src/crypto/keybackup";
import { logger } from "matrix-js-sdk/src/logger";
import type CreateKeyBackupDialog from "../../../async-components/views/dialogs/security/CreateKeyBackupDialog";
import type ExportE2eKeysDialog from "../../../async-components/views/dialogs/security/ExportE2eKeysDialog";
import Modal from "../../../Modal";
import dis from "../../../dispatcher/dispatcher";
import { _t } from "../../../languageHandler";
@ -81,7 +83,7 @@ export default class LogoutDialog extends React.Component<IProps, IState> {
private onExportE2eKeysClicked = (): void => {
Modal.createDialogAsync(
import("../../../async-components/views/dialogs/security/ExportE2eKeysDialog") as unknown as Promise<
ComponentType<{}>
typeof ExportE2eKeysDialog
>,
{
matrixClient: MatrixClientPeg.get(),
@ -89,7 +91,7 @@ export default class LogoutDialog extends React.Component<IProps, IState> {
);
};
private onFinished = (confirmed: boolean): void => {
private onFinished = (confirmed?: boolean): void => {
if (confirmed) {
dis.dispatch({ action: "logout" });
}
@ -112,7 +114,7 @@ export default class LogoutDialog extends React.Component<IProps, IState> {
} else {
Modal.createDialogAsync(
import("../../../async-components/views/dialogs/security/CreateKeyBackupDialog") as unknown as Promise<
ComponentType<{}>
typeof CreateKeyBackupDialog
>,
undefined,
undefined,

View file

@ -18,7 +18,6 @@ import React, { useMemo, useState } from "react";
import { Room } from "matrix-js-sdk/src/models/room";
import { _t } from "../../../languageHandler";
import { IDialogProps } from "./IDialogProps";
import BaseDialog from "./BaseDialog";
import SearchBox from "../../structures/SearchBox";
import SpaceStore from "../../../stores/spaces/SpaceStore";
@ -28,9 +27,10 @@ import AutoHideScrollbar from "../../structures/AutoHideScrollbar";
import StyledCheckbox from "../elements/StyledCheckbox";
import MatrixClientContext from "../../../contexts/MatrixClientContext";
interface IProps extends IDialogProps {
interface IProps {
room: Room;
selected?: string[];
onFinished(rooms?: string[]): void;
}
const Entry: React.FC<{

View file

@ -25,11 +25,11 @@ import { MatrixClientPeg } from "../../../MatrixClientPeg";
import * as FormattingUtils from "../../../utils/FormattingUtils";
import { _t } from "../../../languageHandler";
import QuestionDialog from "./QuestionDialog";
import { IDialogProps } from "./IDialogProps";
interface IProps extends IDialogProps {
interface IProps {
userId: string;
device: DeviceInfo;
onFinished(confirm?: boolean): void;
}
export default class ManualDeviceKeyVerificationDialog extends React.Component<IProps> {

View file

@ -30,10 +30,10 @@ import ScrollPanel from "../../structures/ScrollPanel";
import Spinner from "../elements/Spinner";
import EditHistoryMessage from "../messages/EditHistoryMessage";
import DateSeparator from "../messages/DateSeparator";
import { IDialogProps } from "./IDialogProps";
interface IProps extends IDialogProps {
interface IProps {
mxEvent: MatrixEvent;
onFinished(): void;
}
interface IState {

View file

@ -46,7 +46,7 @@ interface IProps {
widgetDefinition: IModalWidgetOpenRequestData;
widgetRoomId?: string;
sourceWidgetId: string;
onFinished(success: boolean, data?: IModalWidgetReturnData): void;
onFinished(success?: boolean, data?: IModalWidgetReturnData): void;
}
interface IState {

View file

@ -19,13 +19,13 @@ import { DialogContent, DialogProps } from "@matrix-org/react-sdk-module-api/lib
import { logger } from "matrix-js-sdk/src/logger";
import ScrollableBaseModal, { IScrollableBaseState } from "./ScrollableBaseModal";
import { IDialogProps } from "./IDialogProps";
import { _t } from "../../../languageHandler";
interface IProps extends IDialogProps {
contentFactory: (props: DialogProps, ref: React.Ref<DialogContent>) => React.ReactNode;
interface IProps<C extends React.Component = React.Component> {
contentFactory: (props: DialogProps, ref: React.Ref<C>) => React.ReactNode;
contentProps: DialogProps;
title: string;
onFinished(ok?: boolean, model?: Awaited<ReturnType<DialogContent["trySubmit"]>>): void;
}
interface IState extends IScrollableBaseState {

View file

@ -19,11 +19,10 @@ import React from "react";
import classNames from "classnames";
import { _t } from "../../../languageHandler";
import { IDialogProps } from "./IDialogProps";
import BaseDialog from "./BaseDialog";
import DialogButtons from "../elements/DialogButtons";
export interface IQuestionDialogProps extends IDialogProps {
export interface IQuestionDialogProps {
title?: string;
description?: React.ReactNode;
extraButtons?: React.ReactNode;
@ -37,6 +36,7 @@ export interface IQuestionDialogProps extends IDialogProps {
className?: string;
hasCancelButton?: boolean;
cancelButton?: React.ReactNode;
onFinished(ok?: boolean): void;
}
export default class QuestionDialog extends React.Component<IQuestionDialogProps> {

View file

@ -18,13 +18,12 @@ import * as React from "react";
import { SyntheticEvent, useRef, useState } from "react";
import { _t, _td } from "../../../languageHandler";
import { IDialogProps } from "./IDialogProps";
import Field from "../elements/Field";
import BaseDialog from "./BaseDialog";
import DialogButtons from "../elements/DialogButtons";
import EmailField from "../auth/EmailField";
interface IProps extends IDialogProps {
interface IProps {
onFinished(continued: boolean, email?: string): void;
}

View file

@ -21,7 +21,6 @@ import { logger } from "matrix-js-sdk/src/logger";
import { _t } from "../../../languageHandler";
import { ensureDMExists } from "../../../createRoom";
import { IDialogProps } from "./IDialogProps";
import { MatrixClientPeg } from "../../../MatrixClientPeg";
import SdkConfig from "../../../SdkConfig";
import Markdown from "../../../Markdown";
@ -33,8 +32,9 @@ import Field from "../elements/Field";
import Spinner from "../elements/Spinner";
import LabelledCheckbox from "../elements/LabelledCheckbox";
interface IProps extends IDialogProps {
interface IProps {
mxEvent: MatrixEvent;
onFinished(report?: boolean): void;
}
interface IState {

View file

@ -45,7 +45,7 @@ export const ROOM_ADVANCED_TAB = "ROOM_ADVANCED_TAB";
interface IProps {
roomId: string;
onFinished: (success: boolean) => void;
onFinished: (success?: boolean) => void;
initialTabId?: string;
}

View file

@ -20,14 +20,14 @@ import { Room } from "matrix-js-sdk/src/models/room";
import Modal from "../../../Modal";
import { _t } from "../../../languageHandler";
import { upgradeRoom } from "../../../utils/RoomUpgrade";
import { IDialogProps } from "./IDialogProps";
import BaseDialog from "./BaseDialog";
import ErrorDialog from "./ErrorDialog";
import DialogButtons from "../elements/DialogButtons";
import Spinner from "../elements/Spinner";
interface IProps extends IDialogProps {
interface IProps {
room: Room;
onFinished(upgrade?: boolean): void;
}
interface IState {

View file

@ -23,7 +23,6 @@ import SdkConfig from "../../../SdkConfig";
import LabelledToggleSwitch from "../elements/LabelledToggleSwitch";
import { MatrixClientPeg } from "../../../MatrixClientPeg";
import Modal from "../../../Modal";
import { IDialogProps } from "./IDialogProps";
import BugReportDialog from "./BugReportDialog";
import BaseDialog from "./BaseDialog";
import DialogButtons from "../elements/DialogButtons";
@ -35,11 +34,12 @@ export interface IFinishedOpts {
invite: boolean;
}
interface IProps extends IDialogProps {
interface IProps {
roomId: string;
targetVersion: string;
description?: ReactNode;
doUpgrade?(opts: IFinishedOpts, fn: (progressText: string, progress: number, total: number) => void): Promise<void>;
onFinished(opts?: IFinishedOpts): void;
}
interface IState {
@ -70,19 +70,14 @@ export default class RoomUpgradeWarningDialog extends React.Component<IProps, IS
this.setState({ progressText, progress, total });
};
private onContinue = (): void => {
private onContinue = async (): Promise<void> => {
const opts = {
continue: true,
invite: this.isPrivate && this.state.inviteUsersToNewRoom,
};
if (this.props.doUpgrade) {
this.props.doUpgrade(opts, this.onProgressCallback).then(() => {
await this.props.doUpgrade?.(opts, this.onProgressCallback);
this.props.onFinished(opts);
});
} else {
this.props.onFinished(opts);
}
};
private onCancel = (): void => {

View file

@ -19,7 +19,6 @@ import { MatrixClient } from "matrix-js-sdk/src/client";
import FocusLock from "react-focus-lock";
import { MatrixClientPeg } from "../../../MatrixClientPeg";
import { IDialogProps } from "./IDialogProps";
import MatrixClientContext from "../../../contexts/MatrixClientContext";
import { _t } from "../../../languageHandler";
import AccessibleButton from "../elements/AccessibleButton";
@ -36,7 +35,7 @@ export interface IScrollableBaseState {
* Scrollable dialog base from Compound (Web Components).
*/
export default abstract class ScrollableBaseModal<
TProps extends IDialogProps,
TProps extends { onFinished?: (...args: any[]) => void },
TState extends IScrollableBaseState,
> extends React.PureComponent<TProps, TState> {
protected constructor(props: TProps) {

View file

@ -28,9 +28,10 @@ import Spinner from "../elements/Spinner";
import AccessibleButton from "../elements/AccessibleButton";
import { UPDATE_EVENT } from "../../../stores/AsyncStore";
import { MatrixClientPeg } from "../../../MatrixClientPeg";
import { IDialogProps } from "./IDialogProps";
interface IProps extends IDialogProps {}
interface IProps {
onFinished(): void;
}
export default class ServerOfflineDialog extends React.PureComponent<IProps> {
public componentDidMount(): void {

View file

@ -19,9 +19,12 @@ import React from "react";
import { _t } from "../../../languageHandler";
import BaseDialog from "./BaseDialog";
import DialogButtons from "../elements/DialogButtons";
import { IDialogProps } from "./IDialogProps";
export default class SeshatResetDialog extends React.PureComponent<IDialogProps> {
interface Props {
onFinished(reset?: boolean): void;
}
export default class SeshatResetDialog extends React.PureComponent<Props> {
public render(): React.ReactNode {
return (
<BaseDialog

View file

@ -25,10 +25,10 @@ import QuestionDialog from "./QuestionDialog";
import BugReportDialog from "./BugReportDialog";
import BaseDialog from "./BaseDialog";
import DialogButtons from "../elements/DialogButtons";
import { IDialogProps } from "./IDialogProps";
interface IProps extends IDialogProps {
interface IProps {
error: Error;
onFinished(clear?: boolean): void;
}
export default class SessionRestoreErrorDialog extends React.Component<IProps> {

View file

@ -27,10 +27,10 @@ import ErrorDialog from "./ErrorDialog";
import QuestionDialog from "./QuestionDialog";
import BaseDialog from "./BaseDialog";
import EditableText from "../elements/EditableText";
import { IDialogProps } from "./IDialogProps";
interface IProps extends IDialogProps {
interface IProps {
title: string;
onFinished(ok?: boolean): void;
}
interface IState {

View file

@ -26,7 +26,6 @@ import QRCode from "../elements/QRCode";
import { RoomPermalinkCreator, makeUserPermalink } from "../../../utils/permalinks/Permalinks";
import { selectText } from "../../../utils/strings";
import StyledCheckbox from "../elements/StyledCheckbox";
import { IDialogProps } from "./IDialogProps";
import SettingsStore from "../../../settings/SettingsStore";
import { UIFeature } from "../../../settings/UIFeature";
import BaseDialog from "./BaseDialog";
@ -64,9 +63,10 @@ const socials = [
},
];
interface IProps extends IDialogProps {
interface IProps {
target: Room | User | RoomMember | MatrixEvent;
permalinkCreator: RoomPermalinkCreator;
permalinkCreator?: RoomPermalinkCreator;
onFinished(): void;
}
interface IState {

View file

@ -18,10 +18,11 @@ import React from "react";
import { _t } from "../../../languageHandler";
import { Command, CommandCategories, Commands } from "../../../SlashCommands";
import { IDialogProps } from "./IDialogProps";
import InfoDialog from "./InfoDialog";
interface IProps extends IDialogProps {}
interface IProps {
onFinished(): void;
}
const SlashCommandHelpDialog: React.FC<IProps> = ({ onFinished }) => {
const categories: Record<string, Command[]> = {};

View file

@ -19,7 +19,6 @@ import { MatrixClient, Method } from "matrix-js-sdk/src/matrix";
import { logger } from "matrix-js-sdk/src/logger";
import { _t } from "../../../languageHandler";
import { IDialogProps } from "./IDialogProps";
import SettingsStore from "../../../settings/SettingsStore";
import TextInputDialog from "./TextInputDialog";
import withValidation from "../elements/Validation";
@ -63,7 +62,7 @@ async function proxyHealthCheck(endpoint: string, hsUrl?: string): Promise<void>
logger.info("sliding sync proxy is OK");
}
export const SlidingSyncOptionsDialog: React.FC<IDialogProps> = ({ onFinished }) => {
export const SlidingSyncOptionsDialog: React.FC<{ onFinished(enabled: boolean): void }> = ({ onFinished }) => {
const cli = MatrixClientPeg.get();
const currentProxy = SettingsStore.getValue("feature_sliding_sync_proxy_url");
const hasNativeSupport = useAsyncMemo(

View file

@ -19,7 +19,6 @@ import { Room } from "matrix-js-sdk/src/models/room";
import { _t, _td } from "../../../languageHandler";
import BaseDialog from "../dialogs/BaseDialog";
import { IDialogProps } from "./IDialogProps";
import TabbedView, { Tab } from "../../structures/TabbedView";
import StyledCheckbox from "../elements/StyledCheckbox";
import { useSettingValue } from "../../../hooks/useSettings";
@ -28,9 +27,10 @@ import { SettingLevel } from "../../../settings/SettingLevel";
import RoomName from "../elements/RoomName";
import { SpacePreferenceTab } from "../../../dispatcher/payloads/OpenSpacePreferencesPayload";
interface IProps extends IDialogProps {
interface IProps {
space: Room;
initialTabId?: SpacePreferenceTab;
onFinished(): void;
}
const SpacePreferencesAppearanceTab: React.FC<Pick<IProps, "space">> = ({ space }) => {

View file

@ -19,7 +19,6 @@ import { Room } from "matrix-js-sdk/src/models/room";
import { MatrixClient } from "matrix-js-sdk/src/client";
import { _t, _td } from "../../../languageHandler";
import { IDialogProps } from "./IDialogProps";
import BaseDialog from "./BaseDialog";
import defaultDispatcher from "../../../dispatcher/dispatcher";
import { useDispatcher } from "../../../hooks/useDispatcher";
@ -39,15 +38,16 @@ export enum SpaceSettingsTab {
Advanced = "SPACE_ADVANCED_TAB",
}
interface IProps extends IDialogProps {
interface IProps {
matrixClient: MatrixClient;
space: Room;
onFinished(): void;
}
const SpaceSettingsDialog: React.FC<IProps> = ({ matrixClient: cli, space, onFinished }) => {
useDispatcher(defaultDispatcher, (payload) => {
if (payload.action === Action.AfterLeaveRoom && payload.room_id === space.roomId) {
onFinished(false);
onFinished();
}
});
@ -57,7 +57,7 @@ const SpaceSettingsDialog: React.FC<IProps> = ({ matrixClient: cli, space, onFin
SpaceSettingsTab.General,
_td("General"),
"mx_SpaceSettingsDialog_generalIcon",
<SpaceSettingsGeneralTab matrixClient={cli} space={space} onFinished={onFinished} />,
<SpaceSettingsGeneralTab matrixClient={cli} space={space} />,
),
new Tab(
SpaceSettingsTab.Visibility,

View file

@ -22,10 +22,11 @@ import { _t } from "../../../languageHandler";
import BaseDialog from "./BaseDialog";
import DialogButtons from "../elements/DialogButtons";
import BugReportDialog from "./BugReportDialog";
import { IDialogProps } from "./IDialogProps";
import AccessibleButton from "../elements/AccessibleButton";
interface IProps extends IDialogProps {}
interface IProps {
onFinished(signOut?: boolean): void;
}
export default class StorageEvictedDialog extends React.Component<IProps> {
private sendBugReport = (ev: React.MouseEvent): void => {

View file

@ -21,9 +21,8 @@ import { _t, _td } from "../../../languageHandler";
import { IFieldState, IValidationResult } from "../elements/Validation";
import BaseDialog from "./BaseDialog";
import DialogButtons from "../elements/DialogButtons";
import { IDialogProps } from "./IDialogProps";
interface IProps extends IDialogProps {
interface IProps {
title?: string;
description?: React.ReactNode;
value?: string;
@ -34,6 +33,7 @@ interface IProps extends IDialogProps {
hasCancel?: boolean;
validator?: (fieldState: IFieldState) => Promise<IValidationResult>; // result of withValidation
fixedWidth?: boolean;
onFinished(ok?: boolean, text?: string): void;
}
interface IState {
@ -45,7 +45,7 @@ interface IState {
export default class TextInputDialog extends React.Component<IProps, IState> {
private field = createRef<Field>();
public static defaultProps = {
public static defaultProps: Partial<IProps> = {
title: "",
value: "",
description: "",

View file

@ -22,12 +22,12 @@ import { MatrixClientPeg } from "../../../MatrixClientPeg";
import E2EIcon, { E2EState } from "../rooms/E2EIcon";
import AccessibleButton from "../elements/AccessibleButton";
import BaseDialog from "./BaseDialog";
import { IDialogProps } from "./IDialogProps";
import { IDevice } from "../right_panel/UserInfo";
interface IProps extends IDialogProps {
interface IProps {
user: User;
device: IDevice;
onFinished(mode?: "legacy" | "sas" | false): void;
}
const UntrustedDeviceDialog: React.FC<IProps> = ({ device, user, onFinished }) => {

View file

@ -26,7 +26,7 @@ import DialogButtons from "../elements/DialogButtons";
interface IProps {
file: File;
currentIndex: number;
currentIndex?: number;
totalFiles?: number;
onFinished: (uploadConfirmed: boolean, uploadAll?: boolean) => void;
}
@ -35,7 +35,7 @@ export default class UploadConfirmDialog extends React.Component<IProps> {
private readonly objectUrl: string;
private readonly mimeType: string;
public static defaultProps = {
public static defaultProps: Partial<IProps> = {
totalFiles: 1,
};

View file

@ -21,12 +21,12 @@ import { _t } from "../../../languageHandler";
import ContentMessages from "../../../ContentMessages";
import BaseDialog from "./BaseDialog";
import DialogButtons from "../elements/DialogButtons";
import { IDialogProps } from "./IDialogProps";
interface IProps extends IDialogProps {
interface IProps {
badFiles: File[];
totalFiles: number;
contentMessages: ContentMessages;
onFinished(upload?: boolean): void;
}
/*

View file

@ -32,14 +32,14 @@ import SdkConfig from "../../../SdkConfig";
import MjolnirUserSettingsTab from "../settings/tabs/user/MjolnirUserSettingsTab";
import { UIFeature } from "../../../settings/UIFeature";
import BaseDialog from "./BaseDialog";
import { IDialogProps } from "./IDialogProps";
import SidebarUserSettingsTab from "../settings/tabs/user/SidebarUserSettingsTab";
import KeyboardUserSettingsTab from "../settings/tabs/user/KeyboardUserSettingsTab";
import SessionManagerTab from "../settings/tabs/user/SessionManagerTab";
import { UserTab } from "./UserTab";
interface IProps extends IDialogProps {
interface IProps {
initialTabId?: UserTab;
onFinished(): void;
}
interface IState {
@ -202,7 +202,7 @@ export default class UserSettingsDialog extends React.Component<IProps, IState>
UserTab.Help,
_td("Help & About"),
"mx_UserSettingsDialog_helpIcon",
<HelpUserSettingsTab closeSettingsFn={() => this.props.onFinished(true)} />,
<HelpUserSettingsTab closeSettingsFn={() => this.props.onFinished()} />,
"UserSettingsHelpAbout",
),
);

View file

@ -24,14 +24,14 @@ import BaseDialog from "./BaseDialog";
import EncryptionPanel from "../right_panel/EncryptionPanel";
interface IProps {
verificationRequest: VerificationRequest;
verificationRequestPromise: Promise<VerificationRequest>;
verificationRequest?: VerificationRequest;
verificationRequestPromise?: Promise<VerificationRequest>;
onFinished: () => void;
member: User;
member?: User;
}
interface IState {
verificationRequest: VerificationRequest;
verificationRequest?: VerificationRequest;
}
export default class VerificationRequestDialog extends React.Component<IProps, IState> {
@ -40,18 +40,16 @@ export default class VerificationRequestDialog extends React.Component<IProps, I
this.state = {
verificationRequest: this.props.verificationRequest,
};
if (this.props.verificationRequestPromise) {
this.props.verificationRequestPromise.then((r) => {
this.props.verificationRequestPromise?.then((r) => {
this.setState({ verificationRequest: r });
});
}
}
public render(): React.ReactNode {
const request = this.state.verificationRequest;
const otherUserId = request && request.otherUserId;
const member = this.props.member || (otherUserId && MatrixClientPeg.get().getUser(otherUserId));
const title = request && request.isSelfVerification ? _t("Verify other device") : _t("Verification Request");
const otherUserId = request?.otherUserId;
const member = this.props.member || (otherUserId ? MatrixClientPeg.get().getUser(otherUserId) : null);
const title = request?.isSelfVerification ? _t("Verify other device") : _t("Verification Request");
return (
<BaseDialog

View file

@ -20,17 +20,17 @@ import { lexicographicCompare } from "matrix-js-sdk/src/utils";
import BaseDialog from "./BaseDialog";
import { _t } from "../../../languageHandler";
import { IDialogProps } from "./IDialogProps";
import { objectShallowClone } from "../../../utils/objects";
import StyledCheckbox from "../elements/StyledCheckbox";
import DialogButtons from "../elements/DialogButtons";
import LabelledToggleSwitch from "../elements/LabelledToggleSwitch";
import { CapabilityText } from "../../../widgets/CapabilityText";
interface IProps extends IDialogProps {
interface IProps {
requestedCapabilities: Set<Capability>;
widget: Widget;
widgetKind: WidgetKind; // TODO: Refactor into the Widget class
onFinished(result?: { approved: Capability[]; remember: boolean }): void;
}
type BooleanStates = Partial<{

View file

@ -22,15 +22,15 @@ import { logger } from "matrix-js-sdk/src/logger";
import { _t } from "../../../languageHandler";
import LabelledToggleSwitch from "../elements/LabelledToggleSwitch";
import { OIDCState } from "../../../stores/widgets/WidgetPermissionStore";
import { IDialogProps } from "./IDialogProps";
import BaseDialog from "./BaseDialog";
import DialogButtons from "../elements/DialogButtons";
import { SdkContextClass } from "../../../contexts/SDKContext";
interface IProps extends IDialogProps {
interface IProps {
widget: Widget;
widgetKind: WidgetKind;
inRoomId?: string;
onFinished(allowed?: boolean): void;
}
interface IState {

View file

@ -20,7 +20,6 @@ import { MatrixEvent, Poll, Room } from "matrix-js-sdk/src/matrix";
import { _t } from "../../../../languageHandler";
import BaseDialog from "../BaseDialog";
import { IDialogProps } from "../IDialogProps";
import { PollHistoryList } from "./PollHistoryList";
import { PollHistoryFilter } from "./types";
import { PollDetailHeader } from "./PollDetailHeader";
@ -29,10 +28,11 @@ import { RoomPermalinkCreator } from "../../../../utils/permalinks/Permalinks";
import { usePollsWithRelations } from "./usePollHistory";
import { useFetchPastPolls } from "./fetchPastPolls";
type PollHistoryDialogProps = Pick<IDialogProps, "onFinished"> & {
type PollHistoryDialogProps = {
room: Room;
matrixClient: MatrixClient;
permalinkCreator: RoomPermalinkCreator;
onFinished(): void;
};
const sortEventsByLatest = (left: MatrixEvent, right: MatrixEvent): number => right.getTs() - left.getTs();

View file

@ -24,7 +24,6 @@ import { MatrixClientPeg } from "../../../../MatrixClientPeg";
import Field from "../../elements/Field";
import AccessibleButton from "../../elements/AccessibleButton";
import { _t } from "../../../../languageHandler";
import { IDialogProps } from "../IDialogProps";
import { accessSecretStorage } from "../../../../SecurityManager";
import Modal from "../../../../Modal";
import InteractiveAuthDialog from "../InteractiveAuthDialog";
@ -40,9 +39,12 @@ const KEY_FILE_MAX_SIZE = 128;
// Don't shout at the user that their key is invalid every time they type a key: wait a short time
const VALIDATION_THROTTLE_MS = 200;
interface IProps extends IDialogProps {
export type KeyParams = { passphrase?: string; recoveryKey?: string };
interface IProps {
keyInfo?: ISecretStorageKeyInfo;
checkPrivateKey: (k: { passphrase?: string; recoveryKey?: string }) => boolean;
checkPrivateKey: (k: KeyParams) => Promise<boolean>;
onFinished(result?: false | KeyParams): void;
}
interface IState {
@ -246,7 +248,7 @@ export default class AccessSecretStorageDialog extends React.PureComponent<IProp
// Now we can indicate that the user is done pressing buttons, finally.
// Upstream flows will detect the new secret storage, key backup, etc and use it.
this.props.onFinished(true);
this.props.onFinished({});
}, true);
} catch (e) {
logger.error(e);

View file

@ -21,7 +21,7 @@ import BaseDialog from "../BaseDialog";
import DialogButtons from "../../elements/DialogButtons";
interface IProps {
onFinished: (success: boolean) => void;
onFinished: (success?: boolean) => void;
}
export default class ConfirmDestroyCrossSigningDialog extends React.Component<IProps> {

View file

@ -32,7 +32,7 @@ import InteractiveAuthDialog from "../InteractiveAuthDialog";
interface IProps {
accountPassword?: string;
tokenLogin?: boolean;
onFinished?: (success: boolean) => void;
onFinished?: (success?: boolean) => void;
}
interface IState {

View file

@ -24,7 +24,6 @@ import { logger } from "matrix-js-sdk/src/logger";
import { MatrixClientPeg } from "../../../../MatrixClientPeg";
import { _t } from "../../../../languageHandler";
import { accessSecretStorage } from "../../../../SecurityManager";
import { IDialogProps } from "../IDialogProps";
import Spinner from "../../elements/Spinner";
import DialogButtons from "../../elements/DialogButtons";
import AccessibleButton from "../../elements/AccessibleButton";
@ -42,13 +41,14 @@ enum ProgressState {
LoadKeys = "load_keys",
}
interface IProps extends IDialogProps {
interface IProps {
// if false, will close the dialog as soon as the restore completes successfully
// default: true
showSummary?: boolean;
// If specified, gather the key from the user but then call the function with the backup
// key rather than actually (necessarily) restoring the backup.
keyCallback?: (key: Uint8Array) => void;
onFinished(done?: boolean): void;
}
interface IState {
@ -77,7 +77,7 @@ interface IState {
* Dialog for restoring e2e keys from a backup and the user's recovery key
*/
export default class RestoreKeyBackupDialog extends React.PureComponent<IProps, IState> {
public static defaultProps = {
public static defaultProps: Partial<IProps> = {
showSummary: true,
};

View file

@ -20,7 +20,6 @@ import SetupEncryptionBody from "../../../structures/auth/SetupEncryptionBody";
import BaseDialog from "../BaseDialog";
import { _t } from "../../../../languageHandler";
import { SetupEncryptionStore, Phase } from "../../../../stores/SetupEncryptionStore";
import { IDialogProps } from "../IDialogProps";
function iconFromPhase(phase: Phase): string {
if (phase === Phase.Done) {
@ -30,7 +29,9 @@ function iconFromPhase(phase: Phase): string {
}
}
interface IProps extends IDialogProps {}
interface IProps {
onFinished(): void;
}
interface IState {
icon: string;
}

View file

@ -83,7 +83,6 @@ import Spinner from "../../elements/Spinner";
import NotificationBadge from "../../rooms/NotificationBadge";
import BaseDialog from "../BaseDialog";
import FeedbackDialog from "../FeedbackDialog";
import { IDialogProps } from "../IDialogProps";
import { Option } from "./Option";
import { PublicRoomResultDetails } from "./PublicRoomResultDetails";
import { RoomResultContextMenus } from "./RoomResultContextMenus";
@ -99,9 +98,10 @@ const MAX_RECENT_SEARCHES = 10;
const SECTION_LIMIT = 50; // only show 50 results per section for performance reasons
const AVATAR_SIZE = 24;
interface IProps extends IDialogProps {
interface IProps {
initialText?: string;
initialFilter?: Filter;
onFinished(): void;
}
function refIsForRecentlyViewed(ref: RefObject<HTMLElement>): boolean {

View file

@ -33,7 +33,6 @@ import dis from "../../../dispatcher/dispatcher";
import { Action } from "../../../dispatcher/actions";
import { RoomPermalinkCreator } from "../../../utils/permalinks/Permalinks";
import { normalizeWheelEvent } from "../../../utils/Mouse";
import { IDialogProps } from "../dialogs/IDialogProps";
import UIStore from "../../../stores/UIStore";
import { ViewRoomPayload } from "../../../dispatcher/payloads/ViewRoomPayload";
import { KeyBindingAction } from "../../../accessibility/KeyboardShortcuts";
@ -56,7 +55,7 @@ const getPanelHeight = (): number => {
return parseInt(value.slice(0, value.length - 2));
};
interface IProps extends IDialogProps {
interface IProps {
src: string; // the source of the image being displayed
name?: string; // the main title ('name') for the image
link?: string; // the link (if any) applied to the name of the image
@ -77,6 +76,7 @@ interface IProps extends IDialogProps {
width: number;
height: number;
};
onFinished(): void;
}
interface IState {

View file

@ -27,7 +27,6 @@ import { MatrixEvent } from "matrix-js-sdk/src/models/event";
import { IPartialEvent } from "matrix-js-sdk/src/@types/extensible_events";
import ScrollableBaseModal, { IScrollableBaseState } from "../dialogs/ScrollableBaseModal";
import { IDialogProps } from "../dialogs/IDialogProps";
import QuestionDialog from "../dialogs/QuestionDialog";
import Modal from "../../../Modal";
import { _t } from "../../../languageHandler";
@ -37,10 +36,11 @@ import AccessibleButton from "./AccessibleButton";
import Spinner from "./Spinner";
import { doMaybeLocalRoomAction } from "../../../utils/local-room";
interface IProps extends IDialogProps {
interface IProps {
room: Room;
threadId?: string;
editingMxEvent?: MatrixEvent; // Truthy if we are editing an existing poll
onFinished(pollCreated?: boolean): void;
}
enum FocusTarget {

View file

@ -22,6 +22,7 @@ interface IProps {
w?: number;
h?: number;
message?: string;
onFinished: any; // XXX: Spinner pretends to be a dialog so it must accept an onFinished, but it never calls it
}
export default class Spinner extends React.PureComponent<IProps> {

View file

@ -19,15 +19,15 @@ import { MatrixEvent } from "matrix-js-sdk/src/models/event";
import { MatrixClient } from "matrix-js-sdk/src/client";
import BaseDialog from "../dialogs/BaseDialog";
import { IDialogProps } from "../dialogs/IDialogProps";
import { locationEventGeoUri, isSelfLocation } from "../../../utils/location";
import Map from "./Map";
import SmartMarker from "./SmartMarker";
import ZoomButtons from "./ZoomButtons";
interface IProps extends IDialogProps {
interface IProps {
matrixClient: MatrixClient;
mxEvent: MatrixEvent;
onFinished(): void;
}
interface IState {

View file

@ -80,7 +80,9 @@ export default class EditHistoryMessage extends React.PureComponent<IProps, ISta
Modal.createDialog(
ConfirmAndWaitRedactDialog,
{
redact: () => cli.redactEvent(event.getRoomId(), event.getId()),
redact: async () => {
await cli.redactEvent(event.getRoomId(), event.getId());
},
},
"mx_Dialog_confirmredact",
);

View file

@ -162,7 +162,6 @@ const MBeaconBody: React.FC<IBodyProps> = React.forwardRef(({ mxEvent, getRelati
roomId: mxEvent.getRoomId(),
matrixClient,
initialFocusedBeacon: beacon,
isMapDisplayError,
},
"mx_BeaconViewDialog_wrapper",
false, // isPriority

View file

@ -41,7 +41,7 @@ const MISMATCHES = ["m.key_mismatch", "m.user_error", "m.mismatched_sas"];
interface IProps {
member: RoomMember | User;
onClose: () => void;
verificationRequest: VerificationRequest;
verificationRequest?: VerificationRequest;
verificationRequestPromise?: Promise<VerificationRequest>;
layout: string;
isRoomEncrypted: boolean;

View file

@ -30,6 +30,7 @@ import { logger } from "matrix-js-sdk/src/logger";
import { CryptoEvent } from "matrix-js-sdk/src/crypto";
import { RoomStateEvent } from "matrix-js-sdk/src/models/room-state";
import { UserTrustLevel } from "matrix-js-sdk/src/crypto/CrossSigning";
import { DeviceInfo } from "matrix-js-sdk/src/crypto/deviceinfo";
import dis from "../../../dispatcher/dispatcher";
import Modal from "../../../Modal";
@ -79,10 +80,8 @@ import { ViewRoomPayload } from "../../../dispatcher/payloads/ViewRoomPayload";
import { DirectoryMember, startDmOnFirstMessage } from "../../../utils/direct-messages";
import { SdkContextClass } from "../../../contexts/SDKContext";
export interface IDevice {
deviceId: string;
export interface IDevice extends DeviceInfo {
ambiguous?: boolean;
getDisplayName(): string;
}
export const disambiguateDevices = (devices: IDevice[]): void => {
@ -239,8 +238,8 @@ function DevicesSection({
const isMe = userId === cli.getUserId();
const deviceTrusts = devices.map((d) => cli.checkDeviceTrust(userId, d.deviceId));
let expandSectionDevices = [];
const unverifiedDevices = [];
let expandSectionDevices: IDevice[] = [];
const unverifiedDevices: IDevice[] = [];
let expandCountCaption;
let expandHideCaption;
@ -487,7 +486,7 @@ export const UserOptionsSection: React.FC<{
};
const warnSelfDemote = async (isSpace: boolean): Promise<boolean> => {
const { finished } = Modal.createDialog<[boolean]>(QuestionDialog, {
const { finished } = Modal.createDialog(QuestionDialog, {
title: _t("Demote yourself?"),
description: (
<div>
@ -592,9 +591,7 @@ export const RoomKickButton = ({
if (member.membership !== "invite" && member.membership !== "join") return null;
const onKick = async (): Promise<void> => {
const { finished } = Modal.createDialog(
room.isSpaceRoom() ? ConfirmSpaceUserActionDialog : ConfirmUserActionDialog,
{
const commonProps = {
member,
action: room.isSpaceRoom()
? member.membership === "invite"
@ -609,7 +606,15 @@ export const RoomKickButton = ({
: _t("Remove from %(roomName)s", { roomName: room.name }),
askReason: member.membership === "join",
danger: true,
// space-specific props
};
let finished: Promise<[success?: boolean, reason?: string, rooms?: Room[]]>;
if (room.isSpaceRoom()) {
({ finished } = Modal.createDialog(
ConfirmSpaceUserActionDialog,
{
...commonProps,
space: room,
spaceChildFilter: (child: Room) => {
// Return true if the target member is not banned and we have sufficient PL to ban them
@ -627,8 +632,11 @@ export const RoomKickButton = ({
specificLabel: _t("Remove them from specific things I'm able to"),
warningMessage: _t("They'll still be able to access whatever you're not an admin of."),
},
room.isSpaceRoom() ? "mx_ConfirmSpaceUserActionDialog_wrapper" : undefined,
);
"mx_ConfirmSpaceUserActionDialog_wrapper",
));
} else {
({ finished } = Modal.createDialog(ConfirmUserActionDialog, commonProps));
}
const [proceed, reason, rooms = []] = await finished;
if (!proceed) return;
@ -705,9 +713,7 @@ export const BanToggleButton = ({
const isBanned = member.membership === "ban";
const onBanOrUnban = async (): Promise<void> => {
const { finished } = Modal.createDialog(
room.isSpaceRoom() ? ConfirmSpaceUserActionDialog : ConfirmUserActionDialog,
{
const commonProps = {
member,
action: room.isSpaceRoom()
? isBanned
@ -721,7 +727,15 @@ export const BanToggleButton = ({
: _t("Ban from %(roomName)s", { roomName: room.name }),
askReason: !isBanned,
danger: !isBanned,
// space-specific props
};
let finished: Promise<[success?: boolean, reason?: string, rooms?: Room[]]>;
if (room.isSpaceRoom()) {
({ finished } = Modal.createDialog(
ConfirmSpaceUserActionDialog,
{
...commonProps,
space: room,
spaceChildFilter: isBanned
? (child: Room) => {
@ -758,8 +772,11 @@ export const BanToggleButton = ({
? _t("They won't be able to access whatever you're not an admin of.")
: _t("They'll still be able to access whatever you're not an admin of."),
},
room.isSpaceRoom() ? "mx_ConfirmSpaceUserActionDialog_wrapper" : undefined,
);
"mx_ConfirmSpaceUserActionDialog_wrapper",
));
} else {
({ finished } = Modal.createDialog(ConfirmUserActionDialog, commonProps));
}
const [proceed, reason, rooms = []] = await finished;
if (!proceed) return;
@ -1173,8 +1190,8 @@ export const useDevices = (userId: string): IDevice[] | undefined | null => {
return;
}
disambiguateDevices(devices as IDevice[]);
setDevices(devices as IDevice[]);
disambiguateDevices(devices);
setDevices(devices);
} catch (err) {
setDevices(null);
}
@ -1193,7 +1210,7 @@ export const useDevices = (userId: string): IDevice[] | undefined | null => {
const updateDevices = async (): Promise<void> => {
const newDevices = cli.getStoredDevicesForUser(userId);
if (cancel) return;
setDevices(newDevices as IDevice[]);
setDevices(newDevices);
};
const onDevicesUpdated = (users: string[]): void => {
if (!users.includes(userId)) return;
@ -1603,7 +1620,7 @@ const UserInfo: React.FC<IProps> = ({ user, room, onClose, phase = RightPanelPha
RightPanelStore.instance.popCard();
};
let content;
let content: JSX.Element | undefined;
switch (phase) {
case RightPanelPhases.RoomMemberInfo:
case RightPanelPhases.SpaceMemberInfo:
@ -1611,7 +1628,7 @@ const UserInfo: React.FC<IProps> = ({ user, room, onClose, phase = RightPanelPha
<BasicUserInfo
room={room as Room}
member={member as User}
devices={devices as IDevice[]}
devices={devices}
isRoomEncrypted={Boolean(isRoomEncrypted)}
/>
);

View file

@ -30,12 +30,11 @@ export function openLinkModal(
composerContext: ComposerContextState,
isEditing: boolean,
): void {
const modal = Modal.createDialog(
Modal.createDialog(
LinkModal,
{
composerContext,
composer,
onClose: () => modal.close(),
isTextEnabled: isSelectionEmpty(),
isEditing,
},
@ -52,18 +51,18 @@ function isEmpty(text: string): boolean {
interface LinkModalProps {
composer: FormattingFunctions;
isTextEnabled: boolean;
onClose: () => void;
onFinished: () => void;
composerContext: ComposerContextState;
isEditing: boolean;
}
export function LinkModal({
export const LinkModal: React.FC<LinkModalProps> = ({
composer,
isTextEnabled,
onClose,
onFinished,
composerContext,
isEditing,
}: LinkModalProps): JSX.Element {
}) => {
const [hasLinkChanged, setHasLinkChanged] = useState(false);
const [fields, setFields] = useState({ text: "", link: isEditing ? composer.getLink() : "" });
const hasText = !isEditing && isTextEnabled;
@ -74,7 +73,7 @@ export function LinkModal({
className="mx_LinkModal"
title={isEditing ? _t("Edit link") : _t("Create a link")}
hasCancel={true}
onFinished={onClose}
onFinished={onFinished}
>
<form
className="mx_LinkModal_content"
@ -82,7 +81,7 @@ export function LinkModal({
evt.preventDefault();
evt.stopPropagation();
onClose();
onFinished();
// When submitting is done when pressing enter when the link field has the focus,
// The link field is getting back the focus (due to react-focus-lock)
@ -126,7 +125,7 @@ export function LinkModal({
className="danger"
onClick={() => {
composer.removeLinks();
onClose();
onFinished();
}}
>
{_t("Remove")}
@ -136,10 +135,10 @@ export function LinkModal({
primaryButton={_t("Save")}
primaryDisabled={isSaveDisabled}
primaryIsSubmit={true}
onCancel={onClose}
onCancel={onFinished}
/>
</div>
</form>
</BaseDialog>
);
}
};

View file

@ -15,9 +15,10 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import React, { ComponentType } from "react";
import React from "react";
import { MatrixClient } from "matrix-js-sdk/src/client";
import type ExportE2eKeysDialog from "../../../async-components/views/dialogs/security/ExportE2eKeysDialog";
import Field from "../elements/Field";
import { MatrixClientPeg } from "../../../MatrixClientPeg";
import AccessibleButton from "../elements/AccessibleButton";
@ -100,7 +101,7 @@ export default class ChangePassword extends React.Component<IProps, IState> {
if (userHasOtherDevices && !serverSupportsControlOfDevicesLogout && this.props.confirm) {
// warn about logging out all devices
const { finished } = Modal.createDialog<[boolean]>(QuestionDialog, {
const { finished } = Modal.createDialog(QuestionDialog, {
title: _t("Warning!"),
description: (
<div>
@ -218,7 +219,7 @@ export default class ChangePassword extends React.Component<IProps, IState> {
private onExportE2eKeysClicked = (): void => {
Modal.createDialogAsync(
import("../../../async-components/views/dialogs/security/ExportE2eKeysDialog") as unknown as Promise<
ComponentType<{}>
typeof ExportE2eKeysDialog
>,
{
matrixClient: MatrixClientPeg.get(),

View file

@ -14,8 +14,10 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import React, { ComponentType } from "react";
import React from "react";
import type ExportE2eKeysDialog from "../../../async-components/views/dialogs/security/ExportE2eKeysDialog";
import type ImportE2eKeysDialog from "../../../async-components/views/dialogs/security/ImportE2eKeysDialog";
import { MatrixClientPeg } from "../../../MatrixClientPeg";
import { _t } from "../../../languageHandler";
import Modal from "../../../Modal";
@ -44,7 +46,7 @@ export default class CryptographyPanel extends React.Component<IProps, IState> {
identityKey = FormattingUtils.formatCryptoKey(identityKey);
}
let importExportButtons = null;
let importExportButtons: JSX.Element | undefined;
if (client.isCryptoEnabled()) {
importExportButtons = (
<div className="mx_CryptographyPanel_importExportButtons">
@ -58,7 +60,7 @@ export default class CryptographyPanel extends React.Component<IProps, IState> {
);
}
let noSendUnverifiedSetting;
let noSendUnverifiedSetting: JSX.Element | undefined;
if (SettingsStore.isEnabled("blacklistUnverifiedDevices")) {
noSendUnverifiedSetting = (
<SettingsFlag
@ -99,7 +101,7 @@ export default class CryptographyPanel extends React.Component<IProps, IState> {
private onExportE2eKeysClicked = (): void => {
Modal.createDialogAsync(
import("../../../async-components/views/dialogs/security/ExportE2eKeysDialog") as unknown as Promise<
ComponentType<{}>
typeof ExportE2eKeysDialog
>,
{ matrixClient: MatrixClientPeg.get() },
);
@ -108,7 +110,7 @@ export default class CryptographyPanel extends React.Component<IProps, IState> {
private onImportE2eKeysClicked = (): void => {
Modal.createDialogAsync(
import("../../../async-components/views/dialogs/security/ImportE2eKeysDialog") as unknown as Promise<
ComponentType<{}>
typeof ImportE2eKeysDialog
>,
{ matrixClient: MatrixClientPeg.get() },
);

Some files were not shown because too many files have changed in this diff Show more