diff --git a/webclient/app-controller.js b/webclient/app-controller.js
index a77d32a5ac..ea48cbb011 100644
--- a/webclient/app-controller.js
+++ b/webclient/app-controller.js
@@ -1,5 +1,5 @@
/*
-Copyright 2014 matrix.org
+Copyright 2014 OpenMarket Ltd
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
diff --git a/webclient/app-directive.js b/webclient/app-directive.js
index eee0d3842f..75283598ab 100644
--- a/webclient/app-directive.js
+++ b/webclient/app-directive.js
@@ -1,5 +1,5 @@
/*
- Copyright 2014 matrix.org
+ Copyright 2014 OpenMarket Ltd
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
diff --git a/webclient/app-filter.js b/webclient/app-filter.js
index e0e8130e45..27f435674f 100644
--- a/webclient/app-filter.js
+++ b/webclient/app-filter.js
@@ -1,5 +1,5 @@
/*
- Copyright 2014 matrix.org
+ Copyright 2014 OpenMarket Ltd
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -97,23 +97,28 @@ angular.module('matrixWebClient')
// Else, build the name from its users
var room = $rootScope.events.rooms[room_id];
if (room) {
- if (room.members) {
+ var room_name_event = room["m.room.name"];
+
+ if (room_name_event) {
+ roomName = room_name_event.content.name;
+ }
+ else if (room.members) {
// Limit the room renaming to 1:1 room
if (2 === Object.keys(room.members).length) {
for (var i in room.members) {
var member = room.members[i];
- if (member.user_id !== matrixService.config().user_id) {
+ if (member.state_key !== matrixService.config().user_id) {
- if (member.user_id in $rootScope.presence) {
+ if (member.state_key in $rootScope.presence) {
// If the user is available in presence, use the displayname there
// as it is the most uptodate
- roomName = $rootScope.presence[member.user_id].content.displayname;
+ roomName = $rootScope.presence[member.state_key].content.displayname;
}
else if (member.content.displayname) {
roomName = member.content.displayname;
}
else {
- roomName = member.user_id;
+ roomName = member.state_key;
}
}
}
@@ -140,7 +145,7 @@ angular.module('matrixWebClient')
roomName = $rootScope.presence[userID].content.displayname;
}
else {
- roomName = member.user_id;
+ roomName = userID;
}
}
}
diff --git a/webclient/app.js b/webclient/app.js
index dac4f048cd..d25e2a6234 100644
--- a/webclient/app.js
+++ b/webclient/app.js
@@ -1,5 +1,5 @@
/*
-Copyright 2014 matrix.org
+Copyright 2014 OpenMarket Ltd
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
diff --git a/webclient/components/fileInput/file-input-directive.js b/webclient/components/fileInput/file-input-directive.js
index c5e4ae07a8..14e2f772f7 100644
--- a/webclient/components/fileInput/file-input-directive.js
+++ b/webclient/components/fileInput/file-input-directive.js
@@ -1,5 +1,5 @@
/*
- Copyright 2014 matrix.org
+ Copyright 2014 OpenMarket Ltd
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
diff --git a/webclient/components/fileUpload/file-upload-service.js b/webclient/components/fileUpload/file-upload-service.js
index 699a3cbffc..e0f67b2c6c 100644
--- a/webclient/components/fileUpload/file-upload-service.js
+++ b/webclient/components/fileUpload/file-upload-service.js
@@ -1,5 +1,5 @@
/*
- Copyright 2014 matrix.org
+ Copyright 2014 OpenMarket Ltd
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
diff --git a/webclient/components/matrix/event-handler-service.js b/webclient/components/matrix/event-handler-service.js
index d6a0600132..ee478d2eb0 100644
--- a/webclient/components/matrix/event-handler-service.js
+++ b/webclient/components/matrix/event-handler-service.js
@@ -1,5 +1,5 @@
/*
-Copyright 2014 matrix.org
+Copyright 2014 OpenMarket Ltd
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -32,7 +32,9 @@ angular.module('eventHandlerService', [])
var MSG_EVENT = "MSG_EVENT";
var MEMBER_EVENT = "MEMBER_EVENT";
var PRESENCE_EVENT = "PRESENCE_EVENT";
+ var POWERLEVEL_EVENT = "POWERLEVEL_EVENT";
var CALL_EVENT = "CALL_EVENT";
+ var NAME_EVENT = "NAME_EVENT";
var InitialSyncDeferred = $q.defer();
@@ -95,7 +97,7 @@ angular.module('eventHandlerService', [])
}
}
- $rootScope.events.rooms[event.room_id].members[event.user_id] = event;
+ $rootScope.events.rooms[event.room_id].members[event.state_key] = event;
$rootScope.$broadcast(MEMBER_EVENT, event, isLiveEvent);
};
@@ -107,10 +109,20 @@ angular.module('eventHandlerService', [])
var handlePowerLevels = function(event, isLiveEvent) {
initRoom(event.room_id);
- $rootScope.events.rooms[event.room_id][event.type] = event;
+ // Keep the latest data. Do not care of events that come when paginating back
+ if (!$rootScope.events.rooms[event.room_id][event.type] || isLiveEvent) {
+ $rootScope.events.rooms[event.room_id][event.type] = event;
+ $rootScope.$broadcast(POWERLEVEL_EVENT, event, isLiveEvent);
+ }
+ };
- //TODO
- //$rootScope.$broadcast(PRESENCE_EVENT, event, isLiveEvent);
+ var handleRoomName = function(event, isLiveEvent) {
+ console.log("handleRoomName " + isLiveEvent);
+
+ initRoom(event.room_id);
+
+ $rootScope.events.rooms[event.room_id][event.type] = event;
+ $rootScope.$broadcast(NAME_EVENT, event, isLiveEvent);
};
var handleCallEvent = function(event, isLiveEvent) {
@@ -122,7 +134,9 @@ angular.module('eventHandlerService', [])
MSG_EVENT: MSG_EVENT,
MEMBER_EVENT: MEMBER_EVENT,
PRESENCE_EVENT: PRESENCE_EVENT,
+ POWERLEVEL_EVENT: POWERLEVEL_EVENT,
CALL_EVENT: CALL_EVENT,
+ NAME_EVENT: NAME_EVENT,
handleEvent: function(event, isLiveEvent) {
@@ -146,7 +160,9 @@ angular.module('eventHandlerService', [])
case 'm.room.power_levels':
handlePowerLevels(event, isLiveEvent);
break;
-
+ case 'm.room.name':
+ handleRoomName(event, isLiveEvent);
+ break;
default:
console.log("Unable to handle event type " + event.type);
console.log(JSON.stringify(event, undefined, 4));
diff --git a/webclient/components/matrix/event-stream-service.js b/webclient/components/matrix/event-stream-service.js
index 441148670e..1c0f7712b4 100644
--- a/webclient/components/matrix/event-stream-service.js
+++ b/webclient/components/matrix/event-stream-service.js
@@ -1,5 +1,5 @@
/*
-Copyright 2014 matrix.org
+Copyright 2014 OpenMarket Ltd
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
diff --git a/webclient/components/matrix/matrix-call.js b/webclient/components/matrix/matrix-call.js
index 47b63d7f2f..3e13e4e81f 100644
--- a/webclient/components/matrix/matrix-call.js
+++ b/webclient/components/matrix/matrix-call.js
@@ -1,5 +1,5 @@
/*
-Copyright 2014 matrix.org
+Copyright 2014 OpenMarket Ltd
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
diff --git a/webclient/components/matrix/matrix-phone-service.js b/webclient/components/matrix/matrix-phone-service.js
index d9e2e8baa3..ca86b473e7 100644
--- a/webclient/components/matrix/matrix-phone-service.js
+++ b/webclient/components/matrix/matrix-phone-service.js
@@ -1,5 +1,5 @@
/*
-Copyright 2014 matrix.org
+Copyright 2014 OpenMarket Ltd
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
diff --git a/webclient/components/matrix/matrix-service.js b/webclient/components/matrix/matrix-service.js
index d399aa3cb9..7c6d4ae50f 100644
--- a/webclient/components/matrix/matrix-service.js
+++ b/webclient/components/matrix/matrix-service.js
@@ -1,5 +1,5 @@
/*
-Copyright 2014 matrix.org
+Copyright 2014 OpenMarket Ltd
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -167,6 +167,29 @@ angular.module('matrixService', [])
return doRequest("POST", path, undefined, data);
},
+ // Change the membership of an another user
+ setMembership: function(room_id, user_id, membershipValue) {
+ // The REST path spec
+ var path = "/rooms/$room_id/state/m.room.member/$user_id";
+ path = path.replace("$room_id", encodeURIComponent(room_id));
+ path = path.replace("$user_id", user_id);
+
+ return doRequest("PUT", path, undefined, {
+ membership: membershipValue
+ });
+ },
+
+ // Bans a user from from a room
+ ban: function(room_id, user_id, reason) {
+ var path = "/rooms/$room_id/ban";
+ path = path.replace("$room_id", encodeURIComponent(room_id));
+
+ return doRequest("POST", path, undefined, {
+ user_id: user_id,
+ reason: reason
+ });
+ },
+
// Retrieves the room ID corresponding to a room alias
resolveRoomAlias:function(room_alias) {
var path = "/_matrix/client/api/v1/directory/room/$room_alias";
@@ -253,7 +276,7 @@ angular.module('matrixService', [])
// get a list of public rooms on your home server
publicRooms: function() {
- var path = "/publicRooms"
+ var path = "/publicRooms";
return doRequest("GET", path);
},
@@ -309,7 +332,7 @@ angular.module('matrixService', [])
// hit the Identity Server for a 3PID request.
linkEmail: function(email, clientSecret, sendAttempt) {
- var path = "/_matrix/identity/api/v1/validate/email/requestToken"
+ var path = "/_matrix/identity/api/v1/validate/email/requestToken";
var data = "clientSecret="+clientSecret+"&email=" + encodeURIComponent(email)+"&sendAttempt="+sendAttempt;
var headers = {};
headers["Content-Type"] = "application/x-www-form-urlencoded";
@@ -414,7 +437,8 @@ angular.module('matrixService', [])
state: presence
});
},
-
+
+
/****** Permanent storage of user information ******/
// Returns the current config
@@ -514,6 +538,35 @@ angular.module('matrixService', [])
}
}
return powerLevel;
+ },
+
+ /**
+ * Change or reset the power level of a user
+ * @param {String} room_id the room id
+ * @param {String} user_id the user id
+ * @param {Number} powerLevel a value between 0 and 10
+ * If undefined, the user power level will be reset, ie he will use the default room user power level
+ * @returns {promise} an $http promise
+ */
+ setUserPowerLevel: function(room_id, user_id, powerLevel) {
+
+ // Hack: currently, there is no home server API so do it by hand by updating
+ // the current m.room.power_levels of the room and send it to the server
+ var room = $rootScope.events.rooms[room_id];
+ if (room && room["m.room.power_levels"]) {
+ var content = angular.copy(room["m.room.power_levels"].content);
+ content[user_id] = powerLevel;
+
+ var path = "/rooms/$room_id/state/m.room.power_levels";
+ path = path.replace("$room_id", encodeURIComponent(room_id));
+
+ return doRequest("PUT", path, undefined, content);
+ }
+
+ // The room does not exist or does not contain power_levels data
+ var deferred = $q.defer();
+ deferred.reject({data:{error: "Invalid room: " + room_id}});
+ return deferred.promise;
}
};
diff --git a/webclient/components/matrix/presence-service.js b/webclient/components/matrix/presence-service.js
index 555118133b..952c8ec8a9 100644
--- a/webclient/components/matrix/presence-service.js
+++ b/webclient/components/matrix/presence-service.js
@@ -1,5 +1,5 @@
/*
- Copyright 2014 matrix.org
+ Copyright 2014 OpenMarket Ltd
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
diff --git a/webclient/components/utilities/utilities-service.js b/webclient/components/utilities/utilities-service.js
index 3df2f04458..b417cc5b39 100644
--- a/webclient/components/utilities/utilities-service.js
+++ b/webclient/components/utilities/utilities-service.js
@@ -1,5 +1,5 @@
/*
- Copyright 2014 matrix.org
+ Copyright 2014 OpenMarket Ltd
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
diff --git a/webclient/home/home-controller.js b/webclient/home/home-controller.js
index f4ce3053ea..11b3682d34 100644
--- a/webclient/home/home-controller.js
+++ b/webclient/home/home-controller.js
@@ -1,5 +1,5 @@
/*
-Copyright 2014 matrix.org
+Copyright 2014 OpenMarket Ltd
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
diff --git a/webclient/login/login-controller.js b/webclient/login/login-controller.js
index e367b2f0c5..5ef39a7122 100644
--- a/webclient/login/login-controller.js
+++ b/webclient/login/login-controller.js
@@ -1,5 +1,5 @@
/*
- Copyright 2014 matrix.org
+ Copyright 2014 OpenMarket Ltd
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
diff --git a/webclient/login/register-controller.js b/webclient/login/register-controller.js
index d70e83c3bd..b7584a7d33 100644
--- a/webclient/login/register-controller.js
+++ b/webclient/login/register-controller.js
@@ -1,5 +1,5 @@
/*
- Copyright 2014 matrix.org
+ Copyright 2014 OpenMarket Ltd
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
diff --git a/webclient/recents/recents-controller.js b/webclient/recents/recents-controller.js
index d7d3bf4053..3209f2cbdf 100644
--- a/webclient/recents/recents-controller.js
+++ b/webclient/recents/recents-controller.js
@@ -1,5 +1,5 @@
/*
- Copyright 2014 matrix.org
+ Copyright 2014 OpenMarket Ltd
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
diff --git a/webclient/recents/recents-filter.js b/webclient/recents/recents-filter.js
index 45653fca96..d80de6fbeb 100644
--- a/webclient/recents/recents-filter.js
+++ b/webclient/recents/recents-filter.js
@@ -1,5 +1,5 @@
/*
- Copyright 2014 matrix.org
+ Copyright 2014 OpenMarket Ltd
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
diff --git a/webclient/recents/recents.html b/webclient/recents/recents.html
index db3b0fb32f..9978e08b13 100644
--- a/webclient/recents/recents.html
+++ b/webclient/recents/recents.html
@@ -23,8 +23,8 @@
<div ng-hide="room.membership === 'invite'" ng-switch="room.lastMsg.type" >
<div ng-switch-when="m.room.member">
{{ room.lastMsg.user_id }}
- {{ {"join": "joined", "leave": "left", "invite": "invited"}[room.lastMsg.content.membership] }}
- {{ room.lastMsg.content.membership === "invite" ? (room.lastMsg.state_key || '') : '' }}
+ {{ {"join": "joined", "leave": "left", "invite": "invited", "ban": "banned"}[msg.content.membership] }}
+ {{ (msg.content.membership === "invite" || msg.content.membership === "ban") ? (msg.state_key || '') : '' }}
</div>
<div ng-switch-when="m.room.message">
diff --git a/webclient/room/room-controller.js b/webclient/room/room-controller.js
index 72c290ad73..52c57856ee 100644
--- a/webclient/room/room-controller.js
+++ b/webclient/room/room-controller.js
@@ -1,5 +1,5 @@
/*
-Copyright 2014 matrix.org
+Copyright 2014 OpenMarket Ltd
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -85,6 +85,14 @@ angular.module('RoomController', ['ngSanitize', 'mFileInput'])
updatePresence(event);
}
});
+
+ $scope.$on(eventHandlerService.POWERLEVEL_EVENT, function(ngEvent, event, isLive) {
+ if (isLive && event.room_id === $scope.room_id) {
+ for (var user_id in event.content) {
+ updateUserPowerLevel(user_id);
+ }
+ }
+ });
$scope.memberCount = function() {
return Object.keys($scope.members).length;
@@ -161,6 +169,11 @@ angular.module('RoomController', ['ngSanitize', 'mFileInput'])
var updateMemberList = function(chunk) {
if (chunk.room_id != $scope.room_id) return;
+ // Ignore banned people
+ if ("ban" === chunk.membership) {
+ return;
+ }
+
// set target_user_id to keep things clear
var target_user_id = chunk.state_key;
@@ -240,6 +253,29 @@ angular.module('RoomController', ['ngSanitize', 'mFileInput'])
var member = $scope.members[user_id];
if (member) {
member.powerLevel = matrixService.getUserPowerLevel($scope.room_id, user_id);
+
+ normaliseMembersPowerLevels();
+ }
+ }
+
+ // Normalise users power levels so that the user with the higher power level
+ // will have a bar covering 100% of the width of his avatar
+ var normaliseMembersPowerLevels = function() {
+ // Find the max power level
+ var maxPowerLevel = 0;
+ for (var i in $scope.members) {
+ var member = $scope.members[i];
+ if (member.powerLevel) {
+ maxPowerLevel = Math.max(maxPowerLevel, member.powerLevel);
+ }
+ }
+
+ // Normalized them on a 0..100% scale to be use in css width
+ if (maxPowerLevel) {
+ for (var i in $scope.members) {
+ var member = $scope.members[i];
+ member.powerLevelNorm = (member.powerLevel * 100) / maxPowerLevel;
+ }
}
}
@@ -250,28 +286,93 @@ angular.module('RoomController', ['ngSanitize', 'mFileInput'])
$scope.state.sending = true;
- // Send the text message
var promise;
- // FIXME: handle other commands too
- if ($scope.textInput.indexOf("/me") === 0) {
- promise = matrixService.sendEmoteMessage($scope.room_id, $scope.textInput.substr(4));
- }
- else if ($scope.textInput.indexOf("/nick ") === 0) {
- // Change user display name
- promise = matrixService.setDisplayName($scope.textInput.substr(6));
+
+ // Check for IRC style commands first
+ if ($scope.textInput.indexOf("/") === 0) {
+ var args = $scope.textInput.split(' ');
+ var cmd = args[0];
+
+ switch (cmd) {
+ case "/me":
+ var emoteMsg = args.slice(1).join(' ');
+ promise = matrixService.sendEmoteMessage($scope.room_id, emoteMsg);
+ break;
+
+ case "/nick":
+ // Change user display name
+ if (2 === args.length) {
+ promise = matrixService.setDisplayName(args[1]);
+ }
+ break;
+
+ case "/kick":
+ // Kick a user from the room
+ if (2 === args.length) {
+ var user_id = args[1];
+
+ // Set his state in the room as leave
+ promise = matrixService.setMembership($scope.room_id, user_id, "leave");
+ }
+ break;
+
+ case "/ban":
+ // Ban a user from the room
+ if (2 <= args.length) {
+ // TODO: The user may have entered the display name
+ // Need display name -> user_id resolution. Pb: how to manage user with same display names?
+ var user_id = args[1];
+
+ // Does the user provide a reason?
+ if (3 <= args.length) {
+ var reason = args.slice(2).join(' ');
+ }
+ promise = matrixService.ban($scope.room_id, user_id, reason);
+ }
+ break;
+
+ case "/unban":
+ // Unban a user from the room
+ if (2 === args.length) {
+ var user_id = args[1];
+
+ // Reset the user membership to leave to unban him
+ promise = matrixService.setMembership($scope.room_id, user_id, "leave");
+ }
+ break;
+
+ case "/op":
+ // Define the power level of a user
+ if (3 === args.length) {
+ var user_id = args[1];
+ var powerLevel = parseInt(args[2]);
+ promise = matrixService.setUserPowerLevel($scope.room_id, user_id, powerLevel);
+ }
+ break;
+
+ case "/deop":
+ // Reset the power level of a user
+ if (2 === args.length) {
+ var user_id = args[1];
+ promise = matrixService.setUserPowerLevel($scope.room_id, user_id, undefined);
+ }
+ break;
+ }
}
- else {
+
+ if (!promise) {
+ // Send the text message
promise = matrixService.sendTextMessage($scope.room_id, $scope.textInput);
}
promise.then(
function() {
- console.log("Sent message");
+ console.log("Request successfully sent");
$scope.textInput = "";
$scope.state.sending = false;
},
function(error) {
- $scope.feedback = "Failed to send: " + error.data.error;
+ $scope.feedback = "Request failed: " + error.data.error;
$scope.state.sending = false;
});
};
@@ -363,7 +464,8 @@ angular.module('RoomController', ['ngSanitize', 'mFileInput'])
onInit3();
},
function(reason) {
- $scope.feedback = "Can't join room: " + reason;
+ console.log("Can't join room: " + JSON.stringify(reason));
+ $scope.feedback = "You do not have permission to join this room";
});
}
else {
diff --git a/webclient/room/room-directive.js b/webclient/room/room-directive.js
index 1a99a37abb..659bcbc60f 100644
--- a/webclient/room/room-directive.js
+++ b/webclient/room/room-directive.js
@@ -1,5 +1,5 @@
/*
- Copyright 2014 matrix.org
+ Copyright 2014 OpenMarket Ltd
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
diff --git a/webclient/room/room.html b/webclient/room/room.html
index e672b1d7e2..e29f511ecf 100644
--- a/webclient/room/room.html
+++ b/webclient/room/room.html
@@ -24,7 +24,7 @@
title="{{ member.id }}"
width="80" height="80"/>
<img class="userAvatarGradient" src="img/gradient.png" title="{{ member.id }}" width="80" height="24"/>
- <div class="userPowerLevel" ng-style="{'width': (10 * member.powerLevel) +'%'}"></div>
+ <div class="userPowerLevel" ng-style="{'width': member.powerLevelNorm +'%'}"></div>
<div class="userName">{{ member.displayname || member.id.substr(0, member.id.indexOf(':')) }}<br/>{{ member.displayname ? "" : member.id.substr(member.id.indexOf(':')) }}</div>
</td>
<td class="userPresence" ng-class="(member.presence === 'online' ? 'online' : (member.presence === 'unavailable' ? 'unavailable' : '')) + ' ' + (member.membership == 'invite' ? 'invited' : '')">
@@ -50,8 +50,9 @@
<div class="bubble">
<span ng-show='msg.type === "m.room.member"'>
{{ members[msg.user_id].displayname || msg.user_id }}
- {{ {"join": "joined", "leave": "left", "invite": "invited"}[msg.content.membership] }}
- {{ msg.content.membership === "invite" ? (msg.state_key || '') : '' }}
+ {{ {"join": "joined", "leave": "left", "invite": "invited", "ban": "banned"}[msg.content.membership] }}
+ {{ (msg.content.membership === "invite" || msg.content.membership === "ban") ? (msg.state_key || '') : '' }}
+
</span>
<span ng-show='msg.content.msgtype === "m.emote"' ng-bind-html="'* ' + (members[msg.user_id].displayname || msg.user_id) + ' ' + msg.content.body | linky:'_blank'"/>
<span ng-show='msg.content.msgtype === "m.text"' ng-bind-html="((msg.content.msgtype === 'm.text') ? msg.content.body : '') | linky:'_blank'"/>
diff --git a/webclient/settings/settings-controller.js b/webclient/settings/settings-controller.js
index dc680ef075..7a26367a1b 100644
--- a/webclient/settings/settings-controller.js
+++ b/webclient/settings/settings-controller.js
@@ -1,5 +1,5 @@
/*
-Copyright 2014 matrix.org
+Copyright 2014 OpenMarket Ltd
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
diff --git a/webclient/settings/settings.html b/webclient/settings/settings.html
index 03927838d2..49dc603540 100644
--- a/webclient/settings/settings.html
+++ b/webclient/settings/settings.html
@@ -74,6 +74,21 @@
<div>Access token: {{ config.access_token }} </div>
</div>
<br/>
+
+ <h3>Commands</h3>
+ <div class="section">
+ The following commands are available in the room chat:
+ <ul>
+ <li>/nick <display_name>: change your display name</li>
+ <li>/me <action>: send the action you are doing. /me will be replaced by your display name</li>
+ <li>/kick <user_id>: kick the user</li>
+ <li>/ban <user_id> [<reason>]: ban the user</li>
+ <li>/unban <user_id>: unban the user</li>
+ <li>/op <user_id> <power_level>: set user power level</li>
+ <li>/deop <user_id>: reset user power level to the room default value</li>
+ </ul>
+ </div>
+ <br/>
{{ feedback }}
diff --git a/webclient/user/user-controller.js b/webclient/user/user-controller.js
index b5b2d439a2..3940db6683 100644
--- a/webclient/user/user-controller.js
+++ b/webclient/user/user-controller.js
@@ -1,5 +1,5 @@
/*
-Copyright 2014 matrix.org
+Copyright 2014 OpenMarket Ltd
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
|