2015-11-27 13:42:03 +03:00
|
|
|
/*
|
2016-01-07 07:06:39 +03:00
|
|
|
Copyright 2015, 2016 OpenMarket Ltd
|
2015-11-27 13:42:03 +03:00
|
|
|
|
|
|
|
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.
|
|
|
|
*/
|
|
|
|
|
2016-02-02 15:46:14 +03:00
|
|
|
var q = require("q");
|
2015-11-27 13:42:03 +03:00
|
|
|
var React = require('react');
|
|
|
|
var MatrixClientPeg = require('../../../MatrixClientPeg');
|
2016-05-06 16:19:56 +03:00
|
|
|
var SdkConfig = require('../../../SdkConfig');
|
2015-11-27 13:42:03 +03:00
|
|
|
var sdk = require('../../../index');
|
2016-01-17 05:48:55 +03:00
|
|
|
var Modal = require('../../../Modal');
|
2016-02-05 14:59:19 +03:00
|
|
|
var ObjectUtils = require("../../../ObjectUtils");
|
2016-04-12 19:18:32 +03:00
|
|
|
var dis = require("../../../dispatcher");
|
2016-05-06 16:19:56 +03:00
|
|
|
var ScalarAuthClient = require("../../../ScalarAuthClient");
|
2016-08-23 14:00:11 +03:00
|
|
|
var ScalarMessaging = require('../../../ScalarMessaging');
|
2016-06-23 14:21:31 +03:00
|
|
|
var UserSettingsStore = require('../../../UserSettingsStore');
|
2015-11-27 13:42:03 +03:00
|
|
|
|
2016-06-23 12:36:16 +03:00
|
|
|
// parse a string as an integer; if the input is undefined, or cannot be parsed
|
|
|
|
// as an integer, return a default.
|
|
|
|
function parseIntWithDefault(val, def) {
|
|
|
|
var res = parseInt(val);
|
|
|
|
return isNaN(res) ? def : res;
|
|
|
|
}
|
|
|
|
|
2015-11-27 13:42:03 +03:00
|
|
|
module.exports = React.createClass({
|
|
|
|
displayName: 'RoomSettings',
|
|
|
|
|
|
|
|
propTypes: {
|
|
|
|
room: React.PropTypes.object.isRequired,
|
2016-01-17 06:59:31 +03:00
|
|
|
onSaveClick: React.PropTypes.func,
|
|
|
|
onCancelClick: React.PropTypes.func,
|
2015-11-27 13:42:03 +03:00
|
|
|
},
|
|
|
|
|
|
|
|
getInitialState: function() {
|
2016-01-17 08:13:16 +03:00
|
|
|
var tags = {};
|
|
|
|
Object.keys(this.props.room.tags).forEach(function(tagName) {
|
2016-05-31 23:44:11 +03:00
|
|
|
tags[tagName] = ['yep'];
|
2016-01-17 08:13:16 +03:00
|
|
|
});
|
|
|
|
|
2015-11-27 13:42:03 +03:00
|
|
|
return {
|
2016-02-04 18:26:12 +03:00
|
|
|
name: this._yankValueFromEvent("m.room.name", "name"),
|
|
|
|
topic: this._yankValueFromEvent("m.room.topic", "topic"),
|
|
|
|
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"),
|
2016-01-08 06:22:38 +03:00
|
|
|
power_levels_changed: false,
|
2016-01-17 08:13:16 +03:00
|
|
|
tags_changed: false,
|
|
|
|
tags: tags,
|
2016-07-18 17:22:08 +03:00
|
|
|
// isRoomPublished is loaded async in componentWillMount so when the component
|
|
|
|
// inits, the saved value will always be undefined, however getInitialState()
|
|
|
|
// is also called from the saving code so we must return the correct value here
|
|
|
|
// if we have it (although this could race if the user saves before we load whether
|
2016-07-18 17:36:19 +03:00
|
|
|
// the room is published or not).
|
2016-08-03 20:23:38 +03:00
|
|
|
// Default to false if it's undefined, otherwise react complains about changing
|
|
|
|
// components from uncontrolled to controlled
|
|
|
|
isRoomPublished: this._originalIsRoomPublished || false,
|
2016-08-05 01:26:27 +03:00
|
|
|
scalar_error: null,
|
2015-11-27 13:42:03 +03:00
|
|
|
};
|
|
|
|
},
|
2016-03-22 03:57:40 +03:00
|
|
|
|
|
|
|
componentWillMount: function() {
|
2016-08-23 14:00:11 +03:00
|
|
|
ScalarMessaging.startListening();
|
2016-03-22 15:10:58 +03:00
|
|
|
MatrixClientPeg.get().getRoomDirectoryVisibility(
|
2016-03-22 03:57:40 +03:00
|
|
|
this.props.room.roomId
|
|
|
|
).done((result) => {
|
2016-03-22 15:10:58 +03:00
|
|
|
this.setState({ isRoomPublished: result.visibility === "public" });
|
2016-04-12 03:27:12 +03:00
|
|
|
this._originalIsRoomPublished = result.visibility === "public";
|
2016-03-22 03:57:40 +03:00
|
|
|
}, (err) => {
|
|
|
|
console.error("Failed to get room visibility: " + err);
|
|
|
|
});
|
2016-04-12 19:18:32 +03:00
|
|
|
|
2016-09-02 18:36:43 +03:00
|
|
|
if (UserSettingsStore.isFeatureEnabled("integration_management")) {
|
|
|
|
this.scalarClient = new ScalarAuthClient();
|
|
|
|
this.scalarClient.connect().done(() => {
|
|
|
|
this.forceUpdate();
|
|
|
|
}, (err) => {
|
|
|
|
this.setState({
|
|
|
|
scalar_error: err
|
|
|
|
});
|
|
|
|
})
|
|
|
|
}
|
2016-05-06 16:19:56 +03:00
|
|
|
|
2016-04-12 19:18:32 +03:00
|
|
|
dis.dispatch({
|
|
|
|
action: 'ui_opacity',
|
|
|
|
sideOpacity: 0.3,
|
|
|
|
middleOpacity: 0.3,
|
|
|
|
});
|
|
|
|
},
|
|
|
|
|
|
|
|
componentWillUnmount: function() {
|
2016-08-23 14:00:11 +03:00
|
|
|
ScalarMessaging.stopListening();
|
|
|
|
|
2016-04-12 19:18:32 +03:00
|
|
|
dis.dispatch({
|
|
|
|
action: 'ui_opacity',
|
|
|
|
sideOpacity: 1.0,
|
|
|
|
middleOpacity: 1.0,
|
|
|
|
});
|
2016-03-22 03:57:40 +03:00
|
|
|
},
|
2016-04-12 03:27:12 +03:00
|
|
|
|
2016-02-04 18:26:12 +03:00
|
|
|
setName: function(name) {
|
|
|
|
this.setState({
|
|
|
|
name: name
|
|
|
|
});
|
|
|
|
},
|
2016-04-12 03:27:12 +03:00
|
|
|
|
2016-02-04 18:26:12 +03:00
|
|
|
setTopic: function(topic) {
|
|
|
|
this.setState({
|
|
|
|
topic: topic
|
|
|
|
});
|
|
|
|
},
|
2016-04-12 03:27:12 +03:00
|
|
|
|
2016-02-04 18:26:12 +03:00
|
|
|
save: function() {
|
|
|
|
var stateWasSetDefer = q.defer();
|
|
|
|
// the caller may have JUST called setState on stuff, so we need to re-render before saving
|
|
|
|
// else we won't use the latest values of things.
|
|
|
|
// We can be a bit cheeky here and set a loading flag, and listen for the callback on that
|
|
|
|
// to know when things have been set.
|
|
|
|
this.setState({ _loading: true}, () => {
|
|
|
|
stateWasSetDefer.resolve();
|
|
|
|
this.setState({ _loading: false});
|
|
|
|
});
|
2016-04-12 03:27:12 +03:00
|
|
|
|
2016-02-04 18:26:12 +03:00
|
|
|
return stateWasSetDefer.promise.then(() => {
|
2016-09-15 02:43:30 +03:00
|
|
|
return q.allSettled(this._calcSavePromises());
|
2016-02-04 18:26:12 +03:00
|
|
|
});
|
|
|
|
},
|
|
|
|
|
2016-09-15 02:43:30 +03:00
|
|
|
_calcSavePromises: function() {
|
2016-02-04 18:26:12 +03:00
|
|
|
const roomId = this.props.room.roomId;
|
|
|
|
var promises = this.saveAliases(); // returns Promise[]
|
|
|
|
var originalState = this.getInitialState();
|
2016-02-05 14:59:19 +03:00
|
|
|
|
2016-02-04 18:26:12 +03:00
|
|
|
// diff between original state and this.state to work out what has been changed
|
|
|
|
console.log("Original: %s", JSON.stringify(originalState));
|
|
|
|
console.log("New: %s", JSON.stringify(this.state));
|
2016-02-05 14:59:19 +03:00
|
|
|
|
|
|
|
// name and topic
|
2016-02-05 14:27:11 +03:00
|
|
|
if (this._hasDiff(this.state.name, originalState.name)) {
|
2016-02-04 18:26:12 +03:00
|
|
|
promises.push(MatrixClientPeg.get().setRoomName(roomId, this.state.name));
|
|
|
|
}
|
2016-02-05 14:27:11 +03:00
|
|
|
if (this._hasDiff(this.state.topic, originalState.topic)) {
|
2016-02-04 18:26:12 +03:00
|
|
|
promises.push(MatrixClientPeg.get().setRoomTopic(roomId, this.state.topic));
|
|
|
|
}
|
2016-02-05 14:59:19 +03:00
|
|
|
|
2016-02-05 17:38:28 +03:00
|
|
|
if (this.state.history_visibility !== originalState.history_visibility) {
|
|
|
|
promises.push(MatrixClientPeg.get().sendStateEvent(
|
|
|
|
roomId, "m.room.history_visibility",
|
|
|
|
{ history_visibility: this.state.history_visibility },
|
|
|
|
""
|
|
|
|
));
|
|
|
|
}
|
|
|
|
|
2016-03-22 03:57:40 +03:00
|
|
|
if (this.state.isRoomPublished !== originalState.isRoomPublished) {
|
2016-03-22 15:10:58 +03:00
|
|
|
promises.push(MatrixClientPeg.get().setRoomDirectoryVisibility(
|
2016-04-12 03:27:12 +03:00
|
|
|
roomId,
|
2016-03-22 03:57:40 +03:00
|
|
|
this.state.isRoomPublished ? "public" : "private"
|
|
|
|
));
|
|
|
|
}
|
|
|
|
|
2016-02-05 17:38:28 +03:00
|
|
|
if (this.state.join_rule !== originalState.join_rule) {
|
|
|
|
promises.push(MatrixClientPeg.get().sendStateEvent(
|
|
|
|
roomId, "m.room.join_rules",
|
|
|
|
{ join_rule: this.state.join_rule },
|
|
|
|
""
|
|
|
|
));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (this.state.guest_access !== originalState.guest_access) {
|
|
|
|
promises.push(MatrixClientPeg.get().sendStateEvent(
|
|
|
|
roomId, "m.room.guest_access",
|
|
|
|
{ guest_access: this.state.guest_access },
|
|
|
|
""
|
|
|
|
));
|
|
|
|
}
|
|
|
|
|
2016-02-05 14:59:19 +03:00
|
|
|
|
2016-02-04 18:26:12 +03:00
|
|
|
// power levels
|
2016-02-05 14:59:19 +03:00
|
|
|
var powerLevels = this._getPowerLevels();
|
|
|
|
if (powerLevels) {
|
|
|
|
promises.push(MatrixClientPeg.get().sendStateEvent(
|
|
|
|
roomId, "m.room.power_levels", powerLevels, ""
|
|
|
|
));
|
|
|
|
}
|
|
|
|
|
2016-02-04 18:26:12 +03:00
|
|
|
// tags
|
2016-02-05 14:59:19 +03:00
|
|
|
if (this.state.tags_changed) {
|
|
|
|
var tagDiffs = ObjectUtils.getKeyValueArrayDiffs(originalState.tags, this.state.tags);
|
2016-05-31 23:44:11 +03:00
|
|
|
// [ {place: add, key: "m.favourite", val: ["yep"]} ]
|
2016-02-05 14:59:19 +03:00
|
|
|
tagDiffs.forEach(function(diff) {
|
|
|
|
switch (diff.place) {
|
|
|
|
case "add":
|
|
|
|
promises.push(
|
|
|
|
MatrixClientPeg.get().setRoomTag(roomId, diff.key, {})
|
|
|
|
);
|
|
|
|
break;
|
|
|
|
case "del":
|
|
|
|
promises.push(
|
|
|
|
MatrixClientPeg.get().deleteRoomTag(roomId, diff.key)
|
|
|
|
);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
console.error("Unknown tag operation: %s", diff.place);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
2016-02-05 14:27:11 +03:00
|
|
|
|
2016-02-04 18:26:12 +03:00
|
|
|
// color scheme
|
2016-09-15 02:43:30 +03:00
|
|
|
var p;
|
|
|
|
p = this.saveColor();
|
|
|
|
if (!q.isFulfilled(p)) {
|
|
|
|
promises.push(p);
|
|
|
|
}
|
2016-04-12 03:27:12 +03:00
|
|
|
|
2016-07-20 14:03:13 +03:00
|
|
|
// url preview settings
|
2016-09-15 02:43:30 +03:00
|
|
|
var ps = this.saveUrlPreviewSettings();
|
|
|
|
if (ps.length > 0) {
|
2016-09-15 02:49:10 +03:00
|
|
|
promises.push(ps);
|
2016-09-15 02:43:30 +03:00
|
|
|
}
|
2016-07-20 14:03:13 +03:00
|
|
|
|
2016-06-23 14:21:31 +03:00
|
|
|
// encryption
|
2016-09-15 02:43:30 +03:00
|
|
|
p = this.saveEncryption();
|
|
|
|
if (!q.isFulfilled(p)) {
|
|
|
|
promises.push(p);
|
|
|
|
}
|
2016-06-23 14:21:31 +03:00
|
|
|
|
2016-07-20 14:03:13 +03:00
|
|
|
console.log("Performing %s operations: %s", promises.length, JSON.stringify(promises));
|
2016-09-15 02:43:30 +03:00
|
|
|
return promises;
|
2016-02-04 18:26:12 +03:00
|
|
|
},
|
2015-11-27 13:42:03 +03:00
|
|
|
|
2016-02-02 15:46:14 +03:00
|
|
|
saveAliases: function() {
|
2016-02-05 14:27:11 +03:00
|
|
|
if (!this.refs.alias_settings) { return [q()]; }
|
2016-02-02 15:46:14 +03:00
|
|
|
return this.refs.alias_settings.saveSettings();
|
|
|
|
},
|
|
|
|
|
2016-02-05 14:27:11 +03:00
|
|
|
saveColor: function() {
|
|
|
|
if (!this.refs.color_settings) { return q(); }
|
|
|
|
return this.refs.color_settings.saveSettings();
|
|
|
|
},
|
|
|
|
|
2016-07-20 14:03:13 +03:00
|
|
|
saveUrlPreviewSettings: function() {
|
|
|
|
if (!this.refs.url_preview_settings) { return q(); }
|
|
|
|
return this.refs.url_preview_settings.saveSettings();
|
|
|
|
},
|
|
|
|
|
2016-06-23 14:21:31 +03:00
|
|
|
saveEncryption: function () {
|
|
|
|
if (!this.refs.encrypt) { return q(); }
|
|
|
|
|
|
|
|
var encrypt = this.refs.encrypt.checked;
|
|
|
|
if (!encrypt) { return q(); }
|
|
|
|
|
|
|
|
var roomId = this.props.room.roomId;
|
|
|
|
return MatrixClientPeg.get().sendStateEvent(
|
|
|
|
roomId, "m.room.encryption",
|
2016-09-03 20:42:54 +03:00
|
|
|
{ algorithm: "m.megolm.v1.aes-sha2" }
|
2016-06-23 14:21:31 +03:00
|
|
|
);
|
|
|
|
},
|
|
|
|
|
2016-02-05 14:27:11 +03:00
|
|
|
_hasDiff: function(strA, strB) {
|
|
|
|
// treat undefined as an empty string because other components may blindly
|
|
|
|
// call setName("") when there has been no diff made to the name!
|
|
|
|
strA = strA || "";
|
|
|
|
strB = strB || "";
|
|
|
|
return strA !== strB;
|
|
|
|
},
|
|
|
|
|
2016-02-05 14:59:19 +03:00
|
|
|
_getPowerLevels: function() {
|
2015-11-27 13:42:03 +03:00
|
|
|
if (!this.state.power_levels_changed) return undefined;
|
|
|
|
|
2016-02-05 18:48:04 +03:00
|
|
|
var powerLevels = this.props.room.currentState.getStateEvents('m.room.power_levels', '');
|
|
|
|
powerLevels = powerLevels ? powerLevels.getContent() : {};
|
2015-11-27 13:42:03 +03:00
|
|
|
|
2016-02-05 18:48:04 +03:00
|
|
|
var newPowerLevels = {
|
2016-01-17 05:48:55 +03:00
|
|
|
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()),
|
2016-02-05 18:48:04 +03:00
|
|
|
users: powerLevels.users,
|
|
|
|
events: powerLevels.events,
|
2015-11-27 13:42:03 +03:00
|
|
|
};
|
|
|
|
|
2016-02-05 18:48:04 +03:00
|
|
|
return newPowerLevels;
|
2015-11-27 13:42:03 +03:00
|
|
|
},
|
|
|
|
|
|
|
|
onPowerLevelsChanged: function() {
|
|
|
|
this.setState({
|
|
|
|
power_levels_changed: true
|
|
|
|
});
|
|
|
|
},
|
2016-06-23 12:36:16 +03:00
|
|
|
|
2016-02-04 18:26:12 +03:00
|
|
|
_yankValueFromEvent: function(stateEventType, keyName, defaultValue) {
|
|
|
|
// E.g.("m.room.name","name") would yank the "name" content key from "m.room.name"
|
|
|
|
var event = this.props.room.currentState.getStateEvents(stateEventType, '');
|
|
|
|
if (!event) {
|
|
|
|
return defaultValue;
|
|
|
|
}
|
|
|
|
return event.getContent()[keyName] || defaultValue;
|
|
|
|
},
|
2016-02-05 17:38:28 +03:00
|
|
|
|
|
|
|
_onHistoryRadioToggle: function(ev) {
|
2016-03-20 01:32:44 +03:00
|
|
|
var self = this;
|
|
|
|
var QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
|
|
|
|
|
|
|
|
// cancel the click unless the user confirms it
|
|
|
|
ev.preventDefault();
|
2016-03-25 04:12:16 +03:00
|
|
|
var value = ev.target.value;
|
2016-03-20 01:32:44 +03:00
|
|
|
|
|
|
|
Modal.createDialog(QuestionDialog, {
|
|
|
|
title: "Privacy warning",
|
|
|
|
description:
|
|
|
|
<div>
|
|
|
|
Changes to who can read history will only apply to future messages in this room.<br/>
|
|
|
|
The visibility of existing history will be unchanged.
|
|
|
|
</div>,
|
|
|
|
button: "Continue",
|
|
|
|
onFinished: function(confirmed) {
|
|
|
|
if (confirmed) {
|
|
|
|
self.setState({
|
2016-03-25 04:12:16 +03:00
|
|
|
history_visibility: value
|
2016-03-20 01:32:44 +03:00
|
|
|
});
|
|
|
|
}
|
|
|
|
},
|
2016-02-05 17:38:28 +03:00
|
|
|
});
|
|
|
|
},
|
2016-06-23 12:36:16 +03:00
|
|
|
|
2016-03-22 03:57:40 +03:00
|
|
|
_onRoomAccessRadioToggle: function(ev) {
|
2016-03-22 15:10:58 +03:00
|
|
|
|
|
|
|
// join_rule
|
|
|
|
// INVITE | PUBLIC
|
|
|
|
// ----------------------+----------------
|
|
|
|
// guest CAN_JOIN | inv_only | pub_with_guest
|
|
|
|
// access ----------------------+----------------
|
|
|
|
// FORBIDDEN | inv_only | pub_no_guest
|
|
|
|
// ----------------------+----------------
|
|
|
|
|
2016-03-22 03:57:40 +03:00
|
|
|
switch (ev.target.value) {
|
|
|
|
case "invite_only":
|
2016-03-22 15:10:58 +03:00
|
|
|
this.setState({
|
2016-03-22 03:57:40 +03:00
|
|
|
join_rule: "invite",
|
2016-03-22 15:26:38 +03:00
|
|
|
// we always set guests can_join here as it makes no sense to have
|
|
|
|
// an invite-only room that guests can't join. If you explicitly
|
|
|
|
// invite them, you clearly want them to join, whether they're a
|
|
|
|
// guest or not. In practice, guest_access should probably have
|
|
|
|
// been implemented as part of the join_rules enum.
|
2016-03-22 03:57:40 +03:00
|
|
|
guest_access: "can_join",
|
|
|
|
});
|
|
|
|
break;
|
|
|
|
case "public_no_guests":
|
2016-03-22 15:10:58 +03:00
|
|
|
this.setState({
|
2016-03-22 03:57:40 +03:00
|
|
|
join_rule: "public",
|
|
|
|
guest_access: "forbidden",
|
|
|
|
});
|
|
|
|
break;
|
|
|
|
case "public_with_guests":
|
2016-03-22 15:10:58 +03:00
|
|
|
this.setState({
|
2016-03-22 03:57:40 +03:00
|
|
|
join_rule: "public",
|
|
|
|
guest_access: "can_join",
|
|
|
|
});
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2016-02-04 19:18:59 +03:00
|
|
|
_onToggle: function(keyName, checkedValue, uncheckedValue, ev) {
|
2016-02-04 18:26:12 +03:00
|
|
|
console.log("Checkbox toggle: %s %s", keyName, ev.target.checked);
|
|
|
|
var state = {};
|
2016-02-04 19:18:59 +03:00
|
|
|
state[keyName] = ev.target.checked ? checkedValue : uncheckedValue;
|
2016-02-04 18:26:12 +03:00
|
|
|
this.setState(state);
|
|
|
|
},
|
2016-01-08 06:22:38 +03:00
|
|
|
|
2016-02-05 14:59:19 +03:00
|
|
|
_onTagChange: function(tagName, event) {
|
2016-01-17 08:13:16 +03:00
|
|
|
if (event.target.checked) {
|
|
|
|
if (tagName === 'm.favourite') {
|
|
|
|
delete this.state.tags['m.lowpriority'];
|
|
|
|
}
|
|
|
|
else if (tagName === 'm.lowpriority') {
|
|
|
|
delete this.state.tags['m.favourite'];
|
|
|
|
}
|
|
|
|
|
2016-02-05 14:59:19 +03:00
|
|
|
this.state.tags[tagName] = this.state.tags[tagName] || ["yep"];
|
2016-01-17 08:13:16 +03:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
delete this.state.tags[tagName];
|
|
|
|
}
|
|
|
|
|
|
|
|
this.setState({
|
|
|
|
tags: this.state.tags,
|
|
|
|
tags_changed: true
|
|
|
|
});
|
|
|
|
},
|
|
|
|
|
2016-03-22 15:26:38 +03:00
|
|
|
mayChangeRoomAccess: function() {
|
|
|
|
var cli = MatrixClientPeg.get();
|
|
|
|
var roomState = this.props.room.currentState;
|
|
|
|
return (roomState.mayClientSendStateEvent("m.room.join_rules", cli) &&
|
|
|
|
roomState.mayClientSendStateEvent("m.room.guest_access", cli))
|
|
|
|
},
|
|
|
|
|
2016-05-19 16:12:03 +03:00
|
|
|
onManageIntegrations(ev) {
|
|
|
|
ev.preventDefault();
|
|
|
|
var IntegrationsManager = sdk.getComponent("views.settings.IntegrationsManager");
|
|
|
|
Modal.createDialog(IntegrationsManager, {
|
2016-09-02 18:03:24 +03:00
|
|
|
src: this.scalarClient.hasCredentials() ?
|
|
|
|
this.scalarClient.getScalarInterfaceUrlForRoom(this.props.room.roomId) :
|
2016-09-16 00:56:03 +03:00
|
|
|
null,
|
|
|
|
onFinished: ()=>{
|
|
|
|
if (this._calcSavePromises().length === 0) {
|
|
|
|
this.props.onCancelClick(ev);
|
|
|
|
}
|
|
|
|
},
|
2016-09-19 14:01:46 +03:00
|
|
|
}, "mx_IntegrationsManager");
|
2016-05-19 16:12:03 +03:00
|
|
|
},
|
|
|
|
|
2016-08-28 02:00:22 +03:00
|
|
|
onLeaveClick() {
|
|
|
|
dis.dispatch({
|
|
|
|
action: 'leave_room',
|
|
|
|
room_id: this.props.room.roomId,
|
|
|
|
});
|
|
|
|
},
|
|
|
|
|
|
|
|
onForgetClick() {
|
|
|
|
// FIXME: duplicated with RoomTagContextualMenu (and dead code in RoomView)
|
|
|
|
MatrixClientPeg.get().forget(this.props.room.roomId).done(function() {
|
|
|
|
dis.dispatch({ action: 'view_next_room' });
|
|
|
|
}, function(err) {
|
|
|
|
var errCode = err.errcode || "unknown error code";
|
|
|
|
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
|
|
|
Modal.createDialog(ErrorDialog, {
|
|
|
|
title: "Error",
|
|
|
|
description: `Failed to forget room (${errCode})`
|
|
|
|
});
|
|
|
|
});
|
|
|
|
},
|
|
|
|
|
2016-09-14 04:07:37 +03:00
|
|
|
onEnableEncryptionClick() {
|
2016-09-17 23:56:10 +03:00
|
|
|
if (!this.refs.encrypt.checked) return;
|
|
|
|
|
2016-09-14 04:07:37 +03:00
|
|
|
var QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
|
|
|
|
Modal.createDialog(QuestionDialog, {
|
|
|
|
title: "Warning!",
|
|
|
|
description: (
|
|
|
|
<div>
|
|
|
|
<p>End-to-end encryption is in beta and may not be reliable.</p>
|
2016-09-18 00:07:43 +03:00
|
|
|
<p>You should <b>not</b> yet trust it to secure data. File transfers and calls are not yet encrypted.</p>
|
2016-09-15 18:38:37 +03:00
|
|
|
<p>Devices will <b>not</b> yet be able to decrypt history from before they joined the room.</p>
|
2016-09-14 04:07:37 +03:00
|
|
|
<p>Once encryption is enabled for a room it <b>cannot</b> be turned off again (for now).</p>
|
|
|
|
<p>Encrypted messages will not be visible on clients that do not yet implement encryption<br/>
|
2016-09-21 16:03:35 +03:00
|
|
|
(e.g. Riot/iOS and Riot/Android).</p>
|
2016-09-14 04:07:37 +03:00
|
|
|
</div>
|
|
|
|
),
|
|
|
|
onFinished: confirm=>{
|
|
|
|
if (!confirm) {
|
|
|
|
this.refs.encrypt.checked = false;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
});
|
|
|
|
},
|
|
|
|
|
2016-06-23 14:21:31 +03:00
|
|
|
_renderEncryptionSection: function() {
|
|
|
|
if (!UserSettingsStore.isFeatureEnabled("e2e_encryption")) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
var cli = MatrixClientPeg.get();
|
|
|
|
var roomState = this.props.room.currentState;
|
|
|
|
var isEncrypted = cli.isRoomEncrypted(this.props.room.roomId);
|
|
|
|
|
|
|
|
if (!isEncrypted &&
|
|
|
|
roomState.mayClientSendStateEvent("m.room.encryption", cli)) {
|
2016-09-14 04:07:37 +03:00
|
|
|
return (
|
2016-06-23 14:21:31 +03:00
|
|
|
<label>
|
2016-09-14 04:07:37 +03:00
|
|
|
<input type="checkbox" ref="encrypt" onClick={ this.onEnableEncryptionClick }/>
|
|
|
|
<img className="mx_RoomSettings_e2eIcon" src="img/e2e-unencrypted.svg" width="12" height="12" />
|
2016-06-23 14:21:31 +03:00
|
|
|
Enable encryption (warning: cannot be disabled again!)
|
|
|
|
</label>
|
|
|
|
);
|
|
|
|
}
|
2016-09-14 04:07:37 +03:00
|
|
|
else {
|
|
|
|
return (
|
|
|
|
<label>
|
|
|
|
{ isEncrypted
|
|
|
|
? <img className="mx_RoomSettings_e2eIcon" src="img/e2e-verified.svg" width="10" height="12" />
|
|
|
|
: <img className="mx_RoomSettings_e2eIcon" src="img/e2e-unencrypted.svg" width="12" height="12" />
|
|
|
|
}
|
|
|
|
Encryption is { isEncrypted ? "" : "not " } enabled in this room.
|
|
|
|
</label>
|
|
|
|
);
|
|
|
|
}
|
2016-06-23 14:21:31 +03:00
|
|
|
},
|
|
|
|
|
2015-11-27 13:42:03 +03:00
|
|
|
render: function() {
|
2016-01-13 16:15:13 +03:00
|
|
|
// TODO: go through greying out things you don't have permission to change
|
|
|
|
// (or turning them into informative stuff)
|
|
|
|
|
2016-02-02 15:46:14 +03:00
|
|
|
var AliasSettings = sdk.getComponent("room_settings.AliasSettings");
|
2016-02-05 14:27:11 +03:00
|
|
|
var ColorSettings = sdk.getComponent("room_settings.ColorSettings");
|
2016-07-18 03:35:42 +03:00
|
|
|
var UrlPreviewSettings = sdk.getComponent("room_settings.UrlPreviewSettings");
|
2016-01-13 16:15:13 +03:00
|
|
|
var EditableText = sdk.getComponent('elements.EditableText');
|
|
|
|
var PowerSelector = sdk.getComponent('elements.PowerSelector');
|
2016-05-06 16:19:56 +03:00
|
|
|
var Loader = sdk.getComponent("elements.Spinner")
|
2015-11-27 13:42:03 +03:00
|
|
|
|
2016-03-16 15:09:26 +03:00
|
|
|
var cli = MatrixClientPeg.get();
|
2016-03-16 15:17:07 +03:00
|
|
|
var roomState = this.props.room.currentState;
|
2016-03-16 15:09:26 +03:00
|
|
|
var user_id = cli.credentials.userId;
|
2016-01-13 16:15:13 +03:00
|
|
|
|
2016-06-23 12:36:16 +03:00
|
|
|
var power_level_event = roomState.getStateEvents('m.room.power_levels', '');
|
|
|
|
var power_levels = power_level_event ? power_level_event.getContent() : {};
|
|
|
|
var events_levels = power_levels.events || {};
|
|
|
|
var user_levels = power_levels.users || {};
|
|
|
|
|
|
|
|
var ban_level = parseIntWithDefault(power_levels.ban, 50);
|
|
|
|
var kick_level = parseIntWithDefault(power_levels.kick, 50);
|
|
|
|
var redact_level = parseIntWithDefault(power_levels.redact, 50);
|
|
|
|
var invite_level = parseIntWithDefault(power_levels.invite, 50);
|
|
|
|
var send_level = parseIntWithDefault(power_levels.events_default, 0);
|
|
|
|
var state_level = power_level_event ? parseIntWithDefault(power_levels.state_default, 50) : 0;
|
|
|
|
var default_user_level = parseIntWithDefault(power_levels.users_default, 0);
|
|
|
|
|
|
|
|
var current_user_level = user_levels[user_id];
|
|
|
|
if (current_user_level === undefined) {
|
|
|
|
current_user_level = default_user_level;
|
2015-11-27 13:42:03 +03:00
|
|
|
}
|
|
|
|
|
2016-06-23 12:36:16 +03:00
|
|
|
var can_change_levels = roomState.mayClientSendStateEvent("m.room.power_levels", cli);
|
2016-01-17 06:59:31 +03:00
|
|
|
|
2016-03-16 15:09:26 +03:00
|
|
|
var canSetTag = !cli.isGuest();
|
2016-01-17 08:13:16 +03:00
|
|
|
|
2016-01-08 06:22:38 +03:00
|
|
|
var self = this;
|
|
|
|
|
2016-02-05 18:48:04 +03:00
|
|
|
var userLevelsSection;
|
2016-01-20 20:12:55 +03:00
|
|
|
if (Object.keys(user_levels).length) {
|
2016-02-05 18:48:04 +03:00
|
|
|
userLevelsSection =
|
2016-01-21 01:47:42 +03:00
|
|
|
<div>
|
|
|
|
<h3>Privileged Users</h3>
|
|
|
|
<ul className="mx_RoomSettings_userLevels">
|
|
|
|
{Object.keys(user_levels).map(function(user, i) {
|
|
|
|
return (
|
|
|
|
<li className="mx_RoomSettings_userLevel" key={user}>
|
|
|
|
{ user } is a <PowerSelector value={ user_levels[user] } disabled={true}/>
|
|
|
|
</li>
|
|
|
|
);
|
|
|
|
})}
|
|
|
|
</ul>
|
|
|
|
</div>;
|
2016-01-08 06:22:38 +03:00
|
|
|
}
|
2016-01-17 05:48:55 +03:00
|
|
|
else {
|
2016-02-05 18:48:04 +03:00
|
|
|
userLevelsSection = <div>No users have specific privileges in this room.</div>
|
2016-01-17 05:48:55 +03:00
|
|
|
}
|
2016-01-08 06:22:38 +03:00
|
|
|
|
2016-01-13 16:15:13 +03:00
|
|
|
var banned = this.props.room.getMembersWithMembership("ban");
|
2016-02-05 18:48:04 +03:00
|
|
|
var bannedUsersSection;
|
2016-01-08 06:22:38 +03:00
|
|
|
if (banned.length) {
|
2016-02-05 18:48:04 +03:00
|
|
|
bannedUsersSection =
|
2016-01-08 06:22:38 +03:00
|
|
|
<div>
|
|
|
|
<h3>Banned users</h3>
|
2016-01-21 01:47:42 +03:00
|
|
|
<ul className="mx_RoomSettings_banned">
|
2016-01-08 06:22:38 +03:00
|
|
|
{banned.map(function(member, i) {
|
|
|
|
return (
|
2016-01-21 01:47:42 +03:00
|
|
|
<li key={i}>
|
2016-01-08 06:22:38 +03:00
|
|
|
{member.userId}
|
2016-01-21 01:47:42 +03:00
|
|
|
</li>
|
2016-01-08 06:22:38 +03:00
|
|
|
);
|
|
|
|
})}
|
2016-01-21 01:47:42 +03:00
|
|
|
</ul>
|
2016-01-08 06:22:38 +03:00
|
|
|
</div>;
|
|
|
|
}
|
|
|
|
|
2016-02-05 18:48:04 +03:00
|
|
|
var unfederatableSection;
|
|
|
|
if (this._yankValueFromEvent("m.room.create", "m.federate") === false) {
|
|
|
|
unfederatableSection = (
|
|
|
|
<div className="mx_RoomSettings_powerLevel">
|
|
|
|
Ths room is not accessible by remote Matrix servers.
|
|
|
|
</div>
|
|
|
|
);
|
2016-01-15 17:22:17 +03:00
|
|
|
}
|
|
|
|
|
2016-08-28 02:00:22 +03:00
|
|
|
var leaveButton = null;
|
|
|
|
var myMember = this.props.room.getMember(user_id);
|
|
|
|
if (myMember) {
|
|
|
|
if (myMember.membership === "join") {
|
|
|
|
leaveButton = (
|
|
|
|
<div className="mx_RoomSettings_leaveButton" onClick={ this.onLeaveClick }>
|
|
|
|
Leave room
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
else if (myMember.membership === "leave") {
|
|
|
|
leaveButton = (
|
|
|
|
<div className="mx_RoomSettings_leaveButton" onClick={ this.onForgetClick }>
|
|
|
|
Forget room
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-01-13 16:15:13 +03:00
|
|
|
// TODO: support editing custom events_levels
|
|
|
|
// TODO: support editing custom user_levels
|
|
|
|
|
2016-01-17 08:13:16 +03:00
|
|
|
var tags = [
|
|
|
|
{ name: "m.favourite", label: "Favourite", ref: "tag_favourite" },
|
|
|
|
{ name: "m.lowpriority", label: "Low priority", ref: "tag_lowpriority" },
|
|
|
|
];
|
|
|
|
|
|
|
|
Object.keys(this.state.tags).sort().forEach(function(tagName) {
|
|
|
|
if (tagName !== 'm.favourite' && tagName !== 'm.lowpriority') {
|
|
|
|
tags.push({ name: tagName, label: tagName });
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2016-03-22 16:47:38 +03:00
|
|
|
var tagsSection = null;
|
|
|
|
if (canSetTag || self.state.tags) {
|
2016-06-23 12:36:16 +03:00
|
|
|
var tagsSection =
|
2016-03-22 16:47:38 +03:00
|
|
|
<div className="mx_RoomSettings_tags">
|
|
|
|
Tagged as: { canSetTag ?
|
|
|
|
(tags.map(function(tag, i) {
|
|
|
|
return (<label key={ i }>
|
|
|
|
<input type="checkbox"
|
|
|
|
ref={ tag.ref }
|
|
|
|
checked={ tag.name in self.state.tags }
|
|
|
|
onChange={ self._onTagChange.bind(self, tag.name) }/>
|
|
|
|
{ tag.label }
|
|
|
|
</label>);
|
|
|
|
})) : (self.state.tags && self.state.tags.join) ? self.state.tags.join(", ") : ""
|
|
|
|
}
|
|
|
|
</div>
|
|
|
|
}
|
2016-01-17 08:13:16 +03:00
|
|
|
|
2016-02-05 17:38:28 +03:00
|
|
|
// If there is no history_visibility, it is assumed to be 'shared'.
|
|
|
|
// http://matrix.org/docs/spec/r0.0.0/client_server.html#id31
|
|
|
|
var historyVisibility = this.state.history_visibility || "shared";
|
|
|
|
|
2016-03-22 03:57:40 +03:00
|
|
|
var addressWarning;
|
|
|
|
var aliasEvents = this.props.room.currentState.getStateEvents('m.room.aliases') || [];
|
|
|
|
var aliasCount = 0;
|
|
|
|
aliasEvents.forEach((event) => {
|
|
|
|
aliasCount += event.getContent().aliases.length;
|
|
|
|
});
|
|
|
|
|
|
|
|
if (this.state.join_rule === "public" && aliasCount == 0) {
|
|
|
|
addressWarning =
|
|
|
|
<div className="mx_RoomSettings_warning">
|
|
|
|
To link to a room it must have <a href="#addresses">an address</a>.
|
|
|
|
</div>
|
|
|
|
}
|
|
|
|
|
2016-03-22 15:10:58 +03:00
|
|
|
var inviteGuestWarning;
|
|
|
|
if (this.state.join_rule !== "public" && this.state.guest_access === "forbidden") {
|
|
|
|
inviteGuestWarning =
|
|
|
|
<div className="mx_RoomSettings_warning">
|
|
|
|
Guests cannot join this room even if explicitly invited. <a href="#" onClick={ (e) => {
|
|
|
|
this.setState({ join_rule: "invite", guest_access: "can_join" });
|
|
|
|
e.preventDefault();
|
|
|
|
}}>Click here to fix</a>.
|
|
|
|
</div>
|
|
|
|
}
|
|
|
|
|
2016-09-14 04:07:37 +03:00
|
|
|
var integrationsButton;
|
2016-08-05 01:26:27 +03:00
|
|
|
if (UserSettingsStore.isFeatureEnabled("integration_management")) {
|
2016-09-02 18:03:24 +03:00
|
|
|
if (this.scalarClient.hasCredentials()) {
|
2016-09-14 04:07:37 +03:00
|
|
|
integrationsButton = (
|
|
|
|
<div className="mx_RoomSettings_integrationsButton" onClick={ this.onManageIntegrations }>
|
|
|
|
Manage Integrations
|
2016-08-05 01:26:27 +03:00
|
|
|
</div>
|
|
|
|
);
|
|
|
|
} else if (this.state.scalar_error) {
|
2016-09-14 04:07:37 +03:00
|
|
|
console.error("Unable to contact integrations server");
|
2016-08-05 01:26:27 +03:00
|
|
|
} else {
|
2016-09-14 04:07:37 +03:00
|
|
|
integrationsButton = (
|
2016-09-15 02:43:30 +03:00
|
|
|
<div className="mx_RoomSettings_integrationsButton" style={{ opacity: 0.5 }}>
|
|
|
|
Manage Integrations
|
2016-09-14 04:07:37 +03:00
|
|
|
</div>
|
|
|
|
);
|
2016-08-05 01:26:27 +03:00
|
|
|
}
|
2016-05-06 16:19:56 +03:00
|
|
|
}
|
|
|
|
|
2015-11-27 13:42:03 +03:00
|
|
|
return (
|
|
|
|
<div className="mx_RoomSettings">
|
2016-01-08 06:22:38 +03:00
|
|
|
|
2016-08-28 02:00:22 +03:00
|
|
|
{ leaveButton }
|
2016-09-14 04:07:37 +03:00
|
|
|
{ integrationsButton }
|
2016-08-28 02:00:22 +03:00
|
|
|
|
2016-02-05 18:48:04 +03:00
|
|
|
{ tagsSection }
|
2016-01-17 08:13:16 +03:00
|
|
|
|
2016-01-18 22:56:38 +03:00
|
|
|
<div className="mx_RoomSettings_toggles">
|
2016-03-22 03:57:40 +03:00
|
|
|
<div className="mx_RoomSettings_settings">
|
|
|
|
<h3>Who can access this room?</h3>
|
2016-03-22 15:10:58 +03:00
|
|
|
{ inviteGuestWarning }
|
2016-03-22 03:57:40 +03:00
|
|
|
<label>
|
|
|
|
<input type="radio" name="roomVis" value="invite_only"
|
2016-03-22 15:26:38 +03:00
|
|
|
disabled={ !this.mayChangeRoomAccess() }
|
2016-03-22 03:57:40 +03:00
|
|
|
onChange={this._onRoomAccessRadioToggle}
|
2016-03-22 15:10:58 +03:00
|
|
|
checked={this.state.join_rule !== "public"}/>
|
2016-03-22 03:57:40 +03:00
|
|
|
Only people who have been invited
|
|
|
|
</label>
|
|
|
|
<label>
|
|
|
|
<input type="radio" name="roomVis" value="public_no_guests"
|
2016-03-22 15:26:38 +03:00
|
|
|
disabled={ !this.mayChangeRoomAccess() }
|
2016-03-22 03:57:40 +03:00
|
|
|
onChange={this._onRoomAccessRadioToggle}
|
2016-03-22 15:10:58 +03:00
|
|
|
checked={this.state.join_rule === "public" && this.state.guest_access !== "can_join"}/>
|
2016-03-22 03:57:40 +03:00
|
|
|
Anyone who knows the room's link, apart from guests
|
|
|
|
</label>
|
|
|
|
<label>
|
|
|
|
<input type="radio" name="roomVis" value="public_with_guests"
|
2016-03-22 15:26:38 +03:00
|
|
|
disabled={ !this.mayChangeRoomAccess() }
|
2016-03-22 03:57:40 +03:00
|
|
|
onChange={this._onRoomAccessRadioToggle}
|
2016-03-22 15:10:58 +03:00
|
|
|
checked={this.state.join_rule === "public" && this.state.guest_access === "can_join"}/>
|
2016-03-22 03:57:40 +03:00
|
|
|
Anyone who knows the room's link, including guests
|
|
|
|
</label>
|
|
|
|
{ addressWarning }
|
|
|
|
<br/>
|
2016-09-14 04:07:37 +03:00
|
|
|
{ this._renderEncryptionSection() }
|
2016-03-22 03:57:40 +03:00
|
|
|
<label>
|
|
|
|
<input type="checkbox" disabled={ !roomState.mayClientSendStateEvent("m.room.aliases", cli) }
|
|
|
|
onChange={ this._onToggle.bind(this, "isRoomPublished", true, false)}
|
|
|
|
checked={this.state.isRoomPublished}/>
|
2016-03-31 16:20:50 +03:00
|
|
|
List this room in { MatrixClientPeg.get().getDomain() }'s room directory?
|
2016-03-22 03:57:40 +03:00
|
|
|
</label>
|
|
|
|
</div>
|
2016-02-05 17:38:28 +03:00
|
|
|
<div className="mx_RoomSettings_settings">
|
|
|
|
<h3>Who can read history?</h3>
|
2016-03-22 03:57:40 +03:00
|
|
|
<label>
|
|
|
|
<input type="radio" name="historyVis" value="world_readable"
|
2016-03-16 16:10:45 +03:00
|
|
|
disabled={ !roomState.mayClientSendStateEvent("m.room.history_visibility", cli) }
|
2016-03-20 01:32:44 +03:00
|
|
|
checked={historyVisibility === "world_readable"}
|
2016-02-05 17:38:28 +03:00
|
|
|
onChange={this._onHistoryRadioToggle} />
|
|
|
|
Anyone
|
|
|
|
</label>
|
2016-03-22 03:57:40 +03:00
|
|
|
<label>
|
|
|
|
<input type="radio" name="historyVis" value="shared"
|
2016-03-16 16:10:45 +03:00
|
|
|
disabled={ !roomState.mayClientSendStateEvent("m.room.history_visibility", cli) }
|
2016-03-20 01:32:44 +03:00
|
|
|
checked={historyVisibility === "shared"}
|
2016-02-05 17:38:28 +03:00
|
|
|
onChange={this._onHistoryRadioToggle} />
|
2016-03-16 02:47:40 +03:00
|
|
|
Members only (since the point in time of selecting this option)
|
2016-02-05 17:38:28 +03:00
|
|
|
</label>
|
2016-03-22 03:57:40 +03:00
|
|
|
<label>
|
|
|
|
<input type="radio" name="historyVis" value="invited"
|
2016-03-16 16:10:45 +03:00
|
|
|
disabled={ !roomState.mayClientSendStateEvent("m.room.history_visibility", cli) }
|
2016-03-20 01:32:44 +03:00
|
|
|
checked={historyVisibility === "invited"}
|
2016-02-05 17:38:28 +03:00
|
|
|
onChange={this._onHistoryRadioToggle} />
|
|
|
|
Members only (since they were invited)
|
|
|
|
</label>
|
2016-03-22 03:57:40 +03:00
|
|
|
<label >
|
|
|
|
<input type="radio" name="historyVis" value="joined"
|
2016-03-16 16:10:45 +03:00
|
|
|
disabled={ !roomState.mayClientSendStateEvent("m.room.history_visibility", cli) }
|
2016-03-20 01:32:44 +03:00
|
|
|
checked={historyVisibility === "joined"}
|
2016-02-05 17:38:28 +03:00
|
|
|
onChange={this._onHistoryRadioToggle} />
|
|
|
|
Members only (since they joined)
|
|
|
|
</label>
|
|
|
|
</div>
|
2016-01-18 22:56:38 +03:00
|
|
|
</div>
|
|
|
|
|
|
|
|
|
2016-02-05 14:27:11 +03:00
|
|
|
<div>
|
|
|
|
<h3>Room Colour</h3>
|
|
|
|
<ColorSettings ref="color_settings" room={this.props.room} />
|
|
|
|
</div>
|
2015-11-27 13:42:03 +03:00
|
|
|
|
2016-03-22 03:57:40 +03:00
|
|
|
<a id="addresses"/>
|
|
|
|
|
2016-02-02 15:46:14 +03:00
|
|
|
<AliasSettings ref="alias_settings"
|
|
|
|
roomId={this.props.room.roomId}
|
2016-03-16 16:10:45 +03:00
|
|
|
canSetCanonicalAlias={ roomState.mayClientSendStateEvent("m.room.canonical_alias", cli) }
|
2016-09-28 01:39:25 +03:00
|
|
|
canSetAliases={
|
|
|
|
true
|
|
|
|
/* Originally, we arbitrarily restricted creating aliases to room admins: roomState.mayClientSendStateEvent("m.room.aliases", cli) */
|
|
|
|
}
|
2016-02-02 15:46:14 +03:00
|
|
|
canonicalAliasEvent={this.props.room.currentState.getStateEvents('m.room.canonical_alias', '')}
|
|
|
|
aliasEvents={this.props.room.currentState.getStateEvents('m.room.aliases')} />
|
2016-01-13 16:15:13 +03:00
|
|
|
|
2016-07-18 03:35:42 +03:00
|
|
|
<UrlPreviewSettings ref="url_preview_settings" room={this.props.room} />
|
|
|
|
|
2016-01-13 16:15:13 +03:00
|
|
|
<h3>Permissions</h3>
|
2016-01-08 06:22:38 +03:00
|
|
|
<div className="mx_RoomSettings_powerLevels mx_RoomSettings_settings">
|
2016-01-13 16:15:13 +03:00
|
|
|
<div className="mx_RoomSettings_powerLevel">
|
2016-01-15 19:33:50 +03:00
|
|
|
<span className="mx_RoomSettings_powerLevelKey">The default role for new room members is </span>
|
2016-03-22 20:17:40 +03:00
|
|
|
<PowerSelector ref="users_default" value={default_user_level} controlled={false} disabled={!can_change_levels || current_user_level < default_user_level} onChange={this.onPowerLevelsChanged}/>
|
2015-11-27 13:42:03 +03:00
|
|
|
</div>
|
2016-01-13 16:15:13 +03:00
|
|
|
<div className="mx_RoomSettings_powerLevel">
|
2016-01-15 19:33:50 +03:00
|
|
|
<span className="mx_RoomSettings_powerLevelKey">To send messages, you must be a </span>
|
2016-03-22 20:17:40 +03:00
|
|
|
<PowerSelector ref="events_default" value={send_level} controlled={false} disabled={!can_change_levels || current_user_level < send_level} onChange={this.onPowerLevelsChanged}/>
|
2015-11-27 13:42:03 +03:00
|
|
|
</div>
|
2016-01-13 16:15:13 +03:00
|
|
|
<div className="mx_RoomSettings_powerLevel">
|
2016-01-15 19:33:50 +03:00
|
|
|
<span className="mx_RoomSettings_powerLevelKey">To invite users into the room, you must be a </span>
|
2016-03-22 20:17:40 +03:00
|
|
|
<PowerSelector ref="invite" value={invite_level} controlled={false} disabled={!can_change_levels || current_user_level < invite_level} onChange={this.onPowerLevelsChanged}/>
|
2015-11-27 13:42:03 +03:00
|
|
|
</div>
|
2016-01-13 16:15:13 +03:00
|
|
|
<div className="mx_RoomSettings_powerLevel">
|
2016-01-15 19:33:50 +03:00
|
|
|
<span className="mx_RoomSettings_powerLevelKey">To configure the room, you must be a </span>
|
2016-03-22 20:17:40 +03:00
|
|
|
<PowerSelector ref="state_default" value={state_level} controlled={false} disabled={!can_change_levels || current_user_level < state_level} onChange={this.onPowerLevelsChanged}/>
|
2015-11-27 13:42:03 +03:00
|
|
|
</div>
|
2016-01-13 16:15:13 +03:00
|
|
|
<div className="mx_RoomSettings_powerLevel">
|
2016-01-15 19:33:50 +03:00
|
|
|
<span className="mx_RoomSettings_powerLevelKey">To kick users, you must be a </span>
|
2016-03-22 20:17:40 +03:00
|
|
|
<PowerSelector ref="kick" value={kick_level} controlled={false} disabled={!can_change_levels || current_user_level < kick_level} onChange={this.onPowerLevelsChanged}/>
|
2015-11-27 13:42:03 +03:00
|
|
|
</div>
|
2016-01-13 16:15:13 +03:00
|
|
|
<div className="mx_RoomSettings_powerLevel">
|
2016-01-15 19:33:50 +03:00
|
|
|
<span className="mx_RoomSettings_powerLevelKey">To ban users, you must be a </span>
|
2016-03-22 20:17:40 +03:00
|
|
|
<PowerSelector ref="ban" value={ban_level} controlled={false} disabled={!can_change_levels || current_user_level < ban_level} onChange={this.onPowerLevelsChanged}/>
|
2015-11-27 13:42:03 +03:00
|
|
|
</div>
|
2016-01-13 16:15:13 +03:00
|
|
|
<div className="mx_RoomSettings_powerLevel">
|
2016-01-15 19:33:50 +03:00
|
|
|
<span className="mx_RoomSettings_powerLevelKey">To redact messages, you must be a </span>
|
2016-03-22 20:17:40 +03:00
|
|
|
<PowerSelector ref="redact" value={redact_level} controlled={false} disabled={!can_change_levels || current_user_level < redact_level} onChange={this.onPowerLevelsChanged}/>
|
2015-11-27 13:42:03 +03:00
|
|
|
</div>
|
|
|
|
|
2016-01-13 16:15:13 +03:00
|
|
|
{Object.keys(events_levels).map(function(event_type, i) {
|
2015-11-27 13:42:03 +03:00
|
|
|
return (
|
2016-01-13 16:15:13 +03:00
|
|
|
<div className="mx_RoomSettings_powerLevel" key={event_type}>
|
2016-01-15 19:33:50 +03:00
|
|
|
<span className="mx_RoomSettings_powerLevelKey">To send events of type <code>{ event_type }</code>, you must be a </span>
|
2016-03-22 20:17:40 +03:00
|
|
|
<PowerSelector value={ events_levels[event_type] } controlled={false} disabled={true} onChange={self.onPowerLevelsChanged}/>
|
2015-11-27 13:42:03 +03:00
|
|
|
</div>
|
|
|
|
);
|
|
|
|
})}
|
2016-01-15 19:33:50 +03:00
|
|
|
|
2016-02-05 18:48:04 +03:00
|
|
|
{ unfederatableSection }
|
2015-11-27 13:42:03 +03:00
|
|
|
</div>
|
|
|
|
|
2016-02-05 18:48:04 +03:00
|
|
|
{ userLevelsSection }
|
2016-01-13 16:15:13 +03:00
|
|
|
|
2016-02-05 18:48:04 +03:00
|
|
|
{ bannedUsersSection }
|
2016-01-13 16:15:13 +03:00
|
|
|
|
2016-01-17 05:48:55 +03:00
|
|
|
<h3>Advanced</h3>
|
|
|
|
<div className="mx_RoomSettings_settings">
|
|
|
|
This room's internal ID is <code>{ this.props.room.roomId }</code>
|
|
|
|
</div>
|
2015-11-27 13:42:03 +03:00
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
});
|