From 13f04f77dc542dd3522022d6e889f31a4276d727 Mon Sep 17 00:00:00 2001
From: Kegan Dougal <kegan@matrix.org>
Date: Tue, 21 Jul 2015 11:43:18 +0100
Subject: [PATCH] Tidy up power level logic. Add 'Moderator' label to members.

---
 skins/base/views/molecules/MemberInfo.js |  6 +-
 src/controllers/molecules/MemberInfo.js  | 79 ++++++++++++------------
 2 files changed, 43 insertions(+), 42 deletions(-)

diff --git a/skins/base/views/molecules/MemberInfo.js b/skins/base/views/molecules/MemberInfo.js
index 036a3fd62d..45db0c308e 100644
--- a/skins/base/views/molecules/MemberInfo.js
+++ b/skins/base/views/molecules/MemberInfo.js
@@ -84,7 +84,10 @@ module.exports = React.createClass({
                 {muteLabel}
             </div>;
         }
-
+        var opLabel;
+        if (this.state.isTargetOp) {
+            opLabel = <div className="mx_MemberInfo_field">Moderator</div>
+        }
         return (
             <div className="mx_MemberInfo">
                 <img className="mx_MemberInfo_chevron" src="img/chevron-right.png" width="9" height="16" />
@@ -95,6 +98,7 @@ module.exports = React.createClass({
                          width="128" height="128" alt=""/>
                 </div>
                 <div className="mx_MemberInfo_field">{this.props.member.userId}</div>
+                {opLabel}
                 <div className="mx_MemberInfo_field">Presence: {this.state.presence}</div>
                 <div className="mx_MemberInfo_field">Last active: {activeAgo}</div>
                 <div className="mx_MemberInfo_button" onClick={this.onChatClick}>Start chat</div>
diff --git a/src/controllers/molecules/MemberInfo.js b/src/controllers/molecules/MemberInfo.js
index fd04df4d55..d335eec5f6 100644
--- a/src/controllers/molecules/MemberInfo.js
+++ b/src/controllers/molecules/MemberInfo.js
@@ -23,7 +23,8 @@ limitations under the License.
  *   ban: boolean,
  *   mute: boolean
  * },
- * 'muted': boolean
+ * 'muted': boolean,
+ * 'isTargetOp': boolean
  */
 
 'use strict';
@@ -62,10 +63,7 @@ module.exports = {
             if ([myUserId, self.props.member.userId].indexOf(member.userId) === -1) {
                 return;
             }
-            self.setState({
-                can: self._calculateOpsPermissions(),
-                muted: self._isMuted(self.props.member)
-            });
+            self.setState(self._calculateOpsPermissions());
         }
         MatrixClientPeg.get().on("RoomMember.powerLevel", updatePowerLevel);
         this.updatePowerLevelFn = updatePowerLevel;
@@ -73,12 +71,10 @@ module.exports = {
         // work out the current state
         if (this.props.member) {
             var usr = MatrixClientPeg.get().getUser(this.props.member.userId) || {};
-            this.setState({
-                presence: usr.presence || "offline",
-                active: usr.lastActiveAgo || -1,
-                can: this._calculateOpsPermissions(),
-                muted: this._isMuted(this.props.member)
-            });
+            var memberState = this._calculateOpsPermissions();
+            memberState.presence = usr.presence || "offline";
+            memberState.active = usr.lastActiveAgo || -1;
+            this.setState(memberState);
         }
     },
 
@@ -220,53 +216,43 @@ module.exports = {
                 ban: false,
                 mute: false
             },
-            muted: false
+            muted: false,
+            isTargetOp: false
         }
     },
 
-    _isMuted: function(member) {
-        var room = MatrixClientPeg.get().getRoom(member.roomId);
+    _calculateOpsPermissions: function() {
+        var defaultPerms = {
+            can: {},
+            muted: false
+        };
+        var room = MatrixClientPeg.get().getRoom(this.props.member.roomId);
         if (!room) {
-            return false;
+            return defaultPerms;
         }
         var powerLevels = room.currentState.getStateEvents(
             "m.room.power_levels", ""
         );
         if (!powerLevels) {
-            return false;
+            return defaultPerms;
         }
-        powerLevels = powerLevels.getContent();
-        var levelToSend = (
-            (powerLevels.events ? powerLevels.events["m.room.message"] : null) ||
-            powerLevels.events_default
-        );
-        return member.powerLevel < levelToSend;
+        var me = room.getMember(MatrixClientPeg.get().credentials.userId);
+        var them = this.props.member;
+        return {
+            can: this._calculateCanPermissions(
+                me, them, powerLevels.getContent()
+            ),
+            muted: this._isMuted(them, powerLevels.getContent()),
+            isTargetOp: them.powerLevel >= me.powerLevel && them.powerLevel > 0
+        };
     },
 
-    _calculateOpsPermissions: function() {
+    _calculateCanPermissions: function(me, them, powerLevels) {
         var can = {
             kick: false,
             ban: false,
             mute: false
         };
-        var them = this.props.member;
-        var room = MatrixClientPeg.get().getRoom(this.props.member.roomId);
-        if (!room) {
-            console.error("No room found");
-            return can;
-        }
-        var myUserId = MatrixClientPeg.get().credentials.userId;
-        var me = room.getMember(myUserId);
-        var powerLevels = room.currentState.getStateEvents(
-            "m.room.power_levels", ""
-        );
-        if (powerLevels) {
-            powerLevels = powerLevels.getContent();
-        }
-        else {
-            console.log("No power level event found in %s", room.roomId);
-            return can; // no power level event, don't allow anything.
-        }
         var canAffectUser = them.powerLevel < me.powerLevel;
         if (!canAffectUser) {
             console.log("Cannot affect user: %s >= %s", them.powerLevel, me.powerLevel);
@@ -280,6 +266,17 @@ module.exports = {
         can.ban = me.powerLevel >= powerLevels.ban;
         can.mute = me.powerLevel >= editPowerLevel;
         return can;
+    },
+
+    _isMuted: function(member, powerLevelContent) {
+        if (!powerLevelContent || !member) {
+            return false;
+        }
+        var levelToSend = (
+            (powerLevelContent.events ? powerLevelContent.events["m.room.message"] : null) ||
+            powerLevelContent.events_default
+        );
+        return member.powerLevel < levelToSend;
     }
 };
 
-- 
GitLab