): 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 055/151] 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 22:07:25 +0100
Subject: [PATCH 056/151] Update yarn.lock
---
yarn.lock | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/yarn.lock b/yarn.lock
index 8e6b4fa732..289d33088f 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -6659,7 +6659,7 @@ prompts@^2.0.1:
kleur "^3.0.3"
sisteransi "^1.0.5"
-prop-types@^15.5.8, prop-types@^15.6.0, prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.7.0, prop-types@^15.7.2:
+prop-types@^15.6.2, prop-types@^15.7.0, prop-types@^15.7.2:
version "15.7.2"
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5"
integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==
@@ -6809,7 +6809,12 @@ react-focus-lock@^2.5.0:
use-callback-ref "^1.2.1"
use-sidecar "^1.0.1"
-react-is@^16.13.1, react-is@^16.7.0, react-is@^16.8.1, react-is@^16.8.6:
+"react-is@^16.12.0 || ^17.0.0", react-is@^17.0.0, react-is@^17.0.2:
+ version "17.0.2"
+ resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0"
+ integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==
+
+react-is@^16.13.1, react-is@^16.7.0, react-is@^16.8.1:
version "16.13.1"
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
From de414cd0a6b4933096b08e7babdff3c778cb639e Mon Sep 17 00:00:00 2001
From: Germain Souquet
Date: Mon, 14 Jun 2021 23:42:36 +0100
Subject: [PATCH 057/151] 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 058/151] 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 059/151] 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 060/151] 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 061/151] 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 a63d9220d2474ffd592c728371107bcfda1ae070 Mon Sep 17 00:00:00 2001
From: Michael Telatynski <7t3chguy@gmail.com>
Date: Tue, 15 Jun 2021 08:26:46 +0100
Subject: [PATCH 062/151] Clear outstanding TODOs
---
src/stores/SpaceStore.tsx | 17 ++++++++++-------
test/utils/stringOrderField-test.ts | 2 +-
2 files changed, 11 insertions(+), 8 deletions(-)
diff --git a/src/stores/SpaceStore.tsx b/src/stores/SpaceStore.tsx
index d0ec573306..9ffb4eb776 100644
--- a/src/stores/SpaceStore.tsx
+++ b/src/stores/SpaceStore.tsx
@@ -634,9 +634,16 @@ export class SpaceStoreClass extends AsyncStoreWithClient {
return sortBy(spaces, [this.getSpaceTagOrdering, "roomId"]);
}
- private setRootSpaceOrder(space: Room, order: string): void {
+ private async setRootSpaceOrder(space: Room, order: string): Promise {
this.spaceOrderLocalEchoMap.set(space.roomId, order);
- this.matrixClient.setRoomAccountData(space.roomId, EventType.SpaceOrder, { order }); // TODO retrying, failure
+ try {
+ await this.matrixClient.setRoomAccountData(space.roomId, EventType.SpaceOrder, { order });
+ } catch (e) {
+ console.log("Failed to set root space order", e);
+ if (this.spaceOrderLocalEchoMap.get(space.roomId) === order) {
+ this.spaceOrderLocalEchoMap.delete(space.roomId);
+ }
+ }
}
public moveRootSpace(fromIndex: number, toIndex: number): void {
@@ -647,11 +654,7 @@ export class SpaceStoreClass extends AsyncStoreWithClient {
this.setRootSpaceOrder(this.rootSpaces[index], order);
});
- if (changes.length) {
- this.notifyIfOrderChanged();
- } else {
- // TODO
- }
+ this.notifyIfOrderChanged();
}
}
diff --git a/test/utils/stringOrderField-test.ts b/test/utils/stringOrderField-test.ts
index a8bc00eeb9..a523872023 100644
--- a/test/utils/stringOrderField-test.ts
+++ b/test/utils/stringOrderField-test.ts
@@ -67,7 +67,7 @@ describe("stringOrderField", () => {
expect(baseToString(BigInt(6241))).toEqual("`a");
expect(baseToString(BigInt(53), "abcdefghijklmnopqrstuvwxyz")).toEqual("ba");
expect(baseToString(BigInt(1234))).toBe("+}");
- expect(baseToString(BigInt(0))).toBe(""); // TODO
+ expect(baseToString(BigInt(0))).toBe("");
expect(baseToString(BigInt(1))).toBe(" ");
expect(baseToString(BigInt(95))).toBe("~");
expect(baseToString(BigInt(96))).toBe(" ");
From 5130d5e111bf32ced37df78096b85467496b9ee2 Mon Sep 17 00:00:00 2001
From: Michael Telatynski <7t3chguy@gmail.com>
Date: Tue, 15 Jun 2021 12:26:09 +0100
Subject: [PATCH 063/151] Hide addresses section for private spaces
---
.../spaces/SpaceSettingsVisibilityTab.tsx | 27 ++++++++++++-------
1 file changed, 17 insertions(+), 10 deletions(-)
diff --git a/src/components/views/spaces/SpaceSettingsVisibilityTab.tsx b/src/components/views/spaces/SpaceSettingsVisibilityTab.tsx
index 9eb4c6eb02..2f80ad97a6 100644
--- a/src/components/views/spaces/SpaceSettingsVisibilityTab.tsx
+++ b/src/components/views/spaces/SpaceSettingsVisibilityTab.tsx
@@ -120,6 +120,22 @@ const SpaceSettingsVisibilityTab = ({ matrixClient: cli, space }: IProps) => {
>;
}
+ let addressesSection;
+ if (visibility !== SpaceVisibility.Private) {
+ addressesSection = <>
+ {_t("Address")}
+
+ >;
+ }
+
return
{_t("Visibility")}
@@ -164,16 +180,7 @@ const SpaceSettingsVisibilityTab = ({ matrixClient: cli, space }: IProps) => {
{ _t("Recommended for public spaces.") }
- {_t("Address")}
-
+ { addressesSection }
;
};
From 5098a304c9850c139aa73e8e594648b622a4710c Mon Sep 17 00:00:00 2001
From: Michael Telatynski <7t3chguy@gmail.com>
Date: Tue, 15 Jun 2021 12:33:46 +0100
Subject: [PATCH 064/151] delint
---
src/components/views/dialogs/RoomSettingsDialog.tsx | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/src/components/views/dialogs/RoomSettingsDialog.tsx b/src/components/views/dialogs/RoomSettingsDialog.tsx
index 1a664951c5..303f17c342 100644
--- a/src/components/views/dialogs/RoomSettingsDialog.tsx
+++ b/src/components/views/dialogs/RoomSettingsDialog.tsx
@@ -108,7 +108,10 @@ export default class RoomSettingsDialog extends React.Component {
ROOM_ADVANCED_TAB,
_td("Advanced"),
"mx_RoomSettingsDialog_warningIcon",
- ,
+ this.props.onFinished(true)}
+ />,
));
}
From b3912dc5b8b499528a2316af790b317a8d5df4ee Mon Sep 17 00:00:00 2001
From: RiotRobot
Date: Tue, 15 Jun 2021 16:16:42 +0100
Subject: [PATCH 065/151] 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 066/151] 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 067/151] 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 068/151] 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 069/151] 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 b4fbc791bb5a7cde05390bb3a077a7065365f0a8 Mon Sep 17 00:00:00 2001
From: Michael Telatynski <7t3chguy@gmail.com>
Date: Wed, 16 Jun 2021 09:01:13 +0100
Subject: [PATCH 070/151] Add experimental options to the Spaces beta
---
res/css/views/beta/_BetaCard.scss | 8 +-
src/components/views/beta/BetaCard.tsx | 11 +-
.../views/dialogs/BetaFeedbackDialog.tsx | 7 +-
src/components/views/spaces/SpacePanel.tsx | 10 +-
src/i18n/strings/en_EN.json | 6 +-
src/rageshake/submit-rageshake.ts | 12 +-
src/settings/Settings.tsx | 26 ++-
src/stores/SpaceStore.tsx | 148 ++++++++++++++----
src/stores/room-list/SpaceWatcher.ts | 15 +-
.../room-list/filters/SpaceFilterCondition.ts | 8 +-
10 files changed, 203 insertions(+), 48 deletions(-)
diff --git a/res/css/views/beta/_BetaCard.scss b/res/css/views/beta/_BetaCard.scss
index 3463a653fc..fd87b1c824 100644
--- a/res/css/views/beta/_BetaCard.scss
+++ b/res/css/views/beta/_BetaCard.scss
@@ -42,7 +42,7 @@ limitations under the License.
margin-bottom: 20px;
}
- .mx_AccessibleButton {
+ .mx_BetaCard_buttons .mx_AccessibleButton {
display: block;
margin: 12px 0;
padding: 7px 40px;
@@ -55,6 +55,12 @@ limitations under the License.
color: $secondary-fg-color;
margin-top: 20px;
}
+
+ .mx_BetaCard_relatedSettings {
+ summary + .mx_SettingsFlag {
+ margin-top: 4px;
+ }
+ }
}
> img {
diff --git a/src/components/views/beta/BetaCard.tsx b/src/components/views/beta/BetaCard.tsx
index 821c448f4f..56770c3385 100644
--- a/src/components/views/beta/BetaCard.tsx
+++ b/src/components/views/beta/BetaCard.tsx
@@ -25,6 +25,7 @@ import TextWithTooltip from "../elements/TextWithTooltip";
import Modal from "../../../Modal";
import BetaFeedbackDialog from "../dialogs/BetaFeedbackDialog";
import SdkConfig from "../../../SdkConfig";
+import SettingsFlag from "../elements/SettingsFlag";
interface IProps {
title?: string;
@@ -66,7 +67,7 @@ const BetaCard = ({ title: titleOverride, featureId }: IProps) => {
const info = SettingsStore.getBetaInfo(featureId);
if (!info) return null; // Beta is invalid/disabled
- const { title, caption, disclaimer, image, feedbackLabel, feedbackSubheading } = info;
+ const { title, caption, disclaimer, image, feedbackLabel, feedbackSubheading, extraSettings } = info;
const value = SettingsStore.getValue(featureId);
let feedbackButton;
@@ -88,7 +89,7 @@ const BetaCard = ({ title: titleOverride, featureId }: IProps) => {
{ _t(caption) }
-
+
{ feedbackButton }
SettingsStore.setValue(featureId, null, SettingLevel.DEVICE, !value)}
@@ -100,6 +101,12 @@ const BetaCard = ({ title: titleOverride, featureId }: IProps) => {
{ disclaimer &&
{ disclaimer(value) }
}
+ { extraSettings &&
+ { _t("Experimental options") }
+ { extraSettings.map(key => (
+
+ )) }
+ }
;
diff --git a/src/components/views/dialogs/BetaFeedbackDialog.tsx b/src/components/views/dialogs/BetaFeedbackDialog.tsx
index 1ae50dd66f..635f743c76 100644
--- a/src/components/views/dialogs/BetaFeedbackDialog.tsx
+++ b/src/components/views/dialogs/BetaFeedbackDialog.tsx
@@ -44,7 +44,12 @@ const BetaFeedbackDialog: React.FC = ({featureId, onFinished}) => {
const sendFeedback = async (ok: boolean) => {
if (!ok) return onFinished(false);
- submitFeedback(SdkConfig.get().bug_report_endpoint_url, info.feedbackLabel, comment, canContact);
+ const extraData = SettingsStore.getBetaInfo(featureId)?.extraSettings.reduce((o, k) => {
+ o[k] = SettingsStore.getValue(k);
+ return o;
+ }, {});
+
+ submitFeedback(SdkConfig.get().bug_report_endpoint_url, info.feedbackLabel, comment, canContact, extraData);
onFinished(true);
Modal.createTrackedDialog("Beta Dialog Sent", featureId, InfoDialog, {
diff --git a/src/components/views/spaces/SpacePanel.tsx b/src/components/views/spaces/SpacePanel.tsx
index eb63b21f0e..fbda34a03c 100644
--- a/src/components/views/spaces/SpacePanel.tsx
+++ b/src/components/views/spaces/SpacePanel.tsx
@@ -26,6 +26,7 @@ import {SpaceItem} from "./SpaceTreeLevel";
import AccessibleTooltipButton from "../elements/AccessibleTooltipButton";
import {useEventEmitter} from "../../../hooks/useEventEmitter";
import SpaceStore, {
+ HOME_SPACE,
UPDATE_INVITED_SPACES,
UPDATE_SELECTED_SPACE,
UPDATE_TOP_LEVEL_SPACES,
@@ -40,6 +41,7 @@ import {
import {Key} from "../../../Keyboard";
import {RoomNotificationStateStore} from "../../../stores/notifications/RoomNotificationStateStore";
import {NotificationState} from "../../../stores/notifications/NotificationState";
+import SettingsStore from "../../../settings/SettingsStore";
interface IButtonProps {
space?: Room;
@@ -205,6 +207,10 @@ const SpacePanel = () => {
const activeSpaces = activeSpace ? [activeSpace] : [];
const expandCollapseButtonTitle = isPanelCollapsed ? _t("Expand space panel") : _t("Collapse space panel");
+
+ const homeNotificationState = SettingsStore.getValue("feature_spaces.all_rooms")
+ ? RoomNotificationStateStore.instance.globalState : SpaceStore.instance.getNotificationState(HOME_SPACE);
+
// TODO drag and drop for re-arranging order
return
{({onKeyDownHandler}) => (
@@ -218,8 +224,8 @@ const SpacePanel = () => {
className="mx_SpaceButton_home"
onClick={() => SpaceStore.instance.setActiveSpace(null)}
selected={!activeSpace}
- tooltip={_t("All rooms")}
- notificationState={RoomNotificationStateStore.instance.globalState}
+ tooltip={SettingsStore.getValue("feature_spaces.all_rooms") ? _t("All rooms") : _t("Home")}
+ notificationState={homeNotificationState}
isNarrow={isPanelCollapsed}
/>
{ invites.map(s => = {},
+) {
let version = "UNKNOWN";
try {
version = await PlatformPeg.get().getAppVersion();
@@ -279,6 +285,10 @@ export async function submitFeedback(endpoint: string, label: string, comment: s
body.append("platform", PlatformPeg.get().getHumanReadableName());
body.append("user_id", MatrixClientPeg.get()?.getUserId());
+ for (const k in extraData) {
+ body.append(k, extraData[k]);
+ }
+
await _submitReport(SdkConfig.get().bug_report_endpoint_url, body, () => {});
}
diff --git a/src/settings/Settings.tsx b/src/settings/Settings.tsx
index 155d039572..a291cd1fba 100644
--- a/src/settings/Settings.tsx
+++ b/src/settings/Settings.tsx
@@ -1,6 +1,6 @@
/*
Copyright 2017 Travis Ralston
-Copyright 2018, 2019, 2020 The Matrix.org Foundation C.I.C.
+Copyright 2018 - 2021 The Matrix.org Foundation C.I.C.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -127,6 +127,7 @@ export interface ISetting {
image: string; // require(...)
feedbackSubheading?: string;
feedbackLabel?: string;
+ extraSettings?: string[];
};
}
@@ -167,8 +168,31 @@ export const SETTINGS: {[setting: string]: ISetting} = {
feedbackSubheading: _td("Your feedback will help make spaces better. " +
"The more detail you can go into, the better."),
feedbackLabel: "spaces-feedback",
+ extraSettings: [
+ "feature_spaces.all_rooms",
+ "feature_spaces.space_member_dms",
+ "feature_spaces.space_dm_badges",
+ ],
},
},
+ "feature_spaces.all_rooms": {
+ displayName: _td("Use an all rooms space instead of a home space."),
+ supportedLevels: LEVELS_FEATURE,
+ default: true,
+ controller: new ReloadOnChangeController(),
+ },
+ "feature_spaces.space_member_dms": {
+ displayName: _td("Show DMs for joined/invited members in the space."),
+ supportedLevels: LEVELS_FEATURE,
+ default: true,
+ controller: new ReloadOnChangeController(),
+ },
+ "feature_spaces.space_dm_badges": {
+ displayName: _td("Show notification badges for DMs in spaces."),
+ supportedLevels: LEVELS_FEATURE,
+ default: false,
+ controller: new ReloadOnChangeController(),
+ },
"feature_dnd": {
isFeature: true,
displayName: _td("Show options to enable 'Do not disturb' mode"),
diff --git a/src/stores/SpaceStore.tsx b/src/stores/SpaceStore.tsx
index 40997d30a8..31c53e897d 100644
--- a/src/stores/SpaceStore.tsx
+++ b/src/stores/SpaceStore.tsx
@@ -14,36 +14,41 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-import {ListIteratee, Many, sortBy, throttle} from "lodash";
-import {EventType, RoomType} from "matrix-js-sdk/src/@types/event";
-import {Room} from "matrix-js-sdk/src/models/room";
-import {MatrixEvent} from "matrix-js-sdk/src/models/event";
+import { ListIteratee, Many, sortBy, throttle } from "lodash";
+import { EventType, RoomType } from "matrix-js-sdk/src/@types/event";
+import { Room } from "matrix-js-sdk/src/models/room";
+import { MatrixEvent } from "matrix-js-sdk/src/models/event";
-import {AsyncStoreWithClient} from "./AsyncStoreWithClient";
+import { AsyncStoreWithClient } from "./AsyncStoreWithClient";
import defaultDispatcher from "../dispatcher/dispatcher";
-import {ActionPayload} from "../dispatcher/payloads";
+import { ActionPayload } from "../dispatcher/payloads";
import RoomListStore from "./room-list/RoomListStore";
import SettingsStore from "../settings/SettingsStore";
import DMRoomMap from "../utils/DMRoomMap";
-import {FetchRoomFn} from "./notifications/ListNotificationState";
-import {SpaceNotificationState} from "./notifications/SpaceNotificationState";
-import {RoomNotificationStateStore} from "./notifications/RoomNotificationStateStore";
-import {DefaultTagID} from "./room-list/models";
-import {EnhancedMap, mapDiff} from "../utils/maps";
-import {setHasDiff} from "../utils/sets";
-import {ISpaceSummaryEvent, ISpaceSummaryRoom} from "../components/structures/SpaceRoomDirectory";
+import { FetchRoomFn } from "./notifications/ListNotificationState";
+import { SpaceNotificationState } from "./notifications/SpaceNotificationState";
+import { RoomNotificationStateStore } from "./notifications/RoomNotificationStateStore";
+import { DefaultTagID } from "./room-list/models";
+import { EnhancedMap, mapDiff } from "../utils/maps";
+import { setHasDiff } from "../utils/sets";
+import { ISpaceSummaryEvent, ISpaceSummaryRoom } from "../components/structures/SpaceRoomDirectory";
import RoomViewStore from "./RoomViewStore";
+import { arrayHasDiff } from "../utils/arrays";
+import { objectDiff } from "../utils/objects";
+
+type SpaceKey = string | symbol;
interface IState {}
const ACTIVE_SPACE_LS_KEY = "mx_active_space";
+export const HOME_SPACE = Symbol("home-space");
export const SUGGESTED_ROOMS = Symbol("suggested-rooms");
export const UPDATE_TOP_LEVEL_SPACES = Symbol("top-level-spaces");
export const UPDATE_INVITED_SPACES = Symbol("invited-spaces");
export const UPDATE_SELECTED_SPACE = Symbol("selected-space");
-// Space Room ID will be emitted when a Space's children change
+// Space Room ID/HOME_SPACE will be emitted when a Space's children change
export interface ISuggestedRoom extends ISpaceSummaryRoom {
viaServers: string[];
@@ -51,7 +56,8 @@ export interface ISuggestedRoom extends ISpaceSummaryRoom {
const MAX_SUGGESTED_ROOMS = 20;
-const getSpaceContextKey = (space?: Room) => `mx_space_context_${space?.roomId || "ALL_ROOMS"}`;
+const homeSpaceKey = SettingsStore.getValue("feature_spaces.all_rooms") ? "ALL_ROOMS" : "HOME_SPACE";
+const getSpaceContextKey = (space?: Room) => `mx_space_context_${space?.roomId || homeSpaceKey}`;
const partitionSpacesAndRooms = (arr: Room[]): [Room[], Room[]] => { // [spaces, rooms]
return arr.reduce((result, room: Room) => {
@@ -85,13 +91,15 @@ export class SpaceStoreClass extends AsyncStoreWithClient {
// The spaces representing the roots of the various tree-like hierarchies
private rootSpaces: Room[] = [];
+ // The list of rooms not present in any currently joined spaces
+ private orphanedRooms = new Set();
// Map from room ID to set of spaces which list it as a child
private parentMap = new EnhancedMap>();
- // Map from spaceId to SpaceNotificationState instance representing that space
- private notificationStateMap = new Map();
+ // Map from SpaceKey to SpaceNotificationState instance representing that space
+ private notificationStateMap = new Map();
// Map from space key to Set of room IDs that should be shown as part of that space's filter
- private spaceFilteredRooms = new Map>();
- // The space currently selected in the Space Panel - if null then All Rooms is selected
+ private spaceFilteredRooms = new Map>();
+ // The space currently selected in the Space Panel - if null then Home is selected
private _activeSpace?: Room = null;
private _suggestedRooms: ISuggestedRoom[] = [];
private _invitedSpaces = new Set();
@@ -251,7 +259,7 @@ export class SpaceStoreClass extends AsyncStoreWithClient {
}
public getSpaceFilteredRoomIds = (space: Room | null): Set => {
- if (!space) {
+ if (!space && SettingsStore.getValue("feature_spaces.all_rooms")) {
return new Set(this.matrixClient.getVisibleRooms().map(r => r.roomId));
}
return this.spaceFilteredRooms.get(space.roomId) || new Set();
@@ -285,7 +293,7 @@ export class SpaceStoreClass extends AsyncStoreWithClient {
});
});
- const [rootSpaces] = partitionSpacesAndRooms(Array.from(unseenChildren));
+ const [rootSpaces, orphanedRooms] = partitionSpacesAndRooms(Array.from(unseenChildren));
// somewhat algorithm to handle full-cycles
const detachedNodes = new Set(spaces);
@@ -326,6 +334,7 @@ export class SpaceStoreClass extends AsyncStoreWithClient {
// rootSpaces.push(space);
// });
+ this.orphanedRooms = new Set(orphanedRooms);
this.rootSpaces = rootSpaces;
this.parentMap = backrefs;
@@ -342,10 +351,30 @@ export class SpaceStoreClass extends AsyncStoreWithClient {
this.emit(UPDATE_INVITED_SPACES, this.invitedSpaces);
}, 100, {trailing: true, leading: true});
- onSpaceUpdate = () => {
+ private onSpaceUpdate = () => {
this.rebuild();
}
+ private showInHomeSpace = (room: Room) => {
+ if (SettingsStore.getValue("feature_spaces.all_rooms")) return true;
+ if (room.isSpaceRoom()) return false;
+ return !this.parentMap.get(room.roomId)?.size // put all orphaned rooms in the Home Space
+ || DMRoomMap.shared().getUserIdForRoomId(room.roomId) // put all DMs in the Home Space
+ || RoomListStore.instance.getTagsForRoom(room).includes(DefaultTagID.Favourite) // show all favourites
+ };
+
+ // Update a given room due to its tag changing (e.g DM-ness or Fav-ness)
+ // This can only change whether it shows up in the HOME_SPACE or not
+ private onRoomUpdate = (room: Room) => {
+ if (this.showInHomeSpace(room)) {
+ this.spaceFilteredRooms.get(HOME_SPACE)?.add(room.roomId);
+ this.emit(HOME_SPACE);
+ } else if (!this.orphanedRooms.has(room.roomId)) {
+ this.spaceFilteredRooms.get(HOME_SPACE)?.delete(room.roomId);
+ this.emit(HOME_SPACE);
+ }
+ };
+
private onSpaceMembersChange = (ev: MatrixEvent) => {
// skip this update if we do not have a DM with this user
if (DMRoomMap.shared().getDMRoomsForUserId(ev.getStateKey()).length < 1) return;
@@ -359,6 +388,18 @@ export class SpaceStoreClass extends AsyncStoreWithClient {
const oldFilteredRooms = this.spaceFilteredRooms;
this.spaceFilteredRooms = new Map();
+ if (!SettingsStore.getValue("feature_spaces.all_rooms")) {
+ // put all room invites in the Home Space
+ const invites = visibleRooms.filter(r => !r.isSpaceRoom() && r.getMyMembership() === "invite");
+ this.spaceFilteredRooms.set(HOME_SPACE, new Set(invites.map(room => room.roomId)));
+
+ visibleRooms.forEach(room => {
+ if (this.showInHomeSpace(room)) {
+ this.spaceFilteredRooms.get(HOME_SPACE).add(room.roomId);
+ }
+ });
+ }
+
this.rootSpaces.forEach(s => {
// traverse each space tree in DFS to build up the supersets as you go up,
// reusing results from like subtrees.
@@ -374,13 +415,15 @@ export class SpaceStoreClass extends AsyncStoreWithClient {
const roomIds = new Set(childRooms.map(r => r.roomId));
const space = this.matrixClient?.getRoom(spaceId);
- // Add relevant DMs
- space?.getMembers().forEach(member => {
- if (member.membership !== "join" && member.membership !== "invite") return;
- DMRoomMap.shared().getDMRoomsForUserId(member.userId).forEach(roomId => {
- roomIds.add(roomId);
+ if (SettingsStore.getValue("feature_spaces.space_member_dms")) {
+ // Add relevant DMs
+ space?.getMembers().forEach(member => {
+ if (member.membership !== "join" && member.membership !== "invite") return;
+ DMRoomMap.shared().getDMRoomsForUserId(member.userId).forEach(roomId => {
+ roomIds.add(roomId);
+ });
});
- });
+ }
const newPath = new Set(parentPath).add(spaceId);
childSpaces.forEach(childSpace => {
@@ -406,6 +449,8 @@ export class SpaceStoreClass extends AsyncStoreWithClient {
// Update NotificationStates
this.getNotificationState(s)?.setRooms(visibleRooms.filter(room => {
if (roomIds.has(room.roomId)) {
+ if (s !== HOME_SPACE && SettingsStore.getValue("feature_spaces.space_dm_badges")) return true;
+
return !DMRoomMap.shared().getUserIdForRoomId(room.roomId)
|| RoomListStore.instance.getTagsForRoom(room).includes(DefaultTagID.Favourite);
}
@@ -489,6 +534,8 @@ export class SpaceStoreClass extends AsyncStoreWithClient {
// TODO confirm this after implementing parenting behaviour
if (room.isSpaceRoom()) {
this.onSpaceUpdate();
+ } else if (!SettingsStore.getValue("feature_spaces.all_rooms")) {
+ this.onRoomUpdate(room);
}
this.emit(room.roomId);
break;
@@ -501,8 +548,38 @@ export class SpaceStoreClass extends AsyncStoreWithClient {
}
};
+ private onRoomAccountData = (ev: MatrixEvent, room: Room, lastEvent?: MatrixEvent) => {
+ if (ev.getType() === EventType.Tag && !room.isSpaceRoom()) {
+ // If the room was in favourites and now isn't or the opposite then update its position in the trees
+ const oldTags = lastEvent?.getContent()?.tags || {};
+ const newTags = ev.getContent()?.tags || {};
+ if (!!oldTags[DefaultTagID.Favourite] !== !!newTags[DefaultTagID.Favourite]) {
+ this.onRoomUpdate(room);
+ }
+ }
+ }
+
+ private onAccountData = (ev: MatrixEvent, lastEvent: MatrixEvent) => {
+ if (ev.getType() === EventType.Direct) {
+ const lastContent = lastEvent.getContent();
+ const content = ev.getContent();
+
+ const diff = objectDiff>(lastContent, content);
+ // filter out keys which changed by reference only by checking whether the sets differ
+ const changed = diff.changed.filter(k => arrayHasDiff(lastContent[k], content[k]));
+ // DM tag changes, refresh relevant rooms
+ new Set([...diff.added, ...diff.removed, ...changed]).forEach(roomId => {
+ const room = this.matrixClient?.getRoom(roomId);
+ if (room) {
+ this.onRoomUpdate(room);
+ }
+ });
+ }
+ };
+
protected async reset() {
this.rootSpaces = [];
+ this.orphanedRooms = new Set();
this.parentMap = new EnhancedMap();
this.notificationStateMap = new Map();
this.spaceFilteredRooms = new Map();
@@ -517,6 +594,10 @@ export class SpaceStoreClass extends AsyncStoreWithClient {
this.matrixClient.removeListener("Room", this.onRoom);
this.matrixClient.removeListener("Room.myMembership", this.onRoom);
this.matrixClient.removeListener("RoomState.events", this.onRoomState);
+ if (!SettingsStore.getValue("feature_spaces.all_rooms")) {
+ this.matrixClient.removeListener("Room.accountData", this.onRoomAccountData);
+ this.matrixClient.removeListener("accountData", this.onAccountData);
+ }
}
await this.reset();
}
@@ -526,6 +607,10 @@ export class SpaceStoreClass extends AsyncStoreWithClient {
this.matrixClient.on("Room", this.onRoom);
this.matrixClient.on("Room.myMembership", this.onRoom);
this.matrixClient.on("RoomState.events", this.onRoomState);
+ if (!SettingsStore.getValue("feature_spaces.all_rooms")) {
+ this.matrixClient.on("Room.accountData", this.onRoomAccountData);
+ this.matrixClient.on("accountData", this.onAccountData);
+ }
await this.onSpaceUpdate(); // trigger an initial update
@@ -550,7 +635,10 @@ export class SpaceStoreClass extends AsyncStoreWithClient {
// Don't context switch when navigating to the space room
// as it will cause you to end up in the wrong room
this.setActiveSpace(room, false);
- } else if (this.activeSpace && !this.getSpaceFilteredRoomIds(this.activeSpace).has(roomId)) {
+ } else if (
+ (!SettingsStore.getValue("feature_spaces.all_rooms") || this.activeSpace) &&
+ !this.getSpaceFilteredRoomIds(this.activeSpace).has(roomId)
+ ) {
this.switchToRelatedSpace(roomId);
}
@@ -568,7 +656,7 @@ export class SpaceStoreClass extends AsyncStoreWithClient {
}
}
- public getNotificationState(key: string): SpaceNotificationState {
+ public getNotificationState(key: SpaceKey): SpaceNotificationState {
if (this.notificationStateMap.has(key)) {
return this.notificationStateMap.get(key);
}
diff --git a/src/stores/room-list/SpaceWatcher.ts b/src/stores/room-list/SpaceWatcher.ts
index 0b1b78bc75..a989e9c147 100644
--- a/src/stores/room-list/SpaceWatcher.ts
+++ b/src/stores/room-list/SpaceWatcher.ts
@@ -19,6 +19,7 @@ import { Room } from "matrix-js-sdk/src/models/room";
import { RoomListStoreClass } from "./RoomListStore";
import { SpaceFilterCondition } from "./filters/SpaceFilterCondition";
import SpaceStore, { UPDATE_SELECTED_SPACE } from "../SpaceStore";
+import SettingsStore from "../../settings/SettingsStore";
/**
* Watches for changes in spaces to manage the filter on the provided RoomListStore
@@ -28,6 +29,10 @@ export class SpaceWatcher {
private activeSpace: Room = SpaceStore.instance.activeSpace;
constructor(private store: RoomListStoreClass) {
+ if (!SettingsStore.getValue("feature_spaces.all_rooms")) {
+ this.updateFilter();
+ store.addFilter(this.filter);
+ }
SpaceStore.instance.on(UPDATE_SELECTED_SPACE, this.onSelectedSpaceUpdated);
}
@@ -35,7 +40,7 @@ export class SpaceWatcher {
this.activeSpace = activeSpace;
if (this.filter) {
- if (activeSpace) {
+ if (activeSpace || !SettingsStore.getValue("feature_spaces.all_rooms")) {
this.updateFilter();
} else {
this.store.removeFilter(this.filter);
@@ -49,9 +54,11 @@ export class SpaceWatcher {
};
private updateFilter = () => {
- SpaceStore.instance.traverseSpace(this.activeSpace.roomId, roomId => {
- this.store.matrixClient?.getRoom(roomId)?.loadMembersIfNeeded();
- });
+ if (this.activeSpace) {
+ SpaceStore.instance.traverseSpace(this.activeSpace.roomId, roomId => {
+ this.store.matrixClient?.getRoom(roomId)?.loadMembersIfNeeded();
+ });
+ }
this.filter.updateSpace(this.activeSpace);
};
}
diff --git a/src/stores/room-list/filters/SpaceFilterCondition.ts b/src/stores/room-list/filters/SpaceFilterCondition.ts
index 6a06bee0d8..0d1886c38f 100644
--- a/src/stores/room-list/filters/SpaceFilterCondition.ts
+++ b/src/stores/room-list/filters/SpaceFilterCondition.ts
@@ -19,7 +19,7 @@ import { Room } from "matrix-js-sdk/src/models/room";
import { FILTER_CHANGED, FilterKind, IFilterCondition } from "./IFilterCondition";
import { IDestroyable } from "../../../utils/IDestroyable";
-import SpaceStore from "../../SpaceStore";
+import SpaceStore, { HOME_SPACE } from "../../SpaceStore";
import { setHasDiff } from "../../../utils/sets";
/**
@@ -55,12 +55,10 @@ export class SpaceFilterCondition extends EventEmitter implements IFilterConditi
}
};
- private getSpaceEventKey = (space: Room) => space.roomId;
+ private getSpaceEventKey = (space: Room | null) => space ? space.roomId : HOME_SPACE;
public updateSpace(space: Room) {
- if (this.space) {
- SpaceStore.instance.off(this.getSpaceEventKey(this.space), this.onStoreUpdate);
- }
+ SpaceStore.instance.off(this.getSpaceEventKey(this.space), this.onStoreUpdate);
SpaceStore.instance.on(this.getSpaceEventKey(this.space = space), this.onStoreUpdate);
this.onStoreUpdate(); // initial update from the change to the space
}
From a75fb98fbc2de2b39e6f4beb44e889a7d61b3ba2 Mon Sep 17 00:00:00 2001
From: Michael Telatynski <7t3chguy@gmail.com>
Date: Wed, 16 Jun 2021 09:07:55 +0100
Subject: [PATCH 071/151] Fix some NPEs
---
src/stores/SpaceStore.tsx | 2 +-
src/stores/room-list/SpaceWatcher.ts | 1 +
2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/stores/SpaceStore.tsx b/src/stores/SpaceStore.tsx
index 31c53e897d..2b5a25e707 100644
--- a/src/stores/SpaceStore.tsx
+++ b/src/stores/SpaceStore.tsx
@@ -262,7 +262,7 @@ export class SpaceStoreClass extends AsyncStoreWithClient {
if (!space && SettingsStore.getValue("feature_spaces.all_rooms")) {
return new Set(this.matrixClient.getVisibleRooms().map(r => r.roomId));
}
- return this.spaceFilteredRooms.get(space.roomId) || new Set();
+ return this.spaceFilteredRooms.get(space?.roomId || HOME_SPACE) || new Set();
};
private rebuild = throttle(() => {
diff --git a/src/stores/room-list/SpaceWatcher.ts b/src/stores/room-list/SpaceWatcher.ts
index a989e9c147..a1f7786578 100644
--- a/src/stores/room-list/SpaceWatcher.ts
+++ b/src/stores/room-list/SpaceWatcher.ts
@@ -30,6 +30,7 @@ export class SpaceWatcher {
constructor(private store: RoomListStoreClass) {
if (!SettingsStore.getValue("feature_spaces.all_rooms")) {
+ this.filter = new SpaceFilterCondition();
this.updateFilter();
store.addFilter(this.filter);
}
From 9e20e5dfc44c33eb896234d05b60e8804493d9b3 Mon Sep 17 00:00:00 2001
From: Michael Telatynski <7t3chguy@gmail.com>
Date: Wed, 16 Jun 2021 09:14:07 +0100
Subject: [PATCH 072/151] mock new settings in tests
---
test/stores/SpaceStore-test.ts | 11 +++++++++--
1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/test/stores/SpaceStore-test.ts b/test/stores/SpaceStore-test.ts
index 01bd528b87..4cbd9f43c8 100644
--- a/test/stores/SpaceStore-test.ts
+++ b/test/stores/SpaceStore-test.ts
@@ -123,8 +123,15 @@ describe("SpaceStore", () => {
jest.runAllTimers();
client.getVisibleRooms.mockReturnValue(rooms = []);
getValue.mockImplementation(settingName => {
- if (settingName === "feature_spaces") {
- return true;
+ switch (settingName) {
+ case "feature_spaces":
+ return true;
+ case "feature_spaces.all_rooms":
+ return true;
+ case "feature_spaces.space_member_dms":
+ return true;
+ case "feature_spaces.space_dm_badges":
+ return false;
}
});
});
From cee294f5a7378737bc0cbaf9707250eeea5a195d Mon Sep 17 00:00:00 2001
From: Michael Telatynski <7t3chguy@gmail.com>
Date: Wed, 16 Jun 2021 09:23:06 +0100
Subject: [PATCH 073/151] iterate PR
---
.../structures/AutoHideScrollbar.tsx | 2 +-
.../structures/SpaceRoomDirectory.tsx | 28 +++++++++----------
.../views/spaces/SpaceTreeLevel.tsx | 28 +++++++++----------
src/stores/SpaceStore.tsx | 5 ++--
src/utils/arrays.ts | 2 +-
src/utils/stringOrderField.ts | 4 +--
6 files changed, 34 insertions(+), 35 deletions(-)
diff --git a/src/components/structures/AutoHideScrollbar.tsx b/src/components/structures/AutoHideScrollbar.tsx
index e5fa124fed..8650224fb3 100644
--- a/src/components/structures/AutoHideScrollbar.tsx
+++ b/src/components/structures/AutoHideScrollbar.tsx
@@ -15,7 +15,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-import React, {HTMLAttributes} from "react";
+import React, { HTMLAttributes } from "react";
interface IProps extends HTMLAttributes {
className?: string;
diff --git a/src/components/structures/SpaceRoomDirectory.tsx b/src/components/structures/SpaceRoomDirectory.tsx
index 2b4fb24c1b..497f525a00 100644
--- a/src/components/structures/SpaceRoomDirectory.tsx
+++ b/src/components/structures/SpaceRoomDirectory.tsx
@@ -14,34 +14,34 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-import React, {ReactNode, useMemo, useState} from "react";
-import {Room} from "matrix-js-sdk/src/models/room";
-import {MatrixClient} from "matrix-js-sdk/src/client";
-import {EventType, RoomType} from "matrix-js-sdk/src/@types/event";
+import React, { ReactNode, useMemo, useState } from "react";
+import { Room } from "matrix-js-sdk/src/models/room";
+import { MatrixClient } from "matrix-js-sdk/src/client";
+import { EventType, RoomType } from "matrix-js-sdk/src/@types/event";
import classNames from "classnames";
-import {sortBy} from "lodash";
+import { sortBy } from "lodash";
-import {MatrixClientPeg} from "../../MatrixClientPeg";
+import { MatrixClientPeg } from "../../MatrixClientPeg";
import dis from "../../dispatcher/dispatcher";
-import {_t} from "../../languageHandler";
-import AccessibleButton, {ButtonEvent} from "../views/elements/AccessibleButton";
+import { _t } from "../../languageHandler";
+import AccessibleButton, { ButtonEvent } from "../views/elements/AccessibleButton";
import BaseDialog from "../views/dialogs/BaseDialog";
import Spinner from "../views/elements/Spinner";
import SearchBox from "./SearchBox";
import RoomAvatar from "../views/avatars/RoomAvatar";
import RoomName from "../views/elements/RoomName";
-import {useAsyncMemo} from "../../hooks/useAsyncMemo";
-import {EnhancedMap} from "../../utils/maps";
+import { useAsyncMemo } from "../../hooks/useAsyncMemo";
+import { EnhancedMap } from "../../utils/maps";
import StyledCheckbox from "../views/elements/StyledCheckbox";
import AutoHideScrollbar from "./AutoHideScrollbar";
import BaseAvatar from "../views/avatars/BaseAvatar";
-import {mediaFromMxc} from "../../customisations/Media";
+import { mediaFromMxc } from "../../customisations/Media";
import InfoTooltip from "../views/elements/InfoTooltip";
import TextWithTooltip from "../views/elements/TextWithTooltip";
-import {useStateToggle} from "../../hooks/useStateToggle";
-import {getChildOrder} from "../../stores/SpaceStore";
+import { useStateToggle } from "../../hooks/useStateToggle";
+import { getChildOrder } from "../../stores/SpaceStore";
import AccessibleTooltipButton from "../views/elements/AccessibleTooltipButton";
-import {linkifyElement} from "../../HtmlUtils";
+import { linkifyElement } from "../../HtmlUtils";
interface IHierarchyProps {
space: Room;
diff --git a/src/components/views/spaces/SpaceTreeLevel.tsx b/src/components/views/spaces/SpaceTreeLevel.tsx
index 7ac863b239..416b4cc6f1 100644
--- a/src/components/views/spaces/SpaceTreeLevel.tsx
+++ b/src/components/views/spaces/SpaceTreeLevel.tsx
@@ -14,23 +14,23 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-import React, {InputHTMLAttributes, LegacyRef} from "react";
+import React, { InputHTMLAttributes, LegacyRef } from "react";
import classNames from "classnames";
-import {Room} from "matrix-js-sdk/src/models/room";
+import { Room } from "matrix-js-sdk/src/models/room";
import RoomAvatar from "../avatars/RoomAvatar";
import SpaceStore from "../../../stores/SpaceStore";
import SpaceTreeLevelLayoutStore from "../../../stores/SpaceTreeLevelLayoutStore";
import NotificationBadge from "../rooms/NotificationBadge";
-import {RovingAccessibleButton} from "../../../accessibility/roving/RovingAccessibleButton";
-import {RovingAccessibleTooltipButton} from "../../../accessibility/roving/RovingAccessibleTooltipButton";
+import { RovingAccessibleButton } from "../../../accessibility/roving/RovingAccessibleButton";
+import { RovingAccessibleTooltipButton } from "../../../accessibility/roving/RovingAccessibleTooltipButton";
import IconizedContextMenu, {
IconizedContextMenuOption,
IconizedContextMenuOptionList,
} from "../context_menus/IconizedContextMenu";
-import {_t} from "../../../languageHandler";
-import {ContextMenuTooltipButton} from "../../../accessibility/context_menu/ContextMenuTooltipButton";
-import {toRightOf} from "../../structures/ContextMenu";
+import { _t } from "../../../languageHandler";
+import { ContextMenuTooltipButton } from "../../../accessibility/context_menu/ContextMenuTooltipButton";
+import { toRightOf } from "../../structures/ContextMenu";
import {
shouldShowSpaceSettings,
showAddExistingRooms,
@@ -39,15 +39,15 @@ import {
showSpaceSettings,
} from "../../../utils/space";
import MatrixClientContext from "../../../contexts/MatrixClientContext";
-import AccessibleButton, {ButtonEvent} from "../elements/AccessibleButton";
+import AccessibleButton, { ButtonEvent } from "../elements/AccessibleButton";
import defaultDispatcher from "../../../dispatcher/dispatcher";
-import {Action} from "../../../dispatcher/actions";
+import { Action } from "../../../dispatcher/actions";
import RoomViewStore from "../../../stores/RoomViewStore";
-import {SetRightPanelPhasePayload} from "../../../dispatcher/payloads/SetRightPanelPhasePayload";
-import {RightPanelPhases} from "../../../stores/RightPanelStorePhases";
-import {EventType} from "matrix-js-sdk/src/@types/event";
-import {StaticNotificationState} from "../../../stores/notifications/StaticNotificationState";
-import {NotificationColor} from "../../../stores/notifications/NotificationColor";
+import { SetRightPanelPhasePayload } from "../../../dispatcher/payloads/SetRightPanelPhasePayload";
+import { RightPanelPhases } from "../../../stores/RightPanelStorePhases";
+import { EventType } from "matrix-js-sdk/src/@types/event";
+import { StaticNotificationState } from "../../../stores/notifications/StaticNotificationState";
+import { NotificationColor } from "../../../stores/notifications/NotificationColor";
interface IItemProps extends InputHTMLAttributes {
space?: Room;
diff --git a/src/stores/SpaceStore.tsx b/src/stores/SpaceStore.tsx
index 9ffb4eb776..b0099b3306 100644
--- a/src/stores/SpaceStore.tsx
+++ b/src/stores/SpaceStore.tsx
@@ -62,14 +62,13 @@ const partitionSpacesAndRooms = (arr: Room[]): [Room[], Room[]] => { // [spaces,
}, [[], []]);
};
-const validOrder = (order: string): string | null => {
+const validOrder = (order: string): string | undefined => {
if (typeof order === "string" && order.length <= 50 && Array.from(order).every((c: string) => {
const charCode = c.charCodeAt(0);
return charCode >= 0x20 && charCode <= 0x7E;
})) {
return order;
}
- return undefined;
};
// For sorting space children using a validated `order`, `m.room.create`'s `origin_server_ts`, `room_id`
@@ -639,7 +638,7 @@ export class SpaceStoreClass extends AsyncStoreWithClient {
try {
await this.matrixClient.setRoomAccountData(space.roomId, EventType.SpaceOrder, { order });
} catch (e) {
- console.log("Failed to set root space order", e);
+ console.warn("Failed to set root space order", e);
if (this.spaceOrderLocalEchoMap.get(space.roomId) === order) {
this.spaceOrderLocalEchoMap.delete(space.roomId);
}
diff --git a/src/utils/arrays.ts b/src/utils/arrays.ts
index d319631d93..148861e5d3 100644
--- a/src/utils/arrays.ts
+++ b/src/utils/arrays.ts
@@ -230,7 +230,7 @@ export function arrayMerge(...a: T[][]): T[] {
* @param toIndex the index of where to put the element.
* @returns A new array with the requested value moved.
*/
-export function reorder(list: T[], fromIndex: number, toIndex: number): T[] {
+export function moveElement(list: T[], fromIndex: number, toIndex: number): T[] {
const result = Array.from(list);
const [removed] = result.splice(fromIndex, 1);
result.splice(toIndex, 0, removed);
diff --git a/src/utils/stringOrderField.ts b/src/utils/stringOrderField.ts
index 4336583b9d..b312b85b08 100644
--- a/src/utils/stringOrderField.ts
+++ b/src/utils/stringOrderField.ts
@@ -16,7 +16,7 @@ limitations under the License.
import { alphabetPad, baseToString, stringToBase, DEFAULT_ALPHABET } from "matrix-js-sdk/src/utils";
-import { reorder } from "./arrays";
+import { moveElement } from "./arrays";
export const midPointsBetweenStrings = (
a: string,
@@ -73,7 +73,7 @@ export const reorderLexicographically = (
// zip orders with their indices to simplify later index wrangling
const ordersWithIndices: IEntry[] = orders.map((order, index) => ({ index, order }));
// apply the fundamental order update to the zipped array
- const newOrder = reorder(ordersWithIndices, fromIndex, toIndex);
+ const newOrder = moveElement(ordersWithIndices, fromIndex, toIndex);
// check if we have to fill undefined orders to complete placement
const orderToLeftUndefined = newOrder[toIndex - 1]?.order === undefined;
From bceee7978edc0a972f67cc612a250d5f0f717dfd Mon Sep 17 00:00:00 2001
From: Michael Telatynski <7t3chguy@gmail.com>
Date: Wed, 16 Jun 2021 09:30:47 +0100
Subject: [PATCH 074/151] improve naming of tests
---
test/utils/stringOrderField-test.ts | 495 +++++++++++++---------------
1 file changed, 221 insertions(+), 274 deletions(-)
diff --git a/test/utils/stringOrderField-test.ts b/test/utils/stringOrderField-test.ts
index a523872023..ece3043d86 100644
--- a/test/utils/stringOrderField-test.ts
+++ b/test/utils/stringOrderField-test.ts
@@ -39,306 +39,253 @@ const moveLexicographicallyTest = (
};
describe("stringOrderField", () => {
- it("stringToBase", () => {
- expect(Number(stringToBase(""))).toBe(0);
- expect(Number(stringToBase(" "))).toBe(1);
- expect(Number(stringToBase("a"))).toBe(66);
- expect(Number(stringToBase(" !"))).toBe(97);
- expect(Number(stringToBase("aa"))).toBe(6336);
- expect(Number(stringToBase("cat"))).toBe(620055);
- expect(Number(stringToBase("doggo"))).toBe(5689339845);
- expect(Number(stringToBase("a", "abcdefghijklmnopqrstuvwxyz"))).toEqual(1);
- expect(Number(stringToBase("a"))).toEqual(66);
- expect(Number(stringToBase("c", "abcdefghijklmnopqrstuvwxyz"))).toEqual(3);
- expect(Number(stringToBase("ab"))).toEqual(6337);
- expect(Number(stringToBase("cb", "abcdefghijklmnopqrstuvwxyz"))).toEqual(80);
- expect(Number(stringToBase("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"))).toEqual(4.648312045971824e+78);
- expect(Number(stringToBase("~".repeat(50)))).toEqual(7.776353884348688e+98);
- expect(Number(stringToBase(" "))).toEqual(7820126496);
- expect(Number(stringToBase(" "))).toEqual(96);
- expect(Number(stringToBase(" !"))).toEqual(97);
- expect(Number(stringToBase("S:J\\~"))).toEqual(4258975590);
- expect(Number(stringToBase("!'Tu:}"))).toEqual(16173443434);
+ describe("midPointsBetweenStrings", () => {
+ it("should work", () => {
+ expect(averageBetweenStrings("!!", "##")).toBe('""');
+ const midpoints = ["a", ...midPointsBetweenStrings("a", "e", 3, 1), "e"].sort();
+ expect(midpoints[0]).toBe("a");
+ expect(midpoints[4]).toBe("e");
+ expect(midPointsBetweenStrings(" ", "!'Tu:}", 1, 50)).toStrictEqual([" S:J\\~"]);
+ });
+
+ it("should return empty array when the request is not possible", () => {
+ expect(midPointsBetweenStrings("a", "e", 0, 1)).toStrictEqual([]);
+ expect(midPointsBetweenStrings("a", "e", 4, 1)).toStrictEqual([]);
+ });
});
- it("baseToString", () => {
- expect(baseToString(BigInt(10))).toBe(DEFAULT_ALPHABET[9]);
- expect(baseToString(BigInt(10), "abcdefghijklmnopqrstuvwxyz")).toEqual("j");
- expect(baseToString(BigInt(6241))).toEqual("`a");
- expect(baseToString(BigInt(53), "abcdefghijklmnopqrstuvwxyz")).toEqual("ba");
- expect(baseToString(BigInt(1234))).toBe("+}");
- expect(baseToString(BigInt(0))).toBe("");
- expect(baseToString(BigInt(1))).toBe(" ");
- expect(baseToString(BigInt(95))).toBe("~");
- expect(baseToString(BigInt(96))).toBe(" ");
- expect(baseToString(BigInt(97))).toBe(" !");
- expect(baseToString(BigInt(98))).toBe(' "');
- expect(baseToString(BigInt(1))).toBe(" ");
- });
+ describe("reorderLexicographically", () => {
+ it("should work when moving left", () => {
+ moveLexicographicallyTest(["a", "c", "e", "g", "i"], 2, 1, 1);
+ });
- it("midPointsBetweenStrings", () => {
- expect(averageBetweenStrings("!!", "##")).toBe('""');
- const midpoints = ["a", ...midPointsBetweenStrings("a", "e", 3, 1), "e"].sort();
- expect(midpoints[0]).toBe("a");
- expect(midpoints[4]).toBe("e");
- expect(midPointsBetweenStrings("a", "e", 0, 1)).toStrictEqual([]);
- expect(midPointsBetweenStrings("a", "e", 4, 1)).toStrictEqual([]);
- expect(midPointsBetweenStrings(" ", "!'Tu:}", 1, 50)).toStrictEqual([" S:J\\~"]);
- expect(averageBetweenStrings(" ", "!!")).toBe(" P");
- expect(averageBetweenStrings("! ", "!!")).toBe("! ");
- });
+ it("should work when moving right", () => {
+ moveLexicographicallyTest(["a", "c", "e", "g", "i"], 1, 2, 1);
+ });
- it("moveLexicographically left", () => {
- moveLexicographicallyTest(["a", "c", "e", "g", "i"], 2, 1, 1);
- });
+ it("should work when all orders are undefined", () => {
+ moveLexicographicallyTest(
+ [undefined, undefined, undefined, undefined, undefined, undefined],
+ 4,
+ 1,
+ 2,
+ );
+ });
- it("moveLexicographically right", () => {
- moveLexicographicallyTest(["a", "c", "e", "g", "i"], 1, 2, 1);
- });
+ it("should work when moving to end and all orders are undefined", () => {
+ moveLexicographicallyTest(
+ [undefined, undefined, undefined, undefined, undefined, undefined],
+ 1,
+ 4,
+ 5,
+ );
+ });
- it("moveLexicographically all undefined", () => {
- moveLexicographicallyTest(
- [undefined, undefined, undefined, undefined, undefined, undefined],
- 4,
- 1,
- 2,
- );
- });
+ it("should work when moving left and some orders are undefined", () => {
+ moveLexicographicallyTest(
+ ["a", "c", "e", undefined, undefined, undefined],
+ 5,
+ 2,
+ 1,
+ );
- it("moveLexicographically all undefined to end", () => {
- moveLexicographicallyTest(
- [undefined, undefined, undefined, undefined, undefined, undefined],
- 1,
- 4,
- 5,
- );
- });
+ moveLexicographicallyTest(
+ ["a", "a", "e", undefined, undefined, undefined],
+ 5,
+ 1,
+ 2,
+ );
+ });
- it("moveLexicographically some undefined move left", () => {
- moveLexicographicallyTest(
- ["a", "c", "e", undefined, undefined, undefined],
- 5,
- 2,
- 1,
- );
- });
+ it("should work moving to the start when all is undefined", () => {
+ moveLexicographicallyTest(
+ [undefined, undefined, undefined, undefined],
+ 2,
+ 0,
+ 1,
+ );
+ });
- it("moveLexicographically some undefined move left close", () => {
- moveLexicographicallyTest(
- ["a", "a", "e", undefined, undefined, undefined],
- 5,
- 1,
- 2,
- );
- });
+ it("should work moving to the end when all is undefined", () => {
+ moveLexicographicallyTest(
+ [undefined, undefined, undefined, undefined],
+ 1,
+ 3,
+ 4,
+ );
+ });
- it("test moving to the start when all is undefined", () => {
- moveLexicographicallyTest(
- [undefined, undefined, undefined, undefined],
- 2,
- 0,
- 1,
- );
- });
+ it("should work moving left when all is undefined", () => {
+ moveLexicographicallyTest(
+ [undefined, undefined, undefined, undefined, undefined, undefined],
+ 4,
+ 1,
+ 2,
+ );
+ });
- it("test moving to the end when all is undefined", () => {
- moveLexicographicallyTest(
- [undefined, undefined, undefined, undefined],
- 1,
- 3,
- 4,
- );
- });
+ it("should work moving right when all is undefined", () => {
+ moveLexicographicallyTest(
+ [undefined, undefined, undefined, undefined],
+ 1,
+ 2,
+ 3,
+ );
+ });
- it("test moving left when all is undefined", () => {
- moveLexicographicallyTest(
- [undefined, undefined, undefined, undefined, undefined, undefined],
- 4,
- 1,
- 2,
- );
- });
+ it("should work moving more right when all is undefined", () => {
+ moveLexicographicallyTest(
+ [undefined, undefined, undefined, undefined, undefined, /**/ undefined, undefined],
+ 1,
+ 4,
+ 5,
+ );
+ });
- it("test moving right when all is undefined", () => {
- moveLexicographicallyTest(
- [undefined, undefined, undefined, undefined],
- 1,
- 2,
- 3,
- );
- });
+ it("should work moving left when right is undefined", () => {
+ moveLexicographicallyTest(
+ ["20", undefined, undefined, undefined, undefined, undefined],
+ 4,
+ 2,
+ 2,
+ );
+ });
- it("test moving more right when all is undefined", () => {
- moveLexicographicallyTest(
- [undefined, undefined, undefined, undefined, undefined, /**/ undefined, undefined],
- 1,
- 4,
- 5,
- );
- });
+ it("should work moving right when right is undefined", () => {
+ moveLexicographicallyTest(
+ ["50", undefined, undefined, undefined, undefined, /**/ undefined, undefined],
+ 1,
+ 4,
+ 4,
+ );
+ });
- it("test moving left when right is undefined", () => {
- moveLexicographicallyTest(
- ["20", undefined, undefined, undefined, undefined, undefined],
- 4,
- 2,
- 2,
- );
- });
+ it("should work moving left when right is defined", () => {
+ moveLexicographicallyTest(
+ ["10", "20", "30", "40", undefined, undefined],
+ 3,
+ 1,
+ 1,
+ );
+ });
- it("test moving right when right is undefined", () => {
- moveLexicographicallyTest(
- ["50", undefined, undefined, undefined, undefined, /**/ undefined, undefined],
- 1,
- 4,
- 4,
- );
- });
+ it("should work moving right when right is defined", () => {
+ moveLexicographicallyTest(
+ ["10", "20", "30", "40", "50", undefined],
+ 1,
+ 3,
+ 1,
+ );
+ });
- it("test moving left when right is defined", () => {
- moveLexicographicallyTest(
- ["10", "20", "30", "40", undefined, undefined],
- 3,
- 1,
- 1,
- );
- });
+ it("should work moving left when all is defined", () => {
+ moveLexicographicallyTest(
+ ["11", "13", "15", "17", "19"],
+ 2,
+ 1,
+ 1,
+ );
+ });
- it("test moving right when right is defined", () => {
- moveLexicographicallyTest(
- ["10", "20", "30", "40", "50", undefined],
- 1,
- 3,
- 1,
- );
- });
+ it("should work moving right when all is defined", () => {
+ moveLexicographicallyTest(
+ ["11", "13", "15", "17", "19"],
+ 1,
+ 2,
+ 1,
+ );
+ });
- it("test moving left when all is defined", () => {
- moveLexicographicallyTest(
- ["11", "13", "15", "17", "19"],
- 2,
- 1,
- 1,
- );
- });
+ it("should work moving left into no left space", () => {
+ moveLexicographicallyTest(
+ ["11", "12", "13", "14", "19"],
+ 3,
+ 1,
+ 2,
+ 2,
+ );
- it("test moving right when all is defined", () => {
- moveLexicographicallyTest(
- ["11", "13", "15", "17", "19"],
- 1,
- 2,
- 1,
- );
- });
+ moveLexicographicallyTest(
+ [
+ DEFAULT_ALPHABET.charAt(0),
+ // Target
+ DEFAULT_ALPHABET.charAt(1),
+ DEFAULT_ALPHABET.charAt(2),
+ DEFAULT_ALPHABET.charAt(3),
+ DEFAULT_ALPHABET.charAt(4),
+ DEFAULT_ALPHABET.charAt(5),
+ ],
+ 5,
+ 1,
+ 5,
+ 1,
+ );
+ });
- it("test moving left into no left space", () => {
- moveLexicographicallyTest(
- ["11", "12", "13", "14", "19"],
- 3,
- 1,
- 2,
- 2,
- );
+ it("should work moving right into no right space", () => {
+ moveLexicographicallyTest(
+ ["15", "16", "17", "18", "19"],
+ 1,
+ 3,
+ 3,
+ 2,
+ );
- moveLexicographicallyTest(
- [
- DEFAULT_ALPHABET.charAt(0),
- // Target
- DEFAULT_ALPHABET.charAt(1),
- DEFAULT_ALPHABET.charAt(2),
- DEFAULT_ALPHABET.charAt(3),
- DEFAULT_ALPHABET.charAt(4),
- DEFAULT_ALPHABET.charAt(5),
- ],
- 5,
- 1,
- 5,
- 1,
- );
- });
+ moveLexicographicallyTest(
+ [
+ DEFAULT_ALPHABET.charAt(DEFAULT_ALPHABET.length - 5),
+ DEFAULT_ALPHABET.charAt(DEFAULT_ALPHABET.length - 4),
+ DEFAULT_ALPHABET.charAt(DEFAULT_ALPHABET.length - 3),
+ DEFAULT_ALPHABET.charAt(DEFAULT_ALPHABET.length - 2),
+ DEFAULT_ALPHABET.charAt(DEFAULT_ALPHABET.length - 1),
+ ],
+ 1,
+ 3,
+ 3,
+ 1,
+ );
+ });
- it("test moving right into no right space", () => {
- moveLexicographicallyTest(
- ["15", "16", "17", "18", "19"],
- 1,
- 3,
- 3,
- 2,
- );
+ it("should work moving right into no left space", () => {
+ moveLexicographicallyTest(
+ ["11", "12", "13", "14", "15", "16", undefined],
+ 1,
+ 3,
+ 3,
+ );
- moveLexicographicallyTest(
- [
- DEFAULT_ALPHABET.charAt(DEFAULT_ALPHABET.length - 5),
- DEFAULT_ALPHABET.charAt(DEFAULT_ALPHABET.length - 4),
- DEFAULT_ALPHABET.charAt(DEFAULT_ALPHABET.length - 3),
- DEFAULT_ALPHABET.charAt(DEFAULT_ALPHABET.length - 2),
- DEFAULT_ALPHABET.charAt(DEFAULT_ALPHABET.length - 1),
- ],
- 1,
- 3,
- 3,
- 1,
- );
- });
+ moveLexicographicallyTest(
+ ["0", "1", "2", "3", "4", "5"],
+ 1,
+ 3,
+ 3,
+ 1,
+ );
+ });
- it("test moving right into no left space", () => {
- moveLexicographicallyTest(
- ["11", "12", "13", "14", "15", "16", undefined],
- 1,
- 3,
- 3,
- );
+ it("should work moving left into no right space", () => {
+ moveLexicographicallyTest(
+ ["15", "16", "17", "18", "19"],
+ 4,
+ 3,
+ 4,
+ 2,
+ );
- moveLexicographicallyTest(
- ["0", "1", "2", "3", "4", "5"],
- 1,
- 3,
- 3,
- 1,
- );
- });
-
- it("test moving left into no right space", () => {
- moveLexicographicallyTest(
- ["15", "16", "17", "18", "19"],
- 4,
- 3,
- 4,
- 2,
- );
-
- moveLexicographicallyTest(
- [
- DEFAULT_ALPHABET.charAt(DEFAULT_ALPHABET.length - 5),
- DEFAULT_ALPHABET.charAt(DEFAULT_ALPHABET.length - 4),
- DEFAULT_ALPHABET.charAt(DEFAULT_ALPHABET.length - 3),
- DEFAULT_ALPHABET.charAt(DEFAULT_ALPHABET.length - 2),
- DEFAULT_ALPHABET.charAt(DEFAULT_ALPHABET.length - 1),
- ],
- 4,
- 3,
- 4,
- 1,
- );
- });
-
- const prev = (str: string) => baseToString(stringToBase(str) - BigInt(1));
- const next = (str: string) => baseToString(stringToBase(str) + BigInt(1));
-
- it("baseN calculation is correctly consecutive", () => {
- const str = "this-is-a-test";
- expect(next(prev(str))).toBe(str);
- });
-
- it("rolls over sanely", () => {
- const maxSpaceValue = "~".repeat(50);
- const fiftyFirstChar = " ".repeat(51);
- expect(next(maxSpaceValue)).toBe(fiftyFirstChar);
- expect(prev(fiftyFirstChar)).toBe(maxSpaceValue);
- expect(Number(stringToBase(DEFAULT_ALPHABET[0]))).toEqual(1);
- expect(Number(stringToBase(DEFAULT_ALPHABET[1]))).toEqual(2);
- expect(DEFAULT_ALPHABET[DEFAULT_ALPHABET.length - 1]).toBe("~");
- expect(DEFAULT_ALPHABET[0]).toBe(" ");
+ moveLexicographicallyTest(
+ [
+ DEFAULT_ALPHABET.charAt(DEFAULT_ALPHABET.length - 5),
+ DEFAULT_ALPHABET.charAt(DEFAULT_ALPHABET.length - 4),
+ DEFAULT_ALPHABET.charAt(DEFAULT_ALPHABET.length - 3),
+ DEFAULT_ALPHABET.charAt(DEFAULT_ALPHABET.length - 2),
+ DEFAULT_ALPHABET.charAt(DEFAULT_ALPHABET.length - 1),
+ ],
+ 4,
+ 3,
+ 4,
+ 1,
+ );
+ });
});
});
From d4e376201f986223c16932229598c7e45a032c82 Mon Sep 17 00:00:00 2001
From: Michael Telatynski <7t3chguy@gmail.com>
Date: Wed, 16 Jun 2021 09:44:37 +0100
Subject: [PATCH 075/151] Break down the SpacePanel component
---
src/components/views/spaces/SpacePanel.tsx | 134 ++++++++++++---------
1 file changed, 76 insertions(+), 58 deletions(-)
diff --git a/src/components/views/spaces/SpacePanel.tsx b/src/components/views/spaces/SpacePanel.tsx
index 27f097e9d4..2e3bfd157a 100644
--- a/src/components/views/spaces/SpacePanel.tsx
+++ b/src/components/views/spaces/SpacePanel.tsx
@@ -14,18 +14,18 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-import React, { useEffect, useState } from "react";
+import React, { Dispatch, ReactNode, SetStateAction, useEffect, useState } from "react";
import { DragDropContext, Droppable, Draggable } from "react-beautiful-dnd";
import classNames from "classnames";
import { Room } from "matrix-js-sdk/src/models/room";
-import {_t} from "../../../languageHandler";
+import { _t } from "../../../languageHandler";
import RoomAvatar from "../avatars/RoomAvatar";
-import {useContextMenu} from "../../structures/ContextMenu";
+import { useContextMenu } from "../../structures/ContextMenu";
import SpaceCreateMenu from "./SpaceCreateMenu";
-import {SpaceItem} from "./SpaceTreeLevel";
+import { SpaceItem } from "./SpaceTreeLevel";
import AccessibleTooltipButton from "../elements/AccessibleTooltipButton";
-import {useEventEmitter} from "../../../hooks/useEventEmitter";
+import { useEventEmitter } from "../../../hooks/useEventEmitter";
import SpaceStore, {
UPDATE_INVITED_SPACES,
UPDATE_SELECTED_SPACE,
@@ -38,9 +38,9 @@ import {
RovingAccessibleTooltipButton,
RovingTabIndexProvider,
} from "../../../accessibility/RovingTabIndex";
-import {Key} from "../../../Keyboard";
-import {RoomNotificationStateStore} from "../../../stores/notifications/RoomNotificationStateStore";
-import {NotificationState} from "../../../stores/notifications/NotificationState";
+import { Key } from "../../../Keyboard";
+import { RoomNotificationStateStore } from "../../../stores/notifications/RoomNotificationStateStore";
+import { NotificationState } from "../../../stores/notifications/NotificationState";
interface IButtonProps {
space?: Room;
@@ -121,11 +121,62 @@ const useSpaces = (): [Room[], Room[], Room | null] => {
return [invites, spaces, activeSpace];
};
+interface IInnerSpacePanelProps {
+ children?: ReactNode;
+ isPanelCollapsed: boolean;
+ setPanelCollapsed: Dispatch>;
+}
+
+// Optimisation based on https://github.com/atlassian/react-beautiful-dnd/blob/master/docs/api/droppable.md#recommended-droppable--performance-optimisation
+const InnerSpacePanel = React.memo(({ children, isPanelCollapsed, setPanelCollapsed }) => {
+ const [invites, spaces, activeSpace] = useSpaces();
+ const activeSpaces = activeSpace ? [activeSpace] : [];
+
+ return
+ SpaceStore.instance.setActiveSpace(null)}
+ selected={!activeSpace}
+ tooltip={_t("All rooms")}
+ notificationState={RoomNotificationStateStore.instance.globalState}
+ isNarrow={isPanelCollapsed}
+ />
+ { invites.map(s => (
+ setPanelCollapsed(false)}
+ />
+ )) }
+ { spaces.map((s, i) => (
+
+ {(provided, snapshot) => (
+ setPanelCollapsed(false)}
+ />
+ )}
+
+ )) }
+ { children }
+
;
+});
+
const SpacePanel = () => {
// We don't need the handle as we position the menu in a constant location
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const [menuDisplayed, handle, openMenu, closeMenu] = useContextMenu();
- const [invites, spaces, activeSpace] = useSpaces();
const [isPanelCollapsed, setPanelCollapsed] = useState(true);
useEffect(() => {
@@ -134,10 +185,6 @@ const SpacePanel = () => {
}
}, [isPanelCollapsed]); // eslint-disable-line react-hooks/exhaustive-deps
- const newClasses = classNames("mx_SpaceButton_new", {
- mx_SpaceButton_newCancel: menuDisplayed,
- });
-
let contextMenu = null;
if (menuDisplayed) {
contextMenu = ;
@@ -204,7 +251,11 @@ const SpacePanel = () => {
}
};
- const activeSpaces = activeSpace ? [activeSpace] : [];
+ const onNewClick = menuDisplayed ? closeMenu : () => {
+ if (!isPanelCollapsed) setPanelCollapsed(true);
+ openMenu();
+ };
+
return (
{
if (!result.destination) return; // dropped outside the list
@@ -226,59 +277,26 @@ const SpacePanel = () => {
pointerEvents: "none",
} : undefined}
>
-
- SpaceStore.instance.setActiveSpace(null)}
- selected={!activeSpace}
- tooltip={_t("All rooms")}
- notificationState={RoomNotificationStateStore.instance.globalState}
- isNarrow={isPanelCollapsed}
- />
- { invites.map(s => (
- setPanelCollapsed(false)}
- />
- )) }
- { spaces.map((s, i) => (
-
- {(provided, snapshot) => (
- setPanelCollapsed(false)}
- />
- )}
-
- )) }
+
{ provided.placeholder }
-
+
+
{
- if (!isPanelCollapsed) setPanelCollapsed(true);
- openMenu();
- }}
+ onClick={onNewClick}
isNarrow={isPanelCollapsed}
/>
)}
setPanelCollapsed(!isPanelCollapsed)}
title={isPanelCollapsed ? _t("Expand space panel") : _t("Collapse space panel")}
/>
From e7fde2686f43da4b9e680eb12ba8b4054f903d8d Mon Sep 17 00:00:00 2001
From: Michael Telatynski <7t3chguy@gmail.com>
Date: Wed, 16 Jun 2021 12:12:00 +0100
Subject: [PATCH 076/151] remove unused imports
---
test/utils/stringOrderField-test.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/test/utils/stringOrderField-test.ts b/test/utils/stringOrderField-test.ts
index ece3043d86..331627dfc0 100644
--- a/test/utils/stringOrderField-test.ts
+++ b/test/utils/stringOrderField-test.ts
@@ -15,7 +15,7 @@ limitations under the License.
*/
import { sortBy } from "lodash";
-import { stringToBase, baseToString, averageBetweenStrings, DEFAULT_ALPHABET } from "matrix-js-sdk/src/utils";
+import { averageBetweenStrings, DEFAULT_ALPHABET } from "matrix-js-sdk/src/utils";
import { midPointsBetweenStrings, reorderLexicographically } from "../../src/utils/stringOrderField";
From 79bf7bee560856be766493cd1a6dda8043bbe932 Mon Sep 17 00:00:00 2001
From: Robin Townsend
Date: Wed, 16 Jun 2021 18:23:44 -0400
Subject: [PATCH 077/151] Fix EventTilePreview display names
Because of 91df392a2a79383fa9a8a35cc9e4def6d3d4caab, we now need to
additionally set rawDisplayName to properly fake our display name for an
event.
Signed-off-by: Robin Townsend
---
src/components/views/elements/EventTilePreview.tsx | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/components/views/elements/EventTilePreview.tsx b/src/components/views/elements/EventTilePreview.tsx
index 20d6cbaeb3..d39557c9bb 100644
--- a/src/components/views/elements/EventTilePreview.tsx
+++ b/src/components/views/elements/EventTilePreview.tsx
@@ -102,6 +102,7 @@ export default class EventTilePreview extends React.Component {
// Fake it more
event.sender = {
name: this.props.displayName || this.props.userId,
+ rawDisplayName: this.props.displayName,
userId: this.props.userId,
getAvatarUrl: (..._) => {
return Avatar.avatarUrlForUser(
From 7c6161d83ad60df8e332656ca0389ce90797ec3e Mon Sep 17 00:00:00 2001
From: "J. Ryan Stinnett"
Date: Wed, 16 Jun 2021 18:00:06 +0100
Subject: [PATCH 078/151] 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 079/151] 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 080/151] 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 7d90612371a31f699d879366262f84fd1082bd9b Mon Sep 17 00:00:00 2001
From: Michael Telatynski <7t3chguy@gmail.com>
Date: Thu, 17 Jun 2021 16:22:40 +0100
Subject: [PATCH 081/151] Iterate PR
---
res/css/views/beta/_BetaCard.scss | 93 +++++++++++--------
src/components/views/beta/BetaCard.tsx | 49 +++++-----
.../views/elements/SettingsFlag.tsx | 10 +-
src/i18n/strings/en_EN.json | 8 +-
src/settings/Settings.tsx | 11 ++-
src/settings/SettingsStore.ts | 10 ++
6 files changed, 107 insertions(+), 74 deletions(-)
diff --git a/res/css/views/beta/_BetaCard.scss b/res/css/views/beta/_BetaCard.scss
index fd87b1c824..1a8241b65f 100644
--- a/res/css/views/beta/_BetaCard.scss
+++ b/res/css/views/beta/_BetaCard.scss
@@ -19,55 +19,68 @@ limitations under the License.
padding: 24px;
background-color: $settings-profile-placeholder-bg-color;
border-radius: 8px;
- display: flex;
box-sizing: border-box;
- > div {
- .mx_BetaCard_title {
- font-weight: $font-semi-bold;
- font-size: $font-18px;
- line-height: $font-22px;
- color: $primary-fg-color;
- margin: 4px 0 14px;
+ .mx_BetaCard_columns {
+ display: flex;
- .mx_BetaCard_betaPill {
- margin-left: 12px;
+ > div {
+ .mx_BetaCard_title {
+ font-weight: $font-semi-bold;
+ font-size: $font-18px;
+ line-height: $font-22px;
+ color: $primary-fg-color;
+ margin: 4px 0 14px;
+
+ .mx_BetaCard_betaPill {
+ margin-left: 12px;
+ }
+ }
+
+ .mx_BetaCard_caption {
+ font-size: $font-15px;
+ line-height: $font-20px;
+ color: $secondary-fg-color;
+ margin-bottom: 20px;
+ }
+
+ .mx_BetaCard_buttons .mx_AccessibleButton {
+ display: block;
+ margin: 12px 0;
+ padding: 7px 40px;
+ width: auto;
+ }
+
+ .mx_BetaCard_disclaimer {
+ font-size: $font-12px;
+ line-height: $font-15px;
+ color: $secondary-fg-color;
+ margin-top: 20px;
}
}
- .mx_BetaCard_caption {
- font-size: $font-15px;
- line-height: $font-20px;
- color: $secondary-fg-color;
- margin-bottom: 20px;
- }
-
- .mx_BetaCard_buttons .mx_AccessibleButton {
- display: block;
- margin: 12px 0;
- padding: 7px 40px;
- width: auto;
- }
-
- .mx_BetaCard_disclaimer {
- font-size: $font-12px;
- line-height: $font-15px;
- color: $secondary-fg-color;
- margin-top: 20px;
- }
-
- .mx_BetaCard_relatedSettings {
- summary + .mx_SettingsFlag {
- margin-top: 4px;
- }
+ > img {
+ margin: auto 0 auto 20px;
+ width: 300px;
+ object-fit: contain;
+ height: 100%;
}
}
- > img {
- margin: auto 0 auto 20px;
- width: 300px;
- object-fit: contain;
- height: 100%;
+ .mx_BetaCard_relatedSettings {
+ .mx_SettingsFlag {
+ margin: 16px 0 0;
+ font-size: $font-15px;
+ line-height: $font-24px;
+ color: $primary-fg-color;
+
+ .mx_SettingsFlag_microcopy {
+ margin-top: 4px;
+ font-size: $font-12px;
+ line-height: $font-15px;
+ color: $secondary-fg-color;
+ }
+ }
}
}
diff --git a/src/components/views/beta/BetaCard.tsx b/src/components/views/beta/BetaCard.tsx
index 56770c3385..aa4fe49f63 100644
--- a/src/components/views/beta/BetaCard.tsx
+++ b/src/components/views/beta/BetaCard.tsx
@@ -83,32 +83,33 @@ const BetaCard = ({ title: titleOverride, featureId }: IProps) => {
}
return
-
-
- { titleOverride || _t(title) }
-
-
-
{ _t(caption) }
-
- { feedbackButton }
-
SettingsStore.setValue(featureId, null, SettingLevel.DEVICE, !value)}
- kind={feedbackButton ? "primary_outline" : "primary"}
- >
- { value ? _t("Leave the beta") : _t("Join the beta") }
-
+
+
+
+ { titleOverride || _t(title) }
+
+
+
{ _t(caption) }
+
+ { feedbackButton }
+
SettingsStore.setValue(featureId, null, SettingLevel.DEVICE, !value)}
+ kind={feedbackButton ? "primary_outline" : "primary"}
+ >
+ { value ? _t("Leave the beta") : _t("Join the beta") }
+
+
+ { disclaimer &&
+ { disclaimer(value) }
+
}
- { disclaimer &&
- { disclaimer(value) }
-
}
- { extraSettings &&
- { _t("Experimental options") }
- { extraSettings.map(key => (
-
- )) }
- }
+
-
+ { extraSettings &&
+ { extraSettings.map(key => (
+
+ )) }
+
}
;
};
diff --git a/src/components/views/elements/SettingsFlag.tsx b/src/components/views/elements/SettingsFlag.tsx
index 4f885ab47d..24a21e1a33 100644
--- a/src/components/views/elements/SettingsFlag.tsx
+++ b/src/components/views/elements/SettingsFlag.tsx
@@ -77,9 +77,10 @@ export default class SettingsFlag extends React.Component
{
public render() {
const canChange = SettingsStore.canSetValue(this.props.name, this.props.roomId, this.props.level);
- let label = this.props.label;
- if (!label) label = SettingsStore.getDisplayName(this.props.name, this.props.level);
- else label = _t(label);
+ const label = this.props.label
+ ? _t(this.props.label)
+ : SettingsStore.getDisplayName(this.props.name, this.props.level);
+ const description = SettingsStore.getDescription(this.props.name);
if (this.props.useCheckbox) {
return {
disabled={this.props.disabled || !canChange}
aria-label={label}
/>
+ { description &&
+ { description }
+
}
);
}
diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json
index 044e3a3079..179b58b617 100644
--- a/src/i18n/strings/en_EN.json
+++ b/src/i18n/strings/en_EN.json
@@ -793,9 +793,10 @@
"You can leave the beta any time from settings or tapping on a beta badge, like the one above.": "You can leave the beta any time from settings or tapping on a beta badge, like the one above.",
"Beta available for web, desktop and Android. Some features may be unavailable on your homeserver.": "Beta available for web, desktop and Android. Some features may be unavailable on your homeserver.",
"Your feedback will help make spaces better. The more detail you can go into, the better.": "Your feedback will help make spaces better. The more detail you can go into, the better.",
- "Use an all rooms space instead of a home space.": "Use an all rooms space instead of a home space.",
- "Show DMs for joined/invited members in the space.": "Show DMs for joined/invited members in the space.",
- "Show notification badges for DMs in spaces.": "Show notification badges for DMs in spaces.",
+ "Show all rooms in Home": "Show all rooms in Home",
+ "Show people in spaces": "Show people in spaces",
+ "If disabled, you can still add Direct Messages to Personal Spaces. If enabled, you'll automatically see everyone who is a member of the Space.": "If disabled, you can still add Direct Messages to Personal Spaces. If enabled, you'll automatically see everyone who is a member of the Space.",
+ "Show notification badges for DMs in Spaces.": "Show notification badges for DMs in Spaces.",
"Show options to enable 'Do not disturb' mode": "Show options to enable 'Do not disturb' mode",
"Send and receive voice messages": "Send and receive voice messages",
"Render LaTeX maths in messages": "Render LaTeX maths in messages",
@@ -2510,7 +2511,6 @@
"Beta": "Beta",
"Leave the beta": "Leave the beta",
"Join the beta": "Join the beta",
- "Experimental options": "Experimental options",
"Avatar": "Avatar",
"This room is public": "This room is public",
"Away": "Away",
diff --git a/src/settings/Settings.tsx b/src/settings/Settings.tsx
index a291cd1fba..af026f4103 100644
--- a/src/settings/Settings.tsx
+++ b/src/settings/Settings.tsx
@@ -94,6 +94,9 @@ export interface ISetting {
[level: SettingLevel]: string;
};
+ // Optional description which will be shown as microCopy under SettingsFlags
+ description?: string;
+
// The supported levels are required. Preferably, use the preset arrays
// at the top of this file to define this rather than a custom array.
supportedLevels?: SettingLevel[];
@@ -176,19 +179,21 @@ export const SETTINGS: {[setting: string]: ISetting} = {
},
},
"feature_spaces.all_rooms": {
- displayName: _td("Use an all rooms space instead of a home space."),
+ displayName: _td("Show all rooms in Home"),
supportedLevels: LEVELS_FEATURE,
default: true,
controller: new ReloadOnChangeController(),
},
"feature_spaces.space_member_dms": {
- displayName: _td("Show DMs for joined/invited members in the space."),
+ displayName: _td("Show people in spaces"),
+ description: _td("If disabled, you can still add Direct Messages to Personal Spaces. " +
+ "If enabled, you'll automatically see everyone who is a member of the Space."),
supportedLevels: LEVELS_FEATURE,
default: true,
controller: new ReloadOnChangeController(),
},
"feature_spaces.space_dm_badges": {
- displayName: _td("Show notification badges for DMs in spaces."),
+ displayName: _td("Show notification badges for DMs in Spaces."),
supportedLevels: LEVELS_FEATURE,
default: false,
controller: new ReloadOnChangeController(),
diff --git a/src/settings/SettingsStore.ts b/src/settings/SettingsStore.ts
index e1e300e185..44f3d5d838 100644
--- a/src/settings/SettingsStore.ts
+++ b/src/settings/SettingsStore.ts
@@ -248,6 +248,16 @@ export default class SettingsStore {
return _t(displayName as string);
}
+ /**
+ * Gets the translated description for a given setting
+ * @param {string} settingName The setting to look up.
+ * @return {String} The description for the setting, or null if not found.
+ */
+ public static getDescription(settingName: string) {
+ if (!SETTINGS[settingName]?.description) return null;
+ return _t(SETTINGS[settingName].description);
+ }
+
/**
* Determines if a setting is also a feature.
* @param {string} settingName The setting to look up.
From a687391b98d638e69983e5d814bcb73bfe52a381 Mon Sep 17 00:00:00 2001
From: Travis Ralston
Date: Thu, 17 Jun 2021 14:21:01 -0600
Subject: [PATCH 082/151] 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 083/151] 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 084/151] 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 085/151] 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 086/151] 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 {