): void => {
this.setState({
- shouldErase: ev.target.checked,
+ shouldErase: ev.currentTarget.checked,
// Disable the auth form because we're going to have to reinitialize the auth
// information. We do this because we can't modify the parameters in the UIA
@@ -123,14 +139,14 @@ export default class DeactivateAccountDialog extends React.Component {
});
// As mentioned above, set up for auth again to get updated UIA session info
- this._initAuth(/* shouldErase= */ev.target.checked);
+ this.initAuth(/* shouldErase= */ev.currentTarget.checked);
};
- _onCancel() {
+ private onCancel(): void {
this.props.onFinished(false);
}
- _initAuth(shouldErase) {
+ private initAuth(shouldErase: boolean): void {
MatrixClientPeg.get().deactivateAccount(null, shouldErase).then(r => {
// If we got here, oops. The server didn't require any auth.
// Our application lifecycle will catch the error and do the logout bits.
@@ -148,7 +164,7 @@ export default class DeactivateAccountDialog extends React.Component {
});
}
- render() {
+ public render() {
const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
let error = null;
@@ -166,9 +182,9 @@ export default class DeactivateAccountDialog extends React.Component {
@@ -214,7 +230,7 @@ export default class DeactivateAccountDialog extends React.Component {
{_t(
"Please forget all messages I have sent when my account is deactivated " +
@@ -235,7 +251,3 @@ export default class DeactivateAccountDialog extends React.Component {
);
}
}
-
-DeactivateAccountDialog.propTypes = {
- onFinished: PropTypes.func.isRequired,
-};
From a030c1270a844c40a8120cd41bd209ac4707c6ce Mon Sep 17 00:00:00 2001
From: Germain Souquet
Date: Mon, 14 Jun 2021 21:55:47 +0100
Subject: [PATCH 15/46] Migrate ErrorDialog to TypeScript
---
.../{ErrorDialog.js => ErrorDialog.tsx} | 34 +++++++++----------
1 file changed, 17 insertions(+), 17 deletions(-)
rename src/components/views/dialogs/{ErrorDialog.js => ErrorDialog.tsx} (81%)
diff --git a/src/components/views/dialogs/ErrorDialog.js b/src/components/views/dialogs/ErrorDialog.tsx
similarity index 81%
rename from src/components/views/dialogs/ErrorDialog.js
rename to src/components/views/dialogs/ErrorDialog.tsx
index 5197c68b5a..d50ec7bf36 100644
--- a/src/components/views/dialogs/ErrorDialog.js
+++ b/src/components/views/dialogs/ErrorDialog.tsx
@@ -26,37 +26,37 @@ limitations under the License.
*/
import React from 'react';
-import PropTypes from 'prop-types';
import * as sdk from '../../../index';
import { _t } from '../../../languageHandler';
import {replaceableComponent} from "../../../utils/replaceableComponent";
-@replaceableComponent("views.dialogs.ErrorDialog")
-export default class ErrorDialog extends React.Component {
- static propTypes = {
- title: PropTypes.string,
- description: PropTypes.oneOfType([
- PropTypes.element,
- PropTypes.string,
- ]),
- button: PropTypes.string,
- focus: PropTypes.bool,
- onFinished: PropTypes.func.isRequired,
- headerImage: PropTypes.string,
- };
+interface IProps {
+ onFinished: (success: boolean) => void;
+ title?: string;
+ description?: React.ReactNode;
+ button?: string;
+ focus?: boolean;
+ headerImage?: string;
+}
- static defaultProps = {
+interface IState {
+ onFinished: (success: boolean) => void;
+}
+
+@replaceableComponent("views.dialogs.ErrorDialog")
+export default class ErrorDialog extends React.Component {
+ public static defaultProps = {
focus: true,
title: null,
description: null,
button: null,
};
- onClick = () => {
+ private onClick = () => {
this.props.onFinished(true);
};
- render() {
+ public render() {
const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
return (
Date: Mon, 14 Jun 2021 23:42:36 +0100
Subject: [PATCH 16/46] Migrate UserSettingsDialog to TypeScript
---
src/components/structures/SpaceRoomView.tsx | 4 +-
src/components/structures/UserMenu.tsx | 6 +-
.../views/dialogs/BetaFeedbackDialog.tsx | 4 +-
...ttingsDialog.js => UserSettingsDialog.tsx} | 75 ++++++++++---------
src/components/views/right_panel/UserInfo.tsx | 4 +-
.../tabs/user/HelpUserSettingsTab.tsx | 2 +-
.../views/spaces/SpaceCreateMenu.tsx | 4 +-
src/toasts/UnverifiedSessionToast.ts | 4 +-
8 files changed, 55 insertions(+), 48 deletions(-)
rename src/components/views/dialogs/{UserSettingsDialog.js => UserSettingsDialog.tsx} (76%)
diff --git a/src/components/structures/SpaceRoomView.tsx b/src/components/structures/SpaceRoomView.tsx
index 276f4ae6ca..907a0e8873 100644
--- a/src/components/structures/SpaceRoomView.tsx
+++ b/src/components/structures/SpaceRoomView.tsx
@@ -59,7 +59,7 @@ import IconizedContextMenu, {
} from "../views/context_menus/IconizedContextMenu";
import AccessibleTooltipButton from "../views/elements/AccessibleTooltipButton";
import {BetaPill} from "../views/beta/BetaCard";
-import {USER_LABS_TAB} from "../views/dialogs/UserSettingsDialog";
+import { USER_TAB } from "../views/dialogs/UserSettingsDialog";
import SettingsStore from "../../settings/SettingsStore";
import dis from "../../dispatcher/dispatcher";
import Modal from "../../Modal";
@@ -165,7 +165,7 @@ const SpaceInfo = ({ space }) => {
const onBetaClick = () => {
defaultDispatcher.dispatch({
action: Action.ViewUserSettings,
- initialTabId: USER_LABS_TAB,
+ initialTabId: USER_TAB.LABS,
});
};
diff --git a/src/components/structures/UserMenu.tsx b/src/components/structures/UserMenu.tsx
index 6a449cf1a2..d942c71c4a 100644
--- a/src/components/structures/UserMenu.tsx
+++ b/src/components/structures/UserMenu.tsx
@@ -26,7 +26,7 @@ import { ActionPayload } from "../../dispatcher/payloads";
import { Action } from "../../dispatcher/actions";
import { _t } from "../../languageHandler";
import { ContextMenuButton } from "./ContextMenu";
-import { USER_NOTIFICATIONS_TAB, USER_SECURITY_TAB } from "../views/dialogs/UserSettingsDialog";
+import { USER_TAB } from "../views/dialogs/UserSettingsDialog";
import { OpenToTabPayload } from "../../dispatcher/payloads/OpenToTabPayload";
import FeedbackDialog from "../views/dialogs/FeedbackDialog";
import Modal from "../../Modal";
@@ -408,12 +408,12 @@ export default class UserMenu extends React.Component {
this.onSettingsOpen(e, USER_NOTIFICATIONS_TAB)}
+ onClick={(e) => this.onSettingsOpen(e, USER_TAB.NOTIFICATIONS)}
/>
this.onSettingsOpen(e, USER_SECURITY_TAB)}
+ onClick={(e) => this.onSettingsOpen(e, USER_TAB.SECURITY)}
/>
= ({featureId, onFinished}) => {
onFinished(false);
defaultDispatcher.dispatch({
action: Action.ViewUserSettings,
- initialTabId: USER_LABS_TAB,
+ initialTabId: USER_TAB.LABS,
});
}}>
{ _t("To leave the beta, visit your settings.") }
diff --git a/src/components/views/dialogs/UserSettingsDialog.js b/src/components/views/dialogs/UserSettingsDialog.tsx
similarity index 76%
rename from src/components/views/dialogs/UserSettingsDialog.js
rename to src/components/views/dialogs/UserSettingsDialog.tsx
index fe29b85aea..921aece7f4 100644
--- a/src/components/views/dialogs/UserSettingsDialog.js
+++ b/src/components/views/dialogs/UserSettingsDialog.tsx
@@ -16,7 +16,6 @@ limitations under the License.
*/
import React from 'react';
-import PropTypes from 'prop-types';
import TabbedView, {Tab} from "../../structures/TabbedView";
import {_t, _td} from "../../../languageHandler";
import GeneralUserSettingsTab from "../settings/tabs/user/GeneralUserSettingsTab";
@@ -35,41 +34,49 @@ import MjolnirUserSettingsTab from "../settings/tabs/user/MjolnirUserSettingsTab
import {UIFeature} from "../../../settings/UIFeature";
import {replaceableComponent} from "../../../utils/replaceableComponent";
-export const USER_GENERAL_TAB = "USER_GENERAL_TAB";
-export const USER_APPEARANCE_TAB = "USER_APPEARANCE_TAB";
-export const USER_FLAIR_TAB = "USER_FLAIR_TAB";
-export const USER_NOTIFICATIONS_TAB = "USER_NOTIFICATIONS_TAB";
-export const USER_PREFERENCES_TAB = "USER_PREFERENCES_TAB";
-export const USER_VOICE_TAB = "USER_VOICE_TAB";
-export const USER_SECURITY_TAB = "USER_SECURITY_TAB";
-export const USER_LABS_TAB = "USER_LABS_TAB";
-export const USER_MJOLNIR_TAB = "USER_MJOLNIR_TAB";
-export const USER_HELP_TAB = "USER_HELP_TAB";
+export enum USER_TAB {
+ GENERAL = "USER_GENERAL_TAB",
+ APPEARANCE = "USER_APPEARANCE_TAB",
+ FLAIR = "USER_FLAIR_TAB",
+ NOTIFICATIONS = "USER_NOTIFICATIONS_TAB",
+ PREFERENCES = "USER_PREFERENCES_TAB",
+ VOICE = "USER_VOICE_TAB",
+ SECURITY = "USER_SECURITY_TAB",
+ LABS = "USER_LABS_TAB",
+ MJOLNIR = "USER_MJOLNIR_TAB",
+ HELP = "USER_HELP_TAB",
+}
+
+interface IProps {
+ onFinished: (success: boolean) => void;
+ initialTabId?: string;
+}
+
+interface IState {
+ mjolnirEnabled: boolean;
+}
@replaceableComponent("views.dialogs.UserSettingsDialog")
-export default class UserSettingsDialog extends React.Component {
- static propTypes = {
- onFinished: PropTypes.func.isRequired,
- initialTabId: PropTypes.string,
- };
+export default class UserSettingsDialog extends React.Component {
+ private mjolnirWatcher: string;
- constructor() {
- super();
+ constructor(props) {
+ super(props);
this.state = {
mjolnirEnabled: SettingsStore.getValue("feature_mjolnir"),
};
}
- componentDidMount(): void {
- this._mjolnirWatcher = SettingsStore.watchSetting("feature_mjolnir", null, this._mjolnirChanged.bind(this));
+ public componentDidMount(): void {
+ this.mjolnirWatcher = SettingsStore.watchSetting("feature_mjolnir", null, this.mjolnirChanged);
}
- componentWillUnmount(): void {
- SettingsStore.unwatchSetting(this._mjolnirWatcher);
+ public componentWillUnmount(): void {
+ SettingsStore.unwatchSetting(this.mjolnirWatcher);
}
- _mjolnirChanged(settingName, roomId, atLevel, newValue) {
+ private mjolnirChanged = (settingName, roomId, atLevel, newValue: boolean) => {
// We can cheat because we know what levels a feature is tracked at, and how it is tracked
this.setState({mjolnirEnabled: newValue});
}
@@ -78,33 +85,33 @@ export default class UserSettingsDialog extends React.Component {
const tabs = [];
tabs.push(new Tab(
- USER_GENERAL_TAB,
+ USER_TAB.GENERAL,
_td("General"),
"mx_UserSettingsDialog_settingsIcon",
,
));
tabs.push(new Tab(
- USER_APPEARANCE_TAB,
+ USER_TAB.APPEARANCE,
_td("Appearance"),
"mx_UserSettingsDialog_appearanceIcon",
,
));
if (SettingsStore.getValue(UIFeature.Flair)) {
tabs.push(new Tab(
- USER_FLAIR_TAB,
+ USER_TAB.FLAIR,
_td("Flair"),
"mx_UserSettingsDialog_flairIcon",
,
));
}
tabs.push(new Tab(
- USER_NOTIFICATIONS_TAB,
+ USER_TAB.NOTIFICATIONS,
_td("Notifications"),
"mx_UserSettingsDialog_bellIcon",
,
));
tabs.push(new Tab(
- USER_PREFERENCES_TAB,
+ USER_TAB.PREFERENCES,
_td("Preferences"),
"mx_UserSettingsDialog_preferencesIcon",
,
@@ -112,7 +119,7 @@ export default class UserSettingsDialog extends React.Component {
if (SettingsStore.getValue(UIFeature.Voip)) {
tabs.push(new Tab(
- USER_VOICE_TAB,
+ USER_TAB.VOICE,
_td("Voice & Video"),
"mx_UserSettingsDialog_voiceIcon",
,
@@ -120,7 +127,7 @@ export default class UserSettingsDialog extends React.Component {
}
tabs.push(new Tab(
- USER_SECURITY_TAB,
+ USER_TAB.SECURITY,
_td("Security & Privacy"),
"mx_UserSettingsDialog_securityIcon",
,
@@ -130,7 +137,7 @@ export default class UserSettingsDialog extends React.Component {
|| SettingsStore.getFeatureSettingNames().some(k => SettingsStore.getBetaInfo(k))
) {
tabs.push(new Tab(
- USER_LABS_TAB,
+ USER_TAB.LABS,
_td("Labs"),
"mx_UserSettingsDialog_labsIcon",
,
@@ -138,17 +145,17 @@ export default class UserSettingsDialog extends React.Component {
}
if (this.state.mjolnirEnabled) {
tabs.push(new Tab(
- USER_MJOLNIR_TAB,
+ USER_TAB.MJOLNIR,
_td("Ignored users"),
"mx_UserSettingsDialog_mjolnirIcon",
,
));
}
tabs.push(new Tab(
- USER_HELP_TAB,
+ USER_TAB.HELP,
_td("Help & About"),
"mx_UserSettingsDialog_helpIcon",
- ,
+ this.props.onFinished(true)} />,
));
return tabs;
diff --git a/src/components/views/right_panel/UserInfo.tsx b/src/components/views/right_panel/UserInfo.tsx
index d6c97f9cf2..ce5a96c8a3 100644
--- a/src/components/views/right_panel/UserInfo.tsx
+++ b/src/components/views/right_panel/UserInfo.tsx
@@ -48,7 +48,7 @@ import EncryptionPanel from "./EncryptionPanel";
import { useAsyncMemo } from '../../../hooks/useAsyncMemo';
import { legacyVerifyUser, verifyDevice, verifyUser } from '../../../verification';
import { Action } from "../../../dispatcher/actions";
-import { USER_SECURITY_TAB } from "../dialogs/UserSettingsDialog";
+import { USER_TAB } from "../dialogs/UserSettingsDialog";
import { useIsEncrypted } from "../../../hooks/useIsEncrypted";
import BaseCard from "./BaseCard";
import { E2EStatus } from "../../../utils/ShieldUtils";
@@ -1381,7 +1381,7 @@ const BasicUserInfo: React.FC<{
{
dis.dispatch({
action: Action.ViewUserSettings,
- initialTabId: USER_SECURITY_TAB,
+ initialTabId: USER_TAB.SECURITY,
});
}}>
{ _t("Edit devices") }
diff --git a/src/components/views/settings/tabs/user/HelpUserSettingsTab.tsx b/src/components/views/settings/tabs/user/HelpUserSettingsTab.tsx
index 3fa0be478c..beff033001 100644
--- a/src/components/views/settings/tabs/user/HelpUserSettingsTab.tsx
+++ b/src/components/views/settings/tabs/user/HelpUserSettingsTab.tsx
@@ -32,7 +32,7 @@ import * as ContextMenu from "../../../../structures/ContextMenu";
import { toRightOf } from "../../../../structures/ContextMenu";
interface IProps {
- closeSettingsFn: () => {};
+ closeSettingsFn: () => void;
}
interface IState {
diff --git a/src/components/views/spaces/SpaceCreateMenu.tsx b/src/components/views/spaces/SpaceCreateMenu.tsx
index 0ebf511018..29be03eaa4 100644
--- a/src/components/views/spaces/SpaceCreateMenu.tsx
+++ b/src/components/views/spaces/SpaceCreateMenu.tsx
@@ -29,7 +29,7 @@ import AccessibleButton from "../elements/AccessibleButton";
import {BetaPill} from "../beta/BetaCard";
import defaultDispatcher from "../../../dispatcher/dispatcher";
import {Action} from "../../../dispatcher/actions";
-import {USER_LABS_TAB} from "../dialogs/UserSettingsDialog";
+import { USER_TAB } from "../dialogs/UserSettingsDialog";
import Field from "../elements/Field";
import withValidation from "../elements/Validation";
import {SpaceFeedbackPrompt} from "../../structures/SpaceRoomView";
@@ -222,7 +222,7 @@ const SpaceCreateMenu = ({ onFinished }) => {
onFinished();
defaultDispatcher.dispatch({
action: Action.ViewUserSettings,
- initialTabId: USER_LABS_TAB,
+ initialTabId: USER_TAB.LABS,
});
}} />
{ body }
diff --git a/src/toasts/UnverifiedSessionToast.ts b/src/toasts/UnverifiedSessionToast.ts
index c856d39d1f..8e3fa7c8a7 100644
--- a/src/toasts/UnverifiedSessionToast.ts
+++ b/src/toasts/UnverifiedSessionToast.ts
@@ -21,7 +21,7 @@ import DeviceListener from '../DeviceListener';
import ToastStore from "../stores/ToastStore";
import GenericToast from "../components/views/toasts/GenericToast";
import { Action } from "../dispatcher/actions";
-import { USER_SECURITY_TAB } from "../components/views/dialogs/UserSettingsDialog";
+import { USER_TAB } from "../components/views/dialogs/UserSettingsDialog";
function toastKey(deviceId: string) {
return "unverified_session_" + deviceId;
@@ -34,7 +34,7 @@ export const showToast = async (deviceId: string) => {
DeviceListener.sharedInstance().dismissUnverifiedSessions([deviceId]);
dis.dispatch({
action: Action.ViewUserSettings,
- initialTabId: USER_SECURITY_TAB,
+ initialTabId: USER_TAB.SECURITY,
});
};
From 75151b7a6c8bc690fe38c145ab77d27000438ad5 Mon Sep 17 00:00:00 2001
From: Germain Souquet
Date: Mon, 14 Jun 2021 23:50:41 +0100
Subject: [PATCH 17/46] Migrate TermsDialog to TypeScript
---
.../{TermsDialog.js => TermsDialog.tsx} | 100 ++++++++++--------
1 file changed, 53 insertions(+), 47 deletions(-)
rename src/components/views/dialogs/{TermsDialog.js => TermsDialog.tsx} (72%)
diff --git a/src/components/views/dialogs/TermsDialog.js b/src/components/views/dialogs/TermsDialog.tsx
similarity index 72%
rename from src/components/views/dialogs/TermsDialog.js
rename to src/components/views/dialogs/TermsDialog.tsx
index e8625ec6cb..ace5316323 100644
--- a/src/components/views/dialogs/TermsDialog.js
+++ b/src/components/views/dialogs/TermsDialog.tsx
@@ -16,22 +16,21 @@ limitations under the License.
import url from 'url';
import React from 'react';
-import PropTypes from 'prop-types';
import * as sdk from '../../../index';
import { _t, pickBestLanguage } from '../../../languageHandler';
import {replaceableComponent} from "../../../utils/replaceableComponent";
-import {SERVICE_TYPES} from "matrix-js-sdk/src/service-types";
+import { SERVICE_TYPES } from "matrix-js-sdk/src/service-types";
-class TermsCheckbox extends React.PureComponent {
- static propTypes = {
- onChange: PropTypes.func.isRequired,
- url: PropTypes.string.isRequired,
- checked: PropTypes.bool.isRequired,
- }
+interface ITermsCheckboxProps {
+ onChange: (url: string, checked: boolean) => void;
+ url: string;
+ checked: boolean;
+}
- onChange = (ev) => {
- this.props.onChange(this.props.url, ev.target.checked);
+class TermsCheckbox extends React.PureComponent {
+ private onChange = (ev: React.FormEvent): void => {
+ this.props.onChange(this.props.url, ev.currentTarget.checked);
}
render() {
@@ -42,30 +41,34 @@ class TermsCheckbox extends React.PureComponent {
}
}
+interface ITermsDialogProps {
+ /**
+ * Array of [Service, policies] pairs, where policies is the response from the
+ * /terms endpoint for that service
+ */
+ policiesAndServicePairs: any[],
+
+ /**
+ * urls that the user has already agreed to
+ */
+ agreedUrls?: string[],
+
+ /**
+ * Called with:
+ * * success {bool} True if the user accepted any douments, false if cancelled
+ * * agreedUrls {string[]} List of agreed URLs
+ */
+ onFinished: (success: boolean, agreedUrls?: string[]) => void,
+}
+
+interface IState {
+ agreedUrls: any;
+}
+
@replaceableComponent("views.dialogs.TermsDialog")
-export default class TermsDialog extends React.PureComponent {
- static propTypes = {
- /**
- * Array of [Service, policies] pairs, where policies is the response from the
- * /terms endpoint for that service
- */
- policiesAndServicePairs: PropTypes.array.isRequired,
-
- /**
- * urls that the user has already agreed to
- */
- agreedUrls: PropTypes.arrayOf(PropTypes.string),
-
- /**
- * Called with:
- * * success {bool} True if the user accepted any douments, false if cancelled
- * * agreedUrls {string[]} List of agreed URLs
- */
- onFinished: PropTypes.func.isRequired,
- }
-
+export default class TermsDialog extends React.PureComponent {
constructor(props) {
- super();
+ super(props);
this.state = {
// url -> boolean
agreedUrls: {},
@@ -75,15 +78,15 @@ export default class TermsDialog extends React.PureComponent {
}
}
- _onCancelClick = () => {
+ private onCancelClick = (): void => {
this.props.onFinished(false);
}
- _onNextClick = () => {
+ private onNextClick = (): void => {
this.props.onFinished(true, Object.keys(this.state.agreedUrls).filter((url) => this.state.agreedUrls[url]));
}
- _nameForServiceType(serviceType, host) {
+ private nameForServiceType(serviceType: SERVICE_TYPES, host: string): JSX.Element {
switch (serviceType) {
case SERVICE_TYPES.IS:
return {_t("Identity Server")}
({host})
;
@@ -92,7 +95,7 @@ export default class TermsDialog extends React.PureComponent {
}
}
- _summaryForServiceType(serviceType) {
+ private summaryForServiceType(serviceType: SERVICE_TYPES): JSX.Element {
switch (serviceType) {
case SERVICE_TYPES.IS:
return
@@ -107,13 +110,13 @@ export default class TermsDialog extends React.PureComponent {
}
}
- _onTermsCheckboxChange = (url, checked) => {
+ private onTermsCheckboxChange = (url: string, checked: boolean) => {
this.setState({
agreedUrls: Object.assign({}, this.state.agreedUrls, { [url]: checked }),
});
}
- render() {
+ public render() {
const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
const DialogButtons = sdk.getComponent('views.elements.DialogButtons');
@@ -128,8 +131,8 @@ export default class TermsDialog extends React.PureComponent {
let serviceName;
let summary;
if (i === 0) {
- serviceName = this._nameForServiceType(policiesAndService.service.serviceType, parsedBaseUrl.host);
- summary = this._summaryForServiceType(
+ serviceName = this.nameForServiceType(policiesAndService.service.serviceType, parsedBaseUrl.host);
+ summary = this.summaryForServiceType(
policiesAndService.service.serviceType,
);
}
@@ -137,12 +140,15 @@ export default class TermsDialog extends React.PureComponent {
rows.push(
{serviceName} |
{summary} |
- {termDoc[termsLang].name}
-
- |
+
+ {termDoc[termsLang].name}
+
+
+
+ |
|
);
@@ -176,7 +182,7 @@ export default class TermsDialog extends React.PureComponent {
return (
From b2f20e052df53cd1a992ab0621a9d723f3891336 Mon Sep 17 00:00:00 2001
From: Germain Souquet
Date: Mon, 14 Jun 2021 23:51:38 +0100
Subject: [PATCH 18/46] remove unused import
---
src/components/views/dialogs/ConfirmWipeDeviceDialog.tsx | 1 -
1 file changed, 1 deletion(-)
diff --git a/src/components/views/dialogs/ConfirmWipeDeviceDialog.tsx b/src/components/views/dialogs/ConfirmWipeDeviceDialog.tsx
index 6911c845fb..d95b1fe358 100644
--- a/src/components/views/dialogs/ConfirmWipeDeviceDialog.tsx
+++ b/src/components/views/dialogs/ConfirmWipeDeviceDialog.tsx
@@ -15,7 +15,6 @@ limitations under the License.
*/
import React from 'react';
-import PropTypes from 'prop-types';
import {_t} from "../../../languageHandler";
import * as sdk from "../../../index";
import {replaceableComponent} from "../../../utils/replaceableComponent";
From 07bdaeaf704b02569edfc3c6a33de75923bdbee2 Mon Sep 17 00:00:00 2001
From: Germain Souquet
Date: Mon, 14 Jun 2021 23:55:14 +0100
Subject: [PATCH 19/46] Fix mjolnir private chat enum
---
src/mjolnir/Mjolnir.ts | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/mjolnir/Mjolnir.ts b/src/mjolnir/Mjolnir.ts
index 891438bbb9..71d63f650c 100644
--- a/src/mjolnir/Mjolnir.ts
+++ b/src/mjolnir/Mjolnir.ts
@@ -20,6 +20,7 @@ import SettingsStore from "../settings/SettingsStore";
import {_t} from "../languageHandler";
import dis from "../dispatcher/dispatcher";
import {SettingLevel} from "../settings/SettingLevel";
+import { Preset } from "../createRoom";
// TODO: Move this and related files to the js-sdk or something once finalized.
@@ -86,7 +87,7 @@ export class Mjolnir {
const resp = await MatrixClientPeg.get().createRoom({
name: _t("My Ban List"),
topic: _t("This is your list of users/servers you have blocked - don't leave the room!"),
- preset: "private_chat",
+ preset: Preset.PrivateChat,
});
personalRoomId = resp['room_id'];
await SettingsStore.setValue(
From 2e6dab0bcd93cfc6e8362423218372767572ae63 Mon Sep 17 00:00:00 2001
From: Germain Souquet
Date: Tue, 15 Jun 2021 00:01:05 +0100
Subject: [PATCH 20/46] change parameter to use preset enum
---
src/components/views/dialogs/CreateRoomDialog.tsx | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/components/views/dialogs/CreateRoomDialog.tsx b/src/components/views/dialogs/CreateRoomDialog.tsx
index cce6b6c34c..614ed4f645 100644
--- a/src/components/views/dialogs/CreateRoomDialog.tsx
+++ b/src/components/views/dialogs/CreateRoomDialog.tsx
@@ -72,7 +72,7 @@ export default class CreateRoomDialog extends React.Component {
canChangeEncryption: true,
};
- MatrixClientPeg.get().doesServerForceEncryptionForPreset("private")
+ MatrixClientPeg.get().doesServerForceEncryptionForPreset(Preset.PrivateChat)
.then(isForced => this.setState({ canChangeEncryption: !isForced }));
}
From b3912dc5b8b499528a2316af790b317a8d5df4ee Mon Sep 17 00:00:00 2001
From: RiotRobot
Date: Tue, 15 Jun 2021 16:16:42 +0100
Subject: [PATCH 21/46] Upgrade matrix-js-sdk to 12.0.0-rc.1
---
package.json | 4 ++--
yarn.lock | 7 ++++---
2 files changed, 6 insertions(+), 5 deletions(-)
diff --git a/package.json b/package.json
index d8c26098ca..7ac73a60e4 100644
--- a/package.json
+++ b/package.json
@@ -78,7 +78,7 @@
"katex": "^0.12.0",
"linkifyjs": "^2.1.9",
"lodash": "^4.17.20",
- "matrix-js-sdk": "github:matrix-org/matrix-js-sdk#develop",
+ "matrix-js-sdk": "12.0.0-rc.1",
"matrix-widget-api": "^0.1.0-beta.14",
"minimist": "^1.2.5",
"opus-recorder": "^8.0.3",
@@ -139,12 +139,12 @@
"@types/zxcvbn": "^4.4.0",
"@typescript-eslint/eslint-plugin": "^4.14.0",
"@typescript-eslint/parser": "^4.14.0",
+ "@wojtekmaj/enzyme-adapter-react-17": "^0.6.1",
"babel-eslint": "^10.1.0",
"babel-jest": "^26.6.3",
"chokidar": "^3.5.1",
"concurrently": "^5.3.0",
"enzyme": "^3.11.0",
- "@wojtekmaj/enzyme-adapter-react-17": "^0.6.1",
"eslint": "7.18.0",
"eslint-config-matrix-org": "^0.2.0",
"eslint-plugin-babel": "^5.3.1",
diff --git a/yarn.lock b/yarn.lock
index 7c232d2aa1..14cd11d769 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -5711,9 +5711,10 @@ mathml-tag-names@^2.1.3:
resolved "https://registry.yarnpkg.com/mathml-tag-names/-/mathml-tag-names-2.1.3.tgz#4ddadd67308e780cf16a47685878ee27b736a0a3"
integrity sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg==
-"matrix-js-sdk@github:matrix-org/matrix-js-sdk#develop":
- version "11.2.0"
- resolved "https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/35ecbed29d16982deff27a8c37b05167738225a2"
+matrix-js-sdk@12.0.0-rc.1:
+ version "12.0.0-rc.1"
+ resolved "https://registry.yarnpkg.com/matrix-js-sdk/-/matrix-js-sdk-12.0.0-rc.1.tgz#b94a72f0549f3000763efb8c7b6fa1f8808e56f6"
+ integrity sha512-bzozc4w9dF6Dl8xXXLXMpe3FqL/ncczKdB9Y8dL1mPaujVrmLWAai+BYmC9/c4SIw+1zUap9P5W16ej3z7prig==
dependencies:
"@babel/runtime" "^7.12.5"
another-json "^0.2.0"
From cdb9d3a41be4c3252781a50a1913b6db4223bb7d Mon Sep 17 00:00:00 2001
From: RiotRobot
Date: Tue, 15 Jun 2021 16:22:33 +0100
Subject: [PATCH 22/46] Prepare changelog for v3.24.0-rc.1
---
CHANGELOG.md | 118 +++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 118 insertions(+)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 94c9530941..a14a0f308e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,121 @@
+Changes in [3.24.0-rc.1](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v3.24.0-rc.1) (2021-06-15)
+===============================================================================================================
+[Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v3.23.0...v3.24.0-rc.1)
+
+ * Upgrade to JS SDK 12.0.0-rc.1
+ * Translations update from Weblate
+ [\#6192](https://github.com/matrix-org/matrix-react-sdk/pull/6192)
+ * Disable comment-on-alert for PR coming from a fork
+ [\#6189](https://github.com/matrix-org/matrix-react-sdk/pull/6189)
+ * Add JS benchmark tracking in CI
+ [\#6177](https://github.com/matrix-org/matrix-react-sdk/pull/6177)
+ * Upgrade matrix-react-test-utils for React 17 peer deps
+ [\#6187](https://github.com/matrix-org/matrix-react-sdk/pull/6187)
+ * Fix display name overlaps on the IRC layout
+ [\#6186](https://github.com/matrix-org/matrix-react-sdk/pull/6186)
+ * Small fixes to the spaces experience
+ [\#6184](https://github.com/matrix-org/matrix-react-sdk/pull/6184)
+ * Add footer and privacy note to the start dm dialog
+ [\#6111](https://github.com/matrix-org/matrix-react-sdk/pull/6111)
+ * Format mxids when disambiguation needed
+ [\#5880](https://github.com/matrix-org/matrix-react-sdk/pull/5880)
+ * Move various createRoom types to the js-sdk
+ [\#6183](https://github.com/matrix-org/matrix-react-sdk/pull/6183)
+ * Fix HTML tag for Event Tile when not rendered in a list
+ [\#6175](https://github.com/matrix-org/matrix-react-sdk/pull/6175)
+ * Remove legacy polyfills and unused dependencies
+ [\#6176](https://github.com/matrix-org/matrix-react-sdk/pull/6176)
+ * Fix buggy hovering/selecting of event tiles
+ [\#6173](https://github.com/matrix-org/matrix-react-sdk/pull/6173)
+ * Add room intro warning when e2ee is not enabled
+ [\#5929](https://github.com/matrix-org/matrix-react-sdk/pull/5929)
+ * Migrate end to end tests to GitHub actions
+ [\#6156](https://github.com/matrix-org/matrix-react-sdk/pull/6156)
+ * Fix expanding last collapsed sticky session when zoomed in
+ [\#6171](https://github.com/matrix-org/matrix-react-sdk/pull/6171)
+ * ⚛️ Upgrade to React@17
+ [\#6165](https://github.com/matrix-org/matrix-react-sdk/pull/6165)
+ * Revert refreshStickyHeaders optimisations
+ [\#6168](https://github.com/matrix-org/matrix-react-sdk/pull/6168)
+ * Add logging for which rooms calls are in
+ [\#6170](https://github.com/matrix-org/matrix-react-sdk/pull/6170)
+ * Restore read receipt animation from event to event
+ [\#6169](https://github.com/matrix-org/matrix-react-sdk/pull/6169)
+ * Restore copy button icon when sharing permalink
+ [\#6166](https://github.com/matrix-org/matrix-react-sdk/pull/6166)
+ * Restore Page Up/Down key bindings when focusing the composer
+ [\#6167](https://github.com/matrix-org/matrix-react-sdk/pull/6167)
+ * Timeline rendering optimizations
+ [\#6143](https://github.com/matrix-org/matrix-react-sdk/pull/6143)
+ * Bump css-what from 5.0.0 to 5.0.1
+ [\#6164](https://github.com/matrix-org/matrix-react-sdk/pull/6164)
+ * Bump ws from 6.2.1 to 6.2.2 in /test/end-to-end-tests
+ [\#6145](https://github.com/matrix-org/matrix-react-sdk/pull/6145)
+ * Bump trim-newlines from 3.0.0 to 3.0.1
+ [\#6163](https://github.com/matrix-org/matrix-react-sdk/pull/6163)
+ * Fix upgrade to element home button in top left menu
+ [\#6162](https://github.com/matrix-org/matrix-react-sdk/pull/6162)
+ * Fix unpinning of pinned messages and panel empty state
+ [\#6140](https://github.com/matrix-org/matrix-react-sdk/pull/6140)
+ * Better handling for widgets that fail to load
+ [\#6161](https://github.com/matrix-org/matrix-react-sdk/pull/6161)
+ * Improved forwarding UI
+ [\#5999](https://github.com/matrix-org/matrix-react-sdk/pull/5999)
+ * Fixes for sharing room links
+ [\#6118](https://github.com/matrix-org/matrix-react-sdk/pull/6118)
+ * Fix setting watchers
+ [\#6160](https://github.com/matrix-org/matrix-react-sdk/pull/6160)
+ * Fix Stickerpicker context menu
+ [\#6152](https://github.com/matrix-org/matrix-react-sdk/pull/6152)
+ * Add warning to private space creation flow
+ [\#6155](https://github.com/matrix-org/matrix-react-sdk/pull/6155)
+ * Add prop to alwaysShowTimestamps on TimelinePanel
+ [\#6159](https://github.com/matrix-org/matrix-react-sdk/pull/6159)
+ * Fix notif panel timestamp padding
+ [\#6157](https://github.com/matrix-org/matrix-react-sdk/pull/6157)
+ * Fixes and refactoring for the ImageView
+ [\#6149](https://github.com/matrix-org/matrix-react-sdk/pull/6149)
+ * Fix timestamps
+ [\#6148](https://github.com/matrix-org/matrix-react-sdk/pull/6148)
+ * Make it easier to pan images in the lightbox
+ [\#6147](https://github.com/matrix-org/matrix-react-sdk/pull/6147)
+ * Fix scroll token for EventTile and EventListSummary node type
+ [\#6154](https://github.com/matrix-org/matrix-react-sdk/pull/6154)
+ * Convert bunch of things to Typescript
+ [\#6153](https://github.com/matrix-org/matrix-react-sdk/pull/6153)
+ * Lint the typescript tests
+ [\#6142](https://github.com/matrix-org/matrix-react-sdk/pull/6142)
+ * Fix jumping to bottom without a highlighted event
+ [\#6146](https://github.com/matrix-org/matrix-react-sdk/pull/6146)
+ * Repair event status position in timeline
+ [\#6141](https://github.com/matrix-org/matrix-react-sdk/pull/6141)
+ * Adapt for js-sdk MatrixClient conversion to TS
+ [\#6132](https://github.com/matrix-org/matrix-react-sdk/pull/6132)
+ * Improve pinned messages in Labs
+ [\#6096](https://github.com/matrix-org/matrix-react-sdk/pull/6096)
+ * Map phone number lookup results to their native rooms
+ [\#6136](https://github.com/matrix-org/matrix-react-sdk/pull/6136)
+ * Fix mx_Event containment rules and empty read avatar row
+ [\#6138](https://github.com/matrix-org/matrix-react-sdk/pull/6138)
+ * Improve switch room rendering
+ [\#6079](https://github.com/matrix-org/matrix-react-sdk/pull/6079)
+ * Add CSS containment rules for shorter reflow operations
+ [\#6127](https://github.com/matrix-org/matrix-react-sdk/pull/6127)
+ * ignore hash/fragment when de-duplicating links for url previews
+ [\#6135](https://github.com/matrix-org/matrix-react-sdk/pull/6135)
+ * Clicking jump to bottom resets room hash
+ [\#5823](https://github.com/matrix-org/matrix-react-sdk/pull/5823)
+ * Use passive option for scroll handlers
+ [\#6113](https://github.com/matrix-org/matrix-react-sdk/pull/6113)
+ * Optimise memberSort performance for large list
+ [\#6130](https://github.com/matrix-org/matrix-react-sdk/pull/6130)
+ * Tweak event border radius to match action bar
+ [\#6133](https://github.com/matrix-org/matrix-react-sdk/pull/6133)
+ * Log when we ignore a second call in a room
+ [\#6131](https://github.com/matrix-org/matrix-react-sdk/pull/6131)
+ * Performance monitoring measurements
+ [\#6041](https://github.com/matrix-org/matrix-react-sdk/pull/6041)
+
Changes in [3.23.0](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v3.23.0) (2021-06-07)
=====================================================================================================
[Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v3.23.0-rc.1...v3.23.0)
From 2eb7d35ea16ce593d7e8fd666327d5a2b2bc495c Mon Sep 17 00:00:00 2001
From: RiotRobot
Date: Tue, 15 Jun 2021 16:22:34 +0100
Subject: [PATCH 23/46] v3.24.0-rc.1
---
package.json | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/package.json b/package.json
index 7ac73a60e4..644793e265 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "matrix-react-sdk",
- "version": "3.23.0",
+ "version": "3.24.0-rc.1",
"description": "SDK for matrix.org using React",
"author": "matrix.org",
"repository": {
@@ -25,7 +25,7 @@
"bin": {
"reskindex": "scripts/reskindex.js"
},
- "main": "./src/index.js",
+ "main": "./lib/index.js",
"matrix_src_main": "./src/index.js",
"matrix_lib_main": "./lib/index.js",
"matrix_lib_typings": "./lib/index.d.ts",
@@ -197,5 +197,6 @@
"coverageReporters": [
"text"
]
- }
+ },
+ "typings": "./lib/index.d.ts"
}
From ea46df0d4841c8c92ed876bae7f2faa98e14da99 Mon Sep 17 00:00:00 2001
From: Travis Ralston
Date: Mon, 7 Jun 2021 20:19:16 -0600
Subject: [PATCH 24/46] Partially restore immutable event objects at the
rendering layer
This is primarily to fix some extremely rare edge cases in local echo, but also restores the accuracy of some comments in the stack regarding immutable event objects (which were made mutable many years ago).
This shouldn't have any impact on the daily usage of the app, only adding a measured 0ms of latency to the stack.
---
src/components/views/messages/TextualBody.js | 1 +
src/components/views/rooms/EventTile.tsx | 124 +++++++++++--------
2 files changed, 76 insertions(+), 49 deletions(-)
diff --git a/src/components/views/messages/TextualBody.js b/src/components/views/messages/TextualBody.js
index 3adfea6ee6..00e7d3d301 100644
--- a/src/components/views/messages/TextualBody.js
+++ b/src/components/views/messages/TextualBody.js
@@ -262,6 +262,7 @@ export default class TextualBody extends React.Component {
// exploit that events are immutable :)
return (nextProps.mxEvent.getId() !== this.props.mxEvent.getId() ||
+ nextProps.mxEvent !== this.props.mxEvent ||
nextProps.highlights !== this.props.highlights ||
nextProps.replacingEventId !== this.props.replacingEventId ||
nextProps.highlightLink !== this.props.highlightLink ||
diff --git a/src/components/views/rooms/EventTile.tsx b/src/components/views/rooms/EventTile.tsx
index 85b9cac2c4..d1b596a709 100644
--- a/src/components/views/rooms/EventTile.tsx
+++ b/src/components/views/rooms/EventTile.tsx
@@ -298,6 +298,9 @@ interface IState {
// The Relations model from the JS SDK for reactions to `mxEvent`
reactions: Relations;
+ // Our snapshotted/local copy of the props.mxEvent, for local echo reasons
+ mxEvent: MatrixEvent;
+
hover: boolean;
}
@@ -332,6 +335,8 @@ export default class EventTile extends React.Component {
// The Relations model from the JS SDK for reactions to `mxEvent`
reactions: this.getReactions(),
+ mxEvent: this.mxEvent.getSnapshotCopy(), // snapshot up front to verify it all works
+
hover: false,
};
@@ -348,6 +353,10 @@ export default class EventTile extends React.Component {
this.ref = React.createRef();
}
+ private get mxEvent(): MatrixEvent {
+ return this.state?.mxEvent ?? this.props.mxEvent;
+ }
+
/**
* When true, the tile qualifies for some sort of special read receipt. This could be a 'sending'
* or 'sent' receipt, for example.
@@ -356,16 +365,16 @@ export default class EventTile extends React.Component {
private get isEligibleForSpecialReceipt() {
// First, if there are other read receipts then just short-circuit this.
if (this.props.readReceipts && this.props.readReceipts.length > 0) return false;
- if (!this.props.mxEvent) return false;
+ if (!this.mxEvent) return false;
// Sanity check (should never happen, but we shouldn't explode if it does)
- const room = this.context.getRoom(this.props.mxEvent.getRoomId());
+ const room = this.context.getRoom(this.mxEvent.getRoomId());
if (!room) return false;
// Quickly check to see if the event was sent by us. If it wasn't, it won't qualify for
// special read receipts.
const myUserId = MatrixClientPeg.get().getUserId();
- if (this.props.mxEvent.getSender() !== myUserId) return false;
+ if (this.mxEvent.getSender() !== myUserId) return false;
// Finally, determine if the type is relevant to the user. This notably excludes state
// events and pretty much anything that can't be sent by the composer as a message. For
@@ -376,7 +385,7 @@ export default class EventTile extends React.Component {
EventType.RoomMessage,
EventType.RoomMessageEncrypted,
];
- if (!simpleSendableEvents.includes(this.props.mxEvent.getType())) return false;
+ if (!simpleSendableEvents.includes(this.mxEvent.getType())) return false;
// Default case
return true;
@@ -418,7 +427,7 @@ export default class EventTile extends React.Component {
// TODO: [REACT-WARNING] Move into constructor
// eslint-disable-next-line camelcase
UNSAFE_componentWillMount() {
- this.verifyEvent(this.props.mxEvent);
+ this.verifyEvent(this.mxEvent);
}
componentDidMount() {
@@ -448,11 +457,21 @@ export default class EventTile extends React.Component {
}
shouldComponentUpdate(nextProps, nextState) {
+ // If the echo changed meaningfully, update.
+ if (!this.state.mxEvent?.isEquivalentTo(nextProps.mxEvent)) {
+ return true;
+ }
+
if (objectHasDiff(this.state, nextState)) {
return true;
}
- return !this.propsEqual(this.props, nextProps);
+ if (!this.propsEqual(this.props, nextProps)) {
+ return true;
+ }
+
+ // Always assume there's no significant change.
+ return false;
}
componentWillUnmount() {
@@ -473,11 +492,18 @@ export default class EventTile extends React.Component {
this.context.on("Room.receipt", this.onRoomReceipt);
this.isListeningForReceipts = true;
}
+
+ // Update the state again if the snapshot needs updating. Note that this will fire
+ // a second state update to re-render child components, which ultimately calls didUpdate
+ // again, so we break that loop with a reference check first (faster than comparing events).
+ if (this.state.mxEvent === prevState.mxEvent && !this.state?.mxEvent.isEquivalentTo(this.props.mxEvent)) {
+ this.setState({mxEvent: this.props.mxEvent.getSnapshotCopy()});
+ }
}
private onRoomReceipt = (ev, room) => {
// ignore events for other rooms
- const tileRoom = MatrixClientPeg.get().getRoom(this.props.mxEvent.getRoomId());
+ const tileRoom = MatrixClientPeg.get().getRoom(this.mxEvent.getRoomId());
if (room !== tileRoom) return;
if (!this.shouldShowSentReceipt && !this.shouldShowSendingReceipt && !this.isListeningForReceipts) {
@@ -501,19 +527,19 @@ export default class EventTile extends React.Component {
// we need to re-verify the sending device.
// (we call onHeightChanged in verifyEvent to handle the case where decryption
// has caused a change in size of the event tile)
- this.verifyEvent(this.props.mxEvent);
+ this.verifyEvent(this.mxEvent);
this.forceUpdate();
};
private onDeviceVerificationChanged = (userId, device) => {
- if (userId === this.props.mxEvent.getSender()) {
- this.verifyEvent(this.props.mxEvent);
+ if (userId === this.mxEvent.getSender()) {
+ this.verifyEvent(this.mxEvent);
}
};
private onUserVerificationChanged = (userId, _trustStatus) => {
- if (userId === this.props.mxEvent.getSender()) {
- this.verifyEvent(this.props.mxEvent);
+ if (userId === this.mxEvent.getSender()) {
+ this.verifyEvent(this.mxEvent);
}
};
@@ -620,11 +646,11 @@ export default class EventTile extends React.Component {
}
shouldHighlight() {
- const actions = this.context.getPushActionsForEvent(this.props.mxEvent.replacingEvent() || this.props.mxEvent);
+ const actions = this.context.getPushActionsForEvent(this.mxEvent.replacingEvent() || this.mxEvent);
if (!actions || !actions.tweaks) { return false; }
// don't show self-highlights from another of our clients
- if (this.props.mxEvent.getSender() === this.context.credentials.userId) {
+ if (this.mxEvent.getSender() === this.context.credentials.userId) {
return false;
}
@@ -639,7 +665,7 @@ export default class EventTile extends React.Component {
getReadAvatars() {
if (this.shouldShowSentReceipt || this.shouldShowSendingReceipt) {
- return ;
+ return ;
}
// return early if there are no read receipts
@@ -726,7 +752,7 @@ export default class EventTile extends React.Component {
}
onSenderProfileClick = event => {
- const mxEvent = this.props.mxEvent;
+ const mxEvent = this.mxEvent;
dis.dispatch({
action: 'insert_mention',
user_id: mxEvent.getSender(),
@@ -743,7 +769,7 @@ export default class EventTile extends React.Component {
// Cancel any outgoing key request for this event and resend it. If a response
// is received for the request with the required keys, the event could be
// decrypted successfully.
- this.context.cancelAndResendEventRoomKeyRequest(this.props.mxEvent);
+ this.context.cancelAndResendEventRoomKeyRequest(this.mxEvent);
};
onPermalinkClicked = e => {
@@ -752,14 +778,14 @@ export default class EventTile extends React.Component {
e.preventDefault();
dis.dispatch({
action: 'view_room',
- event_id: this.props.mxEvent.getId(),
+ event_id: this.mxEvent.getId(),
highlighted: true,
- room_id: this.props.mxEvent.getRoomId(),
+ room_id: this.mxEvent.getRoomId(),
});
};
private renderE2EPadlock() {
- const ev = this.props.mxEvent;
+ const ev = this.mxEvent;
// event could not be decrypted
if (ev.getContent().msgtype === 'm.bad.encrypted') {
@@ -818,7 +844,7 @@ export default class EventTile extends React.Component {
) {
return null;
}
- const eventId = this.props.mxEvent.getId();
+ const eventId = this.mxEvent.getId();
return this.props.getRelationsForEvent(eventId, "m.annotation", "m.reaction");
};
@@ -837,13 +863,13 @@ export default class EventTile extends React.Component {
const SenderProfile = sdk.getComponent('messages.SenderProfile');
const MemberAvatar = sdk.getComponent('avatars.MemberAvatar');
- //console.info("EventTile showUrlPreview for %s is %s", this.props.mxEvent.getId(), this.props.showUrlPreview);
+ //console.info("EventTile showUrlPreview for %s is %s", this.mxEvent.getId(), this.props.showUrlPreview);
- const content = this.props.mxEvent.getContent();
+ const content = this.mxEvent.getContent();
const msgtype = content.msgtype;
- const eventType = this.props.mxEvent.getType();
+ const eventType = this.mxEvent.getType();
- let tileHandler = getHandlerTile(this.props.mxEvent);
+ let tileHandler = getHandlerTile(this.mxEvent);
// Info messages are basically information about commands processed on a room
const isBubbleMessage = eventType.startsWith("m.key.verification") ||
@@ -860,7 +886,7 @@ export default class EventTile extends React.Component {
// source tile when there's no regular tile for an event and also for
// replace relations (which otherwise would display as a confusing
// duplicate of the thing they are replacing).
- if (SettingsStore.getValue("showHiddenEventsInTimeline") && !haveTileForEvent(this.props.mxEvent)) {
+ if (SettingsStore.getValue("showHiddenEventsInTimeline") && !haveTileForEvent(this.mxEvent)) {
tileHandler = "messages.ViewSourceEvent";
// Reuse info message avatar and sender profile styling
isInfoMessage = true;
@@ -879,8 +905,8 @@ export default class EventTile extends React.Component {
const EventTileType = sdk.getComponent(tileHandler);
const isSending = (['sending', 'queued', 'encrypting'].indexOf(this.props.eventSendStatus) !== -1);
- const isRedacted = isMessageEvent(this.props.mxEvent) && this.props.isRedacted;
- const isEncryptionFailure = this.props.mxEvent.isDecryptionFailure();
+ const isRedacted = isMessageEvent(this.mxEvent) && this.props.isRedacted;
+ const isEncryptionFailure = this.mxEvent.isDecryptionFailure();
const isEditing = !!this.props.editState;
const classes = classNames({
@@ -910,14 +936,14 @@ export default class EventTile extends React.Component {
let permalink = "#";
if (this.props.permalinkCreator) {
- permalink = this.props.permalinkCreator.forEvent(this.props.mxEvent.getId());
+ permalink = this.props.permalinkCreator.forEvent(this.mxEvent.getId());
}
// we can't use local echoes as scroll tokens, because their event IDs change.
// Local echos have a send "status".
- const scrollToken = this.props.mxEvent.status
+ const scrollToken = this.mxEvent.status
? undefined
- : this.props.mxEvent.getId();
+ : this.mxEvent.getId();
let avatar;
let sender;
@@ -947,15 +973,15 @@ export default class EventTile extends React.Component {
needsSenderProfile = true;
}
- if (this.props.mxEvent.sender && avatarSize) {
+ if (this.mxEvent.sender && avatarSize) {
let member;
// set member to receiver (target) if it is a 3PID invite
// so that the correct avatar is shown as the text is
// `$target accepted the invitation for $email`
- if (this.props.mxEvent.getContent().third_party_invite) {
- member = this.props.mxEvent.target;
+ if (this.mxEvent.getContent().third_party_invite) {
+ member = this.mxEvent.target;
} else {
- member = this.props.mxEvent.sender;
+ member = this.mxEvent.sender;
}
avatar = (
@@ -970,17 +996,17 @@ export default class EventTile extends React.Component
{
if (needsSenderProfile) {
if (!this.props.tileShape || this.props.tileShape === 'reply' || this.props.tileShape === 'reply_preview') {
sender = ;
} else {
- sender = ;
+ sender = ;
}
}
const MessageActionBar = sdk.getComponent('messages.MessageActionBar');
const actionBar = !isEditing ? {
onFocusChange={this.onActionBarFocusChange}
/> : undefined;
- const showTimestamp = this.props.mxEvent.getTs() &&
+ const showTimestamp = this.mxEvent.getTs() &&
(this.props.alwaysShowTimestamps || this.props.last || this.state.hover || this.state.actionBarFocused);
const timestamp = showTimestamp ?
- : null;
+ : null;
const keyRequestHelpText =
@@ -1031,7 +1057,7 @@ export default class EventTile extends React.Component
{
if (!isRedacted) {
const ReactionsRow = sdk.getComponent('messages.ReactionsRow');
reactionsRow = ;
}
@@ -1039,7 +1065,7 @@ export default class EventTile extends React.Component {
const linkedTimestamp =
{ timestamp }
;
@@ -1058,7 +1084,7 @@ export default class EventTile extends React.Component {
switch (this.props.tileShape) {
case 'notif': {
- const room = this.context.getRoom(this.props.mxEvent.getRoomId());
+ const room = this.context.getRoom(this.mxEvent.getRoomId());
return React.createElement(this.props.as || "li", {
"className": classes,
"aria-live": ariaLive,
@@ -1080,7 +1106,7 @@ export default class EventTile extends React.Component {
,
{
}, [
{
let thread;
if (this.props.tileShape === 'reply_preview') {
thread = ReplyThread.makeThread(
- this.props.mxEvent,
+ this.mxEvent,
this.props.onHeightChanged,
this.props.permalinkCreator,
this.replyThread,
@@ -1148,7 +1174,7 @@ export default class EventTile extends React.Component {
{ groupPadlock }
{ thread }
{
}
default: {
const thread = ReplyThread.makeThread(
- this.props.mxEvent,
+ this.mxEvent,
this.props.onHeightChanged,
this.props.permalinkCreator,
this.replyThread,
@@ -1188,7 +1214,7 @@ export default class EventTile extends React.Component {
{ groupPadlock }
{ thread }
Date: Tue, 15 Jun 2021 17:24:56 -0600
Subject: [PATCH 25/46] Update MSC number references for voice messages
as per https://github.com/matrix-org/matrix-doc/pull/3245
---
src/components/views/messages/MVoiceOrAudioBody.tsx | 4 +++-
.../views/rooms/VoiceRecordComposerTile.tsx | 11 ++++-------
2 files changed, 7 insertions(+), 8 deletions(-)
diff --git a/src/components/views/messages/MVoiceOrAudioBody.tsx b/src/components/views/messages/MVoiceOrAudioBody.tsx
index 0cebcf3440..6d26ef3dcb 100644
--- a/src/components/views/messages/MVoiceOrAudioBody.tsx
+++ b/src/components/views/messages/MVoiceOrAudioBody.tsx
@@ -28,7 +28,9 @@ interface IProps {
@replaceableComponent("views.messages.MVoiceOrAudioBody")
export default class MVoiceOrAudioBody extends React.PureComponent {
public render() {
- const isVoiceMessage = !!this.props.mxEvent.getContent()['org.matrix.msc2516.voice'];
+ // MSC2516 is a legacy identifier. See https://github.com/matrix-org/matrix-doc/pull/3245
+ const isVoiceMessage = !!this.props.mxEvent.getContent()['org.matrix.msc2516.voice']
+ || !!this.props.mxEvent.getContent()['org.matrix.msc3245.voice'];
const voiceMessagesEnabled = SettingsStore.getValue("feature_voice_messages");
if (isVoiceMessage && voiceMessagesEnabled) {
return ;
diff --git a/src/components/views/rooms/VoiceRecordComposerTile.tsx b/src/components/views/rooms/VoiceRecordComposerTile.tsx
index 2102071bf3..20d8c9c5d4 100644
--- a/src/components/views/rooms/VoiceRecordComposerTile.tsx
+++ b/src/components/views/rooms/VoiceRecordComposerTile.tsx
@@ -77,7 +77,8 @@ export default class VoiceRecordComposerTile extends React.PureComponent Math.round(v * 1024)),
},
- "org.matrix.msc2516.voice": {}, // No content, this is a rendering hint
+ "org.matrix.msc3245.voice": {}, // No content, this is a rendering hint
});
await this.disposeRecording();
}
From 7c6161d83ad60df8e332656ca0389ce90797ec3e Mon Sep 17 00:00:00 2001
From: "J. Ryan Stinnett"
Date: Wed, 16 Jun 2021 18:00:06 +0100
Subject: [PATCH 26/46] Stop requesting null next replies from the server
A recent change (47e007e08f9bedaf47cf59a63c9bd04219195d76) introduced a
regression where we failed to check whether a reply thread has a next reply.
This meant that we would end up sending `/context/undefined` requests to the
server for every reply thread on every room view.
Fixes https://github.com/vector-im/element-web/issues/17563
Regressed by https://github.com/matrix-org/matrix-react-sdk/pull/6079
---
src/components/views/elements/ReplyThread.js | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/components/views/elements/ReplyThread.js b/src/components/views/elements/ReplyThread.js
index 81ed360b17..a9b24a306b 100644
--- a/src/components/views/elements/ReplyThread.js
+++ b/src/components/views/elements/ReplyThread.js
@@ -297,6 +297,7 @@ export default class ReplyThread extends React.Component {
}
async getEvent(eventId) {
+ if (!eventId) return null;
const event = this.room.findEventById(eventId);
if (event) return event;
From 0367b5bcced808ce75e19f0a7669f3ab5b61524c Mon Sep 17 00:00:00 2001
From: Germain Souquet
Date: Thu, 17 Jun 2021 08:45:09 +0100
Subject: [PATCH 27/46] remove stray bullet point in reply preview
---
src/components/views/elements/ReplyThread.js | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/components/views/elements/ReplyThread.js b/src/components/views/elements/ReplyThread.js
index 81ed360b17..0f6aef37eb 100644
--- a/src/components/views/elements/ReplyThread.js
+++ b/src/components/views/elements/ReplyThread.js
@@ -392,6 +392,7 @@ export default class ReplyThread extends React.Component {
alwaysShowTimestamps={this.props.alwaysShowTimestamps}
enableFlair={SettingsStore.getValue(UIFeature.Flair)}
replacingEventId={ev.replacingEventId()}
+ as="div"
/>
;
});
From 1597b2a971bb3e0194c4a8cf8bb5530923f17438 Mon Sep 17 00:00:00 2001
From: Germain Souquet
Date: Wed, 16 Jun 2021 10:01:23 +0100
Subject: [PATCH 28/46] Keep composer reply when scrolling away from a
highlighted event
---
src/components/structures/RoomView.tsx | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/components/structures/RoomView.tsx b/src/components/structures/RoomView.tsx
index fe90d2f873..c0ce6ba4c9 100644
--- a/src/components/structures/RoomView.tsx
+++ b/src/components/structures/RoomView.tsx
@@ -701,6 +701,7 @@ export default class RoomView extends React.Component {
room_id: this.state.room.roomId,
event_id: this.state.initialEventId,
highlighted: false,
+ replyingToEvent: this.state.replyToEvent,
});
}
}
From a687391b98d638e69983e5d814bcb73bfe52a381 Mon Sep 17 00:00:00 2001
From: Travis Ralston
Date: Thu, 17 Jun 2021 14:21:01 -0600
Subject: [PATCH 29/46] Switch order
---
src/components/views/messages/TextualBody.js | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/components/views/messages/TextualBody.js b/src/components/views/messages/TextualBody.js
index 00e7d3d301..cb6a4f14b6 100644
--- a/src/components/views/messages/TextualBody.js
+++ b/src/components/views/messages/TextualBody.js
@@ -261,8 +261,8 @@ export default class TextualBody extends React.Component {
//console.info("shouldComponentUpdate: ShowUrlPreview for %s is %s", this.props.mxEvent.getId(), this.props.showUrlPreview);
// exploit that events are immutable :)
- return (nextProps.mxEvent.getId() !== this.props.mxEvent.getId() ||
- nextProps.mxEvent !== this.props.mxEvent ||
+ return (nextProps.mxEvent !== this.props.mxEvent ||
+ nextProps.mxEvent.getId() !== this.props.mxEvent.getId() ||
nextProps.highlights !== this.props.highlights ||
nextProps.replacingEventId !== this.props.replacingEventId ||
nextProps.highlightLink !== this.props.highlightLink ||
From 98e0200b4a17fc80b1865ae25bdfec80de0bc161 Mon Sep 17 00:00:00 2001
From: Travis Ralston
Date: Thu, 17 Jun 2021 14:21:50 -0600
Subject: [PATCH 30/46] Function name
---
src/components/views/rooms/EventTile.tsx | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/components/views/rooms/EventTile.tsx b/src/components/views/rooms/EventTile.tsx
index d1b596a709..4dd8fff636 100644
--- a/src/components/views/rooms/EventTile.tsx
+++ b/src/components/views/rooms/EventTile.tsx
@@ -335,7 +335,7 @@ export default class EventTile extends React.Component {
// The Relations model from the JS SDK for reactions to `mxEvent`
reactions: this.getReactions(),
- mxEvent: this.mxEvent.getSnapshotCopy(), // snapshot up front to verify it all works
+ mxEvent: this.mxEvent.toSnapshot(), // snapshot up front to verify it all works
hover: false,
};
@@ -497,7 +497,7 @@ export default class EventTile extends React.Component {
// a second state update to re-render child components, which ultimately calls didUpdate
// again, so we break that loop with a reference check first (faster than comparing events).
if (this.state.mxEvent === prevState.mxEvent && !this.state?.mxEvent.isEquivalentTo(this.props.mxEvent)) {
- this.setState({mxEvent: this.props.mxEvent.getSnapshotCopy()});
+ this.setState({mxEvent: this.props.mxEvent.toSnapshot()});
}
}
From d22617c422ebabc88435bb8a8421b0b347d5e7c0 Mon Sep 17 00:00:00 2001
From: Germain Souquet
Date: Fri, 18 Jun 2021 12:44:15 +0100
Subject: [PATCH 31/46] More specific type definition and adhering to code
style better
---
src/components/structures/SpaceRoomView.tsx | 4 +-
src/components/structures/UserMenu.tsx | 6 +--
.../structures/auth/Registration.tsx | 2 +-
.../views/dialogs/BetaFeedbackDialog.tsx | 4 +-
.../views/dialogs/ConfirmUserActionDialog.tsx | 6 ---
.../views/dialogs/DeactivateAccountDialog.tsx | 2 +-
.../views/dialogs/UserSettingsDialog.tsx | 46 +++++++++----------
.../security/CreateCrossSigningDialog.tsx | 6 +--
.../security/SetupEncryptionDialog.tsx | 10 ++--
src/components/views/right_panel/UserInfo.tsx | 4 +-
.../views/spaces/SpaceCreateMenu.tsx | 4 +-
src/stores/SetupEncryptionStore.ts | 40 ++++++++--------
src/toasts/UnverifiedSessionToast.ts | 4 +-
13 files changed, 66 insertions(+), 72 deletions(-)
diff --git a/src/components/structures/SpaceRoomView.tsx b/src/components/structures/SpaceRoomView.tsx
index 36da384e69..aad770888b 100644
--- a/src/components/structures/SpaceRoomView.tsx
+++ b/src/components/structures/SpaceRoomView.tsx
@@ -59,7 +59,7 @@ import IconizedContextMenu, {
} from "../views/context_menus/IconizedContextMenu";
import AccessibleTooltipButton from "../views/elements/AccessibleTooltipButton";
import {BetaPill} from "../views/beta/BetaCard";
-import { USER_TAB } from "../views/dialogs/UserSettingsDialog";
+import { UserTab } from "../views/dialogs/UserSettingsDialog";
import SettingsStore from "../../settings/SettingsStore";
import dis from "../../dispatcher/dispatcher";
import Modal from "../../Modal";
@@ -166,7 +166,7 @@ const SpaceInfo = ({ space }) => {
const onBetaClick = () => {
defaultDispatcher.dispatch({
action: Action.ViewUserSettings,
- initialTabId: USER_TAB.LABS,
+ initialTabId: UserTab.Labs,
});
};
diff --git a/src/components/structures/UserMenu.tsx b/src/components/structures/UserMenu.tsx
index d942c71c4a..3cf0dc5f84 100644
--- a/src/components/structures/UserMenu.tsx
+++ b/src/components/structures/UserMenu.tsx
@@ -26,7 +26,7 @@ import { ActionPayload } from "../../dispatcher/payloads";
import { Action } from "../../dispatcher/actions";
import { _t } from "../../languageHandler";
import { ContextMenuButton } from "./ContextMenu";
-import { USER_TAB } from "../views/dialogs/UserSettingsDialog";
+import { UserTab } from "../views/dialogs/UserSettingsDialog";
import { OpenToTabPayload } from "../../dispatcher/payloads/OpenToTabPayload";
import FeedbackDialog from "../views/dialogs/FeedbackDialog";
import Modal from "../../Modal";
@@ -408,12 +408,12 @@ export default class UserMenu extends React.Component {
this.onSettingsOpen(e, USER_TAB.NOTIFICATIONS)}
+ onClick={(e) => this.onSettingsOpen(e, UserTab.Notifications)}
/>
this.onSettingsOpen(e, USER_TAB.SECURITY)}
+ onClick={(e) => this.onSettingsOpen(e, UserTab.Security)}
/>
{
);
}
- private onUIAuthFinished = async (success, response) => {
+ private onUIAuthFinished = async (success: boolean, response: any) => {
if (!success) {
let msg = response.message || response.toString();
// can we give a better error message?
diff --git a/src/components/views/dialogs/BetaFeedbackDialog.tsx b/src/components/views/dialogs/BetaFeedbackDialog.tsx
index 85fe81ef4e..1c2dab4bfc 100644
--- a/src/components/views/dialogs/BetaFeedbackDialog.tsx
+++ b/src/components/views/dialogs/BetaFeedbackDialog.tsx
@@ -29,7 +29,7 @@ import InfoDialog from "./InfoDialog";
import AccessibleButton from "../elements/AccessibleButton";
import defaultDispatcher from "../../../dispatcher/dispatcher";
import {Action} from "../../../dispatcher/actions";
-import { USER_TAB } from "./UserSettingsDialog";
+import { UserTab } from "./UserSettingsDialog";
interface IProps extends IDialogProps {
featureId: string;
@@ -70,7 +70,7 @@ const BetaFeedbackDialog: React.FC = ({featureId, onFinished}) => {
onFinished(false);
defaultDispatcher.dispatch({
action: Action.ViewUserSettings,
- initialTabId: USER_TAB.LABS,
+ initialTabId: UserTab.Labs,
});
}}>
{ _t("To leave the beta, visit your settings.") }
diff --git a/src/components/views/dialogs/ConfirmUserActionDialog.tsx b/src/components/views/dialogs/ConfirmUserActionDialog.tsx
index 13be70dbab..c91dcba95c 100644
--- a/src/components/views/dialogs/ConfirmUserActionDialog.tsx
+++ b/src/components/views/dialogs/ConfirmUserActionDialog.tsx
@@ -58,12 +58,6 @@ export default class ConfirmUserActionDialog extends React.Component {
askReason: false,
};
- constructor(props) {
- super(props);
-
- this.reasonField = null;
- }
-
public onOk = (): void => {
let reason;
if (this.reasonField) {
diff --git a/src/components/views/dialogs/DeactivateAccountDialog.tsx b/src/components/views/dialogs/DeactivateAccountDialog.tsx
index 4e64a354bb..cf88802340 100644
--- a/src/components/views/dialogs/DeactivateAccountDialog.tsx
+++ b/src/components/views/dialogs/DeactivateAccountDialog.tsx
@@ -115,7 +115,7 @@ export default class DeactivateAccountDialog extends React.Component {
+ private onUIAuthComplete = (auth: any): void => {
MatrixClientPeg.get().deactivateAccount(auth, this.state.shouldErase).then(r => {
// Deactivation worked - logout & close this dialog
Analytics.trackEvent('Account', 'Deactivate Account');
diff --git a/src/components/views/dialogs/UserSettingsDialog.tsx b/src/components/views/dialogs/UserSettingsDialog.tsx
index 921aece7f4..1a62a4ff22 100644
--- a/src/components/views/dialogs/UserSettingsDialog.tsx
+++ b/src/components/views/dialogs/UserSettingsDialog.tsx
@@ -19,7 +19,7 @@ import React from 'react';
import TabbedView, {Tab} from "../../structures/TabbedView";
import {_t, _td} from "../../../languageHandler";
import GeneralUserSettingsTab from "../settings/tabs/user/GeneralUserSettingsTab";
-import SettingsStore from "../../../settings/SettingsStore";
+import SettingsStore, { CallbackFn } from "../../../settings/SettingsStore";
import LabsUserSettingsTab from "../settings/tabs/user/LabsUserSettingsTab";
import AppearanceUserSettingsTab from "../settings/tabs/user/AppearanceUserSettingsTab";
import SecurityUserSettingsTab from "../settings/tabs/user/SecurityUserSettingsTab";
@@ -34,17 +34,17 @@ import MjolnirUserSettingsTab from "../settings/tabs/user/MjolnirUserSettingsTab
import {UIFeature} from "../../../settings/UIFeature";
import {replaceableComponent} from "../../../utils/replaceableComponent";
-export enum USER_TAB {
- GENERAL = "USER_GENERAL_TAB",
- APPEARANCE = "USER_APPEARANCE_TAB",
- FLAIR = "USER_FLAIR_TAB",
- NOTIFICATIONS = "USER_NOTIFICATIONS_TAB",
- PREFERENCES = "USER_PREFERENCES_TAB",
- VOICE = "USER_VOICE_TAB",
- SECURITY = "USER_SECURITY_TAB",
- LABS = "USER_LABS_TAB",
- MJOLNIR = "USER_MJOLNIR_TAB",
- HELP = "USER_HELP_TAB",
+export enum UserTab {
+ General = "USER_GENERAL_TAB",
+ Appearance = "USER_APPEARANCE_TAB",
+ Flair = "USER_FLAIR_TAB",
+ Notifications = "USER_NOTIFICATIONS_TAB",
+ Preferences = "USER_PREFERENCES_TAB",
+ Voice = "USER_VOICE_TAB",
+ Security = "USER_SECURITY_TAB",
+ Labs = "USER_LABS_TAB",
+ Mjolnir = "USER_MJOLNIR_TAB",
+ Help = "USER_HELP_TAB",
}
interface IProps {
@@ -76,7 +76,7 @@ export default class UserSettingsDialog extends React.Component
SettingsStore.unwatchSetting(this.mjolnirWatcher);
}
- private mjolnirChanged = (settingName, roomId, atLevel, newValue: boolean) => {
+ private mjolnirChanged: CallbackFn = (settingName, roomId, atLevel, newValue) => {
// We can cheat because we know what levels a feature is tracked at, and how it is tracked
this.setState({mjolnirEnabled: newValue});
}
@@ -85,33 +85,33 @@ export default class UserSettingsDialog extends React.Component
const tabs = [];
tabs.push(new Tab(
- USER_TAB.GENERAL,
+ UserTab.General,
_td("General"),
"mx_UserSettingsDialog_settingsIcon",
,
));
tabs.push(new Tab(
- USER_TAB.APPEARANCE,
+ UserTab.Appearance,
_td("Appearance"),
"mx_UserSettingsDialog_appearanceIcon",
,
));
if (SettingsStore.getValue(UIFeature.Flair)) {
tabs.push(new Tab(
- USER_TAB.FLAIR,
+ UserTab.Flair,
_td("Flair"),
"mx_UserSettingsDialog_flairIcon",
,
));
}
tabs.push(new Tab(
- USER_TAB.NOTIFICATIONS,
+ UserTab.Notifications,
_td("Notifications"),
"mx_UserSettingsDialog_bellIcon",
,
));
tabs.push(new Tab(
- USER_TAB.PREFERENCES,
+ UserTab.Preferences,
_td("Preferences"),
"mx_UserSettingsDialog_preferencesIcon",
,
@@ -119,7 +119,7 @@ export default class UserSettingsDialog extends React.Component
if (SettingsStore.getValue(UIFeature.Voip)) {
tabs.push(new Tab(
- USER_TAB.VOICE,
+ UserTab.Voice,
_td("Voice & Video"),
"mx_UserSettingsDialog_voiceIcon",
,
@@ -127,7 +127,7 @@ export default class UserSettingsDialog extends React.Component
}
tabs.push(new Tab(
- USER_TAB.SECURITY,
+ UserTab.Security,
_td("Security & Privacy"),
"mx_UserSettingsDialog_securityIcon",
,
@@ -137,7 +137,7 @@ export default class UserSettingsDialog extends React.Component
|| SettingsStore.getFeatureSettingNames().some(k => SettingsStore.getBetaInfo(k))
) {
tabs.push(new Tab(
- USER_TAB.LABS,
+ UserTab.Labs,
_td("Labs"),
"mx_UserSettingsDialog_labsIcon",
,
@@ -145,14 +145,14 @@ export default class UserSettingsDialog extends React.Component
}
if (this.state.mjolnirEnabled) {
tabs.push(new Tab(
- USER_TAB.MJOLNIR,
+ UserTab.Mjolnir,
_td("Ignored users"),
"mx_UserSettingsDialog_mjolnirIcon",
,
));
}
tabs.push(new Tab(
- USER_TAB.HELP,
+ UserTab.Help,
_td("Help & About"),
"mx_UserSettingsDialog_helpIcon",
this.props.onFinished(true)} />,
diff --git a/src/components/views/dialogs/security/CreateCrossSigningDialog.tsx b/src/components/views/dialogs/security/CreateCrossSigningDialog.tsx
index 7770da3049..840390f6fb 100644
--- a/src/components/views/dialogs/security/CreateCrossSigningDialog.tsx
+++ b/src/components/views/dialogs/security/CreateCrossSigningDialog.tsx
@@ -34,7 +34,7 @@ interface IProps {
interface IState {
error: Error | null;
- canUploadKeysWithPasswordOnly: boolean | null;
+ canUploadKeysWithPasswordOnly?: boolean;
accountPassword: string;
}
@@ -45,7 +45,7 @@ interface IState {
*/
@replaceableComponent("views.dialogs.security.CreateCrossSigningDialog")
export default class CreateCrossSigningDialog extends React.PureComponent {
- constructor(props) {
+ constructor(props: IProps) {
super(props);
this.state = {
@@ -90,7 +90,7 @@ export default class CreateCrossSigningDialog extends React.PureComponent => {
+ private doBootstrapUIAuth = async (makeRequest: (authData: any) => void): Promise => {
if (this.state.canUploadKeysWithPasswordOnly && this.state.accountPassword) {
await makeRequest({
type: 'm.login.password',
diff --git a/src/components/views/dialogs/security/SetupEncryptionDialog.tsx b/src/components/views/dialogs/security/SetupEncryptionDialog.tsx
index b86b89cede..19c7af01ff 100644
--- a/src/components/views/dialogs/security/SetupEncryptionDialog.tsx
+++ b/src/components/views/dialogs/security/SetupEncryptionDialog.tsx
@@ -18,11 +18,11 @@ import React from 'react';
import SetupEncryptionBody from '../../../structures/auth/SetupEncryptionBody';
import BaseDialog from '../BaseDialog';
import { _t } from '../../../../languageHandler';
-import { SetupEncryptionStore, PHASE } from '../../../../stores/SetupEncryptionStore';
+import { SetupEncryptionStore, Phase } from '../../../../stores/SetupEncryptionStore';
import {replaceableComponent} from "../../../../utils/replaceableComponent";
-function iconFromPhase(phase: PHASE) {
- if (phase === PHASE.DONE) {
+function iconFromPhase(phase: Phase) {
+ if (phase === Phase.Done) {
return require("../../../../../res/img/e2e/verified.svg");
} else {
return require("../../../../../res/img/e2e/warning.svg");
@@ -34,14 +34,14 @@ interface IProps {
}
interface IState {
- icon: PHASE;
+ icon: Phase;
}
@replaceableComponent("views.dialogs.security.SetupEncryptionDialog")
export default class SetupEncryptionDialog extends React.Component {
private store: SetupEncryptionStore;
- constructor(props) {
+ constructor(props: IProps) {
super(props);
this.store = SetupEncryptionStore.sharedInstance();
diff --git a/src/components/views/right_panel/UserInfo.tsx b/src/components/views/right_panel/UserInfo.tsx
index fe77ac0377..03954bad56 100644
--- a/src/components/views/right_panel/UserInfo.tsx
+++ b/src/components/views/right_panel/UserInfo.tsx
@@ -48,7 +48,7 @@ import EncryptionPanel from "./EncryptionPanel";
import { useAsyncMemo } from '../../../hooks/useAsyncMemo';
import { legacyVerifyUser, verifyDevice, verifyUser } from '../../../verification';
import { Action } from "../../../dispatcher/actions";
-import { USER_TAB } from "../dialogs/UserSettingsDialog";
+import { UserTab } from "../dialogs/UserSettingsDialog";
import { useIsEncrypted } from "../../../hooks/useIsEncrypted";
import BaseCard from "./BaseCard";
import { E2EStatus } from "../../../utils/ShieldUtils";
@@ -1381,7 +1381,7 @@ const BasicUserInfo: React.FC<{
{
dis.dispatch({
action: Action.ViewUserSettings,
- initialTabId: USER_TAB.SECURITY,
+ initialTabId: UserTab.Security,
});
}}>
{ _t("Edit devices") }
diff --git a/src/components/views/spaces/SpaceCreateMenu.tsx b/src/components/views/spaces/SpaceCreateMenu.tsx
index 95bbabbe53..977cd4a9aa 100644
--- a/src/components/views/spaces/SpaceCreateMenu.tsx
+++ b/src/components/views/spaces/SpaceCreateMenu.tsx
@@ -29,7 +29,7 @@ import AccessibleButton from "../elements/AccessibleButton";
import {BetaPill} from "../beta/BetaCard";
import defaultDispatcher from "../../../dispatcher/dispatcher";
import {Action} from "../../../dispatcher/actions";
-import { USER_TAB } from "../dialogs/UserSettingsDialog";
+import { UserTab } from "../dialogs/UserSettingsDialog";
import Field from "../elements/Field";
import withValidation from "../elements/Validation";
import {SpaceFeedbackPrompt} from "../../structures/SpaceRoomView";
@@ -224,7 +224,7 @@ const SpaceCreateMenu = ({ onFinished }) => {
onFinished();
defaultDispatcher.dispatch({
action: Action.ViewUserSettings,
- initialTabId: USER_TAB.LABS,
+ initialTabId: UserTab.Labs,
});
}} />
{ body }
diff --git a/src/stores/SetupEncryptionStore.ts b/src/stores/SetupEncryptionStore.ts
index 86e8b7afc3..88385d0399 100644
--- a/src/stores/SetupEncryptionStore.ts
+++ b/src/stores/SetupEncryptionStore.ts
@@ -22,18 +22,18 @@ import { MatrixClientPeg } from '../MatrixClientPeg';
import { accessSecretStorage, AccessCancelledError } from '../SecurityManager';
import { PHASE_DONE as VERIF_PHASE_DONE } from "matrix-js-sdk/src/crypto/verification/request/VerificationRequest";
-export enum PHASE {
- LOADING = 0,
- INTRO = 1,
- BUSY = 2,
- DONE = 3, // final done stage, but still showing UX
- CONFIRM_SKIP = 4,
- FINISHED = 5, // UX can be closed
+export enum Phase {
+ Loading = 0,
+ Intro = 1,
+ Busy = 2,
+ Done = 3, // final done stage, but still showing UX
+ ConfirmSkip = 4,
+ Finished = 5, // UX can be closed
}
export class SetupEncryptionStore extends EventEmitter {
private started: boolean;
- public phase: PHASE;
+ public phase: Phase;
public verificationRequest: VerificationRequest;
public backupInfo: IKeyBackupVersion;
public keyId: string;
@@ -50,7 +50,7 @@ export class SetupEncryptionStore extends EventEmitter {
return;
}
this.started = true;
- this.phase = PHASE.LOADING;
+ this.phase = Phase.Loading;
this.verificationRequest = null;
this.backupInfo = null;
@@ -110,15 +110,15 @@ export class SetupEncryptionStore extends EventEmitter {
if (!this.hasDevicesToVerifyAgainst && !this.keyInfo) {
// skip before we can even render anything.
- this.phase = PHASE.FINISHED;
+ this.phase = Phase.Finished;
} else {
- this.phase = PHASE.INTRO;
+ this.phase = Phase.Intro;
}
this.emit("update");
}
public async usePassPhrase(): Promise {
- this.phase = PHASE.BUSY;
+ this.phase = Phase.Busy;
this.emit("update");
const cli = MatrixClientPeg.get();
try {
@@ -147,7 +147,7 @@ export class SetupEncryptionStore extends EventEmitter {
});
if (cli.getCrossSigningId()) {
- this.phase = PHASE.DONE;
+ this.phase = Phase.Done;
this.emit("update");
}
} catch (e) {
@@ -155,7 +155,7 @@ export class SetupEncryptionStore extends EventEmitter {
console.log(e);
}
// this will throw if the user hits cancel, so ignore
- this.phase = PHASE.INTRO;
+ this.phase = Phase.Intro;
this.emit("update");
}
}
@@ -164,7 +164,7 @@ export class SetupEncryptionStore extends EventEmitter {
if (userId !== MatrixClientPeg.get().getUserId()) return;
const publicKeysTrusted = MatrixClientPeg.get().getCrossSigningId();
if (publicKeysTrusted) {
- this.phase = PHASE.DONE;
+ this.phase = Phase.Done;
this.emit("update");
}
}
@@ -185,28 +185,28 @@ export class SetupEncryptionStore extends EventEmitter {
// cross signing to be ready to use, so wait for the user trust status to
// change (or change to DONE if it's already ready).
const publicKeysTrusted = MatrixClientPeg.get().getCrossSigningId();
- this.phase = publicKeysTrusted ? PHASE.DONE : PHASE.BUSY;
+ this.phase = publicKeysTrusted ? Phase.Done : Phase.Busy;
this.emit("update");
}
}
public skip(): void {
- this.phase = PHASE.CONFIRM_SKIP;
+ this.phase = Phase.ConfirmSkip;
this.emit("update");
}
public skipConfirm(): void {
- this.phase = PHASE.FINISHED;
+ this.phase = Phase.Finished;
this.emit("update");
}
public returnAfterSkip(): void {
- this.phase = PHASE.INTRO;
+ this.phase = Phase.Intro;
this.emit("update");
}
public done(): void {
- this.phase = PHASE.FINISHED;
+ this.phase = Phase.Finished;
this.emit("update");
// async - ask other clients for keys, if necessary
MatrixClientPeg.get().crypto.cancelAndResendAllOutgoingKeyRequests();
diff --git a/src/toasts/UnverifiedSessionToast.ts b/src/toasts/UnverifiedSessionToast.ts
index 8e3fa7c8a7..05425b93c0 100644
--- a/src/toasts/UnverifiedSessionToast.ts
+++ b/src/toasts/UnverifiedSessionToast.ts
@@ -21,7 +21,7 @@ import DeviceListener from '../DeviceListener';
import ToastStore from "../stores/ToastStore";
import GenericToast from "../components/views/toasts/GenericToast";
import { Action } from "../dispatcher/actions";
-import { USER_TAB } from "../components/views/dialogs/UserSettingsDialog";
+import { UserTab } from "../components/views/dialogs/UserSettingsDialog";
function toastKey(deviceId: string) {
return "unverified_session_" + deviceId;
@@ -34,7 +34,7 @@ export const showToast = async (deviceId: string) => {
DeviceListener.sharedInstance().dismissUnverifiedSessions([deviceId]);
dis.dispatch({
action: Action.ViewUserSettings,
- initialTabId: USER_TAB.SECURITY,
+ initialTabId: UserTab.Security,
});
};
From fcda0604e0ff1bf6531f1fd45f8c50b4145f6fa1 Mon Sep 17 00:00:00 2001
From: Germain Souquet
Date: Fri, 18 Jun 2021 12:48:31 +0100
Subject: [PATCH 32/46] Fix RoomMember import
---
src/components/views/dialogs/ConfirmUserActionDialog.tsx | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/components/views/dialogs/ConfirmUserActionDialog.tsx b/src/components/views/dialogs/ConfirmUserActionDialog.tsx
index c91dcba95c..05f8c63ace 100644
--- a/src/components/views/dialogs/ConfirmUserActionDialog.tsx
+++ b/src/components/views/dialogs/ConfirmUserActionDialog.tsx
@@ -16,7 +16,7 @@ limitations under the License.
import React from 'react';
import { MatrixClient } from 'matrix-js-sdk/src/client';
-import RoomMember from "matrix-js-sdk/src/models/room-member.js";
+import { RoomMember } from "matrix-js-sdk/src/models/room-member";
import * as sdk from '../../../index';
import { _t } from '../../../languageHandler';
import { GroupMemberType } from '../../../groups';
From 538165d51580805170e4230ba7ded0862f1f89bd Mon Sep 17 00:00:00 2001
From: "J. Ryan Stinnett"
Date: Fri, 18 Jun 2021 14:05:12 +0100
Subject: [PATCH 33/46] Fix phase enum usage in JS modules as well
https://github.com/matrix-org/matrix-react-sdk/pull/6185 converted
`SetupEncryptionStore` to TS, including moving the phase states to an enum. The
calling JS modules were forgotten, so they got a bit confused.
Fixes https://github.com/vector-im/element-web/issues/17689
Regressed by https://github.com/matrix-org/matrix-react-sdk/pull/6185
---
.../structures/auth/CompleteSecurity.js | 19 ++++++------------
.../structures/auth/SetupEncryptionBody.js | 20 ++++++-------------
2 files changed, 12 insertions(+), 27 deletions(-)
diff --git a/src/components/structures/auth/CompleteSecurity.js b/src/components/structures/auth/CompleteSecurity.js
index 49fcf20415..654dd9b6c8 100644
--- a/src/components/structures/auth/CompleteSecurity.js
+++ b/src/components/structures/auth/CompleteSecurity.js
@@ -18,14 +18,7 @@ import React from 'react';
import PropTypes from 'prop-types';
import { _t } from '../../../languageHandler';
import * as sdk from '../../../index';
-import {
- SetupEncryptionStore,
- PHASE_LOADING,
- PHASE_INTRO,
- PHASE_BUSY,
- PHASE_DONE,
- PHASE_CONFIRM_SKIP,
-} from '../../../stores/SetupEncryptionStore';
+import { SetupEncryptionStore, Phase } from '../../../stores/SetupEncryptionStore';
import SetupEncryptionBody from "./SetupEncryptionBody";
import {replaceableComponent} from "../../../utils/replaceableComponent";
@@ -61,18 +54,18 @@ export default class CompleteSecurity extends React.Component {
let icon;
let title;
- if (phase === PHASE_LOADING) {
+ if (phase === Phase.Loading) {
return null;
- } else if (phase === PHASE_INTRO) {
+ } else if (phase === Phase.Intro) {
icon = ;
title = _t("Verify this login");
- } else if (phase === PHASE_DONE) {
+ } else if (phase === Phase.Done) {
icon = ;
title = _t("Session verified");
- } else if (phase === PHASE_CONFIRM_SKIP) {
+ } else if (phase === Phase.ConfirmSkip) {
icon = ;
title = _t("Are you sure?");
- } else if (phase === PHASE_BUSY) {
+ } else if (phase === Phase.Busy) {
icon = ;
title = _t("Verify this login");
} else {
diff --git a/src/components/structures/auth/SetupEncryptionBody.js b/src/components/structures/auth/SetupEncryptionBody.js
index 803df19d00..90137e084c 100644
--- a/src/components/structures/auth/SetupEncryptionBody.js
+++ b/src/components/structures/auth/SetupEncryptionBody.js
@@ -21,15 +21,7 @@ import { MatrixClientPeg } from '../../../MatrixClientPeg';
import Modal from '../../../Modal';
import VerificationRequestDialog from '../../views/dialogs/VerificationRequestDialog';
import * as sdk from '../../../index';
-import {
- SetupEncryptionStore,
- PHASE_LOADING,
- PHASE_INTRO,
- PHASE_BUSY,
- PHASE_DONE,
- PHASE_CONFIRM_SKIP,
- PHASE_FINISHED,
-} from '../../../stores/SetupEncryptionStore';
+import { SetupEncryptionStore, Phase } from '../../../stores/SetupEncryptionStore';
import {replaceableComponent} from "../../../utils/replaceableComponent";
function keyHasPassphrase(keyInfo) {
@@ -63,7 +55,7 @@ export default class SetupEncryptionBody extends React.Component {
_onStoreUpdate = () => {
const store = SetupEncryptionStore.sharedInstance();
- if (store.phase === PHASE_FINISHED) {
+ if (store.phase === Phase.Finished) {
this.props.onFinished();
return;
}
@@ -136,7 +128,7 @@ export default class SetupEncryptionBody extends React.Component {
onClose={this.props.onFinished}
member={MatrixClientPeg.get().getUser(this.state.verificationRequest.otherUserId)}
/>;
- } else if (phase === PHASE_INTRO) {
+ } else if (phase === Phase.Intro) {
const store = SetupEncryptionStore.sharedInstance();
let recoveryKeyPrompt;
if (store.keyInfo && keyHasPassphrase(store.keyInfo)) {
@@ -174,7 +166,7 @@ export default class SetupEncryptionBody extends React.Component {
);
- } else if (phase === PHASE_DONE) {
+ } else if (phase === Phase.Done) {
let message;
if (this.state.backupInfo) {
message = {_t(
@@ -200,7 +192,7 @@ export default class SetupEncryptionBody extends React.Component {
);
- } else if (phase === PHASE_CONFIRM_SKIP) {
+ } else if (phase === Phase.ConfirmSkip) {
return (
{_t(
@@ -224,7 +216,7 @@ export default class SetupEncryptionBody extends React.Component {