Merge pull request #5157 from matrix-org/t3chguy/crc1

Remove create-react-class
This commit is contained in:
Michael Telatynski 2020-09-03 17:21:58 +01:00 committed by GitHub
commit e624ce11b4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
112 changed files with 3113 additions and 3578 deletions

View file

@ -16,14 +16,12 @@ limitations under the License.
import React from 'react';
import PropTypes from 'prop-types';
import createReactClass from 'create-react-class';
import {MatrixClientPeg} from "../../../MatrixClientPeg";
import * as sdk from '../../../index';
import { _t } from '../../../languageHandler';
export default createReactClass({
displayName: 'ChangeAvatar',
propTypes: {
export default class ChangeAvatar extends React.Component {
static propTypes = {
initialAvatarUrl: PropTypes.string,
room: PropTypes.object,
// if false, you need to call changeAvatar.onFileSelected yourself.
@ -31,36 +29,36 @@ export default createReactClass({
width: PropTypes.number,
height: PropTypes.number,
className: PropTypes.string,
},
};
Phases: {
static Phases = {
Display: "display",
Uploading: "uploading",
Error: "error",
},
};
getDefaultProps: function() {
return {
showUploadSection: true,
className: "",
width: 80,
height: 80,
};
},
static defaultProps = {
showUploadSection: true,
className: "",
width: 80,
height: 80,
};
getInitialState: function() {
return {
constructor(props) {
super(props);
this.state = {
avatarUrl: this.props.initialAvatarUrl,
phase: this.Phases.Display,
phase: ChangeAvatar.Phases.Display,
};
},
}
componentDidMount: function() {
componentDidMount() {
MatrixClientPeg.get().on("RoomState.events", this.onRoomStateEvents);
},
}
// TODO: [REACT-WARNING] Replace with appropriate lifecycle event
UNSAFE_componentWillReceiveProps: function(newProps) {
UNSAFE_componentWillReceiveProps(newProps) {
if (this.avatarSet) {
// don't clobber what the user has just set
return;
@ -68,15 +66,15 @@ export default createReactClass({
this.setState({
avatarUrl: newProps.initialAvatarUrl,
});
},
}
componentWillUnmount: function() {
componentWillUnmount() {
if (MatrixClientPeg.get()) {
MatrixClientPeg.get().removeListener("RoomState.events", this.onRoomStateEvents);
}
},
}
onRoomStateEvents: function(ev) {
onRoomStateEvents = (ev) => {
if (!this.props.room) {
return;
}
@ -90,13 +88,13 @@ export default createReactClass({
this.avatarSet = false;
this.setState({}); // force update
}
},
};
setAvatarFromFile: function(file) {
setAvatarFromFile(file) {
let newUrl = null;
this.setState({
phase: this.Phases.Uploading,
phase: ChangeAvatar.Phases.Uploading,
});
const self = this;
const httpPromise = MatrixClientPeg.get().uploadContent(file).then(function(url) {
@ -115,31 +113,31 @@ export default createReactClass({
httpPromise.then(function() {
self.setState({
phase: self.Phases.Display,
phase: ChangeAvatar.Phases.Display,
avatarUrl: MatrixClientPeg.get().mxcUrlToHttp(newUrl),
});
}, function(error) {
self.setState({
phase: self.Phases.Error,
phase: ChangeAvatar.Phases.Error,
});
self.onError(error);
});
return httpPromise;
},
}
onFileSelected: function(ev) {
onFileSelected = (ev) => {
this.avatarSet = true;
return this.setAvatarFromFile(ev.target.files[0]);
},
};
onError: function(error) {
onError = (error) => {
this.setState({
errorText: _t("Failed to upload profile picture!"),
});
},
};
render: function() {
render() {
let avatarImg;
// Having just set an avatar we just display that since it will take a little
// time to propagate through to the RoomAvatar.
@ -165,8 +163,8 @@ export default createReactClass({
}
switch (this.state.phase) {
case this.Phases.Display:
case this.Phases.Error:
case ChangeAvatar.Phases.Display:
case ChangeAvatar.Phases.Error:
return (
<div>
<div className={this.props.className}>
@ -175,11 +173,11 @@ export default createReactClass({
{ uploadSection }
</div>
);
case this.Phases.Uploading:
case ChangeAvatar.Phases.Uploading:
var Loader = sdk.getComponent("elements.Spinner");
return (
<Loader />
);
}
},
});
}
}

View file

@ -17,15 +17,12 @@ limitations under the License.
*/
import React from 'react';
import createReactClass from 'create-react-class';
import * as sdk from '../../../index';
import {MatrixClientPeg} from '../../../MatrixClientPeg';
import { _t } from '../../../languageHandler';
export default createReactClass({
displayName: 'ChangeDisplayName',
_getDisplayName: async function() {
export default class ChangeDisplayName extends React.Component {
_getDisplayName = async () => {
const cli = MatrixClientPeg.get();
try {
const res = await cli.getProfileInfo(cli.getUserId());
@ -33,16 +30,16 @@ export default createReactClass({
} catch (e) {
throw new Error("Failed to fetch display name");
}
},
};
_changeDisplayName: function(newDisplayname) {
_changeDisplayName = (newDisplayname) => {
const cli = MatrixClientPeg.get();
return cli.setDisplayName(newDisplayname).catch(function(e) {
throw new Error("Failed to set display name", e);
});
},
};
render: function() {
render() {
const EditableTextContainer = sdk.getComponent('elements.EditableTextContainer');
return (
<EditableTextContainer
@ -51,5 +48,5 @@ export default createReactClass({
blurToSubmit={true}
onSubmit={this._changeDisplayName} />
);
},
});
}
}

View file

@ -18,7 +18,6 @@ limitations under the License.
import Field from "../elements/Field";
import React from 'react';
import PropTypes from 'prop-types';
import createReactClass from 'create-react-class';
import {MatrixClientPeg} from "../../../MatrixClientPeg";
import dis from "../../../dispatcher/dispatcher";
import AccessibleButton from '../elements/AccessibleButton';
@ -28,10 +27,8 @@ import Modal from "../../../Modal";
import sessionStore from '../../../stores/SessionStore';
export default createReactClass({
displayName: 'ChangePassword',
propTypes: {
export default class ChangePassword extends React.Component {
static propTypes = {
onFinished: PropTypes.func,
onError: PropTypes.func,
onCheckPassword: PropTypes.func,
@ -41,65 +38,61 @@ export default createReactClass({
confirm: PropTypes.bool,
// Whether to autoFocus the new password input
autoFocusNewPasswordInput: PropTypes.bool,
},
};
Phases: {
static Phases = {
Edit: "edit",
Uploading: "uploading",
Error: "error",
},
};
getDefaultProps: function() {
return {
onFinished: function() {},
onError: function() {},
onCheckPassword: function(oldPass, newPass, confirmPass) {
if (newPass !== confirmPass) {
return {
error: _t("New passwords don't match"),
};
} else if (!newPass || newPass.length === 0) {
return {
error: _t("Passwords can't be empty"),
};
}
},
confirm: true,
};
},
static defaultProps = {
onFinished() {},
onError() {},
onCheckPassword(oldPass, newPass, confirmPass) {
if (newPass !== confirmPass) {
return {
error: _t("New passwords don't match"),
};
} else if (!newPass || newPass.length === 0) {
return {
error: _t("Passwords can't be empty"),
};
}
},
confirm: true,
}
getInitialState: function() {
return {
phase: this.Phases.Edit,
cachedPassword: null,
oldPassword: "",
newPassword: "",
newPasswordConfirm: "",
};
},
state = {
phase: ChangePassword.Phases.Edit,
cachedPassword: null,
oldPassword: "",
newPassword: "",
newPasswordConfirm: "",
};
componentDidMount: function() {
componentDidMount() {
this._sessionStore = sessionStore;
this._sessionStoreToken = this._sessionStore.addListener(
this._setStateFromSessionStore,
);
this._setStateFromSessionStore();
},
}
componentWillUnmount: function() {
componentWillUnmount() {
if (this._sessionStoreToken) {
this._sessionStoreToken.remove();
}
},
}
_setStateFromSessionStore: function() {
_setStateFromSessionStore = () => {
this.setState({
cachedPassword: this._sessionStore.getCachedPassword(),
});
},
};
changePassword: function(oldPassword, newPassword) {
changePassword(oldPassword, newPassword) {
const cli = MatrixClientPeg.get();
if (!this.props.confirm) {
@ -136,9 +129,9 @@ export default createReactClass({
}
},
});
},
}
_changePassword: function(cli, oldPassword, newPassword) {
_changePassword(cli, oldPassword, newPassword) {
const authDict = {
type: 'm.login.password',
identifier: {
@ -152,7 +145,7 @@ export default createReactClass({
};
this.setState({
phase: this.Phases.Uploading,
phase: ChangePassword.Phases.Uploading,
});
cli.setPassword(authDict, newPassword).then(() => {
@ -172,51 +165,51 @@ export default createReactClass({
this.props.onError(err);
}).finally(() => {
this.setState({
phase: this.Phases.Edit,
phase: ChangePassword.Phases.Edit,
oldPassword: "",
newPassword: "",
newPasswordConfirm: "",
});
});
},
}
_optionallySetEmail: function() {
_optionallySetEmail() {
// Ask for an email otherwise the user has no way to reset their password
const SetEmailDialog = sdk.getComponent("dialogs.SetEmailDialog");
const modal = Modal.createTrackedDialog('Do you want to set an email address?', '', SetEmailDialog, {
title: _t('Do you want to set an email address?'),
});
return modal.finished.then(([confirmed]) => confirmed);
},
}
_onExportE2eKeysClicked: function() {
_onExportE2eKeysClicked = () => {
Modal.createTrackedDialogAsync('Export E2E Keys', 'Change Password',
import('../../../async-components/views/dialogs/ExportE2eKeysDialog'),
{
matrixClient: MatrixClientPeg.get(),
},
);
},
};
onChangeOldPassword(ev) {
onChangeOldPassword = (ev) => {
this.setState({
oldPassword: ev.target.value,
});
},
};
onChangeNewPassword(ev) {
onChangeNewPassword = (ev) => {
this.setState({
newPassword: ev.target.value,
});
},
};
onChangeNewPasswordConfirm(ev) {
onChangeNewPasswordConfirm = (ev) => {
this.setState({
newPasswordConfirm: ev.target.value,
});
},
};
onClickChange: function(ev) {
onClickChange = (ev) => {
ev.preventDefault();
const oldPassword = this.state.cachedPassword || this.state.oldPassword;
const newPassword = this.state.newPassword;
@ -229,9 +222,9 @@ export default createReactClass({
} else {
this.changePassword(oldPassword, newPassword);
}
},
};
render: function() {
render() {
// TODO: Live validation on `new pw == confirm pw`
const rowClassName = this.props.rowClassName;
@ -252,7 +245,7 @@ export default createReactClass({
}
switch (this.state.phase) {
case this.Phases.Edit:
case ChangePassword.Phases.Edit:
const passwordLabel = this.state.cachedPassword ?
_t('Password') : _t('New Password');
return (
@ -282,7 +275,7 @@ export default createReactClass({
</AccessibleButton>
</form>
);
case this.Phases.Uploading:
case ChangePassword.Phases.Uploading:
var Loader = sdk.getComponent("elements.Spinner");
return (
<div className="mx_Dialog_content">
@ -290,5 +283,5 @@ export default createReactClass({
</div>
);
}
},
});
}
}

View file

@ -16,7 +16,6 @@ limitations under the License.
*/
import React from 'react';
import createReactClass from 'create-react-class';
import * as sdk from '../../../index';
import { _t } from '../../../languageHandler';
import {MatrixClientPeg} from '../../../MatrixClientPeg';
@ -65,46 +64,42 @@ function portLegacyActions(actions) {
}
}
export default createReactClass({
displayName: 'Notifications',
phases: {
export default class Notifications extends React.Component {
static phases = {
LOADING: "LOADING", // The component is loading or sending data to the hs
DISPLAY: "DISPLAY", // The component is ready and display data
ERROR: "ERROR", // There was an error
},
};
getInitialState: function() {
return {
phase: this.phases.LOADING,
masterPushRule: undefined, // The master rule ('.m.rule.master')
vectorPushRules: [], // HS default push rules displayed in Vector UI
vectorContentRules: { // Keyword push rules displayed in Vector UI
vectorState: PushRuleVectorState.ON,
rules: [],
},
externalPushRules: [], // Push rules (except content rule) that have been defined outside Vector UI
externalContentRules: [], // Keyword push rules that have been defined outside Vector UI
threepids: [], // used for email notifications
};
},
state = {
phase: Notifications.phases.LOADING,
masterPushRule: undefined, // The master rule ('.m.rule.master')
vectorPushRules: [], // HS default push rules displayed in Vector UI
vectorContentRules: { // Keyword push rules displayed in Vector UI
vectorState: PushRuleVectorState.ON,
rules: [],
},
externalPushRules: [], // Push rules (except content rule) that have been defined outside Vector UI
externalContentRules: [], // Keyword push rules that have been defined outside Vector UI
threepids: [], // used for email notifications
};
componentDidMount: function() {
componentDidMount() {
this._refreshFromServer();
},
}
onEnableNotificationsChange: function(checked) {
onEnableNotificationsChange = (checked) => {
const self = this;
this.setState({
phase: this.phases.LOADING,
phase: Notifications.phases.LOADING,
});
MatrixClientPeg.get().setPushRuleEnabled('global', self.state.masterPushRule.kind, self.state.masterPushRule.rule_id, !checked).then(function() {
self._refreshFromServer();
});
},
};
onEnableDesktopNotificationsChange: function(checked) {
onEnableDesktopNotificationsChange = (checked) => {
SettingsStore.setValue(
"notificationsEnabled", null,
SettingLevel.DEVICE,
@ -112,9 +107,9 @@ export default createReactClass({
).finally(() => {
this.forceUpdate();
});
},
};
onEnableDesktopNotificationBodyChange: function(checked) {
onEnableDesktopNotificationBodyChange = (checked) => {
SettingsStore.setValue(
"notificationBodyEnabled", null,
SettingLevel.DEVICE,
@ -122,9 +117,9 @@ export default createReactClass({
).finally(() => {
this.forceUpdate();
});
},
};
onEnableAudioNotificationsChange: function(checked) {
onEnableAudioNotificationsChange = (checked) => {
SettingsStore.setValue(
"audioNotificationsEnabled", null,
SettingLevel.DEVICE,
@ -132,7 +127,7 @@ export default createReactClass({
).finally(() => {
this.forceUpdate();
});
},
};
/*
* Returns the email pusher (pusher of type 'email') for a given
@ -140,7 +135,7 @@ export default createReactClass({
* pushers are unique over (app ID, pushkey), there will be at most
* one such pusher.
*/
getEmailPusher: function(pushers, address) {
getEmailPusher(pushers, address) {
if (pushers === undefined) {
return undefined;
}
@ -150,9 +145,9 @@ export default createReactClass({
}
}
return undefined;
},
}
onEnableEmailNotificationsChange: function(address, checked) {
onEnableEmailNotificationsChange = (address, checked) => {
let emailPusherPromise;
if (checked) {
const data = {};
@ -181,9 +176,9 @@ export default createReactClass({
description: _t('An error occurred whilst saving your email notification preferences.'),
});
});
},
};
onNotifStateButtonClicked: function(event) {
onNotifStateButtonClicked = (event) => {
// FIXME: use .bind() rather than className metadata here surely
const vectorRuleId = event.target.className.split("-")[0];
const newPushRuleVectorState = event.target.className.split("-")[1];
@ -196,11 +191,9 @@ export default createReactClass({
this._setPushRuleVectorState(rule, newPushRuleVectorState);
}
}
},
onKeywordsClicked: function(event) {
const self = this;
};
onKeywordsClicked = (event) => {
// Compute the keywords list to display
let keywords = [];
for (const i in this.state.vectorContentRules.rules) {
@ -223,7 +216,7 @@ export default createReactClass({
description: _t('Enter keywords separated by a comma:'),
button: _t('OK'),
value: keywords,
onFinished: function onFinished(should_leave, newValue) {
onFinished: (should_leave, newValue) => {
if (should_leave && newValue !== keywords) {
let newKeywords = newValue.split(',');
for (const i in newKeywords) {
@ -238,25 +231,25 @@ export default createReactClass({
return array;
}, []);
self._setKeywords(newKeywords);
this._setKeywords(newKeywords);
}
},
});
},
};
getRule: function(vectorRuleId) {
getRule(vectorRuleId) {
for (const i in this.state.vectorPushRules) {
const rule = this.state.vectorPushRules[i];
if (rule.vectorRuleId === vectorRuleId) {
return rule;
}
}
},
}
_setPushRuleVectorState: function(rule, newPushRuleVectorState) {
_setPushRuleVectorState(rule, newPushRuleVectorState) {
if (rule && rule.vectorState !== newPushRuleVectorState) {
this.setState({
phase: this.phases.LOADING,
phase: Notifications.phases.LOADING,
});
const self = this;
@ -288,9 +281,9 @@ export default createReactClass({
});
});
}
},
}
_setKeywordsPushRuleVectorState: function(newPushRuleVectorState) {
_setKeywordsPushRuleVectorState(newPushRuleVectorState) {
// Is there really a change?
if (this.state.vectorContentRules.vectorState === newPushRuleVectorState
|| this.state.vectorContentRules.rules.length === 0) {
@ -301,7 +294,7 @@ export default createReactClass({
const cli = MatrixClientPeg.get();
this.setState({
phase: this.phases.LOADING,
phase: Notifications.phases.LOADING,
});
// Update all rules in self.state.vectorContentRules
@ -356,11 +349,11 @@ export default createReactClass({
onFinished: self._refreshFromServer,
});
});
},
}
_setKeywords: function(newKeywords) {
_setKeywords(newKeywords) {
this.setState({
phase: this.phases.LOADING,
phase: Notifications.phases.LOADING,
});
const self = this;
@ -440,19 +433,19 @@ export default createReactClass({
self._refreshFromServer();
}, onError);
}, onError);
},
}
// Create a push rule but disabled
_addDisabledPushRule: function(scope, kind, ruleId, body) {
_addDisabledPushRule(scope, kind, ruleId, body) {
const cli = MatrixClientPeg.get();
return cli.addPushRule(scope, kind, ruleId, body).then(() =>
cli.setPushRuleEnabled(scope, kind, ruleId, false),
);
},
}
// Check if any legacy im.vector rules need to be ported to the new API
// for overriding the actions of default rules.
_portRulesToNewAPI: function(rulesets) {
_portRulesToNewAPI(rulesets) {
const needsUpdate = [];
const cli = MatrixClientPeg.get();
@ -485,9 +478,9 @@ export default createReactClass({
// Otherwise return the rules that we already have.
return rulesets;
}
},
}
_refreshFromServer: function() {
_refreshFromServer = () => {
const self = this;
const pushRulesPromise = MatrixClientPeg.get().getPushRules().then(self._portRulesToNewAPI).then(function(rulesets) {
/// XXX seriously? wtf is this?
@ -636,12 +629,12 @@ export default createReactClass({
Promise.all([pushRulesPromise, pushersPromise]).then(function() {
self.setState({
phase: self.phases.DISPLAY,
phase: Notifications.phases.DISPLAY,
});
}, function(error) {
console.error(error);
self.setState({
phase: self.phases.ERROR,
phase: Notifications.phases.ERROR,
});
}).finally(() => {
// actually explicitly update our state having been deep-manipulating it
@ -655,9 +648,9 @@ export default createReactClass({
});
MatrixClientPeg.get().getThreePids().then((r) => this.setState({threepids: r.threepids}));
},
};
_onClearNotifications: function() {
_onClearNotifications = () => {
const cli = MatrixClientPeg.get();
cli.getRooms().forEach(r => {
@ -666,9 +659,9 @@ export default createReactClass({
if (events.length) cli.sendReadReceipt(events.pop());
}
});
},
};
_updatePushRuleActions: function(rule, actions, enabled) {
_updatePushRuleActions(rule, actions, enabled) {
const cli = MatrixClientPeg.get();
return cli.setPushRuleActions(
@ -681,9 +674,9 @@ export default createReactClass({
);
}
});
},
}
renderNotifRulesTableRow: function(title, className, pushRuleVectorState) {
renderNotifRulesTableRow(title, className, pushRuleVectorState) {
return (
<tr key={ className }>
<th>
@ -712,9 +705,9 @@ export default createReactClass({
</th>
</tr>
);
},
}
renderNotifRulesTableRows: function() {
renderNotifRulesTableRows() {
const rows = [];
for (const i in this.state.vectorPushRules) {
const rule = this.state.vectorPushRules[i];
@ -726,9 +719,9 @@ export default createReactClass({
rows.push(this.renderNotifRulesTableRow(rule.description, rule.vectorRuleId, rule.vectorState));
}
return rows;
},
}
hasEmailPusher: function(pushers, address) {
hasEmailPusher(pushers, address) {
if (pushers === undefined) {
return false;
}
@ -738,17 +731,17 @@ export default createReactClass({
}
}
return false;
},
}
emailNotificationsRow: function(address, label) {
emailNotificationsRow(address, label) {
return <LabelledToggleSwitch value={this.hasEmailPusher(this.state.pushers, address)}
onChange={this.onEnableEmailNotificationsChange.bind(this, address)}
label={label} key={`emailNotif_${label}`} />;
},
}
render: function() {
render() {
let spinner;
if (this.state.phase === this.phases.LOADING) {
if (this.state.phase === Notifications.phases.LOADING) {
const Loader = sdk.getComponent("elements.Spinner");
spinner = <Loader />;
}
@ -910,5 +903,5 @@ export default createReactClass({
</div>
);
},
});
}
}