Merge pull request #3743 from matrix-org/t3chguy/react16_contexts

Migrate away from React Legacy contexts API
This commit is contained in:
Michael Telatynski 2019-12-19 20:32:11 +00:00 committed by GitHub
commit 24d0d0d596
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
56 changed files with 654 additions and 757 deletions

View file

@ -22,12 +22,11 @@ import FocusLock from 'react-focus-lock';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import { MatrixClient } from 'matrix-js-sdk';
import { Key } from '../../../Keyboard';
import AccessibleButton from '../elements/AccessibleButton';
import MatrixClientPeg from '../../../MatrixClientPeg';
import { _t } from "../../../languageHandler";
import MatrixClientContext from "../../../contexts/MatrixClientContext";
/**
* Basic container for modal dialogs.
@ -84,16 +83,6 @@ export default createReactClass({
};
},
childContextTypes: {
matrixClient: PropTypes.instanceOf(MatrixClient),
},
getChildContext: function() {
return {
matrixClient: this._matrixClient,
};
},
componentWillMount() {
this._matrixClient = MatrixClientPeg.get();
},
@ -122,36 +111,38 @@ export default createReactClass({
}
return (
<FocusLock
returnFocus={true}
lockProps={{
onKeyDown: this._onKeyDown,
role: "dialog",
["aria-labelledby"]: "mx_BaseDialog_title",
// This should point to a node describing the dialog.
// If we were about to completely follow this recommendation we'd need to
// make all the components relying on BaseDialog to be aware of it.
// So instead we will use the whole content as the description.
// Description comes first and if the content contains more text,
// AT users can skip its presentation.
["aria-describedby"]: this.props.contentId,
}}
className={classNames({
[this.props.className]: true,
'mx_Dialog_fixedWidth': this.props.fixedWidth,
})}
>
<div className={classNames('mx_Dialog_header', {
'mx_Dialog_headerWithButton': !!this.props.headerButton,
})}>
<div className={classNames('mx_Dialog_title', this.props.titleClass)} id='mx_BaseDialog_title'>
{ this.props.title }
<MatrixClientContext.Provider value={this._matrixClient}>
<FocusLock
returnFocus={true}
lockProps={{
onKeyDown: this._onKeyDown,
role: "dialog",
["aria-labelledby"]: "mx_BaseDialog_title",
// This should point to a node describing the dialog.
// If we were about to completely follow this recommendation we'd need to
// make all the components relying on BaseDialog to be aware of it.
// So instead we will use the whole content as the description.
// Description comes first and if the content contains more text,
// AT users can skip its presentation.
["aria-describedby"]: this.props.contentId,
}}
className={classNames({
[this.props.className]: true,
'mx_Dialog_fixedWidth': this.props.fixedWidth,
})}
>
<div className={classNames('mx_Dialog_header', {
'mx_Dialog_headerWithButton': !!this.props.headerButton,
})}>
<div className={classNames('mx_Dialog_title', this.props.titleClass)} id='mx_BaseDialog_title'>
{ this.props.title }
</div>
{ this.props.headerButton }
{ cancelButton }
</div>
{ this.props.headerButton }
{ cancelButton }
</div>
{ this.props.children }
</FocusLock>
{ this.props.children }
</FocusLock>
</MatrixClientContext.Provider>
);
},
});

View file

@ -25,8 +25,8 @@ import Modal from '../../../Modal';
import { _t } from '../../../languageHandler';
export default class BugReportDialog extends React.Component {
constructor(props, context) {
super(props, context);
constructor(props) {
super(props);
this.state = {
sendLogs: true,
busy: false,

View file

@ -25,8 +25,8 @@ import * as Lifecycle from '../../../Lifecycle';
import { _t } from '../../../languageHandler';
export default class DeactivateAccountDialog extends React.Component {
constructor(props, context) {
super(props, context);
constructor(props) {
super(props);
this._onOk = this._onOk.bind(this);
this._onCancel = this._onCancel.bind(this);

View file

@ -16,23 +16,19 @@ limitations under the License.
import React from 'react';
import PropTypes from 'prop-types';
import { Room } from "matrix-js-sdk";
import sdk from '../../../index';
import SyntaxHighlight from '../elements/SyntaxHighlight';
import { _t } from '../../../languageHandler';
import MatrixClientPeg from '../../../MatrixClientPeg';
import Field from "../elements/Field";
import MatrixClientContext from "../../../contexts/MatrixClientContext";
class DevtoolsComponent extends React.Component {
static contextTypes = {
roomId: PropTypes.string.isRequired,
};
}
class GenericEditor extends DevtoolsComponent {
class GenericEditor extends React.PureComponent {
// static propTypes = {onBack: PropTypes.func.isRequired};
constructor(props, context) {
super(props, context);
constructor(props) {
super(props);
this._onChange = this._onChange.bind(this);
this.onBack = this.onBack.bind(this);
}
@ -67,12 +63,15 @@ class SendCustomEvent extends GenericEditor {
static propTypes = {
onBack: PropTypes.func.isRequired,
room: PropTypes.instanceOf(Room).isRequired,
forceStateEvent: PropTypes.bool,
inputs: PropTypes.object,
};
constructor(props, context) {
super(props, context);
static contextType = MatrixClientContext;
constructor(props) {
super(props);
this._send = this._send.bind(this);
const {eventType, stateKey, evContent} = Object.assign({
@ -91,11 +90,11 @@ class SendCustomEvent extends GenericEditor {
}
send(content) {
const cli = MatrixClientPeg.get();
const cli = this.context;
if (this.state.isStateEvent) {
return cli.sendStateEvent(this.context.roomId, this.state.eventType, content, this.state.stateKey);
return cli.sendStateEvent(this.props.room.roomId, this.state.eventType, content, this.state.stateKey);
} else {
return cli.sendEvent(this.context.roomId, this.state.eventType, content);
return cli.sendEvent(this.props.room.roomId, this.state.eventType, content);
}
}
@ -154,13 +153,16 @@ class SendAccountData extends GenericEditor {
static getLabel() { return _t('Send Account Data'); }
static propTypes = {
room: PropTypes.instanceOf(Room).isRequired,
isRoomAccountData: PropTypes.bool,
forceMode: PropTypes.bool,
inputs: PropTypes.object,
};
constructor(props, context) {
super(props, context);
static contextType = MatrixClientContext;
constructor(props) {
super(props);
this._send = this._send.bind(this);
const {eventType, evContent} = Object.assign({
@ -177,9 +179,9 @@ class SendAccountData extends GenericEditor {
}
send(content) {
const cli = MatrixClientPeg.get();
const cli = this.context;
if (this.state.isRoomAccountData) {
return cli.setRoomAccountData(this.context.roomId, this.state.eventType, content);
return cli.setRoomAccountData(this.props.room.roomId, this.state.eventType, content);
}
return cli.setAccountData(this.state.eventType, content);
}
@ -234,7 +236,7 @@ class SendAccountData extends GenericEditor {
const INITIAL_LOAD_TILES = 20;
const LOAD_TILES_STEP_SIZE = 50;
class FilteredList extends React.Component {
class FilteredList extends React.PureComponent {
static propTypes = {
children: PropTypes.any,
query: PropTypes.string,
@ -247,8 +249,8 @@ class FilteredList extends React.Component {
return children.filter((child) => child.key.toLowerCase().includes(lcQuery));
}
constructor(props, context) {
super(props, context);
constructor(props) {
super(props);
this.state = {
filteredChildren: FilteredList.filterChildren(this.props.children, this.props.query),
@ -305,19 +307,20 @@ class FilteredList extends React.Component {
}
}
class RoomStateExplorer extends DevtoolsComponent {
class RoomStateExplorer extends React.PureComponent {
static getLabel() { return _t('Explore Room State'); }
static propTypes = {
onBack: PropTypes.func.isRequired,
room: PropTypes.instanceOf(Room).isRequired,
};
constructor(props, context) {
super(props, context);
static contextType = MatrixClientContext;
const room = MatrixClientPeg.get().getRoom(this.context.roomId);
this.roomStateEvents = room.currentState.events;
constructor(props) {
super(props);
this.roomStateEvents = this.props.room.currentState.events;
this.onBack = this.onBack.bind(this);
this.editEv = this.editEv.bind(this);
@ -373,7 +376,7 @@ class RoomStateExplorer extends DevtoolsComponent {
render() {
if (this.state.event) {
if (this.state.editing) {
return <SendCustomEvent forceStateEvent={true} onBack={this.onBack} inputs={{
return <SendCustomEvent room={this.props.room} forceStateEvent={true} onBack={this.onBack} inputs={{
eventType: this.state.event.getType(),
evContent: JSON.stringify(this.state.event.getContent(), null, '\t'),
stateKey: this.state.event.getStateKey(),
@ -442,15 +445,18 @@ class RoomStateExplorer extends DevtoolsComponent {
}
}
class AccountDataExplorer extends DevtoolsComponent {
class AccountDataExplorer extends React.PureComponent {
static getLabel() { return _t('Explore Account Data'); }
static propTypes = {
onBack: PropTypes.func.isRequired,
room: PropTypes.instanceOf(Room).isRequired,
};
constructor(props, context) {
super(props, context);
static contextType = MatrixClientContext;
constructor(props) {
super(props);
this.onBack = this.onBack.bind(this);
this.editEv = this.editEv.bind(this);
@ -467,11 +473,10 @@ class AccountDataExplorer extends DevtoolsComponent {
}
getData() {
const cli = MatrixClientPeg.get();
if (this.state.isRoomAccountData) {
return cli.getRoom(this.context.roomId).accountData;
return this.props.room.accountData;
}
return cli.store.accountData;
return this.context.store.accountData;
}
onViewSourceClick(event) {
@ -505,10 +510,14 @@ class AccountDataExplorer extends DevtoolsComponent {
render() {
if (this.state.event) {
if (this.state.editing) {
return <SendAccountData isRoomAccountData={this.state.isRoomAccountData} onBack={this.onBack} inputs={{
eventType: this.state.event.getType(),
evContent: JSON.stringify(this.state.event.getContent(), null, '\t'),
}} forceMode={true} />;
return <SendAccountData
room={this.props.room}
isRoomAccountData={this.state.isRoomAccountData}
onBack={this.onBack}
inputs={{
eventType: this.state.event.getType(),
evContent: JSON.stringify(this.state.event.getContent(), null, '\t'),
}} forceMode={true} />;
}
return <div className="mx_ViewSource">
@ -553,17 +562,20 @@ class AccountDataExplorer extends DevtoolsComponent {
}
}
class ServersInRoomList extends DevtoolsComponent {
class ServersInRoomList extends React.PureComponent {
static getLabel() { return _t('View Servers in Room'); }
static propTypes = {
onBack: PropTypes.func.isRequired,
room: PropTypes.instanceOf(Room).isRequired,
};
constructor(props, context) {
super(props, context);
static contextType = MatrixClientContext;
const room = MatrixClientPeg.get().getRoom(this.context.roomId);
constructor(props) {
super(props);
const room = this.props.room;
const servers = new Set();
room.currentState.getStateEvents("m.room.member").forEach(ev => servers.add(ev.getSender().split(":")[1]));
this.servers = Array.from(servers).map(s =>
@ -602,19 +614,14 @@ const Entries = [
ServersInRoomList,
];
export default class DevtoolsDialog extends React.Component {
static childContextTypes = {
roomId: PropTypes.string.isRequired,
// client: PropTypes.instanceOf(MatixClient),
};
export default class DevtoolsDialog extends React.PureComponent {
static propTypes = {
roomId: PropTypes.string.isRequired,
onFinished: PropTypes.func.isRequired,
};
constructor(props, context) {
super(props, context);
constructor(props) {
super(props);
this.onBack = this.onBack.bind(this);
this.onCancel = this.onCancel.bind(this);
@ -627,10 +634,6 @@ export default class DevtoolsDialog extends React.Component {
this._unmounted = true;
}
getChildContext() {
return { roomId: this.props.roomId };
}
_setMode(mode) {
return () => {
this.setState({ mode });
@ -654,15 +657,17 @@ export default class DevtoolsDialog extends React.Component {
let body;
if (this.state.mode) {
body = <div>
<div className="mx_DevTools_label_left">{ this.state.mode.getLabel() }</div>
<div className="mx_DevTools_label_right">Room ID: { this.props.roomId }</div>
<div className="mx_DevTools_label_bottom" />
<this.state.mode onBack={this.onBack} />
</div>;
body = <MatrixClientContext.Consumer>
{(cli) => <React.Fragment>
<div className="mx_DevTools_label_left">{ this.state.mode.getLabel() }</div>
<div className="mx_DevTools_label_right">Room ID: { this.props.roomId }</div>
<div className="mx_DevTools_label_bottom" />
<this.state.mode onBack={this.onBack} room={cli.getRoom(this.props.roomId)} />
</React.Fragment>}
</MatrixClientContext.Consumer>;
} else {
const classes = "mx_DevTools_RoomStateExplorer_button";
body = <div>
body = <React.Fragment>
<div>
<div className="mx_DevTools_label_left">{ _t('Toolbox') }</div>
<div className="mx_DevTools_label_right">Room ID: { this.props.roomId }</div>
@ -679,7 +684,7 @@ export default class DevtoolsDialog extends React.Component {
<div className="mx_Dialog_buttons">
<button onClick={this.onCancel}>{ _t('Cancel') }</button>
</div>
</div>;
</React.Fragment>;
}
const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');

View file

@ -30,8 +30,8 @@ export default class ReportEventDialog extends PureComponent {
onFinished: PropTypes.func.isRequired,
};
constructor(props, context) {
super(props, context);
constructor(props) {
super(props);
this.state = {
reason: "",