1
0
mirror of https://github.com/matrix-org/matrix-react-sdk.git synced 2025-04-30 16:24:49 +03:00

Migrate away from Legacy React Contexts

This commit is contained in:
Michael Telatynski 2019-12-17 17:26:12 +00:00
parent 2e8d66fa36
commit 937b32663c
55 changed files with 651 additions and 750 deletions

View File

@ -26,8 +26,8 @@ import sanitizeHtml from 'sanitize-html';
import sdk from '../../index'; import sdk from '../../index';
import dis from '../../dispatcher'; import dis from '../../dispatcher';
import MatrixClientPeg from '../../MatrixClientPeg'; import MatrixClientPeg from '../../MatrixClientPeg';
import { MatrixClient } from 'matrix-js-sdk';
import classnames from 'classnames'; import classnames from 'classnames';
import MatrixClientContext from "../../contexts/MatrixClientContext";
export default class EmbeddedPage extends React.PureComponent { export default class EmbeddedPage extends React.PureComponent {
static propTypes = { static propTypes = {
@ -39,9 +39,7 @@ export default class EmbeddedPage extends React.PureComponent {
scrollbar: PropTypes.bool, scrollbar: PropTypes.bool,
}; };
static contextTypes = { static contextType = MatrixClientContext;
matrixClient: PropTypes.instanceOf(MatrixClient),
};
constructor(props) { constructor(props) {
super(props); super(props);
@ -104,7 +102,7 @@ export default class EmbeddedPage extends React.PureComponent {
render() { render() {
// HACK: Workaround for the context's MatrixClient not updating. // HACK: Workaround for the context's MatrixClient not updating.
const client = this.context.matrixClient || MatrixClientPeg.get(); const client = this.context || MatrixClientPeg.get();
const isGuest = client ? client.isGuest() : true; const isGuest = client ? client.isGuest() : true;
const className = this.props.className; const className = this.props.className;
const classes = classnames({ const classes = classnames({

View File

@ -19,7 +19,6 @@ import React from 'react';
import createReactClass from 'create-react-class'; import createReactClass from 'create-react-class';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import classNames from 'classnames'; import classNames from 'classnames';
import { MatrixClient } from 'matrix-js-sdk';
import { Key } from '../../Keyboard'; import { Key } from '../../Keyboard';
import sdk from '../../index'; import sdk from '../../index';
import dis from '../../dispatcher'; import dis from '../../dispatcher';
@ -39,10 +38,6 @@ const LeftPanel = createReactClass({
collapsed: PropTypes.bool.isRequired, collapsed: PropTypes.bool.isRequired,
}, },
contextTypes: {
matrixClient: PropTypes.instanceOf(MatrixClient),
},
getInitialState: function() { getInitialState: function() {
return { return {
searchFilter: '', searchFilter: '',

View File

@ -38,6 +38,7 @@ import TagOrderActions from '../../actions/TagOrderActions';
import RoomListActions from '../../actions/RoomListActions'; import RoomListActions from '../../actions/RoomListActions';
import ResizeHandle from '../views/elements/ResizeHandle'; import ResizeHandle from '../views/elements/ResizeHandle';
import {Resizer, CollapseDistributor} from '../../resizer'; import {Resizer, CollapseDistributor} from '../../resizer';
import MatrixClientContext from "../../contexts/MatrixClientContext";
// We need to fetch each pinned message individually (if we don't already have it) // We need to fetch each pinned message individually (if we don't already have it)
// so each pinned message may trigger a request. Limit the number per room for sanity. // so each pinned message may trigger a request. Limit the number per room for sanity.
// NB. this is just for server notices rather than pinned messages in general. // NB. this is just for server notices rather than pinned messages in general.
@ -77,21 +78,6 @@ const LoggedInView = createReactClass({
// and lots and lots of other stuff. // and lots and lots of other stuff.
}, },
childContextTypes: {
matrixClient: PropTypes.instanceOf(MatrixClient),
authCache: PropTypes.object,
},
getChildContext: function() {
return {
matrixClient: this._matrixClient,
authCache: {
auth: {},
lastUpdate: 0,
},
};
},
getInitialState: function() { getInitialState: function() {
return { return {
// use compact timeline view // use compact timeline view
@ -631,7 +617,15 @@ const LoggedInView = createReactClass({
} }
return ( return (
<div onPaste={this._onPaste} onKeyDown={this._onReactKeyDown} className='mx_MatrixChat_wrapper' aria-hidden={this.props.hideToSRUsers} onMouseDown={this._onMouseDown} onMouseUp={this._onMouseUp}> <MatrixClientContext.Provider value={this._matrixClient}>
<div
onPaste={this._onPaste}
onKeyDown={this._onReactKeyDown}
className='mx_MatrixChat_wrapper'
aria-hidden={this.props.hideToSRUsers}
onMouseDown={this._onMouseDown}
onMouseUp={this._onMouseUp}
>
{ topBar } { topBar }
<ToastContainer /> <ToastContainer />
<DragDropContext onDragEnd={this._onDragEnd}> <DragDropContext onDragEnd={this._onDragEnd}>
@ -646,6 +640,7 @@ const LoggedInView = createReactClass({
</div> </div>
</DragDropContext> </DragDropContext>
</div> </div>
</MatrixClientContext.Provider>
); );
}, },
}); });

View File

@ -150,16 +150,6 @@ export default createReactClass({
makeRegistrationUrl: PropTypes.func.isRequired, makeRegistrationUrl: PropTypes.func.isRequired,
}, },
childContextTypes: {
appConfig: PropTypes.object,
},
getChildContext: function() {
return {
appConfig: this.props.config,
};
},
getInitialState: function() { getInitialState: function() {
const s = { const s = {
// the master view we are showing. // the master view we are showing.

View File

@ -17,12 +17,11 @@ limitations under the License.
import React from 'react'; import React from 'react';
import createReactClass from 'create-react-class'; import createReactClass from 'create-react-class';
import PropTypes from 'prop-types';
import { MatrixClient } from 'matrix-js-sdk';
import sdk from '../../index'; import sdk from '../../index';
import { _t } from '../../languageHandler'; import { _t } from '../../languageHandler';
import dis from '../../dispatcher'; import dis from '../../dispatcher';
import AccessibleButton from '../views/elements/AccessibleButton'; import AccessibleButton from '../views/elements/AccessibleButton';
import MatrixClientContext from "../../contexts/MatrixClientContext";
export default createReactClass({ export default createReactClass({
displayName: 'MyGroups', displayName: 'MyGroups',
@ -34,8 +33,8 @@ export default createReactClass({
}; };
}, },
contextTypes: { statics: {
matrixClient: PropTypes.instanceOf(MatrixClient).isRequired, contextType: MatrixClientContext,
}, },
componentWillMount: function() { componentWillMount: function() {
@ -47,7 +46,7 @@ export default createReactClass({
}, },
_fetch: function() { _fetch: function() {
this.context.matrixClient.getJoinedGroups().then((result) => { this.context.getJoinedGroups().then((result) => {
this.setState({groups: result.groups, error: null}); this.setState({groups: result.groups, error: null});
}, (err) => { }, (err) => {
if (err.errcode === 'M_GUEST_ACCESS_FORBIDDEN') { if (err.errcode === 'M_GUEST_ACCESS_FORBIDDEN') {

View File

@ -23,13 +23,13 @@ import PropTypes from 'prop-types';
import classNames from 'classnames'; import classNames from 'classnames';
import sdk from '../../index'; import sdk from '../../index';
import dis from '../../dispatcher'; import dis from '../../dispatcher';
import { MatrixClient } from 'matrix-js-sdk';
import RateLimitedFunc from '../../ratelimitedfunc'; import RateLimitedFunc from '../../ratelimitedfunc';
import { showGroupInviteDialog, showGroupAddRoomDialog } from '../../GroupAddressPicker'; import { showGroupInviteDialog, showGroupAddRoomDialog } from '../../GroupAddressPicker';
import GroupStore from '../../stores/GroupStore'; import GroupStore from '../../stores/GroupStore';
import SettingsStore from "../../settings/SettingsStore"; import SettingsStore from "../../settings/SettingsStore";
import {RIGHT_PANEL_PHASES, RIGHT_PANEL_PHASES_NO_ARGS} from "../../stores/RightPanelStorePhases"; import {RIGHT_PANEL_PHASES, RIGHT_PANEL_PHASES_NO_ARGS} from "../../stores/RightPanelStorePhases";
import RightPanelStore from "../../stores/RightPanelStore"; import RightPanelStore from "../../stores/RightPanelStore";
import MatrixClientContext from "../../contexts/MatrixClientContext";
export default class RightPanel extends React.Component { export default class RightPanel extends React.Component {
static get propTypes() { static get propTypes() {
@ -40,14 +40,10 @@ export default class RightPanel extends React.Component {
}; };
} }
static get contextTypes() { static contextType = MatrixClientContext;
return {
matrixClient: PropTypes.instanceOf(MatrixClient),
};
}
constructor(props, context) { constructor(props) {
super(props, context); super(props);
this.state = { this.state = {
phase: this._getPhaseFromProps(), phase: this._getPhaseFromProps(),
isUserPrivilegedInGroup: null, isUserPrivilegedInGroup: null,
@ -93,15 +89,15 @@ export default class RightPanel extends React.Component {
componentWillMount() { componentWillMount() {
this.dispatcherRef = dis.register(this.onAction); this.dispatcherRef = dis.register(this.onAction);
const cli = this.context.matrixClient; const cli = this.context;
cli.on("RoomState.members", this.onRoomStateMember); cli.on("RoomState.members", this.onRoomStateMember);
this._initGroupStore(this.props.groupId); this._initGroupStore(this.props.groupId);
} }
componentWillUnmount() { componentWillUnmount() {
dis.unregister(this.dispatcherRef); dis.unregister(this.dispatcherRef);
if (this.context.matrixClient) { if (this.context) {
this.context.matrixClient.removeListener("RoomState.members", this.onRoomStateMember); this.context.removeListener("RoomState.members", this.onRoomStateMember);
} }
this._unregisterGroupStore(this.props.groupId); this._unregisterGroupStore(this.props.groupId);
} }

View File

@ -30,6 +30,7 @@ import PropTypes from 'prop-types';
import { _t } from '../../languageHandler'; import { _t } from '../../languageHandler';
import { instanceForInstanceId, protocolNameForInstanceId } from '../../utils/DirectoryUtils'; import { instanceForInstanceId, protocolNameForInstanceId } from '../../utils/DirectoryUtils';
import Analytics from '../../Analytics'; import Analytics from '../../Analytics';
import MatrixClientContext from "../../contexts/MatrixClientContext";
const MAX_NAME_LENGTH = 80; const MAX_NAME_LENGTH = 80;
const MAX_TOPIC_LENGTH = 160; const MAX_TOPIC_LENGTH = 160;
@ -65,16 +66,6 @@ module.exports = createReactClass({
}; };
}, },
childContextTypes: {
matrixClient: PropTypes.object,
},
getChildContext: function() {
return {
matrixClient: MatrixClientPeg.get(),
};
},
componentWillMount: function() { componentWillMount: function() {
this._unmounted = false; this._unmounted = false;
this.nextBatch = null; this.nextBatch = null;

View File

@ -28,7 +28,6 @@ import createReactClass from 'create-react-class';
import ReactDOM from 'react-dom'; import ReactDOM from 'react-dom';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import classNames from 'classnames'; import classNames from 'classnames';
import {Room} from "matrix-js-sdk";
import { _t } from '../../languageHandler'; import { _t } from '../../languageHandler';
import {RoomPermalinkCreator} from '../../utils/permalinks/Permalinks'; import {RoomPermalinkCreator} from '../../utils/permalinks/Permalinks';
@ -55,6 +54,7 @@ import SettingsStore, {SettingLevel} from "../../settings/SettingsStore";
import WidgetUtils from '../../utils/WidgetUtils'; import WidgetUtils from '../../utils/WidgetUtils';
import AccessibleButton from "../views/elements/AccessibleButton"; import AccessibleButton from "../views/elements/AccessibleButton";
import RightPanelStore from "../../stores/RightPanelStore"; import RightPanelStore from "../../stores/RightPanelStore";
import RoomContext from "../../contexts/RoomContext";
const DEBUG = false; const DEBUG = false;
let debuglog = function() {}; let debuglog = function() {};
@ -66,12 +66,6 @@ if (DEBUG) {
debuglog = console.log.bind(console); debuglog = console.log.bind(console);
} }
const RoomContext = PropTypes.shape({
canReact: PropTypes.bool.isRequired,
canReply: PropTypes.bool.isRequired,
room: PropTypes.instanceOf(Room),
});
module.exports = createReactClass({ module.exports = createReactClass({
displayName: 'RoomView', displayName: 'RoomView',
propTypes: { propTypes: {
@ -169,21 +163,6 @@ module.exports = createReactClass({
}; };
}, },
childContextTypes: {
room: RoomContext,
},
getChildContext: function() {
const {canReact, canReply, room} = this.state;
return {
room: {
canReact,
canReply,
room,
},
};
},
componentWillMount: function() { componentWillMount: function() {
this.dispatcherRef = dis.register(this.onAction); this.dispatcherRef = dis.register(this.onAction);
MatrixClientPeg.get().on("Room", this.onRoom); MatrixClientPeg.get().on("Room", this.onRoom);
@ -1989,6 +1968,7 @@ module.exports = createReactClass({
: null; : null;
return ( return (
<RoomContext.Provider value={this.state}>
<main className={"mx_RoomView" + (inCall ? " mx_RoomView_inCall" : "")} ref={this._roomView}> <main className={"mx_RoomView" + (inCall ? " mx_RoomView_inCall" : "")} ref={this._roomView}>
<ErrorBoundary> <ErrorBoundary>
<RoomHeader <RoomHeader
@ -2018,7 +1998,7 @@ module.exports = createReactClass({
</div> </div>
<div className={statusBarAreaClass}> <div className={statusBarAreaClass}>
<div className="mx_RoomView_statusAreaBox"> <div className="mx_RoomView_statusAreaBox">
<div className="mx_RoomView_statusAreaBox_line"></div> <div className="mx_RoomView_statusAreaBox_line" />
{statusBar} {statusBar}
</div> </div>
</div> </div>
@ -2028,6 +2008,7 @@ module.exports = createReactClass({
</MainSplit> </MainSplit>
</ErrorBoundary> </ErrorBoundary>
</main> </main>
</RoomContext.Provider>
); );
}, },
}); });

View File

@ -16,8 +16,6 @@ limitations under the License.
import React from 'react'; import React from 'react';
import createReactClass from 'create-react-class'; import createReactClass from 'create-react-class';
import PropTypes from 'prop-types';
import { MatrixClient } from 'matrix-js-sdk';
import TagOrderStore from '../../stores/TagOrderStore'; import TagOrderStore from '../../stores/TagOrderStore';
import GroupActions from '../../actions/GroupActions'; import GroupActions from '../../actions/GroupActions';
@ -28,12 +26,13 @@ import { _t } from '../../languageHandler';
import { Droppable } from 'react-beautiful-dnd'; import { Droppable } from 'react-beautiful-dnd';
import classNames from 'classnames'; import classNames from 'classnames';
import MatrixClientContext from "../../contexts/MatrixClientContext";
const TagPanel = createReactClass({ const TagPanel = createReactClass({
displayName: 'TagPanel', displayName: 'TagPanel',
contextTypes: { statics: {
matrixClient: PropTypes.instanceOf(MatrixClient), contextType: MatrixClientContext,
}, },
getInitialState() { getInitialState() {
@ -45,8 +44,8 @@ const TagPanel = createReactClass({
componentWillMount: function() { componentWillMount: function() {
this.unmounted = false; this.unmounted = false;
this.context.matrixClient.on("Group.myMembership", this._onGroupMyMembership); this.context.on("Group.myMembership", this._onGroupMyMembership);
this.context.matrixClient.on("sync", this._onClientSync); this.context.on("sync", this._onClientSync);
this._tagOrderStoreToken = TagOrderStore.addListener(() => { this._tagOrderStoreToken = TagOrderStore.addListener(() => {
if (this.unmounted) { if (this.unmounted) {
@ -58,13 +57,13 @@ const TagPanel = createReactClass({
}); });
}); });
// This could be done by anything with a matrix client // This could be done by anything with a matrix client
dis.dispatch(GroupActions.fetchJoinedGroups(this.context.matrixClient)); dis.dispatch(GroupActions.fetchJoinedGroups(this.context));
}, },
componentWillUnmount() { componentWillUnmount() {
this.unmounted = true; this.unmounted = true;
this.context.matrixClient.removeListener("Group.myMembership", this._onGroupMyMembership); this.context.removeListener("Group.myMembership", this._onGroupMyMembership);
this.context.matrixClient.removeListener("sync", this._onClientSync); this.context.removeListener("sync", this._onClientSync);
if (this._filterStoreToken) { if (this._filterStoreToken) {
this._filterStoreToken.remove(); this._filterStoreToken.remove();
} }
@ -72,7 +71,7 @@ const TagPanel = createReactClass({
_onGroupMyMembership() { _onGroupMyMembership() {
if (this.unmounted) return; if (this.unmounted) return;
dis.dispatch(GroupActions.fetchJoinedGroups(this.context.matrixClient)); dis.dispatch(GroupActions.fetchJoinedGroups(this.context));
}, },
_onClientSync(syncState, prevState) { _onClientSync(syncState, prevState) {
@ -81,7 +80,7 @@ const TagPanel = createReactClass({
const reconnected = syncState !== "ERROR" && prevState !== syncState; const reconnected = syncState !== "ERROR" && prevState !== syncState;
if (reconnected) { if (reconnected) {
// Load joined groups // Load joined groups
dis.dispatch(GroupActions.fetchJoinedGroups(this.context.matrixClient)); dis.dispatch(GroupActions.fetchJoinedGroups(this.context));
} }
}, },

View File

@ -19,10 +19,10 @@ limitations under the License.
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import createReactClass from 'create-react-class'; import createReactClass from 'create-react-class';
import { MatrixClient } from 'matrix-js-sdk';
import AvatarLogic from '../../../Avatar'; import AvatarLogic from '../../../Avatar';
import SettingsStore from "../../../settings/SettingsStore"; import SettingsStore from "../../../settings/SettingsStore";
import AccessibleButton from '../elements/AccessibleButton'; import AccessibleButton from '../elements/AccessibleButton';
import MatrixClientContext from "../../../contexts/MatrixClientContext";
module.exports = createReactClass({ module.exports = createReactClass({
displayName: 'BaseAvatar', displayName: 'BaseAvatar',
@ -40,8 +40,8 @@ module.exports = createReactClass({
defaultToInitialLetter: PropTypes.bool, // true to add default url defaultToInitialLetter: PropTypes.bool, // true to add default url
}, },
contextTypes: { statics: {
matrixClient: PropTypes.instanceOf(MatrixClient), contextType: MatrixClientContext,
}, },
getDefaultProps: function() { getDefaultProps: function() {
@ -59,12 +59,12 @@ module.exports = createReactClass({
componentDidMount() { componentDidMount() {
this.unmounted = false; this.unmounted = false;
this.context.matrixClient.on('sync', this.onClientSync); this.context.on('sync', this.onClientSync);
}, },
componentWillUnmount() { componentWillUnmount() {
this.unmounted = true; this.unmounted = true;
this.context.matrixClient.removeListener('sync', this.onClientSync); this.context.removeListener('sync', this.onClientSync);
}, },
componentWillReceiveProps: function(nextProps) { componentWillReceiveProps: function(nextProps) {

View File

@ -38,8 +38,8 @@ export default class MemberStatusMessageAvatar extends React.Component {
resizeMethod: 'crop', resizeMethod: 'crop',
}; };
constructor(props, context) { constructor(props) {
super(props, context); super(props);
this.state = { this.state = {
hasStatus: this.hasStatus, hasStatus: this.hasStatus,

View File

@ -31,8 +31,8 @@ export default class GroupInviteTileContextMenu extends React.Component {
onFinished: PropTypes.func, onFinished: PropTypes.func,
}; };
constructor(props, context) { constructor(props) {
super(props, context); super(props);
this._onClickReject = this._onClickReject.bind(this); this._onClickReject = this._onClickReject.bind(this);
} }

View File

@ -27,8 +27,8 @@ export default class StatusMessageContextMenu extends React.Component {
user: PropTypes.object, user: PropTypes.object,
}; };
constructor(props, context) { constructor(props) {
super(props, context); super(props);
this.state = { this.state = {
message: this.comittedStatusMessage, message: this.comittedStatusMessage,

View File

@ -17,12 +17,12 @@ limitations under the License.
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { MatrixClient } from 'matrix-js-sdk';
import { _t } from '../../../languageHandler'; import { _t } from '../../../languageHandler';
import dis from '../../../dispatcher'; import dis from '../../../dispatcher';
import TagOrderActions from '../../../actions/TagOrderActions'; import TagOrderActions from '../../../actions/TagOrderActions';
import sdk from '../../../index'; import sdk from '../../../index';
import {MenuItem} from "../../structures/ContextMenu"; import {MenuItem} from "../../structures/ContextMenu";
import MatrixClientContext from "../../../contexts/MatrixClientContext";
export default class TagTileContextMenu extends React.Component { export default class TagTileContextMenu extends React.Component {
static propTypes = { static propTypes = {
@ -31,9 +31,7 @@ export default class TagTileContextMenu extends React.Component {
onFinished: PropTypes.func.isRequired, onFinished: PropTypes.func.isRequired,
}; };
static contextTypes = { static contextType = MatrixClientContext;
matrixClient: PropTypes.instanceOf(MatrixClient),
};
constructor() { constructor() {
super(); super();
@ -51,7 +49,7 @@ export default class TagTileContextMenu extends React.Component {
} }
_onRemoveClick() { _onRemoveClick() {
dis.dispatch(TagOrderActions.removeTag(this.context.matrixClient, this.props.tag)); dis.dispatch(TagOrderActions.removeTag(this.context, this.props.tag));
this.props.onFinished(); this.props.onFinished();
} }

View File

@ -22,12 +22,11 @@ import FocusLock from 'react-focus-lock';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import classNames from 'classnames'; import classNames from 'classnames';
import { MatrixClient } from 'matrix-js-sdk';
import { Key } from '../../../Keyboard'; import { Key } from '../../../Keyboard';
import AccessibleButton from '../elements/AccessibleButton'; import AccessibleButton from '../elements/AccessibleButton';
import MatrixClientPeg from '../../../MatrixClientPeg'; import MatrixClientPeg from '../../../MatrixClientPeg';
import { _t } from "../../../languageHandler"; import { _t } from "../../../languageHandler";
import MatrixClientContext from "../../../contexts/MatrixClientContext";
/** /**
* Basic container for modal dialogs. * Basic container for modal dialogs.
@ -84,16 +83,6 @@ export default createReactClass({
}; };
}, },
childContextTypes: {
matrixClient: PropTypes.instanceOf(MatrixClient),
},
getChildContext: function() {
return {
matrixClient: this._matrixClient,
};
},
componentWillMount() { componentWillMount() {
this._matrixClient = MatrixClientPeg.get(); this._matrixClient = MatrixClientPeg.get();
}, },
@ -122,6 +111,7 @@ export default createReactClass({
} }
return ( return (
<MatrixClientContext.Provider value={this._matrixClient}>
<FocusLock <FocusLock
returnFocus={true} returnFocus={true}
lockProps={{ lockProps={{
@ -152,6 +142,7 @@ export default createReactClass({
</div> </div>
{ this.props.children } { this.props.children }
</FocusLock> </FocusLock>
</MatrixClientContext.Provider>
); );
}, },
}); });

View File

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

View File

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

View File

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

View File

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

View File

@ -25,13 +25,13 @@ import sdk from '../../../index';
* Parent components should supply an 'onSubmit' callback which returns a * Parent components should supply an 'onSubmit' callback which returns a
* promise; a spinner is shown until the promise resolves. * promise; a spinner is shown until the promise resolves.
* *
* The parent can also supply a 'getIntialValue' callback, which works in a * The parent can also supply a 'getInitialValue' callback, which works in a
* similarly asynchronous way. If this is not provided, the initial value is * similarly asynchronous way. If this is not provided, the initial value is
* taken from the 'initialValue' property. * taken from the 'initialValue' property.
*/ */
export default class EditableTextContainer extends React.Component { export default class EditableTextContainer extends React.Component {
constructor(props, context) { constructor(props) {
super(props, context); super(props);
this._unmounted = false; this._unmounted = false;
this.state = { this.state = {

View File

@ -21,6 +21,7 @@ import PropTypes from 'prop-types';
import {MatrixClient} from 'matrix-js-sdk'; import {MatrixClient} from 'matrix-js-sdk';
import FlairStore from '../../../stores/FlairStore'; import FlairStore from '../../../stores/FlairStore';
import dis from '../../../dispatcher'; import dis from '../../../dispatcher';
import MatrixClientContext from "../../../contexts/MatrixClientContext";
class FlairAvatar extends React.Component { class FlairAvatar extends React.Component {
@ -40,7 +41,7 @@ class FlairAvatar extends React.Component {
} }
render() { render() {
const httpUrl = this.context.matrixClient.mxcUrlToHttp( const httpUrl = this.context.mxcUrlToHttp(
this.props.groupProfile.avatarUrl, 16, 16, 'scale', false); this.props.groupProfile.avatarUrl, 16, 16, 'scale', false);
const tooltip = this.props.groupProfile.name ? const tooltip = this.props.groupProfile.name ?
`${this.props.groupProfile.name} (${this.props.groupProfile.groupId})`: `${this.props.groupProfile.name} (${this.props.groupProfile.groupId})`:
@ -62,9 +63,7 @@ FlairAvatar.propTypes = {
}), }),
}; };
FlairAvatar.contextTypes = { FlairAvatar.contextType = MatrixClientContext;
matrixClient: PropTypes.instanceOf(MatrixClient).isRequired,
};
export default class Flair extends React.Component { export default class Flair extends React.Component {
constructor() { constructor() {
@ -92,7 +91,7 @@ export default class Flair extends React.Component {
for (const groupId of groups) { for (const groupId of groups) {
let groupProfile = null; let groupProfile = null;
try { try {
groupProfile = await FlairStore.getGroupProfileCached(this.context.matrixClient, groupId); groupProfile = await FlairStore.getGroupProfileCached(this.context, groupId);
} catch (err) { } catch (err) {
console.error('Could not get profile for group', groupId, err); console.error('Could not get profile for group', groupId, err);
} }
@ -134,6 +133,4 @@ Flair.propTypes = {
groups: PropTypes.arrayOf(PropTypes.string), groups: PropTypes.arrayOf(PropTypes.string),
}; };
Flair.contextTypes = { Flair.contextType = MatrixClientContext;
matrixClient: PropTypes.instanceOf(MatrixClient).isRequired,
};

View File

@ -20,12 +20,13 @@ import createReactClass from 'create-react-class';
import sdk from '../../../index'; import sdk from '../../../index';
import dis from '../../../dispatcher'; import dis from '../../../dispatcher';
import classNames from 'classnames'; import classNames from 'classnames';
import { Room, RoomMember, MatrixClient } from 'matrix-js-sdk'; import { Room, RoomMember } from 'matrix-js-sdk';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import MatrixClientPeg from '../../../MatrixClientPeg'; import MatrixClientPeg from '../../../MatrixClientPeg';
import { getDisplayAliasForRoom } from '../../../Rooms'; import { getDisplayAliasForRoom } from '../../../Rooms';
import FlairStore from "../../../stores/FlairStore"; import FlairStore from "../../../stores/FlairStore";
import {getPrimaryPermalinkEntity} from "../../../utils/permalinks/Permalinks"; import {getPrimaryPermalinkEntity} from "../../../utils/permalinks/Permalinks";
import MatrixClientContext from "../../../contexts/MatrixClientContext";
// For URLs of matrix.to links in the timeline which have been reformatted by // For URLs of matrix.to links in the timeline which have been reformatted by
// HttpUtils transformTags to relative links. This excludes event URLs (with `[^\/]*`) // HttpUtils transformTags to relative links. This excludes event URLs (with `[^\/]*`)
@ -66,17 +67,6 @@ const Pill = createReactClass({
isSelected: PropTypes.bool, isSelected: PropTypes.bool,
}, },
childContextTypes: {
matrixClient: PropTypes.instanceOf(MatrixClient),
},
getChildContext() {
return {
matrixClient: this._matrixClient,
};
},
getInitialState() { getInitialState() {
return { return {
// ID/alias of the room/user // ID/alias of the room/user
@ -276,7 +266,8 @@ const Pill = createReactClass({
}); });
if (this.state.pillType) { if (this.state.pillType) {
return this.props.inMessage ? return <MatrixClientContext.Provider value={this._matrixClient}>
{ this.props.inMessage ?
<a className={classes} href={href} onClick={onClick} title={resource} data-offset-key={this.props.offsetKey}> <a className={classes} href={href} onClick={onClick} title={resource} data-offset-key={this.props.offsetKey}>
{ avatar } { avatar }
{ linkText } { linkText }
@ -284,7 +275,8 @@ const Pill = createReactClass({
<span className={classes} title={resource} data-offset-key={this.props.offsetKey}> <span className={classes} title={resource} data-offset-key={this.props.offsetKey}>
{ avatar } { avatar }
{ linkText } { linkText }
</span>; </span> }
</MatrixClientContext.Provider>;
} else { } else {
// Deliberately render nothing if the URL isn't recognised // Deliberately render nothing if the URL isn't recognised
return null; return null;

View File

@ -21,10 +21,11 @@ import {_t} from '../../../languageHandler';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import dis from '../../../dispatcher'; import dis from '../../../dispatcher';
import {wantsDateSeparator} from '../../../DateUtils'; import {wantsDateSeparator} from '../../../DateUtils';
import {MatrixEvent, MatrixClient} from 'matrix-js-sdk'; import {MatrixEvent} from 'matrix-js-sdk';
import {makeUserPermalink, RoomPermalinkCreator} from "../../../utils/permalinks/Permalinks"; import {makeUserPermalink, RoomPermalinkCreator} from "../../../utils/permalinks/Permalinks";
import SettingsStore from "../../../settings/SettingsStore"; import SettingsStore from "../../../settings/SettingsStore";
import escapeHtml from "escape-html"; import escapeHtml from "escape-html";
import MatrixClientContext from "../../../contexts/MatrixClientContext";
// This component does no cycle detection, simply because the only way to make such a cycle would be to // This component does no cycle detection, simply because the only way to make such a cycle would be to
// craft event_id's, using a homeserver that generates predictable event IDs; even then the impact would // craft event_id's, using a homeserver that generates predictable event IDs; even then the impact would
@ -38,12 +39,10 @@ export default class ReplyThread extends React.Component {
permalinkCreator: PropTypes.instanceOf(RoomPermalinkCreator).isRequired, permalinkCreator: PropTypes.instanceOf(RoomPermalinkCreator).isRequired,
}; };
static contextTypes = { static contextType = MatrixClientContext;
matrixClient: PropTypes.instanceOf(MatrixClient).isRequired,
};
constructor(props, context) { constructor(props) {
super(props, context); super(props);
this.state = { this.state = {
// The loaded events to be rendered as linear-replies // The loaded events to be rendered as linear-replies
@ -187,7 +186,7 @@ export default class ReplyThread extends React.Component {
componentWillMount() { componentWillMount() {
this.unmounted = false; this.unmounted = false;
this.room = this.context.matrixClient.getRoom(this.props.parentEv.getRoomId()); this.room = this.context.getRoom(this.props.parentEv.getRoomId());
this.room.on("Room.redaction", this.onRoomRedaction); this.room.on("Room.redaction", this.onRoomRedaction);
// same event handler as Room.redaction as for both we just do forceUpdate // same event handler as Room.redaction as for both we just do forceUpdate
this.room.on("Room.redactionCancelled", this.onRoomRedaction); this.room.on("Room.redactionCancelled", this.onRoomRedaction);
@ -259,7 +258,7 @@ export default class ReplyThread extends React.Component {
try { try {
// ask the client to fetch the event we want using the context API, only interface to do so is to ask // ask the client to fetch the event we want using the context API, only interface to do so is to ask
// for a timeline with that event, but once it is loaded we can use findEventById to look up the ev map // for a timeline with that event, but once it is loaded we can use findEventById to look up the ev map
await this.context.matrixClient.getEventTimeline(this.room.getUnfilteredTimelineSet(), eventId); await this.context.getEventTimeline(this.room.getUnfilteredTimelineSet(), eventId);
} catch (e) { } catch (e) {
// if it fails catch the error and return early, there's no point trying to find the event in this case. // if it fails catch the error and return early, there's no point trying to find the event in this case.
// Return null as it is falsey and thus should be treated as an error (as the event cannot be resolved). // Return null as it is falsey and thus should be treated as an error (as the event cannot be resolved).
@ -300,7 +299,7 @@ export default class ReplyThread extends React.Component {
} else if (this.state.loadedEv) { } else if (this.state.loadedEv) {
const ev = this.state.loadedEv; const ev = this.state.loadedEv;
const Pill = sdk.getComponent('elements.Pill'); const Pill = sdk.getComponent('elements.Pill');
const room = this.context.matrixClient.getRoom(ev.getRoomId()); const room = this.context.getRoom(ev.getRoomId());
header = <blockquote className="mx_ReplyThread"> header = <blockquote className="mx_ReplyThread">
{ {
_t('<a>In reply to</a> <pill>', {}, { _t('<a>In reply to</a> <pill>', {}, {

View File

@ -24,8 +24,8 @@ export default class SyntaxHighlight extends React.Component {
children: PropTypes.node, children: PropTypes.node,
}; };
constructor(props, context) { constructor(props) {
super(props, context); super(props);
this._ref = this._ref.bind(this); this._ref = this._ref.bind(this);
} }

View File

@ -20,7 +20,6 @@ import React, {createRef} from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import createReactClass from 'create-react-class'; import createReactClass from 'create-react-class';
import classNames from 'classnames'; import classNames from 'classnames';
import { MatrixClient } from 'matrix-js-sdk';
import sdk from '../../../index'; import sdk from '../../../index';
import dis from '../../../dispatcher'; import dis from '../../../dispatcher';
import {_t} from '../../../languageHandler'; import {_t} from '../../../languageHandler';
@ -31,6 +30,7 @@ import FlairStore from '../../../stores/FlairStore';
import GroupStore from '../../../stores/GroupStore'; import GroupStore from '../../../stores/GroupStore';
import TagOrderStore from '../../../stores/TagOrderStore'; import TagOrderStore from '../../../stores/TagOrderStore';
import {ContextMenu, ContextMenuButton, toRightOf} from "../../structures/ContextMenu"; import {ContextMenu, ContextMenuButton, toRightOf} from "../../structures/ContextMenu";
import MatrixClientContext from "../../../contexts/MatrixClientContext";
// A class for a child of TagPanel (possibly wrapped in a DNDTagTile) that represents // A class for a child of TagPanel (possibly wrapped in a DNDTagTile) that represents
// a thing to click on for the user to filter the visible rooms in the RoomList to: // a thing to click on for the user to filter the visible rooms in the RoomList to:
@ -46,8 +46,8 @@ export default createReactClass({
tag: PropTypes.string, tag: PropTypes.string,
}, },
contextTypes: { statics: {
matrixClient: PropTypes.instanceOf(MatrixClient).isRequired, contextType: MatrixClientContext,
}, },
getInitialState() { getInitialState() {
@ -81,7 +81,7 @@ export default createReactClass({
_onFlairStoreUpdated() { _onFlairStoreUpdated() {
if (this.unmounted) return; if (this.unmounted) return;
FlairStore.getGroupProfileCached( FlairStore.getGroupProfileCached(
this.context.matrixClient, this.context,
this.props.tag, this.props.tag,
).then((profile) => { ).then((profile) => {
if (this.unmounted) return; if (this.unmounted) return;
@ -145,7 +145,7 @@ export default createReactClass({
const name = profile.name || this.props.tag; const name = profile.name || this.props.tag;
const avatarHeight = 40; const avatarHeight = 40;
const httpUrl = profile.avatarUrl ? this.context.matrixClient.mxcUrlToHttp( const httpUrl = profile.avatarUrl ? this.context.mxcUrlToHttp(
profile.avatarUrl, avatarHeight, avatarHeight, "crop", profile.avatarUrl, avatarHeight, avatarHeight, "crop",
) : null; ) : null;

View File

@ -19,13 +19,13 @@ limitations under the License.
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import createReactClass from 'create-react-class'; import createReactClass from 'create-react-class';
import { MatrixClient } from 'matrix-js-sdk';
import sdk from '../../../index'; import sdk from '../../../index';
import dis from '../../../dispatcher'; import dis from '../../../dispatcher';
import {_t} from '../../../languageHandler'; import {_t} from '../../../languageHandler';
import classNames from 'classnames'; import classNames from 'classnames';
import MatrixClientPeg from "../../../MatrixClientPeg"; import MatrixClientPeg from "../../../MatrixClientPeg";
import {ContextMenu, ContextMenuButton, toRightOf} from "../../structures/ContextMenu"; import {ContextMenu, ContextMenuButton, toRightOf} from "../../structures/ContextMenu";
import MatrixClientContext from "../../../contexts/MatrixClientContext";
// XXX this class copies a lot from RoomTile.js // XXX this class copies a lot from RoomTile.js
export default createReactClass({ export default createReactClass({
@ -35,8 +35,8 @@ export default createReactClass({
group: PropTypes.object.isRequired, group: PropTypes.object.isRequired,
}, },
contextTypes: { statics: {
matrixClient: PropTypes.instanceOf(MatrixClient), contextType: MatrixClientContext,
}, },
getInitialState: function() { getInitialState: function() {
@ -58,7 +58,7 @@ export default createReactClass({
onMouseEnter: function() { onMouseEnter: function() {
const state = {hover: true}; const state = {hover: true};
// Only allow non-guests to access the context menu // Only allow non-guests to access the context menu
if (!this.context.matrixClient.isGuest()) { if (!this.context.isGuest()) {
state.badgeHover = true; state.badgeHover = true;
} }
this.setState(state); this.setState(state);
@ -118,7 +118,7 @@ export default createReactClass({
const groupName = this.props.group.name || this.props.group.groupId; const groupName = this.props.group.name || this.props.group.groupId;
const httpAvatarUrl = this.props.group.avatarUrl ? const httpAvatarUrl = this.props.group.avatarUrl ?
this.context.matrixClient.mxcUrlToHttp(this.props.group.avatarUrl, 24, 24) : null; this.context.mxcUrlToHttp(this.props.group.avatarUrl, 24, 24) : null;
const av = <BaseAvatar name={groupName} width={24} height={24} url={httpAvatarUrl} />; const av = <BaseAvatar name={groupName} width={24} height={24} url={httpAvatarUrl} />;

View File

@ -18,7 +18,6 @@ limitations under the License.
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import createReactClass from 'create-react-class'; import createReactClass from 'create-react-class';
import { MatrixClient } from 'matrix-js-sdk';
import dis from '../../../dispatcher'; import dis from '../../../dispatcher';
import Modal from '../../../Modal'; import Modal from '../../../Modal';
import sdk from '../../../index'; import sdk from '../../../index';
@ -26,12 +25,13 @@ import { _t } from '../../../languageHandler';
import { GroupMemberType } from '../../../groups'; import { GroupMemberType } from '../../../groups';
import GroupStore from '../../../stores/GroupStore'; import GroupStore from '../../../stores/GroupStore';
import AccessibleButton from '../elements/AccessibleButton'; import AccessibleButton from '../elements/AccessibleButton';
import MatrixClientContext from "../../../contexts/MatrixClientContext";
module.exports = createReactClass({ module.exports = createReactClass({
displayName: 'GroupMemberInfo', displayName: 'GroupMemberInfo',
contextTypes: { statics: {
matrixClient: PropTypes.instanceOf(MatrixClient), contextType: MatrixClientContext,
}, },
propTypes: { propTypes: {
@ -85,7 +85,7 @@ module.exports = createReactClass({
_onKick: function() { _onKick: function() {
const ConfirmUserActionDialog = sdk.getComponent("dialogs.ConfirmUserActionDialog"); const ConfirmUserActionDialog = sdk.getComponent("dialogs.ConfirmUserActionDialog");
Modal.createDialog(ConfirmUserActionDialog, { Modal.createDialog(ConfirmUserActionDialog, {
matrixClient: this.context.matrixClient, matrixClient: this.context,
groupMember: this.props.groupMember, groupMember: this.props.groupMember,
action: this.state.isUserInvited ? _t('Disinvite') : _t('Remove from community'), action: this.state.isUserInvited ? _t('Disinvite') : _t('Remove from community'),
title: this.state.isUserInvited ? _t('Disinvite this user from community?') title: this.state.isUserInvited ? _t('Disinvite this user from community?')
@ -95,7 +95,7 @@ module.exports = createReactClass({
if (!proceed) return; if (!proceed) return;
this.setState({removingUser: true}); this.setState({removingUser: true});
this.context.matrixClient.removeUserFromGroup( this.context.removeUserFromGroup(
this.props.groupId, this.props.groupMember.userId, this.props.groupId, this.props.groupMember.userId,
).then(() => { ).then(() => {
// return to the user list // return to the user list
@ -171,7 +171,7 @@ module.exports = createReactClass({
const avatarUrl = this.props.groupMember.avatarUrl; const avatarUrl = this.props.groupMember.avatarUrl;
let avatarElement; let avatarElement;
if (avatarUrl) { if (avatarUrl) {
const httpUrl = this.context.matrixClient.mxcUrlToHttp(avatarUrl, 800, 800); const httpUrl = this.context.mxcUrlToHttp(avatarUrl, 800, 800);
avatarElement = (<div className="mx_MemberInfo_avatar"> avatarElement = (<div className="mx_MemberInfo_avatar">
<img src={httpUrl} /> <img src={httpUrl} />
</div>); </div>);

View File

@ -19,10 +19,10 @@ limitations under the License.
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import createReactClass from 'create-react-class'; import createReactClass from 'create-react-class';
import { MatrixClient } from 'matrix-js-sdk';
import sdk from '../../../index'; import sdk from '../../../index';
import dis from '../../../dispatcher'; import dis from '../../../dispatcher';
import { GroupMemberType } from '../../../groups'; import { GroupMemberType } from '../../../groups';
import MatrixClientContext from "../../../contexts/MatrixClientContext";
export default createReactClass({ export default createReactClass({
displayName: 'GroupMemberTile', displayName: 'GroupMemberTile',
@ -36,8 +36,8 @@ export default createReactClass({
return {}; return {};
}, },
contextTypes: { statics: {
matrixClient: PropTypes.instanceOf(MatrixClient).isRequired, contextType: MatrixClientContext,
}, },
onClick: function(e) { onClick: function(e) {
@ -53,7 +53,7 @@ export default createReactClass({
const EntityTile = sdk.getComponent('rooms.EntityTile'); const EntityTile = sdk.getComponent('rooms.EntityTile');
const name = this.props.member.displayname || this.props.member.userId; const name = this.props.member.displayname || this.props.member.userId;
const avatarUrl = this.context.matrixClient.mxcUrlToHttp( const avatarUrl = this.context.mxcUrlToHttp(
this.props.member.avatarUrl, this.props.member.avatarUrl,
36, 36, 'crop', 36, 36, 'crop',
); );

View File

@ -17,18 +17,18 @@ limitations under the License.
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import createReactClass from 'create-react-class'; import createReactClass from 'create-react-class';
import { MatrixClient } from 'matrix-js-sdk';
import dis from '../../../dispatcher'; import dis from '../../../dispatcher';
import Modal from '../../../Modal'; import Modal from '../../../Modal';
import sdk from '../../../index'; import sdk from '../../../index';
import { _t } from '../../../languageHandler'; import { _t } from '../../../languageHandler';
import GroupStore from '../../../stores/GroupStore'; import GroupStore from '../../../stores/GroupStore';
import MatrixClientContext from "../../../contexts/MatrixClientContext";
module.exports = createReactClass({ module.exports = createReactClass({
displayName: 'GroupRoomInfo', displayName: 'GroupRoomInfo',
contextTypes: { statics: {
matrixClient: PropTypes.instanceOf(MatrixClient), contextType: MatrixClientContext,
}, },
propTypes: { propTypes: {
@ -206,7 +206,7 @@ module.exports = createReactClass({
const avatarUrl = this.state.groupRoom.avatarUrl; const avatarUrl = this.state.groupRoom.avatarUrl;
let avatarElement; let avatarElement;
if (avatarUrl) { if (avatarUrl) {
const httpUrl = this.context.matrixClient.mxcUrlToHttp(avatarUrl, 800, 800); const httpUrl = this.context.mxcUrlToHttp(avatarUrl, 800, 800);
avatarElement = (<div className="mx_MemberInfo_avatar"> avatarElement = (<div className="mx_MemberInfo_avatar">
<img src={httpUrl} /> <img src={httpUrl} />
</div>); </div>);

View File

@ -17,10 +17,10 @@ limitations under the License.
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import createReactClass from 'create-react-class'; import createReactClass from 'create-react-class';
import {MatrixClient} from 'matrix-js-sdk';
import sdk from '../../../index'; import sdk from '../../../index';
import dis from '../../../dispatcher'; import dis from '../../../dispatcher';
import { GroupRoomType } from '../../../groups'; import { GroupRoomType } from '../../../groups';
import MatrixClientContext from "../../../contexts/MatrixClientContext";
const GroupRoomTile = createReactClass({ const GroupRoomTile = createReactClass({
displayName: 'GroupRoomTile', displayName: 'GroupRoomTile',
@ -41,7 +41,7 @@ const GroupRoomTile = createReactClass({
render: function() { render: function() {
const BaseAvatar = sdk.getComponent('avatars.BaseAvatar'); const BaseAvatar = sdk.getComponent('avatars.BaseAvatar');
const AccessibleButton = sdk.getComponent('elements.AccessibleButton'); const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
const avatarUrl = this.context.matrixClient.mxcUrlToHttp( const avatarUrl = this.context.mxcUrlToHttp(
this.props.groupRoom.avatarUrl, this.props.groupRoom.avatarUrl,
36, 36, 'crop', 36, 36, 'crop',
); );
@ -66,9 +66,7 @@ const GroupRoomTile = createReactClass({
}, },
}); });
GroupRoomTile.contextTypes = { GroupRoomTile.contextType = MatrixClientContext;
matrixClient: PropTypes.instanceOf(MatrixClient).isRequired,
};
export default GroupRoomTile; export default GroupRoomTile;

View File

@ -22,6 +22,7 @@ import { Draggable, Droppable } from 'react-beautiful-dnd';
import sdk from '../../../index'; import sdk from '../../../index';
import dis from '../../../dispatcher'; import dis from '../../../dispatcher';
import FlairStore from '../../../stores/FlairStore'; import FlairStore from '../../../stores/FlairStore';
import MatrixClientContext from "../../../contexts/MatrixClientContext";
function nop() {} function nop() {}
@ -37,8 +38,8 @@ const GroupTile = createReactClass({
draggable: PropTypes.bool, draggable: PropTypes.bool,
}, },
contextTypes: { statics: {
matrixClient: PropTypes.instanceOf(MatrixClient).isRequired, contextType: MatrixClientContext,
}, },
getInitialState() { getInitialState() {
@ -56,7 +57,7 @@ const GroupTile = createReactClass({
}, },
componentWillMount: function() { componentWillMount: function() {
FlairStore.getGroupProfileCached(this.context.matrixClient, this.props.groupId).then((profile) => { FlairStore.getGroupProfileCached(this.context, this.props.groupId).then((profile) => {
this.setState({profile}); this.setState({profile});
}).catch((err) => { }).catch((err) => {
console.error('Error whilst getting cached profile for GroupTile', err); console.error('Error whilst getting cached profile for GroupTile', err);
@ -80,7 +81,7 @@ const GroupTile = createReactClass({
const descElement = this.props.showDescription ? const descElement = this.props.showDescription ?
<div className="mx_GroupTile_desc">{ profile.shortDescription }</div> : <div className="mx_GroupTile_desc">{ profile.shortDescription }</div> :
<div />; <div />;
const httpUrl = profile.avatarUrl ? this.context.matrixClient.mxcUrlToHttp( const httpUrl = profile.avatarUrl ? this.context.mxcUrlToHttp(
profile.avatarUrl, avatarHeight, avatarHeight, "crop") : null; profile.avatarUrl, avatarHeight, avatarHeight, "crop") : null;
let avatarElement = ( let avatarElement = (

View File

@ -15,17 +15,16 @@ limitations under the License.
*/ */
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types';
import createReactClass from 'create-react-class'; import createReactClass from 'create-react-class';
import sdk from '../../../index'; import sdk from '../../../index';
import { MatrixClient } from 'matrix-js-sdk';
import { _t } from '../../../languageHandler'; import { _t } from '../../../languageHandler';
import MatrixClientContext from "../../../contexts/MatrixClientContext";
export default createReactClass({ export default createReactClass({
displayName: 'GroupUserSettings', displayName: 'GroupUserSettings',
contextTypes: { statics: {
matrixClient: PropTypes.instanceOf(MatrixClient), contextType: MatrixClientContext,
}, },
getInitialState() { getInitialState() {
@ -36,7 +35,7 @@ export default createReactClass({
}, },
componentWillMount: function() { componentWillMount: function() {
this.context.matrixClient.getJoinedGroups().then((result) => { this.context.getJoinedGroups().then((result) => {
this.setState({groups: result.groups || [], error: null}); this.setState({groups: result.groups || [], error: null});
}, (err) => { }, (err) => {
console.error(err); console.error(err);

View File

@ -26,6 +26,7 @@ import {decryptFile} from '../../../utils/DecryptFile';
import Tinter from '../../../Tinter'; import Tinter from '../../../Tinter';
import request from 'browser-request'; import request from 'browser-request';
import Modal from '../../../Modal'; import Modal from '../../../Modal';
import SdkConfig from "../../../SdkConfig";
// A cached tinted copy of require("../../../../res/img/download.svg") // A cached tinted copy of require("../../../../res/img/download.svg")
@ -214,10 +215,6 @@ module.exports = createReactClass({
tileShape: PropTypes.string, tileShape: PropTypes.string,
}, },
contextTypes: {
appConfig: PropTypes.object,
},
/** /**
* Extracts a human readable label for the file attachment to use as * Extracts a human readable label for the file attachment to use as
* link text. * link text.
@ -360,8 +357,9 @@ module.exports = createReactClass({
// If the attachment is encryped then put the link inside an iframe. // If the attachment is encryped then put the link inside an iframe.
let renderer_url = DEFAULT_CROSS_ORIGIN_RENDERER; let renderer_url = DEFAULT_CROSS_ORIGIN_RENDERER;
if (this.context.appConfig && this.context.appConfig.cross_origin_renderer_url) { const appConfig = SdkConfig.get();
renderer_url = this.context.appConfig.cross_origin_renderer_url; if (appConfig && appConfig.cross_origin_renderer_url) {
renderer_url = appConfig.cross_origin_renderer_url;
} }
renderer_url += "?origin=" + encodeURIComponent(window.location.origin); renderer_url += "?origin=" + encodeURIComponent(window.location.origin);
return ( return (

View File

@ -18,7 +18,6 @@ limitations under the License.
import React, {createRef} from 'react'; import React, {createRef} from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { MatrixClient } from 'matrix-js-sdk';
import MFileBody from './MFileBody'; import MFileBody from './MFileBody';
import Modal from '../../../Modal'; import Modal from '../../../Modal';
@ -26,6 +25,7 @@ import sdk from '../../../index';
import { decryptFile } from '../../../utils/DecryptFile'; import { decryptFile } from '../../../utils/DecryptFile';
import { _t } from '../../../languageHandler'; import { _t } from '../../../languageHandler';
import SettingsStore from "../../../settings/SettingsStore"; import SettingsStore from "../../../settings/SettingsStore";
import MatrixClientContext from "../../../contexts/MatrixClientContext";
export default class MImageBody extends React.Component { export default class MImageBody extends React.Component {
static propTypes = { static propTypes = {
@ -39,9 +39,7 @@ export default class MImageBody extends React.Component {
maxImageHeight: PropTypes.number, maxImageHeight: PropTypes.number,
}; };
static contextTypes = { static contextType = MatrixClientContext;
matrixClient: PropTypes.instanceOf(MatrixClient),
};
constructor(props) { constructor(props) {
super(props); super(props);
@ -71,7 +69,7 @@ export default class MImageBody extends React.Component {
componentWillMount() { componentWillMount() {
this.unmounted = false; this.unmounted = false;
this.context.matrixClient.on('sync', this.onClientSync); this.context.on('sync', this.onClientSync);
} }
// FIXME: factor this out and aplpy it to MVideoBody and MAudioBody too! // FIXME: factor this out and aplpy it to MVideoBody and MAudioBody too!
@ -174,7 +172,7 @@ export default class MImageBody extends React.Component {
if (content.file !== undefined) { if (content.file !== undefined) {
return this.state.decryptedUrl; return this.state.decryptedUrl;
} else { } else {
return this.context.matrixClient.mxcUrlToHttp(content.url); return this.context.mxcUrlToHttp(content.url);
} }
} }
@ -198,7 +196,7 @@ export default class MImageBody extends React.Component {
// special case to return clientside sender-generated thumbnails for SVGs, if any, // special case to return clientside sender-generated thumbnails for SVGs, if any,
// given we deliberately don't thumbnail them serverside to prevent // given we deliberately don't thumbnail them serverside to prevent
// billion lol attacks and similar // billion lol attacks and similar
return this.context.matrixClient.mxcUrlToHttp( return this.context.mxcUrlToHttp(
content.info.thumbnail_url, content.info.thumbnail_url,
thumbWidth, thumbWidth,
thumbHeight, thumbHeight,
@ -221,7 +219,7 @@ export default class MImageBody extends React.Component {
pixelRatio === 1.0 || pixelRatio === 1.0 ||
(!info || !info.w || !info.h || !info.size) (!info || !info.w || !info.h || !info.size)
) { ) {
return this.context.matrixClient.mxcUrlToHttp(content.url, thumbWidth, thumbHeight); return this.context.mxcUrlToHttp(content.url, thumbWidth, thumbHeight);
} else { } else {
// we should only request thumbnails if the image is bigger than 800x600 // we should only request thumbnails if the image is bigger than 800x600
// (or 1600x1200 on retina) otherwise the image in the timeline will just // (or 1600x1200 on retina) otherwise the image in the timeline will just
@ -242,7 +240,7 @@ export default class MImageBody extends React.Component {
// image is too large physically and bytewise to clutter our timeline so // image is too large physically and bytewise to clutter our timeline so
// we ask for a thumbnail, despite knowing that it will be max 800x600 // we ask for a thumbnail, despite knowing that it will be max 800x600
// despite us being retina (as synapse doesn't do 1600x1200 thumbs yet). // despite us being retina (as synapse doesn't do 1600x1200 thumbs yet).
return this.context.matrixClient.mxcUrlToHttp( return this.context.mxcUrlToHttp(
content.url, content.url,
thumbWidth, thumbWidth,
thumbHeight, thumbHeight,
@ -251,7 +249,7 @@ export default class MImageBody extends React.Component {
// download the original image otherwise, so we can scale it client side // download the original image otherwise, so we can scale it client side
// to take pixelRatio into account. // to take pixelRatio into account.
// ( no width/height means we want the original image) // ( no width/height means we want the original image)
return this.context.matrixClient.mxcUrlToHttp( return this.context.mxcUrlToHttp(
content.url, content.url,
); );
} }
@ -308,7 +306,7 @@ export default class MImageBody extends React.Component {
componentWillUnmount() { componentWillUnmount() {
this.unmounted = true; this.unmounted = true;
this.context.matrixClient.removeListener('sync', this.onClientSync); this.context.removeListener('sync', this.onClientSync);
this._afterComponentWillUnmount(); this._afterComponentWillUnmount();
if (this.state.decryptedUrl) { if (this.state.decryptedUrl) {

View File

@ -25,7 +25,7 @@ import dis from '../../../dispatcher';
import Modal from '../../../Modal'; import Modal from '../../../Modal';
import {aboveLeftOf, ContextMenu, ContextMenuButton, useContextMenu} from '../../structures/ContextMenu'; import {aboveLeftOf, ContextMenu, ContextMenuButton, useContextMenu} from '../../structures/ContextMenu';
import { isContentActionable, canEditContent } from '../../../utils/EventUtils'; import { isContentActionable, canEditContent } from '../../../utils/EventUtils';
import {RoomContext} from "../../structures/RoomView"; import RoomContext from "../../../contexts/RoomContext";
const OptionsButton = ({mxEvent, getTile, getReplyThread, permalinkCreator, onFocusChange}) => { const OptionsButton = ({mxEvent, getTile, getReplyThread, permalinkCreator, onFocusChange}) => {
const [menuDisplayed, button, openMenu, closeMenu] = useContextMenu(); const [menuDisplayed, button, openMenu, closeMenu] = useContextMenu();
@ -117,9 +117,7 @@ export default class MessageActionBar extends React.PureComponent {
onFocusChange: PropTypes.func, onFocusChange: PropTypes.func,
}; };
static contextTypes = { static contextType = RoomContext;
room: RoomContext,
};
componentDidMount() { componentDidMount() {
this.props.mxEvent.on("Event.decrypted", this.onDecrypted); this.props.mxEvent.on("Event.decrypted", this.onDecrypted);
@ -164,12 +162,12 @@ export default class MessageActionBar extends React.PureComponent {
let editButton; let editButton;
if (isContentActionable(this.props.mxEvent)) { if (isContentActionable(this.props.mxEvent)) {
if (this.context.room.canReact) { if (this.context.canReact) {
reactButton = ( reactButton = (
<ReactButton mxEvent={this.props.mxEvent} reactions={this.props.reactions} onFocusChange={this.onFocusChange} /> <ReactButton mxEvent={this.props.mxEvent} reactions={this.props.reactions} onFocusChange={this.onFocusChange} />
); );
} }
if (this.context.room.canReply) { if (this.context.canReply) {
replyButton = <AccessibleButton replyButton = <AccessibleButton
className="mx_MessageActionBar_maskButton mx_MessageActionBar_replyButton" className="mx_MessageActionBar_maskButton mx_MessageActionBar_replyButton"
title={_t("Reply")} title={_t("Reply")}

View File

@ -17,11 +17,11 @@
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import createReactClass from 'create-react-class'; import createReactClass from 'create-react-class';
import {MatrixClient} from 'matrix-js-sdk';
import Flair from '../elements/Flair.js'; import Flair from '../elements/Flair.js';
import FlairStore from '../../../stores/FlairStore'; import FlairStore from '../../../stores/FlairStore';
import { _t } from '../../../languageHandler'; import { _t } from '../../../languageHandler';
import {getUserNameColorClass} from '../../../utils/FormattingUtils'; import {getUserNameColorClass} from '../../../utils/FormattingUtils';
import MatrixClientContext from "../../../contexts/MatrixClientContext";
export default createReactClass({ export default createReactClass({
displayName: 'SenderProfile', displayName: 'SenderProfile',
@ -31,8 +31,8 @@ export default createReactClass({
onClick: PropTypes.func, onClick: PropTypes.func,
}, },
contextTypes: { statics: {
matrixClient: PropTypes.instanceOf(MatrixClient), contextType: MatrixClientContext,
}, },
getInitialState() { getInitialState() {
@ -47,18 +47,18 @@ export default createReactClass({
this._updateRelatedGroups(); this._updateRelatedGroups();
FlairStore.getPublicisedGroupsCached( FlairStore.getPublicisedGroupsCached(
this.context.matrixClient, this.props.mxEvent.getSender(), this.context, this.props.mxEvent.getSender(),
).then((userGroups) => { ).then((userGroups) => {
if (this.unmounted) return; if (this.unmounted) return;
this.setState({userGroups}); this.setState({userGroups});
}); });
this.context.matrixClient.on('RoomState.events', this.onRoomStateEvents); this.context.on('RoomState.events', this.onRoomStateEvents);
}, },
componentWillUnmount() { componentWillUnmount() {
this.unmounted = true; this.unmounted = true;
this.context.matrixClient.removeListener('RoomState.events', this.onRoomStateEvents); this.context.removeListener('RoomState.events', this.onRoomStateEvents);
}, },
onRoomStateEvents(event) { onRoomStateEvents(event) {
@ -71,7 +71,7 @@ export default createReactClass({
_updateRelatedGroups() { _updateRelatedGroups() {
if (this.unmounted) return; if (this.unmounted) return;
const room = this.context.matrixClient.getRoom(this.props.mxEvent.getRoomId()); const room = this.context.getRoom(this.props.mxEvent.getRoomId());
if (!room) return; if (!room) return;
const relatedGroupsEvent = room.currentState.getStateEvents('m.room.related_groups', ''); const relatedGroupsEvent = room.currentState.getStateEvents('m.room.related_groups', '');

View File

@ -17,7 +17,7 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import React, {useCallback, useMemo, useState, useEffect} from 'react'; import React, {useCallback, useMemo, useState, useEffect, useContext} from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import classNames from 'classnames'; import classNames from 'classnames';
import {Group, RoomMember, User} from 'matrix-js-sdk'; import {Group, RoomMember, User} from 'matrix-js-sdk';
@ -37,9 +37,9 @@ import MultiInviter from "../../../utils/MultiInviter";
import GroupStore from "../../../stores/GroupStore"; import GroupStore from "../../../stores/GroupStore";
import MatrixClientPeg from "../../../MatrixClientPeg"; import MatrixClientPeg from "../../../MatrixClientPeg";
import E2EIcon from "../rooms/E2EIcon"; import E2EIcon from "../rooms/E2EIcon";
import withLegacyMatrixClient from "../../../utils/withLegacyMatrixClient";
import {useEventEmitter} from "../../../hooks/useEventEmitter"; import {useEventEmitter} from "../../../hooks/useEventEmitter";
import {textualPowerLevel} from '../../../Roles'; import {textualPowerLevel} from '../../../Roles';
import MatrixClientContext from "../../../contexts/MatrixClientContext";
const _disambiguateDevices = (devices) => { const _disambiguateDevices = (devices) => {
const names = Object.create(null); const names = Object.create(null);
@ -203,7 +203,9 @@ function DevicesSection({devices, userId, loading}) {
); );
} }
const UserOptionsSection = withLegacyMatrixClient(({matrixClient: cli, member, isIgnored, canInvite, devices}) => { const UserOptionsSection = ({member, isIgnored, canInvite, devices}) => {
const cli = useContext(MatrixClientContext);
let ignoreButton = null; let ignoreButton = null;
let insertPillButton = null; let insertPillButton = null;
let inviteUserButton = null; let inviteUserButton = null;
@ -336,7 +338,7 @@ const UserOptionsSection = withLegacyMatrixClient(({matrixClient: cli, member, i
</div> </div>
</div> </div>
); );
}); };
const _warnSelfDemote = async () => { const _warnSelfDemote = async () => {
const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog"); const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
@ -404,7 +406,9 @@ const useRoomPowerLevels = (cli, room) => {
return powerLevels; return powerLevels;
}; };
const RoomKickButton = withLegacyMatrixClient(({matrixClient: cli, member, startUpdating, stopUpdating}) => { const RoomKickButton = ({member, startUpdating, stopUpdating}) => {
const cli = useContext(MatrixClientContext);
const onKick = async () => { const onKick = async () => {
const ConfirmUserActionDialog = sdk.getComponent("dialogs.ConfirmUserActionDialog"); const ConfirmUserActionDialog = sdk.getComponent("dialogs.ConfirmUserActionDialog");
const {finished} = Modal.createTrackedDialog( const {finished} = Modal.createTrackedDialog(
@ -444,9 +448,11 @@ const RoomKickButton = withLegacyMatrixClient(({matrixClient: cli, member, start
return <AccessibleButton className="mx_UserInfo_field mx_UserInfo_destructive" onClick={onKick}> return <AccessibleButton className="mx_UserInfo_field mx_UserInfo_destructive" onClick={onKick}>
{ kickLabel } { kickLabel }
</AccessibleButton>; </AccessibleButton>;
}); };
const RedactMessagesButton = ({member}) => {
const cli = useContext(MatrixClientContext);
const RedactMessagesButton = withLegacyMatrixClient(({matrixClient: cli, member}) => {
const onRedactAllMessages = async () => { const onRedactAllMessages = async () => {
const {roomId, userId} = member; const {roomId, userId} = member;
const room = cli.getRoom(roomId); const room = cli.getRoom(roomId);
@ -517,9 +523,11 @@ const RedactMessagesButton = withLegacyMatrixClient(({matrixClient: cli, member}
return <AccessibleButton className="mx_UserInfo_field mx_UserInfo_destructive" onClick={onRedactAllMessages}> return <AccessibleButton className="mx_UserInfo_field mx_UserInfo_destructive" onClick={onRedactAllMessages}>
{ _t("Remove recent messages") } { _t("Remove recent messages") }
</AccessibleButton>; </AccessibleButton>;
}); };
const BanToggleButton = ({member, startUpdating, stopUpdating}) => {
const cli = useContext(MatrixClientContext);
const BanToggleButton = withLegacyMatrixClient(({matrixClient: cli, member, startUpdating, stopUpdating}) => {
const onBanOrUnban = async () => { const onBanOrUnban = async () => {
const ConfirmUserActionDialog = sdk.getComponent("dialogs.ConfirmUserActionDialog"); const ConfirmUserActionDialog = sdk.getComponent("dialogs.ConfirmUserActionDialog");
const {finished} = Modal.createTrackedDialog( const {finished} = Modal.createTrackedDialog(
@ -573,10 +581,11 @@ const BanToggleButton = withLegacyMatrixClient(({matrixClient: cli, member, star
return <AccessibleButton className={classes} onClick={onBanOrUnban}> return <AccessibleButton className={classes} onClick={onBanOrUnban}>
{ label } { label }
</AccessibleButton>; </AccessibleButton>;
}); };
const MuteToggleButton = ({member, room, powerLevels, startUpdating, stopUpdating}) => {
const cli = useContext(MatrixClientContext);
const MuteToggleButton = withLegacyMatrixClient(
({matrixClient: cli, member, room, powerLevels, startUpdating, stopUpdating}) => {
const isMuted = _isMuted(member, powerLevels); const isMuted = _isMuted(member, powerLevels);
const onMuteToggle = async () => { const onMuteToggle = async () => {
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog"); const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
@ -635,11 +644,10 @@ const MuteToggleButton = withLegacyMatrixClient(
return <AccessibleButton className={classes} onClick={onMuteToggle}> return <AccessibleButton className={classes} onClick={onMuteToggle}>
{ muteLabel } { muteLabel }
</AccessibleButton>; </AccessibleButton>;
}, };
);
const RoomAdminToolsContainer = withLegacyMatrixClient( const RoomAdminToolsContainer = ({room, children, member, startUpdating, stopUpdating, powerLevels}) => {
({matrixClient: cli, room, children, member, startUpdating, stopUpdating, powerLevels}) => { const cli = useContext(MatrixClientContext);
let kickButton; let kickButton;
let banButton; let banButton;
let muteButton; let muteButton;
@ -688,11 +696,11 @@ const RoomAdminToolsContainer = withLegacyMatrixClient(
} }
return <div />; return <div />;
}, };
);
const GroupAdminToolsSection = ({children, groupId, groupMember, startUpdating, stopUpdating}) => {
const cli = useContext(MatrixClientContext);
const GroupAdminToolsSection = withLegacyMatrixClient(
({matrixClient: cli, children, groupId, groupMember, startUpdating, stopUpdating}) => {
const [isPrivileged, setIsPrivileged] = useState(false); const [isPrivileged, setIsPrivileged] = useState(false);
const [isInvited, setIsInvited] = useState(false); const [isInvited, setIsInvited] = useState(false);
@ -772,8 +780,7 @@ const GroupAdminToolsSection = withLegacyMatrixClient(
} }
return <div />; return <div />;
}, };
);
const GroupMember = PropTypes.shape({ const GroupMember = PropTypes.shape({
userId: PropTypes.string.isRequired, userId: PropTypes.string.isRequired,
@ -849,7 +856,9 @@ function useRoomPermissions(cli, room, user) {
return roomPermissions; return roomPermissions;
} }
const PowerLevelSection = withLegacyMatrixClient(({matrixClient: cli, user, room, roomPermissions, powerLevels}) => { const PowerLevelSection = ({user, room, roomPermissions, powerLevels}) => {
const cli = useContext(MatrixClientContext);
const [isEditing, setEditing] = useState(false); const [isEditing, setEditing] = useState(false);
if (room && user.roomId) { // is in room if (room && user.roomId) { // is in room
if (isEditing) { if (isEditing) {
@ -876,9 +885,11 @@ const PowerLevelSection = withLegacyMatrixClient(({matrixClient: cli, user, room
} else { } else {
return null; return null;
} }
}); };
const PowerLevelEditor = ({user, room, roomPermissions, onFinished}) => {
const cli = useContext(MatrixClientContext);
const PowerLevelEditor = withLegacyMatrixClient(({matrixClient: cli, user, room, roomPermissions, onFinished}) => {
const [isUpdating, setIsUpdating] = useState(false); const [isUpdating, setIsUpdating] = useState(false);
const [selectedPowerLevel, setSelectedPowerLevel] = useState(parseInt(user.powerLevel, 10)); const [selectedPowerLevel, setSelectedPowerLevel] = useState(parseInt(user.powerLevel, 10));
const [isDirty, setIsDirty] = useState(false); const [isDirty, setIsDirty] = useState(false);
@ -982,10 +993,11 @@ const PowerLevelEditor = withLegacyMatrixClient(({matrixClient: cli, user, room,
{buttonOrSpinner} {buttonOrSpinner}
</div> </div>
); );
}); };
const UserInfo = ({user, groupId, roomId, onClose}) => {
const cli = useContext(MatrixClientContext);
// cli is injected by withLegacyMatrixClient
const UserInfo = withLegacyMatrixClient(({matrixClient: cli, user, groupId, roomId, onClose}) => {
// Load room if we are given a room id and memoize it // Load room if we are given a room id and memoize it
const room = useMemo(() => roomId ? cli.getRoom(roomId) : null, [cli, roomId]); const room = useMemo(() => roomId ? cli.getRoom(roomId) : null, [cli, roomId]);
@ -1320,7 +1332,7 @@ const UserInfo = withLegacyMatrixClient(({matrixClient: cli, user, groupId, room
</AutoHideScrollbar> </AutoHideScrollbar>
</div> </div>
); );
}); };
UserInfo.propTypes = { UserInfo.propTypes = {
user: PropTypes.oneOfType([ user: PropTypes.oneOfType([

View File

@ -16,11 +16,12 @@ limitations under the License.
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import {MatrixEvent, MatrixClient} from 'matrix-js-sdk'; import {MatrixEvent} from 'matrix-js-sdk';
import sdk from '../../../index'; import sdk from '../../../index';
import { _t } from '../../../languageHandler'; import { _t } from '../../../languageHandler';
import Modal from '../../../Modal'; import Modal from '../../../Modal';
import ErrorDialog from "../dialogs/ErrorDialog"; import ErrorDialog from "../dialogs/ErrorDialog";
import MatrixClientContext from "../../../contexts/MatrixClientContext";
const GROUP_ID_REGEX = /\+\S+:\S+/; const GROUP_ID_REGEX = /\+\S+:\S+/;
@ -31,9 +32,7 @@ export default class RelatedGroupSettings extends React.Component {
relatedGroupsEvent: PropTypes.instanceOf(MatrixEvent), relatedGroupsEvent: PropTypes.instanceOf(MatrixEvent),
}; };
static contextTypes = { static contextType = MatrixClientContext;
matrixClient: PropTypes.instanceOf(MatrixClient),
};
static defaultProps = { static defaultProps = {
canSetRelatedGroups: false, canSetRelatedGroups: false,
@ -49,7 +48,7 @@ export default class RelatedGroupSettings extends React.Component {
} }
updateGroups(newGroupsList) { updateGroups(newGroupsList) {
this.context.matrixClient.sendStateEvent(this.props.roomId, 'm.room.related_groups', { this.context.sendStateEvent(this.props.roomId, 'm.room.related_groups', {
groups: newGroupsList, groups: newGroupsList,
}, '').catch((err) => { }, '').catch((err) => {
console.error(err); console.error(err);
@ -99,7 +98,7 @@ export default class RelatedGroupSettings extends React.Component {
}; };
render() { render() {
const localDomain = this.context.matrixClient.getDomain(); const localDomain = this.context.getDomain();
const EditableItemList = sdk.getComponent('elements.EditableItemList'); const EditableItemList = sdk.getComponent('elements.EditableItemList');
return <div> return <div>
<EditableItemList <EditableItemList

View File

@ -80,8 +80,8 @@ export default class BasicMessageEditor extends React.Component {
initialCaret: PropTypes.object, // See DocumentPosition in editor/model.js initialCaret: PropTypes.object, // See DocumentPosition in editor/model.js
}; };
constructor(props, context) { constructor(props) {
super(props, context); super(props);
this.state = { this.state = {
autoComplete: null, autoComplete: null,
}; };

View File

@ -31,6 +31,7 @@ import classNames from 'classnames';
import {EventStatus} from 'matrix-js-sdk'; import {EventStatus} from 'matrix-js-sdk';
import BasicMessageComposer from "./BasicMessageComposer"; import BasicMessageComposer from "./BasicMessageComposer";
import {Key} from "../../../Keyboard"; import {Key} from "../../../Keyboard";
import MatrixClientContext from "../../../contexts/MatrixClientContext";
function _isReply(mxEvent) { function _isReply(mxEvent) {
const relatesTo = mxEvent.getContent()["m.relates_to"]; const relatesTo = mxEvent.getContent()["m.relates_to"];
@ -105,12 +106,10 @@ export default class EditMessageComposer extends React.Component {
editState: PropTypes.instanceOf(EditorStateTransfer).isRequired, editState: PropTypes.instanceOf(EditorStateTransfer).isRequired,
}; };
static contextTypes = { static contextType = MatrixClientContext;
matrixClient: PropTypes.instanceOf(MatrixClient).isRequired,
};
constructor(props, context) { constructor(props) {
super(props, context); super(props);
this.model = null; this.model = null;
this._editorRef = null; this._editorRef = null;
@ -124,7 +123,7 @@ export default class EditMessageComposer extends React.Component {
}; };
_getRoom() { _getRoom() {
return this.context.matrixClient.getRoom(this.props.editState.getEvent().getRoomId()); return this.context.getRoom(this.props.editState.getEvent().getRoomId());
} }
_onKeyDown = (event) => { _onKeyDown = (event) => {
@ -190,7 +189,7 @@ export default class EditMessageComposer extends React.Component {
if (this._isContentModified(newContent)) { if (this._isContentModified(newContent)) {
const roomId = editedEvent.getRoomId(); const roomId = editedEvent.getRoomId();
this._cancelPreviousPendingEdit(); this._cancelPreviousPendingEdit();
this.context.matrixClient.sendMessage(roomId, editContent); this.context.sendMessage(roomId, editContent);
} }
// close the event editing and focus composer // close the event editing and focus composer
@ -205,7 +204,7 @@ export default class EditMessageComposer extends React.Component {
previousEdit.status === EventStatus.QUEUED || previousEdit.status === EventStatus.QUEUED ||
previousEdit.status === EventStatus.NOT_SENT previousEdit.status === EventStatus.NOT_SENT
)) { )) {
this.context.matrixClient.cancelPendingEvent(previousEdit); this.context.cancelPendingEvent(previousEdit);
} }
} }
@ -232,7 +231,7 @@ export default class EditMessageComposer extends React.Component {
_createEditorModel() { _createEditorModel() {
const {editState} = this.props; const {editState} = this.props;
const room = this._getRoom(); const room = this._getRoom();
const partCreator = new PartCreator(room, this.context.matrixClient); const partCreator = new PartCreator(room, this.context);
let parts; let parts;
if (editState.hasEditorState()) { if (editState.hasEditorState()) {
// if restoring state from a previous editor, // if restoring state from a previous editor,

View File

@ -31,10 +31,11 @@ const TextForEvent = require('../../../TextForEvent');
import dis from '../../../dispatcher'; import dis from '../../../dispatcher';
import SettingsStore from "../../../settings/SettingsStore"; import SettingsStore from "../../../settings/SettingsStore";
import {EventStatus, MatrixClient} from 'matrix-js-sdk'; import {EventStatus} from 'matrix-js-sdk';
import {formatTime} from "../../../DateUtils"; import {formatTime} from "../../../DateUtils";
import MatrixClientPeg from '../../../MatrixClientPeg'; import MatrixClientPeg from '../../../MatrixClientPeg';
import {ALL_RULE_TYPES} from "../../../mjolnir/BanList"; import {ALL_RULE_TYPES} from "../../../mjolnir/BanList";
import MatrixClientContext from "../../../contexts/MatrixClientContext";
const ObjectUtils = require('../../../ObjectUtils'); const ObjectUtils = require('../../../ObjectUtils');
@ -222,8 +223,8 @@ module.exports = createReactClass({
}; };
}, },
contextTypes: { statics: {
matrixClient: PropTypes.instanceOf(MatrixClient).isRequired, contextType: MatrixClientContext,
}, },
componentWillMount: function() { componentWillMount: function() {
@ -237,7 +238,7 @@ module.exports = createReactClass({
componentDidMount: function() { componentDidMount: function() {
this._suppressReadReceiptAnimation = false; this._suppressReadReceiptAnimation = false;
const client = this.context.matrixClient; const client = this.context;
client.on("deviceVerificationChanged", this.onDeviceVerificationChanged); client.on("deviceVerificationChanged", this.onDeviceVerificationChanged);
this.props.mxEvent.on("Event.decrypted", this._onDecrypted); this.props.mxEvent.on("Event.decrypted", this._onDecrypted);
if (this.props.showReactions) { if (this.props.showReactions) {
@ -262,7 +263,7 @@ module.exports = createReactClass({
}, },
componentWillUnmount: function() { componentWillUnmount: function() {
const client = this.context.matrixClient; const client = this.context;
client.removeListener("deviceVerificationChanged", this.onDeviceVerificationChanged); client.removeListener("deviceVerificationChanged", this.onDeviceVerificationChanged);
this.props.mxEvent.removeListener("Event.decrypted", this._onDecrypted); this.props.mxEvent.removeListener("Event.decrypted", this._onDecrypted);
if (this.props.showReactions) { if (this.props.showReactions) {
@ -291,7 +292,7 @@ module.exports = createReactClass({
return; return;
} }
const verified = await this.context.matrixClient.isEventSenderVerified(mxEvent); const verified = await this.context.isEventSenderVerified(mxEvent);
this.setState({ this.setState({
verified: verified, verified: verified,
}, () => { }, () => {
@ -349,11 +350,11 @@ module.exports = createReactClass({
}, },
shouldHighlight: function() { shouldHighlight: function() {
const actions = this.context.matrixClient.getPushActionsForEvent(this.props.mxEvent); const actions = this.context.getPushActionsForEvent(this.props.mxEvent);
if (!actions || !actions.tweaks) { return false; } if (!actions || !actions.tweaks) { return false; }
// don't show self-highlights from another of our clients // don't show self-highlights from another of our clients
if (this.props.mxEvent.getSender() === this.context.matrixClient.credentials.userId) { if (this.props.mxEvent.getSender() === this.context.credentials.userId) {
return false; return false;
} }
@ -461,7 +462,7 @@ module.exports = createReactClass({
// Cancel any outgoing key request for this event and resend it. If a response // Cancel any outgoing key request for this event and resend it. If a response
// is received for the request with the required keys, the event could be // is received for the request with the required keys, the event could be
// decrypted successfully. // decrypted successfully.
this.context.matrixClient.cancelAndResendEventRoomKeyRequest(this.props.mxEvent); this.context.cancelAndResendEventRoomKeyRequest(this.props.mxEvent);
}, },
onPermalinkClicked: function(e) { onPermalinkClicked: function(e) {
@ -494,7 +495,7 @@ module.exports = createReactClass({
} }
} }
if (this.context.matrixClient.isRoomEncrypted(ev.getRoomId())) { if (this.context.isRoomEncrypted(ev.getRoomId())) {
// else if room is encrypted // else if room is encrypted
// and event is being encrypted or is not_sent (Unknown Devices/Network Error) // and event is being encrypted or is not_sent (Unknown Devices/Network Error)
if (ev.status === EventStatus.ENCRYPTING) { if (ev.status === EventStatus.ENCRYPTING) {
@ -741,7 +742,7 @@ module.exports = createReactClass({
switch (this.props.tileShape) { switch (this.props.tileShape) {
case 'notif': { case 'notif': {
const room = this.context.matrixClient.getRoom(this.props.mxEvent.getRoomId()); const room = this.context.getRoom(this.props.mxEvent.getRoomId());
return ( return (
<div className={classes}> <div className={classes}>
<div className="mx_EventTile_roomName"> <div className="mx_EventTile_roomName">

View File

@ -31,7 +31,6 @@ import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import createReactClass from 'create-react-class'; import createReactClass from 'create-react-class';
import classNames from 'classnames'; import classNames from 'classnames';
import { MatrixClient } from 'matrix-js-sdk';
import dis from '../../../dispatcher'; import dis from '../../../dispatcher';
import Modal from '../../../Modal'; import Modal from '../../../Modal';
import sdk from '../../../index'; import sdk from '../../../index';
@ -48,7 +47,7 @@ import SettingsStore from "../../../settings/SettingsStore";
import E2EIcon from "./E2EIcon"; import E2EIcon from "./E2EIcon";
import AutoHideScrollbar from "../../structures/AutoHideScrollbar"; import AutoHideScrollbar from "../../structures/AutoHideScrollbar";
import MatrixClientPeg from "../../../MatrixClientPeg"; import MatrixClientPeg from "../../../MatrixClientPeg";
import {EventTimeline} from "matrix-js-sdk"; import MatrixClientContext from "../../../contexts/MatrixClientContext";
module.exports = createReactClass({ module.exports = createReactClass({
displayName: 'MemberInfo', displayName: 'MemberInfo',
@ -76,13 +75,13 @@ module.exports = createReactClass({
}; };
}, },
contextTypes: { statics: {
matrixClient: PropTypes.instanceOf(MatrixClient).isRequired, contextType: MatrixClientContext,
}, },
componentWillMount: function() { componentWillMount: function() {
this._cancelDeviceList = null; this._cancelDeviceList = null;
const cli = this.context.matrixClient; const cli = this.context;
// only display the devices list if our client supports E2E // only display the devices list if our client supports E2E
this._enableDevices = cli.isCryptoEnabled(); this._enableDevices = cli.isCryptoEnabled();
@ -112,7 +111,7 @@ module.exports = createReactClass({
}, },
componentWillUnmount: function() { componentWillUnmount: function() {
const client = this.context.matrixClient; const client = this.context;
if (client) { if (client) {
client.removeListener("deviceVerificationChanged", this.onDeviceVerificationChanged); client.removeListener("deviceVerificationChanged", this.onDeviceVerificationChanged);
client.removeListener("Room", this.onRoom); client.removeListener("Room", this.onRoom);
@ -131,7 +130,7 @@ module.exports = createReactClass({
}, },
_checkIgnoreState: function() { _checkIgnoreState: function() {
const isIgnoring = this.context.matrixClient.isUserIgnored(this.props.member.userId); const isIgnoring = this.context.isUserIgnored(this.props.member.userId);
this.setState({isIgnoring: isIgnoring}); this.setState({isIgnoring: isIgnoring});
}, },
@ -163,7 +162,7 @@ module.exports = createReactClass({
// Promise.resolve to handle transition from static result to promise; can be removed // Promise.resolve to handle transition from static result to promise; can be removed
// in future // in future
Promise.resolve(this.context.matrixClient.getStoredDevicesForUser(userId)).then((devices) => { Promise.resolve(this.context.getStoredDevicesForUser(userId)).then((devices) => {
this.setState({ this.setState({
devices: devices, devices: devices,
e2eStatus: this._getE2EStatus(devices), e2eStatus: this._getE2EStatus(devices),
@ -197,7 +196,7 @@ module.exports = createReactClass({
onRoomReceipt: function(receiptEvent, room) { onRoomReceipt: function(receiptEvent, room) {
// because if we read a notification, it will affect notification count // because if we read a notification, it will affect notification count
// only bother updating if there's a receipt from us // only bother updating if there's a receipt from us
if (findReadReceiptFromUserId(receiptEvent, this.context.matrixClient.credentials.userId)) { if (findReadReceiptFromUserId(receiptEvent, this.context.credentials.userId)) {
this.forceUpdate(); this.forceUpdate();
} }
}, },
@ -242,7 +241,7 @@ module.exports = createReactClass({
let cancelled = false; let cancelled = false;
this._cancelDeviceList = function() { cancelled = true; }; this._cancelDeviceList = function() { cancelled = true; };
const client = this.context.matrixClient; const client = this.context;
const self = this; const self = this;
client.downloadKeys([member.userId], true).then(() => { client.downloadKeys([member.userId], true).then(() => {
return client.getStoredDevicesForUser(member.userId); return client.getStoredDevicesForUser(member.userId);
@ -267,7 +266,7 @@ module.exports = createReactClass({
}, },
onIgnoreToggle: function() { onIgnoreToggle: function() {
const ignoredUsers = this.context.matrixClient.getIgnoredUsers(); const ignoredUsers = this.context.getIgnoredUsers();
if (this.state.isIgnoring) { if (this.state.isIgnoring) {
const index = ignoredUsers.indexOf(this.props.member.userId); const index = ignoredUsers.indexOf(this.props.member.userId);
if (index !== -1) ignoredUsers.splice(index, 1); if (index !== -1) ignoredUsers.splice(index, 1);
@ -275,7 +274,7 @@ module.exports = createReactClass({
ignoredUsers.push(this.props.member.userId); ignoredUsers.push(this.props.member.userId);
} }
this.context.matrixClient.setIgnoredUsers(ignoredUsers).then(() => { this.context.setIgnoredUsers(ignoredUsers).then(() => {
return this.setState({isIgnoring: !this.state.isIgnoring}); return this.setState({isIgnoring: !this.state.isIgnoring});
}); });
}, },
@ -293,7 +292,7 @@ module.exports = createReactClass({
if (!proceed) return; if (!proceed) return;
this.setState({ updating: this.state.updating + 1 }); this.setState({ updating: this.state.updating + 1 });
this.context.matrixClient.kick( this.context.kick(
this.props.member.roomId, this.props.member.userId, this.props.member.roomId, this.props.member.userId,
reason || undefined, reason || undefined,
).then(function() { ).then(function() {
@ -329,11 +328,11 @@ module.exports = createReactClass({
this.setState({ updating: this.state.updating + 1 }); this.setState({ updating: this.state.updating + 1 });
let promise; let promise;
if (this.props.member.membership === 'ban') { if (this.props.member.membership === 'ban') {
promise = this.context.matrixClient.unban( promise = this.context.unban(
this.props.member.roomId, this.props.member.userId, this.props.member.roomId, this.props.member.userId,
); );
} else { } else {
promise = this.context.matrixClient.ban( promise = this.context.ban(
this.props.member.roomId, this.props.member.userId, this.props.member.roomId, this.props.member.userId,
reason || undefined, reason || undefined,
); );
@ -360,7 +359,7 @@ module.exports = createReactClass({
onRedactAllMessages: async function() { onRedactAllMessages: async function() {
const {roomId, userId} = this.props.member; const {roomId, userId} = this.props.member;
const room = this.context.matrixClient.getRoom(roomId); const room = this.context.getRoom(roomId);
if (!room) { if (!room) {
return; return;
} }
@ -414,7 +413,7 @@ module.exports = createReactClass({
console.info(`Started redacting recent ${count} messages for ${user} in ${roomId}`); console.info(`Started redacting recent ${count} messages for ${user} in ${roomId}`);
await Promise.all(eventsToRedact.map(async event => { await Promise.all(eventsToRedact.map(async event => {
try { try {
await this.context.matrixClient.redactEvent(roomId, event.getId()); await this.context.redactEvent(roomId, event.getId());
} catch (err) { } catch (err) {
// log and swallow errors // log and swallow errors
console.error("Could not redact", event.getId()); console.error("Could not redact", event.getId());
@ -446,11 +445,11 @@ module.exports = createReactClass({
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog"); const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
const roomId = this.props.member.roomId; const roomId = this.props.member.roomId;
const target = this.props.member.userId; const target = this.props.member.userId;
const room = this.context.matrixClient.getRoom(roomId); const room = this.context.getRoom(roomId);
if (!room) return; if (!room) return;
// if muting self, warn as it may be irreversible // if muting self, warn as it may be irreversible
if (target === this.context.matrixClient.getUserId()) { if (target === this.context.getUserId()) {
try { try {
if (!(await this._warnSelfDemote())) return; if (!(await this._warnSelfDemote())) return;
} catch (e) { } catch (e) {
@ -478,7 +477,7 @@ module.exports = createReactClass({
if (!isNaN(level)) { if (!isNaN(level)) {
this.setState({ updating: this.state.updating + 1 }); this.setState({ updating: this.state.updating + 1 });
this.context.matrixClient.setPowerLevel(roomId, target, level, powerLevelEvent).then( this.context.setPowerLevel(roomId, target, level, powerLevelEvent).then(
function() { function() {
// NO-OP; rely on the m.room.member event coming down else we could // NO-OP; rely on the m.room.member event coming down else we could
// get out of sync if we force setState here! // get out of sync if we force setState here!
@ -500,13 +499,13 @@ module.exports = createReactClass({
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog"); const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
const roomId = this.props.member.roomId; const roomId = this.props.member.roomId;
const target = this.props.member.userId; const target = this.props.member.userId;
const room = this.context.matrixClient.getRoom(roomId); const room = this.context.getRoom(roomId);
if (!room) return; if (!room) return;
const powerLevelEvent = room.currentState.getStateEvents("m.room.power_levels", ""); const powerLevelEvent = room.currentState.getStateEvents("m.room.power_levels", "");
if (!powerLevelEvent) return; if (!powerLevelEvent) return;
const me = room.getMember(this.context.matrixClient.credentials.userId); const me = room.getMember(this.context.credentials.userId);
if (!me) return; if (!me) return;
const defaultLevel = powerLevelEvent.getContent().users_default; const defaultLevel = powerLevelEvent.getContent().users_default;
@ -515,7 +514,7 @@ module.exports = createReactClass({
// toggle the level // toggle the level
const newLevel = this.state.isTargetMod ? defaultLevel : modLevel; const newLevel = this.state.isTargetMod ? defaultLevel : modLevel;
this.setState({ updating: this.state.updating + 1 }); this.setState({ updating: this.state.updating + 1 });
this.context.matrixClient.setPowerLevel(roomId, target, parseInt(newLevel), powerLevelEvent).then( this.context.setPowerLevel(roomId, target, parseInt(newLevel), powerLevelEvent).then(
function() { function() {
// NO-OP; rely on the m.room.member event coming down else we could // NO-OP; rely on the m.room.member event coming down else we could
// get out of sync if we force setState here! // get out of sync if we force setState here!
@ -550,7 +549,7 @@ module.exports = createReactClass({
danger: true, danger: true,
onFinished: (accepted) => { onFinished: (accepted) => {
if (!accepted) return; if (!accepted) return;
this.context.matrixClient.deactivateSynapseUser(this.props.member.userId).catch(e => { this.context.deactivateSynapseUser(this.props.member.userId).catch(e => {
console.error("Failed to deactivate user"); console.error("Failed to deactivate user");
console.error(e); console.error(e);
@ -566,7 +565,7 @@ module.exports = createReactClass({
_applyPowerChange: function(roomId, target, powerLevel, powerLevelEvent) { _applyPowerChange: function(roomId, target, powerLevel, powerLevelEvent) {
this.setState({ updating: this.state.updating + 1 }); this.setState({ updating: this.state.updating + 1 });
this.context.matrixClient.setPowerLevel(roomId, target, parseInt(powerLevel), powerLevelEvent).then( this.context.setPowerLevel(roomId, target, parseInt(powerLevel), powerLevelEvent).then(
function() { function() {
// NO-OP; rely on the m.room.member event coming down else we could // NO-OP; rely on the m.room.member event coming down else we could
// get out of sync if we force setState here! // get out of sync if we force setState here!
@ -587,7 +586,7 @@ module.exports = createReactClass({
onPowerChange: async function(powerLevel) { onPowerChange: async function(powerLevel) {
const roomId = this.props.member.roomId; const roomId = this.props.member.roomId;
const target = this.props.member.userId; const target = this.props.member.userId;
const room = this.context.matrixClient.getRoom(roomId); const room = this.context.getRoom(roomId);
if (!room) return; if (!room) return;
const powerLevelEvent = room.currentState.getStateEvents("m.room.power_levels", ""); const powerLevelEvent = room.currentState.getStateEvents("m.room.power_levels", "");
@ -598,7 +597,7 @@ module.exports = createReactClass({
return; return;
} }
const myUserId = this.context.matrixClient.getUserId(); const myUserId = this.context.getUserId();
const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog"); const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
// If we are changing our own PL it can only ever be decreasing, which we cannot reverse. // If we are changing our own PL it can only ever be decreasing, which we cannot reverse.
@ -650,9 +649,9 @@ module.exports = createReactClass({
_calculateOpsPermissions: async function(member) { _calculateOpsPermissions: async function(member) {
let canDeactivate = false; let canDeactivate = false;
if (this.context.matrixClient) { if (this.context) {
try { try {
canDeactivate = await this.context.matrixClient.isSynapseAdministrator(); canDeactivate = await this.context.isSynapseAdministrator();
} catch (e) { } catch (e) {
console.error(e); console.error(e);
} }
@ -665,13 +664,13 @@ module.exports = createReactClass({
}, },
muted: false, muted: false,
}; };
const room = this.context.matrixClient.getRoom(member.roomId); const room = this.context.getRoom(member.roomId);
if (!room) return defaultPerms; if (!room) return defaultPerms;
const powerLevels = room.currentState.getStateEvents("m.room.power_levels", ""); const powerLevels = room.currentState.getStateEvents("m.room.power_levels", "");
if (!powerLevels) return defaultPerms; if (!powerLevels) return defaultPerms;
const me = room.getMember(this.context.matrixClient.credentials.userId); const me = room.getMember(this.context.credentials.userId);
if (!me) return defaultPerms; if (!me) return defaultPerms;
const them = member; const them = member;
@ -738,7 +737,7 @@ module.exports = createReactClass({
const avatarUrl = member.getMxcAvatarUrl(); const avatarUrl = member.getMxcAvatarUrl();
if (!avatarUrl) return; if (!avatarUrl) return;
const httpUrl = this.context.matrixClient.mxcUrlToHttp(avatarUrl); const httpUrl = this.context.mxcUrlToHttp(avatarUrl);
const ImageView = sdk.getComponent("elements.ImageView"); const ImageView = sdk.getComponent("elements.ImageView");
const params = { const params = {
src: httpUrl, src: httpUrl,
@ -797,7 +796,7 @@ module.exports = createReactClass({
}, },
_renderUserOptions: function() { _renderUserOptions: function() {
const cli = this.context.matrixClient; const cli = this.context;
const member = this.props.member; const member = this.props.member;
let ignoreButton = null; let ignoreButton = null;
@ -905,9 +904,9 @@ module.exports = createReactClass({
let synapseDeactivateButton; let synapseDeactivateButton;
let spinner; let spinner;
if (this.props.member.userId !== this.context.matrixClient.credentials.userId) { if (this.props.member.userId !== this.context.credentials.userId) {
// TODO: Immutable DMs replaces a lot of this // TODO: Immutable DMs replaces a lot of this
const dmRoomMap = new DMRoomMap(this.context.matrixClient); const dmRoomMap = new DMRoomMap(this.context);
// dmRooms will not include dmRooms that we have been invited into but did not join. // dmRooms will not include dmRooms that we have been invited into but did not join.
// Because DMRoomMap runs off account_data[m.direct] which is only set on join of dm room. // Because DMRoomMap runs off account_data[m.direct] which is only set on join of dm room.
// XXX: we potentially want DMs we have been invited to, to also show up here :L // XXX: we potentially want DMs we have been invited to, to also show up here :L
@ -918,7 +917,7 @@ module.exports = createReactClass({
const tiles = []; const tiles = [];
for (const roomId of dmRooms) { for (const roomId of dmRooms) {
const room = this.context.matrixClient.getRoom(roomId); const room = this.context.getRoom(roomId);
if (room) { if (room) {
const myMembership = room.getMyMembership(); const myMembership = room.getMyMembership();
// not a DM room if we have are not joined // not a DM room if we have are not joined
@ -1064,12 +1063,12 @@ module.exports = createReactClass({
} }
} }
const room = this.context.matrixClient.getRoom(this.props.member.roomId); const room = this.context.getRoom(this.props.member.roomId);
const powerLevelEvent = room ? room.currentState.getStateEvents("m.room.power_levels", "") : null; const powerLevelEvent = room ? room.currentState.getStateEvents("m.room.power_levels", "") : null;
const powerLevelUsersDefault = powerLevelEvent ? powerLevelEvent.getContent().users_default : 0; const powerLevelUsersDefault = powerLevelEvent ? powerLevelEvent.getContent().users_default : 0;
const enablePresenceByHsUrl = SdkConfig.get()["enable_presence_by_hs_url"]; const enablePresenceByHsUrl = SdkConfig.get()["enable_presence_by_hs_url"];
const hsUrl = this.context.matrixClient.baseUrl; const hsUrl = this.context.baseUrl;
let showPresence = true; let showPresence = true;
if (enablePresenceByHsUrl && enablePresenceByHsUrl[hsUrl] !== undefined) { if (enablePresenceByHsUrl && enablePresenceByHsUrl[hsUrl] !== undefined) {
showPresence = enablePresenceByHsUrl[hsUrl]; showPresence = enablePresenceByHsUrl[hsUrl];
@ -1108,7 +1107,7 @@ module.exports = createReactClass({
</div> </div>
</div>; </div>;
const isEncrypted = this.context.matrixClient.isRoomEncrypted(this.props.member.roomId); const isEncrypted = this.context.isRoomEncrypted(this.props.member.roomId);
if (this.state.e2eStatus && isEncrypted) { if (this.state.e2eStatus && isEncrypted) {
e2eIconElement = (<E2EIcon status={this.state.e2eStatus} isUser={true} />); e2eIconElement = (<E2EIcon status={this.state.e2eStatus} isUser={true} />);
} }
@ -1117,7 +1116,7 @@ module.exports = createReactClass({
const avatarUrl = this.props.member.getMxcAvatarUrl(); const avatarUrl = this.props.member.getMxcAvatarUrl();
let avatarElement; let avatarElement;
if (avatarUrl) { if (avatarUrl) {
const httpUrl = this.context.matrixClient.mxcUrlToHttp(avatarUrl, 800, 800); const httpUrl = this.context.mxcUrlToHttp(avatarUrl, 800, 800);
avatarElement = <div className="mx_MemberInfo_avatar"> avatarElement = <div className="mx_MemberInfo_avatar">
<img src={httpUrl} /> <img src={httpUrl} />
</div>; </div>;

View File

@ -107,8 +107,8 @@ class UploadButton extends React.Component {
roomId: PropTypes.string.isRequired, roomId: PropTypes.string.isRequired,
} }
constructor(props, context) { constructor(props) {
super(props, context); super(props);
this.onUploadClick = this.onUploadClick.bind(this); this.onUploadClick = this.onUploadClick.bind(this);
this.onUploadFileInputChange = this.onUploadFileInputChange.bind(this); this.onUploadFileInputChange = this.onUploadFileInputChange.bind(this);
@ -165,8 +165,8 @@ class UploadButton extends React.Component {
} }
export default class MessageComposer extends React.Component { export default class MessageComposer extends React.Component {
constructor(props, context) { constructor(props) {
super(props, context); super(props);
this.onInputStateChanged = this.onInputStateChanged.bind(this); this.onInputStateChanged = this.onInputStateChanged.bind(this);
this.onEvent = this.onEvent.bind(this); this.onEvent = this.onEvent.bind(this);
this._onRoomStateEvents = this._onRoomStateEvents.bind(this); this._onRoomStateEvents = this._onRoomStateEvents.bind(this);

View File

@ -141,8 +141,8 @@ export default class MessageComposerInput extends React.Component {
autocomplete: Autocomplete; autocomplete: Autocomplete;
historyManager: SlateComposerHistoryManager; historyManager: SlateComposerHistoryManager;
constructor(props, context) { constructor(props) {
super(props, context); super(props);
const isRichTextEnabled = SettingsStore.getValue('MessageComposerInput.isRichTextEnabled'); const isRichTextEnabled = SettingsStore.getValue('MessageComposerInput.isRichTextEnabled');

View File

@ -35,8 +35,8 @@ export default class ReplyPreview extends React.Component {
permalinkCreator: PropTypes.instanceOf(RoomPermalinkCreator).isRequired, permalinkCreator: PropTypes.instanceOf(RoomPermalinkCreator).isRequired,
}; };
constructor(props, context) { constructor(props) {
super(props, context); super(props);
this.unmounted = false; this.unmounted = false;
this.state = { this.state = {

View File

@ -26,7 +26,6 @@ import {
unescapeMessage, unescapeMessage,
} from '../../../editor/serialize'; } from '../../../editor/serialize';
import {CommandPartCreator} from '../../../editor/parts'; import {CommandPartCreator} from '../../../editor/parts';
import {MatrixClient} from 'matrix-js-sdk';
import BasicMessageComposer from "./BasicMessageComposer"; import BasicMessageComposer from "./BasicMessageComposer";
import ReplyPreview from "./ReplyPreview"; import ReplyPreview from "./ReplyPreview";
import RoomViewStore from '../../../stores/RoomViewStore'; import RoomViewStore from '../../../stores/RoomViewStore';
@ -40,6 +39,7 @@ import Modal from '../../../Modal';
import {_t, _td} from '../../../languageHandler'; import {_t, _td} from '../../../languageHandler';
import ContentMessages from '../../../ContentMessages'; import ContentMessages from '../../../ContentMessages';
import {Key} from "../../../Keyboard"; import {Key} from "../../../Keyboard";
import MatrixClientContext from "../../../contexts/MatrixClientContext";
function addReplyToMessageContent(content, repliedToEvent, permalinkCreator) { function addReplyToMessageContent(content, repliedToEvent, permalinkCreator) {
const replyContent = ReplyThread.makeReplyMixIn(repliedToEvent); const replyContent = ReplyThread.makeReplyMixIn(repliedToEvent);
@ -89,12 +89,10 @@ export default class SendMessageComposer extends React.Component {
permalinkCreator: PropTypes.object.isRequired, permalinkCreator: PropTypes.object.isRequired,
}; };
static contextTypes = { static contextType = MatrixClientContext;
matrixClient: PropTypes.instanceOf(MatrixClient).isRequired,
};
constructor(props, context) { constructor(props) {
super(props, context); super(props);
this.model = null; this.model = null;
this._editorRef = null; this._editorRef = null;
this.currentlyComposedEditorState = null; this.currentlyComposedEditorState = null;
@ -245,7 +243,7 @@ export default class SendMessageComposer extends React.Component {
const isReply = !!RoomViewStore.getQuotingEvent(); const isReply = !!RoomViewStore.getQuotingEvent();
const {roomId} = this.props.room; const {roomId} = this.props.room;
const content = createMessageContent(this.model, this.props.permalinkCreator); const content = createMessageContent(this.model, this.props.permalinkCreator);
this.context.matrixClient.sendMessage(roomId, content); this.context.sendMessage(roomId, content);
if (isReply) { if (isReply) {
// Clear reply_to_event as we put the message into the queue // Clear reply_to_event as we put the message into the queue
// if the send fails, retry will handle resending. // if the send fails, retry will handle resending.
@ -273,7 +271,7 @@ export default class SendMessageComposer extends React.Component {
} }
componentWillMount() { componentWillMount() {
const partCreator = new CommandPartCreator(this.props.room, this.context.matrixClient); const partCreator = new CommandPartCreator(this.props.room, this.context);
const parts = this._restoreStoredEditorState(partCreator) || []; const parts = this._restoreStoredEditorState(partCreator) || [];
this.model = new EditorModel(parts, partCreator); this.model = new EditorModel(parts, partCreator);
this.dispatcherRef = dis.register(this.onAction); this.dispatcherRef = dis.register(this.onAction);
@ -361,7 +359,7 @@ export default class SendMessageComposer extends React.Component {
// from Finder) but more images copied from a different website // from Finder) but more images copied from a different website
// / word processor etc. // / word processor etc.
ContentMessages.sharedInstance().sendContentListToRoom( ContentMessages.sharedInstance().sendContentListToRoom(
Array.from(clipboardData.files), this.props.room.roomId, this.context.matrixClient, Array.from(clipboardData.files), this.props.room.roomId, this.context,
); );
} }
} }

View File

@ -137,8 +137,8 @@ class UploadButton extends React.Component {
static propTypes = { static propTypes = {
roomId: PropTypes.string.isRequired, roomId: PropTypes.string.isRequired,
} }
constructor(props, context) { constructor(props) {
super(props, context); super(props);
this.onUploadClick = this.onUploadClick.bind(this); this.onUploadClick = this.onUploadClick.bind(this);
this.onUploadFileInputChange = this.onUploadFileInputChange.bind(this); this.onUploadFileInputChange = this.onUploadFileInputChange.bind(this);
@ -193,8 +193,8 @@ class UploadButton extends React.Component {
} }
export default class SlateMessageComposer extends React.Component { export default class SlateMessageComposer extends React.Component {
constructor(props, context) { constructor(props) {
super(props, context); super(props);
this._onAutocompleteConfirm = this._onAutocompleteConfirm.bind(this); this._onAutocompleteConfirm = this._onAutocompleteConfirm.bind(this);
this.onToggleFormattingClicked = this.onToggleFormattingClicked.bind(this); this.onToggleFormattingClicked = this.onToggleFormattingClicked.bind(this);
this.onToggleMarkdownClicked = this.onToggleMarkdownClicked.bind(this); this.onToggleMarkdownClicked = this.onToggleMarkdownClicked.bind(this);

View File

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

View File

@ -23,8 +23,8 @@ import MatrixClientPeg from '../../../MatrixClientPeg';
import {formatDate} from '../../../DateUtils'; import {formatDate} from '../../../DateUtils';
export default class DevicesPanelEntry extends React.Component { export default class DevicesPanelEntry extends React.Component {
constructor(props, context) { constructor(props) {
super(props, context); super(props);
this._unmounted = false; this._unmounted = false;
this.onDeviceToggled = this.onDeviceToggled.bind(this); this.onDeviceToggled = this.onDeviceToggled.bind(this);

View File

@ -18,22 +18,19 @@ import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import {_t} from "../../../../../languageHandler"; import {_t} from "../../../../../languageHandler";
import RoomProfileSettings from "../../../room_settings/RoomProfileSettings"; import RoomProfileSettings from "../../../room_settings/RoomProfileSettings";
import MatrixClientPeg from "../../../../../MatrixClientPeg";
import sdk from "../../../../.."; import sdk from "../../../../..";
import AccessibleButton from "../../../elements/AccessibleButton"; import AccessibleButton from "../../../elements/AccessibleButton";
import {MatrixClient} from "matrix-js-sdk";
import dis from "../../../../../dispatcher"; import dis from "../../../../../dispatcher";
import LabelledToggleSwitch from "../../../elements/LabelledToggleSwitch"; import LabelledToggleSwitch from "../../../elements/LabelledToggleSwitch";
import MatrixClientContext from "../../../../../contexts/MatrixClientContext";
export default class GeneralRoomSettingsTab extends React.Component { export default class GeneralRoomSettingsTab extends React.Component {
static childContextTypes = {
matrixClient: PropTypes.instanceOf(MatrixClient),
};
static propTypes = { static propTypes = {
roomId: PropTypes.string.isRequired, roomId: PropTypes.string.isRequired,
}; };
static contextType = MatrixClientContext;
constructor() { constructor() {
super(); super();
@ -42,14 +39,8 @@ export default class GeneralRoomSettingsTab extends React.Component {
}; };
} }
getChildContext() {
return {
matrixClient: MatrixClientPeg.get(),
};
}
componentWillMount() { componentWillMount() {
MatrixClientPeg.get().getRoomDirectoryVisibility(this.props.roomId).then((result => { this.context.getRoomDirectoryVisibility(this.props.roomId).then((result => {
this.setState({isRoomPublished: result.visibility === 'public'}); this.setState({isRoomPublished: result.visibility === 'public'});
})); }));
} }
@ -59,7 +50,7 @@ export default class GeneralRoomSettingsTab extends React.Component {
const newValue = !valueBefore; const newValue = !valueBefore;
this.setState({isRoomPublished: newValue}); this.setState({isRoomPublished: newValue});
MatrixClientPeg.get().setRoomDirectoryVisibility( this.context.setRoomDirectoryVisibility(
this.props.roomId, this.props.roomId,
newValue ? 'public' : 'private', newValue ? 'public' : 'private',
).catch(() => { ).catch(() => {
@ -80,7 +71,7 @@ export default class GeneralRoomSettingsTab extends React.Component {
const RelatedGroupSettings = sdk.getComponent("room_settings.RelatedGroupSettings"); const RelatedGroupSettings = sdk.getComponent("room_settings.RelatedGroupSettings");
const UrlPreviewSettings = sdk.getComponent("room_settings.UrlPreviewSettings"); const UrlPreviewSettings = sdk.getComponent("room_settings.UrlPreviewSettings");
const client = MatrixClientPeg.get(); const client = this.context;
const room = client.getRoom(this.props.roomId); const room = client.getRoom(this.props.roomId);
const canSetAliases = true; // Previously, we arbitrarily only allowed admins to do this const canSetAliases = true; // Previously, we arbitrarily only allowed admins to do this

View File

@ -17,25 +17,8 @@ limitations under the License.
import React from 'react'; import React from 'react';
import {_t} from "../../../../../languageHandler"; import {_t} from "../../../../../languageHandler";
import GroupUserSettings from "../../../groups/GroupUserSettings"; import GroupUserSettings from "../../../groups/GroupUserSettings";
import MatrixClientPeg from "../../../../../MatrixClientPeg";
import PropTypes from "prop-types";
import {MatrixClient} from "matrix-js-sdk";
export default class FlairUserSettingsTab extends React.Component { export default class FlairUserSettingsTab extends React.Component {
static childContextTypes = {
matrixClient: PropTypes.instanceOf(MatrixClient),
};
constructor() {
super();
}
getChildContext() {
return {
matrixClient: MatrixClientPeg.get(),
};
}
render() { render() {
return ( return (
<div className="mx_SettingsTab"> <div className="mx_SettingsTab">

View File

@ -14,18 +14,8 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import React from "react"; import { createContext } from "react";
import PropTypes from "prop-types";
import {MatrixClient} from "matrix-js-sdk";
// Higher Order Component to allow use of legacy MatrixClient React Context const MatrixClientContext = createContext(undefined);
// in Functional Components which do not otherwise support legacy React Contexts MatrixClientContext.displayName = "MatrixClientContext";
export default (Component) => class extends React.PureComponent { export default MatrixClientContext;
static contextTypes = {
matrixClient: PropTypes.instanceOf(MatrixClient).isRequired,
};
render() {
return <Component {...this.props} matrixClient={this.context.matrixClient} />;
}
};

View File

@ -0,0 +1,25 @@
/*
Copyright 2019 The Matrix.org Foundation C.I.C.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import { createContext } from "react";
const RoomContext = createContext({
canReact: undefined,
canReply: undefined,
room: undefined,
});
RoomContext.displayName = "RoomContext";
export default RoomContext;

View File

@ -36,27 +36,14 @@ const test_utils = require('test-utils');
const mockclock = require('mock-clock'); const mockclock = require('mock-clock');
import Velocity from 'velocity-animate'; import Velocity from 'velocity-animate';
import MatrixClientContext from "../../../src/contexts/MatrixClientContext";
import RoomContext from "../../../src/contexts/RoomContext";
let client; let client;
const room = new Matrix.Room(); const room = new Matrix.Room();
// wrap MessagePanel with a component which provides the MatrixClient in the context. // wrap MessagePanel with a component which provides the MatrixClient in the context.
const WrappedMessagePanel = createReactClass({ const WrappedMessagePanel = createReactClass({
childContextTypes: {
matrixClient: PropTypes.object,
room: PropTypes.object,
},
getChildContext: function() {
return {
matrixClient: client,
room: {
canReact: true,
canReply: true,
},
};
},
getInitialState: function() { getInitialState: function() {
return { return {
resizeNotifier: new EventEmitter(), resizeNotifier: new EventEmitter(),
@ -64,7 +51,11 @@ const WrappedMessagePanel = createReactClass({
}, },
render: function() { render: function() {
return <MessagePanel room={room} {...this.props} resizeNotifier={this.state.resizeNotifier} />; return <MatrixClientContext.Provider value={client}>
<RoomContext.Provider value={{ canReact: true, canReply: true }}>
<MessagePanel room={room} {...this.props} resizeNotifier={this.state.resizeNotifier} />
</RoomContext.Provider>
</MatrixClientContext.Provider>;
}, },
}); });

View File

@ -9,6 +9,7 @@ import jssdk from 'matrix-js-sdk';
import {makeType} from "../src/utils/TypeUtils"; import {makeType} from "../src/utils/TypeUtils";
import {ValidatedServerConfig} from "../src/utils/AutoDiscoveryUtils"; import {ValidatedServerConfig} from "../src/utils/AutoDiscoveryUtils";
import ShallowRenderer from 'react-test-renderer/shallow'; import ShallowRenderer from 'react-test-renderer/shallow';
import MatrixClientContext from "../src/contexts/MatrixClientContext";
const MatrixEvent = jssdk.MatrixEvent; const MatrixEvent = jssdk.MatrixEvent;
/** /**
@ -291,22 +292,16 @@ export function getDispatchForStore(store) {
export function wrapInMatrixClientContext(WrappedComponent) { export function wrapInMatrixClientContext(WrappedComponent) {
class Wrapper extends React.Component { class Wrapper extends React.Component {
static childContextTypes = { constructor(props) {
matrixClient: PropTypes.object, super(props);
}
getChildContext() {
return {
matrixClient: this._matrixClient,
};
}
componentWillMount() {
this._matrixClient = peg.get(); this._matrixClient = peg.get();
} }
render() { render() {
return <WrappedComponent ref={this.props.wrappedRef} {...this.props} />; return <MatrixClientContext.Provider value={this._matrixClient}>
<WrappedComponent ref={this.props.wrappedRef} {...this.props} />
</MatrixClientContext.Provider>;
} }
} }
return Wrapper; return Wrapper;