Tweak private / underscores for fields and methods

This commit is contained in:
J. Ryan Stinnett 2021-04-26 14:02:53 +01:00
parent f34489e2df
commit b8a915bb76
17 changed files with 324 additions and 325 deletions

View File

@ -51,7 +51,7 @@ export default class ScalarAuthClient {
this.isDefaultManager = apiUrl === configApiUrl && configUiUrl === uiUrl; this.isDefaultManager = apiUrl === configApiUrl && configUiUrl === uiUrl;
} }
_writeTokenToStore() { private writeTokenToStore() {
window.localStorage.setItem("mx_scalar_token_at_" + this.apiUrl, this.scalarToken); window.localStorage.setItem("mx_scalar_token_at_" + this.apiUrl, this.scalarToken);
if (this.isDefaultManager) { if (this.isDefaultManager) {
// We remove the old token from storage to migrate upwards. This is safe // We remove the old token from storage to migrate upwards. This is safe
@ -61,7 +61,7 @@ export default class ScalarAuthClient {
} }
} }
_readTokenFromStore() { private readTokenFromStore() {
let token = window.localStorage.getItem("mx_scalar_token_at_" + this.apiUrl); let token = window.localStorage.getItem("mx_scalar_token_at_" + this.apiUrl);
if (!token && this.isDefaultManager) { if (!token && this.isDefaultManager) {
token = window.localStorage.getItem("mx_scalar_token"); token = window.localStorage.getItem("mx_scalar_token");
@ -69,9 +69,9 @@ export default class ScalarAuthClient {
return token; return token;
} }
_readToken() { private readToken() {
if (this.scalarToken) return this.scalarToken; if (this.scalarToken) return this.scalarToken;
return this._readTokenFromStore(); return this.readTokenFromStore();
} }
setTermsInteractionCallback(callback) { setTermsInteractionCallback(callback) {
@ -90,12 +90,12 @@ export default class ScalarAuthClient {
// Returns a promise that resolves to a scalar_token string // Returns a promise that resolves to a scalar_token string
getScalarToken() { getScalarToken() {
const token = this._readToken(); const token = this.readToken();
if (!token) { if (!token) {
return this.registerForToken(); return this.registerForToken();
} else { } else {
return this._checkToken(token).catch((e) => { return this.checkToken(token).catch((e) => {
if (e instanceof TermsNotSignedError) { if (e instanceof TermsNotSignedError) {
// retrying won't help this // retrying won't help this
throw e; throw e;
@ -105,7 +105,7 @@ export default class ScalarAuthClient {
} }
} }
_getAccountName(token) { private getAccountName(token) {
const url = this.apiUrl + "/account"; const url = this.apiUrl + "/account";
return new Promise(function(resolve, reject) { return new Promise(function(resolve, reject) {
@ -130,8 +130,8 @@ export default class ScalarAuthClient {
}); });
} }
_checkToken(token) { private checkToken(token) {
return this._getAccountName(token).then(userId => { return this.getAccountName(token).then(userId => {
const me = MatrixClientPeg.get().getUserId(); const me = MatrixClientPeg.get().getUserId();
if (userId !== me) { if (userId !== me) {
throw new Error("Scalar token is owned by someone else: " + me); throw new Error("Scalar token is owned by someone else: " + me);
@ -177,10 +177,10 @@ export default class ScalarAuthClient {
return this.exchangeForScalarToken(tokenObject); return this.exchangeForScalarToken(tokenObject);
}).then((token) => { }).then((token) => {
// Validate it (this mostly checks to see if the IM needs us to agree to some terms) // Validate it (this mostly checks to see if the IM needs us to agree to some terms)
return this._checkToken(token); return this.checkToken(token);
}).then((token) => { }).then((token) => {
this.scalarToken = token; this.scalarToken = token;
this._writeTokenToStore(); this.writeTokenToStore();
return token; return token;
}); });
} }

View File

@ -131,14 +131,14 @@ export default class ManageEventIndexDialog extends React.Component<IProps, ISta
}); });
} }
_onDisable = async () => { private onDisable = async () => {
Modal.createTrackedDialogAsync("Disable message search", "Disable message search", Modal.createTrackedDialogAsync("Disable message search", "Disable message search",
import("./DisableEventIndexDialog"), import("./DisableEventIndexDialog"),
null, null, /* priority = */ false, /* static = */ true, null, null, /* priority = */ false, /* static = */ true,
); );
}; };
_onCrawlerSleepTimeChange = (e) => { private onCrawlerSleepTimeChange = (e) => {
this.setState({crawlerSleepTime: e.target.value}); this.setState({crawlerSleepTime: e.target.value});
SettingsStore.setValue("crawlerSleepTime", null, SettingLevel.DEVICE, e.target.value); SettingsStore.setValue("crawlerSleepTime", null, SettingLevel.DEVICE, e.target.value);
}; };
@ -177,7 +177,7 @@ export default class ManageEventIndexDialog extends React.Component<IProps, ISta
label={_t('Message downloading sleep time(ms)')} label={_t('Message downloading sleep time(ms)')}
type='number' type='number'
value={this.state.crawlerSleepTime} value={this.state.crawlerSleepTime}
onChange={this._onCrawlerSleepTimeChange} /> onChange={this.onCrawlerSleepTimeChange} />
</div> </div>
</div> </div>
); );
@ -196,7 +196,7 @@ export default class ManageEventIndexDialog extends React.Component<IProps, ISta
onPrimaryButtonClick={this.props.onFinished} onPrimaryButtonClick={this.props.onFinished}
primaryButtonClass="primary" primaryButtonClass="primary"
cancelButton={_t("Disable")} cancelButton={_t("Disable")}
onCancel={this._onDisable} onCancel={this.onDisable}
cancelButtonClass="danger" cancelButtonClass="danger"
/> />
</BaseDialog> </BaseDialog>

View File

@ -83,7 +83,7 @@ export default class SoftLogout extends React.Component<IProps, IState> {
return; return;
} }
this._initLogin(); this.initLogin();
const cli = MatrixClientPeg.get(); const cli = MatrixClientPeg.get();
if (cli.isCryptoEnabled()) { if (cli.isCryptoEnabled()) {
@ -105,7 +105,7 @@ export default class SoftLogout extends React.Component<IProps, IState> {
}); });
}; };
async _initLogin() { private async initLogin() {
const queryParams = this.props.realQueryParams; const queryParams = this.props.realQueryParams;
const hasAllParams = queryParams && queryParams['loginToken']; const hasAllParams = queryParams && queryParams['loginToken'];
if (hasAllParams) { if (hasAllParams) {
@ -200,7 +200,7 @@ export default class SoftLogout extends React.Component<IProps, IState> {
}); });
} }
_renderSignInSection() { private renderSignInSection() {
if (this.state.loginView === LOGIN_VIEW.LOADING) { if (this.state.loginView === LOGIN_VIEW.LOADING) {
const Spinner = sdk.getComponent("elements.Spinner"); const Spinner = sdk.getComponent("elements.Spinner");
return <Spinner />; return <Spinner />;
@ -300,7 +300,7 @@ export default class SoftLogout extends React.Component<IProps, IState> {
<h3>{_t("Sign in")}</h3> <h3>{_t("Sign in")}</h3>
<div> <div>
{this._renderSignInSection()} {this.renderSignInSection()}
</div> </div>
<h3>{_t("Clear personal data")}</h3> <h3>{_t("Clear personal data")}</h3>

View File

@ -293,10 +293,10 @@ interface IState {
@replaceableComponent("views.rooms.EventTile") @replaceableComponent("views.rooms.EventTile")
export default class EventTile extends React.Component<IProps, IState> { export default class EventTile extends React.Component<IProps, IState> {
private _suppressReadReceiptAnimation: boolean; private suppressReadReceiptAnimation: boolean;
private _isListeningForReceipts: boolean; private isListeningForReceipts: boolean;
private _tile = React.createRef(); private tile = React.createRef();
private _replyThread = React.createRef(); private replyThread = React.createRef();
static defaultProps = { static defaultProps = {
// no-op function because onHeightChanged is optional yet some sub-components assume its existence // no-op function because onHeightChanged is optional yet some sub-components assume its existence
@ -323,23 +323,22 @@ export default class EventTile extends React.Component<IProps, IState> {
}; };
// don't do RR animations until we are mounted // don't do RR animations until we are mounted
this._suppressReadReceiptAnimation = true; this.suppressReadReceiptAnimation = true;
// Throughout the component we manage a read receipt listener to see if our tile still // Throughout the component we manage a read receipt listener to see if our tile still
// qualifies for a "sent" or "sending" state (based on their relevant conditions). We // qualifies for a "sent" or "sending" state (based on their relevant conditions). We
// don't want to over-subscribe to the read receipt events being fired, so we use a flag // don't want to over-subscribe to the read receipt events being fired, so we use a flag
// to determine if we've already subscribed and use a combination of other flags to find // to determine if we've already subscribed and use a combination of other flags to find
// out if we should even be subscribed at all. // out if we should even be subscribed at all.
this._isListeningForReceipts = false; this.isListeningForReceipts = false;
} }
/** /**
* When true, the tile qualifies for some sort of special read receipt. This could be a 'sending' * When true, the tile qualifies for some sort of special read receipt. This could be a 'sending'
* or 'sent' receipt, for example. * or 'sent' receipt, for example.
* @returns {boolean} * @returns {boolean}
* @private
*/ */
get _isEligibleForSpecialReceipt() { private get isEligibleForSpecialReceipt() {
// First, if there are other read receipts then just short-circuit this. // First, if there are other read receipts then just short-circuit this.
if (this.props.readReceipts && this.props.readReceipts.length > 0) return false; if (this.props.readReceipts && this.props.readReceipts.length > 0) return false;
if (!this.props.mxEvent) return false; if (!this.props.mxEvent) return false;
@ -368,9 +367,9 @@ export default class EventTile extends React.Component<IProps, IState> {
return true; return true;
} }
get _shouldShowSentReceipt() { private get shouldShowSentReceipt() {
// If we're not even eligible, don't show the receipt. // If we're not even eligible, don't show the receipt.
if (!this._isEligibleForSpecialReceipt) return false; if (!this.isEligibleForSpecialReceipt) return false;
// We only show the 'sent' receipt on the last successful event. // We only show the 'sent' receipt on the last successful event.
if (!this.props.lastSuccessful) return false; if (!this.props.lastSuccessful) return false;
@ -388,9 +387,9 @@ export default class EventTile extends React.Component<IProps, IState> {
return true; return true;
} }
get _shouldShowSendingReceipt() { private get shouldShowSendingReceipt() {
// If we're not even eligible, don't show the receipt. // If we're not even eligible, don't show the receipt.
if (!this._isEligibleForSpecialReceipt) return false; if (!this.isEligibleForSpecialReceipt) return false;
// Check the event send status to see if we are pending. Null/undefined status means the // Check the event send status to see if we are pending. Null/undefined status means the
// message was sent, so check for that and 'sent' explicitly. // message was sent, so check for that and 'sent' explicitly.
@ -404,22 +403,22 @@ 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 camelcase
UNSAFE_componentWillMount() { UNSAFE_componentWillMount() {
this._verifyEvent(this.props.mxEvent); this.verifyEvent(this.props.mxEvent);
} }
componentDidMount() { componentDidMount() {
this._suppressReadReceiptAnimation = false; this.suppressReadReceiptAnimation = false;
const client = this.context; const client = this.context;
client.on("deviceVerificationChanged", this.onDeviceVerificationChanged); client.on("deviceVerificationChanged", this.onDeviceVerificationChanged);
client.on("userTrustStatusChanged", this.onUserVerificationChanged); client.on("userTrustStatusChanged", this.onUserVerificationChanged);
this.props.mxEvent.on("Event.decrypted", this._onDecrypted); this.props.mxEvent.on("Event.decrypted", this.onDecrypted);
if (this.props.showReactions) { if (this.props.showReactions) {
this.props.mxEvent.on("Event.relationsCreated", this._onReactionsCreated); this.props.mxEvent.on("Event.relationsCreated", this.onReactionsCreated);
} }
if (this._shouldShowSentReceipt || this._shouldShowSendingReceipt) { if (this.shouldShowSentReceipt || this.shouldShowSendingReceipt) {
client.on("Room.receipt", this._onRoomReceipt); client.on("Room.receipt", this.onRoomReceipt);
this._isListeningForReceipts = true; this.isListeningForReceipts = true;
} }
} }
@ -429,7 +428,7 @@ export default class EventTile extends React.Component<IProps, IState> {
// 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.
if (nextProps.eventSendStatus !== this.props.eventSendStatus) { if (nextProps.eventSendStatus !== this.props.eventSendStatus) {
this._verifyEvent(nextProps.mxEvent); this.verifyEvent(nextProps.mxEvent);
} }
} }
@ -438,35 +437,35 @@ export default class EventTile extends React.Component<IProps, IState> {
return true; return true;
} }
return !this._propsEqual(this.props, nextProps); return !this.propsEqual(this.props, nextProps);
} }
componentWillUnmount() { componentWillUnmount() {
const client = this.context; const client = this.context;
client.removeListener("deviceVerificationChanged", this.onDeviceVerificationChanged); client.removeListener("deviceVerificationChanged", this.onDeviceVerificationChanged);
client.removeListener("userTrustStatusChanged", this.onUserVerificationChanged); client.removeListener("userTrustStatusChanged", this.onUserVerificationChanged);
client.removeListener("Room.receipt", this._onRoomReceipt); client.removeListener("Room.receipt", this.onRoomReceipt);
this._isListeningForReceipts = false; this.isListeningForReceipts = false;
this.props.mxEvent.removeListener("Event.decrypted", this._onDecrypted); this.props.mxEvent.removeListener("Event.decrypted", this.onDecrypted);
if (this.props.showReactions) { if (this.props.showReactions) {
this.props.mxEvent.removeListener("Event.relationsCreated", this._onReactionsCreated); this.props.mxEvent.removeListener("Event.relationsCreated", this.onReactionsCreated);
} }
} }
componentDidUpdate(prevProps, prevState, snapshot) { componentDidUpdate(prevProps, prevState, snapshot) {
// If we're not listening for receipts and expect to be, register a listener. // If we're not listening for receipts and expect to be, register a listener.
if (!this._isListeningForReceipts && (this._shouldShowSentReceipt || this._shouldShowSendingReceipt)) { if (!this.isListeningForReceipts && (this.shouldShowSentReceipt || this.shouldShowSendingReceipt)) {
this.context.on("Room.receipt", this._onRoomReceipt); this.context.on("Room.receipt", this.onRoomReceipt);
this._isListeningForReceipts = true; this.isListeningForReceipts = true;
} }
} }
_onRoomReceipt = (ev, room) => { private onRoomReceipt = (ev, room) => {
// ignore events for other rooms // ignore events for other rooms
const tileRoom = MatrixClientPeg.get().getRoom(this.props.mxEvent.getRoomId()); const tileRoom = MatrixClientPeg.get().getRoom(this.props.mxEvent.getRoomId());
if (room !== tileRoom) return; if (room !== tileRoom) return;
if (!this._shouldShowSentReceipt && !this._shouldShowSendingReceipt && !this._isListeningForReceipts) { if (!this.shouldShowSentReceipt && !this.shouldShowSendingReceipt && !this.isListeningForReceipts) {
return; return;
} }
@ -474,36 +473,36 @@ export default class EventTile extends React.Component<IProps, IState> {
// the getters we use here to determine what needs rendering. // the getters we use here to determine what needs rendering.
this.forceUpdate(() => { this.forceUpdate(() => {
// Per elsewhere in this file, we can remove the listener once we will have no further purpose for it. // Per elsewhere in this file, we can remove the listener once we will have no further purpose for it.
if (!this._shouldShowSentReceipt && !this._shouldShowSendingReceipt) { if (!this.shouldShowSentReceipt && !this.shouldShowSendingReceipt) {
this.context.removeListener("Room.receipt", this._onRoomReceipt); this.context.removeListener("Room.receipt", this.onRoomReceipt);
this._isListeningForReceipts = false; this.isListeningForReceipts = false;
} }
}); });
}; };
/** called when the event is decrypted after we show it. /** called when the event is decrypted after we show it.
*/ */
_onDecrypted = () => { private onDecrypted = () => {
// we need to re-verify the sending device. // we need to re-verify the sending device.
// (we call onHeightChanged in _verifyEvent to handle the case where decryption // (we call onHeightChanged in verifyEvent to handle the case where decryption
// has caused a change in size of the event tile) // has caused a change in size of the event tile)
this._verifyEvent(this.props.mxEvent); this.verifyEvent(this.props.mxEvent);
this.forceUpdate(); this.forceUpdate();
}; };
onDeviceVerificationChanged = (userId, device) => { private onDeviceVerificationChanged = (userId, device) => {
if (userId === this.props.mxEvent.getSender()) { if (userId === this.props.mxEvent.getSender()) {
this._verifyEvent(this.props.mxEvent); this.verifyEvent(this.props.mxEvent);
} }
}; };
onUserVerificationChanged = (userId, _trustStatus) => { private onUserVerificationChanged = (userId, _trustStatus) => {
if (userId === this.props.mxEvent.getSender()) { if (userId === this.props.mxEvent.getSender()) {
this._verifyEvent(this.props.mxEvent); this.verifyEvent(this.props.mxEvent);
} }
}; };
async _verifyEvent(mxEvent) { private async verifyEvent(mxEvent) {
if (!mxEvent.isEncrypted()) { if (!mxEvent.isEncrypted()) {
return; return;
} }
@ -557,7 +556,7 @@ export default class EventTile extends React.Component<IProps, IState> {
}, this.props.onHeightChanged); // Decryption may have caused a change in size }, this.props.onHeightChanged); // Decryption may have caused a change in size
} }
_propsEqual(objA, objB) { private propsEqual(objA, objB) {
const keysA = Object.keys(objA); const keysA = Object.keys(objA);
const keysB = Object.keys(objB); const keysB = Object.keys(objB);
@ -624,7 +623,7 @@ export default class EventTile extends React.Component<IProps, IState> {
}; };
getReadAvatars() { getReadAvatars() {
if (this._shouldShowSentReceipt || this._shouldShowSendingReceipt) { if (this.shouldShowSentReceipt || this.shouldShowSendingReceipt) {
return <SentReceipt messageState={this.props.mxEvent.getAssociatedStatus()} />; return <SentReceipt messageState={this.props.mxEvent.getAssociatedStatus()} />;
} }
@ -671,7 +670,7 @@ export default class EventTile extends React.Component<IProps, IState> {
leftOffset={left} hidden={hidden} leftOffset={left} hidden={hidden}
readReceiptInfo={readReceiptInfo} readReceiptInfo={readReceiptInfo}
checkUnmounting={this.props.checkUnmounting} checkUnmounting={this.props.checkUnmounting}
suppressAnimation={this._suppressReadReceiptAnimation} suppressAnimation={this.suppressReadReceiptAnimation}
onClick={this.toggleAllReadAvatars} onClick={this.toggleAllReadAvatars}
timestamp={receipt.ts} timestamp={receipt.ts}
showTwelveHour={this.props.isTwelveHour} showTwelveHour={this.props.isTwelveHour}
@ -728,7 +727,7 @@ export default class EventTile extends React.Component<IProps, IState> {
}); });
}; };
_renderE2EPadlock() { private renderE2EPadlock() {
const ev = this.props.mxEvent; const ev = this.props.mxEvent;
// event could not be decrypted // event could not be decrypted
@ -777,9 +776,9 @@ export default class EventTile extends React.Component<IProps, IState> {
}); });
}; };
getTile = () => this._tile.current; getTile = () => this.tile.current;
getReplyThread = () => this._replyThread.current; getReplyThread = () => this.replyThread.current;
getReactions = () => { getReactions = () => {
if ( if (
@ -799,11 +798,11 @@ export default class EventTile extends React.Component<IProps, IState> {
return this.props.getRelationsForEvent(eventId, "m.annotation", "m.reaction"); return this.props.getRelationsForEvent(eventId, "m.annotation", "m.reaction");
}; };
_onReactionsCreated = (relationType, eventType) => { private onReactionsCreated = (relationType, eventType) => {
if (relationType !== "m.annotation" || eventType !== "m.reaction") { if (relationType !== "m.annotation" || eventType !== "m.reaction") {
return; return;
} }
this.props.mxEvent.removeListener("Event.relationsCreated", this._onReactionsCreated); this.props.mxEvent.removeListener("Event.relationsCreated", this.onReactionsCreated);
this.setState({ this.setState({
reactions: this.getReactions(), reactions: this.getReactions(),
}); });
@ -1017,8 +1016,8 @@ export default class EventTile extends React.Component<IProps, IState> {
const useIRCLayout = this.props.layout == Layout.IRC; const useIRCLayout = this.props.layout == Layout.IRC;
const groupTimestamp = !useIRCLayout ? linkedTimestamp : null; const groupTimestamp = !useIRCLayout ? linkedTimestamp : null;
const ircTimestamp = useIRCLayout ? linkedTimestamp : null; const ircTimestamp = useIRCLayout ? linkedTimestamp : null;
const groupPadlock = !useIRCLayout && !isBubbleMessage && this._renderE2EPadlock(); const groupPadlock = !useIRCLayout && !isBubbleMessage && this.renderE2EPadlock();
const ircPadlock = useIRCLayout && !isBubbleMessage && this._renderE2EPadlock(); const ircPadlock = useIRCLayout && !isBubbleMessage && this.renderE2EPadlock();
let msgOption; let msgOption;
if (this.props.showReadReceipts) { if (this.props.showReadReceipts) {
@ -1049,7 +1048,7 @@ export default class EventTile extends React.Component<IProps, IState> {
</a> </a>
</div> </div>
<div className="mx_EventTile_line"> <div className="mx_EventTile_line">
<EventTileType ref={this._tile} <EventTileType ref={this.tile}
mxEvent={this.props.mxEvent} mxEvent={this.props.mxEvent}
highlights={this.props.highlights} highlights={this.props.highlights}
highlightLink={this.props.highlightLink} highlightLink={this.props.highlightLink}
@ -1064,7 +1063,7 @@ export default class EventTile extends React.Component<IProps, IState> {
return ( return (
<div className={classes} aria-live={ariaLive} aria-atomic="true"> <div className={classes} aria-live={ariaLive} aria-atomic="true">
<div className="mx_EventTile_line"> <div className="mx_EventTile_line">
<EventTileType ref={this._tile} <EventTileType ref={this.tile}
mxEvent={this.props.mxEvent} mxEvent={this.props.mxEvent}
highlights={this.props.highlights} highlights={this.props.highlights}
highlightLink={this.props.highlightLink} highlightLink={this.props.highlightLink}
@ -1095,7 +1094,7 @@ export default class EventTile extends React.Component<IProps, IState> {
this.props.mxEvent, this.props.mxEvent,
this.props.onHeightChanged, this.props.onHeightChanged,
this.props.permalinkCreator, this.props.permalinkCreator,
this._replyThread, this.replyThread,
); );
} }
return ( return (
@ -1108,7 +1107,7 @@ export default class EventTile extends React.Component<IProps, IState> {
{ groupTimestamp } { groupTimestamp }
{ groupPadlock } { groupPadlock }
{ thread } { thread }
<EventTileType ref={this._tile} <EventTileType ref={this.tile}
mxEvent={this.props.mxEvent} mxEvent={this.props.mxEvent}
highlights={this.props.highlights} highlights={this.props.highlights}
highlightLink={this.props.highlightLink} highlightLink={this.props.highlightLink}
@ -1125,7 +1124,7 @@ export default class EventTile extends React.Component<IProps, IState> {
this.props.mxEvent, this.props.mxEvent,
this.props.onHeightChanged, this.props.onHeightChanged,
this.props.permalinkCreator, this.props.permalinkCreator,
this._replyThread, this.replyThread,
this.props.layout, this.props.layout,
); );
@ -1139,7 +1138,7 @@ export default class EventTile extends React.Component<IProps, IState> {
{ groupTimestamp } { groupTimestamp }
{ groupPadlock } { groupPadlock }
{ thread } { thread }
<EventTileType ref={this._tile} <EventTileType ref={this.tile}
mxEvent={this.props.mxEvent} mxEvent={this.props.mxEvent}
replacingEventId={this.props.replacingEventId} replacingEventId={this.props.replacingEventId}
editState={this.props.editState} editState={this.props.editState}

View File

@ -108,17 +108,17 @@ interface IUploadButtonProps {
} }
class UploadButton extends React.Component<IUploadButtonProps> { class UploadButton extends React.Component<IUploadButtonProps> {
private _uploadInput = React.createRef<HTMLInputElement>(); private uploadInput = React.createRef<HTMLInputElement>();
private _dispatcherRef: string; private dispatcherRef: string;
constructor(props) { constructor(props) {
super(props); super(props);
this._dispatcherRef = dis.register(this.onAction); this.dispatcherRef = dis.register(this.onAction);
} }
componentWillUnmount() { componentWillUnmount() {
dis.unregister(this._dispatcherRef); dis.unregister(this.dispatcherRef);
} }
private onAction = payload => { private onAction = payload => {
@ -132,7 +132,7 @@ class UploadButton extends React.Component<IUploadButtonProps> {
dis.dispatch({action: 'require_registration'}); dis.dispatch({action: 'require_registration'});
return; return;
} }
this._uploadInput.current.click(); this.uploadInput.current.click();
} }
private onUploadFileInputChange = (ev) => { private onUploadFileInputChange = (ev) => {
@ -165,7 +165,7 @@ class UploadButton extends React.Component<IUploadButtonProps> {
title={_t('Upload file')} title={_t('Upload file')}
> >
<input <input
ref={this._uploadInput} ref={this.uploadInput}
type="file" type="file"
style={uploadInputStyle} style={uploadInputStyle}
multiple multiple
@ -200,7 +200,7 @@ export default class MessageComposer extends React.Component<IProps, IState> {
constructor(props) { constructor(props) {
super(props); super(props);
VoiceRecordingStore.instance.on(UPDATE_EVENT, this._onVoiceStoreUpdate); VoiceRecordingStore.instance.on(UPDATE_EVENT, this.onVoiceStoreUpdate);
this.state = { this.state = {
tombstone: this.getRoomTombstone(), tombstone: this.getRoomTombstone(),
@ -249,7 +249,7 @@ export default class MessageComposer extends React.Component<IProps, IState> {
if (MatrixClientPeg.get()) { if (MatrixClientPeg.get()) {
MatrixClientPeg.get().removeListener("RoomState.events", this.onRoomStateEvents); MatrixClientPeg.get().removeListener("RoomState.events", this.onRoomStateEvents);
} }
VoiceRecordingStore.instance.off(UPDATE_EVENT, this._onVoiceStoreUpdate); VoiceRecordingStore.instance.off(UPDATE_EVENT, this.onVoiceStoreUpdate);
dis.unregister(this.dispatcherRef); dis.unregister(this.dispatcherRef);
} }
@ -331,7 +331,7 @@ export default class MessageComposer extends React.Component<IProps, IState> {
}); });
} }
_onVoiceStoreUpdate = () => { private onVoiceStoreUpdate = () => {
const recording = VoiceRecordingStore.instance.activeRecording; const recording = VoiceRecordingStore.instance.activeRecording;
this.setState({haveRecording: !!recording}); this.setState({haveRecording: !!recording});
if (recording) { if (recording) {

View File

@ -109,7 +109,7 @@ export default class EventIndexPanel extends React.Component<{}, IState> {
}); });
} }
_onManage = async () => { private onManage = async () => {
Modal.createTrackedDialogAsync('Message search', 'Message search', Modal.createTrackedDialogAsync('Message search', 'Message search',
// @ts-ignore: TS doesn't seem to like the type of this now that it // @ts-ignore: TS doesn't seem to like the type of this now that it
// has also been converted to TS as well, but I can't figure out why... // has also been converted to TS as well, but I can't figure out why...
@ -120,7 +120,7 @@ export default class EventIndexPanel extends React.Component<{}, IState> {
); );
} }
_onEnable = async () => { private onEnable = async () => {
this.setState({ this.setState({
enabling: true, enabling: true,
}); });
@ -132,13 +132,13 @@ export default class EventIndexPanel extends React.Component<{}, IState> {
await this.updateState(); await this.updateState();
} }
_confirmEventStoreReset = () => { private confirmEventStoreReset = () => {
const { close } = Modal.createDialog(SeshatResetDialog, { const { close } = Modal.createDialog(SeshatResetDialog, {
onFinished: async (success) => { onFinished: async (success) => {
if (success) { if (success) {
await SettingsStore.setValue('enableEventIndexing', null, SettingLevel.DEVICE, false); await SettingsStore.setValue('enableEventIndexing', null, SettingLevel.DEVICE, false);
await EventIndexPeg.deleteEventIndex(); await EventIndexPeg.deleteEventIndex();
await this._onEnable(); await this.onEnable();
close(); close();
} }
}, },
@ -165,7 +165,7 @@ export default class EventIndexPanel extends React.Component<{}, IState> {
}, },
)}</div> )}</div>
<div> <div>
<AccessibleButton kind="primary" onClick={this._onManage}> <AccessibleButton kind="primary" onClick={this.onManage}>
{_t("Manage")} {_t("Manage")}
</AccessibleButton> </AccessibleButton>
</div> </div>
@ -180,7 +180,7 @@ export default class EventIndexPanel extends React.Component<{}, IState> {
)}</div> )}</div>
<div> <div>
<AccessibleButton kind="primary" disabled={this.state.enabling} <AccessibleButton kind="primary" disabled={this.state.enabling}
onClick={this._onEnable}> onClick={this.onEnable}>
{_t("Enable")} {_t("Enable")}
</AccessibleButton> </AccessibleButton>
{this.state.enabling ? <InlineSpinner /> : <div />} {this.state.enabling ? <InlineSpinner /> : <div />}
@ -242,7 +242,7 @@ export default class EventIndexPanel extends React.Component<{}, IState> {
{EventIndexPeg.error.message} {EventIndexPeg.error.message}
</code> </code>
<p> <p>
<AccessibleButton key="delete" kind="danger" onClick={this._confirmEventStoreReset}> <AccessibleButton key="delete" kind="danger" onClick={this.confirmEventStoreReset}>
{_t("Reset")} {_t("Reset")}
</AccessibleButton> </AccessibleButton>
</p> </p>

View File

@ -107,7 +107,7 @@ export default class SetIdServer extends React.Component<IProps, IState> {
dis.unregister(this.dispatcherRef); dis.unregister(this.dispatcherRef);
} }
onAction = (payload) => { private onAction = (payload) => {
// We react to changes in the ID server in the event the user is staring at this form // We react to changes in the ID server in the event the user is staring at this form
// when changing their identity server on another device. // when changing their identity server on another device.
if (payload.action !== "id_server_changed") return; if (payload.action !== "id_server_changed") return;
@ -117,13 +117,13 @@ export default class SetIdServer extends React.Component<IProps, IState> {
}); });
}; };
_onIdentityServerChanged = (ev) => { private onIdentityServerChanged = (ev) => {
const u = ev.target.value; const u = ev.target.value;
this.setState({idServer: u}); this.setState({idServer: u});
}; };
_getTooltip = () => { private getTooltip = () => {
if (this.state.checking) { if (this.state.checking) {
const InlineSpinner = sdk.getComponent('views.elements.InlineSpinner'); const InlineSpinner = sdk.getComponent('views.elements.InlineSpinner');
return <div> return <div>
@ -137,11 +137,11 @@ export default class SetIdServer extends React.Component<IProps, IState> {
} }
}; };
_idServerChangeEnabled = () => { private idServerChangeEnabled = () => {
return !!this.state.idServer && !this.state.busy; return !!this.state.idServer && !this.state.busy;
}; };
_saveIdServer = (fullUrl) => { private saveIdServer = (fullUrl) => {
// Account data change will update localstorage, client, etc through dispatcher // Account data change will update localstorage, client, etc through dispatcher
MatrixClientPeg.get().setAccountData("m.identity_server", { MatrixClientPeg.get().setAccountData("m.identity_server", {
base_url: fullUrl, base_url: fullUrl,
@ -154,7 +154,7 @@ export default class SetIdServer extends React.Component<IProps, IState> {
}); });
}; };
_checkIdServer = async (e) => { private checkIdServer = async (e) => {
e.preventDefault(); e.preventDefault();
const { idServer, currentClientIdServer } = this.state; const { idServer, currentClientIdServer } = this.state;
@ -177,14 +177,14 @@ export default class SetIdServer extends React.Component<IProps, IState> {
// Double check that the identity server even has terms of service. // Double check that the identity server even has terms of service.
const hasTerms = await doesIdentityServerHaveTerms(fullUrl); const hasTerms = await doesIdentityServerHaveTerms(fullUrl);
if (!hasTerms) { if (!hasTerms) {
const [confirmed] = await this._showNoTermsWarning(fullUrl); const [confirmed] = await this.showNoTermsWarning(fullUrl);
save = confirmed; save = confirmed;
} }
// Show a general warning, possibly with details about any bound // Show a general warning, possibly with details about any bound
// 3PIDs that would be left behind. // 3PIDs that would be left behind.
if (save && currentClientIdServer && fullUrl !== currentClientIdServer) { if (save && currentClientIdServer && fullUrl !== currentClientIdServer) {
const [confirmed] = await this._showServerChangeWarning({ const [confirmed] = await this.showServerChangeWarning({
title: _t("Change identity server"), title: _t("Change identity server"),
unboundMessage: _t( unboundMessage: _t(
"Disconnect from the identity server <current /> and " + "Disconnect from the identity server <current /> and " +
@ -200,7 +200,7 @@ export default class SetIdServer extends React.Component<IProps, IState> {
} }
if (save) { if (save) {
this._saveIdServer(fullUrl); this.saveIdServer(fullUrl);
} }
} catch (e) { } catch (e) {
console.error(e); console.error(e);
@ -215,7 +215,7 @@ export default class SetIdServer extends React.Component<IProps, IState> {
}); });
}; };
_showNoTermsWarning(fullUrl) { private showNoTermsWarning(fullUrl) {
const QuestionDialog = sdk.getComponent("views.dialogs.QuestionDialog"); const QuestionDialog = sdk.getComponent("views.dialogs.QuestionDialog");
const { finished } = Modal.createTrackedDialog('No Terms Warning', '', QuestionDialog, { const { finished } = Modal.createTrackedDialog('No Terms Warning', '', QuestionDialog, {
title: _t("Identity server has no terms of service"), title: _t("Identity server has no terms of service"),
@ -234,10 +234,10 @@ export default class SetIdServer extends React.Component<IProps, IState> {
return finished; return finished;
} }
_onDisconnectClicked = async () => { private onDisconnectClicked = async () => {
this.setState({disconnectBusy: true}); this.setState({disconnectBusy: true});
try { try {
const [confirmed] = await this._showServerChangeWarning({ const [confirmed] = await this.showServerChangeWarning({
title: _t("Disconnect identity server"), title: _t("Disconnect identity server"),
unboundMessage: _t( unboundMessage: _t(
"Disconnect from the identity server <idserver />?", {}, "Disconnect from the identity server <idserver />?", {},
@ -246,14 +246,14 @@ export default class SetIdServer extends React.Component<IProps, IState> {
button: _t("Disconnect"), button: _t("Disconnect"),
}); });
if (confirmed) { if (confirmed) {
this._disconnectIdServer(); this.disconnectIdServer();
} }
} finally { } finally {
this.setState({disconnectBusy: false}); this.setState({disconnectBusy: false});
} }
}; };
async _showServerChangeWarning({ title, unboundMessage, button }) { private async showServerChangeWarning({ title, unboundMessage, button }) {
const { currentClientIdServer } = this.state; const { currentClientIdServer } = this.state;
let threepids = []; let threepids = [];
@ -329,7 +329,7 @@ export default class SetIdServer extends React.Component<IProps, IState> {
return finished; return finished;
} }
_disconnectIdServer = () => { private disconnectIdServer = () => {
// Account data change will update localstorage, client, etc through dispatcher // Account data change will update localstorage, client, etc through dispatcher
MatrixClientPeg.get().setAccountData("m.identity_server", { MatrixClientPeg.get().setAccountData("m.identity_server", {
base_url: null, // clear base_url: null, // clear
@ -402,14 +402,14 @@ export default class SetIdServer extends React.Component<IProps, IState> {
} }
discoSection = <div> discoSection = <div>
<span className="mx_SettingsTab_subsectionText">{discoBodyText}</span> <span className="mx_SettingsTab_subsectionText">{discoBodyText}</span>
<AccessibleButton onClick={this._onDisconnectClicked} kind="danger_sm"> <AccessibleButton onClick={this.onDisconnectClicked} kind="danger_sm">
{discoButtonContent} {discoButtonContent}
</AccessibleButton> </AccessibleButton>
</div>; </div>;
} }
return ( return (
<form className="mx_SettingsTab_section mx_SetIdServer" onSubmit={this._checkIdServer}> <form className="mx_SettingsTab_section mx_SetIdServer" onSubmit={this.checkIdServer}>
<span className="mx_SettingsTab_subheading"> <span className="mx_SettingsTab_subheading">
{sectionTitle} {sectionTitle}
</span> </span>
@ -422,15 +422,15 @@ export default class SetIdServer extends React.Component<IProps, IState> {
autoComplete="off" autoComplete="off"
placeholder={this.state.defaultIdServer} placeholder={this.state.defaultIdServer}
value={this.state.idServer} value={this.state.idServer}
onChange={this._onIdentityServerChanged} onChange={this.onIdentityServerChanged}
tooltipContent={this._getTooltip()} tooltipContent={this.getTooltip()}
tooltipClassName="mx_SetIdServer_tooltip" tooltipClassName="mx_SetIdServer_tooltip"
disabled={this.state.busy} disabled={this.state.busy}
forceValidity={this.state.error ? false : null} forceValidity={this.state.error ? false : null}
/> />
<AccessibleButton type="submit" kind="primary_sm" <AccessibleButton type="submit" kind="primary_sm"
onClick={this._checkIdServer} onClick={this.checkIdServer}
disabled={!this._idServerChangeEnabled()} disabled={!this.idServerChangeEnabled()}
>{_t("Change")}</AccessibleButton> >{_t("Change")}</AccessibleButton>
{discoSection} {discoSection}
</form> </form>

View File

@ -71,7 +71,7 @@ interface IBannedUserProps {
} }
export class BannedUser extends React.Component<IBannedUserProps> { export class BannedUser extends React.Component<IBannedUserProps> {
_onUnbanClick = (e) => { private onUnbanClick = (e) => {
MatrixClientPeg.get().unban(this.props.member.roomId, this.props.member.userId).catch((err) => { MatrixClientPeg.get().unban(this.props.member.roomId, this.props.member.userId).catch((err) => {
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog"); const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
console.error("Failed to unban: " + err); console.error("Failed to unban: " + err);
@ -89,7 +89,7 @@ export class BannedUser extends React.Component<IBannedUserProps> {
unbanButton = ( unbanButton = (
<AccessibleButton className='mx_RolesRoomSettingsTab_unbanBtn' <AccessibleButton className='mx_RolesRoomSettingsTab_unbanBtn'
kind='danger_sm' kind='danger_sm'
onClick={this._onUnbanClick} onClick={this.onUnbanClick}
> >
{ _t('Unban') } { _t('Unban') }
</AccessibleButton> </AccessibleButton>
@ -116,22 +116,22 @@ interface IProps {
@replaceableComponent("views.settings.tabs.room.RolesRoomSettingsTab") @replaceableComponent("views.settings.tabs.room.RolesRoomSettingsTab")
export default class RolesRoomSettingsTab extends React.Component<IProps> { export default class RolesRoomSettingsTab extends React.Component<IProps> {
componentDidMount(): void { componentDidMount(): void {
MatrixClientPeg.get().on("RoomState.members", this._onRoomMembership); MatrixClientPeg.get().on("RoomState.members", this.onRoomMembership);
} }
componentWillUnmount(): void { componentWillUnmount(): void {
const client = MatrixClientPeg.get(); const client = MatrixClientPeg.get();
if (client) { if (client) {
client.removeListener("RoomState.members", this._onRoomMembership); client.removeListener("RoomState.members", this.onRoomMembership);
} }
} }
_onRoomMembership = (event, state, member) => { private onRoomMembership = (event, state, member) => {
if (state.roomId !== this.props.roomId) return; if (state.roomId !== this.props.roomId) return;
this.forceUpdate(); this.forceUpdate();
}; };
_populateDefaultPlEvents(eventsSection, stateLevel, eventsLevel) { private populateDefaultPlEvents(eventsSection, stateLevel, eventsLevel) {
for (const desiredEvent of Object.keys(plEventsToShow)) { for (const desiredEvent of Object.keys(plEventsToShow)) {
if (!(desiredEvent in eventsSection)) { if (!(desiredEvent in eventsSection)) {
eventsSection[desiredEvent] = (plEventsToShow[desiredEvent].isState ? stateLevel : eventsLevel); eventsSection[desiredEvent] = (plEventsToShow[desiredEvent].isState ? stateLevel : eventsLevel);
@ -139,7 +139,7 @@ export default class RolesRoomSettingsTab extends React.Component<IProps> {
} }
} }
_onPowerLevelsChanged = (value, powerLevelKey) => { private onPowerLevelsChanged = (value, powerLevelKey) => {
const client = MatrixClientPeg.get(); const client = MatrixClientPeg.get();
const room = client.getRoom(this.props.roomId); const room = client.getRoom(this.props.roomId);
const plEvent = room.currentState.getStateEvents('m.room.power_levels', ''); const plEvent = room.currentState.getStateEvents('m.room.power_levels', '');
@ -184,7 +184,7 @@ export default class RolesRoomSettingsTab extends React.Component<IProps> {
}); });
}; };
_onUserPowerLevelChanged = (value, powerLevelKey) => { private onUserPowerLevelChanged = (value, powerLevelKey) => {
const client = MatrixClientPeg.get(); const client = MatrixClientPeg.get();
const room = client.getRoom(this.props.roomId); const room = client.getRoom(this.props.roomId);
const plEvent = room.currentState.getStateEvents('m.room.power_levels', ''); const plEvent = room.currentState.getStateEvents('m.room.power_levels', '');
@ -268,7 +268,7 @@ export default class RolesRoomSettingsTab extends React.Component<IProps> {
currentUserLevel = defaultUserLevel; currentUserLevel = defaultUserLevel;
} }
this._populateDefaultPlEvents( this.populateDefaultPlEvents(
eventsLevels, eventsLevels,
parseIntWithDefault(plContent.state_default, powerLevelDescriptors.state_default.defaultValue), parseIntWithDefault(plContent.state_default, powerLevelDescriptors.state_default.defaultValue),
parseIntWithDefault(plContent.events_default, powerLevelDescriptors.events_default.defaultValue), parseIntWithDefault(plContent.events_default, powerLevelDescriptors.events_default.defaultValue),
@ -290,7 +290,7 @@ export default class RolesRoomSettingsTab extends React.Component<IProps> {
label={user} label={user}
key={user} key={user}
powerLevelKey={user} // Will be sent as the second parameter to `onChange` powerLevelKey={user} // Will be sent as the second parameter to `onChange`
onChange={this._onUserPowerLevelChanged} onChange={this.onUserPowerLevelChanged}
/>, />,
); );
} else if (userLevels[user] < defaultUserLevel) { // muted } else if (userLevels[user] < defaultUserLevel) { // muted
@ -301,7 +301,7 @@ export default class RolesRoomSettingsTab extends React.Component<IProps> {
label={user} label={user}
key={user} key={user}
powerLevelKey={user} // Will be sent as the second parameter to `onChange` powerLevelKey={user} // Will be sent as the second parameter to `onChange`
onChange={this._onUserPowerLevelChanged} onChange={this.onUserPowerLevelChanged}
/>, />,
); );
} }
@ -376,7 +376,7 @@ export default class RolesRoomSettingsTab extends React.Component<IProps> {
usersDefault={defaultUserLevel} usersDefault={defaultUserLevel}
disabled={!canChangeLevels || currentUserLevel < value} disabled={!canChangeLevels || currentUserLevel < value}
powerLevelKey={key} // Will be sent as the second parameter to `onChange` powerLevelKey={key} // Will be sent as the second parameter to `onChange`
onChange={this._onPowerLevelsChanged} onChange={this.onPowerLevelsChanged}
/> />
</div>; </div>;
}); });
@ -401,7 +401,7 @@ export default class RolesRoomSettingsTab extends React.Component<IProps> {
usersDefault={defaultUserLevel} usersDefault={defaultUserLevel}
disabled={!canChangeLevels || currentUserLevel < eventsLevels[eventType]} disabled={!canChangeLevels || currentUserLevel < eventsLevels[eventType]}
powerLevelKey={"event_levels_" + eventType} powerLevelKey={"event_levels_" + eventType}
onChange={this._onPowerLevelsChanged} onChange={this.onPowerLevelsChanged}
/> />
</div> </div>
); );

View File

@ -59,42 +59,42 @@ 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(): Promise<void> { // eslint-disable-line camelcase async UNSAFE_componentWillMount(): Promise<void> { // eslint-disable-line camelcase
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);
const state = room.currentState; const state = room.currentState;
const joinRule: JoinRule = this._pullContentPropertyFromEvent( const joinRule: JoinRule = this.pullContentPropertyFromEvent(
state.getStateEvents("m.room.join_rules", ""), state.getStateEvents("m.room.join_rules", ""),
'join_rule', 'join_rule',
'invite', 'invite',
); );
const guestAccess: GuestAccess = this._pullContentPropertyFromEvent( const guestAccess: GuestAccess = this.pullContentPropertyFromEvent(
state.getStateEvents("m.room.guest_access", ""), state.getStateEvents("m.room.guest_access", ""),
'guest_access', 'guest_access',
'forbidden', 'forbidden',
); );
const history: History = this._pullContentPropertyFromEvent( const history: History = this.pullContentPropertyFromEvent(
state.getStateEvents("m.room.history_visibility", ""), state.getStateEvents("m.room.history_visibility", ""),
'history_visibility', 'history_visibility',
'shared', 'shared',
); );
const encrypted = MatrixClientPeg.get().isRoomEncrypted(this.props.roomId); const encrypted = MatrixClientPeg.get().isRoomEncrypted(this.props.roomId);
this.setState({joinRule, guestAccess, history, encrypted}); this.setState({joinRule, guestAccess, history, encrypted});
const hasAliases = await this._hasAliases(); const hasAliases = await this.hasAliases();
this.setState({hasAliases}); this.setState({hasAliases});
} }
_pullContentPropertyFromEvent(event, key, defaultValue) { private pullContentPropertyFromEvent(event, key, defaultValue) {
if (!event || !event.getContent()) return defaultValue; if (!event || !event.getContent()) return defaultValue;
return event.getContent()[key] || defaultValue; return event.getContent()[key] || defaultValue;
} }
componentWillUnmount(): void { componentWillUnmount(): void {
MatrixClientPeg.get().removeListener("RoomState.events", this._onStateEvent); MatrixClientPeg.get().removeListener("RoomState.events", this.onStateEvent);
} }
_onStateEvent = (e) => { private onStateEvent = (e) => {
const refreshWhenTypes = [ const refreshWhenTypes = [
'm.room.join_rules', 'm.room.join_rules',
'm.room.guest_access', 'm.room.guest_access',
@ -104,7 +104,7 @@ export default class SecurityRoomSettingsTab extends React.Component<IProps, ISt
if (refreshWhenTypes.includes(e.getType())) this.forceUpdate(); if (refreshWhenTypes.includes(e.getType())) this.forceUpdate();
}; };
_onEncryptionChange = (e) => { private onEncryptionChange = (e) => {
Modal.createTrackedDialog('Enable encryption', '', QuestionDialog, { Modal.createTrackedDialog('Enable encryption', '', QuestionDialog, {
title: _t('Enable encryption?'), title: _t('Enable encryption?'),
description: _t( description: _t(
@ -137,7 +137,7 @@ export default class SecurityRoomSettingsTab extends React.Component<IProps, ISt
}); });
}; };
_fixGuestAccess = (e) => { private fixGuestAccess = (e) => {
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
@ -159,7 +159,7 @@ export default class SecurityRoomSettingsTab extends React.Component<IProps, ISt
}); });
}; };
_onRoomAccessRadioToggle = (roomAccess) => { private onRoomAccessRadioToggle = (roomAccess) => {
// join_rule // join_rule
// INVITE | PUBLIC // INVITE | PUBLIC
// ----------------------+---------------- // ----------------------+----------------
@ -205,7 +205,7 @@ export default class SecurityRoomSettingsTab extends React.Component<IProps, ISt
}); });
}; };
_onHistoryRadioToggle = (history) => { private onHistoryRadioToggle = (history) => {
const beforeHistory = this.state.history; const beforeHistory = this.state.history;
this.setState({history: history}); this.setState({history: history});
MatrixClientPeg.get().sendStateEvent(this.props.roomId, "m.room.history_visibility", { MatrixClientPeg.get().sendStateEvent(this.props.roomId, "m.room.history_visibility", {
@ -216,11 +216,11 @@ export default class SecurityRoomSettingsTab extends React.Component<IProps, ISt
}); });
}; };
_updateBlacklistDevicesFlag = (checked) => { private updateBlacklistDevicesFlag = (checked) => {
MatrixClientPeg.get().getRoom(this.props.roomId).setBlacklistUnverifiedDevices(checked); MatrixClientPeg.get().getRoom(this.props.roomId).setBlacklistUnverifiedDevices(checked);
}; };
async _hasAliases() { private async hasAliases() {
const cli = MatrixClientPeg.get(); const cli = MatrixClientPeg.get();
if (await cli.doesServerSupportUnstableFeature("org.matrix.msc2432")) { if (await cli.doesServerSupportUnstableFeature("org.matrix.msc2432")) {
const response = await cli.unstableGetLocalAliases(this.props.roomId); const response = await cli.unstableGetLocalAliases(this.props.roomId);
@ -234,7 +234,7 @@ export default class SecurityRoomSettingsTab extends React.Component<IProps, ISt
} }
} }
_renderRoomAccess() { private renderRoomAccess() {
const client = MatrixClientPeg.get(); const client = MatrixClientPeg.get();
const room = client.getRoom(this.props.roomId); const room = client.getRoom(this.props.roomId);
const joinRule = this.state.joinRule; const joinRule = this.state.joinRule;
@ -250,7 +250,7 @@ export default class SecurityRoomSettingsTab extends React.Component<IProps, ISt
<img src={require("../../../../../../res/img/warning.svg")} width={15} height={15} /> <img src={require("../../../../../../res/img/warning.svg")} width={15} height={15} />
<span> <span>
{_t("Guests cannot join this room even if explicitly invited.")}&nbsp; {_t("Guests cannot join this room even if explicitly invited.")}&nbsp;
<a href="" onClick={this._fixGuestAccess}>{_t("Click here to fix")}</a> <a href="" onClick={this.fixGuestAccess}>{_t("Click here to fix")}</a>
</span> </span>
</div> </div>
); );
@ -275,7 +275,7 @@ export default class SecurityRoomSettingsTab extends React.Component<IProps, ISt
<StyledRadioGroup <StyledRadioGroup
name="roomVis" name="roomVis"
value={joinRule} value={joinRule}
onChange={this._onRoomAccessRadioToggle} onChange={this.onRoomAccessRadioToggle}
definitions={[ definitions={[
{ {
value: "invite_only", value: "invite_only",
@ -301,7 +301,7 @@ export default class SecurityRoomSettingsTab extends React.Component<IProps, ISt
); );
} }
_renderHistory() { private renderHistory() {
const client = MatrixClientPeg.get(); const client = MatrixClientPeg.get();
const history = this.state.history; const history = this.state.history;
const state = client.getRoom(this.props.roomId).currentState; const state = client.getRoom(this.props.roomId).currentState;
@ -316,7 +316,7 @@ export default class SecurityRoomSettingsTab extends React.Component<IProps, ISt
<StyledRadioGroup <StyledRadioGroup
name="historyVis" name="historyVis"
value={history} value={history}
onChange={this._onHistoryRadioToggle} onChange={this.onHistoryRadioToggle}
definitions={[ definitions={[
{ {
value: "world_readable", value: "world_readable",
@ -358,7 +358,7 @@ export default class SecurityRoomSettingsTab extends React.Component<IProps, ISt
encryptionSettings = <SettingsFlag encryptionSettings = <SettingsFlag
name="blacklistUnverifiedDevices" name="blacklistUnverifiedDevices"
level={SettingLevel.ROOM_DEVICE} level={SettingLevel.ROOM_DEVICE}
onChange={this._updateBlacklistDevicesFlag} onChange={this.updateBlacklistDevicesFlag}
roomId={this.props.roomId} roomId={this.props.roomId}
/>; />;
} }
@ -366,7 +366,7 @@ export default class SecurityRoomSettingsTab extends React.Component<IProps, ISt
let historySection = (<> let historySection = (<>
<span className='mx_SettingsTab_subheading'>{_t("Who can read history?")}</span> <span className='mx_SettingsTab_subheading'>{_t("Who can read history?")}</span>
<div className='mx_SettingsTab_section mx_SettingsTab_subsectionText'> <div className='mx_SettingsTab_section mx_SettingsTab_subsectionText'>
{this._renderHistory()} {this.renderHistory()}
</div> </div>
</>); </>);
if (!SettingsStore.getValue(UIFeature.RoomHistorySettings)) { if (!SettingsStore.getValue(UIFeature.RoomHistorySettings)) {
@ -383,7 +383,7 @@ export default class SecurityRoomSettingsTab extends React.Component<IProps, ISt
<div className='mx_SettingsTab_subsectionText'> <div className='mx_SettingsTab_subsectionText'>
<span>{_t("Once enabled, encryption cannot be disabled.")}</span> <span>{_t("Once enabled, encryption cannot be disabled.")}</span>
</div> </div>
<LabelledToggleSwitch value={isEncrypted} onChange={this._onEncryptionChange} <LabelledToggleSwitch value={isEncrypted} onChange={this.onEncryptionChange}
label={_t("Encrypted")} disabled={!canEnableEncryption} label={_t("Encrypted")} disabled={!canEnableEncryption}
/> />
</div> </div>
@ -392,7 +392,7 @@ export default class SecurityRoomSettingsTab extends React.Component<IProps, ISt
<span className='mx_SettingsTab_subheading'>{_t("Who can access this room?")}</span> <span className='mx_SettingsTab_subheading'>{_t("Who can access this room?")}</span>
<div className='mx_SettingsTab_section mx_SettingsTab_subsectionText'> <div className='mx_SettingsTab_section mx_SettingsTab_subsectionText'>
{this._renderRoomAccess()} {this.renderRoomAccess()}
</div> </div>
{historySection} {historySection}

View File

@ -56,7 +56,7 @@ export default class HelpUserSettingsTab extends React.Component<IProps, IState>
}); });
} }
_onClearCacheAndReload = (e) => { private onClearCacheAndReload = (e) => {
if (!PlatformPeg.get()) return; if (!PlatformPeg.get()) return;
// Dev note: please keep this log line, it's useful when troubleshooting a MatrixClient suddenly // Dev note: please keep this log line, it's useful when troubleshooting a MatrixClient suddenly
@ -68,7 +68,7 @@ export default class HelpUserSettingsTab extends React.Component<IProps, IState>
}); });
}; };
_onBugReport = (e) => { private onBugReport = (e) => {
const BugReportDialog = sdk.getComponent("dialogs.BugReportDialog"); const BugReportDialog = sdk.getComponent("dialogs.BugReportDialog");
if (!BugReportDialog) { if (!BugReportDialog) {
return; return;
@ -76,7 +76,7 @@ export default class HelpUserSettingsTab extends React.Component<IProps, IState>
Modal.createTrackedDialog('Bug Report Dialog', '', BugReportDialog, {}); Modal.createTrackedDialog('Bug Report Dialog', '', BugReportDialog, {});
}; };
_onStartBotChat = (e) => { private onStartBotChat = (e) => {
this.props.closeSettingsFn(); this.props.closeSettingsFn();
createRoom({ createRoom({
dmUserId: SdkConfig.get().welcomeUserId, dmUserId: SdkConfig.get().welcomeUserId,
@ -84,7 +84,7 @@ export default class HelpUserSettingsTab extends React.Component<IProps, IState>
}); });
}; };
_showSpoiler = (event) => { private showSpoiler = (event) => {
const target = event.target; const target = event.target;
target.innerHTML = target.getAttribute('data-spoiler'); target.innerHTML = target.getAttribute('data-spoiler');
@ -96,7 +96,7 @@ export default class HelpUserSettingsTab extends React.Component<IProps, IState>
selection.addRange(range); selection.addRange(range);
}; };
_renderLegal() { private renderLegal() {
const tocLinks = SdkConfig.get().terms_and_conditions_links; const tocLinks = SdkConfig.get().terms_and_conditions_links;
if (!tocLinks) return null; if (!tocLinks) return null;
@ -117,7 +117,7 @@ export default class HelpUserSettingsTab extends React.Component<IProps, IState>
); );
} }
_renderCredits() { private renderCredits() {
// Note: This is not translated because it is legal text. // Note: This is not translated because it is legal text.
// Also, &nbsp; is ugly but necessary. // Also, &nbsp; is ugly but necessary.
return ( return (
@ -191,7 +191,7 @@ export default class HelpUserSettingsTab extends React.Component<IProps, IState>
}, },
)} )}
<div> <div>
<AccessibleButton onClick={this._onStartBotChat} kind='primary'> <AccessibleButton onClick={this.onStartBotChat} kind='primary'>
{_t("Chat with %(brand)s Bot", { brand })} {_t("Chat with %(brand)s Bot", { brand })}
</AccessibleButton> </AccessibleButton>
</div> </div>
@ -223,7 +223,7 @@ export default class HelpUserSettingsTab extends React.Component<IProps, IState>
"other users. They do not contain messages.", "other users. They do not contain messages.",
)} )}
<div className='mx_HelpUserSettingsTab_debugButton'> <div className='mx_HelpUserSettingsTab_debugButton'>
<AccessibleButton onClick={this._onBugReport} kind='primary'> <AccessibleButton onClick={this.onBugReport} kind='primary'>
{_t("Submit debug logs")} {_t("Submit debug logs")}
</AccessibleButton> </AccessibleButton>
</div> </div>
@ -262,21 +262,21 @@ export default class HelpUserSettingsTab extends React.Component<IProps, IState>
{updateButton} {updateButton}
</div> </div>
</div> </div>
{this._renderLegal()} {this.renderLegal()}
{this._renderCredits()} {this.renderCredits()}
<div className='mx_SettingsTab_section mx_HelpUserSettingsTab_versions'> <div className='mx_SettingsTab_section mx_HelpUserSettingsTab_versions'>
<span className='mx_SettingsTab_subheading'>{_t("Advanced")}</span> <span className='mx_SettingsTab_subheading'>{_t("Advanced")}</span>
<div className='mx_SettingsTab_subsectionText'> <div className='mx_SettingsTab_subsectionText'>
{_t("Homeserver is")} <code>{MatrixClientPeg.get().getHomeserverUrl()}</code><br /> {_t("Homeserver is")} <code>{MatrixClientPeg.get().getHomeserverUrl()}</code><br />
{_t("Identity Server is")} <code>{MatrixClientPeg.get().getIdentityServerUrl()}</code><br /> {_t("Identity Server is")} <code>{MatrixClientPeg.get().getIdentityServerUrl()}</code><br />
{_t("Access Token:") + ' '} {_t("Access Token:") + ' '}
<AccessibleButton element="span" onClick={this._showSpoiler} <AccessibleButton element="span" onClick={this.showSpoiler}
data-spoiler={MatrixClientPeg.get().getAccessToken()} data-spoiler={MatrixClientPeg.get().getAccessToken()}
> >
&lt;{ _t("click to reveal") }&gt; &lt;{ _t("click to reveal") }&gt;
</AccessibleButton> </AccessibleButton>
<div className='mx_HelpUserSettingsTab_debugButton'> <div className='mx_HelpUserSettingsTab_debugButton'>
<AccessibleButton onClick={this._onClearCacheAndReload} kind='danger'> <AccessibleButton onClick={this.onClearCacheAndReload} kind='danger'>
{_t("Clear cache and reload")} {_t("Clear cache and reload")}
</AccessibleButton> </AccessibleButton>
</div> </div>

View File

@ -43,15 +43,15 @@ export default class MjolnirUserSettingsTab extends React.Component<{}, IState>
}; };
} }
_onPersonalRuleChanged = (e) => { private onPersonalRuleChanged = (e) => {
this.setState({newPersonalRule: e.target.value}); this.setState({newPersonalRule: e.target.value});
}; };
_onNewListChanged = (e) => { private onNewListChanged = (e) => {
this.setState({newList: e.target.value}); this.setState({newList: e.target.value});
}; };
_onAddPersonalRule = async (e) => { private onAddPersonalRule = async (e) => {
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
@ -78,7 +78,7 @@ export default class MjolnirUserSettingsTab extends React.Component<{}, IState>
} }
}; };
_onSubscribeList = async (e) => { private onSubscribeList = async (e) => {
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
@ -100,7 +100,7 @@ export default class MjolnirUserSettingsTab extends React.Component<{}, IState>
} }
}; };
async _removePersonalRule(rule: ListRule) { private async removePersonalRule(rule: ListRule) {
this.setState({busy: true}); this.setState({busy: true});
try { try {
const list = Mjolnir.sharedInstance().getPersonalList(); const list = Mjolnir.sharedInstance().getPersonalList();
@ -118,7 +118,7 @@ export default class MjolnirUserSettingsTab extends React.Component<{}, IState>
} }
} }
async _unsubscribeFromList(list: BanList) { private async unsubscribeFromList(list: BanList) {
this.setState({busy: true}); this.setState({busy: true});
try { try {
await Mjolnir.sharedInstance().unsubscribeFromList(list.roomId); await Mjolnir.sharedInstance().unsubscribeFromList(list.roomId);
@ -136,7 +136,7 @@ export default class MjolnirUserSettingsTab extends React.Component<{}, IState>
} }
} }
_viewListRules(list: BanList) { private viewListRules(list: BanList) {
const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog"); const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
const room = MatrixClientPeg.get().getRoom(list.roomId); const room = MatrixClientPeg.get().getRoom(list.roomId);
@ -167,7 +167,7 @@ export default class MjolnirUserSettingsTab extends React.Component<{}, IState>
}); });
} }
_renderPersonalBanListRules() { private renderPersonalBanListRules() {
const AccessibleButton = sdk.getComponent('elements.AccessibleButton'); const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
const list = Mjolnir.sharedInstance().getPersonalList(); const list = Mjolnir.sharedInstance().getPersonalList();
@ -180,7 +180,7 @@ export default class MjolnirUserSettingsTab extends React.Component<{}, IState>
<li key={rule.entity} className="mx_MjolnirUserSettingsTab_listItem"> <li key={rule.entity} className="mx_MjolnirUserSettingsTab_listItem">
<AccessibleButton <AccessibleButton
kind="danger_sm" kind="danger_sm"
onClick={() => this._removePersonalRule(rule)} onClick={() => this.removePersonalRule(rule)}
disabled={this.state.busy} disabled={this.state.busy}
> >
{_t("Remove")} {_t("Remove")}
@ -198,7 +198,7 @@ export default class MjolnirUserSettingsTab extends React.Component<{}, IState>
); );
} }
_renderSubscribedBanLists() { private renderSubscribedBanLists() {
const AccessibleButton = sdk.getComponent('elements.AccessibleButton'); const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
const personalList = Mjolnir.sharedInstance().getPersonalList(); const personalList = Mjolnir.sharedInstance().getPersonalList();
@ -215,14 +215,14 @@ export default class MjolnirUserSettingsTab extends React.Component<{}, IState>
<li key={list.roomId} className="mx_MjolnirUserSettingsTab_listItem"> <li key={list.roomId} className="mx_MjolnirUserSettingsTab_listItem">
<AccessibleButton <AccessibleButton
kind="danger_sm" kind="danger_sm"
onClick={() => this._unsubscribeFromList(list)} onClick={() => this.unsubscribeFromList(list)}
disabled={this.state.busy} disabled={this.state.busy}
> >
{_t("Unsubscribe")} {_t("Unsubscribe")}
</AccessibleButton>&nbsp; </AccessibleButton>&nbsp;
<AccessibleButton <AccessibleButton
kind="primary_sm" kind="primary_sm"
onClick={() => this._viewListRules(list)} onClick={() => this.viewListRules(list)}
disabled={this.state.busy} disabled={this.state.busy}
> >
{_t("View rules")} {_t("View rules")}
@ -277,21 +277,21 @@ export default class MjolnirUserSettingsTab extends React.Component<{}, IState>
)} )}
</div> </div>
<div> <div>
{this._renderPersonalBanListRules()} {this.renderPersonalBanListRules()}
</div> </div>
<div> <div>
<form onSubmit={this._onAddPersonalRule} autoComplete="off"> <form onSubmit={this.onAddPersonalRule} autoComplete="off">
<Field <Field
type="text" type="text"
label={_t("Server or user ID to ignore")} label={_t("Server or user ID to ignore")}
placeholder={_t("eg: @bot:* or example.org")} placeholder={_t("eg: @bot:* or example.org")}
value={this.state.newPersonalRule} value={this.state.newPersonalRule}
onChange={this._onPersonalRuleChanged} onChange={this.onPersonalRuleChanged}
/> />
<AccessibleButton <AccessibleButton
type="submit" type="submit"
kind="primary" kind="primary"
onClick={this._onAddPersonalRule} onClick={this.onAddPersonalRule}
disabled={this.state.busy} disabled={this.state.busy}
> >
{_t("Ignore")} {_t("Ignore")}
@ -309,20 +309,20 @@ export default class MjolnirUserSettingsTab extends React.Component<{}, IState>
)}</span> )}</span>
</div> </div>
<div> <div>
{this._renderSubscribedBanLists()} {this.renderSubscribedBanLists()}
</div> </div>
<div> <div>
<form onSubmit={this._onSubscribeList} autoComplete="off"> <form onSubmit={this.onSubscribeList} autoComplete="off">
<Field <Field
type="text" type="text"
label={_t("Room ID or address of ban list")} label={_t("Room ID or address of ban list")}
value={this.state.newList} value={this.state.newList}
onChange={this._onNewListChanged} onChange={this.onNewListChanged}
/> />
<AccessibleButton <AccessibleButton
type="submit" type="submit"
kind="primary" kind="primary"
onClick={this._onSubscribeList} onClick={this.onSubscribeList}
disabled={this.state.busy} disabled={this.state.busy}
> >
{_t("Subscribe")} {_t("Subscribe")}

View File

@ -142,38 +142,38 @@ export default class PreferencesUserSettingsTab extends React.Component<{}, ISta
}); });
} }
_onAutoLaunchChange = (checked) => { private onAutoLaunchChange = (checked) => {
PlatformPeg.get().setAutoLaunchEnabled(checked).then(() => this.setState({autoLaunch: checked})); PlatformPeg.get().setAutoLaunchEnabled(checked).then(() => this.setState({autoLaunch: checked}));
}; };
_onWarnBeforeExitChange = (checked) => { private onWarnBeforeExitChange = (checked) => {
PlatformPeg.get().setWarnBeforeExit(checked).then(() => this.setState({warnBeforeExit: checked})); PlatformPeg.get().setWarnBeforeExit(checked).then(() => this.setState({warnBeforeExit: checked}));
} }
_onAlwaysShowMenuBarChange = (checked) => { private onAlwaysShowMenuBarChange = (checked) => {
PlatformPeg.get().setAutoHideMenuBarEnabled(!checked).then(() => this.setState({alwaysShowMenuBar: checked})); PlatformPeg.get().setAutoHideMenuBarEnabled(!checked).then(() => this.setState({alwaysShowMenuBar: checked}));
}; };
_onMinimizeToTrayChange = (checked) => { private onMinimizeToTrayChange = (checked) => {
PlatformPeg.get().setMinimizeToTrayEnabled(checked).then(() => this.setState({minimizeToTray: checked})); PlatformPeg.get().setMinimizeToTrayEnabled(checked).then(() => this.setState({minimizeToTray: checked}));
}; };
_onAutocompleteDelayChange = (e) => { private onAutocompleteDelayChange = (e) => {
this.setState({autocompleteDelay: e.target.value}); this.setState({autocompleteDelay: e.target.value});
SettingsStore.setValue("autocompleteDelay", null, SettingLevel.DEVICE, e.target.value); SettingsStore.setValue("autocompleteDelay", null, SettingLevel.DEVICE, e.target.value);
}; };
_onReadMarkerInViewThresholdMs = (e) => { private onReadMarkerInViewThresholdMs = (e) => {
this.setState({readMarkerInViewThresholdMs: e.target.value}); this.setState({readMarkerInViewThresholdMs: e.target.value});
SettingsStore.setValue("readMarkerInViewThresholdMs", null, SettingLevel.DEVICE, e.target.value); SettingsStore.setValue("readMarkerInViewThresholdMs", null, SettingLevel.DEVICE, e.target.value);
}; };
_onReadMarkerOutOfViewThresholdMs = (e) => { private onReadMarkerOutOfViewThresholdMs = (e) => {
this.setState({readMarkerOutOfViewThresholdMs: e.target.value}); this.setState({readMarkerOutOfViewThresholdMs: e.target.value});
SettingsStore.setValue("readMarkerOutOfViewThresholdMs", null, SettingLevel.DEVICE, e.target.value); SettingsStore.setValue("readMarkerOutOfViewThresholdMs", null, SettingLevel.DEVICE, e.target.value);
}; };
_renderGroup(settingIds) { private renderGroup(settingIds) {
const SettingsFlag = sdk.getComponent("views.elements.SettingsFlag"); const SettingsFlag = sdk.getComponent("views.elements.SettingsFlag");
return settingIds.filter(SettingsStore.isEnabled).map(i => { return settingIds.filter(SettingsStore.isEnabled).map(i => {
return <SettingsFlag key={i} name={i} level={SettingLevel.ACCOUNT} />; return <SettingsFlag key={i} name={i} level={SettingLevel.ACCOUNT} />;
@ -185,7 +185,7 @@ export default class PreferencesUserSettingsTab extends React.Component<{}, ISta
if (this.state.autoLaunchSupported) { if (this.state.autoLaunchSupported) {
autoLaunchOption = <LabelledToggleSwitch autoLaunchOption = <LabelledToggleSwitch
value={this.state.autoLaunch} value={this.state.autoLaunch}
onChange={this._onAutoLaunchChange} onChange={this.onAutoLaunchChange}
label={_t('Start automatically after system login')} />; label={_t('Start automatically after system login')} />;
} }
@ -193,7 +193,7 @@ export default class PreferencesUserSettingsTab extends React.Component<{}, ISta
if (this.state.warnBeforeExitSupported) { if (this.state.warnBeforeExitSupported) {
warnBeforeExitOption = <LabelledToggleSwitch warnBeforeExitOption = <LabelledToggleSwitch
value={this.state.warnBeforeExit} value={this.state.warnBeforeExit}
onChange={this._onWarnBeforeExitChange} onChange={this.onWarnBeforeExitChange}
label={_t('Warn before quitting')} />; label={_t('Warn before quitting')} />;
} }
@ -201,7 +201,7 @@ export default class PreferencesUserSettingsTab extends React.Component<{}, ISta
if (this.state.alwaysShowMenuBarSupported) { if (this.state.alwaysShowMenuBarSupported) {
autoHideMenuOption = <LabelledToggleSwitch autoHideMenuOption = <LabelledToggleSwitch
value={this.state.alwaysShowMenuBar} value={this.state.alwaysShowMenuBar}
onChange={this._onAlwaysShowMenuBarChange} onChange={this.onAlwaysShowMenuBarChange}
label={_t('Always show the window menu bar')} />; label={_t('Always show the window menu bar')} />;
} }
@ -209,7 +209,7 @@ export default class PreferencesUserSettingsTab extends React.Component<{}, ISta
if (this.state.minimizeToTraySupported) { if (this.state.minimizeToTraySupported) {
minimizeToTrayOption = <LabelledToggleSwitch minimizeToTrayOption = <LabelledToggleSwitch
value={this.state.minimizeToTray} value={this.state.minimizeToTray}
onChange={this._onMinimizeToTrayChange} onChange={this.onMinimizeToTrayChange}
label={_t('Show tray icon and minimize window to it on close')} />; label={_t('Show tray icon and minimize window to it on close')} />;
} }
@ -219,22 +219,22 @@ export default class PreferencesUserSettingsTab extends React.Component<{}, ISta
<div className="mx_SettingsTab_section"> <div className="mx_SettingsTab_section">
<span className="mx_SettingsTab_subheading">{_t("Room list")}</span> <span className="mx_SettingsTab_subheading">{_t("Room list")}</span>
{this._renderGroup(PreferencesUserSettingsTab.ROOM_LIST_SETTINGS)} {this.renderGroup(PreferencesUserSettingsTab.ROOM_LIST_SETTINGS)}
</div> </div>
<div className="mx_SettingsTab_section"> <div className="mx_SettingsTab_section">
<span className="mx_SettingsTab_subheading">{_t("Composer")}</span> <span className="mx_SettingsTab_subheading">{_t("Composer")}</span>
{this._renderGroup(PreferencesUserSettingsTab.COMPOSER_SETTINGS)} {this.renderGroup(PreferencesUserSettingsTab.COMPOSER_SETTINGS)}
</div> </div>
<div className="mx_SettingsTab_section"> <div className="mx_SettingsTab_section">
<span className="mx_SettingsTab_subheading">{_t("Timeline")}</span> <span className="mx_SettingsTab_subheading">{_t("Timeline")}</span>
{this._renderGroup(PreferencesUserSettingsTab.TIMELINE_SETTINGS)} {this.renderGroup(PreferencesUserSettingsTab.TIMELINE_SETTINGS)}
</div> </div>
<div className="mx_SettingsTab_section"> <div className="mx_SettingsTab_section">
<span className="mx_SettingsTab_subheading">{_t("General")}</span> <span className="mx_SettingsTab_subheading">{_t("General")}</span>
{this._renderGroup(PreferencesUserSettingsTab.GENERAL_SETTINGS)} {this.renderGroup(PreferencesUserSettingsTab.GENERAL_SETTINGS)}
{minimizeToTrayOption} {minimizeToTrayOption}
{autoHideMenuOption} {autoHideMenuOption}
{autoLaunchOption} {autoLaunchOption}
@ -243,17 +243,17 @@ export default class PreferencesUserSettingsTab extends React.Component<{}, ISta
label={_t('Autocomplete delay (ms)')} label={_t('Autocomplete delay (ms)')}
type='number' type='number'
value={this.state.autocompleteDelay} value={this.state.autocompleteDelay}
onChange={this._onAutocompleteDelayChange} /> onChange={this.onAutocompleteDelayChange} />
<Field <Field
label={_t('Read Marker lifetime (ms)')} label={_t('Read Marker lifetime (ms)')}
type='number' type='number'
value={this.state.readMarkerInViewThresholdMs} value={this.state.readMarkerInViewThresholdMs}
onChange={this._onReadMarkerInViewThresholdMs} /> onChange={this.onReadMarkerInViewThresholdMs} />
<Field <Field
label={_t('Read Marker off-screen lifetime (ms)')} label={_t('Read Marker off-screen lifetime (ms)')}
type='number' type='number'
value={this.state.readMarkerOutOfViewThresholdMs} value={this.state.readMarkerOutOfViewThresholdMs}
onChange={this._onReadMarkerOutOfViewThresholdMs} /> onChange={this.onReadMarkerOutOfViewThresholdMs} />
</div> </div>
</div> </div>
); );

View File

@ -25,7 +25,7 @@ const TYPING_SERVER_TIMEOUT = 30000;
* Tracks typing state for users. * Tracks typing state for users.
*/ */
export default class TypingStore { export default class TypingStore {
private _typingStates: { private typingStates: {
[roomId: string]: { [roomId: string]: {
isTyping: boolean, isTyping: boolean,
userTimer: Timer, userTimer: Timer,
@ -49,7 +49,7 @@ export default class TypingStore {
* MatrixClientPeg client changes. * MatrixClientPeg client changes.
*/ */
reset() { reset() {
this._typingStates = { this.typingStates = {
// "roomId": { // "roomId": {
// isTyping: bool, // Whether the user is typing or not // isTyping: bool, // Whether the user is typing or not
// userTimer: Timer, // Local timeout for "user has stopped typing" // userTimer: Timer, // Local timeout for "user has stopped typing"
@ -67,14 +67,14 @@ export default class TypingStore {
if (!SettingsStore.getValue('sendTypingNotifications')) return; if (!SettingsStore.getValue('sendTypingNotifications')) return;
if (SettingsStore.getValue('lowBandwidth')) return; if (SettingsStore.getValue('lowBandwidth')) return;
let currentTyping = this._typingStates[roomId]; let currentTyping = this.typingStates[roomId];
if ((!isTyping && !currentTyping) || (currentTyping && currentTyping.isTyping === isTyping)) { if ((!isTyping && !currentTyping) || (currentTyping && currentTyping.isTyping === isTyping)) {
// No change in state, so don't do anything. We'll let the timer run its course. // No change in state, so don't do anything. We'll let the timer run its course.
return; return;
} }
if (!currentTyping) { if (!currentTyping) {
currentTyping = this._typingStates[roomId] = { currentTyping = this.typingStates[roomId] = {
isTyping: isTyping, isTyping: isTyping,
serverTimer: new Timer(TYPING_SERVER_TIMEOUT), serverTimer: new Timer(TYPING_SERVER_TIMEOUT),
userTimer: new Timer(TYPING_USER_TIMEOUT), userTimer: new Timer(TYPING_USER_TIMEOUT),
@ -86,7 +86,7 @@ export default class TypingStore {
if (isTyping) { if (isTyping) {
if (!currentTyping.serverTimer.isRunning()) { if (!currentTyping.serverTimer.isRunning()) {
currentTyping.serverTimer.restart().finished().then(() => { currentTyping.serverTimer.restart().finished().then(() => {
const currentTyping = this._typingStates[roomId]; const currentTyping = this.typingStates[roomId];
if (currentTyping) currentTyping.isTyping = false; if (currentTyping) currentTyping.isTyping = false;
// The server will (should) time us out on typing, so we don't // The server will (should) time us out on typing, so we don't

View File

@ -23,7 +23,7 @@ import {WidgetType} from "../widgets/WidgetType";
* proxying through state from the js-sdk. * proxying through state from the js-sdk.
*/ */
class WidgetEchoStore extends EventEmitter { class WidgetEchoStore extends EventEmitter {
private _roomWidgetEcho: { private roomWidgetEcho: {
[roomId: string]: { [roomId: string]: {
[widgetId: string]: IWidget, [widgetId: string]: IWidget,
}, },
@ -32,7 +32,7 @@ class WidgetEchoStore extends EventEmitter {
constructor() { constructor() {
super(); super();
this._roomWidgetEcho = { this.roomWidgetEcho = {
// Map as below. Object is the content of the widget state event, // Map as below. Object is the content of the widget state event,
// so for widgets that have been deleted locally, the object is empty. // so for widgets that have been deleted locally, the object is empty.
// roomId: { // roomId: {
@ -55,7 +55,7 @@ class WidgetEchoStore extends EventEmitter {
getEchoedRoomWidgets(roomId, currentRoomWidgets) { getEchoedRoomWidgets(roomId, currentRoomWidgets) {
const echoedWidgets = []; const echoedWidgets = [];
const roomEchoState = Object.assign({}, this._roomWidgetEcho[roomId]); const roomEchoState = Object.assign({}, this.roomWidgetEcho[roomId]);
for (const w of currentRoomWidgets) { for (const w of currentRoomWidgets) {
const widgetId = w.getStateKey(); const widgetId = w.getStateKey();
@ -72,7 +72,7 @@ class WidgetEchoStore extends EventEmitter {
} }
roomHasPendingWidgetsOfType(roomId, currentRoomWidgets, type?: WidgetType) { roomHasPendingWidgetsOfType(roomId, currentRoomWidgets, type?: WidgetType) {
const roomEchoState = Object.assign({}, this._roomWidgetEcho[roomId]); const roomEchoState = Object.assign({}, this.roomWidgetEcho[roomId]);
// any widget IDs that are already in the room are not pending, so // any widget IDs that are already in the room are not pending, so
// echoes for them don't count as pending. // echoes for them don't count as pending.
@ -96,15 +96,15 @@ class WidgetEchoStore extends EventEmitter {
} }
setRoomWidgetEcho(roomId: string, widgetId: string, state: IWidget) { setRoomWidgetEcho(roomId: string, widgetId: string, state: IWidget) {
if (this._roomWidgetEcho[roomId] === undefined) this._roomWidgetEcho[roomId] = {}; if (this.roomWidgetEcho[roomId] === undefined) this.roomWidgetEcho[roomId] = {};
this._roomWidgetEcho[roomId][widgetId] = state; this.roomWidgetEcho[roomId][widgetId] = state;
this.emit('update', roomId, widgetId); this.emit('update', roomId, widgetId);
} }
removeRoomWidgetEcho(roomId, widgetId) { removeRoomWidgetEcho(roomId, widgetId) {
delete this._roomWidgetEcho[roomId][widgetId]; delete this.roomWidgetEcho[roomId][widgetId];
if (Object.keys(this._roomWidgetEcho[roomId]).length === 0) delete this._roomWidgetEcho[roomId]; if (Object.keys(this.roomWidgetEcho[roomId]).length === 0) delete this.roomWidgetEcho[roomId];
this.emit('update', roomId, widgetId); this.emit('update', roomId, widgetId);
} }
} }

View File

@ -26,51 +26,51 @@ Once a timer is finished or aborted, it can't be started again
a new one through `clone()` or `cloneIfRun()`. a new one through `clone()` or `cloneIfRun()`.
*/ */
export default class Timer { export default class Timer {
private _timeout: number; private timeout: number;
private _timerHandle: NodeJS.Timeout; private timerHandle: NodeJS.Timeout;
private _startTs: number; private startTs: number;
private _promise: Promise<void>; private promise: Promise<void>;
private _resolve: () => void; private resolve: () => void;
private _reject: (Error) => void; private reject: (Error) => void;
constructor(timeout) { constructor(timeout) {
this._timeout = timeout; this.timeout = timeout;
this._onTimeout = this._onTimeout.bind(this); this.onTimeout = this.onTimeout.bind(this);
this._setNotStarted(); this.setNotStarted();
} }
_setNotStarted() { private setNotStarted() {
this._timerHandle = null; this.timerHandle = null;
this._startTs = null; this.startTs = null;
this._promise = new Promise<void>((resolve, reject) => { this.promise = new Promise<void>((resolve, reject) => {
this._resolve = resolve; this.resolve = resolve;
this._reject = reject; this.reject = reject;
}).finally(() => { }).finally(() => {
this._timerHandle = null; this.timerHandle = null;
}); });
} }
_onTimeout() { private onTimeout() {
const now = Date.now(); const now = Date.now();
const elapsed = now - this._startTs; const elapsed = now - this.startTs;
if (elapsed >= this._timeout) { if (elapsed >= this.timeout) {
this._resolve(); this.resolve();
this._setNotStarted(); this.setNotStarted();
} else { } else {
const delta = this._timeout - elapsed; const delta = this.timeout - elapsed;
this._timerHandle = setTimeout(this._onTimeout, delta); this.timerHandle = setTimeout(this.onTimeout, delta);
} }
} }
changeTimeout(timeout) { changeTimeout(timeout) {
if (timeout === this._timeout) { if (timeout === this.timeout) {
return; return;
} }
const isSmallerTimeout = timeout < this._timeout; const isSmallerTimeout = timeout < this.timeout;
this._timeout = timeout; this.timeout = timeout;
if (this.isRunning() && isSmallerTimeout) { if (this.isRunning() && isSmallerTimeout) {
clearTimeout(this._timerHandle); clearTimeout(this.timerHandle);
this._onTimeout(); this.onTimeout();
} }
} }
@ -80,8 +80,8 @@ export default class Timer {
*/ */
start() { start() {
if (!this.isRunning()) { if (!this.isRunning()) {
this._startTs = Date.now(); this.startTs = Date.now();
this._timerHandle = setTimeout(this._onTimeout, this._timeout); this.timerHandle = setTimeout(this.onTimeout, this.timeout);
} }
return this; return this;
} }
@ -96,7 +96,7 @@ export default class Timer {
// can be called in fast succession, // can be called in fast succession,
// instead just take note and compare // instead just take note and compare
// when the already running timeout expires // when the already running timeout expires
this._startTs = Date.now(); this.startTs = Date.now();
return this; return this;
} else { } else {
return this.start(); return this.start();
@ -110,9 +110,9 @@ export default class Timer {
*/ */
abort() { abort() {
if (this.isRunning()) { if (this.isRunning()) {
clearTimeout(this._timerHandle); clearTimeout(this.timerHandle);
this._reject(new Error("Timer was aborted.")); this.reject(new Error("Timer was aborted."));
this._setNotStarted(); this.setNotStarted();
} }
return this; return this;
} }
@ -123,10 +123,10 @@ export default class Timer {
*@return {Promise} *@return {Promise}
*/ */
finished() { finished() {
return this._promise; return this.promise;
} }
isRunning() { isRunning() {
return this._timerHandle !== null; return this.timerHandle !== null;
} }
} }

View File

@ -20,31 +20,31 @@ import PermalinkConstructor, {PermalinkParts} from "./PermalinkConstructor";
* Generates permalinks that self-reference the running webapp * Generates permalinks that self-reference the running webapp
*/ */
export default class ElementPermalinkConstructor extends PermalinkConstructor { export default class ElementPermalinkConstructor extends PermalinkConstructor {
private _elementUrl: string; private elementUrl: string;
constructor(elementUrl: string) { constructor(elementUrl: string) {
super(); super();
this._elementUrl = elementUrl; this.elementUrl = elementUrl;
if (!this._elementUrl.startsWith("http:") && !this._elementUrl.startsWith("https:")) { if (!this.elementUrl.startsWith("http:") && !this.elementUrl.startsWith("https:")) {
throw new Error("Element prefix URL does not appear to be an HTTP(S) URL"); throw new Error("Element prefix URL does not appear to be an HTTP(S) URL");
} }
} }
forEvent(roomId: string, eventId: string, serverCandidates: string[]): string { forEvent(roomId: string, eventId: string, serverCandidates: string[]): string {
return `${this._elementUrl}/#/room/${roomId}/${eventId}${this.encodeServerCandidates(serverCandidates)}`; return `${this.elementUrl}/#/room/${roomId}/${eventId}${this.encodeServerCandidates(serverCandidates)}`;
} }
forRoom(roomIdOrAlias: string, serverCandidates?: string[]): string { forRoom(roomIdOrAlias: string, serverCandidates?: string[]): string {
return `${this._elementUrl}/#/room/${roomIdOrAlias}${this.encodeServerCandidates(serverCandidates)}`; return `${this.elementUrl}/#/room/${roomIdOrAlias}${this.encodeServerCandidates(serverCandidates)}`;
} }
forUser(userId: string): string { forUser(userId: string): string {
return `${this._elementUrl}/#/user/${userId}`; return `${this.elementUrl}/#/user/${userId}`;
} }
forGroup(groupId: string): string { forGroup(groupId: string): string {
return `${this._elementUrl}/#/group/${groupId}`; return `${this.elementUrl}/#/group/${groupId}`;
} }
forEntity(entityId: string): string { forEntity(entityId: string): string {
@ -58,7 +58,7 @@ export default class ElementPermalinkConstructor extends PermalinkConstructor {
} }
isPermalinkHost(testHost: string): boolean { isPermalinkHost(testHost: string): boolean {
const parsedUrl = new URL(this._elementUrl); const parsedUrl = new URL(this.elementUrl);
return testHost === (parsedUrl.host || parsedUrl.hostname); // one of the hosts should match return testHost === (parsedUrl.host || parsedUrl.hostname); // one of the hosts should match
} }
@ -71,11 +71,11 @@ export default class ElementPermalinkConstructor extends PermalinkConstructor {
// https://github.com/turt2live/matrix-js-bot-sdk/blob/7c4665c9a25c2c8e0fe4e509f2616505b5b66a1c/src/Permalinks.ts#L33-L61 // https://github.com/turt2live/matrix-js-bot-sdk/blob/7c4665c9a25c2c8e0fe4e509f2616505b5b66a1c/src/Permalinks.ts#L33-L61
// Adapted for Element's URL format // Adapted for Element's URL format
parsePermalink(fullUrl: string): PermalinkParts { parsePermalink(fullUrl: string): PermalinkParts {
if (!fullUrl || !fullUrl.startsWith(this._elementUrl)) { if (!fullUrl || !fullUrl.startsWith(this.elementUrl)) {
throw new Error("Does not appear to be a permalink"); throw new Error("Does not appear to be a permalink");
} }
const parts = fullUrl.substring(`${this._elementUrl}/#/`.length); const parts = fullUrl.substring(`${this.elementUrl}/#/`.length);
return ElementPermalinkConstructor.parseAppRoute(parts); return ElementPermalinkConstructor.parseAppRoute(parts);
} }

View File

@ -74,29 +74,29 @@ const MAX_SERVER_CANDIDATES = 3;
// the list and magically have the link work. // the list and magically have the link work.
export class RoomPermalinkCreator { export class RoomPermalinkCreator {
private _room: Room; private room: Room;
private _roomId: string; private roomId: string;
private _highestPlUserId: string; private highestPlUserId: string;
private _populationMap: { [serverName: string]: number }; private populationMap: { [serverName: string]: number };
private _bannedHostsRegexps: RegExp[]; private bannedHostsRegexps: RegExp[];
private _allowedHostsRegexps: RegExp[]; private allowedHostsRegexps: RegExp[];
private _serverCandidates: string[]; private _serverCandidates: string[];
private _started: boolean; private started: boolean;
// We support being given a roomId as a fallback in the event the `room` object // We support being given a roomId as a fallback in the event the `room` object
// doesn't exist or is not healthy for us to rely on. For example, loading a // doesn't exist or is not healthy for us to rely on. For example, loading a
// permalink to a room which the MatrixClient doesn't know about. // permalink to a room which the MatrixClient doesn't know about.
constructor(room: Room, roomId: string = null) { constructor(room: Room, roomId: string = null) {
this._room = room; this.room = room;
this._roomId = room ? room.roomId : roomId; this.roomId = room ? room.roomId : roomId;
this._highestPlUserId = null; this.highestPlUserId = null;
this._populationMap = null; this.populationMap = null;
this._bannedHostsRegexps = null; this.bannedHostsRegexps = null;
this._allowedHostsRegexps = null; this.allowedHostsRegexps = null;
this._serverCandidates = null; this._serverCandidates = null;
this._started = false; this.started = false;
if (!this._roomId) { if (!this.roomId) {
throw new Error("Failed to resolve a roomId for the permalink creator to use"); throw new Error("Failed to resolve a roomId for the permalink creator to use");
} }
@ -105,7 +105,7 @@ export class RoomPermalinkCreator {
} }
load() { load() {
if (!this._room || !this._room.currentState) { if (!this.room || !this.room.currentState) {
// Under rare and unknown circumstances it is possible to have a room with no // Under rare and unknown circumstances it is possible to have a room with no
// currentState, at least potentially at the early stages of joining a room. // currentState, at least potentially at the early stages of joining a room.
// To avoid breaking everything, we'll just warn rather than throw as well as // To avoid breaking everything, we'll just warn rather than throw as well as
@ -113,23 +113,23 @@ export class RoomPermalinkCreator {
console.warn("Tried to load a permalink creator with no room state"); console.warn("Tried to load a permalink creator with no room state");
return; return;
} }
this._updateAllowedServers(); this.updateAllowedServers();
this._updateHighestPlUser(); this.updateHighestPlUser();
this._updatePopulationMap(); this.updatePopulationMap();
this._updateServerCandidates(); this.updateServerCandidates();
} }
start() { start() {
this.load(); this.load();
this._room.on("RoomMember.membership", this.onMembership); this.room.on("RoomMember.membership", this.onMembership);
this._room.on("RoomState.events", this.onRoomState); this.room.on("RoomState.events", this.onRoomState);
this._started = true; this.started = true;
} }
stop() { stop() {
this._room.removeListener("RoomMember.membership", this.onMembership); this.room.removeListener("RoomMember.membership", this.onMembership);
this._room.removeListener("RoomState.events", this.onRoomState); this.room.removeListener("RoomState.events", this.onRoomState);
this._started = false; this.started = false;
} }
get serverCandidates() { get serverCandidates() {
@ -137,44 +137,44 @@ export class RoomPermalinkCreator {
} }
isStarted() { isStarted() {
return this._started; return this.started;
} }
forEvent(eventId) { forEvent(eventId) {
return getPermalinkConstructor().forEvent(this._roomId, eventId, this._serverCandidates); return getPermalinkConstructor().forEvent(this.roomId, eventId, this._serverCandidates);
} }
forShareableRoom() { forShareableRoom() {
if (this._room) { if (this.room) {
// Prefer to use canonical alias for permalink if possible // Prefer to use canonical alias for permalink if possible
const alias = this._room.getCanonicalAlias(); const alias = this.room.getCanonicalAlias();
if (alias) { if (alias) {
return getPermalinkConstructor().forRoom(alias, this._serverCandidates); return getPermalinkConstructor().forRoom(alias, this._serverCandidates);
} }
} }
return getPermalinkConstructor().forRoom(this._roomId, this._serverCandidates); return getPermalinkConstructor().forRoom(this.roomId, this._serverCandidates);
} }
forRoom() { forRoom() {
return getPermalinkConstructor().forRoom(this._roomId, this._serverCandidates); return getPermalinkConstructor().forRoom(this.roomId, this._serverCandidates);
} }
onRoomState(event) { private onRoomState(event) {
switch (event.getType()) { switch (event.getType()) {
case "m.room.server_acl": case "m.room.server_acl":
this._updateAllowedServers(); this.updateAllowedServers();
this._updateHighestPlUser(); this.updateHighestPlUser();
this._updatePopulationMap(); this.updatePopulationMap();
this._updateServerCandidates(); this.updateServerCandidates();
return; return;
case "m.room.power_levels": case "m.room.power_levels":
this._updateHighestPlUser(); this.updateHighestPlUser();
this._updateServerCandidates(); this.updateServerCandidates();
return; return;
} }
} }
onMembership(evt, member, oldMembership) { private onMembership(evt, member, oldMembership) {
const userId = member.userId; const userId = member.userId;
const membership = member.membership; const membership = member.membership;
const serverName = getServerName(userId); const serverName = getServerName(userId);
@ -182,17 +182,17 @@ export class RoomPermalinkCreator {
const hasLeft = oldMembership === "join" && membership !== "join"; const hasLeft = oldMembership === "join" && membership !== "join";
if (hasLeft) { if (hasLeft) {
this._populationMap[serverName]--; this.populationMap[serverName]--;
} else if (hasJoined) { } else if (hasJoined) {
this._populationMap[serverName]++; this.populationMap[serverName]++;
} }
this._updateHighestPlUser(); this.updateHighestPlUser();
this._updateServerCandidates(); this.updateServerCandidates();
} }
_updateHighestPlUser() { private updateHighestPlUser() {
const plEvent = this._room.currentState.getStateEvents("m.room.power_levels", ""); const plEvent = this.room.currentState.getStateEvents("m.room.power_levels", "");
if (plEvent) { if (plEvent) {
const content = plEvent.getContent(); const content = plEvent.getContent();
if (content) { if (content) {
@ -200,14 +200,14 @@ export class RoomPermalinkCreator {
if (users) { if (users) {
const entries = Object.entries(users); const entries = Object.entries(users);
const allowedEntries = entries.filter(([userId]) => { const allowedEntries = entries.filter(([userId]) => {
const member = this._room.getMember(userId); const member = this.room.getMember(userId);
if (!member || member.membership !== "join") { if (!member || member.membership !== "join") {
return false; return false;
} }
const serverName = getServerName(userId); const serverName = getServerName(userId);
return !isHostnameIpAddress(serverName) && return !isHostnameIpAddress(serverName) &&
!isHostInRegex(serverName, this._bannedHostsRegexps) && !isHostInRegex(serverName, this.bannedHostsRegexps) &&
isHostInRegex(serverName, this._allowedHostsRegexps); isHostInRegex(serverName, this.allowedHostsRegexps);
}); });
const maxEntry = allowedEntries.reduce((max, entry) => { const maxEntry = allowedEntries.reduce((max, entry) => {
return (entry[1] > max[1]) ? entry : max; return (entry[1] > max[1]) ? entry : max;
@ -215,20 +215,20 @@ export class RoomPermalinkCreator {
const [userId, powerLevel] = maxEntry; const [userId, powerLevel] = maxEntry;
// object wasn't empty, and max entry wasn't a demotion from the default // object wasn't empty, and max entry wasn't a demotion from the default
if (userId !== null && powerLevel >= 50) { if (userId !== null && powerLevel >= 50) {
this._highestPlUserId = userId; this.highestPlUserId = userId;
return; return;
} }
} }
} }
} }
this._highestPlUserId = null; this.highestPlUserId = null;
} }
_updateAllowedServers() { private updateAllowedServers() {
const bannedHostsRegexps = []; const bannedHostsRegexps = [];
let allowedHostsRegexps = [new RegExp(".*")]; // default allow everyone let allowedHostsRegexps = [new RegExp(".*")]; // default allow everyone
if (this._room.currentState) { if (this.room.currentState) {
const aclEvent = this._room.currentState.getStateEvents("m.room.server_acl", ""); const aclEvent = this.room.currentState.getStateEvents("m.room.server_acl", "");
if (aclEvent && aclEvent.getContent()) { if (aclEvent && aclEvent.getContent()) {
const getRegex = (hostname) => new RegExp("^" + utils.globToRegexp(hostname, false) + "$"); const getRegex = (hostname) => new RegExp("^" + utils.globToRegexp(hostname, false) + "$");
@ -240,35 +240,35 @@ export class RoomPermalinkCreator {
allowed.forEach(h => allowedHostsRegexps.push(getRegex(h))); allowed.forEach(h => allowedHostsRegexps.push(getRegex(h)));
} }
} }
this._bannedHostsRegexps = bannedHostsRegexps; this.bannedHostsRegexps = bannedHostsRegexps;
this._allowedHostsRegexps = allowedHostsRegexps; this.allowedHostsRegexps = allowedHostsRegexps;
} }
_updatePopulationMap() { private updatePopulationMap() {
const populationMap: { [server: string]: number } = {}; const populationMap: { [server: string]: number } = {};
for (const member of this._room.getJoinedMembers()) { for (const member of this.room.getJoinedMembers()) {
const serverName = getServerName(member.userId); const serverName = getServerName(member.userId);
if (!populationMap[serverName]) { if (!populationMap[serverName]) {
populationMap[serverName] = 0; populationMap[serverName] = 0;
} }
populationMap[serverName]++; populationMap[serverName]++;
} }
this._populationMap = populationMap; this.populationMap = populationMap;
} }
_updateServerCandidates() { private updateServerCandidates() {
let candidates = []; let candidates = [];
if (this._highestPlUserId) { if (this.highestPlUserId) {
candidates.push(getServerName(this._highestPlUserId)); candidates.push(getServerName(this.highestPlUserId));
} }
const serversByPopulation = Object.keys(this._populationMap) const serversByPopulation = Object.keys(this.populationMap)
.sort((a, b) => this._populationMap[b] - this._populationMap[a]) .sort((a, b) => this.populationMap[b] - this.populationMap[a])
.filter(a => { .filter(a => {
return !candidates.includes(a) && return !candidates.includes(a) &&
!isHostnameIpAddress(a) && !isHostnameIpAddress(a) &&
!isHostInRegex(a, this._bannedHostsRegexps) && !isHostInRegex(a, this.bannedHostsRegexps) &&
isHostInRegex(a, this._allowedHostsRegexps); isHostInRegex(a, this.allowedHostsRegexps);
}); });
const remainingServers = serversByPopulation.slice(0, MAX_SERVER_CANDIDATES - candidates.length); const remainingServers = serversByPopulation.slice(0, MAX_SERVER_CANDIDATES - candidates.length);