diff --git a/src/MatrixClientPeg.js b/src/MatrixClientPeg.js index 14dfa91fa4..99841c986e 100644 --- a/src/MatrixClientPeg.js +++ b/src/MatrixClientPeg.js @@ -175,4 +175,4 @@ class MatrixClientPeg { if (!global.mxMatrixClientPeg) { global.mxMatrixClientPeg = new MatrixClientPeg(); } -module.exports = global.mxMatrixClientPeg; +export default global.mxMatrixClientPeg; diff --git a/src/components/views/elements/PowerSelector.js b/src/components/views/elements/PowerSelector.js index f8443c6ecd..d1f102d9fe 100644 --- a/src/components/views/elements/PowerSelector.js +++ b/src/components/views/elements/PowerSelector.js @@ -42,6 +42,9 @@ module.exports = React.createClass({ // should the user be able to change the value? false by default. disabled: PropTypes.bool, onChange: PropTypes.func, + + // Optional key to pass as the second argument to `onChange` + powerLevelKey: PropTypes.string, }, getInitialState: function() { @@ -84,17 +87,17 @@ module.exports = React.createClass({ onSelectChange: function(event) { this.setState({ custom: event.target.value === "SELECT_VALUE_CUSTOM" }); if (event.target.value !== "SELECT_VALUE_CUSTOM") { - this.props.onChange(event.target.value); + this.props.onChange(event.target.value, this.props.powerLevelKey); } }, onCustomBlur: function(event) { - this.props.onChange(parseInt(this.refs.custom.value)); + this.props.onChange(parseInt(this.refs.custom.value), this.props.powerLevelKey); }, onCustomKeyDown: function(event) { if (event.key == "Enter") { - this.props.onChange(parseInt(this.refs.custom.value)); + this.props.onChange(parseInt(this.refs.custom.value), this.props.powerLevelKey); } }, diff --git a/src/components/views/rooms/RoomSettings.js b/src/components/views/rooms/RoomSettings.js index ea4a29615e..e2dad93698 100644 --- a/src/components/views/rooms/RoomSettings.js +++ b/src/components/views/rooms/RoomSettings.js @@ -117,7 +117,6 @@ module.exports = React.createClass({ propTypes: { room: PropTypes.object.isRequired, - onSaveClick: PropTypes.func, }, getInitialState: function() { @@ -132,7 +131,8 @@ module.exports = React.createClass({ join_rule: this._yankValueFromEvent("m.room.join_rules", "join_rule"), history_visibility: this._yankValueFromEvent("m.room.history_visibility", "history_visibility"), guest_access: this._yankValueFromEvent("m.room.guest_access", "guest_access"), - power_levels_changed: false, + powerLevels: this._yankContentFromEvent("m.room.power_levels", {}), + powerLevelsChanged: false, tags_changed: false, tags: tags, // isRoomPublished is loaded async in componentWillMount so when the component @@ -151,7 +151,7 @@ module.exports = React.createClass({ MatrixClientPeg.get().getRoomDirectoryVisibility( this.props.room.roomId, - ).done((result) => { + ).done((result = {}) => { this.setState({ isRoomPublished: result.visibility === "public" }); this._originalIsRoomPublished = result.visibility === "public"; }, (err) => { @@ -272,8 +272,8 @@ module.exports = React.createClass({ // power levels - const powerLevels = this._getPowerLevels(); - if (powerLevels) { + const powerLevels = this.state.powerLevels; + if (this.state.powerLevelsChanged) { promises.push(MatrixClientPeg.get().sendStateEvent( roomId, "m.room.power_levels", powerLevels, "", )); @@ -384,36 +384,32 @@ module.exports = React.createClass({ return strA !== strB; }, - _getPowerLevels: function() { - if (!this.state.power_levels_changed) return undefined; + onPowerLevelsChanged: function(value, powerLevelKey) { + const powerLevels = Object.assign({}, this.state.powerLevels); + const eventsLevelPrefix = "event_levels_"; - let powerLevels = this.props.room.currentState.getStateEvents('m.room.power_levels', ''); - powerLevels = powerLevels ? powerLevels.getContent() : {}; + value = parseInt(value); - for (const key of Object.keys(this.refs).filter((k) => k.startsWith("event_levels_"))) { - const eventType = key.substring("event_levels_".length); - powerLevels.events[eventType] = parseInt(this.refs[key].getValue()); + if (powerLevelKey.startsWith(eventsLevelPrefix)) { + // deep copy "events" object, Object.assign itself won't deep copy + powerLevels["events"] = Object.assign({}, this.state.powerLevels["events"] || {}); + powerLevels["events"][powerLevelKey.slice(eventsLevelPrefix.length)] = value; + } else { + powerLevels[powerLevelKey] = value; } - - const newPowerLevels = { - ban: parseInt(this.refs.ban.getValue()), - kick: parseInt(this.refs.kick.getValue()), - redact: parseInt(this.refs.redact.getValue()), - invite: parseInt(this.refs.invite.getValue()), - events_default: parseInt(this.refs.events_default.getValue()), - state_default: parseInt(this.refs.state_default.getValue()), - users_default: parseInt(this.refs.users_default.getValue()), - users: powerLevels.users, - events: powerLevels.events, - }; - - return newPowerLevels; + this.setState({ + powerLevels, + powerLevelsChanged: true, + }); }, - onPowerLevelsChanged: function() { - this.setState({ - power_levels_changed: true, - }); + _yankContentFromEvent: function(stateEventType, defaultValue) { + // E.g.("m.room.name") would yank the content of "m.room.name" + const event = this.props.room.currentState.getStateEvents(stateEventType, ''); + if (!event) { + return defaultValue; + } + return event.getContent() || defaultValue; }, _yankValueFromEvent: function(stateEventType, keyName, defaultValue) { @@ -633,29 +629,61 @@ module.exports = React.createClass({ const cli = MatrixClientPeg.get(); const roomState = this.props.room.currentState; - const user_id = cli.credentials.userId; + const myUserId = cli.credentials.userId; - const power_level_event = roomState.getStateEvents('m.room.power_levels', ''); - const power_levels = power_level_event ? power_level_event.getContent() : {}; - const events_levels = power_levels.events || {}; - const user_levels = power_levels.users || {}; + const powerLevels = this.state.powerLevels; + const eventsLevels = powerLevels.events || {}; + const userLevels = powerLevels.users || {}; - const ban_level = parseIntWithDefault(power_levels.ban, 50); - const kick_level = parseIntWithDefault(power_levels.kick, 50); - const redact_level = parseIntWithDefault(power_levels.redact, 50); - const invite_level = parseIntWithDefault(power_levels.invite, 50); - const send_level = parseIntWithDefault(power_levels.events_default, 0); - const state_level = power_level_event ? parseIntWithDefault(power_levels.state_default, 50) : 0; - const default_user_level = parseIntWithDefault(power_levels.users_default, 0); + const powerLevelDescriptors = { + users_default: { + desc: _t('The default role for new room members is'), + defaultValue: 0, + }, + events_default: { + desc: _t('To send messages, you must be a'), + defaultValue: 0, + }, + invite: { + desc: _t('To invite users into the room, you must be a'), + defaultValue: 50, + }, + state_default: { + desc: _t('To configure the room, you must be a'), + defaultValue: 50, + }, + kick: { + desc: _t('To kick users, you must be a'), + defaultValue: 50, + }, + ban: { + desc: _t('To ban users, you must be a'), + defaultValue: 50, + }, + redact: { + desc: _t('To remove other users\' messages, you must be a'), + defaultValue: 50, + }, + }; - this._populateDefaultPlEvents(events_levels, state_level, send_level); + const banLevel = parseIntWithDefault(powerLevels.ban, powerLevelDescriptors.ban.defaultValue); + const defaultUserLevel = parseIntWithDefault( + powerLevels.users_default, + powerLevelDescriptors.users_default.defaultValue, + ); - let current_user_level = user_levels[user_id]; - if (current_user_level === undefined) { - current_user_level = default_user_level; + this._populateDefaultPlEvents( + eventsLevels, + parseIntWithDefault(powerLevels.state_default, powerLevelDescriptors.state_default.defaultValue), + parseIntWithDefault(powerLevels.events_default, powerLevelDescriptors.events_default.defaultValue), + ); + + let currentUserLevel = userLevels[myUserId]; + if (currentUserLevel === undefined) { + currentUserLevel = defaultUserLevel; } - const can_change_levels = roomState.mayClientSendStateEvent("m.room.power_levels", cli); + const canChangeLevels = roomState.mayClientSendStateEvent("m.room.power_levels", cli); const canSetTag = !cli.isGuest(); @@ -668,15 +696,16 @@ module.exports = React.createClass({ />; let userLevelsSection; - if (Object.keys(user_levels).length) { + if (Object.keys(userLevels).length) { userLevelsSection =

{ _t('Privileged Users') }