diff --git a/src/Roles.js b/src/Roles.js
new file mode 100644
index 0000000000..cef8670aad
--- /dev/null
+++ b/src/Roles.js
@@ -0,0 +1,29 @@
+/*
+Copyright 2017 Vector Creations 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.
+*/
+export const LEVEL_ROLE_MAP = {
+ undefined: 'Default',
+ 0: 'User',
+ 50: 'Moderator',
+ 100: 'Admin',
+};
+
+export function textualPowerLevel(level, userDefault) {
+ if (LEVEL_ROLE_MAP[level]) {
+ return LEVEL_ROLE_MAP[level] + (level !== undefined ? ` (${level})` : ` (${userDefault})`);
+ } else {
+ return level;
+ }
+}
diff --git a/src/TextForEvent.js b/src/TextForEvent.js
index 3e1659f392..40d6a49998 100644
--- a/src/TextForEvent.js
+++ b/src/TextForEvent.js
@@ -17,6 +17,8 @@ limitations under the License.
var MatrixClientPeg = require("./MatrixClientPeg");
var CallHandler = require("./CallHandler");
+import * as Roles from './Roles';
+
function textForMemberEvent(ev) {
// XXX: SYJS-16 "sender is sometimes null for join messages"
var senderName = ev.sender ? ev.sender.name : ev.getSender();
@@ -182,6 +184,45 @@ function textForEncryptionEvent(event) {
return senderName + " turned on end-to-end encryption (algorithm " + event.getContent().algorithm + ")";
}
+// Currently will only display a change if a user's power level is changed
+function textForPowerEvent(event) {
+ const senderName = event.sender ? event.sender.name : event.getSender();
+ if (!event.getPrevContent() || !event.getPrevContent().users) {
+ return '';
+ }
+ const userDefault = event.getContent().users_default || 0;
+ // Construct set of userIds
+ let users = [];
+ Object.keys(event.getContent().users).forEach(
+ (userId) => {
+ if (users.indexOf(userId) === -1) users.push(userId);
+ }
+ );
+ Object.keys(event.getPrevContent().users).forEach(
+ (userId) => {
+ if (users.indexOf(userId) === -1) users.push(userId);
+ }
+ );
+ let diff = [];
+ users.forEach((userId) => {
+ // Previous power level
+ const from = event.getPrevContent().users[userId];
+ // Current power level
+ const to = event.getContent().users[userId];
+ if (to !== from) {
+ diff.push(
+ userId +
+ ' from ' + Roles.textualPowerLevel(from, userDefault) +
+ ' to ' + Roles.textualPowerLevel(to, userDefault)
+ );
+ }
+ });
+ if (!diff.length) {
+ return '';
+ }
+ return senderName + ' changed the power level of ' + diff.join(', ');
+}
+
var handlers = {
'm.room.message': textForMessageEvent,
'm.room.name': textForRoomNameEvent,
@@ -193,6 +234,7 @@ var handlers = {
'm.room.third_party_invite': textForThreePidInviteEvent,
'm.room.history_visibility': textForHistoryVisibilityEvent,
'm.room.encryption': textForEncryptionEvent,
+ 'm.room.power_levels': textForPowerEvent,
};
module.exports = {
diff --git a/src/components/views/elements/PowerSelector.js b/src/components/views/elements/PowerSelector.js
index c7bfd4eec1..5eec464ead 100644
--- a/src/components/views/elements/PowerSelector.js
+++ b/src/components/views/elements/PowerSelector.js
@@ -16,17 +16,12 @@ limitations under the License.
'use strict';
-var React = require('react');
-
-var roles = {
- 0: 'User',
- 50: 'Moderator',
- 100: 'Admin',
-};
+import React from 'react';
+import * as Roles from '../../../Roles';
var reverseRoles = {};
-Object.keys(roles).forEach(function(key) {
- reverseRoles[roles[key]] = key;
+Object.keys(Roles.LEVEL_ROLE_MAP).forEach(function(key) {
+ reverseRoles[Roles.LEVEL_ROLE_MAP[key]] = key;
});
module.exports = React.createClass({
@@ -49,7 +44,7 @@ module.exports = React.createClass({
getInitialState: function() {
return {
- custom: (roles[this.props.value] === undefined),
+ custom: (Roles.LEVEL_ROLE_MAP[this.props.value] === undefined),
};
},
@@ -99,22 +94,34 @@ module.exports = React.createClass({
selectValue = "Custom";
}
else {
- selectValue = roles[this.props.value] || "Custom";
+ selectValue = Roles.LEVEL_ROLE_MAP[this.props.value] || "Custom";
}
var select;
if (this.props.disabled) {
select = { selectValue };
}
else {
+ // Each level must have a definition in LEVEL_ROLE_MAP
+ const levels = [0, 50, 100];
+ let options = levels.map((level) => {
+ return {
+ value: Roles.LEVEL_ROLE_MAP[level],
+ // Give a userDefault (users_default in the power event) of 0 but
+ // because level !== undefined, this should never be used.
+ text: Roles.textualPowerLevel(level, 0),
+ }
+ });
+ options.push({ value: "Custom", text: "Custom level" });
+ options = options.map((op) => {
+ return ;
+ });
+
select =
;
}
diff --git a/src/components/views/rooms/EventTile.js b/src/components/views/rooms/EventTile.js
index 8b8e52ae83..9df0499eb2 100644
--- a/src/components/views/rooms/EventTile.js
+++ b/src/components/views/rooms/EventTile.js
@@ -40,6 +40,7 @@ var eventTileTypes = {
'm.room.third_party_invite' : 'messages.TextualEvent',
'm.room.history_visibility' : 'messages.TextualEvent',
'm.room.encryption' : 'messages.TextualEvent',
+ 'm.room.power_levels' : 'messages.TextualEvent',
};
var MAX_READ_AVATARS = 5;