Merge branch 'develop' into show-invite-reasons

This commit is contained in:
Robin Townsend 2021-03-31 15:47:26 -04:00
commit 2477258249
540 changed files with 19085 additions and 3868 deletions

View file

@ -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,

View file

@ -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();

View file

@ -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,

View file

@ -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,

View file

@ -21,6 +21,7 @@ import {MatrixClientPeg} from "../../../../../MatrixClientPeg";
import * as sdk from "../../../../..";
import AccessibleButton from "../../../elements/AccessibleButton";
import Modal from "../../../../../Modal";
import {replaceableComponent} from "../../../../../utils/replaceableComponent";
const plEventsToLabels = {
// These will be translated for us later.
@ -103,6 +104,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,

View file

@ -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,

View file

@ -37,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 {
}
@ -69,7 +70,7 @@ interface IState extends IThemeState {
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!");

View file

@ -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 (

View file

@ -22,6 +22,7 @@ import ProfileSettings from "../../ProfileSettings";
import * as languageHandler from "../../../../../languageHandler";
import SettingsStore from "../../../../../settings/SettingsStore";
import LanguageDropdown from "../../../elements/LanguageDropdown";
import SpellCheckSettings from "../../SpellCheckSettings";
import AccessibleButton from "../../../elements/AccessibleButton";
import DeactivateAccountDialog from "../../../dialogs/DeactivateAccountDialog";
import PropTypes from "prop-types";
@ -31,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,
@ -49,6 +52,7 @@ export default class GeneralUserSettingsTab extends React.Component {
this.state = {
language: languageHandler.getCurrentLanguage(),
spellCheckLanguages: [],
haveIdServer: Boolean(MatrixClientPeg.get().getIdentityServerUrl()),
serverSupportsSeparateAddAndBind: null,
idServerHasUnsignedTerms: false,
@ -85,6 +89,15 @@ export default class GeneralUserSettingsTab extends React.Component {
this._getThreepidState();
}
async componentDidMount() {
const plaf = PlatformPeg.get();
if (plaf) {
this.setState({
spellCheckLanguages: await plaf.getSpellCheckLanguages(),
});
}
}
componentWillUnmount() {
dis.unregister(this.dispatcherRef);
}
@ -182,12 +195,21 @@ export default class GeneralUserSettingsTab extends React.Component {
PlatformPeg.get().reload();
};
_onSpellCheckLanguagesChange = (languages) => {
this.setState({spellCheckLanguages: languages});
const plaf = PlatformPeg.get();
if (plaf) {
plaf.setSpellCheckLanguages(languages);
}
};
_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");
@ -303,6 +325,16 @@ export default class GeneralUserSettingsTab extends React.Component {
);
}
_renderSpellCheckSection() {
return (
<div className="mx_SettingsTab_section">
<span className="mx_SettingsTab_subheading">{_t("Spell check dictionaries")}</span>
<SpellCheckSettings languages={this.state.spellCheckLanguages}
onLanguagesChange={this._onSpellCheckLanguagesChange} />
</div>
);
}
_renderDiscoverySection() {
const SetIdServer = sdk.getComponent("views.settings.SetIdServer");
@ -381,6 +413,9 @@ export default class GeneralUserSettingsTab extends React.Component {
}
render() {
const plaf = PlatformPeg.get();
const supportsMultiLanguageSpellCheck = plaf.supportsMultiLanguageSpellCheck();
const discoWarning = this.state.requiredPolicyInfo.hasTerms
? <img className='mx_GeneralUserSettingsTab_warningIcon'
src={require("../../../../../../res/img/feather-customised/warning-triangle.svg")}
@ -409,6 +444,7 @@ export default class GeneralUserSettingsTab extends React.Component {
{this._renderProfileSection()}
{this._renderAccountSection()}
{this._renderLanguageSection()}
{supportsMultiLanguageSpellCheck ? this._renderSpellCheckSection() : null}
{ discoverySection }
{this._renderIntegrationManagerSection() /* Has its own title */}
{ accountManagementSection }

View file

@ -27,7 +27,9 @@ import * as sdk from "../../../../../";
import PlatformPeg from "../../../../../PlatformPeg";
import * as KeyboardShortcuts from "../../../../../accessibility/KeyboardShortcuts";
import UpdateCheckButton from "../../UpdateCheckButton";
import {replaceableComponent} from "../../../../../utils/replaceableComponent";
@replaceableComponent("views.settings.tabs.user.HelpUserSettingsTab")
export default class HelpUserSettingsTab extends React.Component {
static propTypes = {
closeSettingsFn: PropTypes.func.isRequired,

View file

@ -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();

View file

@ -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();

View file

@ -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();

View file

@ -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',
@ -48,6 +50,7 @@ export default class PreferencesUserSettingsTab extends React.Component {
'showRedactions',
'enableSyntaxHighlightLanguageDetection',
'expandCodeByDefault',
'scrollToBottomOnMessageSent',
'showCodeLineNumbers',
'showJoinLeaves',
'showAvatarChanges',
@ -71,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,
@ -93,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) {
@ -108,6 +119,8 @@ export default class PreferencesUserSettingsTab extends React.Component {
this.setState({
autoLaunch,
autoLaunchSupported,
warnBeforeExit,
warnBeforeExitSupported,
alwaysShowMenuBarSupported,
alwaysShowMenuBar,
minimizeToTraySupported,
@ -119,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}));
};
@ -158,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
@ -199,6 +224,7 @@ export default class PreferencesUserSettingsTab extends React.Component {
{minimizeToTrayOption}
{autoHideMenuOption}
{autoLaunchOption}
{warnBeforeExitOption}
<Field
label={_t('Autocomplete delay (ms)')}
type='number'

View file

@ -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,

View file

@ -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, {