Merge remote-tracking branch 'upstream/develop' into reorganize-preferences

This commit is contained in:
Šimon Brandner 2021-07-01 18:53:53 +02:00
commit e355bf0db1
No known key found for this signature in database
GPG key ID: 9760693FDD98A790
838 changed files with 21747 additions and 13629 deletions

View file

@ -14,13 +14,13 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import React, {useState} from "react";
import React, { useState } from "react";
import PropTypes from "prop-types";
import {_t} from "../../../languageHandler";
import { _t } from "../../../languageHandler";
import AccessibleButton from "../elements/AccessibleButton";
import classNames from "classnames";
const AvatarSetting = ({avatarUrl, avatarAltText, avatarName, uploadAvatar, removeAvatar}) => {
const AvatarSetting = ({ avatarUrl, avatarAltText, avatarName, uploadAvatar, removeAvatar }) => {
const [isHovering, setIsHovering] = useState(false);
const hoveringProps = {
onMouseEnter: () => setIsHovering(true),

View file

@ -16,16 +16,16 @@ limitations under the License.
import React from 'react';
import PropTypes from 'prop-types';
import {_t} from "../../../languageHandler";
import { _t } from "../../../languageHandler";
import Pill from "../elements/Pill";
import {makeUserPermalink} from "../../../utils/permalinks/Permalinks";
import { makeUserPermalink } from "../../../utils/permalinks/Permalinks";
import BaseAvatar from "../avatars/BaseAvatar";
import SettingsStore from "../../../settings/SettingsStore";
import {MatrixEvent} from "matrix-js-sdk/src/models/event";
import { MatrixEvent } from "matrix-js-sdk/src/models/event";
import { Room } from "matrix-js-sdk/src/models/room";
import { isUrlPermitted } from '../../../HtmlUtils';
import {replaceableComponent} from "../../../utils/replaceableComponent";
import {mediaFromMxc} from "../../../customisations/Media";
import { replaceableComponent } from "../../../utils/replaceableComponent";
import { mediaFromMxc } from "../../../customisations/Media";
interface IProps {
ev: MatrixEvent;
@ -69,7 +69,7 @@ export default class BridgeTile extends React.PureComponent<IProps> {
static propTypes = {
ev: PropTypes.object.isRequired,
room: PropTypes.object.isRequired,
}
};
render() {
const content: IBridgeStateEvent = this.props.ev.getContent();
@ -131,7 +131,9 @@ export default class BridgeTile extends React.PureComponent<IProps> {
const networkName = network.displayname || network.id;
let networkLink = <span>{networkName}</span>;
if (typeof network.external_url === "string" && isUrlPermitted(network.external_url)) {
networkLink = <a href={network.external_url} target="_blank" rel="noreferrer noopener">{networkName}</a>
networkLink = (
<a href={network.external_url} target="_blank" rel="noreferrer noopener">{networkName}</a>
);
}
networkItem = _t("Workspace: <networkLink/>", {}, {
networkLink: () => networkLink,
@ -140,7 +142,7 @@ export default class BridgeTile extends React.PureComponent<IProps> {
let channelLink = <span>{channelName}</span>;
if (typeof channel.external_url === "string" && isUrlPermitted(channel.external_url)) {
channelLink = <a href={channel.external_url} target="_blank" rel="noreferrer noopener">{channelName}</a>
channelLink = <a href={channel.external_url} target="_blank" rel="noreferrer noopener">{channelName}</a>;
}
const id = this.props.ev.getId();

View file

@ -16,12 +16,12 @@ limitations under the License.
import React from 'react';
import PropTypes from 'prop-types';
import {MatrixClientPeg} from "../../../MatrixClientPeg";
import { MatrixClientPeg } from "../../../MatrixClientPeg";
import * as sdk from '../../../index';
import { _t } from '../../../languageHandler';
import Spinner from '../elements/Spinner';
import {replaceableComponent} from "../../../utils/replaceableComponent";
import {mediaFromMxc} from "../../../customisations/Media";
import { replaceableComponent } from "../../../utils/replaceableComponent";
import { mediaFromMxc } from "../../../customisations/Media";
@replaceableComponent("views.settings.ChangeAvatar")
export default class ChangeAvatar extends React.Component {
@ -107,7 +107,7 @@ export default class ChangeAvatar extends React.Component {
return MatrixClientPeg.get().sendStateEvent(
self.props.room.roomId,
'm.room.avatar',
{url: url},
{ url: url },
'',
);
} else {

View file

@ -18,9 +18,9 @@ limitations under the License.
import React from 'react';
import * as sdk from '../../../index';
import {MatrixClientPeg} from '../../../MatrixClientPeg';
import { MatrixClientPeg } from '../../../MatrixClientPeg';
import { _t } from '../../../languageHandler';
import {replaceableComponent} from "../../../utils/replaceableComponent";
import { replaceableComponent } from "../../../utils/replaceableComponent";
@replaceableComponent("views.settings.ChangeDisplayName")
export default class ChangeDisplayName extends React.Component {

View file

@ -18,7 +18,7 @@ limitations under the License.
import Field from "../elements/Field";
import React from 'react';
import PropTypes from 'prop-types';
import {MatrixClientPeg} from "../../../MatrixClientPeg";
import { MatrixClientPeg } from "../../../MatrixClientPeg";
import AccessibleButton from '../elements/AccessibleButton';
import Spinner from '../elements/Spinner';
import withValidation from '../elements/Validation';
@ -27,7 +27,7 @@ import * as sdk from "../../../index";
import Modal from "../../../Modal";
import PassphraseField from "../auth/PassphraseField";
import CountlyAnalytics from "../../../CountlyAnalytics";
import {replaceableComponent} from "../../../utils/replaceableComponent";
import { replaceableComponent } from "../../../utils/replaceableComponent";
import { PASSWORD_MIN_SCORE } from '../auth/RegistrationForm';
const FIELD_OLD_PASSWORD = 'field_old_password';

View file

@ -16,14 +16,14 @@ limitations under the License.
import React from 'react';
import {MatrixClientPeg} from '../../../MatrixClientPeg';
import { MatrixClientPeg } from '../../../MatrixClientPeg';
import { _t } from '../../../languageHandler';
import * as sdk from '../../../index';
import Modal from '../../../Modal';
import Spinner from '../elements/Spinner';
import InteractiveAuthDialog from '../dialogs/InteractiveAuthDialog';
import ConfirmDestroyCrossSigningDialog from '../dialogs/security/ConfirmDestroyCrossSigningDialog';
import {replaceableComponent} from "../../../utils/replaceableComponent";
import { replaceableComponent } from "../../../utils/replaceableComponent";
@replaceableComponent("views.settings.CrossSigningPanel")
export default class CrossSigningPanel extends React.PureComponent {
@ -79,8 +79,8 @@ export default class CrossSigningPanel extends React.PureComponent {
async _getUpdatedStatus() {
const cli = MatrixClientPeg.get();
const pkCache = cli.getCrossSigningCacheCallbacks();
const crossSigning = cli._crypto._crossSigningInfo;
const secretStorage = cli._crypto._secretStorage;
const crossSigning = cli.crypto.crossSigningInfo;
const secretStorage = cli.crypto.secretStorage;
const crossSigningPublicKeysOnDevice = crossSigning.getId();
const crossSigningPrivateKeysInStorage = await crossSigning.isStoredInSecretStorage(secretStorage);
const masterPrivateKeyCached = !!(pkCache && await pkCache.getCrossSigningKeyCache("master"));

View file

@ -20,11 +20,11 @@ import PropTypes from 'prop-types';
import classNames from 'classnames';
import * as sdk from '../../../index';
import {MatrixClientPeg} from '../../../MatrixClientPeg';
import { MatrixClientPeg } from '../../../MatrixClientPeg';
import { _t } from '../../../languageHandler';
import Modal from '../../../Modal';
import {SSOAuthEntry} from "../auth/InteractiveAuthEntryComponents";
import {replaceableComponent} from "../../../utils/replaceableComponent";
import { SSOAuthEntry } from "../auth/InteractiveAuthEntryComponents";
import { replaceableComponent } from "../../../utils/replaceableComponent";
@replaceableComponent("views.settings.DevicesPanel")
export default class DevicesPanel extends React.Component {
@ -58,7 +58,7 @@ export default class DevicesPanel extends React.Component {
MatrixClientPeg.get().getDevices().then(
(resp) => {
if (this._unmounted) { return; }
this.setState({devices: resp.devices || []});
this.setState({ devices: resp.devices || [] });
},
(error) => {
if (this._unmounted) { return; }
@ -70,12 +70,11 @@ export default class DevicesPanel extends React.Component {
console.error("Error loading sessions:", error);
errtxt = _t("Unable to load session list");
}
this.setState({deviceLoadError: errtxt});
this.setState({ deviceLoadError: errtxt });
},
);
}
/*
* compare two devices, sorting from most-recently-seen to least-recently-seen
* (and then, for stability, by device id)
@ -107,7 +106,7 @@ export default class DevicesPanel extends React.Component {
selectedDevices.splice(i, 1);
}
return {selectedDevices};
return { selectedDevices };
});
}
@ -141,7 +140,7 @@ export default class DevicesPanel extends React.Component {
body: _t("Click the button below to confirm deleting these sessions.", {
count: numDevices,
}),
continueText: _t("Delete sessions", {count: numDevices}),
continueText: _t("Delete sessions", { count: numDevices }),
continueKind: "danger",
},
};
@ -214,7 +213,7 @@ export default class DevicesPanel extends React.Component {
const deleteButton = this.state.deleting ?
<Spinner w={22} h={22} /> :
<AccessibleButton onClick={this._onDeleteClick} kind="danger_sm">
{ _t("Delete %(count)s sessions", {count: this.state.selectedDevices.length})}
{ _t("Delete %(count)s sessions", { count: this.state.selectedDevices.length })}
</AccessibleButton>;
const classes = classNames(this.props.className, "mx_DevicesPanel");

View file

@ -19,10 +19,10 @@ import PropTypes from 'prop-types';
import * as sdk from '../../../index';
import { _t } from '../../../languageHandler';
import {MatrixClientPeg} from '../../../MatrixClientPeg';
import {formatDate} from '../../../DateUtils';
import { MatrixClientPeg } from '../../../MatrixClientPeg';
import { formatDate } from '../../../DateUtils';
import StyledCheckbox from '../elements/StyledCheckbox';
import {replaceableComponent} from "../../../utils/replaceableComponent";
import { replaceableComponent } from "../../../utils/replaceableComponent";
@replaceableComponent("views.settings.DevicesPanelEntry")
export default class DevicesPanelEntry extends React.Component {

View file

@ -17,8 +17,8 @@ limitations under the License.
import React from 'react';
import * as sdk from '../../../index';
import {_t} from "../../../languageHandler";
import {SettingLevel} from "../../../settings/SettingLevel";
import { _t } from "../../../languageHandler";
import { SettingLevel } from "../../../settings/SettingLevel";
import SettingsStore from "../../../settings/SettingsStore";
const SETTING_MANUALLY_VERIFY_ALL_SESSIONS = "e2ee.manuallyVerifyAllSessions";

View file

@ -22,10 +22,10 @@ import * as sdk from '../../../index';
import Modal from '../../../Modal';
import SettingsStore from "../../../settings/SettingsStore";
import AccessibleButton from "../elements/AccessibleButton";
import {formatBytes, formatCountLong} from "../../../utils/FormattingUtils";
import { formatBytes, formatCountLong } from "../../../utils/FormattingUtils";
import EventIndexPeg from "../../../indexing/EventIndexPeg";
import {SettingLevel} from "../../../settings/SettingLevel";
import {replaceableComponent} from "../../../utils/replaceableComponent";
import { SettingLevel } from "../../../settings/SettingLevel";
import { replaceableComponent } from "../../../utils/replaceableComponent";
import SeshatResetDialog from '../dialogs/SeshatResetDialog';
interface IState {
@ -118,7 +118,7 @@ export default class EventIndexPanel extends React.Component<{}, IState> {
onFinished: () => {},
}, null, /* priority = */ false, /* static = */ true,
);
}
};
private onEnable = async () => {
this.setState({
@ -130,7 +130,7 @@ export default class EventIndexPanel extends React.Component<{}, IState> {
await EventIndexPeg.get().startCrawler();
await SettingsStore.setValue('enableEventIndexing', null, SettingLevel.DEVICE, true);
await this.updateState();
}
};
private confirmEventStoreReset = () => {
const { close } = Modal.createDialog(SeshatResetDialog, {
@ -143,7 +143,7 @@ export default class EventIndexPanel extends React.Component<{}, IState> {
}
},
});
}
};
render() {
let eventIndexingSettings = null;

View file

@ -20,8 +20,8 @@ import PropTypes from 'prop-types';
import * as sdk from '../../../index';
import { _t } from '../../../languageHandler';
import dis from '../../../dispatcher/dispatcher';
import {Key} from "../../../Keyboard";
import {replaceableComponent} from "../../../utils/replaceableComponent";
import { Key } from "../../../Keyboard";
import { replaceableComponent } from "../../../utils/replaceableComponent";
@replaceableComponent("views.settings.IntegrationManager")
export default class IntegrationManager extends React.Component {

View file

@ -18,7 +18,7 @@ limitations under the License.
import React from 'react';
import * as sdk from '../../../index';
import { _t } from '../../../languageHandler';
import {MatrixClientPeg} from '../../../MatrixClientPeg';
import { MatrixClientPeg } from '../../../MatrixClientPeg';
import SettingsStore from '../../../settings/SettingsStore';
import Modal from '../../../Modal';
import {
@ -30,9 +30,9 @@ import {
import SdkConfig from "../../../SdkConfig";
import LabelledToggleSwitch from "../elements/LabelledToggleSwitch";
import AccessibleButton from "../elements/AccessibleButton";
import {SettingLevel} from "../../../settings/SettingLevel";
import {UIFeature} from "../../../settings/UIFeature";
import {replaceableComponent} from "../../../utils/replaceableComponent";
import { SettingLevel } from "../../../settings/SettingLevel";
import { UIFeature } from "../../../settings/UIFeature";
import { replaceableComponent } from "../../../utils/replaceableComponent";
// TODO: this "view" component still has far too much application logic in it,
// which should be factored out to other files.
@ -40,7 +40,6 @@ import {replaceableComponent} from "../../../utils/replaceableComponent";
// TODO: this component also does a lot of direct poking into this.state, which
// is VERY NAUGHTY.
/**
* Rules that Vector used to set in order to override the actions of default rules.
* These are used to port peoples existing overrides to match the current API.
@ -517,7 +516,7 @@ export default class Notifications extends React.Component {
};
// HS default rules
const defaultRules = {master: [], vector: {}, others: []};
const defaultRules = { master: [], vector: {}, others: [] };
for (const kind in rulesets.global) {
for (let i = 0; i < Object.keys(rulesets.global[kind]).length; ++i) {
@ -632,7 +631,7 @@ export default class Notifications extends React.Component {
});
const pushersPromise = MatrixClientPeg.get().getPushers().then(function(resp) {
self.setState({pushers: resp.pushers});
self.setState({ pushers: resp.pushers });
});
Promise.all([pushRulesPromise, pushersPromise]).then(function() {
@ -655,7 +654,7 @@ export default class Notifications extends React.Component {
});
});
MatrixClientPeg.get().getThreePids().then((r) => this.setState({threepids: r.threepids}));
MatrixClientPeg.get().getThreePids().then((r) => this.setState({ threepids: r.threepids }));
};
_onClearNotifications = () => {

View file

@ -14,17 +14,17 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import React, {createRef} from 'react';
import {_t} from "../../../languageHandler";
import {MatrixClientPeg} from "../../../MatrixClientPeg";
import React, { createRef } from 'react';
import { _t } from "../../../languageHandler";
import { MatrixClientPeg } from "../../../MatrixClientPeg";
import Field from "../elements/Field";
import { getHostingLink } from '../../../utils/HostingLink';
import * as sdk from "../../../index";
import {OwnProfileStore} from "../../../stores/OwnProfileStore";
import { OwnProfileStore } from "../../../stores/OwnProfileStore";
import Modal from "../../../Modal";
import ErrorDialog from "../dialogs/ErrorDialog";
import {replaceableComponent} from "../../../utils/replaceableComponent";
import {mediaFromMxc} from "../../../customisations/Media";
import { replaceableComponent } from "../../../utils/replaceableComponent";
import { mediaFromMxc } from "../../../customisations/Media";
@replaceableComponent("views.settings.ProfileSettings")
export default class ProfileSettings extends React.Component {
@ -79,7 +79,7 @@ export default class ProfileSettings extends React.Component {
e.preventDefault();
if (!this.state.enableProfileSave) return;
this.setState({enableProfileSave: false});
this.setState({ enableProfileSave: false });
const client = MatrixClientPeg.get();
const newState = {};

View file

@ -17,7 +17,7 @@ limitations under the License.
import React from 'react';
import {MatrixClientPeg} from '../../../MatrixClientPeg';
import { MatrixClientPeg } from '../../../MatrixClientPeg';
import { _t } from '../../../languageHandler';
import Modal from '../../../Modal';
import { isSecureBackupRequired } from '../../../utils/WellKnownUtils';
@ -26,7 +26,7 @@ import AccessibleButton from '../elements/AccessibleButton';
import QuestionDialog from '../dialogs/QuestionDialog';
import RestoreKeyBackupDialog from '../dialogs/security/RestoreKeyBackupDialog';
import { accessSecretStorage } from '../../../SecurityManager';
import {replaceableComponent} from "../../../utils/replaceableComponent";
import { replaceableComponent } from "../../../utils/replaceableComponent";
@replaceableComponent("views.settings.SecureBackupPanel")
export default class SecureBackupPanel extends React.PureComponent {
@ -85,7 +85,7 @@ export default class SecureBackupPanel extends React.PureComponent {
async _checkKeyBackupStatus() {
this._getUpdatedDiagnostics();
try {
const {backupInfo, trustInfo} = await MatrixClientPeg.get().checkKeyBackup();
const { backupInfo, trustInfo } = await MatrixClientPeg.get().checkKeyBackup();
this.setState({
loading: false,
error: null,
@ -131,10 +131,10 @@ export default class SecureBackupPanel extends React.PureComponent {
async _getUpdatedDiagnostics() {
const cli = MatrixClientPeg.get();
const secretStorage = cli._crypto._secretStorage;
const secretStorage = cli.crypto.secretStorage;
const backupKeyStored = !!(await cli.isKeyBackupKeyStored());
const backupKeyFromCache = await cli._crypto.getSessionBackupPrivateKey();
const backupKeyFromCache = await cli.crypto.getSessionBackupPrivateKey();
const backupKeyCached = !!(backupKeyFromCache);
const backupKeyWellFormed = backupKeyFromCache instanceof Uint8Array;
const secretStorageKeyInAccount = await secretStorage.hasKey();
@ -172,7 +172,7 @@ export default class SecureBackupPanel extends React.PureComponent {
danger: true,
onFinished: (proceed) => {
if (!proceed) return;
this.setState({loading: true});
this.setState({ loading: true });
MatrixClientPeg.get().deleteKeyBackupVersion(this.state.backupInfo.version).then(() => {
this._loadBackupStatus();
});
@ -237,7 +237,7 @@ export default class SecureBackupPanel extends React.PureComponent {
"This session is <b>not backing up your keys</b>, " +
"but you do have an existing backup you can restore from " +
"and add to going forward.", {},
{b: sub => <b>{sub}</b>},
{ b: sub => <b>{sub}</b> },
)}</p>
<p>{_t(
"Connect this session to key backup before signing out to avoid " +
@ -385,7 +385,7 @@ export default class SecureBackupPanel extends React.PureComponent {
statusDescription = <>
<p>{_t(
"Your keys are <b>not being backed up from this session</b>.", {},
{b: sub => <b>{sub}</b>},
{ b: sub => <b>{sub}</b> },
)}</p>
<p>{_t("Back up your keys before signing out to avoid losing them.")}</p>
</>;

View file

@ -16,17 +16,17 @@ limitations under the License.
import url from 'url';
import React from 'react';
import {_t} from "../../../languageHandler";
import { _t } from "../../../languageHandler";
import * as sdk from '../../../index';
import {MatrixClientPeg} from "../../../MatrixClientPeg";
import { MatrixClientPeg } from "../../../MatrixClientPeg";
import Modal from '../../../Modal';
import dis from "../../../dispatcher/dispatcher";
import { getThreepidsWithBindStatus } from '../../../boundThreepids';
import IdentityAuthClient from "../../../IdentityAuthClient";
import {abbreviateUrl, unabbreviateUrl} from "../../../utils/UrlUtils";
import { abbreviateUrl, unabbreviateUrl } from "../../../utils/UrlUtils";
import { getDefaultIdentityServerUrl, doesIdentityServerHaveTerms } from '../../../utils/IdentityServerUtils';
import {timeout} from "../../../utils/promise";
import {replaceableComponent} from "../../../utils/replaceableComponent";
import { timeout } from "../../../utils/promise";
import { replaceableComponent } from "../../../utils/replaceableComponent";
import { ActionPayload } from '../../../dispatcher/payloads';
// We'll wait up to this long when checking for 3PID bindings on the IS.
@ -50,7 +50,7 @@ async function checkIdentityServerUrl(u) {
if (response.ok) {
return null;
} else if (response.status < 200 || response.status >= 300) {
return _t("Not a valid Identity Server (status code %(code)s)", {code: response.status});
return _t("Not a valid Identity Server (status code %(code)s)", { code: response.status });
} else {
return _t("Could not connect to Identity Server");
}
@ -121,7 +121,7 @@ export default class SetIdServer extends React.Component<IProps, IState> {
private onIdentityServerChanged = (ev) => {
const u = ev.target.value;
this.setState({idServer: u});
this.setState({ idServer: u });
};
private getTooltip = () => {
@ -159,14 +159,14 @@ export default class SetIdServer extends React.Component<IProps, IState> {
e.preventDefault();
const { idServer, currentClientIdServer } = this.state;
this.setState({busy: true, checking: true, error: null});
this.setState({ busy: true, checking: true, error: null });
const fullUrl = unabbreviateUrl(idServer);
let errStr = await checkIdentityServerUrl(fullUrl);
if (!errStr) {
try {
this.setState({checking: false}); // clear tooltip
this.setState({ checking: false }); // clear tooltip
// Test the identity server by trying to register with it. This
// may result in a terms of service prompt.
@ -236,13 +236,13 @@ export default class SetIdServer extends React.Component<IProps, IState> {
}
private onDisconnectClicked = async () => {
this.setState({disconnectBusy: true});
this.setState({ disconnectBusy: true });
try {
const [confirmed] = await this.showServerChangeWarning({
title: _t("Disconnect identity server"),
unboundMessage: _t(
"Disconnect from the identity server <idserver />?", {},
{idserver: sub => <b>{abbreviateUrl(this.state.currentClientIdServer)}</b>},
{ idserver: sub => <b>{abbreviateUrl(this.state.currentClientIdServer)}</b> },
),
button: _t("Disconnect"),
});
@ -250,7 +250,7 @@ export default class SetIdServer extends React.Component<IProps, IState> {
this.disconnectIdServer();
}
} finally {
this.setState({disconnectBusy: false});
this.setState({ disconnectBusy: false });
}
};
@ -369,7 +369,7 @@ export default class SetIdServer extends React.Component<IProps, IState> {
bodyText = _t(
"If you don't want to use <server /> to discover and be discoverable by existing " +
"contacts you know, enter another identity server below.",
{}, {server: sub => <b>{abbreviateUrl(idServerUrl)}</b>},
{}, { server: sub => <b>{abbreviateUrl(idServerUrl)}</b> },
);
}
} else {

View file

@ -15,12 +15,12 @@ limitations under the License.
*/
import React from 'react';
import {_t} from "../../../languageHandler";
import {IntegrationManagers} from "../../../integrations/IntegrationManagers";
import { _t } from "../../../languageHandler";
import { IntegrationManagers } from "../../../integrations/IntegrationManagers";
import * as sdk from '../../../index';
import SettingsStore from "../../../settings/SettingsStore";
import {SettingLevel} from "../../../settings/SettingLevel";
import {replaceableComponent} from "../../../utils/replaceableComponent";
import { SettingLevel } from "../../../settings/SettingLevel";
import { replaceableComponent } from "../../../utils/replaceableComponent";
@replaceableComponent("views.settings.SetIntegrationManager")
export default class SetIntegrationManager extends React.Component {
@ -41,9 +41,9 @@ export default class SetIntegrationManager extends React.Component {
console.error("Error changing integration manager provisioning");
console.error(err);
this.setState({provisioningEnabled: current});
this.setState({ provisioningEnabled: current });
});
this.setState({provisioningEnabled: !current});
this.setState({ provisioningEnabled: !current });
};
render() {
@ -57,7 +57,7 @@ export default class SetIntegrationManager extends React.Component {
bodyText = _t(
"Use an Integration Manager <b>(%(serverName)s)</b> to manage bots, widgets, " +
"and sticker packs.",
{serverName: currentManager.name},
{ serverName: currentManager.name },
{ b: sub => <b>{sub}</b> },
);
} else {

View file

@ -17,8 +17,8 @@ limitations under the License.
import React from 'react';
import SpellCheckLanguagesDropdown from "../../../components/views/elements/SpellCheckLanguagesDropdown";
import AccessibleButton from "../../../components/views/elements/AccessibleButton";
import {_t} from "../../../languageHandler";
import {replaceableComponent} from "../../../utils/replaceableComponent";
import { _t } from "../../../languageHandler";
import { replaceableComponent } from "../../../utils/replaceableComponent";
interface ExistingSpellCheckLanguageIProps {
language: string,
@ -60,7 +60,7 @@ export default class SpellCheckLanguages extends React.Component<SpellCheckLangu
super(props);
this.state = {
newLanguage: "",
}
};
}
_onRemoved = (language) => {
@ -77,13 +77,13 @@ export default class SpellCheckLanguages extends React.Component<SpellCheckLangu
if (!language) return;
if (this.props.languages.includes(language)) return;
this.props.languages.push(language)
this.props.languages.push(language);
this.props.onLanguagesChange(this.props.languages);
};
_onNewLanguageChange = (language: string) => {
if (this.state.newLanguage === language) return;
this.setState({newLanguage: language});
this.setState({ newLanguage: language });
};
render() {

View file

@ -14,17 +14,17 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import React, {useState} from "react";
import React, { useState } from "react";
import {UpdateCheckStatus} from "../../../BasePlatform";
import { UpdateCheckStatus } from "../../../BasePlatform";
import PlatformPeg from "../../../PlatformPeg";
import {useDispatcher} from "../../../hooks/useDispatcher";
import { useDispatcher } from "../../../hooks/useDispatcher";
import dis from "../../../dispatcher/dispatcher";
import {Action} from "../../../dispatcher/actions";
import {_t} from "../../../languageHandler";
import { Action } from "../../../dispatcher/actions";
import { _t } from "../../../languageHandler";
import InlineSpinner from "../../../components/views/elements/InlineSpinner";
import AccessibleButton from "../../../components/views/elements/AccessibleButton";
import {CheckUpdatesPayload} from "../../../dispatcher/payloads/CheckUpdatesPayload";
import { CheckUpdatesPayload } from "../../../dispatcher/payloads/CheckUpdatesPayload";
function installUpdate() {
PlatformPeg.get().installUpdate();
@ -61,7 +61,7 @@ const UpdateCheckButton = () => {
PlatformPeg.get().startUpdateCheck();
};
useDispatcher(dis, ({action, ...params}) => {
useDispatcher(dis, ({ action, ...params }) => {
if (action === Action.CheckUpdates) {
setState(params as CheckUpdatesPayload);
}

View file

@ -17,15 +17,15 @@ limitations under the License.
import React from 'react';
import PropTypes from 'prop-types';
import {_t} from "../../../../languageHandler";
import {MatrixClientPeg} from "../../../../MatrixClientPeg";
import { _t } from "../../../../languageHandler";
import { MatrixClientPeg } from "../../../../MatrixClientPeg";
import Field from "../../elements/Field";
import AccessibleButton from "../../elements/AccessibleButton";
import * as Email from "../../../../email";
import AddThreepid from "../../../../AddThreepid";
import * as sdk from '../../../../index';
import Modal from '../../../../Modal';
import {replaceableComponent} from "../../../../utils/replaceableComponent";
import { replaceableComponent } from "../../../../utils/replaceableComponent";
/*
TODO: Improve the UX for everything in here.
@ -57,14 +57,14 @@ export class ExistingEmailAddress extends React.Component {
e.stopPropagation();
e.preventDefault();
this.setState({verifyRemove: true});
this.setState({ verifyRemove: true });
};
_onDontRemove = (e) => {
e.stopPropagation();
e.preventDefault();
this.setState({verifyRemove: false});
this.setState({ verifyRemove: false });
};
_onActuallyRemove = (e) => {
@ -88,7 +88,7 @@ export class ExistingEmailAddress extends React.Component {
return (
<div className="mx_ExistingEmailAddress">
<span className="mx_ExistingEmailAddress_promptText">
{_t("Remove %(email)s?", {email: this.props.email.address} )}
{_t("Remove %(email)s?", { email: this.props.email.address } )}
</span>
<AccessibleButton
onClick={this._onActuallyRemove}
@ -167,13 +167,13 @@ export default class EmailAddresses extends React.Component {
}
const task = new AddThreepid();
this.setState({verifying: true, continueDisabled: true, addTask: task});
this.setState({ verifying: true, continueDisabled: true, addTask: task });
task.addEmailAddress(email).then(() => {
this.setState({continueDisabled: false});
this.setState({ continueDisabled: false });
}).catch((err) => {
console.error("Unable to add email address " + email + " " + err);
this.setState({verifying: false, continueDisabled: false, addTask: null});
this.setState({ verifying: false, continueDisabled: false, addTask: null });
Modal.createTrackedDialog('Unable to add email address', '', ErrorDialog, {
title: _t("Unable to add email address"),
description: ((err && err.message) ? err.message : _t("Operation failed")),
@ -185,7 +185,7 @@ export default class EmailAddresses extends React.Component {
e.stopPropagation();
e.preventDefault();
this.setState({continueDisabled: true});
this.setState({ continueDisabled: true });
this.state.addTask.checkEmailLinkClicked().then(([finished]) => {
let newEmailAddress = this.state.newEmailAddress;
if (finished) {
@ -204,7 +204,7 @@ export default class EmailAddresses extends React.Component {
newEmailAddress,
});
}).catch((err) => {
this.setState({continueDisabled: false});
this.setState({ continueDisabled: false });
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
if (err.errcode === 'M_THREEPID_AUTH_FAILED') {
Modal.createTrackedDialog("Email hasn't been verified yet", "", ErrorDialog, {

View file

@ -17,15 +17,15 @@ limitations under the License.
import React from 'react';
import PropTypes from 'prop-types';
import {_t} from "../../../../languageHandler";
import {MatrixClientPeg} from "../../../../MatrixClientPeg";
import { _t } from "../../../../languageHandler";
import { MatrixClientPeg } from "../../../../MatrixClientPeg";
import Field from "../../elements/Field";
import AccessibleButton from "../../elements/AccessibleButton";
import AddThreepid from "../../../../AddThreepid";
import CountryDropdown from "../../auth/CountryDropdown";
import * as sdk from '../../../../index';
import Modal from '../../../../Modal';
import {replaceableComponent} from "../../../../utils/replaceableComponent";
import { replaceableComponent } from "../../../../utils/replaceableComponent";
/*
TODO: Improve the UX for everything in here.
@ -52,14 +52,14 @@ export class ExistingPhoneNumber extends React.Component {
e.stopPropagation();
e.preventDefault();
this.setState({verifyRemove: true});
this.setState({ verifyRemove: true });
};
_onDontRemove = (e) => {
e.stopPropagation();
e.preventDefault();
this.setState({verifyRemove: false});
this.setState({ verifyRemove: false });
};
_onActuallyRemove = (e) => {
@ -83,7 +83,7 @@ export class ExistingPhoneNumber extends React.Component {
return (
<div className="mx_ExistingPhoneNumber">
<span className="mx_ExistingPhoneNumber_promptText">
{_t("Remove %(phone)s?", {phone: this.props.msisdn.address})}
{_t("Remove %(phone)s?", { phone: this.props.msisdn.address })}
</span>
<AccessibleButton
onClick={this._onActuallyRemove}
@ -164,13 +164,13 @@ export default class PhoneNumbers extends React.Component {
const phoneCountry = this.state.phoneCountry;
const task = new AddThreepid();
this.setState({verifying: true, continueDisabled: true, addTask: task});
this.setState({ verifying: true, continueDisabled: true, addTask: task });
task.addMsisdn(phoneCountry, phoneNumber).then((response) => {
this.setState({continueDisabled: false, verifyMsisdn: response.msisdn});
this.setState({ continueDisabled: false, verifyMsisdn: response.msisdn });
}).catch((err) => {
console.error("Unable to add phone number " + phoneNumber + " " + err);
this.setState({verifying: false, continueDisabled: false, addTask: null});
this.setState({ verifying: false, continueDisabled: false, addTask: null });
Modal.createTrackedDialog('Add Phone Number Error', '', ErrorDialog, {
title: _t("Error"),
description: ((err && err.message) ? err.message : _t("Operation failed")),
@ -182,7 +182,7 @@ export default class PhoneNumbers extends React.Component {
e.stopPropagation();
e.preventDefault();
this.setState({continueDisabled: true});
this.setState({ continueDisabled: true });
const token = this.state.newPhoneNumberCode;
const address = this.state.verifyMsisdn;
this.state.addTask.haveMsisdnToken(token).then(([finished]) => {
@ -205,7 +205,7 @@ export default class PhoneNumbers extends React.Component {
newPhoneNumberCode: "",
});
}).catch((err) => {
this.setState({continueDisabled: false});
this.setState({ continueDisabled: false });
if (err.errcode !== 'M_THREEPID_AUTH_FAILED') {
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
console.error("Unable to verify phone number: " + err);
@ -214,13 +214,13 @@ export default class PhoneNumbers extends React.Component {
description: ((err && err.message) ? err.message : _t("Operation failed")),
});
} else {
this.setState({verifyError: _t("Incorrect verification code")});
this.setState({ verifyError: _t("Incorrect verification code") });
}
});
};
_onCountryChanged = (e) => {
this.setState({phoneCountry: e.iso2});
this.setState({ phoneCountry: e.iso2 });
};
render() {

View file

@ -19,11 +19,11 @@ import React from 'react';
import PropTypes from 'prop-types';
import { _t } from "../../../../languageHandler";
import {MatrixClientPeg} from "../../../../MatrixClientPeg";
import { MatrixClientPeg } from "../../../../MatrixClientPeg";
import * as sdk from '../../../../index';
import Modal from '../../../../Modal';
import AddThreepid from '../../../../AddThreepid';
import {replaceableComponent} from "../../../../utils/replaceableComponent";
import { replaceableComponent } from "../../../../utils/replaceableComponent";
/*
TODO: Improve the UX for everything in here.

View file

@ -19,11 +19,11 @@ import React from 'react';
import PropTypes from 'prop-types';
import { _t } from "../../../../languageHandler";
import {MatrixClientPeg} from "../../../../MatrixClientPeg";
import { MatrixClientPeg } from "../../../../MatrixClientPeg";
import * as sdk from '../../../../index';
import Modal from '../../../../Modal';
import AddThreepid from '../../../../AddThreepid';
import {replaceableComponent} from "../../../../utils/replaceableComponent";
import { replaceableComponent } from "../../../../utils/replaceableComponent";
/*
TODO: Improve the UX for everything in here.
@ -190,7 +190,7 @@ export class PhoneNumber extends React.Component {
description: ((err && err.message) ? err.message : _t("Operation failed")),
});
} else {
this.setState({verifyError: _t("Incorrect verification code")});
this.setState({ verifyError: _t("Incorrect verification code") });
}
}
}

View file

@ -1,5 +1,5 @@
/*
Copyright 2019 New Vector Ltd
Copyright 2019 - 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.
@ -15,68 +15,76 @@ limitations under the License.
*/
import React from 'react';
import PropTypes from 'prop-types';
import {_t} from "../../../../../languageHandler";
import {MatrixClientPeg} from "../../../../../MatrixClientPeg";
import * as sdk from "../../../../..";
import { EventType } from 'matrix-js-sdk/src/@types/event';
import { _t } from "../../../../../languageHandler";
import { MatrixClientPeg } from "../../../../../MatrixClientPeg";
import AccessibleButton from "../../../elements/AccessibleButton";
import RoomUpgradeDialog from "../../../dialogs/RoomUpgradeDialog";
import DevtoolsDialog from "../../../dialogs/DevtoolsDialog";
import Modal from "../../../../../Modal";
import dis from "../../../../../dispatcher/dispatcher";
import {replaceableComponent} from "../../../../../utils/replaceableComponent";
import { replaceableComponent } from "../../../../../utils/replaceableComponent";
interface IProps {
roomId: string;
closeSettingsFn(): void;
}
interface IRecommendedVersion {
version: string;
needsUpgrade: boolean;
urgent: boolean;
}
interface IState {
upgradeRecommendation?: IRecommendedVersion;
oldRoomId?: string;
oldEventId?: string;
upgraded?: boolean;
}
@replaceableComponent("views.settings.tabs.room.AdvancedRoomSettingsTab")
export default class AdvancedRoomSettingsTab extends React.Component {
static propTypes = {
roomId: PropTypes.string.isRequired,
closeSettingsFn: PropTypes.func.isRequired,
};
constructor(props) {
super(props);
export default class AdvancedRoomSettingsTab extends React.Component<IProps, IState> {
constructor(props, context) {
super(props, context);
this.state = {
// This is eventually set to the value of room.getRecommendedVersion()
upgradeRecommendation: null,
};
}
// TODO: [REACT-WARNING] Move this to constructor
UNSAFE_componentWillMount() { // eslint-disable-line camelcase
// we handle lack of this object gracefully later, so don't worry about it failing here.
const room = MatrixClientPeg.get().getRoom(this.props.roomId);
room.getRecommendedVersion().then((v) => {
const tombstone = room.currentState.getStateEvents("m.room.tombstone", "");
const tombstone = room.currentState.getStateEvents(EventType.RoomTombstone, "");
const additionalStateChanges = {};
const createEvent = room.currentState.getStateEvents("m.room.create", "");
const additionalStateChanges: Partial<IState> = {};
const createEvent = room.currentState.getStateEvents(EventType.RoomCreate, "");
const predecessor = createEvent ? createEvent.getContent().predecessor : null;
if (predecessor && predecessor.room_id) {
additionalStateChanges['oldRoomId'] = predecessor.room_id;
additionalStateChanges['oldEventId'] = predecessor.event_id;
additionalStateChanges['hasPreviousRoom'] = true;
additionalStateChanges.oldRoomId = predecessor.room_id;
additionalStateChanges.oldEventId = predecessor.event_id;
}
this.setState({
upgraded: tombstone && tombstone.getContent().replacement_room,
upgraded: !!tombstone?.getContent().replacement_room,
upgradeRecommendation: v,
...additionalStateChanges,
});
});
}
_upgradeRoom = (e) => {
const RoomUpgradeDialog = sdk.getComponent('dialogs.RoomUpgradeDialog');
private upgradeRoom = (e) => {
const room = MatrixClientPeg.get().getRoom(this.props.roomId);
Modal.createTrackedDialog('Upgrade Room Version', '', RoomUpgradeDialog, {room: room});
Modal.createTrackedDialog('Upgrade Room Version', '', RoomUpgradeDialog, { room });
};
_openDevtools = (e) => {
const DevtoolsDialog = sdk.getComponent('dialogs.DevtoolsDialog');
Modal.createDialog(DevtoolsDialog, {roomId: this.props.roomId});
private openDevtools = (e) => {
Modal.createDialog(DevtoolsDialog, { roomId: this.props.roomId });
};
_onOldRoomClicked = (e) => {
private onOldRoomClicked = (e) => {
e.preventDefault();
e.stopPropagation();
@ -93,9 +101,9 @@ export default class AdvancedRoomSettingsTab extends React.Component {
const room = client.getRoom(this.props.roomId);
let unfederatableSection;
const createEvent = room.currentState.getStateEvents('m.room.create', '');
const createEvent = room.currentState.getStateEvents(EventType.RoomCreate, '');
if (createEvent && createEvent.getContent()['m.federate'] === false) {
unfederatableSection = <div>{_t('This room is not accessible by remote Matrix servers')}</div>;
unfederatableSection = <div>{ _t('This room is not accessible by remote Matrix servers') }</div>;
}
let roomUpgradeButton;
@ -103,7 +111,7 @@ export default class AdvancedRoomSettingsTab extends React.Component {
roomUpgradeButton = (
<div>
<p className='mx_SettingsTab_warningText'>
{_t(
{ _t(
"<b>Warning</b>: Upgrading a room will <i>not automatically migrate room members " +
"to the new version of the room.</i> We'll post a link to the new room in the old " +
"version of the room - room members will have to click this link to join the new room.",
@ -111,51 +119,53 @@ export default class AdvancedRoomSettingsTab extends React.Component {
"b": (sub) => <b>{sub}</b>,
"i": (sub) => <i>{sub}</i>,
},
)}
) }
</p>
<AccessibleButton onClick={this._upgradeRoom} kind='primary'>
{_t("Upgrade this room to the recommended room version")}
<AccessibleButton onClick={this.upgradeRoom} kind='primary'>
{ _t("Upgrade this room to the recommended room version") }
</AccessibleButton>
</div>
);
}
let oldRoomLink;
if (this.state.hasPreviousRoom) {
if (this.state.oldRoomId) {
let name = _t("this room");
const room = MatrixClientPeg.get().getRoom(this.props.roomId);
if (room && room.name) name = room.name;
oldRoomLink = (
<AccessibleButton element='a' onClick={this._onOldRoomClicked}>
{_t("View older messages in %(roomName)s.", {roomName: name})}
<AccessibleButton element='a' onClick={this.onOldRoomClicked}>
{ _t("View older messages in %(roomName)s.", { roomName: name }) }
</AccessibleButton>
);
}
return (
<div className="mx_SettingsTab">
<div className="mx_SettingsTab_heading">{_t("Advanced")}</div>
<div className="mx_SettingsTab_heading">{ _t("Advanced") }</div>
<div className='mx_SettingsTab_section mx_SettingsTab_subsectionText'>
<span className='mx_SettingsTab_subheading'>{_t("Room information")}</span>
<span className='mx_SettingsTab_subheading'>
{ room?.isSpaceRoom() ? _t("Space information") : _t("Room information") }
</span>
<div>
<span>{_t("Internal room ID:")}</span>&nbsp;
{this.props.roomId}
<span>{ _t("Internal room ID:") }</span>&nbsp;
{ this.props.roomId }
</div>
{unfederatableSection}
{ unfederatableSection }
</div>
<div className='mx_SettingsTab_section mx_SettingsTab_subsectionText'>
<span className='mx_SettingsTab_subheading'>{_t("Room version")}</span>
<span className='mx_SettingsTab_subheading'>{ _t("Room version") }</span>
<div>
<span>{_t("Room version:")}</span>&nbsp;
{room.getVersion()}
<span>{ _t("Room version:") }</span>&nbsp;
{ room.getVersion() }
</div>
{oldRoomLink}
{roomUpgradeButton}
{ oldRoomLink }
{ roomUpgradeButton }
</div>
<div className='mx_SettingsTab_section mx_SettingsTab_subsectionText'>
<span className='mx_SettingsTab_subheading'>{_t("Developer options")}</span>
<AccessibleButton onClick={this._openDevtools} kind='primary'>
{_t("Open Devtools")}
<span className='mx_SettingsTab_subheading'>{ _t("Developer options") }</span>
<AccessibleButton onClick={this.openDevtools} kind='primary'>
{ _t("Open Devtools") }
</AccessibleButton>
</div>
</div>

View file

@ -15,13 +15,13 @@ limitations under the License.
*/
import React from "react";
import {Room} from "matrix-js-sdk/src/models/room";
import {MatrixEvent} from "matrix-js-sdk/src/models/event";
import { Room } from "matrix-js-sdk/src/models/room";
import { MatrixEvent } from "matrix-js-sdk/src/models/event";
import {_t} from "../../../../../languageHandler";
import {MatrixClientPeg} from "../../../../../MatrixClientPeg";
import { _t } from "../../../../../languageHandler";
import { MatrixClientPeg } from "../../../../../MatrixClientPeg";
import BridgeTile from "../../BridgeTile";
import {replaceableComponent} from "../../../../../utils/replaceableComponent";
import { replaceableComponent } from "../../../../../utils/replaceableComponent";
const BRIDGE_EVENT_TYPES = [
"uk.half-shot.bridge",
@ -44,14 +44,11 @@ export default class BridgeSettingsTab extends React.Component<IProps> {
return <BridgeTile key={event.getId()} room={room} ev={event} />;
}
static getBridgeStateEvents(roomId: string) {
static getBridgeStateEvents(roomId: string): MatrixEvent[] {
const client = MatrixClientPeg.get();
const roomState = client.getRoom(roomId).currentState;
return BRIDGE_EVENT_TYPES.map(typeName => {
const events = roomState.events.get(typeName);
return events ? Array.from(events.values()) : [];
}).flat(1);
return BRIDGE_EVENT_TYPES.map(typeName => roomState.getStateEvents(typeName)).flat(1);
}
render() {

View file

@ -16,15 +16,15 @@ limitations under the License.
import React from 'react';
import PropTypes from 'prop-types';
import {_t} from "../../../../../languageHandler";
import { _t } from "../../../../../languageHandler";
import RoomProfileSettings from "../../../room_settings/RoomProfileSettings";
import * as sdk from "../../../../..";
import AccessibleButton from "../../../elements/AccessibleButton";
import dis from "../../../../../dispatcher/dispatcher";
import MatrixClientContext from "../../../../../contexts/MatrixClientContext";
import SettingsStore from "../../../../../settings/SettingsStore";
import {UIFeature} from "../../../../../settings/UIFeature";
import {replaceableComponent} from "../../../../../utils/replaceableComponent";
import { UIFeature } from "../../../../../settings/UIFeature";
import { replaceableComponent } from "../../../../../utils/replaceableComponent";
@replaceableComponent("views.settings.tabs.room.GeneralRoomSettingsTab")
export default class GeneralRoomSettingsTab extends React.Component {
@ -60,7 +60,6 @@ export default class GeneralRoomSettingsTab extends React.Component {
const canSetAliases = true; // Previously, we arbitrarily only allowed admins to do this
const canSetCanonical = room.currentState.mayClientSendStateEvent("m.room.canonical_alias", client);
const canonicalAliasEv = room.currentState.getStateEvents("m.room.canonical_alias", '');
const aliasEvents = room.currentState.getStateEvents("m.room.aliases");
const canChangeGroups = room.currentState.mayClientSendStateEvent("m.room.related_groups", client);
const groupsEvent = room.currentState.getStateEvents("m.room.related_groups", "");
@ -100,7 +99,7 @@ export default class GeneralRoomSettingsTab extends React.Component {
<div className='mx_SettingsTab_section mx_SettingsTab_subsectionText'>
<AliasSettings roomId={this.props.roomId}
canSetCanonicalAlias={canSetCanonical} canSetAliases={canSetAliases}
canonicalAliasEvent={canonicalAliasEv} aliasEvents={aliasEvents} />
canonicalAliasEvent={canonicalAliasEv} />
</div>
<div className="mx_SettingsTab_heading">{_t("Other")}</div>
{ flairSection }

View file

@ -14,15 +14,15 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import React, {createRef} from 'react';
import React, { createRef } from 'react';
import PropTypes from 'prop-types';
import {_t} from "../../../../../languageHandler";
import {MatrixClientPeg} from "../../../../../MatrixClientPeg";
import { _t } from "../../../../../languageHandler";
import { MatrixClientPeg } from "../../../../../MatrixClientPeg";
import AccessibleButton from "../../../elements/AccessibleButton";
import Notifier from "../../../../../Notifier";
import SettingsStore from '../../../../../settings/SettingsStore';
import {SettingLevel} from "../../../../../settings/SettingLevel";
import {replaceableComponent} from "../../../../../utils/replaceableComponent";
import { SettingLevel } from "../../../../../settings/SettingLevel";
import { replaceableComponent } from "../../../../../utils/replaceableComponent";
@replaceableComponent("views.settings.tabs.room.NotificationsSettingsTab")
export default class NotificationsSettingsTab extends React.Component {
@ -47,7 +47,7 @@ export default class NotificationsSettingsTab extends React.Component {
if (!soundData) {
return;
}
this.setState({currentSound: soundData.name || soundData.url});
this.setState({ currentSound: soundData.name || soundData.url });
}
async _triggerUploader(e) {

View file

@ -15,16 +15,17 @@ limitations under the License.
*/
import React from 'react';
import {_t, _td} from "../../../../../languageHandler";
import {MatrixClientPeg} from "../../../../../MatrixClientPeg";
import { _t, _td } from "../../../../../languageHandler";
import { MatrixClientPeg } from "../../../../../MatrixClientPeg";
import * as sdk from "../../../../..";
import AccessibleButton from "../../../elements/AccessibleButton";
import Modal from "../../../../../Modal";
import {replaceableComponent} from "../../../../../utils/replaceableComponent";
import {EventType} from "matrix-js-sdk/src/@types/event";
import { replaceableComponent } from "../../../../../utils/replaceableComponent";
import { EventType } from "matrix-js-sdk/src/@types/event";
import { RoomMember } from "matrix-js-sdk/src/models/room-member";
import { MatrixEvent } from "matrix-js-sdk/src/models/event";
import { RoomState } from "matrix-js-sdk/src/models/room-state";
import { compare } from "../../../../../utils/strings";
const plEventsToLabels = {
// These will be translated for us later.
@ -44,18 +45,18 @@ const plEventsToLabels = {
const plEventsToShow = {
// If an event is listed here, it will be shown in the PL settings. Defaults will be calculated.
[EventType.RoomAvatar]: {isState: true},
[EventType.RoomName]: {isState: true},
[EventType.RoomCanonicalAlias]: {isState: true},
[EventType.RoomHistoryVisibility]: {isState: true},
[EventType.RoomPowerLevels]: {isState: true},
[EventType.RoomTopic]: {isState: true},
[EventType.RoomTombstone]: {isState: true},
[EventType.RoomEncryption]: {isState: true},
[EventType.RoomServerAcl]: {isState: true},
[EventType.RoomAvatar]: { isState: true },
[EventType.RoomName]: { isState: true },
[EventType.RoomCanonicalAlias]: { isState: true },
[EventType.RoomHistoryVisibility]: { isState: true },
[EventType.RoomPowerLevels]: { isState: true },
[EventType.RoomTopic]: { isState: true },
[EventType.RoomTombstone]: { isState: true },
[EventType.RoomEncryption]: { isState: true },
[EventType.RoomServerAcl]: { isState: true },
// TODO: Enable support for m.widget event type (https://github.com/vector-im/element-web/issues/13111)
"im.vector.modular.widgets": {isState: true},
"im.vector.modular.widgets": { isState: true },
};
// parse a string as an integer; if the input is undefined, or cannot be parsed
@ -102,7 +103,7 @@ export class BannedUser extends React.Component<IBannedUserProps> {
return (
<li>
{unbanButton}
<span title={_t("Banned by %(displayName)s", {displayName: this.props.by})}>
<span title={_t("Banned by %(displayName)s", { displayName: this.props.by })}>
<strong>{ this.props.member.name }</strong> {userId}
{this.props.reason ? " " + _t('Reason') + ": " + this.props.reason : ""}
</span>
@ -312,7 +313,7 @@ export default class RolesRoomSettingsTab extends React.Component<IProps> {
// comparator for sorting PL users lexicographically on PL descending, MXID ascending. (case-insensitive)
const comparator = (a, b) => {
const plDiff = userLevels[b.key] - userLevels[a.key];
return plDiff !== 0 ? plDiff : a.key.toLocaleLowerCase().localeCompare(b.key.toLocaleLowerCase());
return plDiff !== 0 ? plDiff : compare(a.key.toLocaleLowerCase(), b.key.toLocaleLowerCase());
};
privilegedUsers.sort(comparator);
@ -393,7 +394,7 @@ export default class RolesRoomSettingsTab extends React.Component<IProps> {
if (label) {
label = _t(label);
} else {
label = _t("Send %(eventType)s events", {eventType});
label = _t("Send %(eventType)s events", { eventType });
}
return (
<div className="" key={eventType}>

View file

@ -16,32 +16,35 @@ limitations under the License.
import React from 'react';
import { MatrixEvent } from "matrix-js-sdk/src/models/event";
import {_t} from "../../../../../languageHandler";
import {MatrixClientPeg} from "../../../../../MatrixClientPeg";
import { _t } from "../../../../../languageHandler";
import { MatrixClientPeg } from "../../../../../MatrixClientPeg";
import * as sdk from "../../../../..";
import LabelledToggleSwitch from "../../../elements/LabelledToggleSwitch";
import Modal from "../../../../../Modal";
import QuestionDialog from "../../../dialogs/QuestionDialog";
import StyledRadioGroup from '../../../elements/StyledRadioGroup';
import {SettingLevel} from "../../../../../settings/SettingLevel";
import { SettingLevel } from "../../../../../settings/SettingLevel";
import SettingsStore from "../../../../../settings/SettingsStore";
import {UIFeature} from "../../../../../settings/UIFeature";
import { UIFeature } from "../../../../../settings/UIFeature";
import { replaceableComponent } from "../../../../../utils/replaceableComponent";
// Knock and private are reserved keywords which are not yet implemented.
enum JoinRule {
export enum JoinRule {
Public = "public",
Knock = "knock",
Invite = "invite",
/**
* @deprecated Reserved. Should not be used.
*/
Private = "private",
}
enum GuestAccess {
export enum GuestAccess {
CanJoin = "can_join",
Forbidden = "forbidden",
}
enum HistoryVisibility {
export enum HistoryVisibility {
Invited = "invited",
Joined = "joined",
Shared = "shared",
@ -97,9 +100,9 @@ export default class SecurityRoomSettingsTab extends React.Component<IProps, ISt
HistoryVisibility.Shared,
);
const encrypted = MatrixClientPeg.get().isRoomEncrypted(this.props.roomId);
this.setState({joinRule, guestAccess, history, encrypted});
this.setState({ joinRule, guestAccess, history, encrypted });
const hasAliases = await this.hasAliases();
this.setState({hasAliases});
this.setState({ hasAliases });
}
private pullContentPropertyFromEvent<T>(event: MatrixEvent, key: string, defaultValue: T): T {
@ -121,7 +124,7 @@ export default class SecurityRoomSettingsTab extends React.Component<IProps, ISt
if (refreshWhenTypes.includes(e.getType())) this.forceUpdate();
};
private onEncryptionChange = (e: React.ChangeEvent) => {
private onEncryptionChange = () => {
Modal.createTrackedDialog('Enable encryption', '', QuestionDialog, {
title: _t('Enable encryption?'),
description: _t(
@ -137,18 +140,18 @@ export default class SecurityRoomSettingsTab extends React.Component<IProps, ISt
),
onFinished: (confirm) => {
if (!confirm) {
this.setState({encrypted: false});
this.setState({ encrypted: false });
return;
}
const beforeEncrypted = this.state.encrypted;
this.setState({encrypted: true});
this.setState({ encrypted: true });
MatrixClientPeg.get().sendStateEvent(
this.props.roomId, "m.room.encryption",
{ algorithm: "m.megolm.v1.aes-sha2" },
).catch((e) => {
console.error(e);
this.setState({encrypted: beforeEncrypted});
this.setState({ encrypted: beforeEncrypted });
});
},
});
@ -163,16 +166,26 @@ export default class SecurityRoomSettingsTab extends React.Component<IProps, ISt
const beforeJoinRule = this.state.joinRule;
const beforeGuestAccess = this.state.guestAccess;
this.setState({joinRule, guestAccess});
this.setState({ joinRule, guestAccess });
const client = MatrixClientPeg.get();
client.sendStateEvent(this.props.roomId, "m.room.join_rules", {join_rule: joinRule}, "").catch((e) => {
client.sendStateEvent(
this.props.roomId,
"m.room.join_rules",
{ join_rule: joinRule },
"",
).catch((e) => {
console.error(e);
this.setState({joinRule: beforeJoinRule});
this.setState({ joinRule: beforeJoinRule });
});
client.sendStateEvent(this.props.roomId, "m.room.guest_access", {guest_access: guestAccess}, "").catch((e) => {
client.sendStateEvent(
this.props.roomId,
"m.room.guest_access",
{ guest_access: guestAccess },
"",
).catch((e) => {
console.error(e);
this.setState({guestAccess: beforeGuestAccess});
this.setState({ guestAccess: beforeGuestAccess });
});
};
@ -209,27 +222,37 @@ export default class SecurityRoomSettingsTab extends React.Component<IProps, ISt
const beforeJoinRule = this.state.joinRule;
const beforeGuestAccess = this.state.guestAccess;
this.setState({joinRule, guestAccess});
this.setState({ joinRule, guestAccess });
const client = MatrixClientPeg.get();
client.sendStateEvent(this.props.roomId, "m.room.join_rules", {join_rule: joinRule}, "").catch((e) => {
client.sendStateEvent(
this.props.roomId,
"m.room.join_rules",
{ join_rule: joinRule },
"",
).catch((e) => {
console.error(e);
this.setState({joinRule: beforeJoinRule});
this.setState({ joinRule: beforeJoinRule });
});
client.sendStateEvent(this.props.roomId, "m.room.guest_access", {guest_access: guestAccess}, "").catch((e) => {
client.sendStateEvent(
this.props.roomId,
"m.room.guest_access",
{ guest_access: guestAccess },
"",
).catch((e) => {
console.error(e);
this.setState({guestAccess: beforeGuestAccess});
this.setState({ guestAccess: beforeGuestAccess });
});
};
private onHistoryRadioToggle = (history: HistoryVisibility) => {
const beforeHistory = this.state.history;
this.setState({history: history});
this.setState({ history: history });
MatrixClientPeg.get().sendStateEvent(this.props.roomId, "m.room.history_visibility", {
history_visibility: history,
}, "").catch((e) => {
console.error(e);
this.setState({history: beforeHistory});
this.setState({ history: beforeHistory });
});
};

View file

@ -16,7 +16,7 @@ limitations under the License.
*/
import React from 'react';
import {_t} from "../../../../../languageHandler";
import { _t } from "../../../../../languageHandler";
import SdkConfig from "../../../../../SdkConfig";
import { MatrixClientPeg } from '../../../../../MatrixClientPeg';
import SettingsStore from "../../../../../settings/SettingsStore";
@ -35,9 +35,10 @@ import Field from '../../../elements/Field';
import EventTilePreview from '../../../elements/EventTilePreview';
import StyledRadioGroup from "../../../elements/StyledRadioGroup";
import { SettingLevel } from "../../../../../settings/SettingLevel";
import {UIFeature} from "../../../../../settings/UIFeature";
import {Layout} from "../../../../../settings/Layout";
import {replaceableComponent} from "../../../../../utils/replaceableComponent";
import { UIFeature } from "../../../../../settings/UIFeature";
import { Layout } from "../../../../../settings/Layout";
import { replaceableComponent } from "../../../../../utils/replaceableComponent";
import { compare } from "../../../../../utils/strings";
interface IProps {
}
@ -83,7 +84,7 @@ export default class AppearanceUserSettingsTab extends React.Component<IProps, I
fontSize: (SettingsStore.getValue("baseFontSize", null) + FontWatcher.SIZE_DIFF).toString(),
...this.calculateThemeState(),
customThemeUrl: "",
customThemeMessage: {isError: false, text: ""},
customThemeMessage: { isError: false, text: "" },
useCustomFontSize: SettingsStore.getValue("useCustomFontSize"),
useSystemFont: SettingsStore.getValue("useSystemFont"),
systemFont: SettingsStore.getValue("systemFont"),
@ -148,43 +149,43 @@ export default class AppearanceUserSettingsTab extends React.Component<IProps, I
// so remember what the value was before we tried to set it so we can revert
const oldTheme: string = SettingsStore.getValue('theme');
SettingsStore.setValue("theme", null, SettingLevel.DEVICE, newTheme).catch(() => {
dis.dispatch<RecheckThemePayload>({action: Action.RecheckTheme});
this.setState({theme: oldTheme});
dis.dispatch<RecheckThemePayload>({ action: Action.RecheckTheme });
this.setState({ theme: oldTheme });
});
this.setState({theme: newTheme});
this.setState({ theme: newTheme });
// The settings watcher doesn't fire until the echo comes back from the
// server, so to make the theme change immediately we need to manually
// do the dispatch now
// XXX: The local echoed value appears to be unreliable, in particular
// when settings custom themes(!) so adding forceTheme to override
// the value from settings.
dis.dispatch<RecheckThemePayload>({action: Action.RecheckTheme, forceTheme: newTheme});
dis.dispatch<RecheckThemePayload>({ action: Action.RecheckTheme, forceTheme: newTheme });
};
private onUseSystemThemeChanged = (checked: boolean): void => {
this.setState({useSystemTheme: checked});
this.setState({ useSystemTheme: checked });
SettingsStore.setValue("use_system_theme", null, SettingLevel.DEVICE, checked);
dis.dispatch<RecheckThemePayload>({action: Action.RecheckTheme});
dis.dispatch<RecheckThemePayload>({ action: Action.RecheckTheme });
};
private onFontSizeChanged = (size: number): void => {
this.setState({fontSize: size.toString()});
this.setState({ fontSize: size.toString() });
SettingsStore.setValue("baseFontSize", null, SettingLevel.DEVICE, size - FontWatcher.SIZE_DIFF);
};
private onValidateFontSize = async ({value}: Pick<IFieldState, "value">): Promise<IValidationResult> => {
private onValidateFontSize = async ({ value }: Pick<IFieldState, "value">): Promise<IValidationResult> => {
const parsedSize = parseFloat(value);
const min = FontWatcher.MIN_SIZE + FontWatcher.SIZE_DIFF;
const max = FontWatcher.MAX_SIZE + FontWatcher.SIZE_DIFF;
if (isNaN(parsedSize)) {
return {valid: false, feedback: _t("Size must be a number")};
return { valid: false, feedback: _t("Size must be a number") };
}
if (!(min <= parsedSize && parsedSize <= max)) {
return {
valid: false,
feedback: _t('Custom font size can only be between %(min)s pt and %(max)s pt', {min, max}),
feedback: _t('Custom font size can only be between %(min)s pt and %(max)s pt', { min, max }),
};
}
@ -195,7 +196,7 @@ export default class AppearanceUserSettingsTab extends React.Component<IProps, I
parseInt(value, 10) - FontWatcher.SIZE_DIFF,
);
return {valid: true, feedback: _t('Use between %(min)s pt and %(max)s pt', {min, max})};
return { valid: true, feedback: _t('Use between %(min)s pt and %(max)s pt', { min, max }) };
};
private onAddCustomTheme = async (): Promise<void> => {
@ -212,37 +213,37 @@ export default class AppearanceUserSettingsTab extends React.Component<IProps, I
// XXX: need some schema for this
const themeInfo = await r.json();
if (!themeInfo || typeof(themeInfo['name']) !== 'string' || typeof(themeInfo['colors']) !== 'object') {
this.setState({customThemeMessage: {text: _t("Invalid theme schema."), isError: true}});
this.setState({ customThemeMessage: { text: _t("Invalid theme schema."), isError: true } });
return;
}
currentThemes.push(themeInfo);
} catch (e) {
console.error(e);
this.setState({customThemeMessage: {text: _t("Error downloading theme information."), isError: true}});
this.setState({ customThemeMessage: { text: _t("Error downloading theme information."), isError: true } });
return; // Don't continue on error
}
await SettingsStore.setValue("custom_themes", null, SettingLevel.ACCOUNT, currentThemes);
this.setState({customThemeUrl: "", customThemeMessage: {text: _t("Theme added!"), isError: false}});
this.setState({ customThemeUrl: "", customThemeMessage: { text: _t("Theme added!"), isError: false } });
this.themeTimer = setTimeout(() => {
this.setState({customThemeMessage: {text: "", isError: false}});
this.setState({ customThemeMessage: { text: "", isError: false } });
}, 3000);
};
private onCustomThemeChange = (e: React.ChangeEvent<HTMLSelectElement | HTMLInputElement>): void => {
this.setState({customThemeUrl: e.target.value});
this.setState({ customThemeUrl: e.target.value });
};
private onIRCLayoutChange = (enabled: boolean) => {
if (enabled) {
this.setState({layout: Layout.IRC});
this.setState({ layout: Layout.IRC });
SettingsStore.setValue("layout", null, SettingLevel.DEVICE, Layout.IRC);
} else {
this.setState({layout: Layout.Group});
this.setState({ layout: Layout.Group });
SettingsStore.setValue("layout", null, SettingLevel.DEVICE, Layout.Group);
}
}
};
private renderThemeSection() {
const themeWatcher = new ThemeWatcher();
@ -292,10 +293,10 @@ export default class AppearanceUserSettingsTab extends React.Component<IProps, I
// XXX: replace any type here
const themes = Object.entries<any>(enumerateThemes())
.map(p => ({id: p[0], name: p[1]})); // convert pairs to objects for code readability
.map(p => ({ id: p[0], name: p[1] })); // convert pairs to objects for code readability
const builtInThemes = themes.filter(p => !p.id.startsWith("custom-"));
const customThemes = themes.filter(p => !builtInThemes.includes(p))
.sort((a, b) => a.name.localeCompare(b.name));
.sort((a, b) => compare(a.name, b.name));
const orderedThemes = [...builtInThemes, ...customThemes];
return (
<div className="mx_SettingsTab_section mx_AppearanceUserSettingsTab_themeSection">
@ -347,7 +348,7 @@ export default class AppearanceUserSettingsTab extends React.Component<IProps, I
<SettingsFlag
name="useCustomFontSize"
level={SettingLevel.ACCOUNT}
onChange={(checked) => this.setState({useCustomFontSize: checked})}
onChange={(checked) => this.setState({ useCustomFontSize: checked })}
useCheckbox={true}
/>
@ -359,7 +360,7 @@ export default class AppearanceUserSettingsTab extends React.Component<IProps, I
value={this.state.fontSize.toString()}
id="font_size_field"
onValidate={this.onValidateFontSize}
onChange={(value) => this.setState({fontSize: value.target.value})}
onChange={(value) => this.setState({ fontSize: value.target.value })}
disabled={!this.state.useCustomFontSize}
className="mx_SettingsTab_customFontSizeField"
/>
@ -372,7 +373,7 @@ export default class AppearanceUserSettingsTab extends React.Component<IProps, I
const brand = SdkConfig.get().brand;
const toggle = <div
className="mx_AppearanceUserSettingsTab_AdvancedToggle"
onClick={() => this.setState({showAdvanced: !this.state.showAdvanced})}
onClick={() => this.setState({ showAdvanced: !this.state.showAdvanced })}
>
{this.state.showAdvanced ? _t("Hide advanced") : _t("Show advanced")}
</div>;
@ -402,7 +403,7 @@ export default class AppearanceUserSettingsTab extends React.Component<IProps, I
name="useSystemFont"
level={SettingLevel.DEVICE}
useCheckbox={true}
onChange={(checked) => this.setState({useSystemFont: checked})}
onChange={(checked) => this.setState({ useSystemFont: checked })}
/>
<Field
className="mx_AppearanceUserSettingsTab_systemFont"

View file

@ -15,9 +15,9 @@ limitations under the License.
*/
import React from 'react';
import {_t} from "../../../../../languageHandler";
import { _t } from "../../../../../languageHandler";
import GroupUserSettings from "../../../groups/GroupUserSettings";
import {replaceableComponent} from "../../../../../utils/replaceableComponent";
import { replaceableComponent } from "../../../../../utils/replaceableComponent";
@replaceableComponent("views.settings.tabs.user.FlairUserSettingsTab")
export default class FlairUserSettingsTab extends React.Component {

View file

@ -17,7 +17,7 @@ limitations under the License.
*/
import React from 'react';
import {_t} from "../../../../../languageHandler";
import { _t } from "../../../../../languageHandler";
import ProfileSettings from "../../ProfileSettings";
import * as languageHandler from "../../../../../languageHandler";
import SettingsStore from "../../../../../settings/SettingsStore";
@ -27,19 +27,19 @@ import AccessibleButton from "../../../elements/AccessibleButton";
import DeactivateAccountDialog from "../../../dialogs/DeactivateAccountDialog";
import PropTypes from "prop-types";
import PlatformPeg from "../../../../../PlatformPeg";
import {MatrixClientPeg} from "../../../../../MatrixClientPeg";
import { MatrixClientPeg } from "../../../../../MatrixClientPeg";
import * as sdk from "../../../../..";
import Modal from "../../../../../Modal";
import dis from "../../../../../dispatcher/dispatcher";
import {Service, startTermsFlow} from "../../../../../Terms";
import {SERVICE_TYPES} from "matrix-js-sdk/src/service-types";
import { Service, startTermsFlow } from "../../../../../Terms";
import { SERVICE_TYPES } from "matrix-js-sdk/src/service-types";
import IdentityAuthClient from "../../../../../IdentityAuthClient";
import {abbreviateUrl} from "../../../../../utils/UrlUtils";
import { abbreviateUrl } from "../../../../../utils/UrlUtils";
import { getThreepidsWithBindStatus } from '../../../../../boundThreepids';
import Spinner from "../../../elements/Spinner";
import {SettingLevel} from "../../../../../settings/SettingLevel";
import {UIFeature} from "../../../../../settings/UIFeature";
import {replaceableComponent} from "../../../../../utils/replaceableComponent";
import { SettingLevel } from "../../../../../settings/SettingLevel";
import { UIFeature } from "../../../../../settings/UIFeature";
import { replaceableComponent } from "../../../../../utils/replaceableComponent";
@replaceableComponent("views.settings.tabs.user.GeneralUserSettingsTab")
export default class GeneralUserSettingsTab extends React.Component {
@ -84,7 +84,7 @@ export default class GeneralUserSettingsTab extends React.Component {
// the enabled flag value.
const canChangePassword = !changePasswordCap || changePasswordCap['enabled'] !== false;
this.setState({serverSupportsSeparateAddAndBind, canChangePassword});
this.setState({ serverSupportsSeparateAddAndBind, canChangePassword });
this._getThreepidState();
}
@ -104,7 +104,7 @@ export default class GeneralUserSettingsTab extends React.Component {
_onAction = (payload) => {
if (payload.action === 'id_server_changed') {
this.setState({haveIdServer: Boolean(MatrixClientPeg.get().getIdentityServerUrl())});
this.setState({ haveIdServer: Boolean(MatrixClientPeg.get().getIdentityServerUrl()) });
this._getThreepidState();
}
};
@ -145,7 +145,7 @@ export default class GeneralUserSettingsTab extends React.Component {
async _checkTerms() {
if (!this.state.haveIdServer) {
this.setState({idServerHasUnsignedTerms: false});
this.setState({ idServerHasUnsignedTerms: false });
return;
}
@ -191,7 +191,7 @@ export default class GeneralUserSettingsTab extends React.Component {
if (this.state.language === newLanguage) return;
SettingsStore.setValue("language", null, SettingLevel.DEVICE, newLanguage);
this.setState({language: newLanguage});
this.setState({ language: newLanguage });
const platform = PlatformPeg.get();
if (platform) {
platform.setLanguage(newLanguage);
@ -200,7 +200,7 @@ export default class GeneralUserSettingsTab extends React.Component {
};
_onSpellCheckLanguagesChange = (languages) => {
this.setState({spellCheckLanguages: languages});
this.setState({ spellCheckLanguages: languages });
const plaf = PlatformPeg.get();
if (plaf) {
@ -353,7 +353,7 @@ export default class GeneralUserSettingsTab extends React.Component {
{_t(
"Agree to the identity server (%(serverName)s) Terms of Service to " +
"allow yourself to be discoverable by email address or phone number.",
{serverName: this.state.idServerName},
{ serverName: this.state.idServerName },
)}
</span>;
return (

View file

@ -15,8 +15,8 @@ limitations under the License.
*/
import React from 'react';
import {_t, getCurrentLanguage} from "../../../../../languageHandler";
import {MatrixClientPeg} from "../../../../../MatrixClientPeg";
import { _t, getCurrentLanguage } from "../../../../../languageHandler";
import { MatrixClientPeg } from "../../../../../MatrixClientPeg";
import AccessibleButton from "../../../elements/AccessibleButton";
import AccessibleTooltipButton from '../../../elements/AccessibleTooltipButton';
import SdkConfig from "../../../../../SdkConfig";
@ -32,7 +32,7 @@ import * as ContextMenu from "../../../../structures/ContextMenu";
import { toRightOf } from "../../../../structures/ContextMenu";
interface IProps {
closeSettingsFn: () => {};
closeSettingsFn: () => void;
}
interface IState {
@ -54,10 +54,10 @@ export default class HelpUserSettingsTab extends React.Component<IProps, IState>
}
componentDidMount(): void {
PlatformPeg.get().getAppVersion().then((ver) => this.setState({appVersion: ver})).catch((e) => {
PlatformPeg.get().getAppVersion().then((ver) => this.setState({ appVersion: ver })).catch((e) => {
console.error("Error getting vector version: ", e);
});
PlatformPeg.get().canSelfUpdate().then((v) => this.setState({canUpdate: v})).catch((e) => {
PlatformPeg.get().canSelfUpdate().then((v) => this.setState({ canUpdate: v })).catch((e) => {
console.error("Error getting self updatability: ", e);
});
}
@ -172,12 +172,12 @@ export default class HelpUserSettingsTab extends React.Component<IProps, IState>
const successful = await copyPlaintext(MatrixClientPeg.get().getAccessToken());
const buttonRect = target.getBoundingClientRect();
const GenericTextContextMenu = sdk.getComponent('context_menus.GenericTextContextMenu');
const {close} = ContextMenu.createMenu(GenericTextContextMenu, {
const { close } = ContextMenu.createMenu(GenericTextContextMenu, {
...toRightOf(buttonRect, 2),
message: successful ? _t('Copied!') : _t('Failed to copy'),
});
this.closeCopiedTooltip = target.onmouseleave = close;
}
};
render() {
const brand = SdkConfig.get().brand;

View file

@ -15,13 +15,13 @@ limitations under the License.
*/
import React from 'react';
import {_t} from "../../../../../languageHandler";
import { _t } from "../../../../../languageHandler";
import PropTypes from "prop-types";
import SettingsStore from "../../../../../settings/SettingsStore";
import LabelledToggleSwitch from "../../../elements/LabelledToggleSwitch";
import * as sdk from "../../../../../index";
import {SettingLevel} from "../../../../../settings/SettingLevel";
import {replaceableComponent} from "../../../../../utils/replaceableComponent";
import { SettingLevel } from "../../../../../settings/SettingLevel";
import { replaceableComponent } from "../../../../../utils/replaceableComponent";
import SdkConfig from "../../../../../SdkConfig";
import BetaCard from "../../../beta/BetaCard";

View file

@ -15,15 +15,15 @@ limitations under the License.
*/
import React from 'react';
import {_t} from "../../../../../languageHandler";
import { _t } from "../../../../../languageHandler";
import SdkConfig from "../../../../../SdkConfig";
import {Mjolnir} from "../../../../../mjolnir/Mjolnir";
import {ListRule} from "../../../../../mjolnir/ListRule";
import {BanList, RULE_SERVER, RULE_USER} from "../../../../../mjolnir/BanList";
import { Mjolnir } from "../../../../../mjolnir/Mjolnir";
import { ListRule } from "../../../../../mjolnir/ListRule";
import { BanList, RULE_SERVER, RULE_USER } from "../../../../../mjolnir/BanList";
import Modal from "../../../../../Modal";
import {MatrixClientPeg} from "../../../../../MatrixClientPeg";
import { MatrixClientPeg } from "../../../../../MatrixClientPeg";
import * as sdk from "../../../../../index";
import {replaceableComponent} from "../../../../../utils/replaceableComponent";
import { replaceableComponent } from "../../../../../utils/replaceableComponent";
interface IState {
busy: boolean;
@ -44,11 +44,11 @@ export default class MjolnirUserSettingsTab extends React.Component<{}, IState>
}
private onPersonalRuleChanged = (e) => {
this.setState({newPersonalRule: e.target.value});
this.setState({ newPersonalRule: e.target.value });
};
private onNewListChanged = (e) => {
this.setState({newList: e.target.value});
this.setState({ newList: e.target.value });
};
private onAddPersonalRule = async (e) => {
@ -60,11 +60,11 @@ export default class MjolnirUserSettingsTab extends React.Component<{}, IState>
kind = RULE_USER;
}
this.setState({busy: true});
this.setState({ busy: true });
try {
const list = await Mjolnir.sharedInstance().getOrCreatePersonalList();
await list.banEntity(kind, this.state.newPersonalRule, _t("Ignored/Blocked"));
this.setState({newPersonalRule: ""}); // this will also cause the new rule to be rendered
this.setState({ newPersonalRule: "" }); // this will also cause the new rule to be rendered
} catch (e) {
console.error(e);
@ -74,7 +74,7 @@ export default class MjolnirUserSettingsTab extends React.Component<{}, IState>
description: _t('Something went wrong. Please try again or view your console for hints.'),
});
} finally {
this.setState({busy: false});
this.setState({ busy: false });
}
};
@ -82,11 +82,11 @@ export default class MjolnirUserSettingsTab extends React.Component<{}, IState>
e.preventDefault();
e.stopPropagation();
this.setState({busy: true});
this.setState({ busy: true });
try {
const room = await MatrixClientPeg.get().joinRoom(this.state.newList);
await Mjolnir.sharedInstance().subscribeToList(room.roomId);
this.setState({newList: ""}); // this will also cause the new rule to be rendered
this.setState({ newList: "" }); // this will also cause the new rule to be rendered
} catch (e) {
console.error(e);
@ -96,12 +96,12 @@ export default class MjolnirUserSettingsTab extends React.Component<{}, IState>
description: _t('Please verify the room ID or address and try again.'),
});
} finally {
this.setState({busy: false});
this.setState({ busy: false });
}
};
private async removePersonalRule(rule: ListRule) {
this.setState({busy: true});
this.setState({ busy: true });
try {
const list = Mjolnir.sharedInstance().getPersonalList();
await list.unbanEntity(rule.kind, rule.entity);
@ -114,12 +114,12 @@ export default class MjolnirUserSettingsTab extends React.Component<{}, IState>
description: _t('Something went wrong. Please try again or view your console for hints.'),
});
} finally {
this.setState({busy: false});
this.setState({ busy: false });
}
}
private async unsubscribeFromList(list: BanList) {
this.setState({busy: true});
this.setState({ busy: true });
try {
await Mjolnir.sharedInstance().unsubscribeFromList(list.roomId);
await MatrixClientPeg.get().leave(list.roomId);
@ -132,7 +132,7 @@ export default class MjolnirUserSettingsTab extends React.Component<{}, IState>
description: _t('Please try again or view your console for hints.'),
});
} finally {
this.setState({busy: false});
this.setState({ busy: false });
}
}
@ -153,7 +153,7 @@ export default class MjolnirUserSettingsTab extends React.Component<{}, IState>
};
Modal.createTrackedDialog('View Mjolnir list rules', '', QuestionDialog, {
title: _t("Ban list rules - %(roomName)s", {roomName: name}),
title: _t("Ban list rules - %(roomName)s", { roomName: name }),
description: (
<div>
<h3>{_t("Server rules")}</h3>
@ -256,7 +256,7 @@ export default class MjolnirUserSettingsTab extends React.Component<{}, IState>
"Add users and servers you want to ignore here. Use asterisks " +
"to have %(brand)s match any characters. For example, <code>@bot:*</code> " +
"would ignore all users that have the name 'bot' on any server.",
{ brand }, {code: (s) => <code>{s}</code>},
{ brand }, { code: (s) => <code>{s}</code> },
)}<br />
<br />
{_t(

View file

@ -15,9 +15,9 @@ limitations under the License.
*/
import React from 'react';
import {_t} from "../../../../../languageHandler";
import { _t } from "../../../../../languageHandler";
import * as sdk from "../../../../../index";
import {replaceableComponent} from "../../../../../utils/replaceableComponent";
import { replaceableComponent } from "../../../../../utils/replaceableComponent";
@replaceableComponent("views.settings.tabs.user.NotificationUserSettingsTab")
export default class NotificationUserSettingsTab extends React.Component {

View file

@ -16,13 +16,13 @@ limitations under the License.
*/
import React from 'react';
import {_t} from "../../../../../languageHandler";
import { _t } from "../../../../../languageHandler";
import LabelledToggleSwitch from "../../../elements/LabelledToggleSwitch";
import SettingsStore from "../../../../../settings/SettingsStore";
import Field from "../../../elements/Field";
import * as sdk from "../../../../..";
import PlatformPeg from "../../../../../PlatformPeg";
import {SettingLevel} from "../../../../../settings/SettingLevel";
import { SettingLevel } from "../../../../../settings/SettingLevel";
import { replaceableComponent } from "../../../../../utils/replaceableComponent";
interface IState {
@ -151,33 +151,33 @@ export default class PreferencesUserSettingsTab extends React.Component<{}, ISta
}
private onAutoLaunchChange = (checked: boolean) => {
PlatformPeg.get().setAutoLaunchEnabled(checked).then(() => this.setState({autoLaunch: checked}));
PlatformPeg.get().setAutoLaunchEnabled(checked).then(() => this.setState({ autoLaunch: checked }));
};
private onWarnBeforeExitChange = (checked: boolean) => {
PlatformPeg.get().setWarnBeforeExit(checked).then(() => this.setState({warnBeforeExit: checked}));
}
PlatformPeg.get().setWarnBeforeExit(checked).then(() => this.setState({ warnBeforeExit: checked }));
};
private onAlwaysShowMenuBarChange = (checked: boolean) => {
PlatformPeg.get().setAutoHideMenuBarEnabled(!checked).then(() => this.setState({alwaysShowMenuBar: checked}));
PlatformPeg.get().setAutoHideMenuBarEnabled(!checked).then(() => this.setState({ alwaysShowMenuBar: checked }));
};
private onMinimizeToTrayChange = (checked: boolean) => {
PlatformPeg.get().setMinimizeToTrayEnabled(checked).then(() => this.setState({minimizeToTray: checked}));
PlatformPeg.get().setMinimizeToTrayEnabled(checked).then(() => this.setState({ minimizeToTray: checked }));
};
private onAutocompleteDelayChange = (e: React.ChangeEvent<HTMLInputElement>) => {
this.setState({autocompleteDelay: e.target.value});
this.setState({ autocompleteDelay: e.target.value });
SettingsStore.setValue("autocompleteDelay", null, SettingLevel.DEVICE, e.target.value);
};
private onReadMarkerInViewThresholdMs = (e: React.ChangeEvent<HTMLInputElement>) => {
this.setState({readMarkerInViewThresholdMs: e.target.value});
this.setState({ readMarkerInViewThresholdMs: e.target.value });
SettingsStore.setValue("readMarkerInViewThresholdMs", null, SettingLevel.DEVICE, e.target.value);
};
private onReadMarkerOutOfViewThresholdMs = (e: React.ChangeEvent<HTMLInputElement>) => {
this.setState({readMarkerOutOfViewThresholdMs: e.target.value});
this.setState({ readMarkerOutOfViewThresholdMs: e.target.value });
SettingsStore.setValue("readMarkerOutOfViewThresholdMs", null, SettingLevel.DEVICE, e.target.value);
};

View file

@ -17,24 +17,24 @@ limitations under the License.
import React from 'react';
import PropTypes from 'prop-types';
import {_t} from "../../../../../languageHandler";
import { _t } from "../../../../../languageHandler";
import SdkConfig from "../../../../../SdkConfig";
import {MatrixClientPeg} from "../../../../../MatrixClientPeg";
import { MatrixClientPeg } from "../../../../../MatrixClientPeg";
import * as FormattingUtils from "../../../../../utils/FormattingUtils";
import AccessibleButton from "../../../elements/AccessibleButton";
import Analytics from "../../../../../Analytics";
import Modal from "../../../../../Modal";
import * as sdk from "../../../../..";
import {sleep} from "../../../../../utils/promise";
import { sleep } from "../../../../../utils/promise";
import dis from "../../../../../dispatcher/dispatcher";
import {privateShouldBeEncrypted} from "../../../../../createRoom";
import {SettingLevel} from "../../../../../settings/SettingLevel";
import { privateShouldBeEncrypted } from "../../../../../createRoom";
import { SettingLevel } from "../../../../../settings/SettingLevel";
import SecureBackupPanel from "../../SecureBackupPanel";
import SettingsStore from "../../../../../settings/SettingsStore";
import {UIFeature} from "../../../../../settings/UIFeature";
import {isE2eAdvancedPanelPossible} from "../../E2eAdvancedPanel";
import { UIFeature } from "../../../../../settings/UIFeature";
import { isE2eAdvancedPanelPossible } from "../../E2eAdvancedPanel";
import CountlyAnalytics from "../../../../../CountlyAnalytics";
import {replaceableComponent} from "../../../../../utils/replaceableComponent";
import { replaceableComponent } from "../../../../../utils/replaceableComponent";
export class IgnoredUser extends React.Component {
static propTypes = {
@ -82,12 +82,11 @@ export default class SecurityUserSettingsTab extends React.Component {
this._onAction = this._onAction.bind(this);
}
_onAction({action}) {
_onAction({ action }) {
if (action === "ignore_state_changed") {
const ignoredUserIds = MatrixClientPeg.get().getIgnoredUsers();
const newWaitingUnignored = this.state.waitingUnignored.filter(e=> ignoredUserIds.includes(e));
this.setState({ignoredUserIds, waitingUnignored: newWaitingUnignored});
this.setState({ ignoredUserIds, waitingUnignored: newWaitingUnignored });
}
}
@ -111,14 +110,14 @@ export default class SecurityUserSettingsTab extends React.Component {
_onExportE2eKeysClicked = () => {
Modal.createTrackedDialogAsync('Export E2E Keys', '',
import('../../../../../async-components/views/dialogs/security/ExportE2eKeysDialog'),
{matrixClient: MatrixClientPeg.get()},
{ matrixClient: MatrixClientPeg.get() },
);
};
_onImportE2eKeysClicked = () => {
Modal.createTrackedDialogAsync('Import E2E Keys', '',
import('../../../../../async-components/views/dialogs/security/ImportE2eKeysDialog'),
{matrixClient: MatrixClientPeg.get()},
{ matrixClient: MatrixClientPeg.get() },
);
};
@ -131,13 +130,13 @@ export default class SecurityUserSettingsTab extends React.Component {
}
_onUserUnignored = async (userId) => {
const {ignoredUserIds, waitingUnignored} = this.state;
const { ignoredUserIds, waitingUnignored } = this.state;
const currentlyIgnoredUserIds = ignoredUserIds.filter(e => !waitingUnignored.includes(e));
const index = currentlyIgnoredUserIds.indexOf(userId);
if (index !== -1) {
currentlyIgnoredUserIds.splice(index, 1);
this.setState(({waitingUnignored}) => ({waitingUnignored: [...waitingUnignored, userId]}));
this.setState(({ waitingUnignored }) => ({ waitingUnignored: [...waitingUnignored, userId] }));
MatrixClientPeg.get().setIgnoredUsers(currentlyIgnoredUserIds);
}
};
@ -168,7 +167,7 @@ export default class SecurityUserSettingsTab extends React.Component {
// Accept/reject invite
await action(roomId).then(() => {
// No error, update invited rooms button
this.setState({invitedRoomAmt: self.state.invitedRoomAmt - 1});
this.setState({ invitedRoomAmt: self.state.invitedRoomAmt - 1 });
}, async (e) => {
// Action failure
if (e.errcode === "M_LIMIT_EXCEEDED") {
@ -253,7 +252,7 @@ export default class SecurityUserSettingsTab extends React.Component {
}
_renderIgnoredUsers() {
const {waitingUnignored, ignoredUserIds} = this.state;
const { waitingUnignored, ignoredUserIds } = this.state;
const userIds = !ignoredUserIds?.length
? _t('You have no ignored users.')
@ -291,10 +290,10 @@ export default class SecurityUserSettingsTab extends React.Component {
<div className='mx_SettingsTab_section mx_SecurityUserSettingsTab_bulkOptions'>
<span className='mx_SettingsTab_subheading'>{_t('Bulk options')}</span>
<AccessibleButton onClick={onClickAccept} kind='primary' disabled={this.state.managingInvites}>
{_t("Accept all %(invitedRooms)s invites", {invitedRooms: this.state.invitedRoomAmt})}
{_t("Accept all %(invitedRooms)s invites", { invitedRooms: this.state.invitedRoomAmt })}
</AccessibleButton>
<AccessibleButton onClick={onClickReject} kind='danger' disabled={this.state.managingInvites}>
{_t("Reject all %(invitedRooms)s invites", {invitedRooms: this.state.invitedRoomAmt})}
{_t("Reject all %(invitedRooms)s invites", { invitedRooms: this.state.invitedRoomAmt })}
</AccessibleButton>
{this.state.managingInvites ? <InlineSpinner /> : <div />}
</div>

View file

@ -16,16 +16,16 @@ limitations under the License.
*/
import React from 'react';
import {_t} from "../../../../../languageHandler";
import { _t } from "../../../../../languageHandler";
import SdkConfig from "../../../../../SdkConfig";
import CallMediaHandler from "../../../../../CallMediaHandler";
import MediaDeviceHandler from "../../../../../MediaDeviceHandler";
import Field from "../../../elements/Field";
import AccessibleButton from "../../../elements/AccessibleButton";
import {MatrixClientPeg} from "../../../../../MatrixClientPeg";
import { MatrixClientPeg } from "../../../../../MatrixClientPeg";
import * as sdk from "../../../../../index";
import Modal from "../../../../../Modal";
import {SettingLevel} from "../../../../../settings/SettingLevel";
import {replaceableComponent} from "../../../../../utils/replaceableComponent";
import { SettingLevel } from "../../../../../settings/SettingLevel";
import { replaceableComponent } from "../../../../../utils/replaceableComponent";
@replaceableComponent("views.settings.tabs.user.VoiceUserSettingsTab")
export default class VoiceUserSettingsTab extends React.Component {
@ -41,7 +41,7 @@ export default class VoiceUserSettingsTab extends React.Component {
}
async componentDidMount() {
const canSeeDeviceLabels = await CallMediaHandler.hasAnyLabeledDevices();
const canSeeDeviceLabels = await MediaDeviceHandler.hasAnyLabeledDevices();
if (canSeeDeviceLabels) {
this._refreshMediaDevices();
}
@ -49,10 +49,10 @@ export default class VoiceUserSettingsTab extends React.Component {
_refreshMediaDevices = async (stream) => {
this.setState({
mediaDevices: await CallMediaHandler.getDevices(),
activeAudioOutput: CallMediaHandler.getAudioOutput(),
activeAudioInput: CallMediaHandler.getAudioInput(),
activeVideoInput: CallMediaHandler.getVideoInput(),
mediaDevices: await MediaDeviceHandler.getDevices(),
activeAudioOutput: MediaDeviceHandler.getAudioOutput(),
activeAudioInput: MediaDeviceHandler.getAudioInput(),
activeVideoInput: MediaDeviceHandler.getVideoInput(),
});
if (stream) {
// kill stream (after we've enumerated the devices, otherwise we'd get empty labels again)
@ -67,7 +67,7 @@ export default class VoiceUserSettingsTab extends React.Component {
let stream;
let error;
try {
constraints = {video: true, audio: true};
constraints = { video: true, audio: true };
stream = await navigator.mediaDevices.getUserMedia(constraints);
} catch (err) {
// user likely doesn't have a webcam,
@ -100,21 +100,21 @@ export default class VoiceUserSettingsTab extends React.Component {
};
_setAudioOutput = (e) => {
CallMediaHandler.setAudioOutput(e.target.value);
MediaDeviceHandler.instance.setAudioOutput(e.target.value);
this.setState({
activeAudioOutput: e.target.value,
});
};
_setAudioInput = (e) => {
CallMediaHandler.setAudioInput(e.target.value);
MediaDeviceHandler.instance.setAudioInput(e.target.value);
this.setState({
activeAudioInput: e.target.value,
});
};
_setVideoInput = (e) => {
CallMediaHandler.setVideoInput(e.target.value);
MediaDeviceHandler.instance.setVideoInput(e.target.value);
this.setState({
activeVideoInput: e.target.value,
});
@ -171,7 +171,7 @@ export default class VoiceUserSettingsTab extends React.Component {
}
};
const audioOutputs = this.state.mediaDevices.audiooutput.slice(0);
const audioOutputs = this.state.mediaDevices.audioOutput.slice(0);
if (audioOutputs.length > 0) {
const defaultDevice = getDefaultDevice(audioOutputs);
speakerDropdown = (
@ -183,7 +183,7 @@ export default class VoiceUserSettingsTab extends React.Component {
);
}
const audioInputs = this.state.mediaDevices.audioinput.slice(0);
const audioInputs = this.state.mediaDevices.audioInput.slice(0);
if (audioInputs.length > 0) {
const defaultDevice = getDefaultDevice(audioInputs);
microphoneDropdown = (
@ -195,7 +195,7 @@ export default class VoiceUserSettingsTab extends React.Component {
);
}
const videoInputs = this.state.mediaDevices.videoinput.slice(0);
const videoInputs = this.state.mediaDevices.videoInput.slice(0);
if (videoInputs.length > 0) {
const defaultDevice = getDefaultDevice(videoInputs);
webcamDropdown = (