Conform to new react and typescript eslint rules

This commit is contained in:
Michael Telatynski 2021-07-19 22:43:11 +01:00
parent b6feaf74bc
commit ce78cdf4ad
266 changed files with 1992 additions and 2000 deletions

View file

@ -46,6 +46,7 @@
"start:build": "babel src -w -s -d lib --verbose --extensions \".ts,.js\"", "start:build": "babel src -w -s -d lib --verbose --extensions \".ts,.js\"",
"lint": "yarn lint:types && yarn lint:js && yarn lint:style", "lint": "yarn lint:types && yarn lint:js && yarn lint:style",
"lint:js": "eslint --max-warnings 0 src test", "lint:js": "eslint --max-warnings 0 src test",
"lint:js-fix": "eslint --fix src test",
"lint:types": "tsc --noEmit --jsx react", "lint:types": "tsc --noEmit --jsx react",
"lint:style": "stylelint 'res/css/**/*.scss'", "lint:style": "stylelint 'res/css/**/*.scss'",
"test": "jest", "test": "jest",

View file

@ -50,6 +50,8 @@ import UIStore from "../stores/UIStore";
import { SetupEncryptionStore } from "../stores/SetupEncryptionStore"; import { SetupEncryptionStore } from "../stores/SetupEncryptionStore";
import { RoomScrollStateStore } from "../stores/RoomScrollStateStore"; import { RoomScrollStateStore } from "../stores/RoomScrollStateStore";
/* eslint-disable @typescript-eslint/naming-convention */
declare global { declare global {
interface Window { interface Window {
matrixChat: ReturnType<Renderer>; matrixChat: ReturnType<Renderer>;
@ -186,3 +188,5 @@ declare global {
} }
); );
} }
/* eslint-enable @typescript-eslint/naming-convention */

View file

