Merge branch 'develop' into ctrl-enter-send

This commit is contained in:
Clemens Zeidler 2020-11-19 19:40:38 +13:00
commit 1346416d20
451 changed files with 25135 additions and 10894 deletions

View file

@ -46,9 +46,10 @@ export default class BridgeSettingsTab extends React.Component<IProps> {
const client = MatrixClientPeg.get();
const roomState = client.getRoom(roomId).currentState;
return [].concat(...BRIDGE_EVENT_TYPES.map((typeName) =>
Array.from(roomState.events.get(typeName).values()),
));
return BRIDGE_EVENT_TYPES.map(typeName => {
const events = roomState.events.get(typeName);
return events ? Array.from(events.values()) : [];
}).flat(1);
}
render() {

View file

@ -22,6 +22,8 @@ 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";
export default class GeneralRoomSettingsTab extends React.Component {
static propTypes = {
@ -61,6 +63,28 @@ export default class GeneralRoomSettingsTab extends React.Component {
const canChangeGroups = room.currentState.mayClientSendStateEvent("m.room.related_groups", client);
const groupsEvent = room.currentState.getStateEvents("m.room.related_groups", "");
let urlPreviewSettings = <>
<span className='mx_SettingsTab_subheading'>{_t("URL Previews")}</span>
<div className='mx_SettingsTab_section'>
<UrlPreviewSettings room={room} />
</div>
</>;
if (!SettingsStore.getValue(UIFeature.URLPreviews)) {
urlPreviewSettings = null;
}
let flairSection;
if (SettingsStore.getValue(UIFeature.Flair)) {
flairSection = <>
<span className='mx_SettingsTab_subheading'>{_t("Flair")}</span>
<div className='mx_SettingsTab_section mx_SettingsTab_subsectionText'>
<RelatedGroupSettings roomId={room.roomId}
canSetRelatedGroups={canChangeGroups}
relatedGroupsEvent={groupsEvent} />
</div>
</>;
}
return (
<div className="mx_SettingsTab mx_GeneralRoomSettingsTab">
<div className="mx_SettingsTab_heading">{_t("General")}</div>
@ -75,17 +99,8 @@ export default class GeneralRoomSettingsTab extends React.Component {
canonicalAliasEvent={canonicalAliasEv} aliasEvents={aliasEvents} />
</div>
<div className="mx_SettingsTab_heading">{_t("Other")}</div>
<span className='mx_SettingsTab_subheading'>{_t("Flair")}</span>
<div className='mx_SettingsTab_section mx_SettingsTab_subsectionText'>
<RelatedGroupSettings roomId={room.roomId}
canSetRelatedGroups={canChangeGroups}
relatedGroupsEvent={groupsEvent} />
</div>
<span className='mx_SettingsTab_subheading'>{_t("URL Previews")}</span>
<div className='mx_SettingsTab_section'>
<UrlPreviewSettings room={room} />
</div>
{ flairSection }
{ urlPreviewSettings }
<span className='mx_SettingsTab_subheading'>{_t("Leave room")}</span>
<div className='mx_SettingsTab_section'>

View file

@ -239,7 +239,7 @@ export default class RolesRoomSettingsTab extends React.Component {
defaultValue: 50,
},
"redact": {
desc: _t('Remove messages'),
desc: _t('Remove messages sent by others'),
defaultValue: 50,
},
"notifications.room": {

View file

@ -24,6 +24,8 @@ import Modal from "../../../../../Modal";
import QuestionDialog from "../../../dialogs/QuestionDialog";
import StyledRadioGroup from '../../../elements/StyledRadioGroup';
import {SettingLevel} from "../../../../../settings/SettingLevel";
import SettingsStore from "../../../../../settings/SettingsStore";
import {UIFeature} from "../../../../../settings/UIFeature";
export default class SecurityRoomSettingsTab extends React.Component {
static propTypes = {
@ -340,10 +342,23 @@ export default class SecurityRoomSettingsTab extends React.Component {
const canEnableEncryption = !isEncrypted && hasEncryptionPermission;
let encryptionSettings = null;
if (isEncrypted) {
encryptionSettings = <SettingsFlag name="blacklistUnverifiedDevices" level={SettingLevel.ROOM_DEVICE}
onChange={this._updateBlacklistDevicesFlag}
roomId={this.props.roomId} />;
if (isEncrypted && SettingsStore.isEnabled("blacklistUnverifiedDevices")) {
encryptionSettings = <SettingsFlag
name="blacklistUnverifiedDevices"
level={SettingLevel.ROOM_DEVICE}
onChange={this._updateBlacklistDevicesFlag}
roomId={this.props.roomId}
/>;
}
let historySection = (<>
<span className='mx_SettingsTab_subheading'>{_t("Who can read history?")}</span>
<div className='mx_SettingsTab_section mx_SettingsTab_subsectionText'>
{this._renderHistory()}
</div>
</>);
if (!SettingsStore.getValue(UIFeature.RoomHistorySettings)) {
historySection = null;
}
return (
@ -367,10 +382,7 @@ export default class SecurityRoomSettingsTab extends React.Component {
{this._renderRoomAccess()}
</div>
<span className='mx_SettingsTab_subheading'>{_t("Who can read history?")}</span>
<div className='mx_SettingsTab_section mx_SettingsTab_subsectionText'>
{this._renderHistory()}
</div>
{historySection}
</div>
);
}

View file

@ -36,6 +36,7 @@ import EventTilePreview from '../../../elements/EventTilePreview';
import StyledRadioGroup from "../../../elements/StyledRadioGroup";
import classNames from 'classnames';
import { SettingLevel } from "../../../../../settings/SettingLevel";
import {UIFeature} from "../../../../../settings/UIFeature";
interface IProps {
}
@ -386,6 +387,8 @@ export default class AppearanceUserSettingsTab extends React.Component<IProps, I
};
private renderAdvancedSection() {
if (!SettingsStore.getValue(UIFeature.AdvancedSettings)) return null;
const brand = SdkConfig.get().brand;
const toggle = <div
className="mx_AppearanceUserSettingsTab_AdvancedToggle"

View file

@ -37,6 +37,7 @@ import {abbreviateUrl} from "../../../../../utils/UrlUtils";
import { getThreepidsWithBindStatus } from '../../../../../boundThreepids';
import Spinner from "../../../elements/Spinner";
import {SettingLevel} from "../../../../../settings/SettingLevel";
import {UIFeature} from "../../../../../settings/UIFeature";
export default class GeneralUserSettingsTab extends React.Component {
static propTypes = {
@ -220,7 +221,6 @@ export default class GeneralUserSettingsTab extends React.Component {
_renderProfileSection() {
return (
<div className="mx_SettingsTab_section">
<span className="mx_SettingsTab_subheading">{_t("Profile")}</span>
<ProfileSettings />
</div>
);
@ -247,7 +247,9 @@ export default class GeneralUserSettingsTab extends React.Component {
// validate 3PID ownership even if we're just adding to the homeserver only.
// For newer homeservers with separate 3PID add and bind methods (MSC2290),
// there is no such concern, so we can always show the HS account 3PIDs.
if (this.state.haveIdServer || this.state.serverSupportsSeparateAddAndBind === true) {
if (SettingsStore.getValue(UIFeature.ThirdPartyID) &&
(this.state.haveIdServer || this.state.serverSupportsSeparateAddAndBind === true)
) {
const emails = this.state.loading3pids
? <Spinner />
: <EmailAddresses
@ -366,6 +368,8 @@ export default class GeneralUserSettingsTab extends React.Component {
}
_renderIntegrationManagerSection() {
if (!SettingsStore.getValue(UIFeature.Widgets)) return null;
const SetIntegrationManager = sdk.getComponent("views.settings.SetIntegrationManager");
return (
@ -383,17 +387,31 @@ export default class GeneralUserSettingsTab extends React.Component {
width="18" height="18" alt={_t("Warning")} />
: null;
let accountManagementSection;
if (SettingsStore.getValue(UIFeature.Deactivate)) {
accountManagementSection = <>
<div className="mx_SettingsTab_heading">{_t("Deactivate account")}</div>
{this._renderManagementSection()}
</>;
}
let discoverySection;
if (SettingsStore.getValue(UIFeature.IdentityServer)) {
discoverySection = <>
<div className="mx_SettingsTab_heading">{discoWarning} {_t("Discovery")}</div>
{this._renderDiscoverySection()}
</>;
}
return (
<div className="mx_SettingsTab">
<div className="mx_SettingsTab_heading">{_t("General")}</div>
{this._renderProfileSection()}
{this._renderAccountSection()}
{this._renderLanguageSection()}
<div className="mx_SettingsTab_heading">{discoWarning} {_t("Discovery")}</div>
{this._renderDiscoverySection()}
{ discoverySection }
{this._renderIntegrationManagerSection() /* Has its own title */}
<div className="mx_SettingsTab_heading">{_t("Deactivate account")}</div>
{this._renderManagementSection()}
{ accountManagementSection }
</div>
);
}

View file

@ -204,9 +204,9 @@ export default class HelpUserSettingsTab extends React.Component {
updateButton = <UpdateCheckButton />;
}
return (
<div className="mx_SettingsTab mx_HelpUserSettingsTab">
<div className="mx_SettingsTab_heading">{_t("Help & About")}</div>
let bugReportingSection;
if (SdkConfig.get().bug_report_endpoint_url) {
bugReportingSection = (
<div className="mx_SettingsTab_section">
<span className='mx_SettingsTab_subheading'>{_t('Bug reporting')}</span>
<div className='mx_SettingsTab_subsectionText'>
@ -223,22 +223,24 @@ export default class HelpUserSettingsTab extends React.Component {
{_t("Submit debug logs")}
</AccessibleButton>
</div>
<div className='mx_HelpUserSettingsTab_debugButton'>
<AccessibleButton onClick={this._onClearCacheAndReload} kind='danger'>
{_t("Clear cache and reload")}
</AccessibleButton>
</div>
{
_t( "To report a Matrix-related security issue, please read the Matrix.org " +
"<a>Security Disclosure Policy</a>.", {},
{
'a': (sub) =>
<a href="https://matrix.org/security-disclosure-policy/"
rel="noreferrer noopener" target="_blank">{sub}</a>,
rel="noreferrer noopener" target="_blank">{sub}</a>,
})
}
</div>
</div>
);
}
return (
<div className="mx_SettingsTab mx_HelpUserSettingsTab">
<div className="mx_SettingsTab_heading">{_t("Help & About")}</div>
{ bugReportingSection }
<div className='mx_SettingsTab_section'>
<span className='mx_SettingsTab_subheading'>{_t("FAQ")}</span>
<div className='mx_SettingsTab_subsectionText'>
@ -268,6 +270,11 @@ export default class HelpUserSettingsTab extends React.Component {
data-spoiler={MatrixClientPeg.get().getAccessToken()}>
&lt;{ _t("click to reveal") }&gt;
</AccessibleButton>
<div className='mx_HelpUserSettingsTab_debugButton'>
<AccessibleButton onClick={this._onClearCacheAndReload} kind='danger'>
{_t("Clear cache and reload")}
</AccessibleButton>
</div>
</div>
</div>
</div>

View file

@ -50,11 +50,10 @@ export default class PreferencesUserSettingsTab extends React.Component {
'showAvatarChanges',
'showDisplaynameChanges',
'showImages',
'Pill.shouldShowPillAvatar',
];
static ADVANCED_SETTINGS = [
'alwaysShowEncryptionIcons',
'Pill.shouldShowPillAvatar',
static GENERAL_SETTINGS = [
'TagPanel.enableTagPanel',
'promptBeforeInviteUnknownUsers',
// Start automatically after startup (electron-only)
@ -140,7 +139,9 @@ export default class PreferencesUserSettingsTab extends React.Component {
_renderGroup(settingIds) {
const SettingsFlag = sdk.getComponent("views.elements.SettingsFlag");
return settingIds.map(i => <SettingsFlag key={i} name={i} level={SettingLevel.ACCOUNT} />);
return settingIds.filter(SettingsStore.isEnabled).map(i => {
return <SettingsFlag key={i} name={i} level={SettingLevel.ACCOUNT} />;
});
}
render() {
@ -188,8 +189,8 @@ export default class PreferencesUserSettingsTab extends React.Component {
</div>
<div className="mx_SettingsTab_section">
<span className="mx_SettingsTab_subheading">{_t("Advanced")}</span>
{this._renderGroup(PreferencesUserSettingsTab.ADVANCED_SETTINGS)}
<span className="mx_SettingsTab_subheading">{_t("General")}</span>
{this._renderGroup(PreferencesUserSettingsTab.GENERAL_SETTINGS)}
{minimizeToTrayOption}
{autoHideMenuOption}
{autoLaunchOption}

View file

@ -29,6 +29,11 @@ import {sleep} from "../../../../../utils/promise";
import dis from "../../../../../dispatcher/dispatcher";
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 CountlyAnalytics from "../../../../../CountlyAnalytics";
export class IgnoredUser extends React.Component {
static propTypes = {
@ -98,18 +103,19 @@ export default class SecurityUserSettingsTab extends React.Component {
_updateAnalytics = (checked) => {
checked ? Analytics.enable() : Analytics.disable();
CountlyAnalytics.instance.enable(/* anonymous = */ !checked);
};
_onExportE2eKeysClicked = () => {
Modal.createTrackedDialogAsync('Export E2E Keys', '',
import('../../../../../async-components/views/dialogs/ExportE2eKeysDialog'),
import('../../../../../async-components/views/dialogs/security/ExportE2eKeysDialog'),
{matrixClient: MatrixClientPeg.get()},
);
};
_onImportE2eKeysClicked = () => {
Modal.createTrackedDialogAsync('Import E2E Keys', '',
import('../../../../../async-components/views/dialogs/ImportE2eKeysDialog'),
import('../../../../../async-components/views/dialogs/security/ImportE2eKeysDialog'),
{matrixClient: MatrixClientPeg.get()},
);
};
@ -216,6 +222,15 @@ export default class SecurityUserSettingsTab extends React.Component {
);
}
let noSendUnverifiedSetting;
if (SettingsStore.isEnabled("blacklistUnverifiedDevices")) {
noSendUnverifiedSetting = <SettingsFlag
name='blacklistUnverifiedDevices'
level={SettingLevel.DEVICE}
onChange={this._updateBlacklistDevicesFlag}
/>;
}
return (
<div className='mx_SettingsTab_section'>
<span className='mx_SettingsTab_subheading'>{_t("Cryptography")}</span>
@ -230,8 +245,7 @@ export default class SecurityUserSettingsTab extends React.Component {
</li>
</ul>
{importExportButtons}
<SettingsFlag name='blacklistUnverifiedDevices' level={SettingLevel.DEVICE}
onChange={this._updateBlacklistDevicesFlag} />
{noSendUnverifiedSetting}
</div>
);
}
@ -288,12 +302,11 @@ export default class SecurityUserSettingsTab extends React.Component {
const SettingsFlag = sdk.getComponent('views.elements.SettingsFlag');
const EventIndexPanel = sdk.getComponent('views.settings.EventIndexPanel');
const KeyBackupPanel = sdk.getComponent('views.settings.KeyBackupPanel');
const keyBackup = (
const secureBackup = (
<div className='mx_SettingsTab_section'>
<span className="mx_SettingsTab_subheading">{_t("Key backup")}</span>
<span className="mx_SettingsTab_subheading">{_t("Secure Backup")}</span>
<div className='mx_SettingsTab_subsectionText'>
<KeyBackupPanel />
<SecureBackupPanel />
</div>
</div>
);
@ -311,15 +324,13 @@ export default class SecurityUserSettingsTab extends React.Component {
// can remove this.
const CrossSigningPanel = sdk.getComponent('views.settings.CrossSigningPanel');
const crossSigning = (
<div className='mx_SettingsTab_section'>
<span className="mx_SettingsTab_subheading">{_t("Cross-signing")}</span>
<div className='mx_SettingsTab_subsectionText'>
<CrossSigningPanel />
</div>
<div className='mx_SettingsTab_section'>
<span className="mx_SettingsTab_subheading">{_t("Cross-signing")}</span>
<div className='mx_SettingsTab_subsectionText'>
<CrossSigningPanel />
</div>
);
const E2eAdvancedPanel = sdk.getComponent('views.settings.E2eAdvancedPanel');
</div>
);
let warning;
if (!privateShouldBeEncrypted()) {
@ -329,6 +340,48 @@ export default class SecurityUserSettingsTab extends React.Component {
</div>;
}
let privacySection;
if (Analytics.canEnable() || CountlyAnalytics.instance.canEnable()) {
privacySection = <React.Fragment>
<div className="mx_SettingsTab_heading">{_t("Privacy")}</div>
<div className="mx_SettingsTab_section">
<span className="mx_SettingsTab_subheading">{_t("Analytics")}</span>
<div className="mx_SettingsTab_subsectionText">
{_t(
"%(brand)s collects anonymous analytics to allow us to improve the application.",
{ brand },
)}
&nbsp;
{_t("Privacy is important to us, so we don't collect any personal or " +
"identifiable data for our analytics.")}
<AccessibleButton className="mx_SettingsTab_linkBtn" onClick={Analytics.showDetailsModal}>
{_t("Learn more about how we use analytics.")}
</AccessibleButton>
</div>
<SettingsFlag name="analyticsOptIn" level={SettingLevel.DEVICE} onChange={this._updateAnalytics} />
</div>
</React.Fragment>;
}
const E2eAdvancedPanel = sdk.getComponent('views.settings.E2eAdvancedPanel');
let advancedSection;
if (SettingsStore.getValue(UIFeature.AdvancedSettings)) {
const ignoreUsersPanel = this._renderIgnoredUsers();
const invitesPanel = this._renderManageInvites();
const e2ePanel = isE2eAdvancedPanelPossible() ? <E2eAdvancedPanel /> : null;
// only show the section if there's something to show
if (ignoreUsersPanel || invitesPanel || e2ePanel) {
advancedSection = <>
<div className="mx_SettingsTab_heading">{_t("Advanced")}</div>
<div className="mx_SettingsTab_section">
{ignoreUsersPanel}
{invitesPanel}
{e2ePanel}
</div>
</>;
}
}
return (
<div className="mx_SettingsTab mx_SecurityUserSettingsTab">
{warning}
@ -352,35 +405,13 @@ export default class SecurityUserSettingsTab extends React.Component {
</div>
<div className="mx_SettingsTab_heading">{_t("Encryption")}</div>
<div className="mx_SettingsTab_section">
{keyBackup}
{secureBackup}
{eventIndex}
{crossSigning}
{this._renderCurrentDeviceInfo()}
</div>
<div className="mx_SettingsTab_heading">{_t("Privacy")}</div>
<div className="mx_SettingsTab_section">
<span className="mx_SettingsTab_subheading">{_t("Analytics")}</span>
<div className='mx_SettingsTab_subsectionText'>
{_t(
"%(brand)s collects anonymous analytics to allow us to improve the application.",
{ brand },
)}
&nbsp;
{_t("Privacy is important to us, so we don't collect any personal or " +
"identifiable data for our analytics.")}
<AccessibleButton className="mx_SettingsTab_linkBtn" onClick={Analytics.showDetailsModal}>
{_t("Learn more about how we use analytics.")}
</AccessibleButton>
</div>
<SettingsFlag name='analyticsOptIn' level={SettingLevel.DEVICE}
onChange={this._updateAnalytics} />
</div>
<div className="mx_SettingsTab_heading">{_t("Advanced")}</div>
<div className="mx_SettingsTab_section">
{this._renderIgnoredUsers()}
{this._renderManageInvites()}
<E2eAdvancedPanel />
</div>
{ privacySection }
{ advancedSection }
</div>
);
}