diff --git a/src/components/structures/RoomView.js b/src/components/structures/RoomView.js
index 1c1b0ede40..b5c34de20d 100644
--- a/src/components/structures/RoomView.js
+++ b/src/components/structures/RoomView.js
@@ -858,8 +858,14 @@ module.exports = React.createClass({
uploadingRoomSettings: true,
});
- this.refs.room_settings.setName(this.refs.header.getRoomName());
- this.refs.room_settings.setTopic(this.refs.header.getTopic());
+ var newName = this.refs.header.getEditedName();
+ if (newName !== undefined) {
+ this.refs.room_settings.setName(newName);
+ }
+ var newTopic = this.refs.header.getEditedTopic();
+ if (newTopic !== undefined) {
+ this.refs.room_settings.setTopic(newTopic);
+ }
this.refs.room_settings.save().then((results) => {
var fails = results.filter(function(result) { return result.state !== "fulfilled" });
diff --git a/src/components/structures/UserSettings.js b/src/components/structures/UserSettings.js
index bea55ae8a8..a5f2a59878 100644
--- a/src/components/structures/UserSettings.js
+++ b/src/components/structures/UserSettings.js
@@ -249,7 +249,7 @@ module.exports = React.createClass({
throw new Error("Unknown state.phase => " + this.state.phase);
}
// can only get here if phase is UserSettings.DISPLAY
- var RoomHeader = sdk.getComponent('rooms.RoomHeader');
+ var SimpleRoomHeader = sdk.getComponent('rooms.SimpleRoomHeader');
var ChangeDisplayName = sdk.getComponent("views.settings.ChangeDisplayName");
var ChangePassword = sdk.getComponent("views.settings.ChangePassword");
var ChangeAvatar = sdk.getComponent('settings.ChangeAvatar');
@@ -331,7 +331,7 @@ module.exports = React.createClass({
return (
-
+
diff --git a/src/components/views/rooms/RoomHeader.js b/src/components/views/rooms/RoomHeader.js
index 9a132a73f5..3e237a8f95 100644
--- a/src/components/views/rooms/RoomHeader.js
+++ b/src/components/views/rooms/RoomHeader.js
@@ -18,7 +18,6 @@ limitations under the License.
var React = require('react');
var sdk = require('../../../index');
-var dis = require("../../../dispatcher");
var MatrixClientPeg = require('../../../MatrixClientPeg');
var Modal = require("../../../Modal");
@@ -49,31 +48,9 @@ module.exports = React.createClass({
};
},
- getInitialState: function() {
- return {};
- },
-
- componentWillMount: function() {
- this._recalculateState();
- },
-
- componentWillReceiveProps: function(newProps) {
- if (this.props.room !== newProps.room) {
- this._recalculateState();
- }
- },
-
- _recalculateState: function() {
- if (!this.props.room) return;
-
- var topic = this.props.room.currentState.getStateEvents('m.room.topic', '');
- var name = this.props.room.currentState.getStateEvents('m.room.name', '');
-
- this.setState({
- name: name ? name.getContent().name : '',
- defaultName: this.props.room.getDefaultRoomName(MatrixClientPeg.get().credentials.userId),
- topic: topic ? topic.getContent().topic : '',
- });
+ componentDidMount: function() {
+ var cli = MatrixClientPeg.get();
+ cli.on("RoomState.events", this._onRoomStateEvents);
},
componentDidUpdate: function() {
@@ -82,12 +59,20 @@ module.exports = React.createClass({
}
},
- onNameChanged: function(value) {
- this.setState({ name : value });
+ componentWillUnmount: function() {
+ var cli = MatrixClientPeg.get();
+ if (cli) {
+ cli.removeListener("RoomState.events", this._onRoomStateEvents);
+ }
},
- onTopicChanged: function(value) {
- this.setState({ topic : value });
+ _onRoomStateEvents: function(event, state) {
+ if (!this.props.room || event.getRoomId() != this.props.room.roomId) {
+ return;
+ }
+
+ // redisplay the room name, topic, etc.
+ this.forceUpdate();
},
onAvatarPickerClick: function(ev) {
@@ -113,202 +98,193 @@ module.exports = React.createClass({
}).done();
},
- getRoomName: function() {
- return this.state.name;
+ /**
+ * After editing the settings, get the new name for the room
+ *
+ * Returns undefined if we didn't let the user edit the room name
+ */
+ getEditedName: function() {
+ var newName;
+ if (this.refs.nameEditor) {
+ newName = this.refs.nameEditor.getRoomName();
+ }
+ return newName;
},
- getTopic: function() {
- return this.state.topic;
+ /**
+ * After editing the settings, get the new topic for the room
+ *
+ * Returns undefined if we didn't let the user edit the room topic
+ */
+ getEditedTopic: function() {
+ var newTopic;
+ if (this.refs.topicEditor) {
+ newTopic = this.refs.topicEditor.getTopic();
+ }
+ return newTopic;
},
render: function() {
- var EditableText = sdk.getComponent("elements.EditableText");
var RoomAvatar = sdk.getComponent("avatars.RoomAvatar");
var ChangeAvatar = sdk.getComponent("settings.ChangeAvatar");
var TintableSvg = sdk.getComponent("elements.TintableSvg");
var header;
- if (this.props.simpleHeader) {
- var cancel;
- if (this.props.onCancelClick) {
- cancel =
- }
- header =
-
-
- { this.props.simpleHeader }
- { cancel }
-
-
+ var name = null;
+ var searchStatus = null;
+ var topic_el = null;
+ var cancel_button = null;
+ var save_button = null;
+ var settings_button = null;
+ if (this.props.editing) {
+
+ // calculate permissions. XXX: this should be done on mount or something
+ var user_id = MatrixClientPeg.get().credentials.userId;
+
+ var can_set_room_name = this.props.room.currentState.maySendStateEvent(
+ 'm.room.name', user_id
+ );
+ var can_set_room_avatar = this.props.room.currentState.maySendStateEvent(
+ 'm.room.avatar', user_id
+ );
+ var can_set_room_topic = this.props.room.currentState.maySendStateEvent(
+ 'm.room.topic', user_id
+ );
+ var can_set_room_name = this.props.room.currentState.maySendStateEvent(
+ 'm.room.name', user_id
+ );
+
+ save_button =
Save
+ cancel_button =
+ }
+
+ if (can_set_room_name) {
+ var RoomNameEditor = sdk.getComponent("rooms.RoomNameEditor");
+ name =
}
else {
- var name = null;
- var searchStatus = null;
- var topic_el = null;
- var cancel_button = null;
- var save_button = null;
- var settings_button = null;
- if (this.props.editing) {
-
- // calculate permissions. XXX: this should be done on mount or something
- var user_id = MatrixClientPeg.get().credentials.userId;
-
- var can_set_room_name = this.props.room.currentState.maySendStateEvent(
- 'm.room.name', user_id
- );
- var can_set_room_avatar = this.props.room.currentState.maySendStateEvent(
- 'm.room.avatar', user_id
- );
- var can_set_room_topic = this.props.room.currentState.maySendStateEvent(
- 'm.room.topic', user_id
- );
- var can_set_room_name = this.props.room.currentState.maySendStateEvent(
- 'm.room.name', user_id
- );
-
- var placeholderName = "Unnamed Room";
- if (this.state.defaultName && this.state.defaultName !== 'Empty room') {
- placeholderName += " (" + this.state.defaultName + ")";
- }
-
- save_button =
Save
- cancel_button =
+ var searchStatus;
+ // don't display the search count until the search completes and
+ // gives us a valid (possibly zero) searchCount.
+ if (this.props.searchInfo && this.props.searchInfo.searchCount !== undefined && this.props.searchInfo.searchCount !== null) {
+ searchStatus =
(~{ this.props.searchInfo.searchCount } results)
;
}
- if (can_set_room_name) {
- name =
-
-
-
- }
- else {
- var searchStatus;
- // don't display the search count until the search completes and
- // gives us a valid (possibly zero) searchCount.
- if (this.props.searchInfo && this.props.searchInfo.searchCount !== undefined && this.props.searchInfo.searchCount !== null) {
- searchStatus =
(~{ this.props.searchInfo.searchCount } results)
;
- }
-
- // XXX: this is a bit inefficient - we could just compare room.name for 'Empty room'...
- var settingsHint = false;
- var members = this.props.room ? this.props.room.getJoinedMembers() : undefined;
- if (members) {
- if (members.length === 1 && members[0].userId === MatrixClientPeg.get().credentials.userId) {
- var name = this.props.room.currentState.getStateEvents('m.room.name', '');
- if (!name || !name.getContent().name) {
- settingsHint = true;
- }
+ // XXX: this is a bit inefficient - we could just compare room.name for 'Empty room'...
+ var settingsHint = false;
+ var members = this.props.room ? this.props.room.getJoinedMembers() : undefined;
+ if (members) {
+ if (members.length === 1 && members[0].userId === MatrixClientPeg.get().credentials.userId) {
+ var name = this.props.room.currentState.getStateEvents('m.room.name', '');
+ if (!name || !name.getContent().name) {
+ settingsHint = true;
}
}
+ }
- var roomName = 'Join Room';
- if (this.props.oobData && this.props.oobData.name) {
- roomName = this.props.oobData.name;
- } else if (this.props.room) {
- roomName = this.props.room.name;
- }
+ var roomName = 'Join Room';
+ if (this.props.oobData && this.props.oobData.name) {
+ roomName = this.props.oobData.name;
+ } else if (this.props.room) {
+ roomName = this.props.room.name;
+ }
- name =
-
+ );
+ }
+
+ var leave_button;
+ if (this.props.onLeaveClick) {
+ leave_button =
+
+
+
;
+ }
+
+ var forget_button;
+ if (this.props.onForgetClick) {
+ forget_button =
+
+
+
;
+ }
+
+ var right_row;
+ if (!this.props.editing) {
+ right_row =
+
+ { forget_button }
+ { leave_button }
+
+
+
+
;
+ }
+
+ header =
+
+
+
+ { roomAvatar }
+
+
+ { name }
+ { topic_el }
+
+
+ {save_button}
+ {cancel_button}
+ {right_row}
+
;
+
return (
{ header }
diff --git a/src/components/views/rooms/RoomNameEditor.js b/src/components/views/rooms/RoomNameEditor.js
new file mode 100644
index 0000000000..773b713584
--- /dev/null
+++ b/src/components/views/rooms/RoomNameEditor.js
@@ -0,0 +1,63 @@
+/*
+Copyright 2016 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 sdk = require('../../../index');
+var MatrixClientPeg = require('../../../MatrixClientPeg');
+
+module.exports = React.createClass({
+ displayName: 'RoomNameEditor',
+
+ propTypes: {
+ room: React.PropTypes.object.isRequired,
+ },
+
+ componentWillMount: function() {
+ var room = this.props.room;
+ var name = room.currentState.getStateEvents('m.room.name', '');
+ var myId = MatrixClientPeg.get().credentials.userId;
+ var defaultName = room.getDefaultRoomName(myId);
+
+ this._initialName = name ? name.getContent().name : '';
+
+ this._placeholderName = "Unnamed Room";
+ if (defaultName && defaultName !== 'Empty room') {
+ this._placeholderName += " (" + defaultName + ")";
+ }
+ },
+
+ getRoomName: function() {
+ return this.refs.editor.getValue();
+ },
+
+ render: function() {
+ var EditableText = sdk.getComponent("elements.EditableText");
+
+ return (
+
+
+
+ );
+ },
+});
+
diff --git a/src/components/views/rooms/RoomTopicEditor.js b/src/components/views/rooms/RoomTopicEditor.js
new file mode 100644
index 0000000000..ea4550641b
--- /dev/null
+++ b/src/components/views/rooms/RoomTopicEditor.js
@@ -0,0 +1,51 @@
+/*
+Copyright 2016 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 sdk = require('../../../index');
+
+module.exports = React.createClass({
+ displayName: 'RoomTopicEditor',
+
+ propTypes: {
+ room: React.PropTypes.object.isRequired,
+ },
+
+ componentWillMount: function() {
+ var room = this.props.room;
+ var topic = room.currentState.getStateEvents('m.room.topic', '');
+ this._initialTopic = topic ? topic.getContent().topic : '';
+ },
+
+ getTopic: function() {
+ return this.refs.editor.getValue();
+ },
+
+ render: function() {
+ var EditableText = sdk.getComponent("elements.EditableText");
+
+ return (
+
+ );
+ },
+});
diff --git a/src/components/views/rooms/SimpleRoomHeader.js b/src/components/views/rooms/SimpleRoomHeader.js
new file mode 100644
index 0000000000..8388da4a71
--- /dev/null
+++ b/src/components/views/rooms/SimpleRoomHeader.js
@@ -0,0 +1,44 @@
+/*
+Copyright 2016 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');
+
+/*
+ * A stripped-down room header used for things like the user settings
+ * and room directory.
+ */
+module.exports = React.createClass({
+ displayName: 'SimpleRoomHeader',
+
+ propTypes: {
+ title: React.PropTypes.string,
+ },
+
+ render: function() {
+ return (
+