@ -270,7 +270,7 @@ export class Analytics {
localStorage.removeItem(LAST_VISIT_TS_KEY); localStorage.removeItem(LAST_VISIT_TS_KEY);
} }
private async _track(data: IData) { private async track(data: IData) {
if (this.disabled) return; if (this.disabled) return;
const now = new Date(); const now = new Date();
@ -304,7 +304,7 @@ export class Analytics {
} }
public ping() { public ping() {
this._track({ this.track({
ping: "1", ping: "1",
}); });
localStorage.setItem(LAST_VISIT_TS_KEY, String(new Date().getTime())); // update last visit ts localStorage.setItem(LAST_VISIT_TS_KEY, String(new Date().getTime())); // update last visit ts
@ -324,14 +324,14 @@ export class Analytics {
// But continue anyway because we still want to track the change // But continue anyway because we still want to track the change
} }
this._track({ this.track({
gt_ms: String(generationTimeMs), gt_ms: String(generationTimeMs),
}); });
} }
public trackEvent(category: string, action: string, name?: string, value?: string) { public trackEvent(category: string, action: string, name?: string, value?: string) {
if (this.disabled) return; if (this.disabled) return;
this._track({ this.track({
e_c: category, e_c: category,
e_a: action, e_a: action,
e_n: name, e_n: name,

View file

@ -33,6 +33,7 @@ import { isSecretStorageBeingAccessed, accessSecretStorage } from "./SecurityMan
import { isSecureBackupRequired } from './utils/WellKnownUtils'; import { isSecureBackupRequired } from './utils/WellKnownUtils';
import { isLoggedIn } from './components/structures/MatrixChat'; import { isLoggedIn } from './components/structures/MatrixChat';
import { MatrixEvent } from "matrix-js-sdk/src/models/event"; import { MatrixEvent } from "matrix-js-sdk/src/models/event";
import { ActionPayload } from "./dispatcher/payloads";
const KEY_BACKUP_POLL_INTERVAL = 5 * 60 * 1000; const KEY_BACKUP_POLL_INTERVAL = 5 * 60 * 1000;
@ -58,28 +59,28 @@ export default class DeviceListener {
} }
start() { start() {
MatrixClientPeg.get().on('crypto.willUpdateDevices', this._onWillUpdateDevices); MatrixClientPeg.get().on('crypto.willUpdateDevices', this.onWillUpdateDevices);
MatrixClientPeg.get().on('crypto.devicesUpdated', this._onDevicesUpdated); MatrixClientPeg.get().on('crypto.devicesUpdated', this.onDevicesUpdated);
MatrixClientPeg.get().on('deviceVerificationChanged', this._onDeviceVerificationChanged); MatrixClientPeg.get().on('deviceVerificationChanged', this.onDeviceVerificationChanged);
MatrixClientPeg.get().on('userTrustStatusChanged', this._onUserTrustStatusChanged); MatrixClientPeg.get().on('userTrustStatusChanged', this.onUserTrustStatusChanged);
MatrixClientPeg.get().on('crossSigning.keysChanged', this._onCrossSingingKeysChanged); MatrixClientPeg.get().on('crossSigning.keysChanged', this.onCrossSingingKeysChanged);
MatrixClientPeg.get().on('accountData', this._onAccountData); MatrixClientPeg.get().on('accountData', this.onAccountData);
MatrixClientPeg.get().on('sync', this._onSync); MatrixClientPeg.get().on('sync', this.onSync);
MatrixClientPeg.get().on('RoomState.events', this._onRoomStateEvents); MatrixClientPeg.get().on('RoomState.events', this.onRoomStateEvents);
this.dispatcherRef = dis.register(this._onAction); this.dispatcherRef = dis.register(this.onAction);
this._recheck(); this.recheck();
} }
stop() { stop() {
if (MatrixClientPeg.get()) { if (MatrixClientPeg.get()) {
MatrixClientPeg.get().removeListener('crypto.willUpdateDevices', this._onWillUpdateDevices); MatrixClientPeg.get().removeListener('crypto.willUpdateDevices', this.onWillUpdateDevices);
MatrixClientPeg.get().removeListener('crypto.devicesUpdated', this._onDevicesUpdated); MatrixClientPeg.get().removeListener('crypto.devicesUpdated', this.onDevicesUpdated);
MatrixClientPeg.get().removeListener('deviceVerificationChanged', this._onDeviceVerificationChanged); MatrixClientPeg.get().removeListener('deviceVerificationChanged', this.onDeviceVerificationChanged);
MatrixClientPeg.get().removeListener('userTrustStatusChanged', this._onUserTrustStatusChanged); MatrixClientPeg.get().removeListener('userTrustStatusChanged', this.onUserTrustStatusChanged);
MatrixClientPeg.get().removeListener('crossSigning.keysChanged', this._onCrossSingingKeysChanged); MatrixClientPeg.get().removeListener('crossSigning.keysChanged', this.onCrossSingingKeysChanged);
MatrixClientPeg.get().removeListener('accountData', this._onAccountData); MatrixClientPeg.get().removeListener('accountData', this.onAccountData);
MatrixClientPeg.get().removeListener('sync', this._onSync); MatrixClientPeg.get().removeListener('sync', this.onSync);
MatrixClientPeg.get().removeListener('RoomState.events', this._onRoomStateEvents); MatrixClientPeg.get().removeListener('RoomState.events', this.onRoomStateEvents);
} }
if (this.dispatcherRef) { if (this.dispatcherRef) {
dis.unregister(this.dispatcherRef); dis.unregister(this.dispatcherRef);
@ -103,15 +104,15 @@ export default class DeviceListener {
this.dismissed.add(d); this.dismissed.add(d);
} }
this._recheck(); this.recheck();
} }
dismissEncryptionSetup() { dismissEncryptionSetup() {
this.dismissedThisDeviceToast = true; this.dismissedThisDeviceToast = true;
this._recheck(); this.recheck();
} }
_ensureDeviceIdsAtStartPopulated() { private ensureDeviceIdsAtStartPopulated() {
if (this.ourDeviceIdsAtStart === null) { if (this.ourDeviceIdsAtStart === null) {
const cli = MatrixClientPeg.get(); const cli = MatrixClientPeg.get();
this.ourDeviceIdsAtStart = new Set( this.ourDeviceIdsAtStart = new Set(
@ -120,39 +121,39 @@ export default class DeviceListener {
} }
} }
_onWillUpdateDevices = async (users: string[], initialFetch?: boolean) => { private onWillUpdateDevices = async (users: string[], initialFetch?: boolean) => {
// If we didn't know about *any* devices before (ie. it's fresh login), // If we didn't know about *any* devices before (ie. it's fresh login),
// then they are all pre-existing devices, so ignore this and set the // then they are all pre-existing devices, so ignore this and set the
// devicesAtStart list to the devices that we see after the fetch. // devicesAtStart list to the devices that we see after the fetch.
if (initialFetch) return; if (initialFetch) return;
const myUserId = MatrixClientPeg.get().getUserId(); const myUserId = MatrixClientPeg.get().getUserId();
if (users.includes(myUserId)) this._ensureDeviceIdsAtStartPopulated(); if (users.includes(myUserId)) this.ensureDeviceIdsAtStartPopulated();
// No need to do a recheck here: we just need to get a snapshot of our devices // No need to do a recheck here: we just need to get a snapshot of our devices
// before we download any new ones. // before we download any new ones.
}; };
_onDevicesUpdated = (users: string[]) => { private onDevicesUpdated = (users: string[]) => {
if (!users.includes(MatrixClientPeg.get().getUserId())) return; if (!users.includes(MatrixClientPeg.get().getUserId())) return;
this._recheck(); this.recheck();
}; };
_onDeviceVerificationChanged = (userId: string) => { private onDeviceVerificationChanged = (userId: string) => {
if (userId !== MatrixClientPeg.get().getUserId()) return; if (userId !== MatrixClientPeg.get().getUserId()) return;
this._recheck(); this.recheck();
}; };
_onUserTrustStatusChanged = (userId: string) => { private onUserTrustStatusChanged = (userId: string) => {
if (userId !== MatrixClientPeg.get().getUserId()) return; if (userId !== MatrixClientPeg.get().getUserId()) return;
this._recheck(); this.recheck();
}; };
_onCrossSingingKeysChanged = () => { private onCrossSingingKeysChanged = () => {
this._recheck(); this.recheck();
}; };
_onAccountData = (ev) => { private onAccountData = (ev: MatrixEvent) => {
// User may have: // User may have:
// * migrated SSSS to symmetric // * migrated SSSS to symmetric
// * uploaded keys to secret storage // * uploaded keys to secret storage
@ -163,32 +164,32 @@ export default class DeviceListener {
ev.getType().startsWith('m.cross_signing.') || ev.getType().startsWith('m.cross_signing.') ||
ev.getType() === 'm.megolm_backup.v1' ev.getType() === 'm.megolm_backup.v1'
) { ) {
this._recheck(); this.recheck();
} }
}; };
_onSync = (state, prevState) => { private onSync = (state, prevState) => {
if (state === 'PREPARED' && prevState === null) this._recheck(); if (state === 'PREPARED' && prevState === null) this.recheck();
}; };
_onRoomStateEvents = (ev: MatrixEvent) => { private onRoomStateEvents = (ev: MatrixEvent) => {
if (ev.getType() !== "m.room.encryption") { if (ev.getType() !== "m.room.encryption") {
return; return;
} }
// If a room changes to encrypted, re-check as it may be our first // If a room changes to encrypted, re-check as it may be our first
// encrypted room. This also catches encrypted room creation as well. // encrypted room. This also catches encrypted room creation as well.
this._recheck(); this.recheck();
}; };
_onAction = ({ action }) => { private onAction = ({ action }: ActionPayload) => {
if (action !== "on_logged_in") return; if (action !== "on_logged_in") return;
this._recheck(); this.recheck();
}; };
// The server doesn't tell us when key backup is set up, so we poll // The server doesn't tell us when key backup is set up, so we poll
// & cache the result // & cache the result
async _getKeyBackupInfo() { private async getKeyBackupInfo() {
const now = (new Date()).getTime(); const now = (new Date()).getTime();
if (!this.keyBackupInfo || this.keyBackupFetchedAt < now - KEY_BACKUP_POLL_INTERVAL) { if (!this.keyBackupInfo || this.keyBackupFetchedAt < now - KEY_BACKUP_POLL_INTERVAL) {
this.keyBackupInfo = await MatrixClientPeg.get().getKeyBackupVersion(); this.keyBackupInfo = await MatrixClientPeg.get().getKeyBackupVersion();
@ -206,7 +207,7 @@ export default class DeviceListener {
return cli && cli.getRooms().some(r => cli.isRoomEncrypted(r.roomId)); return cli && cli.getRooms().some(r => cli.isRoomEncrypted(r.roomId));
} }
async _recheck() { private async recheck() {
const cli = MatrixClientPeg.get(); const cli = MatrixClientPeg.get();
if (!await cli.doesServerSupportUnstableFeature("org.matrix.e2e_cross_signing")) return; if (!await cli.doesServerSupportUnstableFeature("org.matrix.e2e_cross_signing")) return;
@ -235,7 +236,7 @@ export default class DeviceListener {
// Cross-signing on account but this device doesn't trust the master key (verify this session) // Cross-signing on account but this device doesn't trust the master key (verify this session)
showSetupEncryptionToast(SetupKind.VERIFY_THIS_SESSION); showSetupEncryptionToast(SetupKind.VERIFY_THIS_SESSION);
} else { } else {
const backupInfo = await this._getKeyBackupInfo(); const backupInfo = await this.getKeyBackupInfo();
if (backupInfo) { if (backupInfo) {
// No cross-signing on account but key backup available (upgrade encryption) // No cross-signing on account but key backup available (upgrade encryption)
showSetupEncryptionToast(SetupKind.UPGRADE_ENCRYPTION); showSetupEncryptionToast(SetupKind.UPGRADE_ENCRYPTION);
@ -256,7 +257,7 @@ export default class DeviceListener {
// This needs to be done after awaiting on downloadKeys() above, so // This needs to be done after awaiting on downloadKeys() above, so
// we make sure we get the devices after the fetch is done. // we make sure we get the devices after the fetch is done.
this._ensureDeviceIdsAtStartPopulated(); this.ensureDeviceIdsAtStartPopulated();
// Unverified devices that were there last time the app ran // Unverified devices that were there last time the app ran
// (technically could just be a boolean: we don't actually // (technically could just be a boolean: we don't actually

View file

@ -105,7 +105,7 @@ export interface IMatrixClientPeg {
* This module provides a singleton instance of this class so the 'current' * This module provides a singleton instance of this class so the 'current'
* Matrix Client object is available easily. * Matrix Client object is available easily.
*/ */
class _MatrixClientPeg implements IMatrixClientPeg { class MatrixClientPegClass implements IMatrixClientPeg {
// These are the default options used when when the // These are the default options used when when the
// client is started in 'start'. These can be altered // client is started in 'start'. These can be altered
// at any time up to after the 'will_start_client' // at any time up to after the 'will_start_client'
@ -300,7 +300,7 @@ class _MatrixClientPeg implements IMatrixClientPeg {
} }
if (!window.mxMatrixClientPeg) { if (!window.mxMatrixClientPeg) {
window.mxMatrixClientPeg = new _MatrixClientPeg(); window.mxMatrixClientPeg = new MatrixClientPegClass();
} }
export const MatrixClientPeg = window.mxMatrixClientPeg; export const MatrixClientPeg = window.mxMatrixClientPeg;

View file

@ -122,14 +122,14 @@ export class ModalManager {
} }
public createDialog<T extends any[]>( public createDialog<T extends any[]>(
Element: React.ComponentType, Element: React.ComponentType, // eslint-disable-line @typescript-eslint/naming-convention
...rest: ParametersWithoutFirst<ModalManager["createDialogAsync"]> ...rest: ParametersWithoutFirst<ModalManager["createDialogAsync"]>
) { ) {
return this.createDialogAsync<T>(Promise.resolve(Element), ...rest); return this.createDialogAsync<T>(Promise.resolve(Element), ...rest);
} }
public appendDialog<T extends any[]>( public appendDialog<T extends any[]>(
Element: React.ComponentType, Element: React.ComponentType, // eslint-disable-line @typescript-eslint/naming-convention
...rest: ParametersWithoutFirst<ModalManager["appendDialogAsync"]> ...rest: ParametersWithoutFirst<ModalManager["appendDialogAsync"]>
) { ) {
return this.appendDialogAsync<T>(Promise.resolve(Element), ...rest); return this.appendDialogAsync<T>(Promise.resolve(Element), ...rest);

View file

@ -522,7 +522,7 @@ export const Commands = [
aliases: ['j', 'goto'], aliases: ['j', 'goto'],
args: '<room-address>', args: '<room-address>',
description: _td('Joins room with given address'), description: _td('Joins room with given address'),
runFn: function(_, args) { runFn: function(roomId, args) {
if (args) { if (args) {
// Note: we support 2 versions of this command. The first is // Note: we support 2 versions of this command. The first is
// the public-facing one for most users and the other is a // the public-facing one for most users and the other is a
@ -1069,7 +1069,7 @@ export const Commands = [
command: "msg", command: "msg",
description: _td("Sends a message to the given user"), description: _td("Sends a message to the given user"),
args: "<user-id> <message>", args: "<user-id> <message>",
runFn: function(_, args) { runFn: function(roomId, args) {
if (args) { if (args) {
// matches the first whitespace delimited group and then the rest of the string // matches the first whitespace delimited group and then the rest of the string
const matches = args.match(/^(\S+?)(?: +(.*))?$/s); const matches = args.match(/^(\S+?)(?: +(.*))?$/s);

View file

@ -109,7 +109,7 @@ export default class UserProvider extends AutocompleteProvider {
limit = -1, limit = -1,
): Promise<ICompletion[]> { ): Promise<ICompletion[]> {
// lazy-load user list into matcher // lazy-load user list into matcher
if (!this.users) this._makeUsers(); if (!this.users) this.makeUsers();
let completions = []; let completions = [];
const { command, range } = this.getCurrentCommand(rawQuery, selection, force); const { command, range } = this.getCurrentCommand(rawQuery, selection, force);
@ -147,7 +147,7 @@ export default class UserProvider extends AutocompleteProvider {
return _t('Users'); return _t('Users');
} }
_makeUsers() { private makeUsers() {
const events = this.room.getLiveTimeline().getEvents(); const events = this.room.getLiveTimeline().getEvents();
const lastSpoken = {}; const lastSpoken = {};

View file

@ -44,7 +44,7 @@ export default class EmbeddedPage extends React.PureComponent {
constructor(props, context) { constructor(props, context) {
super(props, context); super(props, context);
this._dispatcherRef = null; this.dispatcherRef = null;
this.state = { this.state = {
page: '', page: '',

View file

@ -431,7 +431,7 @@ export default class GroupView extends React.Component {
this._initGroupStore(this.props.groupId, true); this._initGroupStore(this.props.groupId, true);
this._dispatcherRef = dis.register(this._onAction); this.dispatcherRef = dis.register(this._onAction);
this._rightPanelStoreToken = RightPanelStore.getSharedInstance().addListener(this._onRightPanelStoreUpdate); this._rightPanelStoreToken = RightPanelStore.getSharedInstance().addListener(this._onRightPanelStoreUpdate);
} }

View file

@ -17,8 +17,8 @@ limitations under the License.
*/ */
import * as React from 'react'; import * as React from 'react';
import * as PropTypes from 'prop-types';
import { MatrixClient } from 'matrix-js-sdk/src/client'; import { MatrixClient } from 'matrix-js-sdk/src/client';
import { MatrixEvent } from 'matrix-js-sdk/src/models/event';
import { Key } from '../../Keyboard'; import { Key } from '../../Keyboard';
import PageTypes from '../../PageTypes'; import PageTypes from '../../PageTypes';
@ -79,6 +79,8 @@ function canElementReceiveInput(el) {
interface IProps { interface IProps {
matrixClient: MatrixClient; matrixClient: MatrixClient;
// Called with the credentials of a registered user (if they were a ROU that
// transitioned to PWLU)
onRegistered: (credentials: IMatrixClientCreds) => Promise<MatrixClient>; onRegistered: (credentials: IMatrixClientCreds) => Promise<MatrixClient>;
hideToSRUsers: boolean; hideToSRUsers: boolean;
resizeNotifier: ResizeNotifier; resizeNotifier: ResizeNotifier;
@ -140,18 +142,6 @@ interface IState {
class LoggedInView extends React.Component<IProps, IState> { class LoggedInView extends React.Component<IProps, IState> {
static displayName = 'LoggedInView'; static displayName = 'LoggedInView';
static propTypes = {
matrixClient: PropTypes.instanceOf(MatrixClient).isRequired,
page_type: PropTypes.string.isRequired,
onRoomCreated: PropTypes.func,
// Called with the credentials of a registered user (if they were a ROU that
// transitioned to PWLU)
onRegistered: PropTypes.func,
// and lots and lots of other stuff.
};
protected readonly _matrixClient: MatrixClient; protected readonly _matrixClient: MatrixClient;
protected readonly _roomView: React.RefObject<any>; protected readonly _roomView: React.RefObject<any>;
protected readonly _resizeContainer: React.RefObject<ResizeHandle>; protected readonly _resizeContainer: React.RefObject<ResizeHandle>;
@ -181,10 +171,10 @@ class LoggedInView extends React.Component<IProps, IState> {
} }
componentDidMount() { componentDidMount() {
document.addEventListener('keydown', this._onNativeKeyDown, false); document.addEventListener('keydown', this.onNativeKeyDown, false);
CallHandler.sharedInstance().addListener(CallHandlerEvent.CallsChanged, this.onCallsChanged); CallHandler.sharedInstance().addListener(CallHandlerEvent.CallsChanged, this.onCallsChanged);
this._updateServerNoticeEvents(); this.updateServerNoticeEvents();
this._matrixClient.on("accountData", this.onAccountData); this._matrixClient.on("accountData", this.onAccountData);
this._matrixClient.on("sync", this.onSync); this._matrixClient.on("sync", this.onSync);
@ -200,13 +190,13 @@ class LoggedInView extends React.Component<IProps, IState> {
"useCompactLayout", null, this.onCompactLayoutChanged, "useCompactLayout", null, this.onCompactLayoutChanged,
); );
this.resizer = this._createResizer(); this.resizer = this.createResizer();
this.resizer.attach(); this.resizer.attach();
this._loadResizerPreferences(); this.loadResizerPreferences();
} }
componentWillUnmount() { componentWillUnmount() {
document.removeEventListener('keydown', this._onNativeKeyDown, false); document.removeEventListener('keydown', this.onNativeKeyDown, false);
CallHandler.sharedInstance().removeListener(CallHandlerEvent.CallsChanged, this.onCallsChanged); CallHandler.sharedInstance().removeListener(CallHandlerEvent.CallsChanged, this.onCallsChanged);
this._matrixClient.removeListener("accountData", this.onAccountData); this._matrixClient.removeListener("accountData", this.onAccountData);
this._matrixClient.removeListener("sync", this.onSync); this._matrixClient.removeListener("sync", this.onSync);
@ -221,37 +211,37 @@ class LoggedInView extends React.Component<IProps, IState> {
}); });
}; };
canResetTimelineInRoom = (roomId) => { public canResetTimelineInRoom = (roomId: string) => {
if (!this._roomView.current) { if (!this._roomView.current) {
return true; return true;
} }
return this._roomView.current.canResetTimeline(); return this._roomView.current.canResetTimeline();
}; };
_createResizer() { private createResizer() {
let size; let panelSize;
let collapsed; let panelCollapsed;
const collapseConfig: ICollapseConfig = { const collapseConfig: ICollapseConfig = {
// TODO decrease this once Spaces launches as it'll no longer need to include the 56px Community Panel // TODO decrease this once Spaces launches as it'll no longer need to include the 56px Community Panel
toggleSize: 206 - 50, toggleSize: 206 - 50,
onCollapsed: (_collapsed) => { onCollapsed: (collapsed) => {
collapsed = _collapsed; panelCollapsed = collapsed;
if (_collapsed) { if (collapsed) {
dis.dispatch({ action: "hide_left_panel" }); dis.dispatch({ action: "hide_left_panel" });
window.localStorage.setItem("mx_lhs_size", '0'); window.localStorage.setItem("mx_lhs_size", '0');
} else { } else {
dis.dispatch({ action: "show_left_panel" }); dis.dispatch({ action: "show_left_panel" });
} }
}, },
onResized: (_size) => { onResized: (size) => {
size = _size; panelSize = size;
this.props.resizeNotifier.notifyLeftHandleResized(); this.props.resizeNotifier.notifyLeftHandleResized();
}, },
onResizeStart: () => { onResizeStart: () => {
this.props.resizeNotifier.startResizing(); this.props.resizeNotifier.startResizing();
}, },
onResizeStop: () => { onResizeStop: () => {
if (!collapsed) window.localStorage.setItem("mx_lhs_size", '' + size); if (!panelCollapsed) window.localStorage.setItem("mx_lhs_size", '' + panelSize);
this.props.resizeNotifier.stopResizing(); this.props.resizeNotifier.stopResizing();
}, },
isItemCollapsed: domNode => { isItemCollapsed: domNode => {
@ -267,7 +257,7 @@ class LoggedInView extends React.Component<IProps, IState> {
return resizer; return resizer;
} }
_loadResizerPreferences() { private loadResizerPreferences() {
let lhsSize = parseInt(window.localStorage.getItem("mx_lhs_size"), 10); let lhsSize = parseInt(window.localStorage.getItem("mx_lhs_size"), 10);
if (isNaN(lhsSize)) { if (isNaN(lhsSize)) {
lhsSize = 350; lhsSize = 350;
@ -275,7 +265,7 @@ class LoggedInView extends React.Component<IProps, IState> {
this.resizer.forHandleAt(0).resize(lhsSize); this.resizer.forHandleAt(0).resize(lhsSize);
} }
onAccountData = (event) => { private onAccountData = (event: MatrixEvent) => {
if (event.getType() === "m.ignored_user_list") { if (event.getType() === "m.ignored_user_list") {
dis.dispatch({ action: "ignore_state_changed" }); dis.dispatch({ action: "ignore_state_changed" });
} }
@ -307,16 +297,16 @@ class LoggedInView extends React.Component<IProps, IState> {
} }
if (oldSyncState === 'PREPARED' && syncState === 'SYNCING') { if (oldSyncState === 'PREPARED' && syncState === 'SYNCING') {
this._updateServerNoticeEvents(); this.updateServerNoticeEvents();
} else { } else {
this._calculateServerLimitToast(this.state.syncErrorData, this.state.usageLimitEventContent); this.calculateServerLimitToast(this.state.syncErrorData, this.state.usageLimitEventContent);
} }
}; };
onRoomStateEvents = (ev, state) => { onRoomStateEvents = (ev, state) => {
const serverNoticeList = RoomListStore.instance.orderedLists[DefaultTagID.ServerNotice]; const serverNoticeList = RoomListStore.instance.orderedLists[DefaultTagID.ServerNotice];
if (serverNoticeList && serverNoticeList.some(r => r.roomId === ev.getRoomId())) { if (serverNoticeList && serverNoticeList.some(r => r.roomId === ev.getRoomId())) {
this._updateServerNoticeEvents(); this.updateServerNoticeEvents();
} }
}; };
@ -326,7 +316,7 @@ class LoggedInView extends React.Component<IProps, IState> {
}); });
}; };
_calculateServerLimitToast(syncError: IState["syncErrorData"], usageLimitEventContent?: IUsageLimit) { private calculateServerLimitToast(syncError: IState["syncErrorData"], usageLimitEventContent?: IUsageLimit) {
const error = syncError && syncError.error && syncError.error.errcode === "M_RESOURCE_LIMIT_EXCEEDED"; const error = syncError && syncError.error && syncError.error.errcode === "M_RESOURCE_LIMIT_EXCEEDED";
if (error) { if (error) {
usageLimitEventContent = syncError.error.data; usageLimitEventContent = syncError.error.data;
@ -346,7 +336,7 @@ class LoggedInView extends React.Component<IProps, IState> {
} }
} }
_updateServerNoticeEvents = async () => { private updateServerNoticeEvents = async () => {
const serverNoticeList = RoomListStore.instance.orderedLists[DefaultTagID.ServerNotice]; const serverNoticeList = RoomListStore.instance.orderedLists[DefaultTagID.ServerNotice];
if (!serverNoticeList) return []; if (!serverNoticeList) return [];
@ -378,7 +368,7 @@ class LoggedInView extends React.Component<IProps, IState> {
); );
}); });
const usageLimitEventContent = usageLimitEvent && usageLimitEvent.getContent(); const usageLimitEventContent = usageLimitEvent && usageLimitEvent.getContent();
this._calculateServerLimitToast(this.state.syncErrorData, usageLimitEventContent); this.calculateServerLimitToast(this.state.syncErrorData, usageLimitEventContent);
this.setState({ this.setState({
usageLimitEventContent, usageLimitEventContent,
usageLimitEventTs: pinnedEventTs, usageLimitEventTs: pinnedEventTs,
@ -387,7 +377,7 @@ class LoggedInView extends React.Component<IProps, IState> {
}); });
}; };
_onPaste = (ev) => { private onPaste = (ev) => {
let canReceiveInput = false; let canReceiveInput = false;
let element = ev.target; let element = ev.target;
// test for all parents because the target can be a child of a contenteditable element // test for all parents because the target can be a child of a contenteditable element
@ -425,22 +415,22 @@ class LoggedInView extends React.Component<IProps, IState> {
We also listen with a native listener on the document to get keydown events when no element is focused. We also listen with a native listener on the document to get keydown events when no element is focused.
Bubbling is irrelevant here as the target is the body element. Bubbling is irrelevant here as the target is the body element.
*/ */
_onReactKeyDown = (ev) => { private onReactKeyDown = (ev) => {
// events caught while bubbling up on the root element // events caught while bubbling up on the root element
// of this component, so something must be focused. // of this component, so something must be focused.
this._onKeyDown(ev); this.onKeyDown(ev);
}; };
_onNativeKeyDown = (ev) => { private onNativeKeyDown = (ev) => {
// only pass this if there is no focused element. // only pass this if there is no focused element.
// if there is, _onKeyDown will be called by the // if there is, onKeyDown will be called by the
// react keydown handler that respects the react bubbling order. // react keydown handler that respects the react bubbling order.
if (ev.target === document.body) { if (ev.target === document.body) {
this._onKeyDown(ev); this.onKeyDown(ev);
} }
}; };
_onKeyDown = (ev) => { private onKeyDown = (ev) => {
let handled = false; let handled = false;
const roomAction = getKeyBindingsManager().getRoomAction(ev); const roomAction = getKeyBindingsManager().getRoomAction(ev);
@ -450,7 +440,7 @@ class LoggedInView extends React.Component<IProps, IState> {
case RoomAction.JumpToFirstMessage: case RoomAction.JumpToFirstMessage:
case RoomAction.JumpToLatestMessage: case RoomAction.JumpToLatestMessage:
// pass the event down to the scroll panel // pass the event down to the scroll panel
this._onScrollKeyPressed(ev); this.onScrollKeyPressed(ev);
handled = true; handled = true;
break; break;
case RoomAction.FocusSearch: case RoomAction.FocusSearch:
@ -565,7 +555,7 @@ class LoggedInView extends React.Component<IProps, IState> {
* dispatch a page-up/page-down/etc to the appropriate component * dispatch a page-up/page-down/etc to the appropriate component
* @param {Object} ev The key event * @param {Object} ev The key event
*/ */
_onScrollKeyPressed = (ev) => { private onScrollKeyPressed = (ev) => {
if (this._roomView.current) { if (this._roomView.current) {
this._roomView.current.handleScrollKey(ev); this._roomView.current.handleScrollKey(ev);
} }
@ -625,8 +615,8 @@ class LoggedInView extends React.Component<IProps, IState> {
return ( return (
<MatrixClientContext.Provider value={this._matrixClient}> <MatrixClientContext.Provider value={this._matrixClient}>
<div <div
onPaste={this._onPaste} onPaste={this.onPaste}
onKeyDown={this._onReactKeyDown} onKeyDown={this.onReactKeyDown}
className='mx_MatrixChat_wrapper' className='mx_MatrixChat_wrapper'
aria-hidden={this.props.hideToSRUsers} aria-hidden={this.props.hideToSRUsers}
> >

View file

@ -431,7 +431,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
} }
// TODO: [REACT-WARNING] Replace with appropriate lifecycle stage // TODO: [REACT-WARNING] Replace with appropriate lifecycle stage
// eslint-disable-next-line camelcase // eslint-disable-next-line
UNSAFE_componentWillUpdate(props, state) { UNSAFE_componentWillUpdate(props, state) {
if (this.shouldTrackPageChange(this.state, state)) { if (this.shouldTrackPageChange(this.state, state)) {
this.startPageChangeTimer(); this.startPageChangeTimer();

View file

@ -17,6 +17,7 @@ limitations under the License.
import React from 'react'; import React from 'react';
import { Room } from "matrix-js-sdk/src/models/room"; import { Room } from "matrix-js-sdk/src/models/room";
import { RoomState } from "matrix-js-sdk/src/models/room-state";
import { User } from "matrix-js-sdk/src/models/user"; import { User } from "matrix-js-sdk/src/models/user";
import { RoomMember } from "matrix-js-sdk/src/models/room-member"; import { RoomMember } from "matrix-js-sdk/src/models/room-member";
import { MatrixEvent } from "matrix-js-sdk/src/models/event"; import { MatrixEvent } from "matrix-js-sdk/src/models/event";
@ -152,7 +153,7 @@ export default class RightPanel extends React.Component<IProps, IState> {
} }
// TODO: [REACT-WARNING] Replace with appropriate lifecycle event // TODO: [REACT-WARNING] Replace with appropriate lifecycle event
UNSAFE_componentWillReceiveProps(newProps) { // eslint-disable-line camelcase UNSAFE_componentWillReceiveProps(newProps) { // eslint-disable-line
if (newProps.groupId !== this.props.groupId) { if (newProps.groupId !== this.props.groupId) {
this.unregisterGroupStore(); this.unregisterGroupStore();
this.initGroupStore(newProps.groupId); this.initGroupStore(newProps.groupId);
@ -174,7 +175,7 @@ export default class RightPanel extends React.Component<IProps, IState> {
}); });
}; };
private onRoomStateMember = (ev: MatrixEvent, _, member: RoomMember) => { private onRoomStateMember = (ev: MatrixEvent, state: RoomState, member: RoomMember) => {
if (!this.props.room || member.roomId !== this.props.room.roomId) { if (!this.props.room || member.roomId !== this.props.room.roomId) {
return; return;
} }

View file

@ -814,7 +814,7 @@ export default class RoomDirectory extends React.Component<IProps, IState> {
}) : _t("Explore rooms"); }) : _t("Explore rooms");
return ( return (
<BaseDialog <BaseDialog
className={'mx_RoomDirectory_dialog'} className="mx_RoomDirectory_dialog"
hasCancel={true} hasCancel={true}
onFinished={this.onFinished} onFinished={this.onFinished}
title={title} title={title}

View file

@ -458,7 +458,7 @@ const SpaceSetupFirstRooms = ({ space, title, description, onFinished }) => {
const numFields = 3; const numFields = 3;
const placeholders = [_t("General"), _t("Random"), _t("Support")]; const placeholders = [_t("General"), _t("Random"), _t("Support")];
const [roomNames, setRoomName] = useStateArray(numFields, [_t("General"), _t("Random"), ""]); const [roomNames, setRoomName] = useStateArray(numFields, [_t("General"), _t("Random"), ""]);
const fields = new Array(numFields).fill(0).map((_, i) => { const fields = new Array(numFields).fill(0).map((x, i) => {
const name = "roomName" + i; const name = "roomName" + i;
return <Field return <Field
key={name} key={name}
@ -625,7 +625,7 @@ const SpaceSetupPrivateInvite = ({ space, onFinished }) => {
const numFields = 3; const numFields = 3;
const fieldRefs: RefObject<Field>[] = [useRef(), useRef(), useRef()]; const fieldRefs: RefObject<Field>[] = [useRef(), useRef(), useRef()];
const [emailAddresses, setEmailAddress] = useStateArray(numFields, ""); const [emailAddresses, setEmailAddress] = useStateArray(numFields, "");
const fields = new Array(numFields).fill(0).map((_, i) => { const fields = new Array(numFields).fill(0).map((x, i) => {
const name = "emailAddress" + i; const name = "emailAddress" + i;
return <Field return <Field
key={name} key={name}

View file

@ -74,7 +74,7 @@ export default class TabbedView extends React.Component<IProps, IState> {
tabLocation: TabLocation.LEFT, tabLocation: TabLocation.LEFT,
}; };
private _getActiveTabIndex() { private getActiveTabIndex() {
if (!this.state || !this.state.activeTabIndex) return 0; if (!this.state || !this.state.activeTabIndex) return 0;
return this.state.activeTabIndex; return this.state.activeTabIndex;
} }
@ -84,7 +84,7 @@ export default class TabbedView extends React.Component<IProps, IState> {
* @param {Tab} tab the tab to show * @param {Tab} tab the tab to show
* @private * @private
*/ */
private _setActiveTab(tab: Tab) { private setActiveTab(tab: Tab) {
const idx = this.props.tabs.indexOf(tab); const idx = this.props.tabs.indexOf(tab);
if (idx !== -1) { if (idx !== -1) {
if (this.props.onChange) this.props.onChange(tab.id); if (this.props.onChange) this.props.onChange(tab.id);
@ -94,18 +94,18 @@ export default class TabbedView extends React.Component<IProps, IState> {
} }
} }
private _renderTabLabel(tab: Tab) { private renderTabLabel(tab: Tab) {
let classes = "mx_TabbedView_tabLabel "; let classes = "mx_TabbedView_tabLabel ";
const idx = this.props.tabs.indexOf(tab); const idx = this.props.tabs.indexOf(tab);
if (idx === this._getActiveTabIndex()) classes += "mx_TabbedView_tabLabel_active"; if (idx === this.getActiveTabIndex()) classes += "mx_TabbedView_tabLabel_active";
let tabIcon = null; let tabIcon = null;
if (tab.icon) { if (tab.icon) {
tabIcon = <span className={`mx_TabbedView_maskedIcon ${tab.icon}`} />; tabIcon = <span className={`mx_TabbedView_maskedIcon ${tab.icon}`} />;
} }
const onClickHandler = () => this._setActiveTab(tab); const onClickHandler = () => this.setActiveTab(tab);
const label = _t(tab.label); const label = _t(tab.label);
return ( return (
@ -118,7 +118,7 @@ export default class TabbedView extends React.Component<IProps, IState> {
); );
} }
private _renderTabPanel(tab: Tab): React.ReactNode { private renderTabPanel(tab: Tab): React.ReactNode {
return ( return (
<div className="mx_TabbedView_tabPanel" key={"mx_tabpanel_" + tab.label}> <div className="mx_TabbedView_tabPanel" key={"mx_tabpanel_" + tab.label}>
<AutoHideScrollbar className='mx_TabbedView_tabPanelContent'> <AutoHideScrollbar className='mx_TabbedView_tabPanelContent'>
@ -129,8 +129,8 @@ export default class TabbedView extends React.Component<IProps, IState> {
} }
public render(): React.ReactNode { public render(): React.ReactNode {
const labels = this.props.tabs.map(tab => this._renderTabLabel(tab)); const labels = this.props.tabs.map(tab => this.renderTabLabel(tab));
const panel = this._renderTabPanel(this.props.tabs[this._getActiveTabIndex()]); const panel = this.renderTabPanel(this.props.tabs[this.getActiveTabIndex()]);
const tabbedViewClasses = classNames({ const tabbedViewClasses = classNames({
'mx_TabbedView': true, 'mx_TabbedView': true,

View file

@ -277,7 +277,7 @@ class TimelinePanel extends React.Component<IProps, IState> {
} }
// TODO: [REACT-WARNING] Move into constructor // TODO: [REACT-WARNING] Move into constructor
// eslint-disable-next-line camelcase // eslint-disable-next-line
UNSAFE_componentWillMount() { UNSAFE_componentWillMount() {
if (this.props.manageReadReceipts) { if (this.props.manageReadReceipts) {
this.updateReadReceiptOnUserActivity(); this.updateReadReceiptOnUserActivity();
@ -290,7 +290,7 @@ class TimelinePanel extends React.Component<IProps, IState> {
} }
// TODO: [REACT-WARNING] Replace with appropriate lifecycle event // TODO: [REACT-WARNING] Replace with appropriate lifecycle event
// eslint-disable-next-line camelcase // eslint-disable-next-line
UNSAFE_componentWillReceiveProps(newProps) { UNSAFE_componentWillReceiveProps(newProps) {
if (newProps.timelineSet !== this.props.timelineSet) { if (newProps.timelineSet !== this.props.timelineSet) {
// throw new Error("changing timelineSet on a TimelinePanel is not supported"); // throw new Error("changing timelineSet on a TimelinePanel is not supported");

View file

@ -37,14 +37,14 @@ export default class ToastContainer extends React.Component<{}, IState> {
// toasts may dismiss themselves in their didMount if they find // toasts may dismiss themselves in their didMount if they find
// they're already irrelevant by the time they're mounted, and // they're already irrelevant by the time they're mounted, and
// our own componentDidMount is too late. // our own componentDidMount is too late.
ToastStore.sharedInstance().on('update', this._onToastStoreUpdate); ToastStore.sharedInstance().on('update', this.onToastStoreUpdate);
} }
componentWillUnmount() { componentWillUnmount() {
ToastStore.sharedInstance().removeListener('update', this._onToastStoreUpdate); ToastStore.sharedInstance().removeListener('update', this.onToastStoreUpdate);
} }
_onToastStoreUpdate = () => { private onToastStoreUpdate = () => {
this.setState({ this.setState({
toasts: ToastStore.sharedInstance().getToasts(), toasts: ToastStore.sharedInstance().getToasts(),
countSeen: ToastStore.sharedInstance().getCountSeen(), countSeen: ToastStore.sharedInstance().getCountSeen(),

View file

@ -101,7 +101,7 @@ export default class ForgotPassword extends React.Component<IProps, IState> {
} }
// TODO: [REACT-WARNING] Replace with appropriate lifecycle event // TODO: [REACT-WARNING] Replace with appropriate lifecycle event
// eslint-disable-next-line camelcase // eslint-disable-next-line
public UNSAFE_componentWillReceiveProps(newProps: IProps): void { public UNSAFE_componentWillReceiveProps(newProps: IProps): void {
if (newProps.serverConfig.hsUrl === this.props.serverConfig.hsUrl && if (newProps.serverConfig.hsUrl === this.props.serverConfig.hsUrl &&
newProps.serverConfig.isUrl === this.props.serverConfig.isUrl) return; newProps.serverConfig.isUrl === this.props.serverConfig.isUrl) return;

View file

@ -144,7 +144,7 @@ export default class LoginComponent extends React.PureComponent<IProps, IState>
} }
// TODO: [REACT-WARNING] Replace with appropriate lifecycle event // TODO: [REACT-WARNING] Replace with appropriate lifecycle event
// eslint-disable-next-line camelcase // eslint-disable-next-line
UNSAFE_componentWillMount() { UNSAFE_componentWillMount() {
this.initLoginLogic(this.props.serverConfig); this.initLoginLogic(this.props.serverConfig);
} }
@ -154,7 +154,7 @@ export default class LoginComponent extends React.PureComponent<IProps, IState>
} }
// TODO: [REACT-WARNING] Replace with appropriate lifecycle event // TODO: [REACT-WARNING] Replace with appropriate lifecycle event
// eslint-disable-next-line camelcase // eslint-disable-next-line
UNSAFE_componentWillReceiveProps(newProps) { UNSAFE_componentWillReceiveProps(newProps) {
if (newProps.serverConfig.hsUrl === this.props.serverConfig.hsUrl && if (newProps.serverConfig.hsUrl === this.props.serverConfig.hsUrl &&
newProps.serverConfig.isUrl === this.props.serverConfig.isUrl) return; newProps.serverConfig.isUrl === this.props.serverConfig.isUrl) return;

View file

@ -141,7 +141,7 @@ export default class Registration extends React.Component<IProps, IState> {
} }
// TODO: [REACT-WARNING] Replace with appropriate lifecycle event // TODO: [REACT-WARNING] Replace with appropriate lifecycle event
// eslint-disable-next-line camelcase // eslint-disable-next-line
UNSAFE_componentWillReceiveProps(newProps) { UNSAFE_componentWillReceiveProps(newProps) {
if (newProps.serverConfig.hsUrl === this.props.serverConfig.hsUrl && if (newProps.serverConfig.hsUrl === this.props.serverConfig.hsUrl &&
newProps.serverConfig.isUrl === this.props.serverConfig.isUrl) return; newProps.serverConfig.isUrl === this.props.serverConfig.isUrl) return;

View file

@ -187,7 +187,7 @@ export default class CommunityPrototypeInviteDialog extends React.PureComponent<
emailAddresses.push(( emailAddresses.push((
<Field <Field
key={emailAddresses.length} key={emailAddresses.length}
value={""} value=""
onChange={(e) => this.onAddressChange(e, emailAddresses.length)} onChange={(e) => this.onAddressChange(e, emailAddresses.length)}
label={emailAddresses.length > 0 ? _t("Add another email") : _t("Email address")} label={emailAddresses.length > 0 ? _t("Add another email") : _t("Email address")}
placeholder={emailAddresses.length > 0 ? _t("Add another email") : _t("Email address")} placeholder={emailAddresses.length > 0 ? _t("Add another email") : _t("Email address")}

View file

@ -102,7 +102,7 @@ export default class CreateGroupDialog extends React.Component<IProps, IState> {
}); });
}; };
_onCancel = () => { private onCancel = () => {
this.props.onFinished(false); this.props.onFinished(false);
}; };
@ -167,7 +167,7 @@ export default class CreateGroupDialog extends React.Component<IProps, IState> {
</div> </div>
<div className="mx_Dialog_buttons"> <div className="mx_Dialog_buttons">
<input type="submit" value={_t('Create')} className="mx_Dialog_primary" /> <input type="submit" value={_t('Create')} className="mx_Dialog_primary" />
<button onClick={this._onCancel}> <button onClick={this.onCancel}>
{ _t("Cancel") } { _t("Cancel") }
</button> </button>
</div> </div>

View file

@ -337,7 +337,7 @@ class FilteredList extends React.PureComponent<IFilteredListProps, IFilteredList
} }
// TODO: [REACT-WARNING] Replace with appropriate lifecycle event // TODO: [REACT-WARNING] Replace with appropriate lifecycle event
UNSAFE_componentWillReceiveProps(nextProps) { // eslint-disable-line camelcase UNSAFE_componentWillReceiveProps(nextProps) { // eslint-disable-line
if (this.props.children === nextProps.children && this.props.query === nextProps.query) return; if (this.props.children === nextProps.children && this.props.query === nextProps.query) return;
this.setState({ this.setState({
filteredChildren: FilteredList.filterChildren(nextProps.children, nextProps.query), filteredChildren: FilteredList.filterChildren(nextProps.children, nextProps.query),

View file

@ -40,7 +40,7 @@ interface IState {
busy: boolean; busy: boolean;
err?: string; err?: string;
// If we know it, the nature of the abuse, as specified by MSC3215. // If we know it, the nature of the abuse, as specified by MSC3215.
nature?: EXTENDED_NATURE; nature?: ExtendedNature;
} }
const MODERATED_BY_STATE_EVENT_TYPE = [ const MODERATED_BY_STATE_EVENT_TYPE = [
@ -55,22 +55,22 @@ const MODERATED_BY_STATE_EVENT_TYPE = [
const ABUSE_EVENT_TYPE = "org.matrix.msc3215.abuse.report"; const ABUSE_EVENT_TYPE = "org.matrix.msc3215.abuse.report";
// Standard abuse natures. // Standard abuse natures.
enum NATURE { enum Nature {
DISAGREEMENT = "org.matrix.msc3215.abuse.nature.disagreement", Disagreement = "org.matrix.msc3215.abuse.nature.disagreement",
TOXIC = "org.matrix.msc3215.abuse.nature.toxic", Toxic = "org.matrix.msc3215.abuse.nature.toxic",
ILLEGAL = "org.matrix.msc3215.abuse.nature.illegal", Illegal = "org.matrix.msc3215.abuse.nature.illegal",
SPAM = "org.matrix.msc3215.abuse.nature.spam", Spam = "org.matrix.msc3215.abuse.nature.spam",
OTHER = "org.matrix.msc3215.abuse.nature.other", Other = "org.matrix.msc3215.abuse.nature.other",
} }
enum NON_STANDARD_NATURE { enum NonStandardValue {
// Non-standard abuse nature. // Non-standard abuse nature.
// It should never leave the client - we use it to fallback to // It should never leave the client - we use it to fallback to
// server-wide abuse reporting. // server-wide abuse reporting.
ADMIN = "non-standard.abuse.nature.admin" Admin = "non-standard.abuse.nature.admin"
} }
type EXTENDED_NATURE = NATURE | NON_STANDARD_NATURE; type ExtendedNature = Nature | NonStandardValue;
type Moderation = { type Moderation = {
// The id of the moderation room. // The id of the moderation room.
@ -170,7 +170,7 @@ export default class ReportEventDialog extends React.Component<IProps, IState> {
// The user has clicked on a nature. // The user has clicked on a nature.
private onNatureChosen = (e: React.FormEvent<HTMLInputElement>): void => { private onNatureChosen = (e: React.FormEvent<HTMLInputElement>): void => {
this.setState({ nature: e.currentTarget.value as EXTENDED_NATURE }); this.setState({ nature: e.currentTarget.value as ExtendedNature });
}; };
// The user has clicked "cancel". // The user has clicked "cancel".
@ -187,7 +187,7 @@ export default class ReportEventDialog extends React.Component<IProps, IState> {
// We need a nature. // We need a nature.
// If the nature is `NATURE.OTHER` or `NON_STANDARD_NATURE.ADMIN`, we also need a `reason`. // If the nature is `NATURE.OTHER` or `NON_STANDARD_NATURE.ADMIN`, we also need a `reason`.
if (!this.state.nature || if (!this.state.nature ||
((this.state.nature == NATURE.OTHER || this.state.nature == NON_STANDARD_NATURE.ADMIN) ((this.state.nature == Nature.Other || this.state.nature == NonStandardValue.Admin)
&& !reason) && !reason)
) { ) {
this.setState({ this.setState({
@ -214,8 +214,8 @@ export default class ReportEventDialog extends React.Component<IProps, IState> {
try { try {
const client = MatrixClientPeg.get(); const client = MatrixClientPeg.get();
const ev = this.props.mxEvent; const ev = this.props.mxEvent;
if (this.moderation && this.state.nature != NON_STANDARD_NATURE.ADMIN) { if (this.moderation && this.state.nature != NonStandardValue.Admin) {
const nature: NATURE = this.state.nature; const nature: Nature = this.state.nature;
// Report to moderators through to the dedicated bot, // Report to moderators through to the dedicated bot,
// as configured in the room's state events. // as configured in the room's state events.
@ -274,27 +274,27 @@ export default class ReportEventDialog extends React.Component<IProps, IState> {
const homeServerName = SdkConfig.get()["validated_server_config"].hsName; const homeServerName = SdkConfig.get()["validated_server_config"].hsName;
let subtitle; let subtitle;
switch (this.state.nature) { switch (this.state.nature) {
case NATURE.DISAGREEMENT: case Nature.Disagreement:
subtitle = _t("What this user is writing is wrong.\n" + subtitle = _t("What this user is writing is wrong.\n" +
"This will be reported to the room moderators."); "This will be reported to the room moderators.");
break; break;
case NATURE.TOXIC: case Nature.Toxic:
subtitle = _t("This user is displaying toxic behaviour, " + subtitle = _t("This user is displaying toxic behaviour, " +
"for instance by insulting other users or sharing " + "for instance by insulting other users or sharing " +
" adult-only content in a family-friendly room " + " adult-only content in a family-friendly room " +
" or otherwise violating the rules of this room.\n" + " or otherwise violating the rules of this room.\n" +
"This will be reported to the room moderators."); "This will be reported to the room moderators.");
break; break;
case NATURE.ILLEGAL: case Nature.Illegal:
subtitle = _t("This user is displaying illegal behaviour, " + subtitle = _t("This user is displaying illegal behaviour, " +
"for instance by doxing people or threatening violence.\n" + "for instance by doxing people or threatening violence.\n" +
"This will be reported to the room moderators who may escalate this to legal authorities."); "This will be reported to the room moderators who may escalate this to legal authorities.");
break; break;
case NATURE.SPAM: case Nature.Spam:
subtitle = _t("This user is spamming the room with ads, links to ads or to propaganda.\n" + subtitle = _t("This user is spamming the room with ads, links to ads or to propaganda.\n" +
"This will be reported to the room moderators."); "This will be reported to the room moderators.");
break; break;
case NON_STANDARD_NATURE.ADMIN: case NonStandardValue.Admin:
if (client.isRoomEncrypted(this.props.mxEvent.getRoomId())) { if (client.isRoomEncrypted(this.props.mxEvent.getRoomId())) {
subtitle = _t("This room is dedicated to illegal or toxic content " + subtitle = _t("This room is dedicated to illegal or toxic content " +
"or the moderators fail to moderate illegal or toxic content.\n" + "or the moderators fail to moderate illegal or toxic content.\n" +
@ -308,7 +308,7 @@ export default class ReportEventDialog extends React.Component<IProps, IState> {
{ homeserver: homeServerName }); { homeserver: homeServerName });
} }
break; break;
case NATURE.OTHER: case Nature.Other:
subtitle = _t("Any other reason. Please describe the problem.\n" + subtitle = _t("Any other reason. Please describe the problem.\n" +
"This will be reported to the room moderators."); "This will be reported to the room moderators.");
break; break;
@ -327,48 +327,48 @@ export default class ReportEventDialog extends React.Component<IProps, IState> {
<div> <div>
<StyledRadioButton <StyledRadioButton
name="nature" name="nature"
value = { NATURE.DISAGREEMENT } value={Nature.Disagreement}
checked = { this.state.nature == NATURE.DISAGREEMENT } checked={this.state.nature == Nature.Disagreement}
onChange={this.onNatureChosen} onChange={this.onNatureChosen}
> >
{ _t('Disagree') } { _t('Disagree') }
</StyledRadioButton> </StyledRadioButton>
<StyledRadioButton <StyledRadioButton
name="nature" name="nature"
value = { NATURE.TOXIC } value={Nature.Toxic}
checked = { this.state.nature == NATURE.TOXIC } checked={this.state.nature == Nature.Toxic}
onChange={this.onNatureChosen} onChange={this.onNatureChosen}
> >
{ _t('Toxic Behaviour') } { _t('Toxic Behaviour') }
</StyledRadioButton> </StyledRadioButton>
<StyledRadioButton <StyledRadioButton
name="nature" name="nature"
value = { NATURE.ILLEGAL } value={Nature.Illegal}
checked = { this.state.nature == NATURE.ILLEGAL } checked={this.state.nature == Nature.Illegal}
onChange={this.onNatureChosen} onChange={this.onNatureChosen}
> >
{ _t('Illegal Content') } { _t('Illegal Content') }
</StyledRadioButton> </StyledRadioButton>
<StyledRadioButton <StyledRadioButton
name="nature" name="nature"
value = { NATURE.SPAM } value={Nature.Spam}
checked = { this.state.nature == NATURE.SPAM } checked={this.state.nature == Nature.Spam}
onChange={this.onNatureChosen} onChange={this.onNatureChosen}
> >
{ _t('Spam or propaganda') } { _t('Spam or propaganda') }
</StyledRadioButton> </StyledRadioButton>
<StyledRadioButton <StyledRadioButton
name="nature" name="nature"
value = { NON_STANDARD_NATURE.ADMIN } value={NonStandardValue.Admin}
checked = { this.state.nature == NON_STANDARD_NATURE.ADMIN } checked={this.state.nature == NonStandardValue.Admin}
onChange={this.onNatureChosen} onChange={this.onNatureChosen}
> >
{ _t('Report the entire room') } { _t('Report the entire room') }
</StyledRadioButton> </StyledRadioButton>
<StyledRadioButton <StyledRadioButton
name="nature" name="nature"
value = { NATURE.OTHER } value={Nature.Other}
checked = { this.state.nature == NATURE.OTHER } checked={this.state.nature == Nature.Other}
onChange={this.onNatureChosen} onChange={this.onNatureChosen}
> >
{ _t('Other') } { _t('Other') }

View file

@ -81,7 +81,7 @@ export default class UserSettingsDialog extends React.Component<IProps, IState>
this.setState({ mjolnirEnabled: newValue }); this.setState({ mjolnirEnabled: newValue });
}; };
_getTabs() { private getTabs() {
const tabs = []; const tabs = [];
tabs.push(new Tab( tabs.push(new Tab(
@ -170,7 +170,7 @@ export default class UserSettingsDialog extends React.Component<IProps, IState>
title={_t("Settings")} title={_t("Settings")}
> >
<div className='mx_SettingsDialog_content'> <div className='mx_SettingsDialog_content'>
<TabbedView tabs={this._getTabs()} initialTabId={this.props.initialTabId} /> <TabbedView tabs={this.getTabs()} initialTabId={this.props.initialTabId} />
</div> </div>
</BaseDialog> </BaseDialog>
); );

View file

@ -453,13 +453,13 @@ export default class AppTile extends React.Component {
title={_t('Popout widget')} title={_t('Popout widget')}
onClick={this._onPopoutWidgetClick} onClick={this._onPopoutWidgetClick}
/> } /> }
{ <ContextMenuButton <ContextMenuButton
className="mx_AppTileMenuBar_iconButton mx_AppTileMenuBar_iconButton_menu" className="mx_AppTileMenuBar_iconButton mx_AppTileMenuBar_iconButton_menu"
label={_t("Options")} label={_t("Options")}
isExpanded={this.state.menuDisplayed} isExpanded={this.state.menuDisplayed}
inputRef={this._contextMenuButton} inputRef={this._contextMenuButton}
onClick={this._onContextMenuClick} onClick={this._onContextMenuClick}
/> } />
</span> </span>
</div> } </div> }
{ appTileBody } { appTileBody }

View file

@ -83,7 +83,7 @@ export default class PersistedElement extends React.Component {
// for this, so we bodge it by listening for document resize and // for this, so we bodge it by listening for document resize and
// the timeline_resize action. // the timeline_resize action.
window.addEventListener('resize', this._repositionChild); window.addEventListener('resize', this._repositionChild);
this._dispatcherRef = dis.register(this._onAction); this.dispatcherRef = dis.register(this._onAction);
} }
/** /**

View file

@ -45,7 +45,7 @@ export default class SpellCheckLanguagesDropdown extends React.Component<SpellCh
SpellCheckLanguagesDropdownIState> { SpellCheckLanguagesDropdownIState> {
constructor(props) { constructor(props) {
super(props); super(props);
this._onSearchChange = this._onSearchChange.bind(this); this.onSearchChange = this.onSearchChange.bind(this);
this.state = { this.state = {
searchQuery: '', searchQuery: '',
@ -76,10 +76,8 @@ export default class SpellCheckLanguagesDropdown extends React.Component<SpellCh
} }
} }
_onSearchChange(search) { private onSearchChange(searchQuery: string) {
this.setState({ this.setState({ searchQuery });
searchQuery: search,
});
} }
render() { render() {
@ -117,7 +115,7 @@ export default class SpellCheckLanguagesDropdown extends React.Component<SpellCh
id="mx_LanguageDropdown" id="mx_LanguageDropdown"
className={this.props.className} className={this.props.className}
onOptionChange={this.props.onOptionChange} onOptionChange={this.props.onOptionChange}
onSearchChange={this._onSearchChange} onSearchChange={this.onSearchChange}
searchEnabled={true} searchEnabled={true}
value={value} value={value}
label={_t("Language Dropdown")}> label={_t("Language Dropdown")}>

View file

@ -56,7 +56,7 @@ export default class TextWithTooltip extends React.Component {
{...tooltipProps} {...tooltipProps}
label={tooltip} label={tooltip}
tooltipClassName={tooltipClass} tooltipClassName={tooltipClass}
className={"mx_TextWithTooltip_tooltip"} className="mx_TextWithTooltip_tooltip"
/> } /> }
</span> </span>
); );

View file

@ -304,13 +304,6 @@ export default class MImageBody extends React.Component<IProps, IState> {
this.downloadImage(); this.downloadImage();
this.setState({ showImage: true }); this.setState({ showImage: true });
} }
this._afterComponentDidMount();
}
// To be overridden by subclasses (e.g. MStickerBody) for further
// initialisation after componentDidMount
_afterComponentDidMount() {
} }
componentWillUnmount() { componentWillUnmount() {

View file

@ -385,7 +385,7 @@ const UserOptionsSection: React.FC<{
} }
insertPillButton = ( insertPillButton = (
<AccessibleButton onClick={onInsertPillButton} className={"mx_UserInfo_field"}> <AccessibleButton onClick={onInsertPillButton} className="mx_UserInfo_field">
{ _t('Mention') } { _t('Mention') }
</AccessibleButton> </AccessibleButton>
); );

View file

@ -106,7 +106,7 @@ export default class RelatedGroupSettings extends React.Component {
<EditableItemList <EditableItemList
id="relatedGroups" id="relatedGroups"
items={this.state.newGroupsList} items={this.state.newGroupsList}
className={"mx_RelatedGroupSettings"} className="mx_RelatedGroupSettings"
newItem={this.state.newGroupId} newItem={this.state.newGroupId}
canRemove={this.props.canSetRelatedGroups} canRemove={this.props.canSetRelatedGroups}
canEdit={this.props.canSetRelatedGroups} canEdit={this.props.canSetRelatedGroups}

View file

@ -430,7 +430,7 @@ export default class EventTile extends React.Component<IProps, IState> {
} }
// TODO: [REACT-WARNING] Move into constructor // TODO: [REACT-WARNING] Move into constructor
// eslint-disable-next-line camelcase // eslint-disable-next-line
UNSAFE_componentWillMount() { UNSAFE_componentWillMount() {
this.verifyEvent(this.props.mxEvent); this.verifyEvent(this.props.mxEvent);
} }
@ -452,7 +452,7 @@ export default class EventTile extends React.Component<IProps, IState> {
} }
// TODO: [REACT-WARNING] Replace with appropriate lifecycle event // TODO: [REACT-WARNING] Replace with appropriate lifecycle event
// eslint-disable-next-line camelcase // eslint-disable-next-line
UNSAFE_componentWillReceiveProps(nextProps) { UNSAFE_componentWillReceiveProps(nextProps) {
// re-check the sender verification as outgoing events progress through // re-check the sender verification as outgoing events progress through
// the send process. // the send process.

View file

@ -93,7 +93,7 @@ export default class MemberList extends React.Component<IProps, IState> {
this.showPresence = enablePresenceByHsUrl?.[hsUrl] ?? true; this.showPresence = enablePresenceByHsUrl?.[hsUrl] ?? true;
} }
// eslint-disable-next-line camelcase // eslint-disable-next-line
UNSAFE_componentWillMount() { UNSAFE_componentWillMount() {
const cli = MatrixClientPeg.get(); const cli = MatrixClientPeg.get();
this.mounted = true; this.mounted = true;

View file

@ -441,7 +441,7 @@ export default class SendMessageComposer extends React.Component<IProps> {
} }
// TODO: [REACT-WARNING] Move this to constructor // TODO: [REACT-WARNING] Move this to constructor
UNSAFE_componentWillMount() { // eslint-disable-line camelcase UNSAFE_componentWillMount() { // eslint-disable-line
const partCreator = new CommandPartCreator(this.props.room, this.context); const partCreator = new CommandPartCreator(this.props.room, this.context);
const parts = this.restoreStoredEditorState(partCreator) || []; const parts = this.restoreStoredEditorState(partCreator) || [];
this.model = new EditorModel(parts, partCreator); this.model = new EditorModel(parts, partCreator);

View file

@ -64,8 +64,8 @@ export default class WhoIsTypingTile extends React.Component<IProps, IState> {
} }
componentDidUpdate(_, prevState) { componentDidUpdate(_, prevState) {
const wasVisible = this._isVisible(prevState); const wasVisible = WhoIsTypingTile.isVisible(prevState);
const isVisible = this._isVisible(this.state); const isVisible = WhoIsTypingTile.isVisible(this.state);
if (this.props.onShown && !wasVisible && isVisible) { if (this.props.onShown && !wasVisible && isVisible) {
this.props.onShown(); this.props.onShown();
} else if (this.props.onHidden && wasVisible && !isVisible) { } else if (this.props.onHidden && wasVisible && !isVisible) {
@ -83,12 +83,12 @@ export default class WhoIsTypingTile extends React.Component<IProps, IState> {
Object.values(this.state.delayedStopTypingTimers).forEach((t) => (t as Timer).abort()); Object.values(this.state.delayedStopTypingTimers).forEach((t) => (t as Timer).abort());
} }
private _isVisible(state: IState): boolean { private static isVisible(state: IState): boolean {
return state.usersTyping.length !== 0 || Object.keys(state.delayedStopTypingTimers).length !== 0; return state.usersTyping.length !== 0 || Object.keys(state.delayedStopTypingTimers).length !== 0;
} }
public isVisible = (): boolean => { public isVisible = (): boolean => {
return this._isVisible(this.state); return WhoIsTypingTile.isVisible(this.state);
}; };
private onRoomTimeline = (event: MatrixEvent, room: Room): void => { private onRoomTimeline = (event: MatrixEvent, room: Room): void => {

View file

@ -35,7 +35,7 @@ interface SpellCheckLanguagesIState {
} }
export class ExistingSpellCheckLanguage extends React.Component<ExistingSpellCheckLanguageIProps> { export class ExistingSpellCheckLanguage extends React.Component<ExistingSpellCheckLanguageIProps> {
_onRemove = (e) => { private onRemove = (e) => {
e.stopPropagation(); e.stopPropagation();
e.preventDefault(); e.preventDefault();
@ -46,7 +46,7 @@ export class ExistingSpellCheckLanguage extends React.Component<ExistingSpellChe
return ( return (
<div className="mx_ExistingSpellCheckLanguage"> <div className="mx_ExistingSpellCheckLanguage">
<span className="mx_ExistingSpellCheckLanguage_language">{ this.props.language }</span> <span className="mx_ExistingSpellCheckLanguage_language">{ this.props.language }</span>
<AccessibleButton onClick={this._onRemove} kind="danger_sm"> <AccessibleButton onClick={this.onRemove} kind="danger_sm">
{ _t("Remove") } { _t("Remove") }
</AccessibleButton> </AccessibleButton>
</div> </div>
@ -63,12 +63,12 @@ export default class SpellCheckLanguages extends React.Component<SpellCheckLangu
}; };
} }
_onRemoved = (language) => { private onRemoved = (language: string) => {
const languages = this.props.languages.filter((e) => e !== language); const languages = this.props.languages.filter((e) => e !== language);
this.props.onLanguagesChange(languages); this.props.onLanguagesChange(languages);
}; };
_onAddClick = (e) => { private onAddClick = (e) => {
e.stopPropagation(); e.stopPropagation();
e.preventDefault(); e.preventDefault();
@ -81,18 +81,18 @@ export default class SpellCheckLanguages extends React.Component<SpellCheckLangu
this.props.onLanguagesChange(this.props.languages); this.props.onLanguagesChange(this.props.languages);
}; };
_onNewLanguageChange = (language: string) => { private onNewLanguageChange = (language: string) => {
if (this.state.newLanguage === language) return; if (this.state.newLanguage === language) return;
this.setState({ newLanguage: language }); this.setState({ newLanguage: language });
}; };
render() { render() {
const existingSpellCheckLanguages = this.props.languages.map((e) => { const existingSpellCheckLanguages = this.props.languages.map((e) => {
return <ExistingSpellCheckLanguage language={e} onRemoved={this._onRemoved} key={e} />; return <ExistingSpellCheckLanguage language={e} onRemoved={this.onRemoved} key={e} />;
}); });
const addButton = ( const addButton = (
<AccessibleButton onClick={this._onAddClick} kind="primary"> <AccessibleButton onClick={this.onAddClick} kind="primary">
{ _t("Add") } { _t("Add") }
</AccessibleButton> </AccessibleButton>
); );
@ -100,11 +100,11 @@ export default class SpellCheckLanguages extends React.Component<SpellCheckLangu
return ( return (
<div className="mx_SpellCheckLanguages"> <div className="mx_SpellCheckLanguages">
{ existingSpellCheckLanguages } { existingSpellCheckLanguages }
<form onSubmit={this._onAddClick} noValidate={true}> <form onSubmit={this.onAddClick} noValidate={true}>
<SpellCheckLanguagesDropdown <SpellCheckLanguagesDropdown
className="mx_GeneralUserSettingsTab_spellCheckLanguageInput" className="mx_GeneralUserSettingsTab_spellCheckLanguageInput"
value={this.state.newLanguage} value={this.state.newLanguage}
onOptionChange={this._onNewLanguageChange} /> onOptionChange={this.onNewLanguageChange} />
{ addButton } { addButton }
</form> </form>
</div> </div>

View file

@ -78,7 +78,7 @@ export default class SecurityRoomSettingsTab extends React.Component<IProps, ISt
} }
// TODO: [REACT-WARNING] Move this to constructor // TODO: [REACT-WARNING] Move this to constructor
async UNSAFE_componentWillMount() { // eslint-disable-line camelcase async UNSAFE_componentWillMount() { // eslint-disable-line
MatrixClientPeg.get().on("RoomState.events", this.onStateEvent); MatrixClientPeg.get().on("RoomState.events", this.onStateEvent);
const room = MatrixClientPeg.get().getRoom(this.props.roomId); const room = MatrixClientPeg.get().getRoom(this.props.roomId);

View file

@ -60,14 +60,14 @@ export default class VerificationRequestToast extends React.PureComponent<IProps
this.setState({ counter }); this.setState({ counter });
}, 1000); }, 1000);
} }
request.on("change", this._checkRequestIsPending); request.on("change", this.checkRequestIsPending);
// We should probably have a separate class managing the active verification toasts, // We should probably have a separate class managing the active verification toasts,
// rather than monitoring this in the toast component itself, since we'll get problems // rather than monitoring this in the toast component itself, since we'll get problems
// like the toasdt not going away when the verification is cancelled unless it's the // like the toasdt not going away when the verification is cancelled unless it's the
// one on the top (ie. the one that's mounted). // one on the top (ie. the one that's mounted).
// As a quick & dirty fix, check the toast is still relevant when it mounts (this prevents // As a quick & dirty fix, check the toast is still relevant when it mounts (this prevents
// a toast hanging around after logging in if you did a verification as part of login). // a toast hanging around after logging in if you did a verification as part of login).
this._checkRequestIsPending(); this.checkRequestIsPending();
if (request.isSelfVerification) { if (request.isSelfVerification) {
const cli = MatrixClientPeg.get(); const cli = MatrixClientPeg.get();
@ -83,10 +83,10 @@ export default class VerificationRequestToast extends React.PureComponent<IProps
componentWillUnmount() { componentWillUnmount() {
clearInterval(this.intervalHandle); clearInterval(this.intervalHandle);
const { request } = this.props; const { request } = this.props;
request.off("change", this._checkRequestIsPending); request.off("change", this.checkRequestIsPending);
} }
_checkRequestIsPending = () => { private checkRequestIsPending = () => {
const { request } = this.props; const { request } = this.props;
if (!request.canAccept) { if (!request.canAccept) {
ToastStore.sharedInstance().dismissToast(this.props.toastKey); ToastStore.sharedInstance().dismissToast(this.props.toastKey);

View file

@ -513,7 +513,9 @@ export default class CallView extends React.Component<IProps, IState> {
transferee: transfereeName, transferee: transfereeName,
}, },
{ {
a: sub => <AccessibleButton kind="link" onClick={this.onTransferClick}>{sub}</AccessibleButton>, a: sub => <AccessibleButton kind="link" onClick={this.onTransferClick}>
{ sub }
</AccessibleButton>,
}, },
) } ) }
</div>; </div>;

View file

@ -144,7 +144,7 @@ export default class IncomingCallBox extends React.Component<IProps, IState> {
</div> </div>
<div className="mx_IncomingCallBox_buttons"> <div className="mx_IncomingCallBox_buttons">
<AccessibleButton <AccessibleButton
className={"mx_IncomingCallBox_decline"} className="mx_IncomingCallBox_decline"
onClick={this.onRejectClick} onClick={this.onRejectClick}
kind="danger" kind="danger"
> >
@ -152,7 +152,7 @@ export default class IncomingCallBox extends React.Component<IProps, IState> {
</AccessibleButton> </AccessibleButton>
<div className="mx_IncomingCallBox_spacer" /> <div className="mx_IncomingCallBox_spacer" />
<AccessibleButton <AccessibleButton
className={"mx_IncomingCallBox_accept"} className="mx_IncomingCallBox_accept"
onClick={this.onAnswerClick} onClick={this.onAnswerClick}
kind="primary" kind="primary"
> >

View file

@ -17,6 +17,7 @@ limitations under the License.
import { MatrixClient } from "matrix-js-sdk/src/client"; import { MatrixClient } from "matrix-js-sdk/src/client";
import { Room } from "matrix-js-sdk/src/models/room"; import { Room } from "matrix-js-sdk/src/models/room";
import { RoomMember } from "matrix-js-sdk/src/models/room-member";
import { EventType } from "matrix-js-sdk/src/@types/event"; import { EventType } from "matrix-js-sdk/src/@types/event";
import { MatrixClientPeg } from './MatrixClientPeg'; import { MatrixClientPeg } from './MatrixClientPeg';
@ -247,11 +248,11 @@ export function findDMForUser(client: MatrixClient, userId: string): Room {
* NOTE: this assumes you've just created the room and there's not been an opportunity * NOTE: this assumes you've just created the room and there's not been an opportunity
* for other code to run, so we shouldn't miss RoomState.newMember when it comes by. * for other code to run, so we shouldn't miss RoomState.newMember when it comes by.
*/ */
export async function _waitForMember(client: MatrixClient, roomId: string, userId: string, opts = { timeout: 1500 }) { export async function waitForMember(client: MatrixClient, roomId: string, userId: string, opts = { timeout: 1500 }) {
const { timeout } = opts; const { timeout } = opts;
let handler; let handler;
return new Promise((resolve) => { return new Promise((resolve) => {
handler = function(_event, _roomstate, member) { handler = function(_, __, member: RoomMember) { // eslint-disable-line @typescript-eslint/naming-convention
if (member.userId !== userId) return; if (member.userId !== userId) return;
if (member.roomId !== roomId) return; if (member.roomId !== roomId) return;
resolve(true); resolve(true);
@ -324,7 +325,7 @@ export async function ensureDMExists(client: MatrixClient, userId: string): Prom
} }
roomId = await createRoom({ encryption, dmUserId: userId, spinner: false, andView: false }); roomId = await createRoom({ encryption, dmUserId: userId, spinner: false, andView: false });
await _waitForMember(client, roomId, userId); await waitForMember(client, roomId, userId);
} }
return roomId; return roomId;
} }

View file

@ -274,7 +274,7 @@ abstract class PillPart extends BasePart implements IPillPart {
} }
// helper method for subclasses // helper method for subclasses
_setAvatarVars(node: HTMLElement, avatarUrl: string, initialLetter: string) { protected setAvatarVars(node: HTMLElement, avatarUrl: string, initialLetter: string) {
const avatarBackground = `url('${avatarUrl}')`; const avatarBackground = `url('${avatarUrl}')`;
const avatarLetter = `'${initialLetter}'`; const avatarLetter = `'${initialLetter}'`;
// check if the value is changing, // check if the value is changing,
@ -354,7 +354,7 @@ class RoomPillPart extends PillPart {
initialLetter = Avatar.getInitialLetter(this.room ? this.room.name : this.resourceId); initialLetter = Avatar.getInitialLetter(this.room ? this.room.name : this.resourceId);
avatarUrl = Avatar.defaultAvatarUrlForString(this.room ? this.room.roomId : this.resourceId); avatarUrl = Avatar.defaultAvatarUrlForString(this.room ? this.room.roomId : this.resourceId);
} }
this._setAvatarVars(node, avatarUrl, initialLetter); this.setAvatarVars(node, avatarUrl, initialLetter);
} }
get type(): IPillPart["type"] { get type(): IPillPart["type"] {
@ -399,7 +399,7 @@ class UserPillPart extends PillPart {
if (avatarUrl === defaultAvatarUrl) { if (avatarUrl === defaultAvatarUrl) {
initialLetter = Avatar.getInitialLetter(name); initialLetter = Avatar.getInitialLetter(name);
} }
this._setAvatarVars(node, avatarUrl, initialLetter); this.setAvatarVars(node, avatarUrl, initialLetter);
} }
get type(): IPillPart["type"] { get type(): IPillPart["type"] {

View file

@ -67,7 +67,7 @@ export function getUserLanguage(): string {
// Function which only purpose is to mark that a string is translatable // Function which only purpose is to mark that a string is translatable
// Does not actually do anything. It's helpful for automatic extraction of translatable strings // Does not actually do anything. It's helpful for automatic extraction of translatable strings
export function _td(s: string): string { export function _td(s: string): string { // eslint-disable-line @typescript-eslint/naming-convention
return s; return s;
} }
@ -132,6 +132,8 @@ export type TranslatedString = string | React.ReactNode;
* *
* @return a React <span> component if any non-strings were used in substitutions, otherwise a string * @return a React <span> component if any non-strings were used in substitutions, otherwise a string
*/ */
// eslint-next-line @typescript-eslint/naming-convention
// eslint-nexline @typescript-eslint/naming-convention
export function _t(text: string, variables?: IVariables): string; export function _t(text: string, variables?: IVariables): string;
export function _t(text: string, variables: IVariables, tags: Tags): React.ReactNode; export function _t(text: string, variables: IVariables, tags: Tags): React.ReactNode;
export function _t(text: string, variables?: IVariables, tags?: Tags): TranslatedString { export function _t(text: string, variables?: IVariables, tags?: Tags): TranslatedString {

View file

@ -14,6 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import { MatrixEvent } from "matrix-js-sdk/src/models/event";
import { MatrixClientPeg } from "../MatrixClientPeg"; import { MatrixClientPeg } from "../MatrixClientPeg";
import { ALL_RULE_TYPES, BanList } from "./BanList"; import { ALL_RULE_TYPES, BanList } from "./BanList";
import SettingsStore from "../settings/SettingsStore"; import SettingsStore from "../settings/SettingsStore";
@ -21,19 +22,17 @@ import { _t } from "../languageHandler";
import dis from "../dispatcher/dispatcher"; import dis from "../dispatcher/dispatcher";
import { SettingLevel } from "../settings/SettingLevel"; import { SettingLevel } from "../settings/SettingLevel";
import { Preset } from "matrix-js-sdk/src/@types/partials"; import { Preset } from "matrix-js-sdk/src/@types/partials";
import { ActionPayload } from "../dispatcher/payloads";
// TODO: Move this and related files to the js-sdk or something once finalized. // TODO: Move this and related files to the js-sdk or something once finalized.
export class Mjolnir { export class Mjolnir {
static _instance: Mjolnir = null; private static instance: Mjolnir = null;
_lists: BanList[] = []; private _lists: BanList[] = []; // eslint-disable-line @typescript-eslint/naming-convention
_roomIds: string[] = []; private _roomIds: string[] = []; // eslint-disable-line @typescript-eslint/naming-convention
_mjolnirWatchRef = null; private mjolnirWatchRef: string = null;
_dispatcherRef = null; private dispatcherRef: string = null;
constructor() {
}
get roomIds(): string[] { get roomIds(): string[] {
return this._roomIds; return this._roomIds;
@ -44,16 +43,16 @@ export class Mjolnir {
} }
start() { start() {
this._mjolnirWatchRef = SettingsStore.watchSetting("mjolnirRooms", null, this._onListsChanged.bind(this)); this.mjolnirWatchRef = SettingsStore.watchSetting("mjolnirRooms", null, this.onListsChanged.bind(this));
this._dispatcherRef = dis.register(this._onAction); this.dispatcherRef = dis.register(this.onAction);
dis.dispatch({ dis.dispatch({
action: 'do_after_sync_prepared', action: 'do_after_sync_prepared',
deferred_action: { action: 'setup_mjolnir' }, deferred_action: { action: 'setup_mjolnir' },
}); });
} }
_onAction = (payload) => { private onAction = (payload: ActionPayload) => {
if (payload['action'] === 'setup_mjolnir') { if (payload['action'] === 'setup_mjolnir') {
console.log("Setting up Mjolnir: after sync"); console.log("Setting up Mjolnir: after sync");
this.setup(); this.setup();
@ -62,23 +61,23 @@ export class Mjolnir {
setup() { setup() {
if (!MatrixClientPeg.get()) return; if (!MatrixClientPeg.get()) return;
this._updateLists(SettingsStore.getValue("mjolnirRooms")); this.updateLists(SettingsStore.getValue("mjolnirRooms"));
MatrixClientPeg.get().on("RoomState.events", this._onEvent); MatrixClientPeg.get().on("RoomState.events", this.onEvent);
} }
stop() { stop() {
if (this._mjolnirWatchRef) { if (this.mjolnirWatchRef) {
SettingsStore.unwatchSetting(this._mjolnirWatchRef); SettingsStore.unwatchSetting(this.mjolnirWatchRef);
this._mjolnirWatchRef = null; this.mjolnirWatchRef = null;
} }
if (this._dispatcherRef) { if (this.dispatcherRef) {
dis.unregister(this._dispatcherRef); dis.unregister(this.dispatcherRef);
this._dispatcherRef = null; this.dispatcherRef = null;
} }
if (!MatrixClientPeg.get()) return; if (!MatrixClientPeg.get()) return;
MatrixClientPeg.get().removeListener("RoomState.events", this._onEvent); MatrixClientPeg.get().removeListener("RoomState.events", this.onEvent);
} }
async getOrCreatePersonalList(): Promise<BanList> { async getOrCreatePersonalList(): Promise<BanList> {
@ -132,20 +131,20 @@ export class Mjolnir {
this._lists = this._lists.filter(b => b.roomId !== roomId); this._lists = this._lists.filter(b => b.roomId !== roomId);
} }
_onEvent = (event) => { private onEvent = (event: MatrixEvent) => {
if (!MatrixClientPeg.get()) return; if (!MatrixClientPeg.get()) return;
if (!this._roomIds.includes(event.getRoomId())) return; if (!this._roomIds.includes(event.getRoomId())) return;
if (!ALL_RULE_TYPES.includes(event.getType())) return; if (!ALL_RULE_TYPES.includes(event.getType())) return;
this._updateLists(this._roomIds); this.updateLists(this._roomIds);
}; };
_onListsChanged(settingName, roomId, atLevel, newValue) { private onListsChanged(settingName: string, roomId: string, atLevel: SettingLevel, newValue: string[]) {
// We know that ban lists are only recorded at one level so we don't need to re-eval them // We know that ban lists are only recorded at one level so we don't need to re-eval them
this._updateLists(newValue); this.updateLists(newValue);
} }
_updateLists(listRoomIds: string[]) { private updateLists(listRoomIds: string[]) {
if (!MatrixClientPeg.get()) return; if (!MatrixClientPeg.get()) return;
console.log("Updating Mjolnir ban lists to: " + listRoomIds); console.log("Updating Mjolnir ban lists to: " + listRoomIds);
@ -182,10 +181,10 @@ export class Mjolnir {
} }
static sharedInstance(): Mjolnir { static sharedInstance(): Mjolnir {
if (!Mjolnir._instance) { if (!Mjolnir.instance) {
Mjolnir._instance = new Mjolnir(); Mjolnir.instance = new Mjolnir();
} }
return Mjolnir._instance; return Mjolnir.instance;
} }
} }

View file

@ -203,7 +203,7 @@ export default async function sendBugReport(bugReportEndpoint: string, opts: IOp
const body = await collectBugReport(opts); const body = await collectBugReport(opts);
progressCallback(_t("Uploading logs")); progressCallback(_t("Uploading logs"));
await _submitReport(bugReportEndpoint, body, progressCallback); await submitReport(bugReportEndpoint, body, progressCallback);
} }
/** /**
@ -289,10 +289,10 @@ export async function submitFeedback(
body.append(k, extraData[k]); body.append(k, extraData[k]);
} }
await _submitReport(SdkConfig.get().bug_report_endpoint_url, body, () => {}); await submitReport(SdkConfig.get().bug_report_endpoint_url, body, () => {});
} }
function _submitReport(endpoint: string, body: FormData, progressCallback: (string) => void) { function submitReport(endpoint: string, body: FormData, progressCallback: (str: string) => void) {
return new Promise<void>((resolve, reject) => { return new Promise<void>((resolve, reject) => {
const req = new XMLHttpRequest(); const req = new XMLHttpRequest();
req.open("POST", endpoint); req.open("POST", endpoint);

View file

@ -49,7 +49,7 @@ class GroupFilterOrderStore extends Store {
this.__emitChange(); this.__emitChange();
} }
__onDispatch(payload) { __onDispatch(payload) { // eslint-disable-line @typescript-eslint/naming-convention
switch (payload.action) { switch (payload.action) {
// Initialise state after initial sync // Initialise state after initial sync
case 'view_room': { case 'view_room': {

View file

@ -44,7 +44,7 @@ class LifecycleStore extends Store<ActionPayload> {
this.__emitChange(); this.__emitChange();
} }
protected __onDispatch(payload: ActionPayload) { protected __onDispatch(payload: ActionPayload) { // eslint-disable-line @typescript-eslint/naming-convention
switch (payload.action) { switch (payload.action) {
case 'do_after_sync_prepared': case 'do_after_sync_prepared':
this.setState({ this.setState({

View file

@ -144,7 +144,7 @@ export default class RightPanelStore extends Store<ActionPayload> {
this.__emitChange(); this.__emitChange();
} }
__onDispatch(payload: ActionPayload) { __onDispatch(payload: ActionPayload) { // eslint-disable-line @typescript-eslint/naming-convention
switch (payload.action) { switch (payload.action) {
case 'view_room': case 'view_room':
if (payload.room_id === this.lastRoomId) break; // skip this transition, probably a permalink if (payload.room_id === this.lastRoomId) break; // skip this transition, probably a permalink

View file

@ -96,7 +96,7 @@ class RoomViewStore extends Store<ActionPayload> {
this.__emitChange(); this.__emitChange();
} }
__onDispatch(payload) { __onDispatch(payload) { // eslint-disable-line @typescript-eslint/naming-convention
switch (payload.action) { switch (payload.action) {
// view_room: // view_room:
// - room_alias: '#somealias:matrix.org' // - room_alias: '#somealias:matrix.org'

View file

@ -63,7 +63,7 @@ const PREVIEWS = {
const MAX_EVENTS_BACKWARDS = 50; const MAX_EVENTS_BACKWARDS = 50;
// type merging ftw // type merging ftw
type TAG_ANY = "im.vector.any"; type TAG_ANY = "im.vector.any"; // eslint-disable-line @typescript-eslint/naming-convention
const TAG_ANY: TAG_ANY = "im.vector.any"; const TAG_ANY: TAG_ANY = "im.vector.any";
interface IState { interface IState {

View file

@ -20,7 +20,7 @@ import { EventType, MsgType } from "matrix-js-sdk/src/@types/event";
import { ElementWidgetCapabilities } from "../stores/widgets/ElementWidgetCapabilities"; import { ElementWidgetCapabilities } from "../stores/widgets/ElementWidgetCapabilities";
import React from "react"; import React from "react";
type GENERIC_WIDGET_KIND = "generic"; type GENERIC_WIDGET_KIND = "generic"; // eslint-disable-line @typescript-eslint/naming-convention
const GENERIC_WIDGET_KIND: GENERIC_WIDGET_KIND = "generic"; const GENERIC_WIDGET_KIND: GENERIC_WIDGET_KIND = "generic";
interface ISendRecvStaticCapText { interface ISendRecvStaticCapText {

View file

@ -1,5 +1,5 @@
import './skinned-sdk'; // Must be first for skinning to work import './skinned-sdk'; // Must be first for skinning to work
import { _waitForMember, canEncryptToAllUsers } from '../src/createRoom'; import { waitForMember, canEncryptToAllUsers } from '../src/createRoom';
import { EventEmitter } from 'events'; import { EventEmitter } from 'events';
/* Shorter timeout, we've got tests to run */ /* Shorter timeout, we've got tests to run */
@ -13,7 +13,7 @@ describe("waitForMember", () => {
}); });
it("resolves with false if the timeout is reached", (done) => { it("resolves with false if the timeout is reached", (done) => {
_waitForMember(client, "", "", { timeout: 0 }).then((r) => { waitForMember(client, "", "", { timeout: 0 }).then((r) => {
expect(r).toBe(false); expect(r).toBe(false);
done(); done();
}); });
@ -22,7 +22,7 @@ describe("waitForMember", () => {
it("resolves with false if the timeout is reached, even if other RoomState.newMember events fire", (done) => { it("resolves with false if the timeout is reached, even if other RoomState.newMember events fire", (done) => {
const roomId = "!roomId:domain"; const roomId = "!roomId:domain";
const userId = "@clientId:domain"; const userId = "@clientId:domain";
_waitForMember(client, roomId, userId, { timeout }).then((r) => { waitForMember(client, roomId, userId, { timeout }).then((r) => {
expect(r).toBe(false); expect(r).toBe(false);
done(); done();
}); });
@ -32,7 +32,7 @@ describe("waitForMember", () => {
it("resolves with true if RoomState.newMember fires", (done) => { it("resolves with true if RoomState.newMember fires", (done) => {
const roomId = "!roomId:domain"; const roomId = "!roomId:domain";
const userId = "@clientId:domain"; const userId = "@clientId:domain";
_waitForMember(client, roomId, userId, { timeout }).then((r) => { waitForMember(client, roomId, userId, { timeout }).then((r) => {
expect(r).toBe(true); expect(r).toBe(true);
expect(client.listeners("RoomState.newMember").length).toBe(0); expect(client.listeners("RoomState.newMember").length).toBe(0);
done(); done();