From e1f3c80f1928eff8fb1085ce26e7cd6e355cffdb Mon Sep 17 00:00:00 2001 From: David Baker Date: Sun, 19 Jul 2015 16:38:56 +0100 Subject: [PATCH] Display who's typing --- skins/base/views/organisms/RoomView.js | 15 ++++++++ src/WhoIsTyping.js | 49 ++++++++++++++++++++++++++ src/controllers/organisms/RoomView.js | 11 ++++++ 3 files changed, 75 insertions(+) create mode 100644 src/WhoIsTyping.js diff --git a/skins/base/views/organisms/RoomView.js b/skins/base/views/organisms/RoomView.js index 88adfdaadf..5878e881e9 100644 --- a/skins/base/views/organisms/RoomView.js +++ b/skins/base/views/organisms/RoomView.js @@ -71,6 +71,20 @@ module.exports = React.createClass({ mx_RoomView_scrollheader: true, loading: this.state.paginating }); + + var statusBar = ( +
+ ); + + var typingString = this.getWhoIsTypingString(); + if (typingString) { + statusBar = ( +
+ {typingString} +
+ ); + } + return (
@@ -88,6 +102,7 @@ module.exports = React.createClass({
+ {statusBar}
diff --git a/src/WhoIsTyping.js b/src/WhoIsTyping.js new file mode 100644 index 0000000000..4fb5399027 --- /dev/null +++ b/src/WhoIsTyping.js @@ -0,0 +1,49 @@ +var MatrixClientPeg = require("./MatrixClientPeg"); + +module.exports = { + usersTypingApartFromMe: function(room) { + return this.usersTyping( + room, [MatrixClientPeg.get().credentials.userId] + ); + }, + + /** + * Given a Room object and, optionally, a list of userID strings + * to exclude, return a list of user objects who are typing. + */ + usersTyping: function(room, exclude) { + var whoIsTyping = []; + + if (exclude === undefined) { + exclude = []; + } + + var memberKeys = Object.keys(room.currentState.members); + for (var i = 0; i < memberKeys.length; ++i) { + var userId = memberKeys[i]; + + if (room.currentState.members[userId].typing) { + if (exclude.indexOf(userId) == -1) { + whoIsTyping.push(room.currentState.members[userId]); + } + } + } + + return whoIsTyping; + }, + + whoIsTypingString: function(room) { + var whoIsTyping = this.usersTypingApartFromMe(room); + if (whoIsTyping.length == 0) { + return null; + } else if (whoIsTyping.length == 1) { + return whoIsTyping[0].name + ' is typing'; + } else { + var names = whoIsTyping.map(function(m) { + return m.name; + }); + var lastPerson = names.shift(); + return names.join(', ') + ' and ' + lastPerson + ' are typing'; + } + } +} diff --git a/src/controllers/organisms/RoomView.js b/src/controllers/organisms/RoomView.js index f73b5c8f46..59807b63fe 100644 --- a/src/controllers/organisms/RoomView.js +++ b/src/controllers/organisms/RoomView.js @@ -20,6 +20,7 @@ var MatrixClientPeg = require("../../MatrixClientPeg"); var React = require("react"); var q = require("q"); var ContentMessages = require("../../ContentMessages"); +var WhoIsTyping = require("../../WhoIsTyping"); var dis = require("../../dispatcher"); @@ -51,6 +52,7 @@ module.exports = { this.dispatcherRef = dis.register(this.onAction); MatrixClientPeg.get().on("Room.timeline", this.onRoomTimeline); MatrixClientPeg.get().on("Room.name", this.onRoomName); + MatrixClientPeg.get().on("RoomMember.typing", this.onRoomMemberTyping); this.atBottom = true; }, @@ -64,6 +66,7 @@ module.exports = { if (MatrixClientPeg.get()) { MatrixClientPeg.get().removeListener("Room.timeline", this.onRoomTimeline); MatrixClientPeg.get().removeListener("Room.name", this.onRoomName); + MatrixClientPeg.get().removeListener("RoomMember.typing", this.onRoomMemberTyping); } }, @@ -118,6 +121,10 @@ module.exports = { } }, + onRoomMemberTyping: function(ev, member) { + this.forceUpdate(); + }, + componentDidMount: function() { if (this.refs.messageWrapper) { var messageWrapper = this.refs.messageWrapper.getDOMNode(); @@ -236,6 +243,10 @@ module.exports = { } }, + getWhoIsTypingString() { + return WhoIsTyping.whoIsTypingString(this.state.room); + }, + getEventTiles: function() { var ret = []; var count = 0;