From f2bd802bdc4c91bcff6197b95bbf29c384cef303 Mon Sep 17 00:00:00 2001
From: Kegan Dougal <kegan@matrix.org>
Date: Mon, 20 Jul 2015 15:07:19 +0100
Subject: [PATCH] Wire up invite button on the member list.

---
 skins/base/views/atoms/EditableText.js   |  2 +-
 skins/base/views/organisms/MemberList.js | 31 +++++++++++++++++++++---
 src/controllers/atoms/EditableText.js    | 13 +++++++---
 src/controllers/organisms/MemberList.js  | 26 ++++++++++++++++++++
 4 files changed, 63 insertions(+), 9 deletions(-)

diff --git a/skins/base/views/atoms/EditableText.js b/skins/base/views/atoms/EditableText.js
index 07bdc911..a4508744 100644
--- a/skins/base/views/atoms/EditableText.js
+++ b/skins/base/views/atoms/EditableText.js
@@ -44,7 +44,7 @@ module.exports = React.createClass({
 
     onFinish: function(ev) {
         if (ev.target.value) {
-            this.setValue(ev.target.value);
+            this.setValue(ev.target.value, ev.key === "Enter");
         } else {
             this.cancelEdit();
         }
diff --git a/skins/base/views/organisms/MemberList.js b/skins/base/views/organisms/MemberList.js
index 590ebb55..9283a928 100644
--- a/skins/base/views/organisms/MemberList.js
+++ b/skins/base/views/organisms/MemberList.js
@@ -23,6 +23,7 @@ var MemberListController = require("../../../../src/controllers/organisms/Member
 var ComponentBroker = require('../../../../src/ComponentBroker');
 
 var MemberTile = ComponentBroker.get("molecules/MemberTile");
+var EditableText = ComponentBroker.get("atoms/EditableText");
 
 
 module.exports = React.createClass({
@@ -39,6 +40,31 @@ module.exports = React.createClass({
         });
     },
 
+    onPopulateInvite: function(inputText, shouldSubmit) {
+        // reset back to placeholder
+        this.refs.invite.setValue("Invite", false, true);
+        if (!shouldSubmit) {
+            return; // enter key wasn't pressed
+        }
+        this.onInvite(inputText);
+    },
+
+    inviteTile: function() {
+        if (this.state.inviting) {
+            return (
+                <div></div>
+            );
+        }
+        return (
+            <div className="mx_MemberTile">
+                <div className="mx_MemberTile_avatar"><img src="img/create-big.png" width="40" height="40" alt=""/></div>            
+                <div className="mx_MemberTile_name">
+                    <EditableText ref="invite" placeHolder="Invite" onValueChanged={this.onPopulateInvite}/>
+                </div>
+            </div>
+        );
+    },
+
     render: function() {
         return (
             <div className="mx_MemberList">
@@ -49,10 +75,7 @@ module.exports = React.createClass({
                     <h2>Members</h2>
                     <div className="mx_MemberList_wrapper">
                         {this.makeMemberTiles()}
-                        <div className="mx_MemberTile">
-                            <div className="mx_MemberTile_avatar"><img src="img/create-big.png" width="40" height="40" alt=""/></div>            
-                            <div className="mx_MemberTile_name">Invite</div>
-                        </div>
+                        {this.inviteTile()}
                     </div>
                 </div>
             </div>
diff --git a/src/controllers/atoms/EditableText.js b/src/controllers/atoms/EditableText.js
index 4d9eb010..15ee58a7 100644
--- a/src/controllers/atoms/EditableText.js
+++ b/src/controllers/atoms/EditableText.js
@@ -55,11 +55,16 @@ module.exports = {
         return this.state.value;
     },
 
-    setValue: function(val) {
+    setValue: function(val, shouldSubmit, suppressListener) {
+        var self = this;
         this.setState({
             value: val,
             phase: this.Phases.Display,
-        }, this.onValueChanged);
+        }, function() {
+            if (!suppressListener) {
+                self.onValueChanged(shouldSubmit);
+            }
+        });
     },
 
     edit: function() {
@@ -74,7 +79,7 @@ module.exports = {
         });
     },
 
-    onValueChanged: function() {
-        this.props.onValueChanged(this.state.value);
+    onValueChanged: function(shouldSubmit) {
+        this.props.onValueChanged(this.state.value, shouldSubmit);
     },
 };
diff --git a/src/controllers/organisms/MemberList.js b/src/controllers/organisms/MemberList.js
index fb5c0028..6021d0fc 100644
--- a/src/controllers/organisms/MemberList.js
+++ b/src/controllers/organisms/MemberList.js
@@ -61,6 +61,32 @@ module.exports = {
         });
     },
 
+    onInvite: function(inputText) {
+        var self = this;
+        // sanity check the input
+        inputText = inputText.trim(); // react requires es5-shim so we know trim() exists
+        if (inputText[0] !== '@' || inputText.indexOf(":") === -1) {
+            console.error("Bad user ID to invite: %s", inputText);
+            return;
+        }
+        self.setState({
+            inviting: true
+        });
+        console.log("Invite %s to %s", inputText, this.props.roomId);
+        MatrixClientPeg.get().invite(this.props.roomId, inputText).done(
+        function(res) {
+            console.log("Invited");
+            self.setState({
+                inviting: false
+            });
+        }, function(err) {
+            console.error("Failed to invite: %s", JSON.stringify(err));
+            self.setState({
+                inviting: false
+            });
+        });
+    },
+
     roomMembers: function(limit) {
         if (!this.props.roomId) return {};
         var cli = MatrixClientPeg.get();