From 6aefd9318ffa9801f188e6d7b1ccd70d5dbb6617 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C5=A0imon=20Brandner?=
Date: Sat, 4 Sep 2021 16:16:21 +0200
Subject: [PATCH 01/34] Convert BaseDialog to TS
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Šimon Brandner
---
.../dialogs/{BaseDialog.js => BaseDialog.tsx} | 112 +++++++++---------
.../security/SetupEncryptionDialog.tsx | 2 +-
2 files changed, 57 insertions(+), 57 deletions(-)
rename src/components/views/dialogs/{BaseDialog.js => BaseDialog.tsx} (61%)
diff --git a/src/components/views/dialogs/BaseDialog.js b/src/components/views/dialogs/BaseDialog.tsx
similarity index 61%
rename from src/components/views/dialogs/BaseDialog.js
rename to src/components/views/dialogs/BaseDialog.tsx
index 42b21ec743..91cceb3123 100644
--- a/src/components/views/dialogs/BaseDialog.js
+++ b/src/components/views/dialogs/BaseDialog.tsx
@@ -18,15 +18,59 @@ limitations under the License.
import React from 'react';
import FocusLock from 'react-focus-lock';
-import PropTypes from 'prop-types';
import classNames from 'classnames';
import { Key } from '../../../Keyboard';
-import AccessibleButton from '../elements/AccessibleButton';
+import AccessibleButton, { ButtonEvent } from '../elements/AccessibleButton';
import { MatrixClientPeg } from '../../../MatrixClientPeg';
import { _t } from "../../../languageHandler";
import MatrixClientContext from "../../../contexts/MatrixClientContext";
import { replaceableComponent } from "../../../utils/replaceableComponent";
+import { MatrixClient } from "matrix-js-sdk/src/client";
+
+interface IProps {
+ // onFinished callback to call when Escape is pressed
+ // Take a boolean which is true if the dialog was dismissed
+ // with a positive / confirm action or false if it was
+ // cancelled (BaseDialog itself only calls this with false).
+ onFinished: (confirm: any) => void;
+
+ // 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
+ // dialog is cancelled, eg. "We can't restore your session and
+ // the app cannot work". Default: true.
+ hasCancel?: boolean;
+
+ // called when a key is pressed
+ onKeyDown?: (e: KeyboardEvent | React.KeyboardEvent) => void;
+
+ // CSS class to apply to dialog div
+ className?: string;
+
+ // if true, dialog container is 60% of the viewport width. Otherwise,
+ // the container will have no fixed size, allowing its contents to
+ // determine its size. Default: true.
+ fixedWidth?: boolean;
+
+ // Title for the dialog.
+ title?: JSX.Element | string;
+
+ // Path to an icon to put in the header
+ headerImage?: string;
+
+ // children should be the content of the dialog
+ children?: React.ReactNode;
+
+ // Id of content element
+ // If provided, this is used to add a aria-describedby attribute
+ contentId?: string;
+
+ // optional additional class for the title element (basically anything that can be passed to classnames)
+ titleClass?: string | string[];
+
+ headerButton?: JSX.Element;
+}
/*
* Basic container for modal dialogs.
@@ -35,54 +79,10 @@ import { replaceableComponent } from "../../../utils/replaceableComponent";
* dialog on escape.
*/
@replaceableComponent("views.dialogs.BaseDialog")
-export default class BaseDialog extends React.Component {
- static propTypes = {
- // onFinished callback to call when Escape is pressed
- // Take a boolean which is true if the dialog was dismissed
- // with a positive / confirm action or false if it was
- // cancelled (BaseDialog itself only calls this with false).
- onFinished: PropTypes.func.isRequired,
+export default class BaseDialog extends React.Component {
+ private matrixClient: MatrixClient;
- // 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
- // dialog is cancelled, eg. "We can't restore your session and
- // the app cannot work". Default: true.
- hasCancel: PropTypes.bool,
-
- // called when a key is pressed
- onKeyDown: PropTypes.func,
-
- // CSS class to apply to dialog div
- className: PropTypes.string,
-
- // if true, dialog container is 60% of the viewport width. Otherwise,
- // the container will have no fixed size, allowing its contents to
- // determine its size. Default: true.
- fixedWidth: PropTypes.bool,
-
- // Title for the dialog.
- title: PropTypes.node.isRequired,
-
- // Path to an icon to put in the header
- headerImage: PropTypes.string,
-
- // children should be the content of the dialog
- children: PropTypes.node,
-
- // Id of content element
- // If provided, this is used to add a aria-describedby attribute
- contentId: PropTypes.string,
-
- // optional additional class for the title element (basically anything that can be passed to classnames)
- titleClass: PropTypes.oneOfType([
- PropTypes.string,
- PropTypes.object,
- PropTypes.arrayOf(PropTypes.string),
- ]),
- };
-
- static defaultProps = {
+ public static defaultProps = {
hasCancel: true,
fixedWidth: true,
};
@@ -90,10 +90,10 @@ export default class BaseDialog extends React.Component {
constructor(props) {
super(props);
- this._matrixClient = MatrixClientPeg.get();
+ this.matrixClient = MatrixClientPeg.get();
}
- _onKeyDown = (e) => {
+ private onKeyDown = (e: KeyboardEvent | React.KeyboardEvent): void => {
if (this.props.onKeyDown) {
this.props.onKeyDown(e);
}
@@ -104,15 +104,15 @@ export default class BaseDialog extends React.Component {
}
};
- _onCancelClick = (e) => {
+ private onCancelClick = (e: ButtonEvent): void => {
this.props.onFinished(false);
};
- render() {
+ public render(): JSX.Element {
let cancelButton;
if (this.props.hasCancel) {
cancelButton = (
-
+
);
}
@@ -122,11 +122,11 @@ export default class BaseDialog extends React.Component {
}
return (
-
+
Date: Sat, 4 Sep 2021 16:36:01 +0200
Subject: [PATCH 02/34] Convert FeedbackDialog to TS
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Šimon Brandner
---
src/CountlyAnalytics.ts | 4 +++-
.../{FeedbackDialog.js => FeedbackDialog.tsx} | 20 ++++++++++++-------
2 files changed, 16 insertions(+), 8 deletions(-)
rename src/components/views/dialogs/{FeedbackDialog.js => FeedbackDialog.tsx} (90%)
diff --git a/src/CountlyAnalytics.ts b/src/CountlyAnalytics.ts
index 72b0462bcd..be35597734 100644
--- a/src/CountlyAnalytics.ts
+++ b/src/CountlyAnalytics.ts
@@ -30,6 +30,8 @@ const HEARTBEAT_INTERVAL = 5_000; // ms
const SESSION_UPDATE_INTERVAL = 60; // seconds
const MAX_PENDING_EVENTS = 1000;
+export type Rating = 1 | 2 | 3 | 4 | 5;
+
enum Orientation {
Landscape = "landscape",
Portrait = "portrait",
@@ -451,7 +453,7 @@ export default class CountlyAnalytics {
window.removeEventListener("scroll", this.onUserActivity);
}
- public reportFeedback(rating: 1 | 2 | 3 | 4 | 5, comment: string) {
+ public reportFeedback(rating: Rating, comment: string) {
this.track("[CLY]_star_rating", { rating, comment }, null, {}, true);
}
diff --git a/src/components/views/dialogs/FeedbackDialog.js b/src/components/views/dialogs/FeedbackDialog.tsx
similarity index 90%
rename from src/components/views/dialogs/FeedbackDialog.js
rename to src/components/views/dialogs/FeedbackDialog.tsx
index ceb8cb2175..00112ab0c7 100644
--- a/src/components/views/dialogs/FeedbackDialog.js
+++ b/src/components/views/dialogs/FeedbackDialog.tsx
@@ -19,7 +19,7 @@ import QuestionDialog from './QuestionDialog';
import { _t } from '../../../languageHandler';
import Field from "../elements/Field";
import AccessibleButton from "../elements/AccessibleButton";
-import CountlyAnalytics from "../../../CountlyAnalytics";
+import CountlyAnalytics, { Rating } from "../../../CountlyAnalytics";
import SdkConfig from "../../../SdkConfig";
import Modal from "../../../Modal";
import BugReportDialog from "./BugReportDialog";
@@ -30,19 +30,23 @@ 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";
-export default (props) => {
- const [rating, setRating] = useState("");
- const [comment, setComment] = useState("");
+interface IProps {
+ onFinished: () => void;
+}
- const onDebugLogsLinkClick = () => {
+const FeedbackDialog: React.FC = (props: IProps) => {
+ const [rating, setRating] = useState();
+ const [comment, setComment] = useState("");
+
+ const onDebugLogsLinkClick = (): void => {
props.onFinished();
Modal.createTrackedDialog('Bug Report Dialog', '', BugReportDialog, {});
};
const hasFeedback = CountlyAnalytics.instance.canEnable();
- const onFinished = (sendFeedback) => {
+ const onFinished = (sendFeedback: boolean): void => {
if (hasFeedback && sendFeedback) {
- CountlyAnalytics.instance.reportFeedback(parseInt(rating, 10), comment);
+ CountlyAnalytics.instance.reportFeedback((parseInt(rating) as Rating), comment);
Modal.createTrackedDialog('Feedback sent', '', InfoDialog, {
title: _t('Feedback sent'),
description: _t('Thank you!'),
@@ -142,3 +146,5 @@ export default (props) => {
onFinished={onFinished}
/>);
};
+
+export default FeedbackDialog;
From 3c9ded5a9acb165cfb061513ad1f62e9532273a7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C5=A0imon=20Brandner?=
Date: Sat, 4 Sep 2021 18:40:54 +0200
Subject: [PATCH 03/34] Convert RestoreKeyBackupDialog to TS
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Šimon Brandner
---
...upDialog.js => RestoreKeyBackupDialog.tsx} | 175 +++++++++++-------
1 file changed, 103 insertions(+), 72 deletions(-)
rename src/components/views/dialogs/security/{RestoreKeyBackupDialog.js => RestoreKeyBackupDialog.tsx} (77%)
diff --git a/src/components/views/dialogs/security/RestoreKeyBackupDialog.js b/src/components/views/dialogs/security/RestoreKeyBackupDialog.tsx
similarity index 77%
rename from src/components/views/dialogs/security/RestoreKeyBackupDialog.js
rename to src/components/views/dialogs/security/RestoreKeyBackupDialog.tsx
index 2b272a3b88..d2b850eb85 100644
--- a/src/components/views/dialogs/security/RestoreKeyBackupDialog.js
+++ b/src/components/views/dialogs/security/RestoreKeyBackupDialog.tsx
@@ -16,30 +16,64 @@ limitations under the License.
*/
import React from 'react';
-import PropTypes from 'prop-types';
-import * as sdk from '../../../../index';
import { MatrixClientPeg } from '../../../../MatrixClientPeg';
import { MatrixClient } from 'matrix-js-sdk/src/client';
import { _t } from '../../../../languageHandler';
import { accessSecretStorage } from '../../../../SecurityManager';
+import { IKeyBackupInfo, IKeyBackupRestoreResult } from "matrix-js-sdk/src/crypto/keybackup";
+import { ISecretStorageKeyInfo } from "matrix-js-sdk/src/crypto/api";
+import * as sdk from '../../../../index';
-const RESTORE_TYPE_PASSPHRASE = 0;
-const RESTORE_TYPE_RECOVERYKEY = 1;
-const RESTORE_TYPE_SECRET_STORAGE = 2;
+enum RestoreType {
+ Passphrase = "passphrase",
+ RecoveryKey = "recovery_key",
+ SecretStorage = "secret_storage"
+}
+
+enum ProgressState {
+ PreFetch = "prefetch",
+ Fetch = "fetch",
+ LoadKeys = "load_keys",
+
+}
+
+interface IProps {
+ // if false, will close the dialog as soon as the restore completes succesfully
+ // 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: (success: boolean) => void;
+}
+
+interface IState {
+ backupInfo: IKeyBackupInfo;
+ backupKeyStored: Record;
+ loading: boolean;
+ loadError: string;
+ restoreError: {
+ errcode: string;
+ };
+ recoveryKey: string;
+ recoverInfo: IKeyBackupRestoreResult;
+ recoveryKeyValid: boolean;
+ forceRecoveryKey: boolean;
+ passPhrase: "";
+ restoreType: RestoreType;
+ progress: {
+ stage: ProgressState;
+ total?: number;
+ successes?: number;
+ failures?: number;
+ };
+}
/*
* Dialog for restoring e2e keys from a backup and the user's recovery key
*/
-export default class RestoreKeyBackupDialog extends React.PureComponent {
- static propTypes = {
- // if false, will close the dialog as soon as the restore completes succesfully
- // default: true
- showSummary: PropTypes.bool,
- // 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: PropTypes.func,
- };
-
+export default class RestoreKeyBackupDialog extends React.PureComponent {
static defaultProps = {
showSummary: true,
};
@@ -58,58 +92,58 @@ export default class RestoreKeyBackupDialog extends React.PureComponent {
forceRecoveryKey: false,
passPhrase: '',
restoreType: null,
- progress: { stage: "prefetch" },
+ progress: { stage: ProgressState.PreFetch },
};
}
- componentDidMount() {
- this._loadBackupStatus();
+ public componentDidMount(): void {
+ this.loadBackupStatus();
}
- _onCancel = () => {
+ private onCancel = (): void => {
this.props.onFinished(false);
- }
+ };
- _onDone = () => {
+ private onDone = (): void => {
this.props.onFinished(true);
- }
+ };
- _onUseRecoveryKeyClick = () => {
+ private onUseRecoveryKeyClick = (): void => {
this.setState({
forceRecoveryKey: true,
});
- }
+ };
- _progressCallback = (data) => {
+ private progressCallback = (data): void => {
this.setState({
progress: data,
});
- }
+ };
- _onResetRecoveryClick = () => {
+ private onResetRecoveryClick = (): void => {
this.props.onFinished(false);
- accessSecretStorage(() => {}, /* forceReset = */ true);
- }
+ accessSecretStorage(async () => {}, /* forceReset = */ true);
+ };
- _onRecoveryKeyChange = (e) => {
+ private onRecoveryKeyChange = (e): void => {
this.setState({
recoveryKey: e.target.value,
recoveryKeyValid: MatrixClientPeg.get().isValidRecoveryKey(e.target.value),
});
- }
+ };
- _onPassPhraseNext = async () => {
+ private onPassPhraseNext = async (): Promise => {
this.setState({
loading: true,
restoreError: null,
- restoreType: RESTORE_TYPE_PASSPHRASE,
+ restoreType: RestoreType.Passphrase,
});
try {
// We do still restore the key backup: we must ensure that the key backup key
// is the right one and restoring it is currently the only way we can do this.
const recoverInfo = await MatrixClientPeg.get().restoreKeyBackupWithPassword(
this.state.passPhrase, undefined, undefined, this.state.backupInfo,
- { progressCallback: this._progressCallback },
+ { progressCallback: this.progressCallback },
);
if (this.props.keyCallback) {
const key = await MatrixClientPeg.get().keyBackupKeyFromPassword(
@@ -133,20 +167,20 @@ export default class RestoreKeyBackupDialog extends React.PureComponent {
restoreError: e,
});
}
- }
+ };
- _onRecoveryKeyNext = async () => {
+ private onRecoveryKeyNext = async (): Promise => {
if (!this.state.recoveryKeyValid) return;
this.setState({
loading: true,
restoreError: null,
- restoreType: RESTORE_TYPE_RECOVERYKEY,
+ restoreType: RestoreType.RecoveryKey,
});
try {
const recoverInfo = await MatrixClientPeg.get().restoreKeyBackupWithRecoveryKey(
this.state.recoveryKey, undefined, undefined, this.state.backupInfo,
- { progressCallback: this._progressCallback },
+ { progressCallback: this.progressCallback },
);
if (this.props.keyCallback) {
const key = MatrixClientPeg.get().keyBackupKeyFromRecoveryKey(this.state.recoveryKey);
@@ -167,31 +201,30 @@ export default class RestoreKeyBackupDialog extends React.PureComponent {
restoreError: e,
});
}
- }
+ };
- _onPassPhraseChange = (e) => {
+ private onPassPhraseChange = (e): void => {
this.setState({
passPhrase: e.target.value,
});
- }
+ };
- async _restoreWithSecretStorage() {
+ private async restoreWithSecretStorage(): Promise {
this.setState({
loading: true,
restoreError: null,
- restoreType: RESTORE_TYPE_SECRET_STORAGE,
+ restoreType: RestoreType.SecretStorage,
});
try {
// `accessSecretStorage` may prompt for storage access as needed.
- const recoverInfo = await accessSecretStorage(async () => {
- return MatrixClientPeg.get().restoreKeyBackupWithSecretStorage(
+ await accessSecretStorage(async () => {
+ await MatrixClientPeg.get().restoreKeyBackupWithSecretStorage(
this.state.backupInfo, undefined, undefined,
- { progressCallback: this._progressCallback },
+ { progressCallback: this.progressCallback },
);
});
this.setState({
loading: false,
- recoverInfo,
});
} catch (e) {
console.log("Error restoring backup", e);
@@ -202,14 +235,14 @@ export default class RestoreKeyBackupDialog extends React.PureComponent {
}
}
- async _restoreWithCachedKey(backupInfo) {
+ private async restoreWithCachedKey(backupInfo): Promise {
if (!backupInfo) return false;
try {
const recoverInfo = await MatrixClientPeg.get().restoreKeyBackupWithCache(
undefined, /* targetRoomId */
undefined, /* targetSessionId */
backupInfo,
- { progressCallback: this._progressCallback },
+ { progressCallback: this.progressCallback },
);
this.setState({
recoverInfo,
@@ -221,7 +254,7 @@ export default class RestoreKeyBackupDialog extends React.PureComponent {
}
}
- async _loadBackupStatus() {
+ private async loadBackupStatus(): Promise {
this.setState({
loading: true,
loadError: null,
@@ -236,7 +269,7 @@ export default class RestoreKeyBackupDialog extends React.PureComponent {
backupKeyStored,
});
- const gotCache = await this._restoreWithCachedKey(backupInfo);
+ const gotCache = await this.restoreWithCachedKey(backupInfo);
if (gotCache) {
console.log("RestoreKeyBackupDialog: found cached backup key");
this.setState({
@@ -247,7 +280,7 @@ export default class RestoreKeyBackupDialog extends React.PureComponent {
// If the backup key is stored, we can proceed directly to restore.
if (backupKeyStored) {
- return this._restoreWithSecretStorage();
+ return this.restoreWithSecretStorage();
}
this.setState({
@@ -263,7 +296,10 @@ export default class RestoreKeyBackupDialog extends React.PureComponent {
}
}
- render() {
+ public render(): JSX.Element {
+ // FIXME: Making these into imports will break tests
+ const DialogButtons = sdk.getComponent('views.elements.DialogButtons');
+ const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
const Spinner = sdk.getComponent("elements.Spinner");
@@ -279,12 +315,12 @@ export default class RestoreKeyBackupDialog extends React.PureComponent {
if (this.state.loading) {
title = _t("Restoring keys from backup");
let details;
- if (this.state.progress.stage === "fetch") {
+ if (this.state.progress.stage === ProgressState.Fetch) {
details = _t("Fetching keys from server...");
- } else if (this.state.progress.stage === "load_keys") {
+ } else if (this.state.progress.stage === ProgressState.LoadKeys) {
const { total, successes, failures } = this.state.progress;
details = _t("%(completed)s of %(total)s keys restored", { total, completed: successes + failures });
- } else if (this.state.progress.stage === "prefetch") {
+ } else if (this.state.progress.stage === ProgressState.PreFetch) {
details = _t("Fetching keys from server...");
}
content =
@@ -296,7 +332,7 @@ export default class RestoreKeyBackupDialog extends React.PureComponent {
content = _t("Unable to load backup status");
} else if (this.state.restoreError) {
if (this.state.restoreError.errcode === MatrixClient.RESTORE_BACKUP_ERROR_BAD_KEY) {
- if (this.state.restoreType === RESTORE_TYPE_RECOVERYKEY) {
+ if (this.state.restoreType === RestoreType.RecoveryKey) {
title = _t("Security Key mismatch");
content =
{ _t(
@@ -321,7 +357,6 @@ export default class RestoreKeyBackupDialog extends React.PureComponent {
title = _t("Error");
content = _t("No backup found!");
} else if (this.state.recoverInfo) {
- const DialogButtons = sdk.getComponent('views.elements.DialogButtons');
title = _t("Keys restored");
let failedToDecrypt;
if (this.state.recoverInfo.total > this.state.recoverInfo.imported) {
@@ -334,14 +369,12 @@ export default class RestoreKeyBackupDialog extends React.PureComponent {
{ _t("Successfully restored %(sessionCount)s keys", { sessionCount: this.state.recoverInfo.imported }) }
{ failedToDecrypt }
;
} else if (backupHasPassphrase && !this.state.forceRecoveryKey) {
- const DialogButtons = sdk.getComponent('views.elements.DialogButtons');
- const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
title = _t("Enter Security Phrase");
content =
{ _t(
@@ -357,16 +390,16 @@ export default class RestoreKeyBackupDialog extends React.PureComponent {
@@ -379,14 +412,14 @@ export default class RestoreKeyBackupDialog extends React.PureComponent {
button1: s =>
{ s }
,
button2: s =>
{ s }
,
@@ -394,8 +427,6 @@ export default class RestoreKeyBackupDialog extends React.PureComponent {
;
} else {
title = _t("Enter Security Key");
- const DialogButtons = sdk.getComponent('views.elements.DialogButtons');
- const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
let keyStatus;
if (this.state.recoveryKey.length === 0) {
@@ -423,15 +454,15 @@ export default class RestoreKeyBackupDialog extends React.PureComponent {
{ keyStatus }
@@ -443,7 +474,7 @@ export default class RestoreKeyBackupDialog extends React.PureComponent {
{
button: s =>
{ s }
,
From 0b9255f5eecb2a8c0ea8f9804c03704e81de620a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C5=A0imon=20Brandner?=
Date: Sun, 5 Sep 2021 08:31:06 +0200
Subject: [PATCH 04/34] Convert UploadFailureDialog to TS
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Šimon Brandner
---
...ilureDialog.js => UploadFailureDialog.tsx} | 43 +++++++++----------
1 file changed, 20 insertions(+), 23 deletions(-)
rename src/components/views/dialogs/{UploadFailureDialog.js => UploadFailureDialog.tsx} (80%)
diff --git a/src/components/views/dialogs/UploadFailureDialog.js b/src/components/views/dialogs/UploadFailureDialog.tsx
similarity index 80%
rename from src/components/views/dialogs/UploadFailureDialog.js
rename to src/components/views/dialogs/UploadFailureDialog.tsx
index 224098f935..807cb08195 100644
--- a/src/components/views/dialogs/UploadFailureDialog.js
+++ b/src/components/views/dialogs/UploadFailureDialog.tsx
@@ -17,11 +17,18 @@ limitations under the License.
import filesize from 'filesize';
import React from 'react';
-import PropTypes from 'prop-types';
-import * as sdk from '../../../index';
import { _t } from '../../../languageHandler';
import ContentMessages from '../../../ContentMessages';
import { replaceableComponent } from "../../../utils/replaceableComponent";
+import BaseDialog from "./BaseDialog";
+import DialogButtons from "../elements/DialogButtons";
+
+interface IProps {
+ badFiles: File[];
+ totalFiles: number;
+ contentMessages: ContentMessages;
+ onFinished: (success: boolean) => void;
+}
/*
* Tells the user about files we know cannot be uploaded before we even try uploading
@@ -29,26 +36,16 @@ import { replaceableComponent } from "../../../utils/replaceableComponent";
* the size of the file.
*/
@replaceableComponent("views.dialogs.UploadFailureDialog")
-export default class UploadFailureDialog extends React.Component {
- static propTypes = {
- badFiles: PropTypes.arrayOf(PropTypes.object).isRequired,
- totalFiles: PropTypes.number.isRequired,
- contentMessages: PropTypes.instanceOf(ContentMessages).isRequired,
- onFinished: PropTypes.func.isRequired,
- }
-
- _onCancelClick = () => {
+export default class UploadFailureDialog extends React.Component {
+ private onCancelClick = (): void => {
this.props.onFinished(false);
- }
+ };
- _onUploadClick = () => {
+ private onUploadClick = (): void => {
this.props.onFinished(true);
- }
-
- render() {
- const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
- const DialogButtons = sdk.getComponent('views.elements.DialogButtons');
+ };
+ public render(): JSX.Element {
let message;
let preview;
let buttons;
@@ -65,7 +62,7 @@ export default class UploadFailureDialog extends React.Component {
);
buttons = ;
} else if (this.props.totalFiles === this.props.badFiles.length) {
@@ -80,7 +77,7 @@ export default class UploadFailureDialog extends React.Component {
);
buttons = ;
} else {
@@ -96,17 +93,17 @@ export default class UploadFailureDialog extends React.Component {
const howManyOthers = this.props.totalFiles - this.props.badFiles.length;
buttons = ;
}
return (
From 37099fd188c585fce7867a75df74d0dd3b84d64d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C5=A0imon=20Brandner?=
Date: Sun, 5 Sep 2021 08:35:24 +0200
Subject: [PATCH 05/34] Convert TextInputDialog to TS
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Šimon Brandner
---
...TextInputDialog.js => TextInputDialog.tsx} | 79 ++++++++++---------
1 file changed, 40 insertions(+), 39 deletions(-)
rename src/components/views/dialogs/{TextInputDialog.js => TextInputDialog.tsx} (67%)
diff --git a/src/components/views/dialogs/TextInputDialog.js b/src/components/views/dialogs/TextInputDialog.tsx
similarity index 67%
rename from src/components/views/dialogs/TextInputDialog.js
rename to src/components/views/dialogs/TextInputDialog.tsx
index 3d37c89424..624e2a58cb 100644
--- a/src/components/views/dialogs/TextInputDialog.js
+++ b/src/components/views/dialogs/TextInputDialog.tsx
@@ -14,33 +14,39 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-import React, { createRef } from 'react';
-import PropTypes from 'prop-types';
-import * as sdk from '../../../index';
+import React, { ChangeEvent, createRef } from 'react';
import Field from "../elements/Field";
import { _t, _td } from '../../../languageHandler';
import { replaceableComponent } from "../../../utils/replaceableComponent";
+import { IFieldState, IValidationResult } from "../elements/Validation";
+import BaseDialog from "./BaseDialog";
+import DialogButtons from "../elements/DialogButtons";
+
+ interface IProps {
+ title?: string;
+ description?: string | JSX.Element;
+ value?: string;
+ placeholder?: string;
+ button?: string;
+ busyMessage?: string; // pass _td string
+ focus?: boolean;
+ onFinished: (success: boolean, value?: string) => void;
+ hasCancel?: boolean;
+ validator?: (fieldState: IFieldState) => IValidationResult; // result of withValidation
+ fixedWidth?: boolean;
+}
+
+interface IState {
+ value: string;
+ busy: boolean;
+ valid: boolean;
+}
@replaceableComponent("views.dialogs.TextInputDialog")
-export default class TextInputDialog extends React.Component {
- static propTypes = {
- title: PropTypes.string,
- description: PropTypes.oneOfType([
- PropTypes.element,
- PropTypes.string,
- ]),
- value: PropTypes.string,
- placeholder: PropTypes.string,
- button: PropTypes.string,
- busyMessage: PropTypes.string, // pass _td string
- focus: PropTypes.bool,
- onFinished: PropTypes.func.isRequired,
- hasCancel: PropTypes.bool,
- validator: PropTypes.func, // result of withValidation
- fixedWidth: PropTypes.bool,
- };
+export default class TextInputDialog extends React.Component {
+ private field = createRef();
- static defaultProps = {
+ public static defaultProps = {
title: "",
value: "",
description: "",
@@ -49,11 +55,9 @@ export default class TextInputDialog extends React.Component {
hasCancel: true,
};
- constructor(props) {
+ constructor(props: IProps) {
super(props);
- this._field = createRef();
-
this.state = {
value: this.props.value,
busy: false,
@@ -61,23 +65,23 @@ export default class TextInputDialog extends React.Component {
};
}
- componentDidMount() {
+ public componentDidMount(): void {
if (this.props.focus) {
// Set the cursor at the end of the text input
// this._field.current.value = this.props.value;
- this._field.current.focus();
+ this.field.current.focus();
}
}
- onOk = async ev => {
+ private onOk = async (ev: React.FormEvent): Promise => {
ev.preventDefault();
if (this.props.validator) {
this.setState({ busy: true });
- await this._field.current.validate({ allowEmpty: false });
+ await this.field.current.validate({ allowEmpty: false });
- if (!this._field.current.state.valid) {
- this._field.current.focus();
- this._field.current.validate({ allowEmpty: false, focused: true });
+ if (!this.field.current.state.valid) {
+ this.field.current.focus();
+ this.field.current.validate({ allowEmpty: false, focused: true });
this.setState({ busy: false });
return;
}
@@ -85,17 +89,17 @@ export default class TextInputDialog extends React.Component {
this.props.onFinished(true, this.state.value);
};
- onCancel = () => {
+ private onCancel = (): void => {
this.props.onFinished(false);
};
- onChange = ev => {
+ private onChange = (ev: ChangeEvent): void => {
this.setState({
value: ev.target.value,
});
};
- onValidate = async fieldState => {
+ private onValidate = async (fieldState: IFieldState): Promise => {
const result = await this.props.validator(fieldState);
this.setState({
valid: result.valid,
@@ -103,9 +107,7 @@ export default class TextInputDialog extends React.Component {
return result;
};
- render() {
- const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
- const DialogButtons = sdk.getComponent('views.elements.DialogButtons');
+ public render(): JSX.Element {
return (
From 161937ac924311f87cc1aa95d932f7e53cc25e6a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C5=A0imon=20Brandner?=
Date: Sun, 5 Sep 2021 09:11:08 +0200
Subject: [PATCH 06/34] Convert TabbedIntegrationManagerDialog to TS
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Šimon Brandner
---
....js => TabbedIntegrationManagerDialog.tsx} | 84 ++++++++++---------
1 file changed, 46 insertions(+), 38 deletions(-)
rename src/components/views/dialogs/{TabbedIntegrationManagerDialog.js => TabbedIntegrationManagerDialog.tsx} (76%)
diff --git a/src/components/views/dialogs/TabbedIntegrationManagerDialog.js b/src/components/views/dialogs/TabbedIntegrationManagerDialog.tsx
similarity index 76%
rename from src/components/views/dialogs/TabbedIntegrationManagerDialog.js
rename to src/components/views/dialogs/TabbedIntegrationManagerDialog.tsx
index 8723d4a453..c8ab25b1bb 100644
--- a/src/components/views/dialogs/TabbedIntegrationManagerDialog.js
+++ b/src/components/views/dialogs/TabbedIntegrationManagerDialog.tsx
@@ -15,42 +15,53 @@ limitations under the License.
*/
import React from 'react';
-import PropTypes from 'prop-types';
import { IntegrationManagers } from "../../../integrations/IntegrationManagers";
import { Room } from "matrix-js-sdk/src/models/room";
-import * as sdk from '../../../index';
import { dialogTermsInteractionCallback, TermsNotSignedError } from "../../../Terms";
import classNames from 'classnames';
import * as ScalarMessaging from "../../../ScalarMessaging";
import { replaceableComponent } from "../../../utils/replaceableComponent";
+import { IntegrationManagerInstance } from "../../../integrations/IntegrationManagerInstance";
+import ScalarAuthClient from "../../../ScalarAuthClient";
+import AccessibleButton from "../elements/AccessibleButton";
+import IntegrationManager from "../settings/IntegrationManager";
+
+interface IProps {
+ /**
+ * Called with:
+ * * success {bool} True if the user accepted any douments, false if cancelled
+ * * agreedUrls {string[]} List of agreed URLs
+ */
+ onFinished: () => void;
+
+ /**
+ * Optional room where the integration manager should be open to
+ */
+ room: Room;
+
+ /**
+ * Optional screen to open on the integration manager
+ */
+ screen?: string;
+
+ /**
+ * Optional integration ID to open in the integration manager
+ */
+ integrationId?: string;
+}
+
+interface IState {
+ managers: IntegrationManagerInstance[];
+ busy: boolean;
+ currentIndex: number;
+ currentConnected: boolean;
+ currentLoading: boolean;
+ currentScalarClient: ScalarAuthClient;
+}
@replaceableComponent("views.dialogs.TabbedIntegrationManagerDialog")
-export default class TabbedIntegrationManagerDialog extends React.Component {
- static propTypes = {
- /**
- * Called with:
- * * success {bool} True if the user accepted any douments, false if cancelled
- * * agreedUrls {string[]} List of agreed URLs
- */
- onFinished: PropTypes.func.isRequired,
-
- /**
- * Optional room where the integration manager should be open to
- */
- room: PropTypes.instanceOf(Room),
-
- /**
- * Optional screen to open on the integration manager
- */
- screen: PropTypes.string,
-
- /**
- * Optional integration ID to open in the integration manager
- */
- integrationId: PropTypes.string,
- };
-
- constructor(props) {
+export default class TabbedIntegrationManagerDialog extends React.Component {
+ constructor(props: IProps) {
super(props);
this.state = {
@@ -63,11 +74,11 @@ export default class TabbedIntegrationManagerDialog extends React.Component {
};
}
- componentDidMount() {
+ public componentDidMount(): void {
this.openManager(0, true);
}
- openManager = async (i, force = false) => {
+ private openManager = async (i: number, force = false): Promise => {
if (i === this.state.currentIndex && !force) return;
const manager = this.state.managers[i];
@@ -120,8 +131,7 @@ export default class TabbedIntegrationManagerDialog extends React.Component {
}
};
- _renderTabs() {
- const AccessibleButton = sdk.getComponent("views.elements.AccessibleButton");
+ private renderTabs(): JSX.Element[] {
return this.state.managers.map((m, i) => {
const classes = classNames({
'mx_TabbedIntegrationManagerDialog_tab': true,
@@ -140,8 +150,7 @@ export default class TabbedIntegrationManagerDialog extends React.Component {
});
}
- _renderTab() {
- const IntegrationManager = sdk.getComponent("views.settings.IntegrationManager");
+ public renderTab(): JSX.Element {
let uiUrl = null;
if (this.state.currentScalarClient) {
uiUrl = this.state.currentScalarClient.getScalarInterfaceUrlForRoom(
@@ -151,7 +160,6 @@ export default class TabbedIntegrationManagerDialog extends React.Component {
);
}
return ;
}
- render() {
+ public render(): JSX.Element {
return (
- { this._renderTabs() }
+ { this.renderTabs() }
- { this._renderTab() }
+ { this.renderTab() }
);
From 1f670e225c0c71d3afc15be8d289860556f8df00 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C5=A0imon=20Brandner?=
Date: Sun, 5 Sep 2021 10:53:57 +0200
Subject: [PATCH 07/34] Convert StorageEvictedDialog to TS
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Šimon Brandner
---
...ctedDialog.js => StorageEvictedDialog.tsx} | 29 +++++++++----------
1 file changed, 13 insertions(+), 16 deletions(-)
rename src/components/views/dialogs/{StorageEvictedDialog.js => StorageEvictedDialog.tsx} (79%)
diff --git a/src/components/views/dialogs/StorageEvictedDialog.js b/src/components/views/dialogs/StorageEvictedDialog.tsx
similarity index 79%
rename from src/components/views/dialogs/StorageEvictedDialog.js
rename to src/components/views/dialogs/StorageEvictedDialog.tsx
index 507ee09e75..60ae049bf6 100644
--- a/src/components/views/dialogs/StorageEvictedDialog.js
+++ b/src/components/views/dialogs/StorageEvictedDialog.tsx
@@ -15,40 +15,37 @@ limitations under the License.
*/
import React from 'react';
-import PropTypes from 'prop-types';
-import * as sdk from '../../../index';
import SdkConfig from '../../../SdkConfig';
import Modal from '../../../Modal';
import { _t } from '../../../languageHandler';
import { replaceableComponent } from "../../../utils/replaceableComponent";
+import BaseDialog from "./BaseDialog";
+import DialogButtons from "../elements/DialogButtons";
+import BugReportDialog from "./BugReportDialog";
+
+interface IProps {
+ onFinished: (confirmed: boolean) => void;
+}
@replaceableComponent("views.dialogs.StorageEvictedDialog")
-export default class StorageEvictedDialog extends React.Component {
- static propTypes = {
- onFinished: PropTypes.func.isRequired,
- };
-
- _sendBugReport = ev => {
+export default class StorageEvictedDialog extends React.Component {
+ private sendBugReport = (ev: React.MouseEvent): void => {
ev.preventDefault();
- const BugReportDialog = sdk.getComponent("dialogs.BugReportDialog");
Modal.createTrackedDialog('Storage evicted', 'Send Bug Report Dialog', BugReportDialog, {});
};
- _onSignOutClick = () => {
+ private onSignOutClick = (): void => {
this.props.onFinished(true);
};
- render() {
- const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
- const DialogButtons = sdk.getComponent('views.elements.DialogButtons');
-
+ public render(): JSX.Element {
let logRequest;
if (SdkConfig.get().bug_report_endpoint_url) {
logRequest = _t(
"To help us prevent this in future, please send us logs.",
{},
{
- a: text => { text },
+ a: text => { text },
},
);
}
@@ -73,7 +70,7 @@ export default class StorageEvictedDialog extends React.Component {
) } { logRequest }
From 444a0da2973a44e33d186e4fcfed432d6de90a26 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C5=A0imon=20Brandner?=
Date: Sun, 5 Sep 2021 11:58:38 +0200
Subject: [PATCH 08/34] Convert SlashCommandHelpDialog to TS
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Šimon Brandner
---
...CommandHelpDialog.js => SlashCommandHelpDialog.tsx} | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
rename src/components/views/dialogs/{SlashCommandHelpDialog.js => SlashCommandHelpDialog.tsx} (90%)
diff --git a/src/components/views/dialogs/SlashCommandHelpDialog.js b/src/components/views/dialogs/SlashCommandHelpDialog.tsx
similarity index 90%
rename from src/components/views/dialogs/SlashCommandHelpDialog.js
rename to src/components/views/dialogs/SlashCommandHelpDialog.tsx
index d21ccbe47f..c47555567e 100644
--- a/src/components/views/dialogs/SlashCommandHelpDialog.js
+++ b/src/components/views/dialogs/SlashCommandHelpDialog.tsx
@@ -17,11 +17,13 @@ limitations under the License.
import React from 'react';
import { _t } from "../../../languageHandler";
import { CommandCategories, Commands } from "../../../SlashCommands";
-import * as sdk from "../../../index";
+import InfoDialog from "./InfoDialog";
-export default ({ onFinished }) => {
- const InfoDialog = sdk.getComponent('dialogs.InfoDialog');
+interface IProps {
+ onFinished: () => void;
+}
+const SlashCommandHelpDialog: React.FC = ({ onFinished }) => {
const categories = {};
Commands.forEach(cmd => {
if (!cmd.isEnabled()) return;
@@ -62,3 +64,5 @@ export default ({ onFinished }) => {
hasCloseButton={true}
onFinished={onFinished} />;
};
+
+export default SlashCommandHelpDialog;
From 02f672570a5c5bc9421c76dc5167464be22d269a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C5=A0imon=20Brandner?=
Date: Sun, 5 Sep 2021 12:02:43 +0200
Subject: [PATCH 09/34] Convert WidgetOpenIDPermissionsDialog to TS
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Šimon Brandner
---
...g.js => WidgetOpenIDPermissionsDialog.tsx} | 53 ++++++++++---------
1 file changed, 27 insertions(+), 26 deletions(-)
rename src/components/views/dialogs/{WidgetOpenIDPermissionsDialog.js => WidgetOpenIDPermissionsDialog.tsx} (71%)
diff --git a/src/components/views/dialogs/WidgetOpenIDPermissionsDialog.js b/src/components/views/dialogs/WidgetOpenIDPermissionsDialog.tsx
similarity index 71%
rename from src/components/views/dialogs/WidgetOpenIDPermissionsDialog.js
rename to src/components/views/dialogs/WidgetOpenIDPermissionsDialog.tsx
index 1bc6444ac1..81bd53a32e 100644
--- a/src/components/views/dialogs/WidgetOpenIDPermissionsDialog.js
+++ b/src/components/views/dialogs/WidgetOpenIDPermissionsDialog.tsx
@@ -15,42 +15,46 @@ limitations under the License.
*/
import React from 'react';
-import PropTypes from 'prop-types';
import { _t } from "../../../languageHandler";
-import * as sdk from "../../../index";
import LabelledToggleSwitch from "../elements/LabelledToggleSwitch";
-import { Widget } from "matrix-widget-api";
+import { Widget, WidgetKind } from "matrix-widget-api";
import { OIDCState, WidgetPermissionStore } from "../../../stores/widgets/WidgetPermissionStore";
import { replaceableComponent } from "../../../utils/replaceableComponent";
+import DialogButtons from "../elements/DialogButtons";
+import BaseDialog from "./BaseDialog";
+
+interface IProps {
+ onFinished: (confirmed: boolean) => void;
+ widget: Widget;
+ widgetKind: WidgetKind; // WidgetKind from widget-api
+ inRoomId?: string;
+}
+
+interface IState {
+ rememberSelection: boolean;
+}
@replaceableComponent("views.dialogs.WidgetOpenIDPermissionsDialog")
-export default class WidgetOpenIDPermissionsDialog extends React.Component {
- static propTypes = {
- onFinished: PropTypes.func.isRequired,
- widget: PropTypes.objectOf(Widget).isRequired,
- widgetKind: PropTypes.string.isRequired, // WidgetKind from widget-api
- inRoomId: PropTypes.string,
- };
-
- constructor() {
- super();
+export default class WidgetOpenIDPermissionsDialog extends React.Component {
+ constructor(props: IProps) {
+ super(props);
this.state = {
rememberSelection: false,
};
}
- _onAllow = () => {
- this._onPermissionSelection(true);
+ private onAllow = (): void => {
+ this.onPermissionSelection(true);
};
- _onDeny = () => {
- this._onPermissionSelection(false);
+ private onDeny = (): void => {
+ this.onPermissionSelection(false);
};
- _onPermissionSelection(allowed) {
+ private onPermissionSelection(allowed: boolean): void {
if (this.state.rememberSelection) {
- console.log(`Remembering ${this.props.widgetId} as allowed=${allowed} for OpenID`);
+ console.log(`Remembering ${this.props.widget.id} as allowed=${allowed} for OpenID`);
WidgetPermissionStore.instance.setOIDCState(
this.props.widget, this.props.widgetKind, this.props.inRoomId,
@@ -61,14 +65,11 @@ export default class WidgetOpenIDPermissionsDialog extends React.Component {
this.props.onFinished(allowed);
}
- _onRememberSelectionChange = (newVal) => {
+ private onRememberSelectionChange = (newVal: boolean): void => {
this.setState({ rememberSelection: newVal });
};
render() {
- const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
- const DialogButtons = sdk.getComponent('views.elements.DialogButtons');
-
return (
}
/>
From 5bf64c2075e5e09183e89a392cb9478d703fb197 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C5=A0imon=20Brandner?=
Date: Sun, 5 Sep 2021 12:42:18 +0200
Subject: [PATCH 10/34] Convert SetEmailDialog to TS
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Šimon Brandner
---
.../{SetEmailDialog.js => SetEmailDialog.tsx} | 62 ++++++++++---------
1 file changed, 34 insertions(+), 28 deletions(-)
rename src/components/views/dialogs/{SetEmailDialog.js => SetEmailDialog.tsx} (81%)
diff --git a/src/components/views/dialogs/SetEmailDialog.js b/src/components/views/dialogs/SetEmailDialog.tsx
similarity index 81%
rename from src/components/views/dialogs/SetEmailDialog.js
rename to src/components/views/dialogs/SetEmailDialog.tsx
index 3dad3821fb..506399d15d 100644
--- a/src/components/views/dialogs/SetEmailDialog.js
+++ b/src/components/views/dialogs/SetEmailDialog.tsx
@@ -16,13 +16,26 @@ limitations under the License.
*/
import React from 'react';
-import PropTypes from 'prop-types';
-import * as sdk from '../../../index';
import * as Email from '../../../email';
import AddThreepid from '../../../AddThreepid';
import { _t } from '../../../languageHandler';
import Modal from '../../../Modal';
import { replaceableComponent } from "../../../utils/replaceableComponent";
+import Spinner from "../elements/Spinner";
+import ErrorDialog from "./ErrorDialog";
+import QuestionDialog from "./QuestionDialog";
+import BaseDialog from "./BaseDialog";
+import EditableText from "../elements/EditableText";
+
+interface IProps {
+ title: string;
+ onFinished: (confirmed: boolean) => void;
+}
+
+interface IState {
+ emailAddress: string;
+ emailBusy: boolean;
+}
/*
* Prompt the user to set an email address.
@@ -30,26 +43,25 @@ import { replaceableComponent } from "../../../utils/replaceableComponent";
* On success, `onFinished(true)` is called.
*/
@replaceableComponent("views.dialogs.SetEmailDialog")
-export default class SetEmailDialog extends React.Component {
- static propTypes = {
- onFinished: PropTypes.func.isRequired,
- };
+export default class SetEmailDialog extends React.Component {
+ private addThreepid: AddThreepid;
- state = {
- emailAddress: '',
- emailBusy: false,
- };
+ constructor(props: IProps) {
+ super(props);
- onEmailAddressChanged = value => {
+ this.state = {
+ emailAddress: '',
+ emailBusy: false,
+ };
+ }
+
+ private onEmailAddressChanged = (value: string): void => {
this.setState({
emailAddress: value,
});
};
- onSubmit = () => {
- const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
- const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
-
+ private onSubmit = (): void => {
const emailAddress = this.state.emailAddress;
if (!Email.looksValid(emailAddress)) {
Modal.createTrackedDialog('Invalid Email Address', '', ErrorDialog, {
@@ -58,8 +70,8 @@ export default class SetEmailDialog extends React.Component {
});
return;
}
- this._addThreepid = new AddThreepid();
- this._addThreepid.addEmailAddress(emailAddress).then(() => {
+ this.addThreepid = new AddThreepid();
+ this.addThreepid.addEmailAddress(emailAddress).then(() => {
Modal.createTrackedDialog('Verification Pending', '', QuestionDialog, {
title: _t("Verification Pending"),
description: _t(
@@ -80,11 +92,11 @@ export default class SetEmailDialog extends React.Component {
this.setState({ emailBusy: true });
};
- onCancelled = () => {
+ private onCancelled = (): void => {
this.props.onFinished(false);
};
- onEmailDialogFinished = ok => {
+ private onEmailDialogFinished = (ok: boolean): void => {
if (ok) {
this.verifyEmailAddress();
} else {
@@ -92,13 +104,12 @@ export default class SetEmailDialog extends React.Component {
}
};
- verifyEmailAddress() {
- this._addThreepid.checkEmailLinkClicked().then(() => {
+ private verifyEmailAddress(): void {
+ this.addThreepid.checkEmailLinkClicked().then(() => {
this.props.onFinished(true);
}, (err) => {
this.setState({ emailBusy: false });
if (err.errcode == 'M_THREEPID_AUTH_FAILED') {
- const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
const message = _t("Unable to verify email address.") + " " +
_t("Please check your email and click on the link it contains. Once this is done, click continue.");
Modal.createTrackedDialog('Verification Pending', '3pid Auth Failed', QuestionDialog, {
@@ -108,7 +119,6 @@ export default class SetEmailDialog extends React.Component {
onFinished: this.onEmailDialogFinished,
});
} else {
- const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
console.error("Unable to verify email address: " + err);
Modal.createTrackedDialog('Unable to verify email address', '', ErrorDialog, {
title: _t("Unable to verify email address."),
@@ -118,11 +128,7 @@ export default class SetEmailDialog extends React.Component {
});
}
- render() {
- const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
- const Spinner = sdk.getComponent('elements.Spinner');
- const EditableText = sdk.getComponent('elements.EditableText');
-
+ public render(): JSX.Element {
const emailInput = this.state.emailBusy ? :
Date: Sun, 5 Sep 2021 12:57:41 +0200
Subject: [PATCH 11/34] Convert QuestionDialog to TS
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Šimon Brandner
---
.../{QuestionDialog.js => QuestionDialog.tsx} | 43 ++++++++++---------
1 file changed, 23 insertions(+), 20 deletions(-)
rename src/components/views/dialogs/{QuestionDialog.js => QuestionDialog.tsx} (76%)
diff --git a/src/components/views/dialogs/QuestionDialog.js b/src/components/views/dialogs/QuestionDialog.tsx
similarity index 76%
rename from src/components/views/dialogs/QuestionDialog.js
rename to src/components/views/dialogs/QuestionDialog.tsx
index 3d90236b08..df036293f0 100644
--- a/src/components/views/dialogs/QuestionDialog.js
+++ b/src/components/views/dialogs/QuestionDialog.tsx
@@ -16,29 +16,30 @@ limitations under the License.
*/
import React from 'react';
-import PropTypes from 'prop-types';
import classNames from "classnames";
import * as sdk from '../../../index';
import { _t } from '../../../languageHandler';
-export default class QuestionDialog extends React.Component {
- static propTypes = {
- title: PropTypes.string,
- description: PropTypes.node,
- extraButtons: PropTypes.node,
- button: PropTypes.string,
- buttonDisabled: PropTypes.bool,
- danger: PropTypes.bool,
- focus: PropTypes.bool,
- onFinished: PropTypes.func.isRequired,
- headerImage: PropTypes.string,
- quitOnly: PropTypes.bool, // quitOnly doesn't show the cancel button just the quit [x].
- fixedWidth: PropTypes.bool,
- className: PropTypes.string,
- };
+interface IProps {
+ title?: string;
+ description?: React.ReactNode;
+ extraButtons?: React.ReactNode;
+ button?: string;
+ buttonDisabled?: boolean;
+ danger?: boolean;
+ focus?: boolean;
+ onFinished: (confirmed: boolean) => void;
+ headerImage?: string;
+ quitOnly?: boolean; // quitOnly doesn't show the cancel button just the quit [x].
+ fixedWidth?: boolean;
+ className?: string;
+ hasCancelButton?: boolean;
+ cancelButton?: JSX.Element;
+}
- static defaultProps = {
+export default class QuestionDialog extends React.Component {
+ public static defaultProps: Partial = {
title: "",
description: "",
extraButtons: null,
@@ -48,17 +49,19 @@ export default class QuestionDialog extends React.Component {
quitOnly: false,
};
- onOk = () => {
+ private onOk = (): void => {
this.props.onFinished(true);
};
- onCancel = () => {
+ private onCancel = (): void => {
this.props.onFinished(false);
};
- render() {
+ public render(): JSX.Element {
+ // Converting these to imports breaks wrench tests
const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
const DialogButtons = sdk.getComponent('views.elements.DialogButtons');
+
let primaryButtonClass = "";
if (this.props.danger) {
primaryButtonClass = "danger";
From b396383e06c00877f1fc531d957afdd817158f04 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C5=A0imon=20Brandner?=
Date: Sun, 5 Sep 2021 13:09:29 +0200
Subject: [PATCH 12/34] Convert LazyLoadingResyncDialog to TS
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Šimon Brandner
---
...LoadingResyncDialog.js => LazyLoadingResyncDialog.tsx} | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
rename src/components/views/dialogs/{LazyLoadingResyncDialog.js => LazyLoadingResyncDialog.tsx} (89%)
diff --git a/src/components/views/dialogs/LazyLoadingResyncDialog.js b/src/components/views/dialogs/LazyLoadingResyncDialog.tsx
similarity index 89%
rename from src/components/views/dialogs/LazyLoadingResyncDialog.js
rename to src/components/views/dialogs/LazyLoadingResyncDialog.tsx
index a5db15ebbe..c942126d12 100644
--- a/src/components/views/dialogs/LazyLoadingResyncDialog.js
+++ b/src/components/views/dialogs/LazyLoadingResyncDialog.tsx
@@ -20,7 +20,11 @@ import QuestionDialog from './QuestionDialog';
import { _t } from '../../../languageHandler';
import SdkConfig from '../../../SdkConfig';
-export default (props) => {
+interface IProps {
+ onFinished: () => void;
+}
+
+const LazyLoadingResyncDialog: React.FC = (props: IProps) => {
const brand = SdkConfig.get().brand;
const description =
_t(
@@ -38,3 +42,5 @@ export default (props) => {
onFinished={props.onFinished}
/>);
};
+
+export default LazyLoadingResyncDialog;
From b2331d1e21a7d989896560595432974a463a9518 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C5=A0imon=20Brandner?=
Date: Sun, 5 Sep 2021 16:03:08 +0200
Subject: [PATCH 13/34] Convert MessageEditHistoryDialog to TS
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Šimon Brandner
---
...Dialog.js => MessageEditHistoryDialog.tsx} | 55 +++++++++++--------
1 file changed, 33 insertions(+), 22 deletions(-)
rename src/components/views/dialogs/{MessageEditHistoryDialog.js => MessageEditHistoryDialog.tsx} (84%)
diff --git a/src/components/views/dialogs/MessageEditHistoryDialog.js b/src/components/views/dialogs/MessageEditHistoryDialog.tsx
similarity index 84%
rename from src/components/views/dialogs/MessageEditHistoryDialog.js
rename to src/components/views/dialogs/MessageEditHistoryDialog.tsx
index 6fce8aecd4..30c16b03bd 100644
--- a/src/components/views/dialogs/MessageEditHistoryDialog.js
+++ b/src/components/views/dialogs/MessageEditHistoryDialog.tsx
@@ -15,21 +15,37 @@ limitations under the License.
*/
import React from 'react';
-import PropTypes from 'prop-types';
import { MatrixClientPeg } from "../../../MatrixClientPeg";
import { _t } from '../../../languageHandler';
-import * as sdk from "../../../index";
import { wantsDateSeparator } from '../../../DateUtils';
import SettingsStore from '../../../settings/SettingsStore';
import { replaceableComponent } from "../../../utils/replaceableComponent";
+import { MatrixEvent } from "matrix-js-sdk/src/models/event";
+import BaseDialog from "./BaseDialog";
+import ScrollPanel from "../../structures/ScrollPanel";
+import Spinner from "../elements/Spinner";
+import EditHistoryMessage from "../messages/EditHistoryMessage";
+import DateSeparator from "../messages/DateSeparator";
+
+interface IProps {
+ mxEvent: MatrixEvent;
+ onFinished: () => void;
+}
+
+interface IState {
+ originalEvent: MatrixEvent;
+ error: {
+ errcode: string;
+ };
+ events: MatrixEvent[];
+ nextBatch: string;
+ isLoading: boolean;
+ isTwelveHour: boolean;
+}
@replaceableComponent("views.dialogs.MessageEditHistoryDialog")
-export default class MessageEditHistoryDialog extends React.PureComponent {
- static propTypes = {
- mxEvent: PropTypes.object.isRequired,
- };
-
- constructor(props) {
+export default class MessageEditHistoryDialog extends React.PureComponent {
+ constructor(props: IProps) {
super(props);
this.state = {
originalEvent: null,
@@ -41,7 +57,7 @@ export default class MessageEditHistoryDialog extends React.PureComponent {
};
}
- loadMoreEdits = async (backwards) => {
+ private loadMoreEdits = async (backwards?: boolean): Promise => {
if (backwards || (!this.state.nextBatch && !this.state.isLoading)) {
// bail out on backwards as we only paginate in one direction
return false;
@@ -53,7 +69,7 @@ export default class MessageEditHistoryDialog extends React.PureComponent {
let result;
let resolve;
let reject;
- const promise = new Promise((_resolve, _reject) => {resolve = _resolve; reject = _reject;});
+ const promise = new Promise((_resolve, _reject) => {resolve = _resolve; reject = _reject;});
try {
result = await client.relations(
roomId, eventId, "m.replace", "m.room.message", opts);
@@ -67,7 +83,7 @@ export default class MessageEditHistoryDialog extends React.PureComponent {
}
const newEvents = result.events;
- this._locallyRedactEventsIfNeeded(newEvents);
+ this.locallyRedactEventsIfNeeded(newEvents);
this.setState({
originalEvent: this.state.originalEvent || result.originalEvent,
events: this.state.events.concat(newEvents),
@@ -78,9 +94,9 @@ export default class MessageEditHistoryDialog extends React.PureComponent {
resolve(hasMoreResults);
});
return promise;
- }
+ };
- _locallyRedactEventsIfNeeded(newEvents) {
+ private locallyRedactEventsIfNeeded(newEvents: MatrixEvent[]): void {
const roomId = this.props.mxEvent.getRoomId();
const client = MatrixClientPeg.get();
const room = client.getRoom(roomId);
@@ -95,13 +111,11 @@ export default class MessageEditHistoryDialog extends React.PureComponent {
}
}
- componentDidMount() {
+ public componentDidMount(): void {
this.loadMoreEdits();
}
- _renderEdits() {
- const EditHistoryMessage = sdk.getComponent('messages.EditHistoryMessage');
- const DateSeparator = sdk.getComponent('messages.DateSeparator');
+ private renderEdits(): JSX.Element[] {
const nodes = [];
let lastEvent;
let allEvents = this.state.events;
@@ -128,7 +142,7 @@ export default class MessageEditHistoryDialog extends React.PureComponent {
return nodes;
}
- render() {
+ public render(): JSX.Element {
let content;
if (this.state.error) {
const { error } = this.state;
@@ -149,20 +163,17 @@ export default class MessageEditHistoryDialog extends React.PureComponent {
);
}
} else if (this.state.isLoading) {
- const Spinner = sdk.getComponent("elements.Spinner");
content = ;
} else {
- const ScrollPanel = sdk.getComponent("structures.ScrollPanel");
content = (
-
+
);
}
- const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
return (
Date: Sun, 5 Sep 2021 16:09:33 +0200
Subject: [PATCH 14/34] Convert IntegrationsDisabledDialog to TS
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Šimon Brandner
---
...alog.js => IntegrationsDisabledDialog.tsx} | 27 +++++++++----------
1 file changed, 12 insertions(+), 15 deletions(-)
rename src/components/views/dialogs/{IntegrationsDisabledDialog.js => IntegrationsDisabledDialog.tsx} (76%)
diff --git a/src/components/views/dialogs/IntegrationsDisabledDialog.js b/src/components/views/dialogs/IntegrationsDisabledDialog.tsx
similarity index 76%
rename from src/components/views/dialogs/IntegrationsDisabledDialog.js
rename to src/components/views/dialogs/IntegrationsDisabledDialog.tsx
index 6a5b2f08f9..f76ed46577 100644
--- a/src/components/views/dialogs/IntegrationsDisabledDialog.js
+++ b/src/components/views/dialogs/IntegrationsDisabledDialog.tsx
@@ -15,32 +15,29 @@ limitations under the License.
*/
import React from 'react';
-import PropTypes from 'prop-types';
import { _t } from "../../../languageHandler";
-import * as sdk from "../../../index";
import dis from '../../../dispatcher/dispatcher';
import { Action } from "../../../dispatcher/actions";
import { replaceableComponent } from "../../../utils/replaceableComponent";
+import BaseDialog from "./BaseDialog";
+import DialogButtons from "../elements/DialogButtons";
+
+interface IProps {
+ onFinished: () => void;
+}
@replaceableComponent("views.dialogs.IntegrationsDisabledDialog")
-export default class IntegrationsDisabledDialog extends React.Component {
- static propTypes = {
- onFinished: PropTypes.func.isRequired,
- };
-
- _onAcknowledgeClick = () => {
+export default class IntegrationsDisabledDialog extends React.Component {
+ private onAcknowledgeClick = (): void => {
this.props.onFinished();
};
- _onOpenSettingsClick = () => {
+ private onOpenSettingsClick = (): void => {
this.props.onFinished();
dis.fire(Action.ViewUserSettings);
};
- render() {
- const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
- const DialogButtons = sdk.getComponent('views.elements.DialogButtons');
-
+ public render(): JSX.Element {
return (
);
From 9e74477771a5b50de721f9c5a57021c6d6097370 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C5=A0imon=20Brandner?=
Date: Sun, 5 Sep 2021 16:11:10 +0200
Subject: [PATCH 15/34] Convert IntegrationsImpossibleDialog to TS
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Šimon Brandner
---
...log.js => IntegrationsImpossibleDialog.tsx} | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
rename src/components/views/dialogs/{IntegrationsImpossibleDialog.js => IntegrationsImpossibleDialog.tsx} (89%)
diff --git a/src/components/views/dialogs/IntegrationsImpossibleDialog.js b/src/components/views/dialogs/IntegrationsImpossibleDialog.tsx
similarity index 89%
rename from src/components/views/dialogs/IntegrationsImpossibleDialog.js
rename to src/components/views/dialogs/IntegrationsImpossibleDialog.tsx
index 6cfb96a1b4..36dc42b783 100644
--- a/src/components/views/dialogs/IntegrationsImpossibleDialog.js
+++ b/src/components/views/dialogs/IntegrationsImpossibleDialog.tsx
@@ -15,23 +15,23 @@ limitations under the License.
*/
import React from 'react';
-import PropTypes from 'prop-types';
import { _t } from "../../../languageHandler";
import SdkConfig from "../../../SdkConfig";
import * as sdk from "../../../index";
import { replaceableComponent } from "../../../utils/replaceableComponent";
-@replaceableComponent("views.dialogs.IntegrationsImpossibleDialog")
-export default class IntegrationsImpossibleDialog extends React.Component {
- static propTypes = {
- onFinished: PropTypes.func.isRequired,
- };
+interface IProps {
+ onFinished: () => void;
- _onAcknowledgeClick = () => {
+}
+
+@replaceableComponent("views.dialogs.IntegrationsImpossibleDialog")
+export default class IntegrationsImpossibleDialog extends React.Component {
+ private onAcknowledgeClick = (): void => {
this.props.onFinished();
};
- render() {
+ public render(): JSX.Element {
const brand = SdkConfig.get().brand;
const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
const DialogButtons = sdk.getComponent('views.elements.DialogButtons');
@@ -54,7 +54,7 @@ export default class IntegrationsImpossibleDialog extends React.Component {
From aba966034e5dc173637385e9354ff0aec298989f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C5=A0imon=20Brandner?=
Date: Sun, 5 Sep 2021 16:17:44 +0200
Subject: [PATCH 16/34] Convert LazyLoadingDisabledDialog to TS
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Šimon Brandner
---
...ngDisabledDialog.js => LazyLoadingDisabledDialog.tsx} | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
rename src/components/views/dialogs/{LazyLoadingDisabledDialog.js => LazyLoadingDisabledDialog.tsx} (90%)
diff --git a/src/components/views/dialogs/LazyLoadingDisabledDialog.js b/src/components/views/dialogs/LazyLoadingDisabledDialog.tsx
similarity index 90%
rename from src/components/views/dialogs/LazyLoadingDisabledDialog.js
rename to src/components/views/dialogs/LazyLoadingDisabledDialog.tsx
index e43cb28a22..32aaf9c531 100644
--- a/src/components/views/dialogs/LazyLoadingDisabledDialog.js
+++ b/src/components/views/dialogs/LazyLoadingDisabledDialog.tsx
@@ -20,7 +20,12 @@ import QuestionDialog from './QuestionDialog';
import { _t } from '../../../languageHandler';
import SdkConfig from '../../../SdkConfig';
-export default (props) => {
+interface IProps {
+ onFinished: () => void;
+ host: string;
+}
+
+const LazyLoadingDisabledDialog: React.FC = (props: IProps) => {
const brand = SdkConfig.get().brand;
const description1 = _t(
"You've previously used %(brand)s on %(host)s with lazy loading of members enabled. " +
@@ -49,3 +54,5 @@ export default (props) => {
onFinished={props.onFinished}
/>);
};
+
+export default LazyLoadingDisabledDialog;
From e80939d3e25a4cde9d8938ecefafd951562dab01 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C5=A0imon=20Brandner?=
Date: Sun, 5 Sep 2021 16:27:46 +0200
Subject: [PATCH 17/34] Convert KeySignatureUploadFailedDialog to TS
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Šimon Brandner
---
....js => KeySignatureUploadFailedDialog.tsx} | 25 +++++++++++++------
1 file changed, 18 insertions(+), 7 deletions(-)
rename src/components/views/dialogs/{KeySignatureUploadFailedDialog.js => KeySignatureUploadFailedDialog.tsx} (88%)
diff --git a/src/components/views/dialogs/KeySignatureUploadFailedDialog.js b/src/components/views/dialogs/KeySignatureUploadFailedDialog.tsx
similarity index 88%
rename from src/components/views/dialogs/KeySignatureUploadFailedDialog.js
rename to src/components/views/dialogs/KeySignatureUploadFailedDialog.tsx
index 6b36c19977..20841c46f4 100644
--- a/src/components/views/dialogs/KeySignatureUploadFailedDialog.js
+++ b/src/components/views/dialogs/KeySignatureUploadFailedDialog.tsx
@@ -15,20 +15,29 @@ limitations under the License.
*/
import React, { useState, useCallback, useRef } from 'react';
-import * as sdk from '../../../index';
import { _t } from '../../../languageHandler';
import SdkConfig from '../../../SdkConfig';
+import BaseDialog from "./BaseDialog";
+import DialogButtons from "../elements/DialogButtons";
+import Spinner from "../elements/Spinner";
-export default function KeySignatureUploadFailedDialog({
+interface IProps {
+ failures: Record>;
+ source: string;
+ continuation: () => void;
+ onFinished: () => void;
+}
+
+const KeySignatureUploadFailedDialog: React.FC = ({
failures,
source,
continuation,
onFinished,
-}) {
+}) => {
const RETRIES = 2;
- const BaseDialog = sdk.getComponent('dialogs.BaseDialog');
- const DialogButtons = sdk.getComponent('views.elements.DialogButtons');
- const Spinner = sdk.getComponent('elements.Spinner');
const [retry, setRetry] = useState(RETRIES);
const [cancelled, setCancelled] = useState(false);
const [retrying, setRetrying] = useState(false);
@@ -107,4 +116,6 @@ export default function KeySignatureUploadFailedDialog({
{ body }
);
-}
+};
+
+export default KeySignatureUploadFailedDialog;
From 4ca2ab11fbac3fdceac6ac8a36c07be73c7b3a7c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C5=A0imon=20Brandner?=
Date: Sun, 5 Sep 2021 16:36:36 +0200
Subject: [PATCH 18/34] Convert ManualDeviceKeyVerificationDialog to TS
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Šimon Brandner
---
... => ManualDeviceKeyVerificationDialog.tsx} | 32 ++++++++-----------
1 file changed, 13 insertions(+), 19 deletions(-)
rename src/components/views/dialogs/{ManualDeviceKeyVerificationDialog.js => ManualDeviceKeyVerificationDialog.tsx} (84%)
diff --git a/src/components/views/dialogs/ManualDeviceKeyVerificationDialog.js b/src/components/views/dialogs/ManualDeviceKeyVerificationDialog.tsx
similarity index 84%
rename from src/components/views/dialogs/ManualDeviceKeyVerificationDialog.js
rename to src/components/views/dialogs/ManualDeviceKeyVerificationDialog.tsx
index 4387108fac..a4c989d7b5 100644
--- a/src/components/views/dialogs/ManualDeviceKeyVerificationDialog.js
+++ b/src/components/views/dialogs/ManualDeviceKeyVerificationDialog.tsx
@@ -19,37 +19,31 @@ limitations under the License.
*/
import React from 'react';
-import PropTypes from 'prop-types';
import { MatrixClientPeg } from '../../../MatrixClientPeg';
-import * as sdk from '../../../index';
import * as FormattingUtils from '../../../utils/FormattingUtils';
import { _t } from '../../../languageHandler';
import { replaceableComponent } from "../../../utils/replaceableComponent";
+import QuestionDialog from "./QuestionDialog";
+import { DeviceInfo } from "matrix-js-sdk/src/crypto/deviceinfo";
+
+interface IProps {
+ userId: string;
+ device: DeviceInfo;
+ onFinished: (confirmed: boolean) => void;
+}
@replaceableComponent("views.dialogs.ManualDeviceKeyVerificationDialog")
-export default class ManualDeviceKeyVerificationDialog extends React.Component {
- static propTypes = {
- userId: PropTypes.string.isRequired,
- device: PropTypes.object.isRequired,
- onFinished: PropTypes.func.isRequired,
- };
-
- _onCancelClick = () => {
- this.props.onFinished(false);
- }
-
- _onLegacyFinished = (confirm) => {
+export default class ManualDeviceKeyVerificationDialog extends React.Component {
+ private onLegacyFinished = (confirm: boolean): void => {
if (confirm) {
MatrixClientPeg.get().setDeviceVerified(
this.props.userId, this.props.device.deviceId, true,
);
}
this.props.onFinished(confirm);
- }
-
- render() {
- const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
+ };
+ public render(): JSX.Element {
let text;
if (MatrixClientPeg.get().getUserId() === this.props.userId) {
text = _t("Confirm by comparing the following with the User Settings in your other session:");
@@ -81,7 +75,7 @@ export default class ManualDeviceKeyVerificationDialog extends React.Component {
title={_t("Verify session")}
description={body}
button={_t("Verify session")}
- onFinished={this._onLegacyFinished}
+ onFinished={this.onLegacyFinished}
/>
);
}
From 0285bb555fa2a9530b42ec4221d1ebff851957f1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C5=A0imon=20Brandner?=
Date: Sun, 5 Sep 2021 16:40:46 +0200
Subject: [PATCH 19/34] Convert SessionRestoreErrorDialog to TS
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Šimon Brandner
---
...ialog.js => SessionRestoreErrorDialog.tsx} | 38 +++++++++----------
1 file changed, 18 insertions(+), 20 deletions(-)
rename src/components/views/dialogs/{SessionRestoreErrorDialog.js => SessionRestoreErrorDialog.tsx} (80%)
diff --git a/src/components/views/dialogs/SessionRestoreErrorDialog.js b/src/components/views/dialogs/SessionRestoreErrorDialog.tsx
similarity index 80%
rename from src/components/views/dialogs/SessionRestoreErrorDialog.js
rename to src/components/views/dialogs/SessionRestoreErrorDialog.tsx
index eeeadbbfe5..752b023f0b 100644
--- a/src/components/views/dialogs/SessionRestoreErrorDialog.js
+++ b/src/components/views/dialogs/SessionRestoreErrorDialog.tsx
@@ -17,27 +17,27 @@ limitations under the License.
*/
import React from 'react';
-import PropTypes from 'prop-types';
-import * as sdk from '../../../index';
import SdkConfig from '../../../SdkConfig';
import Modal from '../../../Modal';
import { _t } from '../../../languageHandler';
import { replaceableComponent } from "../../../utils/replaceableComponent";
+import QuestionDialog from "./QuestionDialog";
+import BugReportDialog from "./BugReportDialog";
+import BaseDialog from "./BaseDialog";
+import DialogButtons from "../elements/DialogButtons";
+
+interface IProps {
+ error: string;
+ onFinished: () => void;
+}
@replaceableComponent("views.dialogs.SessionRestoreErrorDialog")
-export default class SessionRestoreErrorDialog extends React.Component {
- static propTypes = {
- error: PropTypes.string.isRequired,
- onFinished: PropTypes.func.isRequired,
- };
-
- _sendBugReport = () => {
- const BugReportDialog = sdk.getComponent("dialogs.BugReportDialog");
+export default class SessionRestoreErrorDialog extends React.Component {
+ private sendBugReport = (): void => {
Modal.createTrackedDialog('Session Restore Error', 'Send Bug Report Dialog', BugReportDialog, {});
};
- _onClearStorageClick = () => {
- const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
+ private onClearStorageClick = (): void => {
Modal.createTrackedDialog('Session Restore Confirm Logout', '', QuestionDialog, {
title: _t("Sign out"),
description:
@@ -48,19 +48,17 @@ export default class SessionRestoreErrorDialog extends React.Component {
});
};
- _onRefreshClick = () => {
+ private onRefreshClick = (): void => {
// Is this likely to help? Probably not, but giving only one button
// that clears your storage seems awful.
- window.location.reload(true);
+ window.location.reload();
};
- render() {
+ public render(): JSX.Element {
const brand = SdkConfig.get().brand;
- const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
- const DialogButtons = sdk.getComponent('views.elements.DialogButtons');
const clearStorageButton = (
-