Convert SecurityUserSettingsTab to TS

Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
pull/21833/head
Šimon Brandner 2021-09-21 13:59:29 +02:00
parent 222427dae8
commit 073eff4c71
No known key found for this signature in database
GPG Key ID: 55C211A1226CB17D
1 changed files with 71 additions and 66 deletions

View File

@ -16,7 +16,6 @@ limitations under the License.
*/ */
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types';
import { sleep } from "matrix-js-sdk/src/utils"; import { sleep } from "matrix-js-sdk/src/utils";
import { _t } from "../../../../../languageHandler"; import { _t } from "../../../../../languageHandler";
@ -26,34 +25,40 @@ import * as FormattingUtils from "../../../../../utils/FormattingUtils";
import AccessibleButton from "../../../elements/AccessibleButton"; import AccessibleButton from "../../../elements/AccessibleButton";
import Analytics from "../../../../../Analytics"; import Analytics from "../../../../../Analytics";
import Modal from "../../../../../Modal"; import Modal from "../../../../../Modal";
import * as sdk from "../../../../..";
import dis from "../../../../../dispatcher/dispatcher"; import dis from "../../../../../dispatcher/dispatcher";
import { privateShouldBeEncrypted } from "../../../../../createRoom"; import { privateShouldBeEncrypted } from "../../../../../createRoom";
import { SettingLevel } from "../../../../../settings/SettingLevel"; import { SettingLevel } from "../../../../../settings/SettingLevel";
import SecureBackupPanel from "../../SecureBackupPanel"; import SecureBackupPanel from "../../SecureBackupPanel";
import SettingsStore from "../../../../../settings/SettingsStore"; import SettingsStore from "../../../../../settings/SettingsStore";
import { UIFeature } from "../../../../../settings/UIFeature"; import { UIFeature } from "../../../../../settings/UIFeature";
import { isE2eAdvancedPanelPossible } from "../../E2eAdvancedPanel"; import E2eAdvancedPanel, { isE2eAdvancedPanelPossible } from "../../E2eAdvancedPanel";
import CountlyAnalytics from "../../../../../CountlyAnalytics"; import CountlyAnalytics from "../../../../../CountlyAnalytics";
import { replaceableComponent } from "../../../../../utils/replaceableComponent"; import { replaceableComponent } from "../../../../../utils/replaceableComponent";
import { PosthogAnalytics } from "../../../../../PosthogAnalytics"; import { PosthogAnalytics } from "../../../../../PosthogAnalytics";
import { ActionPayload } from "../../../../../dispatcher/payloads";
import { Room } from "matrix-js-sdk/src/models/room";
import DevicesPanel from "../../DevicesPanel";
import SettingsFlag from "../../../elements/SettingsFlag";
import CrossSigningPanel from "../../CrossSigningPanel";
import EventIndexPanel from "../../EventIndexPanel";
import InlineSpinner from "../../../elements/InlineSpinner";
export class IgnoredUser extends React.Component { interface IIgnoredUserProps {
static propTypes = { userId: string;
userId: PropTypes.string.isRequired, onUnignored: (userId: string) => void;
onUnignored: PropTypes.func.isRequired, inProgress: boolean;
inProgress: PropTypes.bool.isRequired, }
};
_onUnignoreClicked = (e) => { export class IgnoredUser extends React.Component<IIgnoredUserProps> {
private onUnignoreClicked = (): void => {
this.props.onUnignored(this.props.userId); this.props.onUnignored(this.props.userId);
}; };
render() { public render(): JSX.Element {
const id = `mx_SecurityUserSettingsTab_ignoredUser_${this.props.userId}`; const id = `mx_SecurityUserSettingsTab_ignoredUser_${this.props.userId}`;
return ( return (
<div className='mx_SecurityUserSettingsTab_ignoredUser'> <div className='mx_SecurityUserSettingsTab_ignoredUser'>
<AccessibleButton onClick={this._onUnignoreClicked} kind='primary_sm' aria-describedby={id} disabled={this.props.inProgress}> <AccessibleButton onClick={this.onUnignoreClicked} kind='primary_sm' aria-describedby={id} disabled={this.props.inProgress}>
{ _t('Unignore') } { _t('Unignore') }
</AccessibleButton> </AccessibleButton>
<span id={id}>{ this.props.userId }</span> <span id={id}>{ this.props.userId }</span>
@ -62,17 +67,26 @@ export class IgnoredUser extends React.Component {
} }
} }
@replaceableComponent("views.settings.tabs.user.SecurityUserSettingsTab") interface IProps {
export default class SecurityUserSettingsTab extends React.Component { closeSettingsFn: () => void;
static propTypes = { }
closeSettingsFn: PropTypes.func.isRequired,
};
constructor() { interface IState {
super(); ignoredUserIds: string[];
waitingUnignored: string[];
managingInvites: boolean;
invitedRoomAmt: number;
}
@replaceableComponent("views.settings.tabs.user.SecurityUserSettingsTab")
export default class SecurityUserSettingsTab extends React.Component<IProps, IState> {
private dispatcherRef: string;
constructor(props: IProps) {
super(props);
// Get number of rooms we're invited to // Get number of rooms we're invited to
const invitedRooms = this._getInvitedRooms(); const invitedRooms = this.getInvitedRooms();
this.state = { this.state = {
ignoredUserIds: MatrixClientPeg.get().getIgnoredUsers(), ignoredUserIds: MatrixClientPeg.get().getIgnoredUsers(),
@ -80,59 +94,57 @@ export default class SecurityUserSettingsTab extends React.Component {
managingInvites: false, managingInvites: false,
invitedRoomAmt: invitedRooms.length, invitedRoomAmt: invitedRooms.length,
}; };
this._onAction = this._onAction.bind(this);
} }
_onAction({ action }) { private onAction = ({ action }: ActionPayload)=> {
if (action === "ignore_state_changed") { if (action === "ignore_state_changed") {
const ignoredUserIds = MatrixClientPeg.get().getIgnoredUsers(); const ignoredUserIds = MatrixClientPeg.get().getIgnoredUsers();
const newWaitingUnignored = this.state.waitingUnignored.filter(e=> ignoredUserIds.includes(e)); const newWaitingUnignored = this.state.waitingUnignored.filter(e=> ignoredUserIds.includes(e));
this.setState({ ignoredUserIds, waitingUnignored: newWaitingUnignored }); this.setState({ ignoredUserIds, waitingUnignored: newWaitingUnignored });
} }
};
public componentDidMount(): void {
this.dispatcherRef = dis.register(this.onAction);
} }
componentDidMount() { public componentWillUnmount(): void {
this.dispatcherRef = dis.register(this._onAction);
}
componentWillUnmount() {
dis.unregister(this.dispatcherRef); dis.unregister(this.dispatcherRef);
} }
_updateBlacklistDevicesFlag = (checked) => { private updateBlacklistDevicesFlag = (checked): void => {
MatrixClientPeg.get().setGlobalBlacklistUnverifiedDevices(checked); MatrixClientPeg.get().setGlobalBlacklistUnverifiedDevices(checked);
}; };
_updateAnalytics = (checked) => { private updateAnalytics = (checked: boolean): void => {
checked ? Analytics.enable() : Analytics.disable(); checked ? Analytics.enable() : Analytics.disable();
CountlyAnalytics.instance.enable(/* anonymous = */ !checked); CountlyAnalytics.instance.enable(/* anonymous = */ !checked);
PosthogAnalytics.instance.updateAnonymityFromSettings(MatrixClientPeg.get().getUserId()); PosthogAnalytics.instance.updateAnonymityFromSettings(MatrixClientPeg.get().getUserId());
}; };
_onExportE2eKeysClicked = () => { private onExportE2eKeysClicked = (): void => {
Modal.createTrackedDialogAsync('Export E2E Keys', '', Modal.createTrackedDialogAsync('Export E2E Keys', '',
import('../../../../../async-components/views/dialogs/security/ExportE2eKeysDialog'), import('../../../../../async-components/views/dialogs/security/ExportE2eKeysDialog'),
{ matrixClient: MatrixClientPeg.get() }, { matrixClient: MatrixClientPeg.get() },
); );
}; };
_onImportE2eKeysClicked = () => { private onImportE2eKeysClicked = (): void => {
Modal.createTrackedDialogAsync('Import E2E Keys', '', Modal.createTrackedDialogAsync('Import E2E Keys', '',
import('../../../../../async-components/views/dialogs/security/ImportE2eKeysDialog'), import('../../../../../async-components/views/dialogs/security/ImportE2eKeysDialog'),
{ matrixClient: MatrixClientPeg.get() }, { matrixClient: MatrixClientPeg.get() },
); );
}; };
_onGoToUserProfileClick = () => { private onGoToUserProfileClick = (): void => {
dis.dispatch({ dis.dispatch({
action: 'view_user_info', action: 'view_user_info',
userId: MatrixClientPeg.get().getUserId(), userId: MatrixClientPeg.get().getUserId(),
}); });
this.props.closeSettingsFn(); this.props.closeSettingsFn();
} };
_onUserUnignored = async (userId) => { private onUserUnignored = async (userId: string): Promise<void> => {
const { ignoredUserIds, waitingUnignored } = this.state; const { ignoredUserIds, waitingUnignored } = this.state;
const currentlyIgnoredUserIds = ignoredUserIds.filter(e => !waitingUnignored.includes(e)); const currentlyIgnoredUserIds = ignoredUserIds.filter(e => !waitingUnignored.includes(e));
@ -144,23 +156,24 @@ export default class SecurityUserSettingsTab extends React.Component {
} }
}; };
_getInvitedRooms = () => { private getInvitedRooms = (): Room[] => {
return MatrixClientPeg.get().getRooms().filter((r) => { return MatrixClientPeg.get().getRooms().filter((r) => {
return r.hasMembershipState(MatrixClientPeg.get().getUserId(), "invite"); return r.hasMembershipState(MatrixClientPeg.get().getUserId(), "invite");
}); });
}; };
_manageInvites = async (accept) => { private manageInvites = async (accept: boolean): Promise<void> => {
this.setState({ this.setState({
managingInvites: true, managingInvites: true,
}); });
// Compile array of invitation room ids // Compile array of invitation room ids
const invitedRoomIds = this._getInvitedRooms().map((room) => { const invitedRoomIds = this.getInvitedRooms().map((room) => {
return room.roomId; return room.roomId;
}); });
// Execute all acceptances/rejections sequentially // Execute all acceptances/rejections sequentially
// eslint-disable-next-line @typescript-eslint/no-this-alias
const self = this; const self = this;
const cli = MatrixClientPeg.get(); const cli = MatrixClientPeg.get();
const action = accept ? cli.joinRoom.bind(cli) : cli.leave.bind(cli); const action = accept ? cli.joinRoom.bind(cli) : cli.leave.bind(cli);
@ -192,17 +205,15 @@ export default class SecurityUserSettingsTab extends React.Component {
}); });
}; };
_onAcceptAllInvitesClicked = (ev) => { private onAcceptAllInvitesClicked = (): void => {
this._manageInvites(true); this.manageInvites(true);
}; };
_onRejectAllInvitesClicked = (ev) => { private onRejectAllInvitesClicked = (): void => {
this._manageInvites(false); this.manageInvites(false);
}; };
_renderCurrentDeviceInfo() { private renderCurrentDeviceInfo(): JSX.Element {
const SettingsFlag = sdk.getComponent('views.elements.SettingsFlag');
const client = MatrixClientPeg.get(); const client = MatrixClientPeg.get();
const deviceId = client.deviceId; const deviceId = client.deviceId;
let identityKey = client.getDeviceEd25519Key(); let identityKey = client.getDeviceEd25519Key();
@ -216,10 +227,10 @@ export default class SecurityUserSettingsTab extends React.Component {
if (client.isCryptoEnabled()) { if (client.isCryptoEnabled()) {
importExportButtons = ( importExportButtons = (
<div className='mx_SecurityUserSettingsTab_importExportButtons'> <div className='mx_SecurityUserSettingsTab_importExportButtons'>
<AccessibleButton kind='primary' onClick={this._onExportE2eKeysClicked}> <AccessibleButton kind='primary' onClick={this.onExportE2eKeysClicked}>
{ _t("Export E2E room keys") } { _t("Export E2E room keys") }
</AccessibleButton> </AccessibleButton>
<AccessibleButton kind='primary' onClick={this._onImportE2eKeysClicked}> <AccessibleButton kind='primary' onClick={this.onImportE2eKeysClicked}>
{ _t("Import E2E room keys") } { _t("Import E2E room keys") }
</AccessibleButton> </AccessibleButton>
</div> </div>
@ -231,7 +242,7 @@ export default class SecurityUserSettingsTab extends React.Component {
noSendUnverifiedSetting = <SettingsFlag noSendUnverifiedSetting = <SettingsFlag
name='blacklistUnverifiedDevices' name='blacklistUnverifiedDevices'
level={SettingLevel.DEVICE} level={SettingLevel.DEVICE}
onChange={this._updateBlacklistDevicesFlag} onChange={this.updateBlacklistDevicesFlag}
/>; />;
} }
@ -254,7 +265,7 @@ export default class SecurityUserSettingsTab extends React.Component {
); );
} }
_renderIgnoredUsers() { private renderIgnoredUsers(): JSX.Element {
const { waitingUnignored, ignoredUserIds } = this.state; const { waitingUnignored, ignoredUserIds } = this.state;
const userIds = !ignoredUserIds?.length const userIds = !ignoredUserIds?.length
@ -263,7 +274,7 @@ export default class SecurityUserSettingsTab extends React.Component {
return ( return (
<IgnoredUser <IgnoredUser
userId={u} userId={u}
onUnignored={this._onUserUnignored} onUnignored={this.onUserUnignored}
key={u} key={u}
inProgress={waitingUnignored.includes(u)} inProgress={waitingUnignored.includes(u)}
/> />
@ -280,15 +291,14 @@ export default class SecurityUserSettingsTab extends React.Component {
); );
} }
_renderManageInvites() { private renderManageInvites(): JSX.Element {
if (this.state.invitedRoomAmt === 0) { if (this.state.invitedRoomAmt === 0) {
return null; return null;
} }
const invitedRooms = this._getInvitedRooms(); const invitedRooms = this.getInvitedRooms();
const InlineSpinner = sdk.getComponent('elements.InlineSpinner'); const onClickAccept = this.onAcceptAllInvitesClicked.bind(this, invitedRooms);
const onClickAccept = this._onAcceptAllInvitesClicked.bind(this, invitedRooms); const onClickReject = this.onRejectAllInvitesClicked.bind(this, invitedRooms);
const onClickReject = this._onRejectAllInvitesClicked.bind(this, invitedRooms);
return ( return (
<div className='mx_SettingsTab_section mx_SecurityUserSettingsTab_bulkOptions'> <div className='mx_SettingsTab_section mx_SecurityUserSettingsTab_bulkOptions'>
<span className='mx_SettingsTab_subheading'>{ _t('Bulk options') }</span> <span className='mx_SettingsTab_subheading'>{ _t('Bulk options') }</span>
@ -303,11 +313,8 @@ export default class SecurityUserSettingsTab extends React.Component {
); );
} }
render() { public render(): JSX.Element {
const brand = SdkConfig.get().brand; const brand = SdkConfig.get().brand;
const DevicesPanel = sdk.getComponent('views.settings.DevicesPanel');
const SettingsFlag = sdk.getComponent('views.elements.SettingsFlag');
const EventIndexPanel = sdk.getComponent('views.settings.EventIndexPanel');
const secureBackup = ( const secureBackup = (
<div className='mx_SettingsTab_section'> <div className='mx_SettingsTab_section'>
@ -329,7 +336,6 @@ export default class SecurityUserSettingsTab extends React.Component {
// it's useful to have for testing the feature. If there's no interest // it's useful to have for testing the feature. If there's no interest
// in having advanced details here once all flows are implemented, we // in having advanced details here once all flows are implemented, we
// can remove this. // can remove this.
const CrossSigningPanel = sdk.getComponent('views.settings.CrossSigningPanel');
const crossSigning = ( const crossSigning = (
<div className='mx_SettingsTab_section'> <div className='mx_SettingsTab_section'>
<span className="mx_SettingsTab_subheading">{ _t("Cross-signing") }</span> <span className="mx_SettingsTab_subheading">{ _t("Cross-signing") }</span>
@ -365,16 +371,15 @@ export default class SecurityUserSettingsTab extends React.Component {
{ _t("Learn more about how we use analytics.") } { _t("Learn more about how we use analytics.") }
</AccessibleButton> </AccessibleButton>
</div> </div>
<SettingsFlag name="analyticsOptIn" level={SettingLevel.DEVICE} onChange={this._updateAnalytics} /> <SettingsFlag name="analyticsOptIn" level={SettingLevel.DEVICE} onChange={this.updateAnalytics} />
</div> </div>
</React.Fragment>; </React.Fragment>;
} }
const E2eAdvancedPanel = sdk.getComponent('views.settings.E2eAdvancedPanel');
let advancedSection; let advancedSection;
if (SettingsStore.getValue(UIFeature.AdvancedSettings)) { if (SettingsStore.getValue(UIFeature.AdvancedSettings)) {
const ignoreUsersPanel = this._renderIgnoredUsers(); const ignoreUsersPanel = this.renderIgnoredUsers();
const invitesPanel = this._renderManageInvites(); const invitesPanel = this.renderManageInvites();
const e2ePanel = isE2eAdvancedPanelPossible() ? <E2eAdvancedPanel /> : null; const e2ePanel = isE2eAdvancedPanelPossible() ? <E2eAdvancedPanel /> : null;
// only show the section if there's something to show // only show the section if there's something to show
if (ignoreUsersPanel || invitesPanel || e2ePanel) { if (ignoreUsersPanel || invitesPanel || e2ePanel) {
@ -399,7 +404,7 @@ export default class SecurityUserSettingsTab extends React.Component {
"Manage the names of and sign out of your sessions below or " + "Manage the names of and sign out of your sessions below or " +
"<a>verify them in your User Profile</a>.", {}, "<a>verify them in your User Profile</a>.", {},
{ {
a: sub => <AccessibleButton kind="link" onClick={this._onGoToUserProfileClick}> a: sub => <AccessibleButton kind="link" onClick={this.onGoToUserProfileClick}>
{ sub } { sub }
</AccessibleButton>, </AccessibleButton>,
}, },
@ -415,7 +420,7 @@ export default class SecurityUserSettingsTab extends React.Component {
{ secureBackup } { secureBackup }
{ eventIndex } { eventIndex }
{ crossSigning } { crossSigning }
{ this._renderCurrentDeviceInfo() } { this.renderCurrentDeviceInfo() }
</div> </div>
{ privacySection } { privacySection }
{ advancedSection } { advancedSection }