diff options
Diffstat (limited to 'webclient/room')
-rw-r--r-- | webclient/room/room-controller.js | 141 | ||||
-rw-r--r-- | webclient/room/room-directive.js | 2 | ||||
-rw-r--r-- | webclient/room/room.html | 21 |
3 files changed, 139 insertions, 25 deletions
diff --git a/webclient/room/room-controller.js b/webclient/room/room-controller.js index 1f90472c67..c3f72c9d25 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,10 +169,13 @@ angular.module('RoomController', ['ngSanitize', 'mFileInput']) var updateMemberList = function(chunk) { if (chunk.room_id != $scope.room_id) return; + // Ignore banned and kicked (leave) people + if ("ban" === chunk.membership || "leave" === chunk.membership) { + return; + } + // set target_user_id to keep things clear var target_user_id = chunk.state_key; - - var now = new Date().getTime(); var isNewMember = !(target_user_id in $scope.members); if (isNewMember) { @@ -174,6 +185,8 @@ angular.module('RoomController', ['ngSanitize', 'mFileInput']) } if ("last_active_ago" in chunk.content) { chunk.last_active_ago = chunk.content.last_active_ago; + $scope.now = new Date().getTime(); + chunk.last_updated = $scope.now; } if ("displayname" in chunk.content) { chunk.displayname = chunk.content.displayname; @@ -181,7 +194,6 @@ angular.module('RoomController', ['ngSanitize', 'mFileInput']) if ("avatar_url" in chunk.content) { chunk.avatar_url = chunk.content.avatar_url; } - chunk.last_updated = now; $scope.members[target_user_id] = chunk; if (target_user_id in $rootScope.presence) { @@ -197,6 +209,8 @@ angular.module('RoomController', ['ngSanitize', 'mFileInput']) } if ("last_active_ago" in chunk.content) { member.last_active_ago = chunk.content.last_active_ago; + $scope.now = new Date().getTime(); + member.last_updated = $scope.now; } } }; @@ -221,6 +235,8 @@ angular.module('RoomController', ['ngSanitize', 'mFileInput']) if ("last_active_ago" in chunk.content) { member.last_active_ago = chunk.content.last_active_ago; + $scope.now = new Date().getTime(); + member.last_updated = $scope.now; } // this may also contain a new display name or avatar url, so check. @@ -237,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; + } } } @@ -247,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; }); }; @@ -332,10 +436,6 @@ angular.module('RoomController', ['ngSanitize', 'mFileInput']) eventHandlerService.waitForInitialSyncCompletion().then( function() { - // Some data has been retrieved from the iniialSync request - // So, the relative time starts here - $scope.now = new Date().getTime(); - var needsToJoin = true; // The room members is available in the data fetched by initialSync @@ -364,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..6732a7b3ae 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' : '')"> @@ -48,10 +48,23 @@ </td> <td ng-class="!msg.content.membership ? (msg.content.msgtype === 'm.emote' ? 'emote text' : 'text') : 'membership text'"> <div class="bubble"> - <span ng-show='msg.type === "m.room.member"'> + <span ng-if="'join' === msg.content.membership"> + {{ members[msg.state_key].displayname || msg.state_key }} joined + </span> + <span ng-if="'leave' === msg.content.membership"> + <span ng-if="msg.user_id === msg.state_key"> + {{ members[msg.state_key].displayname || msg.state_key }} left + </span> + <span ng-if="msg.user_id !== msg.state_key"> + {{ members[msg.user_id].displayname || msg.user_id }} + {{ {"join": "kicked", "ban": "unbanned"}[msg.content.prev] }} + {{ members[msg.state_key].displayname || msg.state_key }} + </span> + </span> + <span ng-if="'invite' === msg.content.membership || 'ban' === msg.content.membership"> {{ members[msg.user_id].displayname || msg.user_id }} - {{ {"join": "joined", "leave": "left", "invite": "invited"}[msg.content.membership] }} - {{ msg.content.membership === "invite" ? (msg.state_key || '') : '' }} + {{ {"invite": "invited", "ban": "banned"}[msg.content.membership] }} + {{ members[msg.state_key].displayname || 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'"/> |