make roomsettings actually work, including alias editing. (using staged UX rather than direct manipulation). loads of tweaks and fixes across the board
This commit is contained in:
parent
90184235bb
commit
82a159d651
4 changed files with 369 additions and 88 deletions
|
@ -66,7 +66,7 @@ function textForMemberEvent(ev) {
|
||||||
function textForTopicEvent(ev) {
|
function textForTopicEvent(ev) {
|
||||||
var senderDisplayName = ev.sender && ev.sender.name ? ev.sender.name : ev.getSender();
|
var senderDisplayName = ev.sender && ev.sender.name ? ev.sender.name : ev.getSender();
|
||||||
|
|
||||||
return senderDisplayName + ' changed the topic to, "' + ev.getContent().topic + '"';
|
return senderDisplayName + ' changed the topic to "' + ev.getContent().topic + '"';
|
||||||
};
|
};
|
||||||
|
|
||||||
function textForRoomNameEvent(ev) {
|
function textForRoomNameEvent(ev) {
|
||||||
|
|
|
@ -887,6 +887,24 @@ module.exports = React.createClass({
|
||||||
old_history_visibility = "shared";
|
old_history_visibility = "shared";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var old_guest_read = (old_history_visibility === "world_readable");
|
||||||
|
|
||||||
|
var old_guest_join = this.state.room.currentState.getStateEvents('m.room.guest_access', '');
|
||||||
|
if (old_guest_join) {
|
||||||
|
old_guest_join = (old_guest_join.getContent().guest_access === "can_join");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
old_guest_join = (old_guest_join.getContent().guest_access === "forbidden");
|
||||||
|
}
|
||||||
|
|
||||||
|
var old_canonical_alias = this.state.room.currentState.getStateEvents('m.room.canonical_alias', '');
|
||||||
|
if (old_canonical_alias) {
|
||||||
|
old_canonical_alias = old_canonical_alias.getContent().alias;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
old_canonical_alias = "";
|
||||||
|
}
|
||||||
|
|
||||||
var deferreds = [];
|
var deferreds = [];
|
||||||
|
|
||||||
if (old_name != newVals.name && newVals.name != undefined) {
|
if (old_name != newVals.name && newVals.name != undefined) {
|
||||||
|
@ -930,6 +948,49 @@ module.exports = React.createClass({
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (newVals.alias_operations) {
|
||||||
|
var oplist = [];
|
||||||
|
for (var i = 0; i < newVals.alias_operations.length; i++) {
|
||||||
|
var alias_operation = newVals.alias_operations[i];
|
||||||
|
switch (alias_operation.type) {
|
||||||
|
case 'put':
|
||||||
|
oplist.push(
|
||||||
|
MatrixClientPeg.get().createAlias(
|
||||||
|
alias_operation.alias, this.state.room.roomId
|
||||||
|
)
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case 'delete':
|
||||||
|
oplist.push(
|
||||||
|
MatrixClientPeg.get().deleteAlias(
|
||||||
|
alias_operation.alias
|
||||||
|
)
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
console.log("Unknown alias operation, ignoring: " + alias_operation.type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (oplist.length) {
|
||||||
|
var deferred = oplist[0];
|
||||||
|
oplist.splice(1).forEach(function (f) {
|
||||||
|
deferred = deferred.then(f);
|
||||||
|
});
|
||||||
|
deferreds.push(deferred);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (old_canonical_alias !== newVals.canonical_alias) {
|
||||||
|
deferreds.push(
|
||||||
|
MatrixClientPeg.get().sendStateEvent(
|
||||||
|
this.state.room.roomId, "m.room.canonical_alias", {
|
||||||
|
alias: newVals.canonical_alias
|
||||||
|
}, ""
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if (newVals.color_scheme) {
|
if (newVals.color_scheme) {
|
||||||
deferreds.push(
|
deferreds.push(
|
||||||
MatrixClientPeg.get().setRoomAccountData(
|
MatrixClientPeg.get().setRoomAccountData(
|
||||||
|
@ -938,26 +999,43 @@ module.exports = React.createClass({
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
deferreds.push(
|
if (old_guest_read != newVals.guest_read ||
|
||||||
MatrixClientPeg.get().setGuestAccess(this.state.room.roomId, {
|
old_guest_join != newVals.guest_join)
|
||||||
allowRead: newVals.guest_read,
|
{
|
||||||
allowJoin: newVals.guest_join
|
deferreds.push(
|
||||||
})
|
MatrixClientPeg.get().setGuestAccess(this.state.room.roomId, {
|
||||||
);
|
allowRead: newVals.guest_read,
|
||||||
|
allowJoin: newVals.guest_join
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if (deferreds.length) {
|
if (deferreds.length) {
|
||||||
var self = this;
|
var self = this;
|
||||||
q.all(deferreds).fail(function(err) {
|
q.allSettled(deferreds).then(
|
||||||
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
function(results) {
|
||||||
Modal.createDialog(ErrorDialog, {
|
var fails = results.filter(function(result) { return result.state !== "fulfilled" });
|
||||||
title: "Failed to set state",
|
if (fails.length) {
|
||||||
description: err.toString()
|
fails.forEach(function(result) {
|
||||||
|
console.error(result.reason);
|
||||||
|
});
|
||||||
|
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||||
|
Modal.createDialog(ErrorDialog, {
|
||||||
|
title: "Failed to set state",
|
||||||
|
description: fails.map(function(result) { return result.reason }).join("\n"),
|
||||||
|
});
|
||||||
|
self.refs.room_settings.resetState();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
self.setState({
|
||||||
|
editingRoomSettings: false
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}).finally(function() {
|
||||||
|
self.setState({
|
||||||
|
uploadingRoomSettings: false,
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}).finally(function() {
|
|
||||||
self.setState({
|
|
||||||
uploadingRoomSettings: false,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
this.setState({
|
this.setState({
|
||||||
editingRoomSettings: false,
|
editingRoomSettings: false,
|
||||||
|
@ -1025,16 +1103,17 @@ module.exports = React.createClass({
|
||||||
|
|
||||||
onSaveClick: function() {
|
onSaveClick: function() {
|
||||||
this.setState({
|
this.setState({
|
||||||
editingRoomSettings: false,
|
|
||||||
uploadingRoomSettings: true,
|
uploadingRoomSettings: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
this.uploadNewState({
|
this.uploadNewState({
|
||||||
name: this.refs.header.getRoomName(),
|
name: this.refs.header.getRoomName(),
|
||||||
topic: this.refs.room_settings.getTopic(),
|
topic: this.refs.header.getTopic(),
|
||||||
join_rule: this.refs.room_settings.getJoinRules(),
|
join_rule: this.refs.room_settings.getJoinRules(),
|
||||||
history_visibility: this.refs.room_settings.getHistoryVisibility(),
|
history_visibility: this.refs.room_settings.getHistoryVisibility(),
|
||||||
power_levels: this.refs.room_settings.getPowerLevels(),
|
power_levels: this.refs.room_settings.getPowerLevels(),
|
||||||
|
alias_operations: this.refs.room_settings.getAliasOperations(),
|
||||||
|
canonical_alias: this.refs.room_settings.getCanonicalAlias(),
|
||||||
guest_join: this.refs.room_settings.canGuestsJoin(),
|
guest_join: this.refs.room_settings.canGuestsJoin(),
|
||||||
guest_read: this.refs.room_settings.canGuestsRead(),
|
guest_read: this.refs.room_settings.canGuestsRead(),
|
||||||
color_scheme: this.refs.room_settings.getColorScheme(),
|
color_scheme: this.refs.room_settings.getColorScheme(),
|
||||||
|
|
|
@ -71,6 +71,13 @@ module.exports = React.createClass({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
componentDidUpdate: function(newProps) {
|
||||||
|
this.value = this.props.initialValue;
|
||||||
|
if (this.refs.editable_div) {
|
||||||
|
this.showPlaceholder(!this.value);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
showPlaceholder: function(show) {
|
showPlaceholder: function(show) {
|
||||||
if (show) {
|
if (show) {
|
||||||
this.refs.editable_div.textContent = this.props.placeholder;
|
this.refs.editable_div.textContent = this.props.placeholder;
|
||||||
|
@ -89,6 +96,11 @@ module.exports = React.createClass({
|
||||||
return this.value;
|
return this.value;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
setValue: function(value) {
|
||||||
|
this.value = value;
|
||||||
|
this.showPlaceholder(!this.value);
|
||||||
|
},
|
||||||
|
|
||||||
edit: function() {
|
edit: function() {
|
||||||
this.setState({
|
this.setState({
|
||||||
phase: this.Phases.Edit,
|
phase: this.Phases.Edit,
|
||||||
|
@ -99,6 +111,8 @@ module.exports = React.createClass({
|
||||||
this.setState({
|
this.setState({
|
||||||
phase: this.Phases.Display,
|
phase: this.Phases.Display,
|
||||||
});
|
});
|
||||||
|
this.value = this.props.initialValue;
|
||||||
|
this.showPlaceholder(!this.value);
|
||||||
this.onValueChanged(false);
|
this.onValueChanged(false);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -110,9 +124,7 @@ module.exports = React.createClass({
|
||||||
// console.log("keyDown: textContent=" + ev.target.textContent + ", value=" + this.value + ", placeholder=" + this.placeholder);
|
// console.log("keyDown: textContent=" + ev.target.textContent + ", value=" + this.value + ", placeholder=" + this.placeholder);
|
||||||
|
|
||||||
if (this.placeholder) {
|
if (this.placeholder) {
|
||||||
if (ev.keyCode !== KEY_SHIFT && !ev.metaKey && !ev.ctrlKey && !ev.altKey && ev.keyCode !== KEY_WINDOWS && ev.keyCode !== KEY_TAB) {
|
this.showPlaceholder(false);
|
||||||
this.showPlaceholder(false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ev.key == "Enter") {
|
if (ev.key == "Enter") {
|
||||||
|
@ -182,7 +194,9 @@ module.exports = React.createClass({
|
||||||
if (this.props.blurToCancel)
|
if (this.props.blurToCancel)
|
||||||
this.cancelEdit();
|
this.cancelEdit();
|
||||||
else
|
else
|
||||||
this.onFinish(ev)
|
this.onFinish(ev);
|
||||||
|
|
||||||
|
this.showPlaceholder(!this.value);
|
||||||
},
|
},
|
||||||
|
|
||||||
render: function() {
|
render: function() {
|
||||||
|
|
|
@ -18,6 +18,7 @@ var React = require('react');
|
||||||
var MatrixClientPeg = require('../../../MatrixClientPeg');
|
var MatrixClientPeg = require('../../../MatrixClientPeg');
|
||||||
var Tinter = require('../../../Tinter');
|
var Tinter = require('../../../Tinter');
|
||||||
var sdk = require('../../../index');
|
var sdk = require('../../../index');
|
||||||
|
var Modal = require('../../../Modal');
|
||||||
|
|
||||||
var room_colors = [
|
var room_colors = [
|
||||||
// magic room default values courtesy of Ribot
|
// magic room default values courtesy of Ribot
|
||||||
|
@ -40,6 +41,9 @@ module.exports = React.createClass({
|
||||||
room: React.PropTypes.object.isRequired,
|
room: React.PropTypes.object.isRequired,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
componentDidMount: function() {
|
||||||
|
},
|
||||||
|
|
||||||
getInitialState: function() {
|
getInitialState: function() {
|
||||||
// work out the initial color index
|
// work out the initial color index
|
||||||
var room_color_index = undefined;
|
var room_color_index = undefined;
|
||||||
|
@ -68,15 +72,28 @@ module.exports = React.createClass({
|
||||||
room_color_index = 0;
|
room_color_index = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// get the aliases
|
||||||
|
var aliases = {};
|
||||||
|
var domain = MatrixClientPeg.get().getDomain();
|
||||||
|
var alias_events = this.props.room.currentState.getStateEvents('m.room.aliases');
|
||||||
|
for (var i = 0; i < alias_events.length; i++) {
|
||||||
|
aliases[alias_events[i].getStateKey()] = alias_events[i].getContent().aliases.slice(); // shallow copy
|
||||||
|
}
|
||||||
|
aliases[domain] = aliases[domain] || [];
|
||||||
|
|
||||||
return {
|
return {
|
||||||
power_levels_changed: false,
|
power_levels_changed: false,
|
||||||
color_scheme_changed: false,
|
color_scheme_changed: false,
|
||||||
color_scheme_index: room_color_index,
|
color_scheme_index: room_color_index,
|
||||||
aliases_changed: false,
|
aliases_changed: false,
|
||||||
aliases: [],
|
aliases: aliases,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
resetState: function() {
|
||||||
|
this.set.state(this.getInitialState());
|
||||||
|
},
|
||||||
|
|
||||||
canGuestsJoin: function() {
|
canGuestsJoin: function() {
|
||||||
return this.refs.guests_join.checked;
|
return this.refs.guests_join.checked;
|
||||||
},
|
},
|
||||||
|
@ -104,13 +121,13 @@ module.exports = React.createClass({
|
||||||
power_levels = power_levels.getContent();
|
power_levels = power_levels.getContent();
|
||||||
|
|
||||||
var new_power_levels = {
|
var new_power_levels = {
|
||||||
ban: parseInt(this.refs.ban.value),
|
ban: parseInt(this.refs.ban.getValue()),
|
||||||
kick: parseInt(this.refs.kick.value),
|
kick: parseInt(this.refs.kick.getValue()),
|
||||||
redact: parseInt(this.refs.redact.value),
|
redact: parseInt(this.refs.redact.getValue()),
|
||||||
invite: parseInt(this.refs.invite.value),
|
invite: parseInt(this.refs.invite.getValue()),
|
||||||
events_default: parseInt(this.refs.events_default.value),
|
events_default: parseInt(this.refs.events_default.getValue()),
|
||||||
state_default: parseInt(this.refs.state_default.value),
|
state_default: parseInt(this.refs.state_default.getValue()),
|
||||||
users_default: parseInt(this.refs.users_default.value),
|
users_default: parseInt(this.refs.users_default.getValue()),
|
||||||
users: power_levels.users,
|
users: power_levels.users,
|
||||||
events: power_levels.events,
|
events: power_levels.events,
|
||||||
};
|
};
|
||||||
|
@ -118,6 +135,75 @@ module.exports = React.createClass({
|
||||||
return new_power_levels;
|
return new_power_levels;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
getCanonicalAlias: function() {
|
||||||
|
return this.refs.canonical_alias ? this.refs.canonical_alias.value : "";
|
||||||
|
},
|
||||||
|
|
||||||
|
getAliasOperations: function() {
|
||||||
|
if (!this.state.aliases_changed) return undefined;
|
||||||
|
|
||||||
|
// work out the delta from room state to UI state
|
||||||
|
var ops = [];
|
||||||
|
|
||||||
|
// calculate original ("old") aliases
|
||||||
|
var oldAliases = {};
|
||||||
|
var aliases = this.state.aliases;
|
||||||
|
var alias_events = this.props.room.currentState.getStateEvents('m.room.aliases');
|
||||||
|
for (var i = 0; i < alias_events.length; i++) {
|
||||||
|
var domain = alias_events[i].getStateKey();
|
||||||
|
oldAliases[domain] = alias_events[i].getContent().aliases.slice(); // shallow copy
|
||||||
|
}
|
||||||
|
|
||||||
|
// work out whether any domains have entirely disappeared or appeared
|
||||||
|
var domainDelta = {}
|
||||||
|
Object.keys(oldAliases).forEach(function(domain) {
|
||||||
|
domainDelta[domain] = domainDelta[domain] || 0;
|
||||||
|
domainDelta[domain]--;
|
||||||
|
});
|
||||||
|
Object.keys(aliases).forEach(function(domain) {
|
||||||
|
domainDelta[domain] = domainDelta[domain] || 0;
|
||||||
|
domainDelta[domain]++;
|
||||||
|
});
|
||||||
|
|
||||||
|
Object.keys(domainDelta).forEach(function(domain) {
|
||||||
|
switch (domainDelta[domain]) {
|
||||||
|
case 1: // entirely new domain
|
||||||
|
aliases[domain].forEach(function(alias) {
|
||||||
|
ops.push({ type: "put", alias : alias });
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case -1: // entirely removed domain
|
||||||
|
oldAliases[domain].forEach(function(alias) {
|
||||||
|
ops.push({ type: "delete", alias : alias });
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case 0: // mix of aliases in this domain.
|
||||||
|
// compare old & new aliases for this domain
|
||||||
|
var delta = {};
|
||||||
|
oldAliases[domain].forEach(function(item) {
|
||||||
|
delta[item] = delta[item] || 0;
|
||||||
|
delta[item]--;
|
||||||
|
});
|
||||||
|
aliases[domain].forEach(function(item) {
|
||||||
|
delta[item] = delta[item] || 0;
|
||||||
|
delta[item]++;
|
||||||
|
});
|
||||||
|
|
||||||
|
Object.keys(delta).forEach(function(alias) {
|
||||||
|
if (delta[alias] == 1) {
|
||||||
|
ops.push({ type: "put", alias: alias });
|
||||||
|
} else if (delta[alias] == -1) {
|
||||||
|
ops.push({ type: "delete", alias: alias });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return ops;
|
||||||
|
},
|
||||||
|
|
||||||
onPowerLevelsChanged: function() {
|
onPowerLevelsChanged: function() {
|
||||||
this.setState({
|
this.setState({
|
||||||
power_levels_changed: true
|
power_levels_changed: true
|
||||||
|
@ -143,16 +229,66 @@ module.exports = React.createClass({
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
onAliasChanged: function(i, j) {
|
onAliasChanged: function(domain, index, alias) {
|
||||||
|
if (alias === "") return; // hit the delete button to delete please
|
||||||
|
var oldAlias;
|
||||||
|
if (this.isAliasValid(alias)) {
|
||||||
|
oldAlias = this.state.aliases[domain][index];
|
||||||
|
this.state.aliases[domain][index] = alias;
|
||||||
|
this.setState({ aliases_changed : true });
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||||
|
Modal.createDialog(ErrorDialog, {
|
||||||
|
title: "Invalid alias format",
|
||||||
|
description: "'" + alias + "' is not a valid format for an alias",
|
||||||
|
});
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
onAliasDeleted: function(i, j) {
|
onAliasDeleted: function(domain, index) {
|
||||||
|
// XXX: can we edit state directly and then set, or should we copy it first?
|
||||||
|
var alias = this.state.aliases[domain].splice(index, 1);
|
||||||
|
this.setState({
|
||||||
|
aliases: this.state.aliases
|
||||||
|
});
|
||||||
|
|
||||||
|
this.setState({ aliases_changed : true });
|
||||||
},
|
},
|
||||||
|
|
||||||
onAliasAdded: function(i, j) {
|
onAliasAdded: function(alias) {
|
||||||
|
if (alias === "") return; // ignore attempts to create blank aliases
|
||||||
|
if (alias === undefined) {
|
||||||
|
alias = this.refs.add_alias ? this.refs.add_alias.getValue() : undefined;
|
||||||
|
if (alias === undefined || alias === "") return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.isAliasValid(alias)) {
|
||||||
|
var domain = alias.replace(/^.*?:/, '');
|
||||||
|
// XXX: do we need to deep copy aliases before editing it?
|
||||||
|
this.state.aliases[domain] = this.state.aliases[domain] || [];
|
||||||
|
this.state.aliases[domain].push(alias);
|
||||||
|
this.setState({
|
||||||
|
aliases: this.state.aliases
|
||||||
|
});
|
||||||
|
|
||||||
|
// reset the add field
|
||||||
|
this.refs.add_alias.setValue('');
|
||||||
|
|
||||||
|
this.setState({ aliases_changed : true });
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||||
|
Modal.createDialog(ErrorDialog, {
|
||||||
|
title: "Invalid alias format",
|
||||||
|
description: "'" + alias + "' is not a valid format for an alias",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
isAliasValid: function(alias) {
|
||||||
|
// XXX: FIXME SPEC-1
|
||||||
|
return (alias.match(/^#([^\/:,]+?):(.+)$/) && encodeURI(alias) === alias);
|
||||||
},
|
},
|
||||||
|
|
||||||
render: function() {
|
render: function() {
|
||||||
|
@ -223,73 +359,117 @@ module.exports = React.createClass({
|
||||||
var can_change_levels = false;
|
var can_change_levels = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
var room_avatar_level = parseInt(power_levels.state_default || 0);
|
var room_aliases_level = parseInt(power_levels.state_default || 0);
|
||||||
if (events_levels['m.room.avatar'] !== undefined) {
|
if (events_levels['m.room.aliases'] !== undefined) {
|
||||||
room_avatar_level = events_levels['m.room.avatar'];
|
room_avatar_level = events_levels['m.room.aliases'];
|
||||||
}
|
}
|
||||||
var can_set_room_avatar = current_user_level >= room_avatar_level;
|
var can_set_room_aliases = current_user_level >= room_aliases_level;
|
||||||
|
|
||||||
|
var canonical_alias_level = parseInt(power_levels.state_default || 0);
|
||||||
|
if (events_levels['m.room.canonical_alias'] !== undefined) {
|
||||||
|
room_avatar_level = events_levels['m.room.canonical_alias'];
|
||||||
|
}
|
||||||
|
var can_set_canonical_alias = current_user_level >= canonical_alias_level;
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
var alias_events = this.props.room.currentState.getStateEvents('m.room.aliases');
|
|
||||||
var canonical_alias_event = this.props.room.currentState.getStateEvents('m.room.canonical_alias', '');
|
var canonical_alias_event = this.props.room.currentState.getStateEvents('m.room.canonical_alias', '');
|
||||||
var canonical_alias = canonical_alias_event ? canonical_alias_event.getContent().alias : "";
|
var canonical_alias = canonical_alias_event ? canonical_alias_event.getContent().alias : "";
|
||||||
var domain = MatrixClientPeg.get().getDomain();
|
var domain = MatrixClientPeg.get().getDomain();
|
||||||
|
|
||||||
|
var remote_domains = Object.keys(this.state.aliases).filter(function(alias) { return alias !== domain });
|
||||||
|
|
||||||
|
var remote_aliases_section;
|
||||||
|
if (remote_domains.length) {
|
||||||
|
remote_aliases_section =
|
||||||
|
<div>
|
||||||
|
<div className="mx_RoomSettings_aliasLabel">
|
||||||
|
This room can be found elsewhere as:
|
||||||
|
</div>
|
||||||
|
<div className="mx_RoomSettings_aliasesTable">
|
||||||
|
{ remote_domains.map(function(state_key, i) {
|
||||||
|
self.state.aliases[state_key].map(function(alias, j) {
|
||||||
|
return (
|
||||||
|
<div className="mx_RoomSettings_aliasesTableRow" key={ i + "_" + j }>
|
||||||
|
<EditableText
|
||||||
|
className="mx_RoomSettings_alias mx_RoomSettings_editable"
|
||||||
|
blurToCancel={ false }
|
||||||
|
editable={ false }
|
||||||
|
initialValue={ alias } />
|
||||||
|
<div className="mx_RoomSettings_deleteAlias">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
var canonical_alias_section;
|
||||||
|
if (can_set_canonical_alias) {
|
||||||
|
canonical_alias_section =
|
||||||
|
<select ref="canonical_alias" defaultValue={ canonical_alias }>
|
||||||
|
{ Object.keys(self.state.aliases).map(function(stateKey, i) {
|
||||||
|
return self.state.aliases[stateKey].map(function(alias, j) {
|
||||||
|
return <option value={ alias } key={ i + "_" + j }>{ alias }</option>
|
||||||
|
});
|
||||||
|
})}
|
||||||
|
<option value="" key="unset">not set</option>
|
||||||
|
</select>
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
canonical_alias_section = <b>{ canonical_alias || "not set" }</b>;
|
||||||
|
}
|
||||||
|
|
||||||
var aliases_section =
|
var aliases_section =
|
||||||
<div>
|
<div>
|
||||||
<h3>Directory</h3>
|
<h3>Directory</h3>
|
||||||
<div className="mx_RoomSettings_aliasLabel">
|
<div className="mx_RoomSettings_aliasLabel">
|
||||||
{ alias_events.length ? "This room is accessible via:" : "This room has no aliases." }
|
{ this.state.aliases[domain].length
|
||||||
|
? "This room can be found on " + domain + " as:"
|
||||||
|
: "This room is not findable on " + domain }
|
||||||
</div>
|
</div>
|
||||||
<div className="mx_RoomSettings_aliasesTable">
|
<div className="mx_RoomSettings_aliasesTable">
|
||||||
{ alias_events.map(function(alias_event, i) {
|
{ this.state.aliases[domain].map(function(alias, i) {
|
||||||
return alias_event.getContent().aliases.map(function(alias, j) {
|
var deleteButton;
|
||||||
var deleteButton;
|
if (can_set_room_aliases) {
|
||||||
if (alias_event && alias_event.getStateKey() === domain) {
|
deleteButton = <img src="img/cancel-small.svg" width="14" height="14" alt="Delete" onClick={ self.onAliasDeleted.bind(self, domain, i) }/>;
|
||||||
deleteButton = <img src="img/cancel-small.svg" width="14" height="14" alt="Delete" onClick={ self.onAliasDeleted.bind(self, i, j) }/>;
|
}
|
||||||
}
|
return (
|
||||||
return (
|
<div className="mx_RoomSettings_aliasesTableRow" key={ i }>
|
||||||
<div className="mx_RoomSettings_aliasesTableRow" key={ i + "_" + j }>
|
<EditableText
|
||||||
<EditableText
|
className="mx_RoomSettings_alias mx_RoomSettings_editable"
|
||||||
className="mx_RoomSettings_alias mx_RoomSettings_editable"
|
placeholderClassName="mx_RoomSettings_aliasPlaceholder"
|
||||||
placeholderClassName="mx_RoomSettings_aliasPlaceholder"
|
placeholder={ "New alias (e.g. #foo:" + domain + ")" }
|
||||||
placeholder={ "New alias (e.g. #foo:" + domain + ")" }
|
blurToCancel={ false }
|
||||||
blurToCancel={ false }
|
onValueChanged={ self.onAliasChanged.bind(self, domain, i) }
|
||||||
onValueChanged={ self.onAliasChanged.bind(self, i, j) }
|
editable={ can_set_room_aliases }
|
||||||
editable={ alias_event && alias_event.getStateKey() === domain }
|
initialValue={ alias } />
|
||||||
initialValue={ alias }
|
<div className="mx_RoomSettings_deleteAlias">
|
||||||
/>
|
{ deleteButton }
|
||||||
<div className="mx_RoomSettings_deleteAlias">
|
|
||||||
{ deleteButton }
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
</div>
|
||||||
});
|
);
|
||||||
})}
|
})}
|
||||||
|
|
||||||
<div className="mx_RoomSettings_aliasesTableRow" key="new">
|
<div className="mx_RoomSettings_aliasesTableRow" key="new">
|
||||||
<EditableText
|
<EditableText
|
||||||
className="mx_RoomSettings_alias mx_RoomSettings_editable"
|
ref="add_alias"
|
||||||
placeholderClassName="mx_RoomSettings_aliasPlaceholder"
|
className="mx_RoomSettings_alias mx_RoomSettings_editable"
|
||||||
placeholder={ "New alias (e.g. #foo:" + domain + ")" }
|
placeholderClassName="mx_RoomSettings_aliasPlaceholder"
|
||||||
blurToCancel={ false }
|
placeholder={ "New alias (e.g. #foo:" + domain + ")" }
|
||||||
onValueChanged={ self.onAliasAdded } />
|
blurToCancel={ false }
|
||||||
|
onValueChanged={ self.onAliasAdded } />
|
||||||
<div className="mx_RoomSettings_addAlias">
|
<div className="mx_RoomSettings_addAlias">
|
||||||
<img src="img/plus.svg" width="14" height="14" alt="Add" onClick={ self.onAliasAdded }/>
|
<img src="img/plus.svg" width="14" height="14" alt="Add" onClick={ self.onAliasAdded.bind(self, undefined) }/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
<div className="mx_RoomSettings_aliasLabel">The canonical entry is
|
|
||||||
<select defaultValue={ canonical_alias }>
|
|
||||||
{ alias_events.map(function(alias_event, i) {
|
|
||||||
return alias_event.getContent().aliases.map(function(alias, j) {
|
|
||||||
return <option value={ alias } key={ i + "_" + j }>{ alias }</option>
|
|
||||||
});
|
|
||||||
})}
|
|
||||||
<option value="" key="unset">not set</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{ remote_aliases_section }
|
||||||
|
|
||||||
|
<div className="mx_RoomSettings_aliasLabel">The official way to refer to this room is: { canonical_alias_section }</div>
|
||||||
</div>;
|
</div>;
|
||||||
|
|
||||||
var room_colors_section =
|
var room_colors_section =
|
||||||
|
@ -337,6 +517,9 @@ module.exports = React.createClass({
|
||||||
</div>
|
</div>
|
||||||
</div>;
|
</div>;
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
user_levels_section = <div>No users have specific privileges in this room.</div>
|
||||||
|
}
|
||||||
|
|
||||||
var banned = this.props.room.getMembersWithMembership("ban");
|
var banned = this.props.room.getMembersWithMembership("ban");
|
||||||
var banned_users_section;
|
var banned_users_section;
|
||||||
|
@ -381,38 +564,38 @@ module.exports = React.createClass({
|
||||||
<div className="mx_RoomSettings_powerLevels mx_RoomSettings_settings">
|
<div className="mx_RoomSettings_powerLevels mx_RoomSettings_settings">
|
||||||
<div className="mx_RoomSettings_powerLevel">
|
<div className="mx_RoomSettings_powerLevel">
|
||||||
<span className="mx_RoomSettings_powerLevelKey">The default role for new room members is </span>
|
<span className="mx_RoomSettings_powerLevelKey">The default role for new room members is </span>
|
||||||
<PowerSelector value={default_user_level} disabled={!can_change_levels || current_user_level < default_user_level} onChange={this.onPowerLevelsChanged}/>
|
<PowerSelector ref="users_default" value={default_user_level} disabled={!can_change_levels || current_user_level < default_user_level} onChange={this.onPowerLevelsChanged}/>
|
||||||
</div>
|
</div>
|
||||||
<div className="mx_RoomSettings_powerLevel">
|
<div className="mx_RoomSettings_powerLevel">
|
||||||
<span className="mx_RoomSettings_powerLevelKey">To send messages, you must be a </span>
|
<span className="mx_RoomSettings_powerLevelKey">To send messages, you must be a </span>
|
||||||
<PowerSelector value={send_level} disabled={!can_change_levels || current_user_level < send_level} onChange={this.onPowerLevelsChanged}/>
|
<PowerSelector ref="events_default" value={send_level} disabled={!can_change_levels || current_user_level < send_level} onChange={this.onPowerLevelsChanged}/>
|
||||||
</div>
|
</div>
|
||||||
<div className="mx_RoomSettings_powerLevel">
|
<div className="mx_RoomSettings_powerLevel">
|
||||||
<span className="mx_RoomSettings_powerLevelKey">To invite users into the room, you must be a </span>
|
<span className="mx_RoomSettings_powerLevelKey">To invite users into the room, you must be a </span>
|
||||||
<PowerSelector value={invite_level} disabled={!can_change_levels || current_user_level < invite_level} onChange={this.onPowerLevelsChanged}/>
|
<PowerSelector ref="invite" value={invite_level} disabled={!can_change_levels || current_user_level < invite_level} onChange={this.onPowerLevelsChanged}/>
|
||||||
</div>
|
</div>
|
||||||
<div className="mx_RoomSettings_powerLevel">
|
<div className="mx_RoomSettings_powerLevel">
|
||||||
<span className="mx_RoomSettings_powerLevelKey">To configure the room, you must be a </span>
|
<span className="mx_RoomSettings_powerLevelKey">To configure the room, you must be a </span>
|
||||||
<PowerSelector value={state_level} disabled={!can_change_levels || current_user_level < state_level} onChange={this.onPowerLevelsChanged}/>
|
<PowerSelector ref="state_default" value={state_level} disabled={!can_change_levels || current_user_level < state_level} onChange={this.onPowerLevelsChanged}/>
|
||||||
</div>
|
</div>
|
||||||
<div className="mx_RoomSettings_powerLevel">
|
<div className="mx_RoomSettings_powerLevel">
|
||||||
<span className="mx_RoomSettings_powerLevelKey">To kick users, you must be a </span>
|
<span className="mx_RoomSettings_powerLevelKey">To kick users, you must be a </span>
|
||||||
<PowerSelector value={kick_level} disabled={!can_change_levels || current_user_level < kick_level} onChange={this.onPowerLevelsChanged}/>
|
<PowerSelector ref="kick" value={kick_level} disabled={!can_change_levels || current_user_level < kick_level} onChange={this.onPowerLevelsChanged}/>
|
||||||
</div>
|
</div>
|
||||||
<div className="mx_RoomSettings_powerLevel">
|
<div className="mx_RoomSettings_powerLevel">
|
||||||
<span className="mx_RoomSettings_powerLevelKey">To ban users, you must be a </span>
|
<span className="mx_RoomSettings_powerLevelKey">To ban users, you must be a </span>
|
||||||
<PowerSelector value={ban_level} disabled={!can_change_levels || current_user_level < ban_level} onChange={this.onPowerLevelsChanged}/>
|
<PowerSelector ref="ban" value={ban_level} disabled={!can_change_levels || current_user_level < ban_level} onChange={this.onPowerLevelsChanged}/>
|
||||||
</div>
|
</div>
|
||||||
<div className="mx_RoomSettings_powerLevel">
|
<div className="mx_RoomSettings_powerLevel">
|
||||||
<span className="mx_RoomSettings_powerLevelKey">To redact messages, you must be a </span>
|
<span className="mx_RoomSettings_powerLevelKey">To redact messages, you must be a </span>
|
||||||
<PowerSelector value={redact_level} disabled={!can_change_levels || current_user_level < redact_level} onChange={this.onPowerLevelsChanged}/>
|
<PowerSelector ref="redact" value={redact_level} disabled={!can_change_levels || current_user_level < redact_level} onChange={this.onPowerLevelsChanged}/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{Object.keys(events_levels).map(function(event_type, i) {
|
{Object.keys(events_levels).map(function(event_type, i) {
|
||||||
return (
|
return (
|
||||||
<div className="mx_RoomSettings_powerLevel" key={event_type}>
|
<div className="mx_RoomSettings_powerLevel" key={event_type}>
|
||||||
<span className="mx_RoomSettings_powerLevelKey">To send events of type <code>{ event_type }</code>, you must be a </span>
|
<span className="mx_RoomSettings_powerLevelKey">To send events of type <code>{ event_type }</code>, you must be a </span>
|
||||||
<PowerSelector value={ events_levels[event_type] } disabled={true} onChange={this.onPowerLevelsChanged}/>
|
<PowerSelector value={ events_levels[event_type] } disabled={true} onChange={self.onPowerLevelsChanged}/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
|
@ -431,6 +614,11 @@ module.exports = React.createClass({
|
||||||
|
|
||||||
{ banned_users_section }
|
{ banned_users_section }
|
||||||
|
|
||||||
|
<h3>Advanced</h3>
|
||||||
|
<div className="mx_RoomSettings_settings">
|
||||||
|
This room's internal ID is <code>{ this.props.room.roomId }</code>
|
||||||
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue