Merge branch 'develop' into warn-on-access-token-reveal
This commit is contained in:
commit
f3c0fc96a3
595 changed files with 18938 additions and 5994 deletions
|
@ -16,9 +16,7 @@ limitations under the License.
|
|||
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import {getHttpUriForMxc} from "matrix-js-sdk/src/content-repo";
|
||||
import {_t} from "../../../languageHandler";
|
||||
import {MatrixClientPeg} from "../../../MatrixClientPeg";
|
||||
import Pill from "../elements/Pill";
|
||||
import {makeUserPermalink} from "../../../utils/permalinks/Permalinks";
|
||||
import BaseAvatar from "../avatars/BaseAvatar";
|
||||
|
@ -26,6 +24,8 @@ import SettingsStore from "../../../settings/SettingsStore";
|
|||
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";
|
||||
|
||||
interface IProps {
|
||||
ev: MatrixEvent;
|
||||
|
@ -64,6 +64,7 @@ interface IBridgeStateEvent {
|
|||
};
|
||||
}
|
||||
|
||||
@replaceableComponent("views.settings.BridgeTile")
|
||||
export default class BridgeTile extends React.PureComponent<IProps> {
|
||||
static propTypes = {
|
||||
ev: PropTypes.object.isRequired,
|
||||
|
@ -112,10 +113,7 @@ export default class BridgeTile extends React.PureComponent<IProps> {
|
|||
let networkIcon;
|
||||
|
||||
if (protocol.avatar_url) {
|
||||
const avatarUrl = getHttpUriForMxc(
|
||||
MatrixClientPeg.get().getHomeserverUrl(),
|
||||
protocol.avatar_url, 64, 64, "crop",
|
||||
);
|
||||
const avatarUrl = mediaFromMxc(protocol.avatar_url).getSquareThumbnailHttp(64);
|
||||
|
||||
networkIcon = <BaseAvatar className="protocol-icon"
|
||||
width={48}
|
||||
|
|
|
@ -20,7 +20,10 @@ 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";
|
||||
|
||||
@replaceableComponent("views.settings.ChangeAvatar")
|
||||
export default class ChangeAvatar extends React.Component {
|
||||
static propTypes = {
|
||||
initialAvatarUrl: PropTypes.string,
|
||||
|
@ -115,7 +118,7 @@ export default class ChangeAvatar extends React.Component {
|
|||
httpPromise.then(function() {
|
||||
self.setState({
|
||||
phase: ChangeAvatar.Phases.Display,
|
||||
avatarUrl: MatrixClientPeg.get().mxcUrlToHttp(newUrl),
|
||||
avatarUrl: mediaFromMxc(newUrl).srcHttp,
|
||||
});
|
||||
}, function(error) {
|
||||
self.setState({
|
||||
|
|
|
@ -20,7 +20,9 @@ import React from 'react';
|
|||
import * as sdk from '../../../index';
|
||||
import {MatrixClientPeg} from '../../../MatrixClientPeg';
|
||||
import { _t } from '../../../languageHandler';
|
||||
import {replaceableComponent} from "../../../utils/replaceableComponent";
|
||||
|
||||
@replaceableComponent("views.settings.ChangeDisplayName")
|
||||
export default class ChangeDisplayName extends React.Component {
|
||||
_getDisplayName = async () => {
|
||||
const cli = MatrixClientPeg.get();
|
||||
|
|
|
@ -27,13 +27,14 @@ import * as sdk from "../../../index";
|
|||
import Modal from "../../../Modal";
|
||||
import PassphraseField from "../auth/PassphraseField";
|
||||
import CountlyAnalytics from "../../../CountlyAnalytics";
|
||||
import {replaceableComponent} from "../../../utils/replaceableComponent";
|
||||
import { PASSWORD_MIN_SCORE } from '../auth/RegistrationForm';
|
||||
|
||||
const FIELD_OLD_PASSWORD = 'field_old_password';
|
||||
const FIELD_NEW_PASSWORD = 'field_new_password';
|
||||
const FIELD_NEW_PASSWORD_CONFIRM = 'field_new_password_confirm';
|
||||
|
||||
const PASSWORD_MIN_SCORE = 3; // safely unguessable: moderate protection from offline slow-hash scenario.
|
||||
|
||||
@replaceableComponent("views.settings.ChangePassword")
|
||||
export default class ChangePassword extends React.Component {
|
||||
static propTypes = {
|
||||
onFinished: PropTypes.func,
|
||||
|
|
|
@ -23,7 +23,9 @@ 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";
|
||||
|
||||
@replaceableComponent("views.settings.CrossSigningPanel")
|
||||
export default class CrossSigningPanel extends React.PureComponent {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
|
|
@ -24,7 +24,9 @@ import {MatrixClientPeg} from '../../../MatrixClientPeg';
|
|||
import { _t } from '../../../languageHandler';
|
||||
import Modal from '../../../Modal';
|
||||
import {SSOAuthEntry} from "../auth/InteractiveAuthEntryComponents";
|
||||
import {replaceableComponent} from "../../../utils/replaceableComponent";
|
||||
|
||||
@replaceableComponent("views.settings.DevicesPanel")
|
||||
export default class DevicesPanel extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
|
|
@ -22,7 +22,9 @@ import { _t } from '../../../languageHandler';
|
|||
import {MatrixClientPeg} from '../../../MatrixClientPeg';
|
||||
import {formatDate} from '../../../DateUtils';
|
||||
import StyledCheckbox from '../elements/StyledCheckbox';
|
||||
import {replaceableComponent} from "../../../utils/replaceableComponent";
|
||||
|
||||
@replaceableComponent("views.settings.DevicesPanelEntry")
|
||||
export default class DevicesPanelEntry extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
|
|
@ -25,7 +25,10 @@ import AccessibleButton from "../elements/AccessibleButton";
|
|||
import {formatBytes, formatCountLong} from "../../../utils/FormattingUtils";
|
||||
import EventIndexPeg from "../../../indexing/EventIndexPeg";
|
||||
import {SettingLevel} from "../../../settings/SettingLevel";
|
||||
import {replaceableComponent} from "../../../utils/replaceableComponent";
|
||||
import SeshatResetDialog from '../dialogs/SeshatResetDialog';
|
||||
|
||||
@replaceableComponent("views.settings.EventIndexPanel")
|
||||
export default class EventIndexPanel extends React.Component {
|
||||
constructor() {
|
||||
super();
|
||||
|
@ -120,6 +123,20 @@ export default class EventIndexPanel extends React.Component {
|
|||
await this.updateState();
|
||||
}
|
||||
|
||||
_confirmEventStoreReset = () => {
|
||||
const self = this;
|
||||
const { close } = Modal.createDialog(SeshatResetDialog, {
|
||||
onFinished: async (success) => {
|
||||
if (success) {
|
||||
await SettingsStore.setValue('enableEventIndexing', null, SettingLevel.DEVICE, false);
|
||||
await EventIndexPeg.deleteEventIndex();
|
||||
await self._onEnable();
|
||||
close();
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
let eventIndexingSettings = null;
|
||||
const InlineSpinner = sdk.getComponent('elements.InlineSpinner');
|
||||
|
@ -165,7 +182,7 @@ export default class EventIndexPanel extends React.Component {
|
|||
);
|
||||
} else if (EventIndexPeg.platformHasSupport() && !EventIndexPeg.supportIsInstalled()) {
|
||||
const nativeLink = (
|
||||
"https://github.com/vector-im/element-web/blob/develop/" +
|
||||
"https://github.com/vector-im/element-desktop/blob/develop/" +
|
||||
"docs/native-node-modules.md#" +
|
||||
"adding-seshat-for-search-in-e2e-encrypted-rooms"
|
||||
);
|
||||
|
@ -188,7 +205,7 @@ export default class EventIndexPanel extends React.Component {
|
|||
}
|
||||
</div>
|
||||
);
|
||||
} else {
|
||||
} else if (!EventIndexPeg.platformHasSupport()) {
|
||||
eventIndexingSettings = (
|
||||
<div className='mx_SettingsTab_subsectionText'>
|
||||
{
|
||||
|
@ -206,6 +223,31 @@ export default class EventIndexPanel extends React.Component {
|
|||
}
|
||||
</div>
|
||||
);
|
||||
} else {
|
||||
eventIndexingSettings = (
|
||||
<div className='mx_SettingsTab_subsectionText'>
|
||||
<p>
|
||||
{this.state.enabling
|
||||
? <InlineSpinner />
|
||||
: _t("Message search initilisation failed")
|
||||
}
|
||||
</p>
|
||||
{EventIndexPeg.error && (
|
||||
<details>
|
||||
<summary>{_t("Advanced")}</summary>
|
||||
<code>
|
||||
{EventIndexPeg.error.message}
|
||||
</code>
|
||||
<p>
|
||||
<AccessibleButton key="delete" kind="danger" onClick={this._confirmEventStoreReset}>
|
||||
{_t("Reset")}
|
||||
</AccessibleButton>
|
||||
</p>
|
||||
</details>
|
||||
)}
|
||||
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return eventIndexingSettings;
|
||||
|
|
|
@ -21,7 +21,9 @@ import * as sdk from '../../../index';
|
|||
import { _t } from '../../../languageHandler';
|
||||
import dis from '../../../dispatcher/dispatcher';
|
||||
import {Key} from "../../../Keyboard";
|
||||
import {replaceableComponent} from "../../../utils/replaceableComponent";
|
||||
|
||||
@replaceableComponent("views.settings.IntegrationManager")
|
||||
export default class IntegrationManager extends React.Component {
|
||||
static propTypes = {
|
||||
// false to display an error saying that we couldn't connect to the integration manager
|
||||
|
|
|
@ -32,6 +32,7 @@ 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";
|
||||
|
||||
// TODO: this "view" component still has far too much application logic in it,
|
||||
// which should be factored out to other files.
|
||||
|
@ -65,6 +66,7 @@ function portLegacyActions(actions) {
|
|||
}
|
||||
}
|
||||
|
||||
@replaceableComponent("views.settings.Notifications")
|
||||
export default class Notifications extends React.Component {
|
||||
static phases = {
|
||||
LOADING: "LOADING", // The component is loading or sending data to the hs
|
||||
|
|
|
@ -23,14 +23,17 @@ import * as sdk from "../../../index";
|
|||
import {OwnProfileStore} from "../../../stores/OwnProfileStore";
|
||||
import Modal from "../../../Modal";
|
||||
import ErrorDialog from "../dialogs/ErrorDialog";
|
||||
import {replaceableComponent} from "../../../utils/replaceableComponent";
|
||||
import {mediaFromMxc} from "../../../customisations/Media";
|
||||
|
||||
@replaceableComponent("views.settings.ProfileSettings")
|
||||
export default class ProfileSettings extends React.Component {
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
const client = MatrixClientPeg.get();
|
||||
let avatarUrl = OwnProfileStore.instance.avatarMxc;
|
||||
if (avatarUrl) avatarUrl = client.mxcUrlToHttp(avatarUrl, 96, 96, 'crop', false);
|
||||
if (avatarUrl) avatarUrl = mediaFromMxc(avatarUrl).getSquareThumbnailHttp(96);
|
||||
this.state = {
|
||||
userId: client.getUserId(),
|
||||
originalDisplayName: OwnProfileStore.instance.displayName,
|
||||
|
@ -95,7 +98,7 @@ export default class ProfileSettings extends React.Component {
|
|||
` (${this.state.avatarFile.size}) bytes`);
|
||||
const uri = await client.uploadContent(this.state.avatarFile);
|
||||
await client.setAvatarUrl(uri);
|
||||
newState.avatarUrl = client.mxcUrlToHttp(uri, 96, 96, 'crop', false);
|
||||
newState.avatarUrl = mediaFromMxc(uri).getSquareThumbnailHttp(96);
|
||||
newState.originalAvatarUrl = newState.avatarUrl;
|
||||
newState.avatarFile = null;
|
||||
} else if (this.state.originalAvatarUrl !== this.state.avatarUrl) {
|
||||
|
|
|
@ -26,7 +26,9 @@ 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";
|
||||
|
||||
@replaceableComponent("views.settings.SecureBackupPanel")
|
||||
export default class SecureBackupPanel extends React.PureComponent {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
|
|
@ -27,6 +27,7 @@ import IdentityAuthClient from "../../../IdentityAuthClient";
|
|||
import {abbreviateUrl, unabbreviateUrl} from "../../../utils/UrlUtils";
|
||||
import { getDefaultIdentityServerUrl, doesIdentityServerHaveTerms } from '../../../utils/IdentityServerUtils';
|
||||
import {timeout} from "../../../utils/promise";
|
||||
import {replaceableComponent} from "../../../utils/replaceableComponent";
|
||||
|
||||
// We'll wait up to this long when checking for 3PID bindings on the IS.
|
||||
const REACHABILITY_TIMEOUT = 10000; // ms
|
||||
|
@ -58,6 +59,7 @@ async function checkIdentityServerUrl(u) {
|
|||
}
|
||||
}
|
||||
|
||||
@replaceableComponent("views.settings.SetIdServer")
|
||||
export default class SetIdServer extends React.Component {
|
||||
static propTypes = {
|
||||
// Whether or not the ID server is missing terms. This affects the text
|
||||
|
|
|
@ -20,7 +20,9 @@ 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";
|
||||
|
||||
@replaceableComponent("views.settings.SetIntegrationManager")
|
||||
export default class SetIntegrationManager extends React.Component {
|
||||
constructor() {
|
||||
super();
|
||||
|
|
|
@ -18,6 +18,7 @@ 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";
|
||||
|
||||
interface ExistingSpellCheckLanguageIProps {
|
||||
language: string,
|
||||
|
@ -53,6 +54,7 @@ export class ExistingSpellCheckLanguage extends React.Component<ExistingSpellChe
|
|||
}
|
||||
}
|
||||
|
||||
@replaceableComponent("views.settings.SpellCheckLanguages")
|
||||
export default class SpellCheckLanguages extends React.Component<SpellCheckLanguagesIProps, SpellCheckLanguagesIState> {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
|
|
@ -25,6 +25,7 @@ import * as Email from "../../../../email";
|
|||
import AddThreepid from "../../../../AddThreepid";
|
||||
import * as sdk from '../../../../index';
|
||||
import Modal from '../../../../Modal';
|
||||
import {replaceableComponent} from "../../../../utils/replaceableComponent";
|
||||
|
||||
/*
|
||||
TODO: Improve the UX for everything in here.
|
||||
|
@ -112,6 +113,7 @@ export class ExistingEmailAddress extends React.Component {
|
|||
}
|
||||
}
|
||||
|
||||
@replaceableComponent("views.settings.account.EmailAddresses")
|
||||
export default class EmailAddresses extends React.Component {
|
||||
static propTypes = {
|
||||
emails: PropTypes.array.isRequired,
|
||||
|
|
|
@ -25,6 +25,7 @@ import AddThreepid from "../../../../AddThreepid";
|
|||
import CountryDropdown from "../../auth/CountryDropdown";
|
||||
import * as sdk from '../../../../index';
|
||||
import Modal from '../../../../Modal';
|
||||
import {replaceableComponent} from "../../../../utils/replaceableComponent";
|
||||
|
||||
/*
|
||||
TODO: Improve the UX for everything in here.
|
||||
|
@ -107,6 +108,7 @@ export class ExistingPhoneNumber extends React.Component {
|
|||
}
|
||||
}
|
||||
|
||||
@replaceableComponent("views.settings.account.PhoneNumbers")
|
||||
export default class PhoneNumbers extends React.Component {
|
||||
static propTypes = {
|
||||
msisdns: PropTypes.array.isRequired,
|
||||
|
|
|
@ -23,6 +23,7 @@ import {MatrixClientPeg} from "../../../../MatrixClientPeg";
|
|||
import * as sdk from '../../../../index';
|
||||
import Modal from '../../../../Modal';
|
||||
import AddThreepid from '../../../../AddThreepid';
|
||||
import {replaceableComponent} from "../../../../utils/replaceableComponent";
|
||||
|
||||
/*
|
||||
TODO: Improve the UX for everything in here.
|
||||
|
@ -202,6 +203,7 @@ export class EmailAddress extends React.Component {
|
|||
className="mx_ExistingEmailAddress_confirmBtn"
|
||||
kind="primary_sm"
|
||||
onClick={this.onContinueClick}
|
||||
disabled={this.state.continueDisabled}
|
||||
>
|
||||
{_t("Complete")}
|
||||
</AccessibleButton>
|
||||
|
@ -233,6 +235,7 @@ export class EmailAddress extends React.Component {
|
|||
}
|
||||
}
|
||||
|
||||
@replaceableComponent("views.settings.discovery.EmailAddresses")
|
||||
export default class EmailAddresses extends React.Component {
|
||||
static propTypes = {
|
||||
emails: PropTypes.array.isRequired,
|
||||
|
|
|
@ -23,6 +23,7 @@ import {MatrixClientPeg} from "../../../../MatrixClientPeg";
|
|||
import * as sdk from '../../../../index';
|
||||
import Modal from '../../../../Modal';
|
||||
import AddThreepid from '../../../../AddThreepid';
|
||||
import {replaceableComponent} from "../../../../utils/replaceableComponent";
|
||||
|
||||
/*
|
||||
TODO: Improve the UX for everything in here.
|
||||
|
@ -246,6 +247,7 @@ export class PhoneNumber extends React.Component {
|
|||
}
|
||||
}
|
||||
|
||||
@replaceableComponent("views.settings.discovery.PhoneNumbers")
|
||||
export default class PhoneNumbers extends React.Component {
|
||||
static propTypes = {
|
||||
msisdns: PropTypes.array.isRequired,
|
||||
|
|
|
@ -22,7 +22,9 @@ import * as sdk from "../../../../..";
|
|||
import AccessibleButton from "../../../elements/AccessibleButton";
|
||||
import Modal from "../../../../../Modal";
|
||||
import dis from "../../../../../dispatcher/dispatcher";
|
||||
import {replaceableComponent} from "../../../../../utils/replaceableComponent";
|
||||
|
||||
@replaceableComponent("views.settings.tabs.room.AdvancedRoomSettingsTab")
|
||||
export default class AdvancedRoomSettingsTab extends React.Component {
|
||||
static propTypes = {
|
||||
roomId: PropTypes.string.isRequired,
|
||||
|
|
|
@ -21,6 +21,7 @@ import {MatrixEvent} from "matrix-js-sdk/src/models/event";
|
|||
import {_t} from "../../../../../languageHandler";
|
||||
import {MatrixClientPeg} from "../../../../../MatrixClientPeg";
|
||||
import BridgeTile from "../../BridgeTile";
|
||||
import {replaceableComponent} from "../../../../../utils/replaceableComponent";
|
||||
|
||||
const BRIDGE_EVENT_TYPES = [
|
||||
"uk.half-shot.bridge",
|
||||
|
@ -33,6 +34,7 @@ interface IProps {
|
|||
roomId: string;
|
||||
}
|
||||
|
||||
@replaceableComponent("views.settings.tabs.room.BridgeSettingsTab")
|
||||
export default class BridgeSettingsTab extends React.Component<IProps> {
|
||||
private renderBridgeCard(event: MatrixEvent, room: Room) {
|
||||
const content = event.getContent();
|
||||
|
|
|
@ -24,7 +24,9 @@ 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";
|
||||
|
||||
@replaceableComponent("views.settings.tabs.room.GeneralRoomSettingsTab")
|
||||
export default class GeneralRoomSettingsTab extends React.Component {
|
||||
static propTypes = {
|
||||
roomId: PropTypes.string.isRequired,
|
||||
|
|
|
@ -22,7 +22,9 @@ import AccessibleButton from "../../../elements/AccessibleButton";
|
|||
import Notifier from "../../../../../Notifier";
|
||||
import SettingsStore from '../../../../../settings/SettingsStore';
|
||||
import {SettingLevel} from "../../../../../settings/SettingLevel";
|
||||
import {replaceableComponent} from "../../../../../utils/replaceableComponent";
|
||||
|
||||
@replaceableComponent("views.settings.tabs.room.NotificationsSettingsTab")
|
||||
export default class NotificationsSettingsTab extends React.Component {
|
||||
static propTypes = {
|
||||
roomId: PropTypes.string.isRequired,
|
||||
|
|
|
@ -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.
|
||||
|
@ -21,17 +21,20 @@ 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";
|
||||
|
||||
const plEventsToLabels = {
|
||||
// These will be translated for us later.
|
||||
"m.room.avatar": _td("Change room avatar"),
|
||||
"m.room.name": _td("Change room name"),
|
||||
"m.room.canonical_alias": _td("Change main address for the room"),
|
||||
"m.room.history_visibility": _td("Change history visibility"),
|
||||
"m.room.power_levels": _td("Change permissions"),
|
||||
"m.room.topic": _td("Change topic"),
|
||||
"m.room.tombstone": _td("Upgrade the room"),
|
||||
"m.room.encryption": _td("Enable room encryption"),
|
||||
[EventType.RoomAvatar]: _td("Change room avatar"),
|
||||
[EventType.RoomName]: _td("Change room name"),
|
||||
[EventType.RoomCanonicalAlias]: _td("Change main address for the room"),
|
||||
[EventType.RoomHistoryVisibility]: _td("Change history visibility"),
|
||||
[EventType.RoomPowerLevels]: _td("Change permissions"),
|
||||
[EventType.RoomTopic]: _td("Change topic"),
|
||||
[EventType.RoomTombstone]: _td("Upgrade the room"),
|
||||
[EventType.RoomEncryption]: _td("Enable room encryption"),
|
||||
[EventType.RoomServerAcl]: _td("Change server ACLs"),
|
||||
|
||||
// TODO: Enable support for m.widget event type (https://github.com/vector-im/element-web/issues/13111)
|
||||
"im.vector.modular.widgets": _td("Modify widgets"),
|
||||
|
@ -39,14 +42,15 @@ const plEventsToLabels = {
|
|||
|
||||
const plEventsToShow = {
|
||||
// If an event is listed here, it will be shown in the PL settings. Defaults will be calculated.
|
||||
"m.room.avatar": {isState: true},
|
||||
"m.room.name": {isState: true},
|
||||
"m.room.canonical_alias": {isState: true},
|
||||
"m.room.history_visibility": {isState: true},
|
||||
"m.room.power_levels": {isState: true},
|
||||
"m.room.topic": {isState: true},
|
||||
"m.room.tombstone": {isState: true},
|
||||
"m.room.encryption": {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},
|
||||
|
@ -103,6 +107,7 @@ export class BannedUser extends React.Component {
|
|||
}
|
||||
}
|
||||
|
||||
@replaceableComponent("views.settings.tabs.room.RolesRoomSettingsTab")
|
||||
export default class RolesRoomSettingsTab extends React.Component {
|
||||
static propTypes = {
|
||||
roomId: PropTypes.string.isRequired,
|
||||
|
|
|
@ -26,7 +26,9 @@ import StyledRadioGroup from '../../../elements/StyledRadioGroup';
|
|||
import {SettingLevel} from "../../../../../settings/SettingLevel";
|
||||
import SettingsStore from "../../../../../settings/SettingsStore";
|
||||
import {UIFeature} from "../../../../../settings/UIFeature";
|
||||
import {replaceableComponent} from "../../../../../utils/replaceableComponent";
|
||||
|
||||
@replaceableComponent("views.settings.tabs.room.SecurityRoomSettingsTab")
|
||||
export default class SecurityRoomSettingsTab extends React.Component {
|
||||
static propTypes = {
|
||||
roomId: PropTypes.string.isRequired,
|
||||
|
|
|
@ -18,6 +18,7 @@ limitations under the License.
|
|||
import React from 'react';
|
||||
import {_t} from "../../../../../languageHandler";
|
||||
import SdkConfig from "../../../../../SdkConfig";
|
||||
import { MatrixClientPeg } from '../../../../../MatrixClientPeg';
|
||||
import SettingsStore from "../../../../../settings/SettingsStore";
|
||||
import { enumerateThemes } from "../../../../../theme";
|
||||
import ThemeWatcher from "../../../../../settings/watchers/ThemeWatcher";
|
||||
|
@ -36,6 +37,7 @@ 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";
|
||||
|
||||
interface IProps {
|
||||
}
|
||||
|
@ -62,9 +64,13 @@ interface IState extends IThemeState {
|
|||
systemFont: string;
|
||||
showAdvanced: boolean;
|
||||
layout: Layout;
|
||||
// User profile data for the message preview
|
||||
userId: string;
|
||||
displayName: string;
|
||||
avatarUrl: string;
|
||||
}
|
||||
|
||||
|
||||
@replaceableComponent("views.settings.tabs.user.AppearanceUserSettingsTab")
|
||||
export default class AppearanceUserSettingsTab extends React.Component<IProps, IState> {
|
||||
private readonly MESSAGE_PREVIEW_TEXT = _t("Hey you. You're the best!");
|
||||
|
||||
|
@ -83,9 +89,25 @@ export default class AppearanceUserSettingsTab extends React.Component<IProps, I
|
|||
systemFont: SettingsStore.getValue("systemFont"),
|
||||
showAdvanced: false,
|
||||
layout: SettingsStore.getValue("layout"),
|
||||
userId: "@erim:fink.fink",
|
||||
displayName: "Erimayas Fink",
|
||||
avatarUrl: null,
|
||||
};
|
||||
}
|
||||
|
||||
async componentDidMount() {
|
||||
// Fetch the current user profile for the message preview
|
||||
const client = MatrixClientPeg.get();
|
||||
const userId = client.getUserId();
|
||||
const profileInfo = await client.getProfileInfo(userId);
|
||||
|
||||
this.setState({
|
||||
userId,
|
||||
displayName: profileInfo.displayname,
|
||||
avatarUrl: profileInfo.avatar_url,
|
||||
});
|
||||
}
|
||||
|
||||
private calculateThemeState(): IThemeState {
|
||||
// We have to mirror the logic from ThemeWatcher.getEffectiveTheme so we
|
||||
// show the right values for things.
|
||||
|
@ -306,6 +328,9 @@ export default class AppearanceUserSettingsTab extends React.Component<IProps, I
|
|||
className="mx_AppearanceUserSettingsTab_fontSlider_preview"
|
||||
message={this.MESSAGE_PREVIEW_TEXT}
|
||||
layout={this.state.layout}
|
||||
userId={this.state.userId}
|
||||
displayName={this.state.displayName}
|
||||
avatarUrl={this.state.avatarUrl}
|
||||
/>
|
||||
<div className="mx_AppearanceUserSettingsTab_fontSlider">
|
||||
<div className="mx_AppearanceUserSettingsTab_fontSlider_smallText">Aa</div>
|
||||
|
|
|
@ -17,7 +17,9 @@ limitations under the License.
|
|||
import React from 'react';
|
||||
import {_t} from "../../../../../languageHandler";
|
||||
import GroupUserSettings from "../../../groups/GroupUserSettings";
|
||||
import {replaceableComponent} from "../../../../../utils/replaceableComponent";
|
||||
|
||||
@replaceableComponent("views.settings.tabs.user.FlairUserSettingsTab")
|
||||
export default class FlairUserSettingsTab extends React.Component {
|
||||
render() {
|
||||
return (
|
||||
|
|
|
@ -32,14 +32,16 @@ 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";
|
||||
import {SERVICE_TYPES} from "matrix-js-sdk/src/service-types";
|
||||
import IdentityAuthClient from "../../../../../IdentityAuthClient";
|
||||
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";
|
||||
|
||||
@replaceableComponent("views.settings.tabs.user.GeneralUserSettingsTab")
|
||||
export default class GeneralUserSettingsTab extends React.Component {
|
||||
static propTypes = {
|
||||
closeSettingsFn: PropTypes.func.isRequired,
|
||||
|
@ -204,10 +206,10 @@ export default class GeneralUserSettingsTab extends React.Component {
|
|||
|
||||
_onPasswordChangeError = (err) => {
|
||||
// TODO: Figure out a design that doesn't involve replacing the current dialog
|
||||
let errMsg = err.error || "";
|
||||
let errMsg = err.error || err.message || "";
|
||||
if (err.httpStatus === 403) {
|
||||
errMsg = _t("Failed to change password. Is your password correct?");
|
||||
} else if (err.httpStatus) {
|
||||
} else if (!errMsg) {
|
||||
errMsg += ` (HTTP status ${err.httpStatus})`;
|
||||
}
|
||||
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||
|
|
|
@ -28,7 +28,9 @@ import PlatformPeg from "../../../../../PlatformPeg";
|
|||
import * as KeyboardShortcuts from "../../../../../accessibility/KeyboardShortcuts";
|
||||
import UpdateCheckButton from "../../UpdateCheckButton";
|
||||
import AccessTokenDialog from '../../../dialogs/AccessTokenDialog';
|
||||
import {replaceableComponent} from "../../../../../utils/replaceableComponent";
|
||||
|
||||
@replaceableComponent("views.settings.tabs.user.HelpUserSettingsTab")
|
||||
export default class HelpUserSettingsTab extends React.Component {
|
||||
static propTypes = {
|
||||
closeSettingsFn: PropTypes.func.isRequired,
|
||||
|
|
|
@ -21,6 +21,7 @@ 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";
|
||||
|
||||
export class LabsSettingToggle extends React.Component {
|
||||
static propTypes = {
|
||||
|
@ -40,6 +41,7 @@ export class LabsSettingToggle extends React.Component {
|
|||
}
|
||||
}
|
||||
|
||||
@replaceableComponent("views.settings.tabs.user.LabsUserSettingsTab")
|
||||
export default class LabsUserSettingsTab extends React.Component {
|
||||
constructor() {
|
||||
super();
|
||||
|
|
|
@ -23,7 +23,9 @@ import {BanList, RULE_SERVER, RULE_USER} from "../../../../../mjolnir/BanList";
|
|||
import Modal from "../../../../../Modal";
|
||||
import {MatrixClientPeg} from "../../../../../MatrixClientPeg";
|
||||
import * as sdk from "../../../../../index";
|
||||
import {replaceableComponent} from "../../../../../utils/replaceableComponent";
|
||||
|
||||
@replaceableComponent("views.settings.tabs.user.MjolnirUserSettingsTab")
|
||||
export default class MjolnirUserSettingsTab extends React.Component {
|
||||
constructor() {
|
||||
super();
|
||||
|
|
|
@ -17,7 +17,9 @@ limitations under the License.
|
|||
import React from 'react';
|
||||
import {_t} from "../../../../../languageHandler";
|
||||
import * as sdk from "../../../../../index";
|
||||
import {replaceableComponent} from "../../../../../utils/replaceableComponent";
|
||||
|
||||
@replaceableComponent("views.settings.tabs.user.NotificationUserSettingsTab")
|
||||
export default class NotificationUserSettingsTab extends React.Component {
|
||||
constructor() {
|
||||
super();
|
||||
|
|
|
@ -23,7 +23,9 @@ import Field from "../../../elements/Field";
|
|||
import * as sdk from "../../../../..";
|
||||
import PlatformPeg from "../../../../../PlatformPeg";
|
||||
import {SettingLevel} from "../../../../../settings/SettingLevel";
|
||||
import {replaceableComponent} from "../../../../../utils/replaceableComponent";
|
||||
|
||||
@replaceableComponent("views.settings.tabs.user.PreferencesUserSettingsTab")
|
||||
export default class PreferencesUserSettingsTab extends React.Component {
|
||||
static ROOM_LIST_SETTINGS = [
|
||||
'breadcrumbs',
|
||||
|
@ -72,6 +74,8 @@ export default class PreferencesUserSettingsTab extends React.Component {
|
|||
this.state = {
|
||||
autoLaunch: false,
|
||||
autoLaunchSupported: false,
|
||||
warnBeforeExit: true,
|
||||
warnBeforeExitSupported: false,
|
||||
alwaysShowMenuBar: true,
|
||||
alwaysShowMenuBarSupported: false,
|
||||
minimizeToTray: true,
|
||||
|
@ -94,6 +98,12 @@ export default class PreferencesUserSettingsTab extends React.Component {
|
|||
autoLaunch = await platform.getAutoLaunchEnabled();
|
||||
}
|
||||
|
||||
const warnBeforeExitSupported = await platform.supportsWarnBeforeExit();
|
||||
let warnBeforeExit = false;
|
||||
if (warnBeforeExitSupported) {
|
||||
warnBeforeExit = await platform.shouldWarnBeforeExit();
|
||||
}
|
||||
|
||||
const alwaysShowMenuBarSupported = await platform.supportsAutoHideMenuBar();
|
||||
let alwaysShowMenuBar = true;
|
||||
if (alwaysShowMenuBarSupported) {
|
||||
|
@ -109,6 +119,8 @@ export default class PreferencesUserSettingsTab extends React.Component {
|
|||
this.setState({
|
||||
autoLaunch,
|
||||
autoLaunchSupported,
|
||||
warnBeforeExit,
|
||||
warnBeforeExitSupported,
|
||||
alwaysShowMenuBarSupported,
|
||||
alwaysShowMenuBar,
|
||||
minimizeToTraySupported,
|
||||
|
@ -120,6 +132,10 @@ export default class PreferencesUserSettingsTab extends React.Component {
|
|||
PlatformPeg.get().setAutoLaunchEnabled(checked).then(() => this.setState({autoLaunch: checked}));
|
||||
};
|
||||
|
||||
_onWarnBeforeExitChange = (checked) => {
|
||||
PlatformPeg.get().setWarnBeforeExit(checked).then(() => this.setState({warnBeforeExit: checked}));
|
||||
}
|
||||
|
||||
_onAlwaysShowMenuBarChange = (checked) => {
|
||||
PlatformPeg.get().setAutoHideMenuBarEnabled(!checked).then(() => this.setState({alwaysShowMenuBar: checked}));
|
||||
};
|
||||
|
@ -159,6 +175,14 @@ export default class PreferencesUserSettingsTab extends React.Component {
|
|||
label={_t('Start automatically after system login')} />;
|
||||
}
|
||||
|
||||
let warnBeforeExitOption = null;
|
||||
if (this.state.warnBeforeExitSupported) {
|
||||
warnBeforeExitOption = <LabelledToggleSwitch
|
||||
value={this.state.warnBeforeExit}
|
||||
onChange={this._onWarnBeforeExitChange}
|
||||
label={_t('Warn before quitting')} />;
|
||||
}
|
||||
|
||||
let autoHideMenuOption = null;
|
||||
if (this.state.alwaysShowMenuBarSupported) {
|
||||
autoHideMenuOption = <LabelledToggleSwitch
|
||||
|
@ -200,6 +224,7 @@ export default class PreferencesUserSettingsTab extends React.Component {
|
|||
{minimizeToTrayOption}
|
||||
{autoHideMenuOption}
|
||||
{autoLaunchOption}
|
||||
{warnBeforeExitOption}
|
||||
<Field
|
||||
label={_t('Autocomplete delay (ms)')}
|
||||
type='number'
|
||||
|
|
|
@ -34,6 +34,7 @@ import SettingsStore from "../../../../../settings/SettingsStore";
|
|||
import {UIFeature} from "../../../../../settings/UIFeature";
|
||||
import {isE2eAdvancedPanelPossible} from "../../E2eAdvancedPanel";
|
||||
import CountlyAnalytics from "../../../../../CountlyAnalytics";
|
||||
import {replaceableComponent} from "../../../../../utils/replaceableComponent";
|
||||
|
||||
export class IgnoredUser extends React.Component {
|
||||
static propTypes = {
|
||||
|
@ -59,6 +60,7 @@ export class IgnoredUser extends React.Component {
|
|||
}
|
||||
}
|
||||
|
||||
@replaceableComponent("views.settings.tabs.user.SecurityUserSettingsTab")
|
||||
export default class SecurityUserSettingsTab extends React.Component {
|
||||
static propTypes = {
|
||||
closeSettingsFn: PropTypes.func.isRequired,
|
||||
|
|
|
@ -25,7 +25,9 @@ import {MatrixClientPeg} from "../../../../../MatrixClientPeg";
|
|||
import * as sdk from "../../../../../index";
|
||||
import Modal from "../../../../../Modal";
|
||||
import {SettingLevel} from "../../../../../settings/SettingLevel";
|
||||
import {replaceableComponent} from "../../../../../utils/replaceableComponent";
|
||||
|
||||
@replaceableComponent("views.settings.tabs.user.VoiceUserSettingsTab")
|
||||
export default class VoiceUserSettingsTab extends React.Component {
|
||||
constructor() {
|
||||
super();
|
||||
|
@ -82,6 +84,7 @@ export default class VoiceUserSettingsTab extends React.Component {
|
|||
}
|
||||
}
|
||||
if (error) {
|
||||
console.log("Failed to list userMedia devices", error);
|
||||
const brand = SdkConfig.get().brand;
|
||||
const ErrorDialog = sdk.getComponent('dialogs.ErrorDialog');
|
||||
Modal.createTrackedDialog('No media permissions', '', ErrorDialog, {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue