From 0039ccf20338869e0ae465d5cd879757b3c1b3d3 Mon Sep 17 00:00:00 2001 From: Erik Johnston Date: Mon, 20 Jul 2015 15:07:51 +0100 Subject: [PATCH 01/11] Add ability to edit room settings --- skins/base/css/organisms/RoomView.css | 4 +- skins/base/views/molecules/RoomHeader.js | 36 ++++++++++-- skins/base/views/organisms/RoomView.js | 74 +++++++++++++++++++++++- src/ComponentBroker.js | 1 + src/controllers/molecules/RoomHeader.js | 18 +++++- src/controllers/organisms/RoomView.js | 8 +-- 6 files changed, 125 insertions(+), 16 deletions(-) diff --git a/skins/base/css/organisms/RoomView.css b/skins/base/css/organisms/RoomView.css index 9341f21335..88f52aa6fa 100644 --- a/skins/base/css/organisms/RoomView.css +++ b/skins/base/css/organisms/RoomView.css @@ -60,7 +60,7 @@ limitations under the License. order: 3; width: 100%; - height: 100%; + flex: 1; margin-top: 18px; margin-bottom: 18px; @@ -101,7 +101,7 @@ limitations under the License. .mx_RoomView_statusAreaBox { max-width: 720px; - margin: auto; + margin: auto; border-top: 1px solid #a8dbf3; } diff --git a/skins/base/views/molecules/RoomHeader.js b/skins/base/views/molecules/RoomHeader.js index a67699772c..6d01c6a412 100644 --- a/skins/base/views/molecules/RoomHeader.js +++ b/skins/base/views/molecules/RoomHeader.js @@ -33,10 +33,13 @@ module.exports = React.createClass({ } }, + getRoomName: function() { + return this.refs.name_edit.getDOMNode().value; + }, + render: function() { var topic = this.props.room.currentState.getStateEvents('m.room.topic', ''); - topic = topic ?
{ topic.getContent().topic }
: null; var callButtons; if (this.state) { @@ -52,6 +55,28 @@ module.exports = React.createClass({ } } + var name = null; + var topic_el = null; + var save_button = null; + var settings_button = null; + if (this.props.editing) { + name = ; + // if (topic) topic_el =
+ save_button = ( +
+ Save +
+ ); + } else { + name = ; + if (topic) topic_el =
{ topic.getContent().topic }
; + settings_button = ( +
+ +
+ ); + } + return (
@@ -61,15 +86,14 @@ module.exports = React.createClass({
- + { name }
- { topic } + { topic_el }
-
- -
+ { save_button } + { settings_button }
diff --git a/skins/base/views/organisms/RoomView.js b/skins/base/views/organisms/RoomView.js index a93937f0bc..3e1fb6c661 100644 --- a/skins/base/views/organisms/RoomView.js +++ b/skins/base/views/organisms/RoomView.js @@ -28,6 +28,7 @@ var MessageTile = ComponentBroker.get('molecules/MessageTile'); var RoomHeader = ComponentBroker.get('molecules/RoomHeader'); var MessageComposer = ComponentBroker.get('molecules/MessageComposer'); var CallView = ComponentBroker.get("molecules/voip/CallView"); +var RoomSettings = ComponentBroker.get("molecules/RoomSettings"); var RoomViewController = require("../../../../src/controllers/organisms/RoomView"); @@ -38,6 +39,68 @@ module.exports = React.createClass({ displayName: 'RoomView', mixins: [RoomViewController], + onSettingsClick: function() { + this.setState({editingRoomSettings: true}); + }, + + onSaveClick: function() { + this.setState({editingRoomSettings: false}); + + var new_name = this.refs.header.getRoomName(); + var new_topic = this.refs.room_settings.getTopic(); + var new_join_rule = this.refs.room_settings.getJoinRules(); + var new_history_visibility = this.refs.room_settings.getHistoryVisibility(); + + var old_name = this.state.room.name; + + var old_topic = this.state.room.currentState.getStateEvents('m.room.topic', ''); + if (old_topic) { + old_topic = old_topic.getContent().topic; + } else { + old_topic = ""; + } + + var old_join_rule = this.state.room.currentState.getStateEvents('m.room.join_rules', ''); + if (old_join_rule) { + old_join_rule = old_join_rule.getContent().join_rule; + } else { + old_join_rule = "invite"; + } + + var old_history_visibility = this.state.room.currentState.getStateEvents('m.room.history_visibility', ''); + console.log(old_history_visibility); + if (old_history_visibility) { + old_history_visibility = old_history_visibility.getContent().history_visibility; + } else { + old_history_visibility = "shared"; + } + + + if (old_name != new_name && new_name != undefined) { + MatrixClientPeg.get().setRoomName(this.state.room.roomId, new_name); + } + + if (old_topic != new_topic && new_topic != undefined) { + MatrixClientPeg.get().setRoomTopic(this.state.room.roomId, new_topic); + } + + if (old_join_rule != new_join_rule && new_join_rule != undefined) { + MatrixClientPeg.get().sendStateEvent( + this.state.room.roomId, "m.room.join_rules", { + join_rule: new_join_rule, + }, "" + ); + } + + if (old_history_visibility != new_history_visibility && new_history_visibility != undefined) { + MatrixClientPeg.get().sendStateEvent( + this.state.room.roomId, "m.room.history_visibility", { + history_visibility: new_history_visibility, + }, "" + ); + } + }, + render: function() { if (!this.state.room) { return ( @@ -103,11 +166,19 @@ module.exports = React.createClass({ } } + var roomEdit = null; + + if (this.state.editingRoomSettings) { + roomEdit = ; + } + return (
- +
+ { roomEdit }
@@ -129,4 +200,3 @@ module.exports = React.createClass({ } }, }); - diff --git a/src/ComponentBroker.js b/src/ComponentBroker.js index 8a7bd6632b..56164d3d4c 100644 --- a/src/ComponentBroker.js +++ b/src/ComponentBroker.js @@ -92,6 +92,7 @@ require('../skins/base/views/molecules/UserSelector'); require('../skins/base/views/organisms/UserSettings'); require('../skins/base/views/molecules/ChangeAvatar'); require('../skins/base/views/molecules/ChangePassword'); +require('../skins/base/views/molecules/RoomSettings'); // new for vector require('../skins/base/views/organisms/LeftPanel'); require('../skins/base/views/organisms/RightPanel'); diff --git a/src/controllers/molecules/RoomHeader.js b/src/controllers/molecules/RoomHeader.js index 5bd51e44d3..2ef99953d0 100644 --- a/src/controllers/molecules/RoomHeader.js +++ b/src/controllers/molecules/RoomHeader.js @@ -21,10 +21,25 @@ limitations under the License. * this.state.call_state = the UI state of the call (see CallHandler) */ +var React = require('react'); var dis = require("../../dispatcher"); var CallHandler = require("../../CallHandler"); module.exports = { + propTypes: { + room: React.PropTypes.object.isRequired, + editing: React.PropTypes.bool, + onSettingsClick: React.PropTypes.func, + onSaveClick: React.PropTypes.func, + }, + + getDefaultProps: function() { + return { + editing: false, + onSettingsClick: function() {}, + onSaveClick: function() {}, + }; + }, componentDidMount: function() { this.dispatcherRef = dis.register(this.onAction); @@ -43,7 +58,7 @@ module.exports = { onAction: function(payload) { // if we were given a room_id to track, don't handle anything else. - if (payload.room_id && this.props.room && + if (payload.room_id && this.props.room && this.props.room.roomId !== payload.room_id) { return; } @@ -78,4 +93,3 @@ module.exports = { }); } }; - diff --git a/src/controllers/organisms/RoomView.js b/src/controllers/organisms/RoomView.js index a5bae75429..4f6c4d3cdf 100644 --- a/src/controllers/organisms/RoomView.js +++ b/src/controllers/organisms/RoomView.js @@ -44,7 +44,8 @@ module.exports = { getInitialState: function() { return { room: this.props.roomId ? MatrixClientPeg.get().getRoom(this.props.roomId) : null, - messageCap: INITIAL_SIZE + messageCap: INITIAL_SIZE, + editingRoomSettings: false, } }, @@ -99,7 +100,7 @@ module.exports = { // we'll only be showing a spinner. if (this.state.joining) return; if (room.roomId != this.props.roomId) return; - + if (this.refs.messageWrapper) { var messageWrapper = this.refs.messageWrapper.getDOMNode(); this.atBottom = messageWrapper.scrollHeight - messageWrapper.scrollTop <= messageWrapper.clientHeight; @@ -300,7 +301,7 @@ module.exports = { dateSeparator = ; continuation = false; } - } + } if (!TileType) continue; ret.unshift( @@ -313,4 +314,3 @@ module.exports = { return ret; } }; - From eae09728208a87734e72be03eff4216145a96f93 Mon Sep 17 00:00:00 2001 From: Erik Johnston Date: Mon, 20 Jul 2015 16:28:23 +0100 Subject: [PATCH 02/11] Add files. Add power levels to room settings --- skins/base/css/molecules/RoomSettings.css | 46 ++++++++ skins/base/views/molecules/RoomSettings.js | 128 +++++++++++++++++++++ skins/base/views/organisms/RoomView.js | 1 - src/controllers/molecules/RoomSettings.js | 25 ++++ 4 files changed, 199 insertions(+), 1 deletion(-) create mode 100644 skins/base/css/molecules/RoomSettings.css create mode 100644 skins/base/views/molecules/RoomSettings.js create mode 100644 src/controllers/molecules/RoomSettings.js diff --git a/skins/base/css/molecules/RoomSettings.css b/skins/base/css/molecules/RoomSettings.css new file mode 100644 index 0000000000..5e32529404 --- /dev/null +++ b/skins/base/css/molecules/RoomSettings.css @@ -0,0 +1,46 @@ +/* +Copyright 2015 OpenMarket Ltd + +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. +*/ + +.mx_RoomSettings_power_levels { + display: table; + margin: 5px 0; +} + +.mx_RoomSettings_power_levels > div { + display: table-row; +} + +.mx_RoomSettings_power_levels > div > * { + display: table-cell; + + margin: 0 10px; +} + + +.mx_RoomSettings_user_levels { + display: table; + margin: 5px 0; +} + +.mx_RoomSettings_user_levels > div { + display: table-row; +} + +.mx_RoomSettings_user_levels > div > * { + display: table-cell; + + margin: 0 10px; +} diff --git a/skins/base/views/molecules/RoomSettings.js b/skins/base/views/molecules/RoomSettings.js new file mode 100644 index 0000000000..358764c64b --- /dev/null +++ b/skins/base/views/molecules/RoomSettings.js @@ -0,0 +1,128 @@ +/* +Copyright 2015 OpenMarket Ltd + +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. +*/ + +'use strict'; + +var React = require('react'); +var MatrixClientPeg = require("../../../../src/MatrixClientPeg"); + +var RoomSettingsController = require("../../../../src/controllers/molecules/RoomSettings"); + +module.exports = React.createClass({ + displayName: 'RoomSettings', + mixins: [RoomSettingsController], + + getTopic: function() { + return this.refs.topic.getDOMNode().value; + }, + + getJoinRules: function() { + return this.refs.is_private.getDOMNode().checked ? "invite" : "public"; + }, + + getHistoryVisibility: function() { + return this.refs.share_history.getDOMNode().checked ? "shared" : "invited"; + }, + + render: function() { + var topic = this.props.room.currentState.getStateEvents('m.room.topic', ''); + if (topic) topic = topic.getContent().topic; + + var join_rule = this.props.room.currentState.getStateEvents('m.room.join_rules', ''); + if (join_rule) join_rule = join_rule.getContent().join_rule; + + var history_visibility = this.props.room.currentState.getStateEvents('m.room.history_visibility', ''); + if (history_visibility) history_visibility = history_visibility.getContent().history_visibility; + + var power_levels = this.props.room.currentState.getStateEvents('m.room.power_levels', ''); + power_levels = power_levels.getContent(); + + var ban_level = parseInt(power_levels.ban); + var kick_level = parseInt(power_levels.kick); + var redact_level = parseInt(power_levels.redact); + var invite_level = parseInt(power_levels.invite); + var send_level = parseInt(power_levels.events_default); + var state_level = parseInt(power_levels.state_default); + var default_user_level = parseInt(power_levels.users_default); + + var user_levels = power_levels.users; + + var user_id = MatrixClientPeg.get().credentials.userId; + + var current_user_level = user_levels[user_id]; + if (current_user_level == undefined) current_user_level = default_user_level; + + var power_level_level = power_levels.events["m.room.power_levels"]; + if (power_level_level == undefined) { + power_level_level = state_level; + } + + var can_change_levels = current_user_level >= power_level_level; + + return ( +
+
save_button = (
@@ -78,7 +80,7 @@ module.exports = React.createClass({
); } else { - name = ; + name = ; if (topic) topic_el =
{ topic.getContent().topic }
; settings_button = (
diff --git a/skins/base/views/organisms/RoomView.js b/skins/base/views/organisms/RoomView.js index 124f74cdaf..ffd7bad5a4 100644 --- a/skins/base/views/organisms/RoomView.js +++ b/skins/base/views/organisms/RoomView.js @@ -83,7 +83,7 @@ module.exports = React.createClass({ var deferreds = []; - if (old_name != new_name && new_name != undefined) { + if (old_name != new_name && new_name != undefined && new_name) { deferreds.push( MatrixClientPeg.get().setRoomName(this.state.room.roomId, new_name) ); From c5d84562bad78980d4a42a78ccfd6dd4a433ffaa Mon Sep 17 00:00:00 2001 From: Erik Johnston Date: Tue, 21 Jul 2015 15:24:10 +0100 Subject: [PATCH 11/11] Move logic from view to controller --- skins/base/views/molecules/RoomHeader.js | 2 +- skins/base/views/organisms/RoomView.js | 91 ++---------------------- src/controllers/organisms/RoomView.js | 90 +++++++++++++++++++++++ 3 files changed, 98 insertions(+), 85 deletions(-) diff --git a/skins/base/views/molecules/RoomHeader.js b/skins/base/views/molecules/RoomHeader.js index e08f2651c8..7ad001d660 100644 --- a/skins/base/views/molecules/RoomHeader.js +++ b/skins/base/views/molecules/RoomHeader.js @@ -72,7 +72,7 @@ module.exports = React.createClass({ var actual_name = this.props.room.currentState.getStateEvents('m.room.name', ''); if (actual_name) actual_name = actual_name.getContent().name; if (this.props.editing) { - name = ; + name = ; // if (topic) topic_el =
save_button = (
diff --git a/skins/base/views/organisms/RoomView.js b/skins/base/views/organisms/RoomView.js index ffd7bad5a4..6ecd02d700 100644 --- a/skins/base/views/organisms/RoomView.js +++ b/skins/base/views/organisms/RoomView.js @@ -31,7 +31,6 @@ var RoomHeader = ComponentBroker.get('molecules/RoomHeader'); var MessageComposer = ComponentBroker.get('molecules/MessageComposer'); var CallView = ComponentBroker.get("molecules/voip/CallView"); var RoomSettings = ComponentBroker.get("molecules/RoomSettings"); -var ErrorDialog = ComponentBroker.get("organisms/ErrorDialog"); var RoomViewController = require("../../../../src/controllers/organisms/RoomView"); @@ -58,89 +57,13 @@ module.exports = React.createClass({ var new_history_visibility = this.refs.room_settings.getHistoryVisibility(); var new_power_levels = this.refs.room_settings.getPowerLevels(); - var old_name = this.state.room.name; - - var old_topic = this.state.room.currentState.getStateEvents('m.room.topic', ''); - if (old_topic) { - old_topic = old_topic.getContent().topic; - } else { - old_topic = ""; - } - - var old_join_rule = this.state.room.currentState.getStateEvents('m.room.join_rules', ''); - if (old_join_rule) { - old_join_rule = old_join_rule.getContent().join_rule; - } else { - old_join_rule = "invite"; - } - - var old_history_visibility = this.state.room.currentState.getStateEvents('m.room.history_visibility', ''); - if (old_history_visibility) { - old_history_visibility = old_history_visibility.getContent().history_visibility; - } else { - old_history_visibility = "shared"; - } - - var deferreds = []; - - if (old_name != new_name && new_name != undefined && new_name) { - deferreds.push( - MatrixClientPeg.get().setRoomName(this.state.room.roomId, new_name) - ); - } - - if (old_topic != new_topic && new_topic != undefined) { - deferreds.push( - MatrixClientPeg.get().setRoomTopic(this.state.room.roomId, new_topic) - ); - } - - if (old_join_rule != new_join_rule && new_join_rule != undefined) { - deferreds.push( - MatrixClientPeg.get().sendStateEvent( - this.state.room.roomId, "m.room.join_rules", { - join_rule: new_join_rule, - }, "" - ) - ); - } - - if (old_history_visibility != new_history_visibility && new_history_visibility != undefined) { - deferreds.push( - MatrixClientPeg.get().sendStateEvent( - this.state.room.roomId, "m.room.history_visibility", { - history_visibility: new_history_visibility, - }, "" - ) - ); - } - - if (new_power_levels) { - deferreds.push( - MatrixClientPeg.get().sendStateEvent( - this.state.room.roomId, "m.room.power_levels", new_power_levels, "" - ) - ); - } - - if (deferreds.length) { - var self = this; - q.all(deferreds).fail(function(err) { - Modal.createDialog(ErrorDialog, { - title: "Failed to set state", - description: err.toString() - }); - }).finally(function() { - self.setState({ - uploadingRoomSettings: false, - }); - }); - } else { - this.setState({ - editingRoomSettings: false, - uploadingRoomSettings: false, - }); - } + this.uploadNewState( + new_name, + new_topic, + new_join_rule, + new_history_visibility, + new_power_levels + ); }, render: function() { diff --git a/src/controllers/organisms/RoomView.js b/src/controllers/organisms/RoomView.js index b02b2937ca..311a3e1e2c 100644 --- a/src/controllers/organisms/RoomView.js +++ b/src/controllers/organisms/RoomView.js @@ -21,6 +21,10 @@ var React = require("react"); var q = require("q"); var ContentMessages = require("../../ContentMessages"); var WhoIsTyping = require("../../WhoIsTyping"); +var Modal = require("../../Modal"); +var ComponentBroker = require('../../ComponentBroker'); + +var ErrorDialog = ComponentBroker.get("organisms/ErrorDialog"); var dis = require("../../dispatcher"); @@ -313,5 +317,91 @@ module.exports = { ++count; } return ret; + }, + + uploadNewState: function(new_name, new_topic, new_join_rule, new_history_visibility, new_power_levels) { + var old_name = this.state.room.name; + + var old_topic = this.state.room.currentState.getStateEvents('m.room.topic', ''); + if (old_topic) { + old_topic = old_topic.getContent().topic; + } else { + old_topic = ""; + } + + var old_join_rule = this.state.room.currentState.getStateEvents('m.room.join_rules', ''); + if (old_join_rule) { + old_join_rule = old_join_rule.getContent().join_rule; + } else { + old_join_rule = "invite"; + } + + var old_history_visibility = this.state.room.currentState.getStateEvents('m.room.history_visibility', ''); + if (old_history_visibility) { + old_history_visibility = old_history_visibility.getContent().history_visibility; + } else { + old_history_visibility = "shared"; + } + + var deferreds = []; + + if (old_name != new_name && new_name != undefined && new_name) { + deferreds.push( + MatrixClientPeg.get().setRoomName(this.state.room.roomId, new_name) + ); + } + + if (old_topic != new_topic && new_topic != undefined) { + deferreds.push( + MatrixClientPeg.get().setRoomTopic(this.state.room.roomId, new_topic) + ); + } + + if (old_join_rule != new_join_rule && new_join_rule != undefined) { + deferreds.push( + MatrixClientPeg.get().sendStateEvent( + this.state.room.roomId, "m.room.join_rules", { + join_rule: new_join_rule, + }, "" + ) + ); + } + + if (old_history_visibility != new_history_visibility && new_history_visibility != undefined) { + deferreds.push( + MatrixClientPeg.get().sendStateEvent( + this.state.room.roomId, "m.room.history_visibility", { + history_visibility: new_history_visibility, + }, "" + ) + ); + } + + if (new_power_levels) { + deferreds.push( + MatrixClientPeg.get().sendStateEvent( + this.state.room.roomId, "m.room.power_levels", new_power_levels, "" + ) + ); + } + + if (deferreds.length) { + var self = this; + q.all(deferreds).fail(function(err) { + Modal.createDialog(ErrorDialog, { + title: "Failed to set state", + description: err.toString() + }); + }).finally(function() { + self.setState({ + uploadingRoomSettings: false, + }); + }); + } else { + this.setState({ + editingRoomSettings: false, + uploadingRoomSettings: false, + }); + } } };