diff --git a/src/components/structures/RoomView.js b/src/components/structures/RoomView.js index 03b371ef7e..535a1f3df3 100644 --- a/src/components/structures/RoomView.js +++ b/src/components/structures/RoomView.js @@ -27,8 +27,8 @@ import React from 'react'; import ReactDOM from 'react-dom'; import PropTypes from 'prop-types'; import Promise from 'bluebird'; -import filesize from 'filesize'; import classNames from 'classnames'; +import {Room} from "matrix-js-sdk"; import { _t } from '../../languageHandler'; import {RoomPermalinkCreator} from '../../matrix-to'; @@ -64,6 +64,12 @@ if (DEBUG) { debuglog = console.log.bind(console); } +const RoomContext = PropTypes.shape({ + canReact: PropTypes.bool.isRequired, + canReply: PropTypes.bool.isRequired, + room: PropTypes.instanceOf(Room), +}); + module.exports = React.createClass({ displayName: 'RoomView', propTypes: { @@ -88,7 +94,7 @@ module.exports = React.createClass({ // * name (string) The room's name // * avatarUrl (string) The mxc:// avatar URL for the room // * inviterName (string) The display name of the person who - // * invited us tovthe room + // * invited us to the room oobData: PropTypes.object, // is the RightPanel collapsed? @@ -156,6 +162,24 @@ module.exports = React.createClass({ // We load this later by asking the js-sdk to suggest a version for us. // This object is the result of Room#getRecommendedVersion() upgradeRecommendation: null, + + canReact: false, + canReply: false, + }; + }, + + childContextTypes: { + room: RoomContext, + }, + + getChildContext: function() { + const {canReact, canReply, room} = this.state; + return { + room: { + canReact, + canReply, + room, + }, }; }, @@ -165,6 +189,7 @@ module.exports = React.createClass({ MatrixClientPeg.get().on("Room.timeline", this.onRoomTimeline); MatrixClientPeg.get().on("Room.name", this.onRoomName); MatrixClientPeg.get().on("Room.accountData", this.onRoomAccountData); + MatrixClientPeg.get().on("RoomState.events", this.onRoomStateEvents); MatrixClientPeg.get().on("RoomState.members", this.onRoomStateMember); MatrixClientPeg.get().on("Room.myMembership", this.onMyMembership); MatrixClientPeg.get().on("accountData", this.onAccountData); @@ -672,6 +697,7 @@ module.exports = React.createClass({ this._loadMembersIfJoined(room); this._calculateRecommendedVersion(room); this._updateE2EStatus(room); + this._updatePermissions(room); }, _calculateRecommendedVersion: async function(room) { @@ -795,6 +821,15 @@ module.exports = React.createClass({ } }, + onRoomStateEvents: function(ev, state) { + // ignore if we don't have a room yet + if (!this.state.room || this.state.room.roomId !== state.roomId) { + return; + } + + this._updatePermissions(this.state.room); + }, + onRoomStateMember: function(ev, state, member) { // ignore if we don't have a room yet if (!this.state.room) { @@ -813,6 +848,17 @@ module.exports = React.createClass({ if (room.roomId === this.state.roomId) { this.forceUpdate(); this._loadMembersIfJoined(room); + this._updatePermissions(room); + } + }, + + _updatePermissions: function(room) { + if (room) { + const me = MatrixClientPeg.get().getUserId(); + const canReact = room.getMyMembership() === "join" && room.currentState.maySendEvent("m.reaction", me); + const canReply = room.maySendMessage(); + + this.setState({canReact, canReply}); } }, @@ -1916,3 +1962,5 @@ module.exports = React.createClass({ ); }, }); + +module.exports.RoomContext = RoomContext; diff --git a/src/components/views/messages/MessageActionBar.js b/src/components/views/messages/MessageActionBar.js index 387a15d292..8db268076c 100644 --- a/src/components/views/messages/MessageActionBar.js +++ b/src/components/views/messages/MessageActionBar.js @@ -24,7 +24,7 @@ import dis from '../../../dispatcher'; import Modal from '../../../Modal'; import { createMenu } from '../../structures/ContextualMenu'; import { isContentActionable, canEditContent } from '../../../utils/EventUtils'; -import MatrixClientPeg from "../../../MatrixClientPeg"; +import {RoomContext} from "../../structures/RoomView"; export default class MessageActionBar extends React.PureComponent { static propTypes = { @@ -37,44 +37,16 @@ export default class MessageActionBar extends React.PureComponent { onFocusChange: PropTypes.func, }; - constructor(props, context) { - super(props, context); - - this.state = { - canReact: true, - canReply: true, - }; - } + static contextTypes = { + room: RoomContext, + }; componentDidMount() { this.props.mxEvent.on("Event.decrypted", this.onDecrypted); - const room = MatrixClientPeg.get().getRoom(this.props.mxEvent.getRoomId()); - if (room) { - room.on("RoomMember.powerLevel", this.onPermissionsChange); - room.on("RoomMember.membership", this.onPermissionsChange); - this.onPermissionsChange(); - } } componentWillUnmount() { this.props.mxEvent.removeListener("Event.decrypted", this.onDecrypted); - const room = MatrixClientPeg.get().getRoom(this.props.mxEvent.getRoomId()); - if (room) { - room.removeListener("RoomMember.powerLevel", this.onPermissionsChange); - room.removeListener("RoomMember.membership", this.onPermissionsChange); - } - } - - onPermissionsChange() { - const cli = MatrixClientPeg.get(); - const room = cli.getRoom(this.props.mxEvent.getRoomId()); - if (room) { - const me = cli.getUserId(); - const canReact = room.getMyMembership() === "join" && room.currentState.maySendEvent("m.reaction", me); - const canReply = room.maySendMessage(); - - this.setState({canReact, canReply}); - } } onDecrypted = () => { @@ -173,10 +145,10 @@ export default class MessageActionBar extends React.PureComponent { let editButton; if (isContentActionable(this.props.mxEvent)) { - if (this.state.canReact) { + if (this.context.room.canReact) { reactButton = this.renderReactButton(); } - if (this.state.canReply) { + if (this.context.room.canReply) { replyButton =